diff options
author | Pedro Giffuni <pfg@apache.org> | 2011-10-16 03:13:16 +0000 |
---|---|---|
committer | Pedro Giffuni <pfg@apache.org> | 2011-10-16 03:13:16 +0000 |
commit | ef33060ab118d5ede5e96660dc05a3f961279392 (patch) | |
tree | 40e76ef24a102c6ec7f6113ea36b0baf2fd86cf6 | |
parent | 9d049b71d03c9073f77ab7f712c4551df3ae9a56 (diff) |
i118508 - Update Anti-Grain Geometry (AGG) to version 2.4. Disable in configure since this is not really used by anything.
162 files changed, 16309 insertions, 12527 deletions
diff --git a/agg/inc/agg_alpha_mask_u8.h b/agg/inc/agg_alpha_mask_u8.h index b7e5c926092f..321defebc5ed 100755 --- a/agg/inc/agg_alpha_mask_u8.h +++ b/agg/inc/agg_alpha_mask_u8.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -49,7 +49,7 @@ namespace agg public: typedef int8u cover_type; typedef alpha_mask_u8<Step, Offset, MaskF> self_type; - enum + enum cover_scale_e { cover_shift = 8, cover_none = 0, @@ -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,10 +70,10 @@ 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(y) + x * Step + Offset); + m_rbuf->row_ptr(y) + x * Step + Offset); } return 0; } @@ -83,11 +83,11 @@ 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)((val * + return (cover_type)((cover_full + val * m_mask_function.calculate( - m_rbuf->row(y) + x * Step + Offset)) >> + m_rbuf->row_ptr(y) + x * Step + Offset)) >> cover_shift); } return 0; @@ -134,7 +134,7 @@ namespace agg memset(covers + count, 0, rest * sizeof(cover_type)); } - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *covers++ = (cover_type)m_mask_function.calculate(mask); @@ -184,10 +184,10 @@ namespace agg memset(covers + count, 0, rest * sizeof(cover_type)); } - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { - *covers = (cover_type)(((*covers) * + *covers = (cover_type)((cover_full + (*covers) * m_mask_function.calculate(mask)) >> cover_shift); ++covers; @@ -236,7 +236,7 @@ namespace agg memset(covers + count, 0, rest * sizeof(cover_type)); } - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *covers++ = (cover_type)m_mask_function.calculate(mask); @@ -285,10 +285,10 @@ namespace agg memset(covers + count, 0, rest * sizeof(cover_type)); } - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { - *covers = (cover_type)(((*covers) * + *covers = (cover_type)((cover_full + (*covers) * m_mask_function.calculate(mask)) >> cover_shift); ++covers; @@ -353,7 +353,7 @@ namespace agg public: typedef int8u cover_type; typedef amask_no_clip_u8<Step, Offset, MaskF> self_type; - enum + enum cover_scale_e { cover_shift = 8, cover_none = 0, @@ -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; } @@ -373,16 +373,16 @@ namespace agg cover_type pixel(int x, int y) const { return (cover_type)m_mask_function.calculate( - m_rbuf->row(y) + x * Step + Offset); + m_rbuf->row_ptr(y) + x * Step + Offset); } //-------------------------------------------------------------------- cover_type combine_pixel(int x, int y, cover_type val) const { - return (cover_type)((val * + return (cover_type)((cover_full + val * m_mask_function.calculate( - m_rbuf->row(y) + x * Step + Offset)) >> + m_rbuf->row_ptr(y) + x * Step + Offset)) >> cover_shift); } @@ -390,7 +390,7 @@ namespace agg //-------------------------------------------------------------------- void fill_hspan(int x, int y, cover_type* dst, int num_pix) const { - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *dst++ = (cover_type)m_mask_function.calculate(mask); @@ -404,10 +404,10 @@ namespace agg //-------------------------------------------------------------------- void combine_hspan(int x, int y, cover_type* dst, int num_pix) const { - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { - *dst = (cover_type)(((*dst) * + *dst = (cover_type)((cover_full + (*dst) * m_mask_function.calculate(mask)) >> cover_shift); ++dst; @@ -420,7 +420,7 @@ namespace agg //-------------------------------------------------------------------- void fill_vspan(int x, int y, cover_type* dst, int num_pix) const { - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { *dst++ = (cover_type)m_mask_function.calculate(mask); @@ -433,10 +433,10 @@ namespace agg //-------------------------------------------------------------------- void combine_vspan(int x, int y, cover_type* dst, int num_pix) const { - const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; do { - *dst = (cover_type)(((*dst) * + *dst = (cover_type)((cover_full + (*dst) * m_mask_function.calculate(mask)) >> cover_shift); ++dst; diff --git a/agg/inc/agg_arc.h b/agg/inc/agg_arc.h index 80b148d910d0..2b872490678f 100755 --- a/agg/inc/agg_arc.h +++ b/agg/inc/agg_arc.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_array.h b/agg/inc/agg_array.h index 2970181c4510..a0b94408d425 100755 --- a/agg/inc/agg_array.h +++ b/agg/inc/agg_array.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -22,26 +22,27 @@ namespace agg { - - //-------------------------------------------------------pod_array_adaptor template<class T> class pod_array_adaptor { public: typedef T value_type; - pod_array_adaptor(T* array, unsigned _size) : - m_array(array), m_size(_size) {} + pod_array_adaptor(T* array, unsigned size) : + m_array(array), m_size(size) {} unsigned size() const { return m_size; } - const T& operator [] (unsigned idx) const { return m_array[idx]; } - T& operator [] (unsigned idx) { return m_array[idx]; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + private: T* m_array; unsigned m_size; }; - //---------------------------------------------------------pod_auto_array template<class T, unsigned Size> class pod_auto_array { @@ -64,46 +65,148 @@ namespace agg static unsigned size() { return Size; } const T& operator [] (unsigned i) const { return m_array[i]; } T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + private: T m_array[Size]; }; + //--------------------------------------------------------pod_auto_vector + template<class T, unsigned Size> class pod_auto_vector + { + public: + typedef T value_type; + typedef pod_auto_vector<T, Size> self_type; + + pod_auto_vector() : m_size(0) {} + void remove_all() { m_size = 0; } + void clear() { m_size = 0; } + void add(const T& v) { m_array[m_size++] = v; } + void push_back(const T& v) { m_array[m_size++] = v; } + void inc_size(unsigned size) { m_size += size; } + + unsigned size() const { return m_size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + private: + T m_array[Size]; + unsigned m_size; + }; //---------------------------------------------------------------pod_array + template<class T> class pod_array + { + public: + typedef T value_type; + typedef pod_array<T> self_type; + + ~pod_array() { pod_allocator<T>::deallocate(m_array, m_size); } + pod_array() : m_array(0), m_size(0) {} + + pod_array(unsigned size) : + m_array(pod_allocator<T>::allocate(size)), + m_size(size) + {} + + pod_array(const self_type& v) : + m_array(pod_allocator<T>::allocate(v.m_size)), + m_size(v.m_size) + { + memcpy(m_array, v.m_array, sizeof(T) * m_size); + } + + void resize(unsigned size) + { + if(size != m_size) + { + pod_allocator<T>::deallocate(m_array, m_size); + m_array = pod_allocator<T>::allocate(m_size = size); + } + } + const self_type& operator = (const self_type& v) + { + resize(v.size()); + memcpy(m_array, v.m_array, sizeof(T) * m_size); + return *this; + } + + unsigned size() const { return m_size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + const T* data() const { return m_array; } + T* data() { return m_array; } + private: + T* m_array; + unsigned m_size; + }; + + + + //--------------------------------------------------------------pod_vector // A simple class template to store Plain Old Data, a vector // of a fixed size. The data is continous in memory //------------------------------------------------------------------------ - template<class T> class pod_array + template<class T> class pod_vector { public: typedef T value_type; - ~pod_array() { delete [] m_array; } - pod_array() : m_size(0), m_capacity(0), m_array(0) {} - pod_array(unsigned cap, unsigned extra_tail=0); + ~pod_vector() { pod_allocator<T>::deallocate(m_array, m_capacity); } + pod_vector() : m_size(0), m_capacity(0), m_array(0) {} + pod_vector(unsigned cap, unsigned extra_tail=0); // Copying - pod_array(const pod_array<T>&); - const pod_array<T>& operator = (const pod_array<T>&); + pod_vector(const pod_vector<T>&); + const pod_vector<T>& operator = (const pod_vector<T>&); - unsigned capacity() const { return m_capacity; } + // Set new capacity. All data is lost, size is set to zero. void capacity(unsigned cap, unsigned extra_tail=0); + unsigned capacity() const { return m_capacity; } + // Allocate n elements. All data is lost, + // but elements can be accessed in range 0...size-1. + void allocate(unsigned size, unsigned extra_tail=0); + + // Resize keeping the content. void resize(unsigned new_size); - void add(const T& v) { m_array[m_size++] = v; } - void inc_size(unsigned _size) { m_size += _size; } - unsigned size() const { return m_size; } - unsigned byte_size() const { return m_size * sizeof(T); } + void zero() + { + memset(m_array, 0, sizeof(T) * m_size); + } + + void add(const T& v) { m_array[m_size++] = v; } + void push_back(const T& v) { m_array[m_size++] = v; } + void insert_at(unsigned pos, const T& val); + void inc_size(unsigned size) { m_size += size; } + unsigned size() const { return m_size; } + unsigned byte_size() const { return m_size * sizeof(T); } void serialize(int8u* ptr) const; void deserialize(const int8u* data, unsigned byte_size); - const T& operator [] (unsigned idx) const { return m_array[idx]; } - T& operator [] (unsigned idx) { return m_array[idx]; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + const T* data() const { return m_array; } + T* data() { return m_array; } void remove_all() { m_size = 0; } + void clear() { m_size = 0; } void cut_at(unsigned num) { if(num < m_size) m_size = num; } private: @@ -114,28 +217,37 @@ namespace agg //------------------------------------------------------------------------ template<class T> - void pod_array<T>::capacity(unsigned cap, unsigned extra_tail) + void pod_vector<T>::capacity(unsigned cap, unsigned extra_tail) { m_size = 0; if(cap > m_capacity) { - delete [] m_array; + pod_allocator<T>::deallocate(m_array, m_capacity); m_capacity = cap + extra_tail; - m_array = m_capacity ? new T [m_capacity] : 0; + m_array = m_capacity ? pod_allocator<T>::allocate(m_capacity) : 0; } } //------------------------------------------------------------------------ template<class T> - void pod_array<T>::resize(unsigned new_size) + void pod_vector<T>::allocate(unsigned size, unsigned extra_tail) + { + capacity(size, extra_tail); + m_size = size; + } + + + //------------------------------------------------------------------------ + template<class T> + void pod_vector<T>::resize(unsigned new_size) { if(new_size > m_size) { if(new_size > m_capacity) { - T* data = new T[new_size]; + T* data = pod_allocator<T>::allocate(new_size); memcpy(data, m_array, m_size * sizeof(T)); - delete [] m_array; + pod_allocator<T>::deallocate(m_array, m_capacity); m_array = data; } } @@ -146,47 +258,61 @@ namespace agg } //------------------------------------------------------------------------ - template<class T> pod_array<T>::pod_array(unsigned cap, unsigned extra_tail) : - m_size(cap), m_capacity(cap + extra_tail), m_array(new T[m_capacity]) {} + template<class T> pod_vector<T>::pod_vector(unsigned cap, unsigned extra_tail) : + m_size(0), + m_capacity(cap + extra_tail), + m_array(pod_allocator<T>::allocate(m_capacity)) {} //------------------------------------------------------------------------ - template<class T> pod_array<T>::pod_array(const pod_array<T>& v) : + template<class T> pod_vector<T>::pod_vector(const pod_vector<T>& v) : m_size(v.m_size), m_capacity(v.m_capacity), - m_array(v.m_capacity ? new T [v.m_capacity] : 0) + m_array(v.m_capacity ? pod_allocator<T>::allocate(v.m_capacity) : 0) { memcpy(m_array, v.m_array, sizeof(T) * v.m_size); } //------------------------------------------------------------------------ - template<class T> const pod_array<T>& - pod_array<T>::operator = (const pod_array<T>&v) + template<class T> const pod_vector<T>& + pod_vector<T>::operator = (const pod_vector<T>&v) { - capacity(v.m_capacity); + allocate(v.m_size); if(v.m_size) memcpy(m_array, v.m_array, sizeof(T) * v.m_size); return *this; } //------------------------------------------------------------------------ - template<class T> void pod_array<T>::serialize(int8u* ptr) const + template<class T> void pod_vector<T>::serialize(int8u* ptr) const { if(m_size) memcpy(ptr, m_array, m_size * sizeof(T)); } //------------------------------------------------------------------------ template<class T> - void pod_array<T>::deserialize(const int8u* data, unsigned _byte_size) + void pod_vector<T>::deserialize(const int8u* data, unsigned byte_size) { - _byte_size /= sizeof(T); - capacity(_byte_size); - if(_byte_size) memcpy(m_array, data, _byte_size * sizeof(T)); + byte_size /= sizeof(T); + allocate(byte_size); + if(byte_size) memcpy(m_array, data, byte_size * sizeof(T)); } + //------------------------------------------------------------------------ + template<class T> + void pod_vector<T>::insert_at(unsigned pos, const T& val) + { + if(pos >= m_size) + { + m_array[m_size] = val; + } + else + { + memmove(m_array + pos + 1, m_array + pos, (m_size - pos) * sizeof(T)); + m_array[pos] = val; + } + ++m_size; + } - - - - //---------------------------------------------------------------pod_deque + //---------------------------------------------------------------pod_bvector // A simple class template to store Plain Old Data, similar to std::deque // It doesn't reallocate memory but instead, uses blocks of data of size // of (1 << S), that is, power of two. The data is NOT contiguous in memory, @@ -197,10 +323,10 @@ namespace agg // of increment to reallocate the pointer buffer. See the second constructor. // By default, the incremeent value equals (1 << S), i.e., the block size. //------------------------------------------------------------------------ - template<class T, unsigned S=6> class pod_deque + template<class T, unsigned S=6> class pod_bvector { public: - enum + enum block_scale_e { block_shift = S, block_size = 1 << block_shift, @@ -209,18 +335,20 @@ namespace agg typedef T value_type; - ~pod_deque(); - pod_deque(); - pod_deque(unsigned block_ptr_inc); + ~pod_bvector(); + pod_bvector(); + pod_bvector(unsigned block_ptr_inc); // Copying - pod_deque(const pod_deque<T, S>& v); - const pod_deque<T, S>& operator = (const pod_deque<T, S>& v); + pod_bvector(const pod_bvector<T, S>& v); + const pod_bvector<T, S>& operator = (const pod_bvector<T, S>& v); void remove_all() { m_size = 0; } - void free_all() { free_tail(0); } + void clear() { m_size = 0; } + void free_all() { free_tail(0); } void free_tail(unsigned size); void add(const T& val); + void push_back(const T& val) { add(val); } void modify_last(const T& val); void remove_last(); @@ -243,21 +371,36 @@ namespace agg } } - void cut_at(unsigned _size) + void cut_at(unsigned size) { - if(_size < m_size) m_size = _size; + if(size < m_size) m_size = size; } unsigned size() const { return m_size; } - const T& operator [] (unsigned idx) const + const T& operator [] (unsigned i) const + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + T& operator [] (unsigned i) + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + const T& at(unsigned i) const { - return m_blocks[idx >> block_shift][idx & block_mask]; + return m_blocks[i >> block_shift][i & block_mask]; } - T& operator [] (unsigned idx) + T& at(unsigned i) { - return m_blocks[idx >> block_shift][idx & block_mask]; + return m_blocks[i >> block_shift][i & block_mask]; + } + + T value_at(unsigned i) const + { + return m_blocks[i >> block_shift][i & block_mask]; } const T& curr(unsigned idx) const @@ -368,39 +511,45 @@ namespace agg //------------------------------------------------------------------------ - template<class T, unsigned S> pod_deque<T, S>::~pod_deque() + template<class T, unsigned S> pod_bvector<T, S>::~pod_bvector() { if(m_num_blocks) { T** blk = m_blocks + m_num_blocks - 1; while(m_num_blocks--) { - delete [] *blk; + pod_allocator<T>::deallocate(*blk, block_size); --blk; } - delete [] m_blocks; } + pod_allocator<T*>::deallocate(m_blocks, m_max_blocks); } //------------------------------------------------------------------------ template<class T, unsigned S> - void pod_deque<T, S>::free_tail(unsigned _size) + void pod_bvector<T, S>::free_tail(unsigned size) { - if(_size < m_size) + if(size < m_size) { - unsigned nb = (_size + block_mask) >> block_shift; + unsigned nb = (size + block_mask) >> block_shift; while(m_num_blocks > nb) { - delete [] m_blocks[--m_num_blocks]; + pod_allocator<T>::deallocate(m_blocks[--m_num_blocks], block_size); } - m_size = _size; + if(m_num_blocks == 0) + { + pod_allocator<T*>::deallocate(m_blocks, m_max_blocks); + m_blocks = 0; + m_max_blocks = 0; + } + m_size = size; } } //------------------------------------------------------------------------ - template<class T, unsigned S> pod_deque<T, S>::pod_deque() : + template<class T, unsigned S> pod_bvector<T, S>::pod_bvector() : m_size(0), m_num_blocks(0), m_max_blocks(0), @@ -412,7 +561,7 @@ namespace agg //------------------------------------------------------------------------ template<class T, unsigned S> - pod_deque<T, S>::pod_deque(unsigned block_ptr_inc) : + pod_bvector<T, S>::pod_bvector(unsigned block_ptr_inc) : m_size(0), m_num_blocks(0), m_max_blocks(0), @@ -424,17 +573,19 @@ namespace agg //------------------------------------------------------------------------ template<class T, unsigned S> - pod_deque<T, S>::pod_deque(const pod_deque<T, S>& v) : + pod_bvector<T, S>::pod_bvector(const pod_bvector<T, S>& v) : m_size(v.m_size), m_num_blocks(v.m_num_blocks), m_max_blocks(v.m_max_blocks), - m_blocks(v.m_max_blocks ? new T* [v.m_max_blocks] : 0), + m_blocks(v.m_max_blocks ? + pod_allocator<T*>::allocate(v.m_max_blocks) : + 0), m_block_ptr_inc(v.m_block_ptr_inc) { unsigned i; for(i = 0; i < v.m_num_blocks; ++i) { - m_blocks[i] = new T [block_size]; + m_blocks[i] = pod_allocator<T>::allocate(block_size); memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); } } @@ -442,7 +593,8 @@ namespace agg //------------------------------------------------------------------------ template<class T, unsigned S> - const pod_deque<T, S>& pod_deque<T, S>::operator = (const pod_deque<T, S>& v) + const pod_bvector<T, S>& + pod_bvector<T, S>::operator = (const pod_bvector<T, S>& v) { unsigned i; for(i = m_num_blocks; i < v.m_num_blocks; ++i) @@ -460,11 +612,11 @@ namespace agg //------------------------------------------------------------------------ template<class T, unsigned S> - void pod_deque<T, S>::allocate_block(unsigned nb) + void pod_bvector<T, S>::allocate_block(unsigned nb) { if(nb >= m_max_blocks) { - T** new_blocks = new T* [m_max_blocks + m_block_ptr_inc]; + T** new_blocks = pod_allocator<T*>::allocate(m_max_blocks + m_block_ptr_inc); if(m_blocks) { @@ -472,12 +624,12 @@ namespace agg m_blocks, m_num_blocks * sizeof(T*)); - delete [] m_blocks; + pod_allocator<T*>::deallocate(m_blocks, m_max_blocks); } m_blocks = new_blocks; m_max_blocks += m_block_ptr_inc; } - m_blocks[nb] = new T [block_size]; + m_blocks[nb] = pod_allocator<T>::allocate(block_size); m_num_blocks++; } @@ -485,7 +637,7 @@ namespace agg //------------------------------------------------------------------------ template<class T, unsigned S> - inline T* pod_deque<T, S>::data_ptr() + inline T* pod_bvector<T, S>::data_ptr() { unsigned nb = m_size >> block_shift; if(nb >= m_num_blocks) @@ -499,7 +651,7 @@ namespace agg //------------------------------------------------------------------------ template<class T, unsigned S> - inline void pod_deque<T, S>::add(const T& val) + inline void pod_bvector<T, S>::add(const T& val) { *data_ptr() = val; ++m_size; @@ -508,7 +660,7 @@ namespace agg //------------------------------------------------------------------------ template<class T, unsigned S> - inline void pod_deque<T, S>::remove_last() + inline void pod_bvector<T, S>::remove_last() { if(m_size) --m_size; } @@ -516,7 +668,7 @@ namespace agg //------------------------------------------------------------------------ template<class T, unsigned S> - void pod_deque<T, S>::modify_last(const T& val) + void pod_bvector<T, S>::modify_last(const T& val) { remove_last(); add(val); @@ -525,7 +677,7 @@ namespace agg //------------------------------------------------------------------------ template<class T, unsigned S> - int pod_deque<T, S>::allocate_continuous_block(unsigned num_elements) + int pod_bvector<T, S>::allocate_continuous_block(unsigned num_elements) { if(num_elements < block_size) { @@ -555,7 +707,7 @@ namespace agg //------------------------------------------------------------------------ template<class T, unsigned S> - unsigned pod_deque<T, S>::byte_size() const + unsigned pod_bvector<T, S>::byte_size() const { return m_size * sizeof(T); } @@ -563,7 +715,7 @@ namespace agg //------------------------------------------------------------------------ template<class T, unsigned S> - void pod_deque<T, S>::serialize(int8u* ptr) const + void pod_bvector<T, S>::serialize(int8u* ptr) const { unsigned i; for(i = 0; i < m_size; i++) @@ -575,11 +727,11 @@ namespace agg //------------------------------------------------------------------------ template<class T, unsigned S> - void pod_deque<T, S>::deserialize(const int8u* data, unsigned _byte_size) + void pod_bvector<T, S>::deserialize(const int8u* data, unsigned byte_size) { remove_all(); - _byte_size /= sizeof(T); - for(unsigned i = 0; i < _byte_size; ++i) + byte_size /= sizeof(T); + for(unsigned i = 0; i < byte_size; ++i) { T* ptr = data_ptr(); memcpy(ptr, data, sizeof(T)); @@ -592,16 +744,16 @@ namespace agg // Replace or add a number of elements starting from "start" position //------------------------------------------------------------------------ template<class T, unsigned S> - void pod_deque<T, S>::deserialize(unsigned start, const T& empty_val, - const int8u* data, unsigned _byte_size) + void pod_bvector<T, S>::deserialize(unsigned start, const T& empty_val, + const int8u* data, unsigned byte_size) { while(m_size < start) { add(empty_val); } - _byte_size /= sizeof(T); - for(unsigned i = 0; i < _byte_size; ++i) + byte_size /= sizeof(T); + for(unsigned i = 0; i < byte_size; ++i) { if(start + i < m_size) { @@ -618,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 @@ -626,20 +778,26 @@ namespace agg // creates a new block of the required size. However, the most efficient // use is when the average reqired size is much less than the block size. //------------------------------------------------------------------------ - class pod_allocator + class block_allocator { + struct block_type + { + int8u* data; + unsigned size; + }; + public: void remove_all() { if(m_num_blocks) { - int8u** blk = m_blocks + m_num_blocks - 1; + block_type* blk = m_blocks + m_num_blocks - 1; while(m_num_blocks--) { - delete [] *blk; + pod_allocator<int8u>::deallocate(blk->data, blk->size); --blk; } - delete [] m_blocks; + pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks); } m_num_blocks = 0; m_max_blocks = 0; @@ -648,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), @@ -673,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) @@ -700,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<block_type>::allocate(m_max_blocks + m_block_ptr_inc); if(m_blocks) { memcpy(new_blocks, m_blocks, - m_num_blocks * sizeof(int8u*)); - - delete [] m_blocks; + m_num_blocks * sizeof(block_type)); + pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks); } m_blocks = new_blocks; m_max_blocks += m_block_ptr_inc; } - m_blocks[m_num_blocks] = m_buf_ptr = new int8u [size]; + + m_blocks[m_num_blocks].size = size; + m_blocks[m_num_blocks].data = + m_buf_ptr = + pod_allocator<int8u>::allocate(size); + m_num_blocks++; m_rest = size; } - 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; }; @@ -735,7 +900,7 @@ namespace agg //------------------------------------------------------------------------ - enum + enum quick_sort_threshold_e { quick_sort_threshold = 9 }; @@ -859,7 +1024,7 @@ namespace agg //------------------------------------------------------remove_duplicates - // Remove duplicates from a sorted array. It doesn't cut the the + // Remove duplicates from a sorted array. It doesn't cut the // tail of the array, it just returns the number of remaining elements. //----------------------------------------------------------------------- template<class Array, class Equal> @@ -879,9 +1044,76 @@ namespace agg return j; } + //--------------------------------------------------------invert_container + template<class Array> void invert_container(Array& arr) + { + int i = 0; + int j = arr.size() - 1; + while(i < j) + { + swap_elements(arr[i++], arr[j--]); + } + } + + //------------------------------------------------------binary_search_pos + template<class Array, class Value, class Less> + unsigned binary_search_pos(const Array& arr, const Value& val, Less less) + { + if(arr.size() == 0) return 0; + + unsigned beg = 0; + unsigned end = arr.size() - 1; + + if(less(val, arr[0])) return 0; + if(less(arr[end], val)) return end + 1; + + while(end - beg > 1) + { + unsigned mid = (end + beg) >> 1; + if(less(val, arr[mid])) end = mid; + else beg = mid; + } + + //if(beg <= 0 && less(val, arr[0])) return 0; + //if(end >= arr.size() - 1 && less(arr[end], val)) ++end; + + return end; + } + + //----------------------------------------------------------range_adaptor + template<class Array> class range_adaptor + { + public: + typedef typename Array::value_type value_type; + + range_adaptor(Array& array, unsigned start, unsigned size) : + m_array(array), m_start(start), m_size(size) + {} + + unsigned size() const { return m_size; } + const value_type& operator [] (unsigned i) const { return m_array[m_start + i]; } + value_type& operator [] (unsigned i) { return m_array[m_start + i]; } + const value_type& at(unsigned i) const { return m_array[m_start + i]; } + value_type& at(unsigned i) { return m_array[m_start + i]; } + value_type value_at(unsigned i) const { return m_array[m_start + i]; } + + private: + Array& m_array; + unsigned m_start; + unsigned m_size; + }; + + //---------------------------------------------------------------int_less + inline bool int_less(int a, int b) { return a < b; } + //------------------------------------------------------------int_greater + inline bool int_greater(int a, int b) { return a > b; } + //----------------------------------------------------------unsigned_less + inline bool unsigned_less(unsigned a, unsigned b) { return a < b; } + //-------------------------------------------------------unsigned_greater + inline bool unsigned_greater(unsigned a, unsigned b) { return a > b; } } #endif diff --git a/agg/inc/agg_arrowhead.h b/agg/inc/agg_arrowhead.h index aac99c5ae980..d900d317b22f 100755 --- a/agg/inc/agg_arrowhead.h +++ b/agg/inc/agg_arrowhead.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -57,7 +57,7 @@ namespace agg void tail() { m_tail_flag = true; } void no_tail() { m_tail_flag = false; } - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: diff --git a/agg/inc/agg_basics.h b/agg/inc/agg_basics.h index d9ca881ab328..a87050c85dbc 100755 --- a/agg/inc/agg_basics.h +++ b/agg/inc/agg_basics.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -16,8 +16,46 @@ #ifndef AGG_BASICS_INCLUDED #define AGG_BASICS_INCLUDED +#include <math.h> #include "agg_config.h" +//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR +#ifdef AGG_CUSTOM_ALLOCATOR +#include "agg_allocator.h" +#else +namespace agg +{ + // The policy of all AGG containers and memory allocation strategy + // in general is that no allocated data requires explicit construction. + // It means that the allocator can be really simple; you can even + // replace new/delete to malloc/free. The constructors and destructors + // won't be called in this case, however everything will remain working. + // The second argument of deallocate() is the size of the allocated + // block. You can use this information if you wish. + //------------------------------------------------------------pod_allocator + template<class T> struct pod_allocator + { + static T* allocate(unsigned num) { return new T [num]; } + static void deallocate(T* ptr, unsigned) { delete [] ptr; } + }; + + // Single object allocator. It's also can be replaced with your custom + // allocator. The difference is that it can only allocate a single + // object and the constructor and destructor must be called. + // In AGG there is no need to allocate an array of objects with + // calling their constructors (only single ones). So that, if you + // replace these new/delete to malloc/free make sure that the in-place + // new is called and take care of calling the destructor too. + //------------------------------------------------------------obj_allocator + template<class T> struct obj_allocator + { + static T* allocate() { return new T; } + static void deallocate(T* ptr) { delete ptr; } + }; +} +#endif + + //-------------------------------------------------------- Default basic types // // If the compiler has different capacity of the basic types you can redefine @@ -49,7 +87,7 @@ #endif #ifndef AGG_INT64 -#if defined(_MSC_VER) +#if defined(_MSC_VER) || defined(__BORLANDC__) #define AGG_INT64 signed __int64 #else #define AGG_INT64 signed long long @@ -57,7 +95,7 @@ #endif #ifndef AGG_INT64U -#if defined(_MSC_VER) +#if defined(_MSC_VER) || defined(__BORLANDC__) #define AGG_INT64U unsigned __int64 #else #define AGG_INT64U unsigned long long @@ -87,9 +125,92 @@ namespace agg typedef AGG_INT64 int64; //----int64 typedef AGG_INT64U int64u; //----int64u +#if defined(AGG_FISTP) +#pragma warning(push) +#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 [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 [t] + __asm mov eax, dword ptr [t] + } +#pragma warning(pop) + AGG_INLINE unsigned ufloor(double v) //-------ufloor + { + return unsigned(floor(v)); + } + AGG_INLINE unsigned uceil(double v) //--------uceil + { + return unsigned(ceil(v)); + } +#elif defined(AGG_QIFIST) + AGG_INLINE int iround(double v) + { + return int(v); + } + AGG_INLINE int uround(double v) + { + return unsigned(v); + } + AGG_INLINE unsigned ufloor(double v) + { + return unsigned(floor(v)); + } + AGG_INLINE unsigned uceil(double v) + { + return unsigned(ceil(v)); + } +#else + AGG_INLINE int iround(double v) + { + return int((v < 0.0) ? v - 0.5 : v + 0.5); + } + AGG_INLINE int uround(double v) + { + return unsigned(v + 0.5); + } + AGG_INLINE unsigned ufloor(double v) + { + return unsigned(v); + } + AGG_INLINE unsigned uceil(double v) + { + return unsigned(ceil(v)); + } +#endif + + //---------------------------------------------------------------saturation + template<int Limit> struct saturation + { + AGG_INLINE static int iround(double v) + { + if(v < double(-Limit)) return -Limit; + if(v > double( Limit)) return Limit; + return agg::iround(v); + } + }; + + //------------------------------------------------------------------mul_one + template<unsigned Shift> struct mul_one + { + AGG_INLINE static unsigned mul(unsigned a, unsigned b) + { + register unsigned q = a * b + (1 << (Shift-1)); + return (q + (q >> Shift)) >> Shift; + } + }; + //------------------------------------------------------------------------- typedef unsigned char cover_type; //----cover_type - enum + enum cover_scale_e { cover_shift = 8, //----cover_shift cover_size = 1 << cover_shift, //----cover_size @@ -98,6 +219,25 @@ namespace agg cover_full = cover_mask //----cover_full }; + //----------------------------------------------------poly_subpixel_scale_e + // These constants determine the subpixel accuracy, to be more precise, + // the number of bits of the fractional part of the coordinates. + // The possible coordinate capacity in bits can be calculated by formula: + // sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and + // 8-bits fractional part the capacity is 24 bits. + enum poly_subpixel_scale_e + { + poly_subpixel_shift = 8, //----poly_subpixel_shift + poly_subpixel_scale = 1<<poly_subpixel_shift, //----poly_subpixel_scale + poly_subpixel_mask = poly_subpixel_scale-1, //----poly_subpixel_mask + }; + + //----------------------------------------------------------filling_rule_e + enum filling_rule_e + { + fill_non_zero, + fill_even_odd + }; //-----------------------------------------------------------------------pi const double pi = 3.14159265358979323846; @@ -117,16 +257,19 @@ namespace agg //----------------------------------------------------------------rect_base template<class T> struct rect_base { + typedef T value_type; typedef rect_base<T> self_type; - T x1; - T y1; - T x2; - T y2; + T x1, y1, x2, y2; rect_base() {} rect_base(T x1_, T y1_, T x2_, T y2_) : x1(x1_), y1(y1_), x2(x2_), y2(y2_) {} + void init(T x1_, T y1_, T x2_, T y2_) + { + x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_; + } + const self_type& normalize() { T t; @@ -148,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 @@ -181,7 +329,8 @@ namespace agg return r; } - typedef rect_base<int> rect; //----rect + typedef rect_base<int> rect_i; //----rect_i + typedef rect_base<float> rect_f; //----rect_f typedef rect_base<double> rect_d; //----rect_d //---------------------------------------------------------path_commands_e @@ -192,7 +341,10 @@ namespace agg path_cmd_line_to = 2, //----path_cmd_line_to path_cmd_curve3 = 3, //----path_cmd_curve3 path_cmd_curve4 = 4, //----path_cmd_curve4 - path_cmd_end_poly = 6, //----path_cmd_end_poly + path_cmd_curveN = 5, //----path_cmd_curveN + path_cmd_catrom = 6, //----path_cmd_catrom + path_cmd_ubspline = 7, //----path_cmd_ubspline + path_cmd_end_poly = 0x0F, //----path_cmd_end_poly path_cmd_mask = 0x0F //----path_cmd_mask }; @@ -212,6 +364,12 @@ namespace agg return c >= path_cmd_move_to && c < path_cmd_end_poly; } + //--------------------------------------------------------------is_drawing + inline bool is_drawing(unsigned c) + { + return c >= path_cmd_line_to && c < path_cmd_end_poly; + } + //-----------------------------------------------------------------is_stop inline bool is_stop(unsigned c) { @@ -258,7 +416,7 @@ namespace agg inline bool is_close(unsigned c) { return (c & ~(path_flags_cw | path_flags_ccw)) == - (((bool)path_cmd_end_poly) | ((bool)path_flags_close)); + (path_cmd_end_poly | path_flags_close); } //------------------------------------------------------------is_next_poly @@ -315,26 +473,55 @@ namespace agg return clear_orientation(c) | o; } - //--------------------------------------------------------------point_type - struct point_type + //--------------------------------------------------------------point_base + template<class T> struct point_base { - double x, y; - - point_type() {} - point_type(double x_, double y_) : x(x_), y(y_) {} + typedef T value_type; + T x,y; + point_base() {} + point_base(T x_, T y_) : x(x_), y(y_) {} }; + typedef point_base<int> point_i; //-----point_i + typedef point_base<float> point_f; //-----point_f + typedef point_base<double> point_d; //-----point_d - //-------------------------------------------------------------vertex_type - struct vertex_type + //-------------------------------------------------------------vertex_base + template<class T> struct vertex_base { - double x, y; + typedef T value_type; + T x,y; unsigned cmd; + vertex_base() {} + vertex_base(T x_, T y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {} + }; + typedef vertex_base<int> vertex_i; //-----vertex_i + typedef vertex_base<float> vertex_f; //-----vertex_f + typedef vertex_base<double> vertex_d; //-----vertex_d - vertex_type() {} - vertex_type(double x_, double y_, unsigned cmd_) : - x(x_), y(y_), cmd(cmd_) {} + //----------------------------------------------------------------row_info + template<class T> struct row_info + { + int x1, x2; + T* ptr; + row_info() {} + row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {} }; + //----------------------------------------------------------const_row_info + template<class T> struct const_row_info + { + int x1, x2; + const T* ptr; + const_row_info() {} + const_row_info(int x1_, int x2_, const T* ptr_) : + x1(x1_), x2(x2_), ptr(ptr_) {} + }; + + //------------------------------------------------------------is_equal_eps + template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon) + { + return fabs(v1 - v2) <= double(epsilon); + } } diff --git a/agg/inc/agg_bezier_arc.h b/agg/inc/agg_bezier_arc.h index f437ab0a00bd..f92d5be4e5e9 100755 --- a/agg/inc/agg_bezier_arc.h +++ b/agg/inc/agg_bezier_arc.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -40,7 +40,7 @@ namespace agg { public: //-------------------------------------------------------------------- - bezier_arc() : m_vertex(26) {} + bezier_arc() : m_vertex(26), m_num_vertices(0), m_cmd(path_cmd_line_to) {} bezier_arc(double x, double y, double rx, double ry, double start_angle, @@ -68,7 +68,7 @@ namespace agg *x = m_vertices[m_vertex]; *y = m_vertices[m_vertex + 1]; m_vertex += 2; - return (m_vertex == 2) ? path_cmd_move_to : path_cmd_curve4; + return (m_vertex == 2) ? path_cmd_move_to : m_cmd; } // Supplemantary functions. num_vertices() actually returns doubled @@ -82,6 +82,7 @@ namespace agg unsigned m_vertex; unsigned m_num_vertices; double m_vertices[26]; + unsigned m_cmd; }; diff --git a/agg/inc/agg_bitset_iterator.h b/agg/inc/agg_bitset_iterator.h index 543432b65d54..843a2b576d89 100755 --- a/agg/inc/agg_bitset_iterator.h +++ b/agg/inc/agg_bitset_iterator.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_bounding_rect.h b/agg/inc/agg_bounding_rect.h index 9a3c301069d7..4c7886be86a7 100755 --- a/agg/inc/agg_bounding_rect.h +++ b/agg/inc/agg_bounding_rect.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_bspline.h b/agg/inc/agg_bspline.h index ca58fa839b44..8d5fcf0b4cdf 100755 --- a/agg/inc/agg_bspline.h +++ b/agg/inc/agg_bspline.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -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<double> m_am; + mutable int m_last_idx; }; diff --git a/agg/inc/agg_clip_liang_barsky.h b/agg/inc/agg_clip_liang_barsky.h index e229d52bc6e9..28765a79cd09 100755 --- a/agg/inc/agg_clip_liang_barsky.h +++ b/agg/inc/agg_clip_liang_barsky.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -24,6 +24,17 @@ namespace agg { + //------------------------------------------------------------------------ + enum clipping_flags_e + { + clipping_flags_x1_clipped = 4, + clipping_flags_x2_clipped = 1, + clipping_flags_y1_clipped = 8, + clipping_flags_y2_clipped = 2, + clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped, + clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped + }; + //----------------------------------------------------------clipping_flags // Determine the clipping code of the vertex according to the // Cyrus-Beck line clipping algorithm @@ -51,11 +62,25 @@ namespace agg ((y < clip_box.y1) << 3); } + //--------------------------------------------------------clipping_flags_x + template<class T> + inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box) + { + return (x > clip_box.x2) | ((x < clip_box.x1) << 2); + } + + + //--------------------------------------------------------clipping_flags_y + template<class T> + inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box) + { + return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3); + } //-------------------------------------------------------clip_liang_barsky template<class T> - /*inline*/ unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, + inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, const rect_base<T>& clip_box, T* x, T* y) { @@ -204,6 +229,105 @@ namespace agg } + //---------------------------------------------------------------------------- + template<class T> + bool clip_move_point(T x1, T y1, T x2, T y2, + const rect_base<T>& clip_box, + T* x, T* y, unsigned flags) + { + T bound; + + if(flags & clipping_flags_x_clipped) + { + if(x1 == x2) + { + return false; + } + bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2; + *y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1); + *x = bound; + } + + flags = clipping_flags_y(*y, clip_box); + if(flags & clipping_flags_y_clipped) + { + if(y1 == y2) + { + return false; + } + bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2; + *x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1); + *y = bound; + } + return true; + } + + //-------------------------------------------------------clip_line_segment + // Returns: ret >= 4 - Fully clipped + // (ret & 1) != 0 - First point has been moved + // (ret & 2) != 0 - Second point has been moved + // + template<class T> + unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2, + const rect_base<T>& clip_box) + { + unsigned f1 = clipping_flags(*x1, *y1, clip_box); + unsigned f2 = clipping_flags(*x2, *y2, clip_box); + unsigned ret = 0; + + if((f2 | f1) == 0) + { + // Fully visible + return 0; + } + + if((f1 & clipping_flags_x_clipped) != 0 && + (f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped)) + { + // Fully clipped + return 4; + } + + if((f1 & clipping_flags_y_clipped) != 0 && + (f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped)) + { + // Fully clipped + return 4; + } + + T tx1 = *x1; + T ty1 = *y1; + T tx2 = *x2; + T ty2 = *y2; + if(f1) + { + if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1)) + { + return 4; + } + if(*x1 == *x2 && *y1 == *y2) + { + return 4; + } + ret |= 1; + } + if(f2) + { + if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2)) + { + return 4; + } + if(*x1 == *x2 && *y1 == *y2) + { + return 4; + } + ret |= 2; + } + return ret; + } + + } + #endif diff --git a/agg/inc/agg_color_gray.h b/agg/inc/agg_color_gray.h index 1d0ffd8e773d..865798e9d06b 100755 --- a/agg/inc/agg_color_gray.h +++ b/agg/inc/agg_color_gray.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -40,11 +40,11 @@ namespace agg typedef int8u value_type; typedef int32u calc_type; typedef int32 long_type; - enum + enum base_scale_e { base_shift = 8, - base_size = 1 << base_shift, - base_mask = base_size - 1 + base_scale = 1 << base_shift, + base_mask = base_scale - 1 }; typedef gray8 self_type; @@ -64,13 +64,13 @@ namespace agg //-------------------------------------------------------------------- gray8(const rgba& c) : - v(value_type((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask) + 0.5)), - a(value_type(c.a * double(base_mask))) {} + v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), + a((value_type)uround(c.a * double(base_mask))) {} //-------------------------------------------------------------------- gray8(const rgba& c, double a_) : - v(value_type((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask) + 0.5)), - a(value_type(a_ * double(base_mask))) {} + v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), + a((value_type)uround(a_ * double(base_mask))) {} //-------------------------------------------------------------------- gray8(const rgba8& c) : @@ -100,7 +100,7 @@ namespace agg { if(a_ < 0.0) a_ = 0.0; if(a_ > 1.0) a_ = 1.0; - a = value_type(a_ * double(base_mask)); + a = (value_type)uround(a_ * double(base_mask)); } //-------------------------------------------------------------------- @@ -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; } @@ -156,13 +156,38 @@ namespace agg self_type gradient(self_type c, double k) const { self_type ret; - calc_type ik = calc_type(k * base_size); + calc_type ik = uround(k * base_scale); ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift)); ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); 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); } }; @@ -202,11 +227,11 @@ namespace agg typedef int16u value_type; typedef int32u calc_type; typedef int64 long_type; - enum + enum base_scale_e { base_shift = 16, - base_size = 1 << base_shift, - base_mask = base_size - 1 + base_scale = 1 << base_shift, + base_mask = base_scale - 1 }; typedef gray16 self_type; @@ -226,13 +251,13 @@ namespace agg //-------------------------------------------------------------------- gray16(const rgba& c) : - v(value_type((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask) + 0.5)), - a(value_type(c.a * double(base_mask))) {} + v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), + a((value_type)uround(c.a * double(base_mask))) {} //-------------------------------------------------------------------- gray16(const rgba& c, double a_) : - v(value_type((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask) + 0.5)), - a(value_type(a_ * double(base_mask))) {} + v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), + a((value_type)uround(a_ * double(base_mask))) {} //-------------------------------------------------------------------- gray16(const rgba8& c) : @@ -262,7 +287,7 @@ namespace agg { if(a_ < 0.0) a_ = 0.0; if(a_ > 1.0) a_ = 1.0; - a = value_type(a_ * double(base_mask)); + a = (value_type)uround(a_ * double(base_mask)); } //-------------------------------------------------------------------- @@ -318,13 +343,38 @@ namespace agg self_type gradient(self_type c, double k) const { self_type ret; - calc_type ik = calc_type(k * base_size); + calc_type ik = uround(k * base_scale); ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift)); ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); 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/inc/agg_color_rgba.h b/agg/inc/agg_color_rgba.h index e1f77206cc66..9b9e9321db1b 100755 --- a/agg/inc/agg_color_rgba.h +++ b/agg/inc/agg_color_rgba.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -31,12 +31,12 @@ namespace agg { // Supported byte orders for RGB and RGBA pixel formats //======================================================================= - struct order_rgb { enum { R=0, G=1, B=2, rgb_tag }; }; //----order_rgb - struct order_bgr { enum { B=0, G=1, R=2, rgb_tag }; }; //----order_bgr - struct order_rgba { enum { R=0, G=1, B=2, A=3, rgba_tag }; }; //----order_rgba - struct order_argb { enum { A=0, R=1, G=2, B=3, rgba_tag }; }; //----order_argb - struct order_abgr { enum { A=0, B=1, G=2, R=3, rgba_tag }; }; //----order_abgr - struct order_bgra { enum { B=0, G=1, R=2, A=3, rgba_tag }; }; //----order_bgra + struct order_rgb { enum rgb_e { R=0, G=1, B=2, rgb_tag }; }; //----order_rgb + struct order_bgr { enum bgr_e { B=0, G=1, R=2, rgb_tag }; }; //----order_bgr + struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag }; }; //----order_rgba + struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag }; }; //----order_argb + struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag }; }; //----order_abgr + struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag }; }; //----order_bgra //====================================================================rgba struct rgba @@ -145,7 +145,7 @@ namespace agg static rgba from_wavelength(double wl, double gamma = 1.0); //-------------------------------------------------------------------- - rgba(double wavelen, double gamma=1.0) + explicit rgba(double wavelen, double gamma=1.0) { *this = from_wavelength(wavelen, gamma); } @@ -225,11 +225,11 @@ namespace agg typedef int8u value_type; typedef int32u calc_type; typedef int32 long_type; - enum + enum base_scale_e { base_shift = 8, - base_size = 1 << base_shift, - base_mask = base_size - 1 + base_scale = 1 << base_shift, + base_mask = base_scale - 1 }; typedef rgba8 self_type; @@ -251,10 +251,10 @@ namespace agg //-------------------------------------------------------------------- rgba8(const rgba& c, double a_) : - r(value_type(c.r * double(base_mask) + 0.5)), - g(value_type(c.g * double(base_mask) + 0.5)), - b(value_type(c.b * double(base_mask) + 0.5)), - a(value_type(a_ * double(base_mask) + 0.5)) {} + r((value_type)uround(c.r * double(base_mask))), + g((value_type)uround(c.g * double(base_mask))), + b((value_type)uround(c.b * double(base_mask))), + a((value_type)uround(a_ * double(base_mask))) {} //-------------------------------------------------------------------- rgba8(const self_type& c, unsigned a_) : @@ -262,10 +262,10 @@ namespace agg //-------------------------------------------------------------------- rgba8(const rgba& c) : - r(value_type(c.r * double(base_mask) + 0.5)), - g(value_type(c.g * double(base_mask) + 0.5)), - b(value_type(c.b * double(base_mask) + 0.5)), - a(value_type(c.a * double(base_mask) + 0.5)) {} + r((value_type)uround(c.r * double(base_mask))), + g((value_type)uround(c.g * double(base_mask))), + b((value_type)uround(c.b * double(base_mask))), + a((value_type)uround(c.a * double(base_mask))) {} //-------------------------------------------------------------------- void clear() @@ -285,7 +285,7 @@ namespace agg { if(a_ < 0.0) a_ = 0.0; if(a_ > 1.0) a_ = 1.0; - a = value_type(a_ * double(base_mask) + 0.5); + a = (value_type)uround(a_ * double(base_mask)); return *this; } @@ -296,7 +296,7 @@ namespace agg } //-------------------------------------------------------------------- - const self_type& premultiply() + AGG_INLINE const self_type& premultiply() { if(a == base_mask) return *this; if(a == 0) @@ -311,7 +311,7 @@ namespace agg } //-------------------------------------------------------------------- - const self_type& premultiply(unsigned a_) + AGG_INLINE const self_type& premultiply(unsigned a_) { if(a == base_mask && a_ >= base_mask) return *this; if(a == 0 || a_ == 0) @@ -330,7 +330,7 @@ namespace agg } //-------------------------------------------------------------------- - const self_type& demultiply() + AGG_INLINE const self_type& demultiply() { if(a == base_mask) return *this; if(a == 0) @@ -341,17 +341,17 @@ namespace agg calc_type r_ = (calc_type(r) * base_mask) / a; calc_type g_ = (calc_type(g) * base_mask) / a; calc_type b_ = (calc_type(b) * base_mask) / a; - r = value_type((r_ > base_mask) ? base_mask : r_); - g = value_type((g_ > base_mask) ? base_mask : g_); - b = value_type((b_ > base_mask) ? base_mask : b_); + r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); + g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); + b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); return *this; } //-------------------------------------------------------------------- - self_type gradient(const self_type& c, double k) const + AGG_INLINE self_type gradient(const self_type& c, double k) const { self_type ret; - calc_type ik = calc_type(k * base_size); + calc_type ik = uround(k * base_scale); ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift)); ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift)); ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift)); @@ -360,6 +360,55 @@ namespace agg } //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cr, cg, cb, ca; + if(cover == cover_mask) + { + if(c.a == base_mask) + { + *this = c; + } + else + { + cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; + cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; + cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; + ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + else + { + cr = r + ((c.r * cover + cover_mask/2) >> cover_shift); + cg = g + ((c.g * cover + cover_mask/2) >> cover_shift); + cb = b + ((c.b * cover + cover_mask/2) >> cover_shift); + ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); + r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; + g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; + b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; + a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + + //-------------------------------------------------------------------- + template<class GammaLUT> + AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) + { + r = gamma.dir(r); + g = gamma.dir(g); + b = gamma.dir(b); + } + + //-------------------------------------------------------------------- + template<class GammaLUT> + AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) + { + r = gamma.inv(r); + g = gamma.inv(g); + b = gamma.inv(b); + } + + //-------------------------------------------------------------------- static self_type no_color() { return self_type(0,0,0,0); } //-------------------------------------------------------------------- @@ -394,42 +443,53 @@ namespace agg } - //-----------------------------------------------------------rgb8_packed + //-------------------------------------------------------------rgb8_packed inline rgba8 rgb8_packed(unsigned v) { return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); } - //-----------------------------------------------------------bgr8_packed + //-------------------------------------------------------------bgr8_packed inline rgba8 bgr8_packed(unsigned v) { return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF); } - //----------------------------------------------------------argb8_packed + //------------------------------------------------------------argb8_packed inline rgba8 argb8_packed(unsigned v) { return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24); } + //---------------------------------------------------------rgba8_gamma_dir + template<class GammaLUT> + rgba8 rgba8_gamma_dir(rgba8 c, const GammaLUT& gamma) + { + return rgba8(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); + } + //---------------------------------------------------------rgba8_gamma_inv + template<class GammaLUT> + rgba8 rgba8_gamma_inv(rgba8 c, const GammaLUT& gamma) + { + return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); + } - - //=================================================================rgba16 + //==================================================================rgba16 struct rgba16 { typedef int16u value_type; typedef int32u calc_type; typedef int64 long_type; - enum + enum base_scale_e { base_shift = 16, - base_size = 1 << base_shift, - base_mask = base_size - 1 + base_scale = 1 << base_shift, + base_mask = base_scale - 1 }; typedef rgba16 self_type; @@ -454,17 +514,17 @@ namespace agg //-------------------------------------------------------------------- rgba16(const rgba& c) : - r(value_type(c.r * double(base_mask) + 0.5)), - g(value_type(c.g * double(base_mask) + 0.5)), - b(value_type(c.b * double(base_mask) + 0.5)), - a(value_type(c.a * double(base_mask) + 0.5)) {} + r((value_type)uround(c.r * double(base_mask))), + g((value_type)uround(c.g * double(base_mask))), + b((value_type)uround(c.b * double(base_mask))), + a((value_type)uround(c.a * double(base_mask))) {} //-------------------------------------------------------------------- rgba16(const rgba& c, double a_) : - r(value_type(c.r * double(base_mask) + 0.5)), - g(value_type(c.g * double(base_mask) + 0.5)), - b(value_type(c.b * double(base_mask) + 0.5)), - a(value_type(a_ * double(base_mask) + 0.5)) {} + r((value_type)uround(c.r * double(base_mask))), + g((value_type)uround(c.g * double(base_mask))), + b((value_type)uround(c.b * double(base_mask))), + a((value_type)uround(a_ * double(base_mask))) {} //-------------------------------------------------------------------- rgba16(const rgba8& c) : @@ -494,11 +554,11 @@ namespace agg } //-------------------------------------------------------------------- - const self_type& opacity(double a_) + AGG_INLINE const self_type& opacity(double a_) { if(a_ < 0.0) a_ = 0.0; if(a_ > 1.0) a_ = 1.0; - a = value_type(a_ * double(base_mask) + 0.5); + a = (value_type)uround(a_ * double(base_mask)); return *this; } @@ -509,7 +569,7 @@ namespace agg } //-------------------------------------------------------------------- - const self_type& premultiply() + AGG_INLINE const self_type& premultiply() { if(a == base_mask) return *this; if(a == 0) @@ -524,7 +584,7 @@ namespace agg } //-------------------------------------------------------------------- - const self_type& premultiply(unsigned a_) + AGG_INLINE const self_type& premultiply(unsigned a_) { if(a == base_mask && a_ >= base_mask) return *this; if(a == 0 || a_ == 0) @@ -543,7 +603,7 @@ namespace agg } //-------------------------------------------------------------------- - const self_type& demultiply() + AGG_INLINE const self_type& demultiply() { if(a == base_mask) return *this; if(a == 0) @@ -554,17 +614,17 @@ namespace agg calc_type r_ = (calc_type(r) * base_mask) / a; calc_type g_ = (calc_type(g) * base_mask) / a; calc_type b_ = (calc_type(b) * base_mask) / a; - r = value_type((r_ > base_mask) ? base_mask : r_); - g = value_type((g_ > base_mask) ? base_mask : g_); - b = value_type((b_ > base_mask) ? base_mask : b_); + r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); + g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); + b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); return *this; } //-------------------------------------------------------------------- - self_type gradient(const self_type& c, double k) const + AGG_INLINE self_type gradient(const self_type& c, double k) const { self_type ret; - calc_type ik = calc_type(k * base_size); + calc_type ik = uround(k * base_scale); ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift)); ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift)); ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift)); @@ -573,6 +633,55 @@ namespace agg } //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cr, cg, cb, ca; + if(cover == cover_mask) + { + if(c.a == base_mask) + { + *this = c; + } + else + { + cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; + cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; + cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; + ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + else + { + cr = r + ((c.r * cover + cover_mask) >> cover_shift); + cg = g + ((c.g * cover + cover_mask) >> cover_shift); + cb = b + ((c.b * cover + cover_mask) >> cover_shift); + ca = a + ((c.a * cover + cover_mask) >> cover_shift); + r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; + g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; + b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; + a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + + //-------------------------------------------------------------------- + template<class GammaLUT> + AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) + { + r = gamma.dir(r); + g = gamma.dir(g); + b = gamma.dir(b); + } + + //-------------------------------------------------------------------- + template<class GammaLUT> + AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) + { + r = gamma.inv(r); + g = gamma.inv(g); + b = gamma.inv(b); + } + + //-------------------------------------------------------------------- static self_type no_color() { return self_type(0,0,0,0); } //-------------------------------------------------------------------- @@ -611,6 +720,22 @@ namespace agg return rgba16(c,a).premultiply(); } + + //------------------------------------------------------rgba16_gamma_dir + template<class GammaLUT> + rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma) + { + return rgba16(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); + } + + //------------------------------------------------------rgba16_gamma_inv + template<class GammaLUT> + rgba16 rgba16_gamma_inv(rgba16 c, const GammaLUT& gamma) + { + return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); + } + + } diff --git a/agg/inc/agg_config.h b/agg/inc/agg_config.h index b412a6dff178..9a17716c52fb 100755 --- a/agg/inc/agg_config.h +++ b/agg/inc/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,9 +26,23 @@ // but it won't result any crash and the rest of the library will remain // fully functional. +//--------------------------------------- +// 2. Default rendering_buffer type. Can be: +// +// Provides faster access for massive pixel operations, +// such as blur, image filtering: +// #define AGG_RENDERING_BUFFER row_ptr_cache<int8u> +// +// Provides cheaper creation and destruction (no mem allocs): +// #define AGG_RENDERING_BUFFER row_accessor<int8u> +// +// You can still use both of them simultaneouslyin your applications +// This #define is used only for default rendering_buffer type, +// in short hand typedefs like pixfmt_rgba32. + // #i65318# Passing agg version on to clients #ifndef AGG_VERSION -# define AGG_VERSION 2300 +# define AGG_VERSION 2400 #endif #endif diff --git a/agg/inc/agg_conv_adaptor_vcgen.h b/agg/inc/agg_conv_adaptor_vcgen.h index f8233a388357..86bc3222de08 100755 --- a/agg/inc/agg_conv_adaptor_vcgen.h +++ b/agg/inc/agg_conv_adaptor_vcgen.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -17,7 +17,6 @@ #define AGG_CONV_ADAPTOR_VCGEN_INCLUDED #include "agg_basics.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -30,11 +29,6 @@ namespace agg void rewind(unsigned) {} unsigned vertex(double*, double*) { return path_cmd_stop; } - - typedef null_markers source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } }; @@ -51,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; } @@ -64,19 +57,14 @@ namespace agg Markers& markers() { return m_markers; } const Markers& markers() const { return m_markers; } - void rewind(unsigned id) + void rewind(unsigned path_id) { - m_source->rewind(id); + m_source->rewind(path_id); m_status = initial; } unsigned vertex(double* x, double* y); - typedef conv_adaptor_vcgen<VertexSource, Generator, Markers> source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: // Prohibit copying conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&); diff --git a/agg/inc/agg_conv_adaptor_vpgen.h b/agg/inc/agg_conv_adaptor_vpgen.h index f6afdb4d7f12..e18c080f38e6 100755 --- a/agg/inc/agg_conv_adaptor_vpgen.h +++ b/agg/inc/agg_conv_adaptor_vpgen.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -17,7 +17,6 @@ #define AGG_CONV_ADAPTOR_VPGEN_INCLUDED #include "agg_basics.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -26,9 +25,8 @@ namespace agg template<class VertexSource, class VPGen> class conv_adaptor_vpgen { public: - conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {} - - void set_source(VertexSource& source) { m_source = &source; } + explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {} + void attach(VertexSource& source) { m_source = &source; } VPGen& vpgen() { return m_vpgen; } const VPGen& vpgen() const { return m_vpgen; } @@ -36,11 +34,6 @@ namespace agg void rewind(unsigned path_id); unsigned vertex(double* x, double* y); - typedef conv_adaptor_vpgen<VertexSource, VPGen> source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&); const conv_adaptor_vpgen<VertexSource, VPGen>& diff --git a/agg/inc/agg_conv_bspline.h b/agg/inc/agg_conv_bspline.h index 9c504daff209..9a70b4abea5d 100755 --- a/agg/inc/agg_conv_bspline.h +++ b/agg/inc/agg_conv_bspline.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_conv_clip_polygon.h b/agg/inc/agg_conv_clip_polygon.h index cbecc51fbdd5..05106cf51f76 100755 --- a/agg/inc/agg_conv_clip_polygon.h +++ b/agg/inc/agg_conv_clip_polygon.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -29,7 +29,6 @@ #include "agg_basics.h" #include "agg_conv_adaptor_vpgen.h" #include "agg_vpgen_clip_polygon.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -53,11 +52,6 @@ namespace agg double x2() const { return base_type::vpgen().x2(); } double y2() const { return base_type::vpgen().y2(); } - typedef conv_clip_polygon<VertexSource> source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_clip_polygon(const conv_clip_polygon<VertexSource>&); const conv_clip_polygon<VertexSource>& diff --git a/agg/inc/agg_conv_clip_polyline.h b/agg/inc/agg_conv_clip_polyline.h index 4ac66276891c..3684d23ac27e 100755 --- a/agg/inc/agg_conv_clip_polyline.h +++ b/agg/inc/agg_conv_clip_polyline.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -29,7 +29,6 @@ #include "agg_basics.h" #include "agg_conv_adaptor_vpgen.h" #include "agg_vpgen_clip_polyline.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -53,11 +52,6 @@ namespace agg double x2() const { return base_type::vpgen().x2(); } double y2() const { return base_type::vpgen().y2(); } - typedef conv_clip_polyline<VertexSource> source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_clip_polyline(const conv_clip_polyline<VertexSource>&); const conv_clip_polyline<VertexSource>& diff --git a/agg/inc/agg_conv_close_polygon.h b/agg/inc/agg_conv_close_polygon.h index 60a756a7408a..7b783ccc877b 100755 --- a/agg/inc/agg_conv_close_polygon.h +++ b/agg/inc/agg_conv_close_polygon.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -17,7 +17,6 @@ #define AGG_CONV_CLOSE_POLYGON_INCLUDED #include "agg_basics.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -26,18 +25,12 @@ namespace agg template<class VertexSource> class conv_close_polygon { public: - conv_close_polygon(VertexSource& vs) : m_source(&vs) {} - - void set_source(VertexSource& source) { m_source = &source; } + explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {} + void attach(VertexSource& source) { m_source = &source; } void rewind(unsigned path_id); unsigned vertex(double* x, double* y); - typedef conv_close_polygon<VertexSource> source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_close_polygon(const conv_close_polygon<VertexSource>&); const conv_close_polygon<VertexSource>& diff --git a/agg/inc/agg_conv_concat.h b/agg/inc/agg_conv_concat.h index 2b9886a1be46..dffaf656c23a 100755 --- a/agg/inc/agg_conv_concat.h +++ b/agg/inc/agg_conv_concat.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -17,7 +17,6 @@ #define AGG_CONV_CONCAT_INCLUDED #include "agg_basics.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -29,14 +28,13 @@ namespace agg public: conv_concat(VS1& source1, VS2& source2) : m_source1(&source1), m_source2(&source2), m_status(2) {} + void attach1(VS1& source) { m_source1 = &source; } + void attach2(VS2& source) { m_source2 = &source; } - void set_source1(VS1& source) { m_source1 = &source; } - void set_source2(VS2& source) { m_source2 = &source; } - - void rewind(unsigned id) + void rewind(unsigned path_id) { - m_source1->rewind(id); + m_source1->rewind(path_id); m_source2->rewind(0); m_status = 0; } @@ -59,11 +57,6 @@ namespace agg return path_cmd_stop; } - typedef conv_concat<VS1, VS2> source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_concat(const conv_concat<VS1, VS2>&); const conv_concat<VS1, VS2>& diff --git a/agg/inc/agg_conv_contour.h b/agg/inc/agg_conv_contour.h index 652a8e1fa4f3..ec3c1bbeb804 100755 --- a/agg/inc/agg_conv_contour.h +++ b/agg/inc/agg_conv_contour.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -38,7 +38,7 @@ namespace agg } void line_join(line_join_e lj) { base_type::generator().line_join(lj); } - void inner_line_join(line_join_e lj) { base_type::generator().inner_line_join(lj); } + void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); } void width(double w) { base_type::generator().width(w); } void miter_limit(double ml) { base_type::generator().miter_limit(ml); } void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); } @@ -47,7 +47,7 @@ namespace agg void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); } line_join_e line_join() const { return base_type::generator().line_join(); } - line_join_e inner_line_join() const { return base_type::generator().inner_line_join(); } + inner_join_e inner_join() const { return base_type::generator().inner_join(); } double width() const { return base_type::generator().width(); } double miter_limit() const { return base_type::generator().miter_limit(); } double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); } diff --git a/agg/inc/agg_conv_curve.h b/agg/inc/agg_conv_curve.h index 3b8e6cff2e2e..d90401054ed8 100755 --- a/agg/inc/agg_conv_curve.h +++ b/agg/inc/agg_conv_curve.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -33,14 +33,14 @@ namespace agg // and curve4. Curve3 is a conic Bezier curve with 2 endpoints and 1 control // point. Curve4 has 2 control points (4 points in total) and can be used // to interpolate more complicated curves. Curve4, unlike curve3 can be used - // to approximate arcs, both curcular and elliptical. Curves are approximated + // to approximate arcs, both circular and elliptical. Curves are approximated // with straight lines and one of the approaches is just to store the whole // sequence of vertices that approximate our curve. It takes additional // memory, and at the same time the consecutive vertices can be calculated // on demand. // // Initially, path storages are not suppose to keep all the vertices of the - // curves (although, nothig prevents us from doing so). Instead, path_storage + // curves (although, nothing prevents us from doing so). Instead, path_storage // keeps only vertices, needed to calculate a curve on demand. Those vertices // are marked with special commands. So, if the path_storage contains curves // (which are not real curves yet), and we render this storage directly, @@ -51,13 +51,29 @@ namespace agg // Class conv_curve recognizes commands path_cmd_curve3 and path_cmd_curve4 // and converts these vertices into a move_to/line_to sequence. //----------------------------------------------------------------------- - template<class VertexSource> class conv_curve + template<class VertexSource, + class Curve3=curve3, + class Curve4=curve4> class conv_curve { public: - conv_curve(VertexSource& source) : + typedef Curve3 curve3_type; + typedef Curve4 curve4_type; + typedef conv_curve<VertexSource, Curve3, Curve4> self_type; + + explicit conv_curve(VertexSource& source) : m_source(&source), m_last_x(0.0), m_last_y(0.0) {} + void attach(VertexSource& source) { m_source = &source; } + + void approximation_method(curve_approximation_method_e v) + { + m_curve3.approximation_method(v); + m_curve4.approximation_method(v); + } - void set_source(VertexSource& source) { m_source = &source; } + curve_approximation_method_e approximation_method() const + { + return m_curve4.approximation_method(); + } void approximation_scale(double s) { @@ -67,36 +83,52 @@ namespace agg double approximation_scale() const { - return m_curve3.approximation_scale(); + return m_curve4.approximation_scale(); } - void rewind(unsigned id); - unsigned vertex(double* x, double* y); + void angle_tolerance(double v) + { + m_curve3.angle_tolerance(v); + m_curve4.angle_tolerance(v); + } - typedef conv_curve<VertexSource> source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } + double angle_tolerance() const + { + return m_curve4.angle_tolerance(); + } + + void cusp_limit(double v) + { + m_curve3.cusp_limit(v); + m_curve4.cusp_limit(v); + } + + double cusp_limit() const + { + return m_curve4.cusp_limit(); + } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); private: - conv_curve(const conv_curve<VertexSource>&); - const conv_curve<VertexSource>& - operator = (const conv_curve<VertexSource>&); + conv_curve(const self_type&); + const self_type& operator = (const self_type&); VertexSource* m_source; double m_last_x; double m_last_y; - curve3 m_curve3; - curve4 m_curve4; + curve3_type m_curve3; + curve4_type m_curve4; }; //------------------------------------------------------------------------ - template<class VertexSource> - void conv_curve<VertexSource>::rewind(unsigned id) + template<class VertexSource, class Curve3, class Curve4> + void conv_curve<VertexSource, Curve3, Curve4>::rewind(unsigned path_id) { - m_source->rewind(id); + m_source->rewind(path_id); m_last_x = 0.0; m_last_y = 0.0; m_curve3.reset(); @@ -105,8 +137,8 @@ namespace agg //------------------------------------------------------------------------ - template<class VertexSource> - unsigned conv_curve<VertexSource>::vertex(double* x, double* y) + template<class VertexSource, class Curve3, class Curve4> + unsigned conv_curve<VertexSource, Curve3, Curve4>::vertex(double* x, double* y) { if(!is_stop(m_curve3.vertex(x, y))) { @@ -122,21 +154,14 @@ namespace agg return path_cmd_line_to; } - double ct2_x = 0; - double ct2_y = 0; - double end_x = 0; - double end_y = 0; + double ct2_x; + double ct2_y; + double end_x; + double end_y; unsigned cmd = m_source->vertex(x, y); switch(cmd) { - case path_cmd_move_to: - case path_cmd_line_to: - m_last_x = *x; - m_last_y = *y; - default: - break; - case path_cmd_curve3: m_source->vertex(&end_x, &end_y); @@ -163,6 +188,8 @@ namespace agg cmd = path_cmd_line_to; break; } + m_last_x = *x; + m_last_y = *y; return cmd; } diff --git a/agg/inc/agg_conv_dash.h b/agg/inc/agg_conv_dash.h index 0520276bbb96..2c00d4e7f4e5 100755 --- a/agg/inc/agg_conv_dash.h +++ b/agg/inc/agg_conv_dash.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_conv_gpc.h b/agg/inc/agg_conv_gpc.h index 1810309d208a..14232eb619a3 100755 --- a/agg/inc/agg_conv_gpc.h +++ b/agg/inc/agg_conv_gpc.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -27,7 +27,6 @@ #include <math.h> #include "agg_basics.h" #include "agg_array.h" -#include "agg_vertex_iterator.h" extern "C" { @@ -63,8 +62,8 @@ namespace agg gpc_vertex* vertices; }; - typedef pod_deque<gpc_vertex, 8> vertex_array_type; - typedef pod_deque<contour_header_type, 6> contour_header_array_type; + typedef pod_bvector<gpc_vertex, 8> vertex_array_type; + typedef pod_bvector<contour_header_type, 6> contour_header_array_type; public: @@ -90,20 +89,15 @@ 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; } // Vertex Source Interface - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); - // Iterator - typedef vertex_iterator<self_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_gpc(const conv_gpc<VSA, VSB>&); const conv_gpc<VSA, VSB>& operator = (const conv_gpc<VSA, VSB>&); @@ -197,10 +191,10 @@ namespace agg int i; for(i = 0; i < p.num_contours; i++) { - delete [] p.contour[i].vertex; + pod_allocator<gpc_vertex>::deallocate(p.contour[i].vertex, + p.contour[i].num_vertices); } - delete [] p.hole; - delete [] p.contour; + pod_allocator<gpc_vertex_list>::deallocate(p.contour, p.num_contours); memset(&p, 0, sizeof(gpc_polygon)); } @@ -266,7 +260,7 @@ namespace agg // TO DO: Clarify the "holes" //if(is_cw(orientation)) h.hole_flag = 1; - h.vertices = new gpc_vertex [h.num_vertices]; + h.vertices = pod_allocator<gpc_vertex>::allocate(h.num_vertices); gpc_vertex* d = h.vertices; int i; for(i = 0; i < h.num_vertices; i++) @@ -294,19 +288,14 @@ namespace agg { p.num_contours = m_contour_accumulator.size(); - // TO DO: Clarify the "holes" - //p.hole = new int[p.num_contours]; p.hole = 0; - - p.contour = new gpc_vertex_list[p.num_contours]; + p.contour = pod_allocator<gpc_vertex_list>::allocate(p.num_contours); int i; - //int* ph = p.hole; gpc_vertex_list* pv = p.contour; for(i = 0; i < p.num_contours; i++) { const contour_header_type& h = m_contour_accumulator[i]; - // *ph++ = h.hole_flag; pv->num_vertices = h.num_vertices; pv->vertex = h.vertices; ++pv; @@ -356,11 +345,11 @@ namespace agg //------------------------------------------------------------------------ template<class VSA, class VSB> - void conv_gpc<VSA, VSB>::rewind(unsigned id) + void conv_gpc<VSA, VSB>::rewind(unsigned path_id) { free_result(); - m_src_a->rewind(id); - m_src_b->rewind(id); + m_src_a->rewind(path_id); + m_src_b->rewind(path_id); add(*m_src_a, m_poly_a); add(*m_src_b, m_poly_b); switch(m_operation) diff --git a/agg/inc/agg_conv_marker.h b/agg/inc/agg_conv_marker.h index 1ae7fc92307b..f311cb957cea 100755 --- a/agg/inc/agg_conv_marker.h +++ b/agg/inc/agg_conv_marker.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -21,7 +21,6 @@ #include "agg_basics.h" #include "agg_trans_affine.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -35,14 +34,9 @@ namespace agg trans_affine& transform() { return m_transform; } const trans_affine& transform() const { return m_transform; } - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); - typedef conv_marker<MarkerLocator, MarkerShapes> source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_marker(const conv_marker<MarkerLocator, MarkerShapes>&); const conv_marker<MarkerLocator, MarkerShapes>& diff --git a/agg/inc/agg_conv_marker_adaptor.h b/agg/inc/agg_conv_marker_adaptor.h index 282d26eb5afc..2e792aec3af9 100755 --- a/agg/inc/agg_conv_marker_adaptor.h +++ b/agg/inc/agg_conv_marker_adaptor.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_conv_segmentator.h b/agg/inc/agg_conv_segmentator.h index df81fea9b276..5a43fb1b8e2d 100755 --- a/agg/inc/agg_conv_segmentator.h +++ b/agg/inc/agg_conv_segmentator.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_conv_shorten_path.h b/agg/inc/agg_conv_shorten_path.h index 07bc9357d6ca..26f498a305bf 100755 --- a/agg/inc/agg_conv_shorten_path.h +++ b/agg/inc/agg_conv_shorten_path.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_conv_smooth_poly1.h b/agg/inc/agg_conv_smooth_poly1.h index f50a48747f9a..c09a02da7ada 100755 --- a/agg/inc/agg_conv_smooth_poly1.h +++ b/agg/inc/agg_conv_smooth_poly1.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_conv_stroke.h b/agg/inc/agg_conv_stroke.h index cbdce446b7be..a91ffadb2002 100755 --- a/agg/inc/agg_conv_stroke.h +++ b/agg/inc/agg_conv_stroke.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -39,13 +39,13 @@ namespace agg { } - void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); } - void line_join(line_join_e lj) { base_type::generator().line_join(lj); } - void inner_line_join(line_join_e lj) { base_type::generator().inner_line_join(lj); } + void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); } + void line_join(line_join_e lj) { base_type::generator().line_join(lj); } + void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); } - line_cap_e line_cap() const { return base_type::generator().line_cap(); } - line_join_e line_join() const { return base_type::generator().line_join(); } - line_join_e inner_line_join() const { return base_type::generator().inner_line_join(); } + line_cap_e line_cap() const { return base_type::generator().line_cap(); } + line_join_e line_join() const { return base_type::generator().line_join(); } + inner_join_e inner_join() const { return base_type::generator().inner_join(); } void width(double w) { base_type::generator().width(w); } void miter_limit(double ml) { base_type::generator().miter_limit(ml); } diff --git a/agg/inc/agg_conv_transform.h b/agg/inc/agg_conv_transform.h index fb2dddcef617..1e9306fb0c14 100755 --- a/agg/inc/agg_conv_transform.h +++ b/agg/inc/agg_conv_transform.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -21,7 +21,6 @@ #include "agg_basics.h" #include "agg_trans_affine.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -32,12 +31,11 @@ namespace agg public: conv_transform(VertexSource& source, const Transformer& tr) : m_source(&source), m_trans(&tr) {} + void attach(VertexSource& source) { m_source = &source; } - void set_source(VertexSource& source) { m_source = &source; } - - void rewind(unsigned id) + void rewind(unsigned path_id) { - m_source->rewind(id); + m_source->rewind(path_id); } unsigned vertex(double* x, double* y) @@ -55,11 +53,6 @@ namespace agg m_trans = &tr; } - typedef conv_transform<VertexSource, Transformer> source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_transform(const conv_transform<VertexSource>&); const conv_transform<VertexSource>& diff --git a/agg/inc/agg_conv_unclose_polygon.h b/agg/inc/agg_conv_unclose_polygon.h index a6ba30a1119e..95fc1d5e5784 100755 --- a/agg/inc/agg_conv_unclose_polygon.h +++ b/agg/inc/agg_conv_unclose_polygon.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -17,7 +17,6 @@ #define AGG_CONV_UNCLOSE_POLYGON_INCLUDED #include "agg_basics.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -25,9 +24,8 @@ namespace agg template<class VertexSource> class conv_unclose_polygon { public: - conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {} - - void set_source(VertexSource& source) { m_source = &source; } + explicit conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {} + void attach(VertexSource& source) { m_source = &source; } void rewind(unsigned path_id) { @@ -41,11 +39,6 @@ namespace agg return cmd; } - typedef conv_unclose_polygon<VertexSource> source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&); const conv_unclose_polygon<VertexSource>& diff --git a/agg/inc/agg_curves.h b/agg/inc/agg_curves.h index bfb02e91ab96..8e8fe37dc065 100755 --- a/agg/inc/agg_curves.h +++ b/agg/inc/agg_curves.h @@ -1,6 +1,7 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// Copyright (C) 2005 Tony Juricic (tonygeek@yahoo.com) // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. @@ -12,34 +13,35 @@ // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- -// -// classes curve3 and curve4 -// -//---------------------------------------------------------------------------- #ifndef AGG_CURVES_INCLUDED #define AGG_CURVES_INCLUDED -#include "agg_basics.h" -#include "agg_vertex_iterator.h" +#include "agg_array.h" namespace agg { - // See Implemantation agg_curves.cpp + // See Implementation agg_curves.cpp + //--------------------------------------------curve_approximation_method_e + enum curve_approximation_method_e + { + curve_inc, + curve_div + }; - //------------------------------------------------------------------curve3 - class curve3 + //--------------------------------------------------------------curve3_inc + class curve3_inc { public: - curve3() : + curve3_inc() : m_num_steps(0), m_step(0), m_scale(1.0) { } - curve3(double x1, double y1, - double x2, double y2, - double x3, double y3) : - m_num_steps(0), m_step(0), m_scale(1.0) + curve3_inc(double x1, double y1, + double x2, double y2, + double x3, double y3) : + m_num_steps(0), m_step(0), m_scale(1.0) { init(x1, y1, x2, y2, x3, y3); } @@ -48,16 +50,21 @@ namespace agg void init(double x1, double y1, double x2, double y2, double x3, double y3); - void approximation_scale(double s) { m_scale = s; } - double approximation_scale() const { return m_scale; } - void rewind(unsigned id); - unsigned vertex(double* x, double* y); + void approximation_method(curve_approximation_method_e) {} + curve_approximation_method_e approximation_method() const { return curve_inc; } + + void approximation_scale(double s); + double approximation_scale() const; + + void angle_tolerance(double) {} + double angle_tolerance() const { return 0.0; } - typedef curve3 source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } + void cusp_limit(double) {} + double cusp_limit() const { return 0.0; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); private: int m_num_steps; @@ -83,40 +90,153 @@ namespace agg + //-------------------------------------------------------------curve3_div + class curve3_div + { + public: + curve3_div() : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_count(0) + {} + + curve3_div(double x1, double y1, + double x2, double y2, + double x3, double y3) : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_count(0) + { + init(x1, y1, x2, y2, x3, y3); + } + + void reset() { m_points.remove_all(); m_count = 0; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3); + + void approximation_method(curve_approximation_method_e) {} + curve_approximation_method_e approximation_method() const { return curve_div; } + + void approximation_scale(double s) { m_approximation_scale = s; } + double approximation_scale() const { return m_approximation_scale; } + void angle_tolerance(double a) { m_angle_tolerance = a; } + double angle_tolerance() const { return m_angle_tolerance; } - //-----------------------------------------------------------------curve4 - class curve4 + void cusp_limit(double) {} + double cusp_limit() const { return 0.0; } + + void rewind(unsigned) + { + m_count = 0; + } + + unsigned vertex(double* x, double* y) + { + if(m_count >= m_points.size()) return path_cmd_stop; + const point_d& p = m_points[m_count++]; + *x = p.x; + *y = p.y; + return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to; + } + + private: + void bezier(double x1, double y1, + double x2, double y2, + double x3, double y3); + void recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + unsigned level); + + double m_approximation_scale; + double m_distance_tolerance_square; + double m_angle_tolerance; + unsigned m_count; + pod_bvector<point_d> m_points; + }; + + + + + + + + //-------------------------------------------------------------curve4_points + struct curve4_points + { + double cp[8]; + curve4_points() {} + curve4_points(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2; + cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4; + } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2; + cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4; + } + double operator [] (unsigned i) const { return cp[i]; } + double& operator [] (unsigned i) { return cp[i]; } + }; + + + + //-------------------------------------------------------------curve4_inc + class curve4_inc { public: - curve4() : - m_num_steps(0), m_step(0), m_scale(1.0) { } + curve4_inc() : + m_num_steps(0), m_step(0), m_scale(1.0) { } - curve4(double x1, double y1, - double x2, double y2, - double x3, double y3, - double x4, double y4) : - m_num_steps(0), m_step(0), m_scale(1.0) + curve4_inc(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) : + m_num_steps(0), m_step(0), m_scale(1.0) { init(x1, y1, x2, y2, x3, y3, x4, y4); } + curve4_inc(const curve4_points& cp) : + m_num_steps(0), m_step(0), m_scale(1.0) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + void reset() { m_num_steps = 0; m_step = -1; } void init(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4); - void approximation_scale(double s) { m_scale = s; } - double approximation_scale() const { return m_scale; } + void init(const curve4_points& cp) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void approximation_method(curve_approximation_method_e) {} + curve_approximation_method_e approximation_method() const { return curve_inc; } - void rewind(unsigned id); - unsigned vertex(double* x, double* y); + void approximation_scale(double s); + double approximation_scale() const; + + void angle_tolerance(double) {} + double angle_tolerance() const { return 0.0; } + + void cusp_limit(double) {} + double cusp_limit() const { return 0.0; } - typedef curve4 source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); private: int m_num_steps; @@ -144,6 +264,429 @@ namespace agg + //-------------------------------------------------------catrom_to_bezier + inline curve4_points catrom_to_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + // Trans. matrix Catmull-Rom to Bezier + // + // 0 1 0 0 + // -1/6 1 1/6 0 + // 0 1/6 1 -1/6 + // 0 0 1 0 + // + return curve4_points( + x2, + y2, + (-x1 + 6*x2 + x3) / 6, + (-y1 + 6*y2 + y3) / 6, + ( x2 + 6*x3 - x4) / 6, + ( y2 + 6*y3 - y4) / 6, + x3, + y3); + } + + + //----------------------------------------------------------------------- + inline curve4_points + catrom_to_bezier(const curve4_points& cp) + { + return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3], + cp[4], cp[5], cp[6], cp[7]); + } + + + + //-----------------------------------------------------ubspline_to_bezier + inline curve4_points ubspline_to_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + // Trans. matrix Uniform BSpline to Bezier + // + // 1/6 4/6 1/6 0 + // 0 4/6 2/6 0 + // 0 2/6 4/6 0 + // 0 1/6 4/6 1/6 + // + return curve4_points( + (x1 + 4*x2 + x3) / 6, + (y1 + 4*y2 + y3) / 6, + (4*x2 + 2*x3) / 6, + (4*y2 + 2*y3) / 6, + (2*x2 + 4*x3) / 6, + (2*y2 + 4*y3) / 6, + (x2 + 4*x3 + x4) / 6, + (y2 + 4*y3 + y4) / 6); + } + + + //----------------------------------------------------------------------- + inline curve4_points + ubspline_to_bezier(const curve4_points& cp) + { + return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3], + cp[4], cp[5], cp[6], cp[7]); + } + + + + + //------------------------------------------------------hermite_to_bezier + inline curve4_points hermite_to_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + // Trans. matrix Hermite to Bezier + // + // 1 0 0 0 + // 1 0 1/3 0 + // 0 1 0 -1/3 + // 0 1 0 0 + // + return curve4_points( + x1, + y1, + (3*x1 + x3) / 3, + (3*y1 + y3) / 3, + (3*x2 - x4) / 3, + (3*y2 - y4) / 3, + x2, + y2); + } + + + + //----------------------------------------------------------------------- + inline curve4_points + hermite_to_bezier(const curve4_points& cp) + { + return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3], + cp[4], cp[5], cp[6], cp[7]); + } + + + //-------------------------------------------------------------curve4_div + class curve4_div + { + public: + curve4_div() : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_cusp_limit(0.0), + m_count(0) + {} + + curve4_div(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_cusp_limit(0.0), + m_count(0) + { + init(x1, y1, x2, y2, x3, y3, x4, y4); + } + + curve4_div(const curve4_points& cp) : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_count(0) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void reset() { m_points.remove_all(); m_count = 0; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + + void init(const curve4_points& cp) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void approximation_method(curve_approximation_method_e) {} + + curve_approximation_method_e approximation_method() const + { + return curve_div; + } + + void approximation_scale(double s) { m_approximation_scale = s; } + double approximation_scale() const { return m_approximation_scale; } + + void angle_tolerance(double a) { m_angle_tolerance = a; } + double angle_tolerance() const { return m_angle_tolerance; } + + void cusp_limit(double v) + { + m_cusp_limit = (v == 0.0) ? 0.0 : pi - v; + } + + double cusp_limit() const + { + return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit; + } + + void rewind(unsigned) + { + m_count = 0; + } + + unsigned vertex(double* x, double* y) + { + if(m_count >= m_points.size()) return path_cmd_stop; + const point_d& p = m_points[m_count++]; + *x = p.x; + *y = p.y; + return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to; + } + + private: + void bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + + void recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4, + unsigned level); + + double m_approximation_scale; + double m_distance_tolerance_square; + double m_angle_tolerance; + double m_cusp_limit; + unsigned m_count; + pod_bvector<point_d> m_points; + }; + + + //-----------------------------------------------------------------curve3 + class curve3 + { + public: + curve3() : m_approximation_method(curve_div) {} + curve3(double x1, double y1, + double x2, double y2, + double x3, double y3) : + m_approximation_method(curve_div) + { + init(x1, y1, x2, y2, x3, y3); + } + + void reset() + { + m_curve_inc.reset(); + m_curve_div.reset(); + } + + void init(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.init(x1, y1, x2, y2, x3, y3); + } + else + { + m_curve_div.init(x1, y1, x2, y2, x3, y3); + } + } + + void approximation_method(curve_approximation_method_e v) + { + m_approximation_method = v; + } + + curve_approximation_method_e approximation_method() const + { + return m_approximation_method; + } + + void approximation_scale(double s) + { + m_curve_inc.approximation_scale(s); + m_curve_div.approximation_scale(s); + } + + double approximation_scale() const + { + return m_curve_inc.approximation_scale(); + } + + void angle_tolerance(double a) + { + m_curve_div.angle_tolerance(a); + } + + double angle_tolerance() const + { + return m_curve_div.angle_tolerance(); + } + + void cusp_limit(double v) + { + m_curve_div.cusp_limit(v); + } + + double cusp_limit() const + { + return m_curve_div.cusp_limit(); + } + + void rewind(unsigned path_id) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.rewind(path_id); + } + else + { + m_curve_div.rewind(path_id); + } + } + + unsigned vertex(double* x, double* y) + { + if(m_approximation_method == curve_inc) + { + return m_curve_inc.vertex(x, y); + } + return m_curve_div.vertex(x, y); + } + + private: + curve3_inc m_curve_inc; + curve3_div m_curve_div; + curve_approximation_method_e m_approximation_method; + }; + + + + + + //-----------------------------------------------------------------curve4 + class curve4 + { + public: + curve4() : m_approximation_method(curve_div) {} + curve4(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) : + m_approximation_method(curve_div) + { + init(x1, y1, x2, y2, x3, y3, x4, y4); + } + + curve4(const curve4_points& cp) : + m_approximation_method(curve_div) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void reset() + { + m_curve_inc.reset(); + m_curve_div.reset(); + } + + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4); + } + else + { + m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4); + } + } + + void init(const curve4_points& cp) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void approximation_method(curve_approximation_method_e v) + { + m_approximation_method = v; + } + + curve_approximation_method_e approximation_method() const + { + return m_approximation_method; + } + + void approximation_scale(double s) + { + m_curve_inc.approximation_scale(s); + m_curve_div.approximation_scale(s); + } + double approximation_scale() const { return m_curve_inc.approximation_scale(); } + + void angle_tolerance(double v) + { + m_curve_div.angle_tolerance(v); + } + + double angle_tolerance() const + { + return m_curve_div.angle_tolerance(); + } + + void cusp_limit(double v) + { + m_curve_div.cusp_limit(v); + } + + double cusp_limit() const + { + return m_curve_div.cusp_limit(); + } + + void rewind(unsigned path_id) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.rewind(path_id); + } + else + { + m_curve_div.rewind(path_id); + } + } + + unsigned vertex(double* x, double* y) + { + if(m_approximation_method == curve_inc) + { + return m_curve_inc.vertex(x, y); + } + return m_curve_div.vertex(x, y); + } + + private: + curve4_inc m_curve_inc; + curve4_div m_curve_div; + curve_approximation_method_e m_approximation_method; + }; + + + } diff --git a/agg/inc/agg_dda_line.h b/agg/inc/agg_dda_line.h index 6e7335c6dfec..7d4c22d4b18e 100755 --- a/agg/inc/agg_dda_line.h +++ b/agg/inc/agg_dda_line.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -86,7 +86,7 @@ namespace agg { public: typedef int save_data_type; - enum { save_size = 2 }; + enum save_size_e { save_size = 2 }; //-------------------------------------------------------------------- dda2_line_interpolator() {} @@ -125,10 +125,10 @@ namespace agg } //-------------------------------------------- Backward-adjusted line - dda2_line_interpolator(int _y, int count) : + dda2_line_interpolator(int y, int count) : m_cnt(count <= 0 ? 1 : count), - m_lft(_y / m_cnt), - m_rem(_y % m_cnt), + m_lft(y / m_cnt), + m_rem(y % m_cnt), m_mod(m_rem), m_y(0) { @@ -217,28 +217,28 @@ namespace agg class line_bresenham_interpolator { public: - enum + enum subpixel_scale_e { subpixel_shift = 8, - subpixel_size = 1 << subpixel_shift, - subpixel_mask = subpixel_size - 1 + subpixel_scale = 1 << subpixel_shift, + subpixel_mask = subpixel_scale - 1 }; //-------------------------------------------------------------------- static int line_lr(int v) { return v >> subpixel_shift; } //-------------------------------------------------------------------- - line_bresenham_interpolator(int _x1, int _y1, int _x2, int _y2) : - m_x1_lr(line_lr(_x1)), - m_y1_lr(line_lr(_y1)), - m_x2_lr(line_lr(_x2)), - m_y2_lr(line_lr(_y2)), + line_bresenham_interpolator(int x1, int y1, int x2, int y2) : + m_x1_lr(line_lr(x1)), + m_y1_lr(line_lr(y1)), + m_x2_lr(line_lr(x2)), + m_y2_lr(line_lr(y2)), m_ver(abs(m_x2_lr - m_x1_lr) < abs(m_y2_lr - m_y1_lr)), m_len(m_ver ? abs(m_y2_lr - m_y1_lr) : abs(m_x2_lr - m_x1_lr)), - m_inc(m_ver ? ((_y2 > _y1) ? 1 : -1) : ((_x2 > _x1) ? 1 : -1)), - m_interpolator(m_ver ? _x1 : _y1, - m_ver ? _x2 : _y2, + m_inc(m_ver ? ((y2 > y1) ? 1 : -1) : ((x2 > x1) ? 1 : -1)), + m_interpolator(m_ver ? x1 : y1, + m_ver ? x2 : y2, m_len) { } diff --git a/agg/inc/agg_ellipse.h b/agg/inc/agg_ellipse.h index 158ecf8b55ed..f4ebc7d63f54 100755 --- a/agg/inc/agg_ellipse.h +++ b/agg/inc/agg_ellipse.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -30,27 +30,41 @@ namespace agg class ellipse { public: - ellipse() : m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_num(4), m_step(0) {} - ellipse(double x, double y, double rx, double ry, unsigned num_steps) - : m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_num(num_steps), m_step(0) {} + ellipse() : + m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_scale(1.0), + m_num(4), m_step(0), m_cw(false) {} + + ellipse(double x, double y, double rx, double ry, + unsigned num_steps=0, bool cw=false) : + m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0), + m_num(num_steps), m_step(0), m_cw(cw) + { + if(m_num == 0) calc_num_steps(); + } + + void init(double x, double y, double rx, double ry, + unsigned num_steps=0, bool cw=false); - void init(double x, double y, double rx, double ry, unsigned num_steps); void approximation_scale(double scale); - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: + void calc_num_steps(); + double m_x; double m_y; double m_rx; double m_ry; + double m_scale; unsigned m_num; unsigned m_step; + bool m_cw; }; - //------------------------------------------------------------------------ - inline void ellipse::init(double x, double y, double rx, double ry, unsigned num_steps) + inline void ellipse::init(double x, double y, double rx, double ry, + unsigned num_steps, bool cw) { m_x = x; m_y = y; @@ -58,13 +72,23 @@ namespace agg m_ry = ry; m_num = num_steps; m_step = 0; + m_cw = cw; + if(m_num == 0) calc_num_steps(); } //------------------------------------------------------------------------ inline void ellipse::approximation_scale(double scale) { - m_num = unsigned((fabs(m_rx) + fabs(m_ry) + 6.0) * scale); - if(m_num < 6) m_num = 6; + m_scale = scale; + calc_num_steps(); + } + + //------------------------------------------------------------------------ + inline void ellipse::calc_num_steps() + { + double ra = (fabs(m_rx) + fabs(m_ry)) / 2; + double da = acos(ra / (ra + 0.125 / m_scale)) * 2; + m_num = uround(2*pi / da); } //------------------------------------------------------------------------ @@ -83,6 +107,7 @@ namespace agg } if(m_step > m_num) return path_cmd_stop; double angle = double(m_step) / double(m_num) * 2.0 * pi; + if(m_cw) angle = 2.0 * pi - angle; *x = m_x + cos(angle) * m_rx; *y = m_y + sin(angle) * m_ry; m_step++; diff --git a/agg/inc/agg_ellipse_bresenham.h b/agg/inc/agg_ellipse_bresenham.h index 41133a473d9e..a83dde12286a 100755 --- a/agg/inc/agg_ellipse_bresenham.h +++ b/agg/inc/agg_ellipse_bresenham.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_embedded_raster_fonts.h b/agg/inc/agg_embedded_raster_fonts.h index f30fedfebe39..3092054b2670 100755 --- a/agg/inc/agg_embedded_raster_fonts.h +++ b/agg/inc/agg_embedded_raster_fonts.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_font_cache_manager.h b/agg/inc/agg_font_cache_manager.h index 55c4d39db75d..813a1a194599 100755 --- a/agg/inc/agg_font_cache_manager.h +++ b/agg/inc/agg_font_cache_manager.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -39,7 +39,7 @@ namespace agg int8u* data; unsigned data_size; glyph_data_type data_type; - rect bounds; + rect_i bounds; double advance_x; double advance_y; }; @@ -49,12 +49,16 @@ namespace agg class font_cache { public: - enum { block_size = 16384-16 }; + enum block_size_e { block_size = 16384-16 }; //-------------------------------------------------------------------- - font_cache(const char* font_signature) : + font_cache() : m_allocator(block_size), m_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); @@ -83,7 +87,7 @@ namespace agg unsigned glyph_index, unsigned data_size, glyph_data_type data_type, - const rect& bounds, + const rect_i& bounds, double advance_x, double advance_y) { @@ -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<font_cache>::deallocate(m_fonts[i]); } - delete [] m_fonts; + pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts); } //-------------------------------------------------------------------- font_cache_pool(unsigned max_fonts=32) : - m_fonts(new font_cache* [max_fonts]), + m_fonts(pod_allocator<font_cache*>::allocate(max_fonts)), m_max_fonts(max_fonts), m_num_fonts(0), m_cur_font(0) @@ -157,8 +161,9 @@ namespace agg { if(reset_cache) { - delete m_fonts[idx]; - m_fonts[idx] = new font_cache(font_signature); + obj_allocator<font_cache>::deallocate(m_fonts[idx]); + m_fonts[idx] = obj_allocator<font_cache>::allocate(); + m_fonts[idx]->signature(font_signature); } m_cur_font = m_fonts[idx]; } @@ -166,13 +171,14 @@ namespace agg { if(m_num_fonts >= m_max_fonts) { - delete m_fonts[0]; + obj_allocator<font_cache>::deallocate(m_fonts[0]); memcpy(m_fonts, m_fonts + 1, (m_max_fonts - 1) * sizeof(font_cache*)); m_num_fonts = m_max_fonts - 1; } - m_fonts[m_num_fonts] = new font_cache(font_signature); + m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate(); + m_fonts[m_num_fonts]->signature(font_signature); m_cur_font = m_fonts[m_num_fonts]; ++m_num_fonts; } @@ -196,7 +202,7 @@ namespace agg unsigned glyph_index, unsigned data_size, glyph_data_type data_type, - const rect& bounds, + const rect_i& bounds, double advance_x, double advance_y) { @@ -270,6 +276,12 @@ namespace agg {} //-------------------------------------------------------------------- + void reset_last_glyph() + { + m_prev_glyph = m_last_glyph = 0; + } + + //-------------------------------------------------------------------- const glyph_cache* glyph(unsigned glyph_code) { synchronize(); diff --git a/agg/inc/agg_gamma_functions.h b/agg/inc/agg_gamma_functions.h index 09a8305faedb..cfebf9c3ea50 100755 --- a/agg/inc/agg_gamma_functions.h +++ b/agg/inc/agg_gamma_functions.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_gamma_lut.h b/agg/inc/agg_gamma_lut.h index 30e3b3c89d04..edbbe7440183 100755 --- a/agg/inc/agg_gamma_lut.h +++ b/agg/inc/agg_gamma_lut.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -27,14 +27,16 @@ namespace agg unsigned HiResShift=8> class gamma_lut { public: - enum + typedef gamma_lut<LoResT, HiResT, GammaShift, HiResShift> self_type; + + enum gamma_scale_e { gamma_shift = GammaShift, gamma_size = 1 << gamma_shift, gamma_mask = gamma_size - 1 }; - enum + enum hi_res_scale_e { hi_res_shift = HiResShift, hi_res_size = 1 << hi_res_shift, @@ -43,14 +45,14 @@ namespace agg ~gamma_lut() { - delete [] m_inv_gamma; - delete [] m_dir_gamma; + pod_allocator<LoResT>::deallocate(m_inv_gamma, hi_res_size); + pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size); } gamma_lut() : m_gamma(1.0), - m_dir_gamma(new HiResT[gamma_size]), - m_inv_gamma(new LoResT[hi_res_size]) + m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)), + m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size)) { unsigned i; for(i = 0; i < gamma_size; i++) @@ -66,8 +68,8 @@ namespace agg gamma_lut(double g) : m_gamma(1.0), - m_dir_gamma(new HiResT[gamma_size]), - m_inv_gamma(new LoResT[hi_res_size]) + m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)), + m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size)) { gamma(g); } @@ -79,13 +81,15 @@ namespace agg unsigned i; for(i = 0; i < gamma_size; i++) { - m_dir_gamma[i] = (HiResT)(pow(double(i) / double(gamma_mask), m_gamma) * double(hi_res_mask) + 0.5); + m_dir_gamma[i] = (HiResT) + uround(pow(i / double(gamma_mask), m_gamma) * double(hi_res_mask)); } double inv_g = 1.0 / g; for(i = 0; i < hi_res_size; i++) { - m_inv_gamma[i] = (LoResT)(pow(double(i) / double(hi_res_mask), inv_g) * double(gamma_mask) + 0.5); + m_inv_gamma[i] = (LoResT) + uround(pow(i / double(hi_res_mask), inv_g) * double(gamma_mask)); } } @@ -105,6 +109,9 @@ namespace agg } private: + gamma_lut(const self_type&); + const self_type& operator = (const self_type&); + double m_gamma; HiResT* m_dir_gamma; LoResT* m_inv_gamma; diff --git a/agg/inc/agg_glyph_raster_bin.h b/agg/inc/agg_glyph_raster_bin.h index 851d9f94bd72..674c247b1395 100755 --- a/agg/inc/agg_glyph_raster_bin.h +++ b/agg/inc/agg_glyph_raster_bin.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_gsv_text.h b/agg/inc/agg_gsv_text.h index 5d8e1cf63bab..2e125055b5a8 100755 --- a/agg/inc/agg_gsv_text.h +++ b/agg/inc/agg_gsv_text.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -20,7 +20,7 @@ #ifndef AGG_GSV_TEXT_INCLUDED #define AGG_GSV_TEXT_INCLUDED -#include "agg_basics.h" +#include "agg_array.h" #include "agg_conv_stroke.h" #include "agg_conv_transform.h" @@ -43,7 +43,6 @@ namespace agg }; public: - ~gsv_text(); gsv_text(); void font(const void* font); @@ -55,7 +54,9 @@ namespace agg void start_point(double x, double y); void text(const char* text); - void rewind(unsigned id); + double text_width(); + + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: @@ -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<char> m_text_buf; + char* m_cur_chr; + const void* m_font; + pod_array<char> m_loaded_font; + status m_status; + bool m_big_endian; + bool m_flip; + int8u* m_indices; + int8* m_glyphs; + int8* m_bglyph; + int8* m_eglyph; + double m_w; + double m_h; }; @@ -129,9 +128,9 @@ namespace agg m_trans->transformer(trans); } - void rewind(unsigned id) + void rewind(unsigned path_id) { - m_trans.rewind(id); + m_trans.rewind(path_id); m_polyline.line_join(round_join); m_polyline.line_cap(round_cap); } diff --git a/agg/inc/agg_image_accessors.h b/agg/inc/agg_image_accessors.h new file mode 100644 index 000000000000..043706fe2b69 --- /dev/null +++ b/agg/inc/agg_image_accessors.h @@ -0,0 +1,481 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_IMAGE_ACCESSORS_INCLUDED +#define AGG_IMAGE_ACCESSORS_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //-----------------------------------------------------image_accessor_clip + template<class PixFmt> class image_accessor_clip + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_clip() {} + explicit image_accessor_clip(const pixfmt_type& pixf, + const color_type& bk) : + m_pixf(&pixf) + { + pixfmt_type::make_pix(m_bk_buf, bk); + } + + void attach(const pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + void background_color(const color_type& bk) + { + pixfmt_type::make_pix(m_bk_buf, bk); + } + + private: + AGG_INLINE const int8u* pixel() const + { + if(m_y >= 0 && m_y < (int)m_pixf->height() && + m_x >= 0 && m_x < (int)m_pixf->width()) + { + return m_pixf->pix_ptr(m_x, m_y); + } + return m_bk_buf; + } + + public: + AGG_INLINE const int8u* span(int x, int y, unsigned len) + { + m_x = m_x0 = x; + m_y = y; + if(y >= 0 && y < (int)m_pixf->height() && + x >= 0 && x+(int)len <= (int)m_pixf->width()) + { + return m_pix_ptr = m_pixf->pix_ptr(x, y); + } + m_pix_ptr = 0; + return pixel(); + } + + AGG_INLINE const int8u* next_x() + { + if(m_pix_ptr) return m_pix_ptr += pix_width; + ++m_x; + return pixel(); + } + + AGG_INLINE const int8u* next_y() + { + ++m_y; + m_x = m_x0; + if(m_pix_ptr && + m_y >= 0 && m_y < (int)m_pixf->height()) + { + return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); + } + m_pix_ptr = 0; + return pixel(); + } + + private: + const pixfmt_type* m_pixf; + int8u m_bk_buf[4]; + int m_x, m_x0, m_y; + const int8u* m_pix_ptr; + }; + + + + + //--------------------------------------------------image_accessor_no_clip + template<class PixFmt> class image_accessor_no_clip + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_no_clip() {} + explicit image_accessor_no_clip(const pixfmt_type& pixf) : + m_pixf(&pixf) + {} + + void attach(const pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + AGG_INLINE const int8u* span(int x, int y, unsigned) + { + m_x = x; + m_y = y; + return m_pix_ptr = m_pixf->pix_ptr(x, y); + } + + AGG_INLINE const int8u* next_x() + { + return m_pix_ptr += pix_width; + } + + AGG_INLINE const int8u* next_y() + { + ++m_y; + return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); + } + + private: + const pixfmt_type* m_pixf; + int m_x, m_y; + const int8u* m_pix_ptr; + }; + + + + + //----------------------------------------------------image_accessor_clone + template<class PixFmt> class image_accessor_clone + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_clone() {} + explicit image_accessor_clone(const pixfmt_type& pixf) : + m_pixf(&pixf) + {} + + void attach(const pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + private: + AGG_INLINE const int8u* pixel() const + { + register int x = m_x; + register int y = m_y; + if(x < 0) x = 0; + if(y < 0) y = 0; + if(x >= (int)m_pixf->width()) x = m_pixf->width() - 1; + if(y >= (int)m_pixf->height()) y = m_pixf->height() - 1; + return m_pixf->pix_ptr(x, y); + } + + public: + AGG_INLINE const int8u* span(int x, int y, unsigned len) + { + m_x = m_x0 = x; + m_y = y; + if(y >= 0 && y < (int)m_pixf->height() && + x >= 0 && x+len <= (int)m_pixf->width()) + { + return m_pix_ptr = m_pixf->pix_ptr(x, y); + } + m_pix_ptr = 0; + return pixel(); + } + + AGG_INLINE const int8u* next_x() + { + if(m_pix_ptr) return m_pix_ptr += pix_width; + ++m_x; + return pixel(); + } + + AGG_INLINE const int8u* next_y() + { + ++m_y; + m_x = m_x0; + if(m_pix_ptr && + m_y >= 0 && m_y < (int)m_pixf->height()) + { + return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); + } + m_pix_ptr = 0; + return pixel(); + } + + private: + const pixfmt_type* m_pixf; + int m_x, m_x0, m_y; + const int8u* m_pix_ptr; + }; + + + + + + //-----------------------------------------------------image_accessor_wrap + template<class PixFmt, class WrapX, class WrapY> class image_accessor_wrap + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_wrap() {} + explicit image_accessor_wrap(const pixfmt_type& pixf) : + m_pixf(&pixf), + m_wrap_x(pixf.width()), + m_wrap_y(pixf.height()) + {} + + void attach(const pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + AGG_INLINE const int8u* span(int x, int y, unsigned) + { + m_x = x; + m_row_ptr = m_pixf->row_ptr(m_wrap_y(y)); + return m_row_ptr + m_wrap_x(x) * pix_width; + } + + AGG_INLINE const int8u* next_x() + { + int x = ++m_wrap_x; + return m_row_ptr + x * pix_width; + } + + AGG_INLINE const int8u* next_y() + { + m_row_ptr = m_pixf->row_ptr(++m_wrap_y); + return m_row_ptr + m_wrap_x(m_x) * pix_width; + } + + private: + const pixfmt_type* m_pixf; + const int8u* m_row_ptr; + int m_x; + WrapX m_wrap_x; + WrapY m_wrap_y; + }; + + + + + //--------------------------------------------------------wrap_mode_repeat + class wrap_mode_repeat + { + public: + wrap_mode_repeat() {} + wrap_mode_repeat(unsigned size) : + m_size(size), + m_add(size * (0x3FFFFFFF / size)), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + return m_value = (unsigned(v) + m_add) % m_size; + } + + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size) m_value = 0; + return m_value; + } + private: + unsigned m_size; + unsigned m_add; + unsigned m_value; + }; + + + //---------------------------------------------------wrap_mode_repeat_pow2 + class wrap_mode_repeat_pow2 + { + public: + wrap_mode_repeat_pow2() {} + wrap_mode_repeat_pow2(unsigned size) : m_value(0) + { + m_mask = 1; + while(m_mask < size) m_mask = (m_mask << 1) | 1; + m_mask >>= 1; + } + AGG_INLINE unsigned operator() (int v) + { + return m_value = unsigned(v) & m_mask; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value > m_mask) m_value = 0; + return m_value; + } + private: + unsigned m_mask; + unsigned m_value; + }; + + + //----------------------------------------------wrap_mode_repeat_auto_pow2 + class wrap_mode_repeat_auto_pow2 + { + public: + wrap_mode_repeat_auto_pow2() {} + wrap_mode_repeat_auto_pow2(unsigned size) : + m_size(size), + m_add(size * (0x3FFFFFFF / size)), + m_mask((m_size & (m_size-1)) ? 0 : m_size-1), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + if(m_mask) return m_value = unsigned(v) & m_mask; + return m_value = (unsigned(v) + m_add) % m_size; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size) m_value = 0; + return m_value; + } + + private: + unsigned m_size; + unsigned m_add; + unsigned m_mask; + unsigned m_value; + }; + + + //-------------------------------------------------------wrap_mode_reflect + class wrap_mode_reflect + { + public: + wrap_mode_reflect() {} + wrap_mode_reflect(unsigned size) : + m_size(size), + m_size2(size * 2), + m_add(m_size2 * (0x3FFFFFFF / m_size2)), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + m_value = (unsigned(v) + m_add) % m_size2; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size2) m_value = 0; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + private: + unsigned m_size; + unsigned m_size2; + unsigned m_add; + unsigned m_value; + }; + + + + //--------------------------------------------------wrap_mode_reflect_pow2 + class wrap_mode_reflect_pow2 + { + public: + wrap_mode_reflect_pow2() {} + wrap_mode_reflect_pow2(unsigned size) : m_value(0) + { + m_mask = 1; + m_size = 1; + while(m_mask < size) + { + m_mask = (m_mask << 1) | 1; + m_size <<= 1; + } + } + AGG_INLINE unsigned operator() (int v) + { + m_value = unsigned(v) & m_mask; + if(m_value >= m_size) return m_mask - m_value; + return m_value; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + m_value &= m_mask; + if(m_value >= m_size) return m_mask - m_value; + return m_value; + } + private: + unsigned m_size; + unsigned m_mask; + unsigned m_value; + }; + + + + //---------------------------------------------wrap_mode_reflect_auto_pow2 + class wrap_mode_reflect_auto_pow2 + { + public: + wrap_mode_reflect_auto_pow2() {} + wrap_mode_reflect_auto_pow2(unsigned size) : + m_size(size), + m_size2(size * 2), + m_add(m_size2 * (0x3FFFFFFF / m_size2)), + m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + m_value = m_mask ? unsigned(v) & m_mask : + (unsigned(v) + m_add) % m_size2; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size2) m_value = 0; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + + private: + unsigned m_size; + unsigned m_size2; + unsigned m_add; + unsigned m_mask; + unsigned m_value; + }; + + +} + + +#endif diff --git a/agg/inc/agg_image_filters.h b/agg/inc/agg_image_filters.h index a2037fe0eff1..64f12cd25b7d 100755 --- a/agg/inc/agg_image_filters.h +++ b/agg/inc/agg_image_filters.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -20,23 +20,26 @@ #ifndef AGG_IMAGE_FILTERS_INCLUDED #define AGG_IMAGE_FILTERS_INCLUDED -#include <math.h> -#include "agg_basics.h" +#include "agg_array.h" +#include "agg_math.h" namespace agg { // See Implementation agg_image_filters.cpp - enum + enum image_filter_scale_e { image_filter_shift = 14, //----image_filter_shift - image_filter_size = 1 << image_filter_shift, //----image_filter_size - image_filter_mask = image_filter_size - 1, //----image_filter_mask + image_filter_scale = 1 << image_filter_shift, //----image_filter_scale + image_filter_mask = image_filter_scale - 1 //----image_filter_mask + }; + enum image_subpixel_scale_e + { image_subpixel_shift = 8, //----image_subpixel_shift - image_subpixel_size = 1 << image_subpixel_shift, //----image_subpixel_size - image_subpixel_mask = image_subpixel_size - 1 //----image_subpixel_mask + image_subpixel_scale = 1 << image_subpixel_shift, //----image_subpixel_scale + image_subpixel_mask = image_subpixel_scale - 1 //----image_subpixel_mask }; @@ -44,22 +47,19 @@ namespace agg class image_filter_lut { public: - ~image_filter_lut(); - image_filter_lut(); - template<class FilterF> void calculate(const FilterF& filter, bool normalization=true) { double r = filter.radius(); - realloc(r); + realloc_lut(r); unsigned i; unsigned pivot = diameter() << (image_subpixel_shift - 1); for(i = 0; i < pivot; i++) { - double x = double(i) / double(image_subpixel_size); + double x = double(i) / double(image_subpixel_scale); double y = filter.calc_weight(x); m_weight_array[pivot + i] = - m_weight_array[pivot - i] = int16(y * image_filter_size + 0.5); + m_weight_array[pivot - i] = (int16)iround(y * image_filter_scale); } unsigned end = (diameter() << image_subpixel_shift) - 1; m_weight_array[0] = m_weight_array[end]; @@ -69,30 +69,29 @@ namespace agg } } + image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {} + template<class FilterF> image_filter_lut(const FilterF& filter, - bool normalization=true) : - m_weight_array(0), - m_max_size(0) + bool normalization=true) { calculate(filter, normalization); } - 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: - void realloc(double radius); + void realloc_lut(double radius); 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<int16> m_weight_array; }; @@ -312,7 +311,7 @@ namespace agg static double radius() { return 3.2383; } static double calc_weight(double x) { - return (x == 0.0) ? pi / 4.0 : j1(pi * x) / (2.0 * x); + return (x == 0.0) ? pi / 4.0 : besj(pi * x, 1) / (2.0 * x); } }; diff --git a/agg/inc/agg_line_aa_basics.h b/agg/inc/agg_line_aa_basics.h index ab8e94715019..d5c4feb36967 100755 --- a/agg/inc/agg_line_aa_basics.h +++ b/agg/inc/agg_line_aa_basics.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -24,44 +24,58 @@ namespace agg // See Implementation agg_line_aa_basics.cpp //------------------------------------------------------------------------- - enum + enum line_subpixel_scale_e { - line_subpixel_shift = 8, //----line_subpixel_shift - line_subpixel_size = 1 << line_subpixel_shift, //----line_subpixel_size - line_subpixel_mask = line_subpixel_size - 1 //----line_subpixel_mask + line_subpixel_shift = 8, //----line_subpixel_shift + line_subpixel_scale = 1 << line_subpixel_shift, //----line_subpixel_scale + line_subpixel_mask = line_subpixel_scale - 1, //----line_subpixel_mask + line_max_coord = (1 << 28) - 1, //----line_max_coord + line_max_length = 1 << (line_subpixel_shift + 10) //----line_max_length }; //------------------------------------------------------------------------- - enum + enum line_mr_subpixel_scale_e { line_mr_subpixel_shift = 4, //----line_mr_subpixel_shift - line_mr_subpixel_size = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_size - line_mr_subpixel_mask = line_mr_subpixel_size - 1 //----line_mr_subpixel_mask + line_mr_subpixel_scale = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_scale + line_mr_subpixel_mask = line_mr_subpixel_scale - 1 //----line_mr_subpixel_mask }; //------------------------------------------------------------------line_mr - inline int line_mr(int x) + AGG_INLINE int line_mr(int x) { - return x >> ((int)line_subpixel_shift - (int)line_mr_subpixel_shift); + return x >> (line_subpixel_shift - line_mr_subpixel_shift); } //-------------------------------------------------------------------line_hr - inline int line_hr(int x) + AGG_INLINE int line_hr(int x) { - return x << ((int)line_subpixel_shift - (int)line_mr_subpixel_shift); + return x << (line_subpixel_shift - line_mr_subpixel_shift); } //---------------------------------------------------------------line_dbl_hr - inline int line_dbl_hr(int x) + AGG_INLINE int line_dbl_hr(int x) { return x << line_subpixel_shift; } //---------------------------------------------------------------line_coord - inline int line_coord(double x) + struct line_coord { - return int(x * line_subpixel_size); - } + AGG_INLINE static int conv(double x) + { + return iround(x * line_subpixel_scale); + } + }; + + //-----------------------------------------------------------line_coord_sat + struct line_coord_sat + { + AGG_INLINE static int conv(double x) + { + return saturation<line_max_coord>::iround(x * line_subpixel_scale); + } + }; //==========================================================line_parameters struct line_parameters @@ -98,6 +112,29 @@ namespace agg } //--------------------------------------------------------------------- + void divide(line_parameters& lp1, line_parameters& lp2) const + { + int xmid = (x1 + x2) >> 1; + int ymid = (y1 + y2) >> 1; + int len2 = len >> 1; + + lp1 = *this; + lp2 = *this; + + lp1.x2 = xmid; + lp1.y2 = ymid; + lp1.len = len2; + lp1.dx = abs(lp1.x2 - lp1.x1); + lp1.dy = abs(lp1.y2 - lp1.y1); + + lp2.x1 = xmid; + lp2.y1 = ymid; + lp2.len = len2; + lp2.dx = abs(lp2.x2 - lp2.x1); + lp2.dy = abs(lp2.y2 - lp2.y1); + } + + //--------------------------------------------------------------------- int x1, y1, x2, y2, dx, dy, sx, sy; bool vertical; int inc; @@ -105,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]; }; @@ -123,9 +160,9 @@ namespace agg void inline fix_degenerate_bisectrix_start(const line_parameters& lp, int* x, int* y) { - int d = int((double(*x - lp.x2) * double(lp.y2 - lp.y1) - - double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len); - if(d < line_subpixel_size) + int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) - + double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len); + if(d < line_subpixel_scale/2) { *x = lp.x1 + (lp.y2 - lp.y1); *y = lp.y1 - (lp.x2 - lp.x1); @@ -137,9 +174,9 @@ namespace agg void inline fix_degenerate_bisectrix_end(const line_parameters& lp, int* x, int* y) { - int d = int((double(*x - lp.x2) * double(lp.y2 - lp.y1) - - double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len); - if(d < line_subpixel_size) + int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) - + double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len); + if(d < line_subpixel_scale/2) { *x = lp.x2 + (lp.y2 - lp.y1); *y = lp.y2 - (lp.x2 - lp.x1); diff --git a/agg/inc/agg_math.h b/agg/inc/agg_math.h index 4aef4df9638e..2c35c805e673 100755 --- a/agg/inc/agg_math.h +++ b/agg/inc/agg_math.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -12,6 +12,9 @@ // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- +// Bessel function (besj) was adapted for use in AGG library by Andy Wilk +// Contact: castor.vulgaris@gmail.com +//---------------------------------------------------------------------------- #ifndef AGG_MATH_INCLUDED #define AGG_MATH_INCLUDED @@ -22,30 +25,34 @@ namespace agg { - const double intersection_epsilon = 1.0e-8; + //------------------------------------------------------vertex_dist_epsilon + // Coinciding points maximal distance (Epsilon) + const double vertex_dist_epsilon = 1e-14; + + //-----------------------------------------------------intersection_epsilon + // See calc_intersection + const double intersection_epsilon = 1.0e-30; - //------------------------------------------------------calc_point_location - AGG_INLINE double calc_point_location(double x1, double y1, - double x2, double y2, - double x, double y) + //------------------------------------------------------------cross_product + AGG_INLINE double cross_product(double x1, double y1, + double x2, double y2, + double x, double y) { 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, double x3, double y3, double x, double y) { - bool cp1 = calc_point_location(x1, y1, x2, y2, x, y) < 0.0; - bool cp2 = calc_point_location(x2, y2, x3, y3, x, y) < 0.0; - bool cp3 = calc_point_location(x3, y3, x1, y1, x, y) < 0.0; + bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0; + bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0; + bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0; return cp1 == cp2 && cp2 == cp3 && cp3 == cp1; } - //-----------------------------------------------------------calc_distance AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2) { @@ -54,17 +61,76 @@ 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_point_line_distance - AGG_INLINE double calc_point_line_distance(double x1, double y1, + //------------------------------------------------calc_line_point_distance + AGG_INLINE double calc_line_point_distance(double x1, double y1, double x2, double y2, double x, double y) { double dx = x2-x1; double dy = y2-y1; - return ((x - x2) * dy - (y - y2) * dx) / sqrt(dx * dx + dy * dy); + double d = sqrt(dx * dx + dy * dy); + if(d < vertex_dist_epsilon) + { + return calc_distance(x1, y1, x, y); + } + 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, @@ -80,6 +146,32 @@ 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) + { + // It's less expensive but you can't control the + // boundary conditions: Less or LessEqual + double dx1 = x2 - x1; + double dy1 = y2 - y1; + double dx2 = x4 - x3; + double dy2 = y4 - y3; + return ((x3 - x2) * dy1 - (y3 - y2) * dx1 < 0.0) != + ((x4 - x2) * dy1 - (y4 - y2) * dx1 < 0.0) && + ((x1 - x4) * dy2 - (y1 - y4) * dx2 < 0.0) != + ((x2 - x4) * dy2 - (y2 - y4) * dx2 < 0.0); + + // It's is more expensive but more flexible + // in terms of boundary conditions. + //-------------------- + //double den = (x2-x1) * (y4-y3) - (y2-y1) * (x4-x3); + //if(fabs(den) < intersection_epsilon) return false; + //double nom1 = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3); + //double nom2 = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3); + //double ua = nom1 / den; + //double ub = nom2 / den; + //return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0; + } //--------------------------------------------------------calc_orthogonal AGG_INLINE void calc_orthogonal(double thickness, @@ -90,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, @@ -108,10 +199,10 @@ namespace agg double dy2=0.0; double dx3=0.0; double dy3=0.0; - double loc = calc_point_location(x1, y1, x2, y2, x3, y3); + double loc = cross_product(x1, y1, x2, y2, x3, y3); if(fabs(loc) > intersection_epsilon) { - if(calc_point_location(x1, y1, x2, y2, x3, y3) > 0.0) + if(cross_product(x1, y1, x2, y2, x3, y3) > 0.0) { d = -d; } @@ -119,12 +210,20 @@ 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 + AGG_INLINE double calc_triangle_area(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5; } //-------------------------------------------------------calc_polygon_area @@ -223,7 +322,7 @@ namespace agg } } - //This is calculation sqrt itself. + //This code calculates the sqrt. bit -= 9; if(bit > 0) { @@ -241,6 +340,97 @@ namespace agg + //--------------------------------------------------------------------besj + // Function BESJ calculates Bessel function of first kind of order n + // Arguments: + // n - an integer (>=0), the order + // x - value at which the Bessel function is required + //-------------------- + // C++ Mathematical Library + // Convereted from equivalent FORTRAN library + // Converetd by Gareth Walker for use by course 392 computational project + // All functions tested and yield the same results as the corresponding + // FORTRAN versions. + // + // If you have any problems using these functions please report them to + // M.Muldoon@UMIST.ac.uk + // + // Documentation available on the web + // http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html + // Version 1.0 8/98 + // 29 October, 1999 + //-------------------- + // Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com) + //------------------------------------------------------------------------ + inline double besj(double x, int n) + { + if(n < 0) + { + return 0; + } + double d = 1E-6; + double b = 0; + if(fabs(x) <= d) + { + if(n != 0) return 0; + return 1; + } + double b1 = 0; // b1 is the value from the previous iteration + // Set up a starting order for recurrence + int m1 = (int)fabs(x) + 6; + if(fabs(x) > 5) + { + m1 = (int)(fabs(1.4 * x + 60 / x)); + } + int m2 = (int)(n + 2 + fabs(x) / 4); + if (m1 > m2) + { + m2 = m1; + } + + // Apply recurrence down from curent max order + for(;;) + { + double c3 = 0; + double c2 = 1E-30; + double c4 = 0; + int m8 = 1; + if (m2 / 2 * 2 == m2) + { + m8 = -1; + } + int imax = m2 - 2; + for (int i = 1; i <= imax; i++) + { + double c6 = 2 * (m2 - i) * c2 / x - c3; + c3 = c2; + c2 = c6; + if(m2 - i - 1 == n) + { + b = c6; + } + m8 = -1 * m8; + if (m8 > 0) + { + c4 = c4 + 2 * c6; + } + } + double c6 = 2 * c2 / x - c3; + if(n == 0) + { + b = c6; + } + c4 += c6; + b /= c4; + if(fabs(b - b1) < d) + { + return b; + } + b1 = b; + m2 += 3; + } + } + } diff --git a/agg/inc/agg_math_stroke.h b/agg/inc/agg_math_stroke.h index 84d83738a9cd..8cec034e11d2 100755 --- a/agg/inc/agg_math_stroke.h +++ b/agg/inc/agg_math_stroke.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -36,297 +36,483 @@ namespace agg //------------------------------------------------------------line_join_e enum line_join_e { - miter_join, - miter_join_revert, - round_join, - bevel_join + miter_join = 0, + miter_join_revert = 1, + round_join = 2, + bevel_join = 3, + miter_join_round = 4 }; - // Minimal angle to calculate round joins, less than 0.1 degree. - const double stroke_theta = 0.001; //----stroke_theta + //-----------------------------------------------------------inner_join_e + enum inner_join_e + { + inner_bevel, + inner_miter, + inner_jag, + inner_round + }; - //--------------------------------------------------------stroke_calc_arc - template<class VertexConsumer> - void stroke_calc_arc(VertexConsumer& out_vertices, - double x, double y, - double dx1, double dy1, - double dx2, double dy2, - double width, - double approximation_scale) + //------------------------------------------------------------math_stroke + template<class VertexConsumer> class math_stroke { + public: typedef typename VertexConsumer::value_type coord_type; - //// Check if we actually need the arc (this optimization works bad) - ////----------------- - //double dd = calc_distance(dx1, dy1, dx2, dy2); - //if(dd < 1.0/approximation_scale) - //{ - // out_vertices.add(coord_type(x + dx1, y + dy1)); - // if(dd > 0.25/approximation_scale) - // { - // out_vertices.add(coord_type(x + dx2, y + dy2)); - // } - // return; - //} - - double a1 = atan2(dy1, dx1); - double a2 = atan2(dy2, dx2); - double da = a1 - a2; + 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; + }; - if(fabs(da) < stroke_theta) + //----------------------------------------------------------------------- + template<class VC> math_stroke<VC>::math_stroke() : + m_width(0.5), + m_width_abs(0.5), + m_width_eps(0.5/1024.0), + m_width_sign(1), + m_miter_limit(4.0), + m_inner_miter_limit(1.01), + m_approx_scale(1.0), + m_line_cap(butt_cap), + m_line_join(miter_join), + m_inner_join(inner_miter) + { + } + + //----------------------------------------------------------------------- + template<class VC> void math_stroke<VC>::width(double w) + { + m_width = w * 0.5; + if(m_width < 0) + { + m_width_abs = -m_width; + m_width_sign = -1; + } + else { - out_vertices.add(coord_type((x + x + dx1 + dx2) * 0.5, - (y + y + dy1 + dy2) * 0.5)); - return; + m_width_abs = m_width; + m_width_sign = 1; } + m_width_eps = m_width / 1024.0; + } + + //----------------------------------------------------------------------- + template<class VC> void math_stroke<VC>::miter_limit_theta(double t) + { + m_miter_limit = 1.0 / sin(t * 0.5) ; + } + + //----------------------------------------------------------------------- + template<class VC> + void math_stroke<VC>::calc_arc(VC& vc, + double x, double y, + double dx1, double dy1, + double dx2, double dy2) + { + double a1 = atan2(dy1 * m_width_sign, dx1 * m_width_sign); + double a2 = atan2(dy2 * m_width_sign, dx2 * m_width_sign); + double da = a1 - a2; + int i, n; - bool ccw = da > 0.0 && da < pi; + da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2; - if(width < 0) width = -width; - da = fabs(1.0 / (width * approximation_scale)); - if(!ccw) + add_vertex(vc, x + dx1, y + dy1); + if(m_width_sign > 0) { if(a1 > a2) a2 += 2 * pi; - while(a1 < a2) + n = int((a2 - a1) / da); + da = (a2 - a1) / (n + 1); + a1 += da; + 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; - while(a1 > a2) + n = int((a1 - a2) / da); + da = (a1 - a2) / (n + 1); + a1 -= da; + for(i = 0; i < n; i++) { - out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width)); + add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width); a1 -= da; } } - out_vertices.add(coord_type(x + dx2, y + dy2)); + add_vertex(vc, x + dx2, y + dy2); } - - - //-------------------------------------------------------stroke_calc_miter - template<class VertexConsumer> - void stroke_calc_miter(VertexConsumer& out_vertices, - const vertex_dist& v0, - const vertex_dist& v1, - const vertex_dist& v2, - double dx1, double dy1, - double dx2, double dy2, - double width, - bool revert_flag, - double miter_limit) + //----------------------------------------------------------------------- + template<class VC> + void math_stroke<VC>::calc_miter(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double dx1, double dy1, + double dx2, double dy2, + line_join_e lj, + double mlimit, + double dbevel) { - typedef typename VertexConsumer::value_type coord_type; - - double xi = v1.x; - double yi = v1.y; - - 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, - &xi, &yi)) + 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, + v1.x + dx2, v1.y - dy2, + v2.x + dx2, v2.y - dy2, + &xi, &yi)) { - // The calculation didn't succeed, most probaly - // the three points lie one straight line + // Calculation of the intersection succeeded + //--------------------- + di = calc_distance(v1.x, v1.y, xi, yi); + if(di <= lim) + { + // Inside the miter limit + //--------------------- + add_vertex(vc, xi, yi); + miter_limit_exceeded = false; + } + intersection_failed = false; + } + else + { + // Calculation of the intersection failed, most probably + // the three points lie one straight line. + // First check if v0 and v2 lie on the opposite sides of vector: + // (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular + // to the line determined by vertices v0 and v1. + // This condition determines whether the next line segments continues + // the previous one or goes back. //---------------- - if(calc_distance(dx1, -dy1, dx2, -dy2) < width * 0.025) + double x2 = v1.x + dx1; + double y2 = v1.y - dy1; + 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)); - } - else - { - // This case means that the next segment goes back - //----------------- - if(revert_flag) - { - out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1)); - out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2)); - } - else - { - // If no miter-revert, calcuate 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)); - } + add_vertex(vc, v1.x + dx1, v1.y - dy1); + miter_limit_exceeded = false; } } - else + + if(miter_limit_exceeded) { - double d1 = calc_distance(v1.x, v1.y, xi, yi); - double lim = width * miter_limit; - if(d1 > lim) + // Miter limit exceeded + //------------------------ + switch(lj) { - // Miter limit exceeded - //------------------------ - if(revert_flag) + case miter_join_revert: + // For the compatibility with SVG, PDF, etc, + // we use a simple bevel join instead of + // "smart" bevel + //------------------- + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + break; + + case miter_join_round: + calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2); + break; + + default: + // If no miter-revert, calculate new dx1, dy1, dx2, dy2 + //---------------- + if(intersection_failed) { - // 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)); + 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 { - // Smart bevel that cuts the miter at the limit point - //------------------- - d1 = lim / d1; double x1 = v1.x + dx1; double y1 = v1.y - dy1; double x2 = v1.x + dx2; double y2 = v1.y - dy2; - - x1 += (xi - x1) * d1; - y1 += (yi - y1) * d1; - x2 += (xi - x2) * d1; - y2 += (yi - y2) * d1; - out_vertices.add(coord_type(x1, y1)); - out_vertices.add(coord_type(x2, y2)); + 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); } - } - else - { - // Inside the miter limit - //--------------------- - out_vertices.add(coord_type(xi, yi)); + break; } } } - - - - - //--------------------------------------------------------stroke_calc_cap - template<class VertexConsumer> - 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<class VC> + void math_stroke<VC>::calc_cap(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + double len) { - typedef typename VertexConsumer::value_type coord_type; + vc.remove_all(); - out_vertices.remove_all(); - - double dx1 = width * (v1.y - v0.y) / len; - double dy1 = width * (v1.x - v0.x) / len; + double dx1 = (v1.y - v0.y) / len; + double dy1 = (v1.x - v0.x) / len; double dx2 = 0; double dy2 = 0; - if(line_cap == square_cap) - { - dx2 = dy1; - dy2 = dx1; - } + dx1 *= m_width; + dy1 *= m_width; - if(line_cap == round_cap) + if(m_line_cap != round_cap) { - double a1 = atan2(dy1, -dx1); - double a2 = a1 + pi; - double da = fabs(1.0 / (width * approximation_scale)); - while(a1 < a2) + if(m_line_cap == square_cap) { - out_vertices.add(coord_type(v0.x + cos(a1) * width, - v0.y + sin(a1) * width)); - a1 += da; + dx2 = dy1 * m_width_sign; + dy2 = dx1 * m_width_sign; } - out_vertices.add(coord_type(v0.x + dx1, v0.y - dy1)); + add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2); + add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2); } else { - 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)); + 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) + { + 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; + } + } + else + { + a1 = atan2(-dy1, dx1); + a1 -= da; + for(i = 0; i < n; i++) + { + add_vertex(vc, v0.x + cos(a1) * m_width, + v0.y + sin(a1) * m_width); + a1 -= da; + } + } + add_vertex(vc, v0.x + dx1, v0.y - dy1); } } - - - //-------------------------------------------------------stroke_calc_join - template<class VertexConsumer> - void stroke_calc_join(VertexConsumer& out_vertices, - const vertex_dist& v0, - const vertex_dist& v1, - const vertex_dist& v2, - double len1, - double len2, - double width, - line_join_e line_join, - line_join_e inner_line_join, - double miter_limit, - double inner_miter_limit, - double approximation_scale) + //----------------------------------------------------------------------- + template<class VC> + void math_stroke<VC>::calc_join(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double len1, + double len2) { - typedef typename VertexConsumer::value_type coord_type; - - double dx1, dy1, dx2, dy2; - - 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; + 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; - out_vertices.remove_all(); + vc.remove_all(); - if(calc_point_location(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y) > 0.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 //--------------- - stroke_calc_miter(out_vertices, - v0, v1, v2, dx1, dy1, dx2, dy2, - width, - inner_line_join == miter_join_revert, - inner_miter_limit); + 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 + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + break; + + case inner_miter: + 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) + { + calc_miter(vc, + v0, v1, v2, dx1, dy1, dx2, dy2, + miter_join_revert, + limit, 0); + } + else + { + if(m_inner_join == inner_jag) + { + 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 + { + 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; + } } else { // Outer join //--------------- - switch(line_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) { - case miter_join: - stroke_calc_miter(out_vertices, - v0, v1, v2, dx1, dy1, dx2, dy2, - width, - false, - miter_limit); - break; + // This is an optimization that reduces the number of points + // 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. + // + // Here we calculate the middle point between the bevel points + // and then, the distance between v1 and this middle point. + // 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 + // add just one point. + // + // The constant in the expression makes the result approximately + // the same as in round joins and caps. You can safely comment + // out this entire "if". + //------------------- + if(m_approx_scale * (m_width_abs - dbevel) < m_width_eps) + { + 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(m_line_join) + { + case miter_join: case miter_join_revert: - stroke_calc_miter(out_vertices, - v0, v1, v2, dx1, dy1, dx2, dy2, - width, - true, - miter_limit); + case miter_join_round: + 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)); - if(calc_distance(dx1, dy1, dx2, dy2) > approximation_scale * 0.25) - { - 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/inc/agg_path_length.h b/agg/inc/agg_path_length.h new file mode 100644 index 000000000000..8f9671748a18 --- /dev/null +++ b/agg/inc/agg_path_length.h @@ -0,0 +1,65 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +#ifndef AGG_PATH_LENGTH_INCLUDED +#define AGG_PATH_LENGTH_INCLUDED + +#include "agg_math.h" + +namespace agg +{ + template<class VertexSource> + double path_length(VertexSource& vs, unsigned path_id = 0) + { + double len = 0.0; + double start_x = 0.0; + double start_y = 0.0; + double x1 = 0.0; + double y1 = 0.0; + double x2 = 0.0; + double y2 = 0.0; + bool first = true; + + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x2, &y2))) + { + if(is_vertex(cmd)) + { + if(first || is_move_to(cmd)) + { + start_x = x2; + start_y = y2; + } + else + { + len += calc_distance(x1, y1, x2, y2); + } + x1 = x2; + y1 = y2; + first = false; + } + else + { + if(is_close(cmd) && !first) + { + len += calc_distance(x1, y1, start_x, start_y); + } + } + } + return len; + } +} + +#endif diff --git a/agg/inc/agg_path_storage.h b/agg/inc/agg_path_storage.h index 8cdb9b9bbeb6..930521b4d48d 100755 --- a/agg/inc/agg_path_storage.h +++ b/agg/inc/agg_path_storage.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -16,101 +16,609 @@ #ifndef AGG_PATH_STORAGE_INCLUDED #define AGG_PATH_STORAGE_INCLUDED -#include "agg_basics.h" +#include <string.h> +#include <math.h> +#include "agg_math.h" +#include "agg_array.h" +#include "agg_bezier_arc.h" namespace agg { - //------------------------------------------------------------path_storage - // A container to store vertices with their flags. - // A path consists of a number of contours separated with "move_to" - // commands. The path storage can keep and maintain more than one - // path. - // To navigate to the beginning of a particular path, use rewind(path_id); - // Where path_id is what start_new_path() returns. So, when you call - // start_new_path() you need to store its return value somewhere else - // to navigate to the path afterwards. - // - // See Implementation: agg_path_storage.cpp - // See also: vertex_source concept - //------------------------------------------------------------------------ - class path_storage + + //----------------------------------------------------vertex_block_storage + template<class T, unsigned BlockShift=8, unsigned BlockPool=256> + class vertex_block_storage { + public: // Allocation parameters - enum + enum block_scale_e { - block_shift = 8, + block_shift = BlockShift, block_size = 1 << block_shift, block_mask = block_size - 1, - block_pool = 256 + block_pool = BlockPool }; - public: + typedef T value_type; + typedef vertex_block_storage<T, BlockShift, BlockPool> self_type; - //-------------------------------------------------------------------- - class const_iterator + ~vertex_block_storage(); + vertex_block_storage(); + vertex_block_storage(const self_type& v); + const self_type& operator = (const self_type& ps); + + void remove_all(); + void free_all(); + + void add_vertex(double x, double y, unsigned cmd); + void modify_vertex(unsigned idx, double x, double y); + void modify_vertex(unsigned idx, double x, double y, unsigned cmd); + void modify_command(unsigned idx, unsigned cmd); + void swap_vertices(unsigned v1, unsigned v2); + + unsigned last_command() const; + unsigned last_vertex(double* x, double* y) const; + unsigned prev_vertex(double* x, double* y) const; + + double last_x() const; + double last_y() const; + + unsigned total_vertices() const; + unsigned vertex(unsigned idx, double* x, double* y) const; + unsigned command(unsigned idx) const; + + private: + void allocate_block(unsigned nb); + int8u* storage_ptrs(T** xy_ptr); + + private: + unsigned m_total_vertices; + unsigned m_total_blocks; + unsigned m_max_blocks; + T** m_coord_blocks; + int8u** m_cmd_blocks; + }; + + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + void vertex_block_storage<T,S,P>::free_all() + { + if(m_total_blocks) { - void vertex() + T** coord_blk = m_coord_blocks + m_total_blocks - 1; + while(m_total_blocks--) { - if(m_vertex_idx < m_path->total_vertices()) - { - m_vertex.cmd = m_path->vertex(m_vertex_idx, &m_vertex.x, &m_vertex.y); - } - else - { - m_vertex.cmd = path_cmd_stop; - m_vertex.x = m_vertex.y = 0.0; - } + pod_allocator<T>::deallocate( + *coord_blk, + block_size * 2 + + block_size / (sizeof(T) / sizeof(unsigned char))); + --coord_blk; } + pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2); + m_total_blocks = 0; + m_max_blocks = 0; + m_coord_blocks = 0; + m_cmd_blocks = 0; + m_total_vertices = 0; + } + } - public: - const_iterator() {} - const_iterator(unsigned cmd) { m_vertex.cmd = cmd; } - const_iterator(const const_iterator& i) : - m_path(i.m_path), - m_vertex_idx(i.m_vertex_idx), - m_vertex(i.m_vertex) + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + vertex_block_storage<T,S,P>::~vertex_block_storage() + { + free_all(); + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + vertex_block_storage<T,S,P>::vertex_block_storage() : + m_total_vertices(0), + m_total_blocks(0), + m_max_blocks(0), + m_coord_blocks(0), + m_cmd_blocks(0) + { + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + vertex_block_storage<T,S,P>::vertex_block_storage(const vertex_block_storage<T,S,P>& v) : + m_total_vertices(0), + m_total_blocks(0), + m_max_blocks(0), + m_coord_blocks(0), + m_cmd_blocks(0) + { + *this = v; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + const vertex_block_storage<T,S,P>& + vertex_block_storage<T,S,P>::operator = (const vertex_block_storage<T,S,P>& v) + { + remove_all(); + unsigned i; + for(i = 0; i < v.total_vertices(); i++) + { + double x, y; + unsigned cmd = v.vertex(i, &x, &y); + add_vertex(x, y, cmd); + } + return *this; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline void vertex_block_storage<T,S,P>::remove_all() + { + m_total_vertices = 0; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline void vertex_block_storage<T,S,P>::add_vertex(double x, double y, + unsigned cmd) + { + T* coord_ptr = 0; + *storage_ptrs(&coord_ptr) = (int8u)cmd; + coord_ptr[0] = T(x); + coord_ptr[1] = T(y); + m_total_vertices++; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx, + double x, double y) + { + T* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1); + pv[0] = T(x); + pv[1] = T(y); + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx, + double x, double y, + unsigned cmd) + { + unsigned block = idx >> block_shift; + unsigned offset = idx & block_mask; + T* pv = m_coord_blocks[block] + (offset << 1); + pv[0] = T(x); + pv[1] = T(y); + m_cmd_blocks[block][offset] = (int8u)cmd; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline void vertex_block_storage<T,S,P>::modify_command(unsigned idx, + unsigned cmd) + { + m_cmd_blocks[idx >> block_shift][idx & block_mask] = (int8u)cmd; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline void vertex_block_storage<T,S,P>::swap_vertices(unsigned v1, unsigned v2) + { + unsigned b1 = v1 >> block_shift; + unsigned b2 = v2 >> block_shift; + unsigned o1 = v1 & block_mask; + unsigned o2 = v2 & block_mask; + T* pv1 = m_coord_blocks[b1] + (o1 << 1); + T* pv2 = m_coord_blocks[b2] + (o2 << 1); + T val; + val = pv1[0]; pv1[0] = pv2[0]; pv2[0] = val; + val = pv1[1]; pv1[1] = pv2[1]; pv2[1] = val; + int8u cmd = m_cmd_blocks[b1][o1]; + m_cmd_blocks[b1][o1] = m_cmd_blocks[b2][o2]; + m_cmd_blocks[b2][o2] = cmd; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline unsigned vertex_block_storage<T,S,P>::last_command() const + { + if(m_total_vertices) return command(m_total_vertices - 1); + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline unsigned vertex_block_storage<T,S,P>::last_vertex(double* x, double* y) const + { + if(m_total_vertices) return vertex(m_total_vertices - 1, x, y); + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline unsigned vertex_block_storage<T,S,P>::prev_vertex(double* x, double* y) const + { + if(m_total_vertices > 1) return vertex(m_total_vertices - 2, x, y); + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline double vertex_block_storage<T,S,P>::last_x() const + { + if(m_total_vertices) + { + unsigned idx = m_total_vertices - 1; + return m_coord_blocks[idx >> block_shift][(idx & block_mask) << 1]; + } + return 0.0; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline double vertex_block_storage<T,S,P>::last_y() const + { + if(m_total_vertices) + { + unsigned idx = m_total_vertices - 1; + return m_coord_blocks[idx >> block_shift][((idx & block_mask) << 1) + 1]; + } + return 0.0; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline unsigned vertex_block_storage<T,S,P>::total_vertices() const + { + return m_total_vertices; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline unsigned vertex_block_storage<T,S,P>::vertex(unsigned idx, + double* x, double* y) const + { + unsigned nb = idx >> block_shift; + const T* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1); + *x = pv[0]; + *y = pv[1]; + return m_cmd_blocks[nb][idx & block_mask]; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline unsigned vertex_block_storage<T,S,P>::command(unsigned idx) const + { + return m_cmd_blocks[idx >> block_shift][idx & block_mask]; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + void vertex_block_storage<T,S,P>::allocate_block(unsigned nb) + { + if(nb >= m_max_blocks) + { + T** new_coords = + pod_allocator<T*>::allocate((m_max_blocks + block_pool) * 2); + + unsigned char** new_cmds = + (unsigned char**)(new_coords + m_max_blocks + block_pool); + + if(m_coord_blocks) { + memcpy(new_coords, + m_coord_blocks, + m_max_blocks * sizeof(T*)); + + memcpy(new_cmds, + m_cmd_blocks, + m_max_blocks * sizeof(unsigned char*)); + + pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2); } + m_coord_blocks = new_coords; + m_cmd_blocks = new_cmds; + m_max_blocks += block_pool; + } + m_coord_blocks[nb] = + pod_allocator<T>::allocate(block_size * 2 + + block_size / (sizeof(T) / sizeof(unsigned char))); + + m_cmd_blocks[nb] = + (unsigned char*)(m_coord_blocks[nb] + block_size * 2); + + m_total_blocks++; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + int8u* vertex_block_storage<T,S,P>::storage_ptrs(T** xy_ptr) + { + unsigned nb = m_total_vertices >> block_shift; + if(nb >= m_total_blocks) + { + allocate_block(nb); + } + *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1); + return m_cmd_blocks[nb] + (m_total_vertices & block_mask); + } + + + + + //-----------------------------------------------------poly_plain_adaptor + template<class T> class poly_plain_adaptor + { + public: + typedef T value_type; + + poly_plain_adaptor() : + m_data(0), + m_ptr(0), + m_end(0), + m_closed(false), + m_stop(false) + {} + + poly_plain_adaptor(const T* data, unsigned num_points, bool closed) : + m_data(data), + m_ptr(data), + m_end(data + num_points * 2), + m_closed(closed), + m_stop(false) + {} + + void init(const T* data, unsigned num_points, bool closed) + { + m_data = data; + m_ptr = data; + m_end = data + num_points * 2; + m_closed = closed; + m_stop = false; + } + + void rewind(unsigned) + { + m_ptr = m_data; + m_stop = false; + } - const_iterator(const path_storage& p, unsigned id) : - m_path(&p), - m_vertex_idx(id) + unsigned vertex(double* x, double* y) + { + if(m_ptr < m_end) + { + bool first = m_ptr == m_data; + *x = *m_ptr++; + *y = *m_ptr++; + return first ? path_cmd_move_to : path_cmd_line_to; + } + *x = *y = 0.0; + if(m_closed && !m_stop) { - vertex(); + m_stop = true; + return path_cmd_end_poly | path_flags_close; } + return path_cmd_stop; + } + + private: + const T* m_data; + const T* m_ptr; + const T* m_end; + bool m_closed; + bool m_stop; + }; + + + + + + //-------------------------------------------------poly_container_adaptor + template<class Container> class poly_container_adaptor + { + public: + typedef typename Container::value_type vertex_type; + + poly_container_adaptor() : + m_container(0), + m_index(0), + m_closed(false), + m_stop(false) + {} - const_iterator& operator++() + poly_container_adaptor(const Container& data, bool closed) : + m_container(&data), + m_index(0), + m_closed(closed), + m_stop(false) + {} + + void init(const Container& data, bool closed) + { + m_container = &data; + m_index = 0; + m_closed = closed; + m_stop = false; + } + + void rewind(unsigned) + { + m_index = 0; + m_stop = false; + } + + unsigned vertex(double* x, double* y) + { + if(m_index < m_container->size()) + { + bool first = m_index == 0; + const vertex_type& v = (*m_container)[m_index++]; + *x = v.x; + *y = v.y; + return first ? path_cmd_move_to : path_cmd_line_to; + } + *x = *y = 0.0; + if(m_closed && !m_stop) { - ++m_vertex_idx; - vertex(); - return *this; + m_stop = true; + return path_cmd_end_poly | path_flags_close; } + return path_cmd_stop; + } + + private: + const Container* m_container; + unsigned m_index; + bool m_closed; + bool m_stop; + }; + + + + //-----------------------------------------poly_container_reverse_adaptor + template<class Container> class poly_container_reverse_adaptor + { + public: + typedef typename Container::value_type vertex_type; - const vertex_type& operator*() const { return m_vertex; } - const vertex_type* operator->() const { return &m_vertex; } + poly_container_reverse_adaptor() : + m_container(0), + m_index(-1), + m_closed(false), + m_stop(false) + {} - bool operator != (const const_iterator& i) + poly_container_reverse_adaptor(const Container& data, bool closed) : + m_container(&data), + m_index(-1), + m_closed(closed), + m_stop(false) + {} + + void init(const Container& data, bool closed) + { + m_container = &data; + m_index = m_container->size() - 1; + m_closed = closed; + m_stop = false; + } + + void rewind(unsigned) + { + m_index = m_container->size() - 1; + m_stop = false; + } + + unsigned vertex(double* x, double* y) + { + if(m_index >= 0) + { + bool first = m_index == int(m_container->size() - 1); + const vertex_type& v = (*m_container)[m_index--]; + *x = v.x; + *y = v.y; + return first ? path_cmd_move_to : path_cmd_line_to; + } + *x = *y = 0.0; + if(m_closed && !m_stop) { - return m_vertex.cmd != i.m_vertex.cmd; + m_stop = true; + return path_cmd_end_poly | path_flags_close; } + return path_cmd_stop; + } - private: - const path_storage* m_path; - unsigned m_vertex_idx; - vertex_type m_vertex; - }; + private: + const Container* m_container; + int m_index; + bool m_closed; + bool m_stop; + }; - ~path_storage(); - path_storage(); - path_storage(const path_storage& ps); - void remove_all(); - unsigned last_vertex(double* x, double* y) const; - unsigned prev_vertex(double* x, double* y) const; - void rel_to_abs(double* x, double* y) const; + + //--------------------------------------------------------line_adaptor + class line_adaptor + { + public: + typedef double value_type; + + line_adaptor() : m_line(m_coord, 2, false) {} + line_adaptor(double x1, double y1, double x2, double y2) : + m_line(m_coord, 2, false) + { + m_coord[0] = x1; + m_coord[1] = y1; + m_coord[2] = x2; + m_coord[3] = y2; + } + + void init(double x1, double y1, double x2, double y2) + { + m_coord[0] = x1; + m_coord[1] = y1; + m_coord[2] = x2; + m_coord[3] = y2; + m_line.rewind(0); + } + + void rewind(unsigned) + { + m_line.rewind(0); + } + + unsigned vertex(double* x, double* y) + { + return m_line.vertex(x, y); + } + + private: + double m_coord[4]; + poly_plain_adaptor<double> m_line; + }; + + + + + + + + + + + + + + //---------------------------------------------------------------path_base + // A container to store vertices with their flags. + // A path consists of a number of contours separated with "move_to" + // commands. The path storage can keep and maintain more than one + // path. + // To navigate to the beginning of a particular path, use rewind(path_id); + // Where path_id is what start_new_path() returns. So, when you call + // start_new_path() you need to store its return value somewhere else + // to navigate to the path afterwards. + // + // See also: vertex_source concept + //------------------------------------------------------------------------ + template<class VertexContainer> class path_base + { + public: + typedef VertexContainer container_type; + typedef path_base<VertexContainer> self_type; + + //-------------------------------------------------------------------- + path_base() : m_vertices(), m_iterator(0) {} + void remove_all() { m_vertices.remove_all(); m_iterator = 0; } + void free_all() { m_vertices.free_all(); m_iterator = 0; } + + // Make path functions + //-------------------------------------------------------------------- + unsigned start_new_path(); void move_to(double x, double y); void move_rel(double dx, double dy); @@ -118,6 +626,12 @@ namespace agg void line_to(double x, double y); void line_rel(double dx, double dy); + void hline_to(double x); + void hline_rel(double dx); + + void vline_to(double y); + void vline_rel(double dy); + void arc_to(double rx, double ry, double angle, bool large_arc_flag, @@ -156,209 +670,876 @@ namespace agg void end_poly(unsigned flags = path_flags_close); + void close_polygon(unsigned flags = path_flags_none); - void close_polygon(unsigned flags = path_flags_none) - { - end_poly(path_flags_close | flags); - } + // Accessors + //-------------------------------------------------------------------- + const container_type& vertices() const { return m_vertices; } + container_type& vertices() { return m_vertices; } + + unsigned total_vertices() const; + + void rel_to_abs(double* x, double* y) const; + + unsigned last_vertex(double* x, double* y) const; + unsigned prev_vertex(double* x, double* y) const; - void add_poly(const double* vertices, unsigned num, - bool solid_path = false, - unsigned end_flags = path_flags_none); + double last_x() const; + double last_y() const; + unsigned vertex(unsigned idx, double* x, double* y) const; + unsigned command(unsigned idx) const; + + void modify_vertex(unsigned idx, double x, double y); + void modify_vertex(unsigned idx, double x, double y, unsigned cmd); + void modify_command(unsigned idx, unsigned cmd); + + // VertexSource interface + //-------------------------------------------------------------------- + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + // Arrange the orientation of a polygon, all polygons in a path, + // or in all paths. After calling arrange_orientations() or + // arrange_orientations_all_paths(), all the polygons will have + // the same orientation, i.e. path_flags_cw or path_flags_ccw + //-------------------------------------------------------------------- + unsigned arrange_polygon_orientation(unsigned start, path_flags_e orientation); + unsigned arrange_orientations(unsigned path_id, path_flags_e orientation); + void arrange_orientations_all_paths(path_flags_e orientation); + void invert_polygon(unsigned start); + + // Flip all vertices horizontally or vertically, + // between x1 and x2, or between y1 and y2 respectively + //-------------------------------------------------------------------- + void flip_x(double x1, double x2); + void flip_y(double y1, double y2); + + // Concatenate path. The path is added as is. + //-------------------------------------------------------------------- template<class VertexSource> - void add_path(VertexSource& vs, - unsigned path_id = 0, - bool solid_path = true) + void concat_path(VertexSource& vs, unsigned path_id = 0) { double x, y; unsigned cmd; vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x, &y))) { - if(is_move_to(cmd) && solid_path && m_total_vertices) + m_vertices.add_vertex(x, y, cmd); + } + } + + //-------------------------------------------------------------------- + // Join path. The path is joined with the existing one, that is, + // it behaves as if the pen of a plotter was always down (drawing) + template<class VertexSource> + void join_path(VertexSource& vs, unsigned path_id = 0) + { + double x, y; + unsigned cmd; + vs.rewind(path_id); + cmd = vs.vertex(&x, &y); + if(!is_stop(cmd)) + { + if(is_vertex(cmd)) + { + double x0, y0; + unsigned cmd0 = last_vertex(&x0, &y0); + if(is_vertex(cmd0)) + { + if(calc_distance(x, y, x0, y0) > vertex_dist_epsilon) + { + if(is_move_to(cmd)) cmd = path_cmd_line_to; + m_vertices.add_vertex(x, y, cmd); + } + } + else + { + if(is_stop(cmd0)) + { + cmd = path_cmd_move_to; + } + else + { + if(is_move_to(cmd)) cmd = path_cmd_line_to; + } + m_vertices.add_vertex(x, y, cmd); + } + } + while(!is_stop(cmd = vs.vertex(&x, &y))) { - cmd = path_cmd_line_to; + m_vertices.add_vertex(x, y, is_move_to(cmd) ? + unsigned(path_cmd_line_to) : + cmd); } - add_vertex(x, y, cmd); } } - unsigned start_new_path(); + // Concatenate polygon/polyline. + //-------------------------------------------------------------------- + template<class T> void concat_poly(const T* data, + unsigned num_points, + bool closed) + { + poly_plain_adaptor<T> poly(data, num_points, closed); + concat_path(poly); + } - void copy_from(const path_storage& ps); - const path_storage& operator = (const path_storage& ps) + // Join polygon/polyline continuously. + //-------------------------------------------------------------------- + template<class T> void join_poly(const T* data, + unsigned num_points, + bool closed) { - copy_from(ps); - return *this; + poly_plain_adaptor<T> poly(data, num_points, closed); + join_path(poly); } + //-------------------------------------------------------------------- + void translate(double dx, double dy, unsigned path_id=0); + void translate_all_paths(double dx, double dy); - unsigned total_vertices() const { return m_total_vertices; } - unsigned vertex(unsigned idx, double* x, double* y) const + //-------------------------------------------------------------------- + template<class Trans> + void transform(const Trans& trans, unsigned path_id=0) { - unsigned nb = idx >> block_shift; - const double* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1); - *x = *pv++; - *y = *pv; - return m_cmd_blocks[nb][idx & block_mask]; + 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); + } + } } - unsigned command(unsigned idx) const + + //-------------------------------------------------------------------- + template<class Trans> + void transform_all_paths(const Trans& trans) { - return m_cmd_blocks[idx >> block_shift][idx & block_mask]; + 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); + } + } } - void rewind(unsigned path_id); - unsigned vertex(double* x, double* y); - const_iterator begin(unsigned id) const { return const_iterator(*this, id); } - const_iterator begin() const { return const_iterator(*this, 0); } - const_iterator end() const { return const_iterator(path_cmd_stop); } - // Arrange the orientation of all the polygons. After calling this - // method all the polygons will have the same orientation - // determined by the new_orientation flag, i.e., - // path_flags_cw or path_flags_ccw - unsigned arrange_orientations(unsigned path_id, path_flags_e new_orientation); - void arrange_orientations_all_paths(path_flags_e new_orientation); - - // Flip all the vertices horizontally or vertically - void flip_x(double x1, double x2); - void flip_y(double y1, double y2); + private: + unsigned perceive_polygon_orientation(unsigned start, unsigned end); + void invert_polygon(unsigned start, unsigned end); - // This function adds a vertex with its flags directly. Since there's no - // checking for errors, keeping proper path integrity is the responsibility - // of the caller. It can be said the function is "not very public". - void add_vertex(double x, double y, unsigned cmd); + VertexContainer m_vertices; + unsigned m_iterator; + }; - // Allows you to modify vertex coordinates. The caller must know - // the index of the vertex. - void modify_vertex(unsigned idx, double x, double y) + //------------------------------------------------------------------------ + template<class VC> + unsigned path_base<VC>::start_new_path() + { + if(!is_stop(m_vertices.last_command())) { - double* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1); - *pv++ = x; - *pv = y; + m_vertices.add_vertex(0.0, 0.0, path_cmd_stop); } + return m_vertices.total_vertices(); + } - // Allows you to modify vertex command. The caller must know - // the index of the vertex. - void modify_command(unsigned idx, unsigned cmd) + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::rel_to_abs(double* x, double* y) const + { + if(m_vertices.total_vertices()) { - m_cmd_blocks[idx >> block_shift][idx & block_mask] = (unsigned char)cmd; + double x2; + double y2; + if(is_vertex(m_vertices.last_vertex(&x2, &y2))) + { + *x += x2; + *y += y2; + } } + } + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::move_to(double x, double y) + { + m_vertices.add_vertex(x, y, path_cmd_move_to); + } - private: - void allocate_block(unsigned nb); - unsigned char* storage_ptrs(double** xy_ptr); - unsigned perceive_polygon_orientation(unsigned idx, - double xs, double ys, - unsigned* orientation); - void reverse_polygon(unsigned start, unsigned end); + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::move_rel(double dx, double dy) + { + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_move_to); + } - private: - unsigned m_total_vertices; - unsigned m_total_blocks; - unsigned m_max_blocks; - double** m_coord_blocks; - unsigned char** m_cmd_blocks; - unsigned m_iterator; - }; + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::line_to(double x, double y) + { + m_vertices.add_vertex(x, y, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::line_rel(double dx, double dy) + { + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_line_to); + } + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::hline_to(double x) + { + m_vertices.add_vertex(x, last_y(), path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::hline_rel(double dx) + { + double dy = 0; + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_line_to); + } //------------------------------------------------------------------------ - inline unsigned path_storage::vertex(double* x, double* y) + template<class VC> + inline void path_base<VC>::vline_to(double y) { - if(m_iterator >= m_total_vertices) return path_cmd_stop; - return vertex(m_iterator++, x, y); + m_vertices.add_vertex(last_x(), y, path_cmd_line_to); } //------------------------------------------------------------------------ - inline unsigned path_storage::prev_vertex(double* x, double* y) const + template<class VC> + inline void path_base<VC>::vline_rel(double dy) { - if(m_total_vertices > 1) + double dx = 0; + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::arc_to(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x, double y) + { + if(m_vertices.total_vertices() && is_vertex(m_vertices.last_command())) { - return vertex(m_total_vertices - 2, x, y); + const double epsilon = 1e-30; + double x0 = 0.0; + double y0 = 0.0; + m_vertices.last_vertex(&x0, &y0); + + rx = fabs(rx); + ry = fabs(ry); + + // Ensure radii are valid + //------------------------- + if(rx < epsilon || ry < epsilon) + { + line_to(x, y); + return; + } + + if(calc_distance(x0, y0, x, y) < epsilon) + { + // If the endpoints (x, y) and (x0, y0) are identical, then this + // is equivalent to omitting the elliptical arc segment entirely. + return; + } + bezier_arc_svg a(x0, y0, rx, ry, angle, large_arc_flag, sweep_flag, x, y); + if(a.radii_ok()) + { + join_path(a); + } + else + { + line_to(x, y); + } + } + else + { + move_to(x, y); } - return path_cmd_stop; } //------------------------------------------------------------------------ - inline unsigned path_storage::last_vertex(double* x, double* y) const + template<class VC> + void path_base<VC>::arc_rel(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double dx, double dy) { - if(m_total_vertices) + rel_to_abs(&dx, &dy); + arc_to(rx, ry, angle, large_arc_flag, sweep_flag, dx, dy); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve3(double x_ctrl, double y_ctrl, + double x_to, double y_to) + { + m_vertices.add_vertex(x_ctrl, y_ctrl, path_cmd_curve3); + m_vertices.add_vertex(x_to, y_to, path_cmd_curve3); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve3_rel(double dx_ctrl, double dy_ctrl, + double dx_to, double dy_to) + { + rel_to_abs(&dx_ctrl, &dy_ctrl); + rel_to_abs(&dx_to, &dy_to); + m_vertices.add_vertex(dx_ctrl, dy_ctrl, path_cmd_curve3); + m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve3); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve3(double x_to, double y_to) + { + double x0; + double y0; + if(is_vertex(m_vertices.last_vertex(&x0, &y0))) { - return vertex(m_total_vertices - 1, x, y); + double x_ctrl; + double y_ctrl; + unsigned cmd = m_vertices.prev_vertex(&x_ctrl, &y_ctrl); + if(is_curve(cmd)) + { + x_ctrl = x0 + x0 - x_ctrl; + y_ctrl = y0 + y0 - y_ctrl; + } + else + { + x_ctrl = x0; + y_ctrl = y0; + } + curve3(x_ctrl, y_ctrl, x_to, y_to); } - return path_cmd_stop; } //------------------------------------------------------------------------ - inline void path_storage::rel_to_abs(double* x, double* y) const + template<class VC> + void path_base<VC>::curve3_rel(double dx_to, double dy_to) { - if(m_total_vertices) + rel_to_abs(&dx_to, &dy_to); + curve3(dx_to, dy_to); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve4(double x_ctrl1, double y_ctrl1, + double x_ctrl2, double y_ctrl2, + double x_to, double y_to) + { + m_vertices.add_vertex(x_ctrl1, y_ctrl1, path_cmd_curve4); + m_vertices.add_vertex(x_ctrl2, y_ctrl2, path_cmd_curve4); + m_vertices.add_vertex(x_to, y_to, path_cmd_curve4); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve4_rel(double dx_ctrl1, double dy_ctrl1, + double dx_ctrl2, double dy_ctrl2, + double dx_to, double dy_to) + { + rel_to_abs(&dx_ctrl1, &dy_ctrl1); + rel_to_abs(&dx_ctrl2, &dy_ctrl2); + rel_to_abs(&dx_to, &dy_to); + m_vertices.add_vertex(dx_ctrl1, dy_ctrl1, path_cmd_curve4); + m_vertices.add_vertex(dx_ctrl2, dy_ctrl2, path_cmd_curve4); + m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve4); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve4(double x_ctrl2, double y_ctrl2, + double x_to, double y_to) + { + double x0; + double y0; + if(is_vertex(last_vertex(&x0, &y0))) { - double x2; - double y2; - if(is_vertex(vertex(m_total_vertices - 1, &x2, &y2))) + double x_ctrl1; + double y_ctrl1; + unsigned cmd = prev_vertex(&x_ctrl1, &y_ctrl1); + if(is_curve(cmd)) { - *x += x2; - *y += y2; + x_ctrl1 = x0 + x0 - x_ctrl1; + y_ctrl1 = y0 + y0 - y_ctrl1; } + else + { + x_ctrl1 = x0; + y_ctrl1 = y0; + } + curve4(x_ctrl1, y_ctrl1, x_ctrl2, y_ctrl2, x_to, y_to); } } //------------------------------------------------------------------------ - inline unsigned char* path_storage::storage_ptrs(double** xy_ptr) + template<class VC> + void path_base<VC>::curve4_rel(double dx_ctrl2, double dy_ctrl2, + double dx_to, double dy_to) { - unsigned nb = m_total_vertices >> block_shift; - if(nb >= m_total_blocks) + rel_to_abs(&dx_ctrl2, &dy_ctrl2); + rel_to_abs(&dx_to, &dy_to); + curve4(dx_ctrl2, dy_ctrl2, dx_to, dy_to); + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::end_poly(unsigned flags) + { + if(is_vertex(m_vertices.last_command())) { - allocate_block(nb); + m_vertices.add_vertex(0.0, 0.0, path_cmd_end_poly | flags); } - *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1); - return m_cmd_blocks[nb] + (m_total_vertices & block_mask); } + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::close_polygon(unsigned flags) + { + end_poly(path_flags_close | flags); + } //------------------------------------------------------------------------ - inline void path_storage::add_vertex(double x, double y, unsigned cmd) + template<class VC> + inline unsigned path_base<VC>::total_vertices() const { - double* coord_ptr = 0; - unsigned char* cmd_ptr = storage_ptrs(&coord_ptr); - *cmd_ptr = (unsigned char)cmd; - *coord_ptr++ = x; - *coord_ptr = y; - m_total_vertices++; + return m_vertices.total_vertices(); } //------------------------------------------------------------------------ - inline void path_storage::move_to(double x, double y) + template<class VC> + inline unsigned path_base<VC>::last_vertex(double* x, double* y) const { - add_vertex(x, y, path_cmd_move_to); + return m_vertices.last_vertex(x, y); } //------------------------------------------------------------------------ - inline void path_storage::move_rel(double dx, double dy) + template<class VC> + inline unsigned path_base<VC>::prev_vertex(double* x, double* y) const { - rel_to_abs(&dx, &dy); - add_vertex(dx, dy, path_cmd_move_to); + return m_vertices.prev_vertex(x, y); } //------------------------------------------------------------------------ - inline void path_storage::line_to(double x, double y) + template<class VC> + inline double path_base<VC>::last_x() const { - add_vertex(x, y, path_cmd_line_to); + return m_vertices.last_x(); } //------------------------------------------------------------------------ - inline void path_storage::line_rel(double dx, double dy) + template<class VC> + inline double path_base<VC>::last_y() const { - rel_to_abs(&dx, &dy); - add_vertex(dx, dy, path_cmd_line_to); + return m_vertices.last_y(); + } + + //------------------------------------------------------------------------ + template<class VC> + inline unsigned path_base<VC>::vertex(unsigned idx, double* x, double* y) const + { + return m_vertices.vertex(idx, x, y); + } + + //------------------------------------------------------------------------ + template<class VC> + inline unsigned path_base<VC>::command(unsigned idx) const + { + return m_vertices.command(idx); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::modify_vertex(unsigned idx, double x, double y) + { + m_vertices.modify_vertex(idx, x, y); } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::modify_vertex(unsigned idx, double x, double y, unsigned cmd) + { + m_vertices.modify_vertex(idx, x, y, cmd); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::modify_command(unsigned idx, unsigned cmd) + { + m_vertices.modify_command(idx, cmd); + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::rewind(unsigned path_id) + { + m_iterator = path_id; + } + + //------------------------------------------------------------------------ + template<class VC> + inline unsigned path_base<VC>::vertex(double* x, double* y) + { + if(m_iterator >= m_vertices.total_vertices()) return path_cmd_stop; + return m_vertices.vertex(m_iterator++, x, y); + } + + //------------------------------------------------------------------------ + template<class VC> + unsigned path_base<VC>::perceive_polygon_orientation(unsigned start, + unsigned end) + { + // Calculate signed area (double area to be exact) + //--------------------- + unsigned np = end - start; + double area = 0.0; + unsigned i; + for(i = 0; i < np; i++) + { + double x1, y1, x2, y2; + m_vertices.vertex(start + i, &x1, &y1); + m_vertices.vertex(start + (i + 1) % np, &x2, &y2); + area += x1 * y2 - y1 * x2; + } + return (area < 0.0) ? path_flags_cw : path_flags_ccw; + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::invert_polygon(unsigned start, unsigned end) + { + unsigned i; + unsigned tmp_cmd = m_vertices.command(start); + + --end; // Make "end" inclusive + + // Shift all commands to one position + for(i = start; i < end; i++) + { + m_vertices.modify_command(i, m_vertices.command(i + 1)); + } + + // Assign starting command to the ending command + m_vertices.modify_command(end, tmp_cmd); + + // Reverse the polygon + while(end > start) + { + m_vertices.swap_vertices(start++, end--); + } + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::invert_polygon(unsigned start) + { + // Skip all non-vertices at the beginning + while(start < m_vertices.total_vertices() && + !is_vertex(m_vertices.command(start))) ++start; + + // Skip all insignificant move_to + while(start+1 < m_vertices.total_vertices() && + is_move_to(m_vertices.command(start)) && + is_move_to(m_vertices.command(start+1))) ++start; + + // Find the last vertex + unsigned end = start + 1; + while(end < m_vertices.total_vertices() && + !is_next_poly(m_vertices.command(end))) ++end; + + invert_polygon(start, end); + } + + //------------------------------------------------------------------------ + template<class VC> + unsigned path_base<VC>::arrange_polygon_orientation(unsigned start, + path_flags_e orientation) + { + if(orientation == path_flags_none) return start; + + // Skip all non-vertices at the beginning + while(start < m_vertices.total_vertices() && + !is_vertex(m_vertices.command(start))) ++start; + + // Skip all insignificant move_to + while(start+1 < m_vertices.total_vertices() && + is_move_to(m_vertices.command(start)) && + is_move_to(m_vertices.command(start+1))) ++start; + + // Find the last vertex + unsigned end = start + 1; + while(end < m_vertices.total_vertices() && + !is_next_poly(m_vertices.command(end))) ++end; + + if(end - start > 2) + { + if(perceive_polygon_orientation(start, end) != unsigned(orientation)) + { + // Invert polygon, set orientation flag, and skip all end_poly + invert_polygon(start, end); + unsigned cmd; + while(end < m_vertices.total_vertices() && + is_end_poly(cmd = m_vertices.command(end))) + { + m_vertices.modify_command(end++, set_orientation(cmd, orientation)); + } + } + } + return end; + } + + //------------------------------------------------------------------------ + template<class VC> + unsigned path_base<VC>::arrange_orientations(unsigned start, + path_flags_e orientation) + { + if(orientation != path_flags_none) + { + while(start < m_vertices.total_vertices()) + { + start = arrange_polygon_orientation(start, orientation); + if(is_stop(m_vertices.command(start))) + { + ++start; + break; + } + } + } + return start; + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::arrange_orientations_all_paths(path_flags_e orientation) + { + if(orientation != path_flags_none) + { + unsigned start = 0; + while(start < m_vertices.total_vertices()) + { + start = arrange_orientations(start, orientation); + } + } + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::flip_x(double x1, double x2) + { + unsigned i; + double x, y; + for(i = 0; i < m_vertices.total_vertices(); i++) + { + unsigned cmd = m_vertices.vertex(i, &x, &y); + if(is_vertex(cmd)) + { + m_vertices.modify_vertex(i, x2 - x + x1, y); + } + } + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::flip_y(double y1, double y2) + { + unsigned i; + double x, y; + for(i = 0; i < m_vertices.total_vertices(); i++) + { + unsigned cmd = m_vertices.vertex(i, &x, &y); + if(is_vertex(cmd)) + { + m_vertices.modify_vertex(i, x, y2 - y + y1); + } + } + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::translate(double dx, double dy, unsigned path_id) + { + unsigned num_ver = m_vertices.total_vertices(); + for(; path_id < num_ver; path_id++) + { + double x, y; + unsigned cmd = m_vertices.vertex(path_id, &x, &y); + if(is_stop(cmd)) break; + if(is_vertex(cmd)) + { + x += dx; + y += dy; + m_vertices.modify_vertex(path_id, x, y); + } + } + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::translate_all_paths(double dx, double dy) + { + unsigned idx; + unsigned num_ver = m_vertices.total_vertices(); + for(idx = 0; idx < num_ver; idx++) + { + double x, y; + if(is_vertex(m_vertices.vertex(idx, &x, &y))) + { + x += dx; + y += dy; + m_vertices.modify_vertex(idx, x, y); + } + } + } + + //-----------------------------------------------------vertex_stl_storage + template<class Container> class vertex_stl_storage + { + public: + typedef typename Container::value_type vertex_type; + typedef typename vertex_type::value_type value_type; + + void remove_all() { m_vertices.clear(); } + void free_all() { m_vertices.clear(); } + + void add_vertex(double x, double y, unsigned cmd) + { + m_vertices.push_back(vertex_type(value_type(x), + value_type(y), + int8u(cmd))); + } + + void modify_vertex(unsigned idx, double x, double y) + { + vertex_type& v = m_vertices[idx]; + v.x = value_type(x); + v.y = value_type(y); + } + + void modify_vertex(unsigned idx, double x, double y, unsigned cmd) + { + vertex_type& v = m_vertices[idx]; + v.x = value_type(x); + v.y = value_type(y); + v.cmd = int8u(cmd); + } + + void modify_command(unsigned idx, unsigned cmd) + { + m_vertices[idx].cmd = int8u(cmd); + } + + void swap_vertices(unsigned v1, unsigned v2) + { + vertex_type t = m_vertices[v1]; + m_vertices[v1] = m_vertices[v2]; + m_vertices[v2] = t; + } + + unsigned last_command() const + { + return m_vertices.size() ? + m_vertices[m_vertices.size() - 1].cmd : + path_cmd_stop; + } + + unsigned last_vertex(double* x, double* y) const + { + if(m_vertices.size() == 0) + { + *x = *y = 0.0; + return path_cmd_stop; + } + return vertex(m_vertices.size() - 1, x, y); + } + + unsigned prev_vertex(double* x, double* y) const + { + if(m_vertices.size() < 2) + { + *x = *y = 0.0; + return path_cmd_stop; + } + return vertex(m_vertices.size() - 2, x, y); + } + + double last_x() const + { + return m_vertices.size() ? m_vertices[m_vertices.size() - 1].x : 0.0; + } + + double last_y() const + { + return m_vertices.size() ? m_vertices[m_vertices.size() - 1].y : 0.0; + } + + unsigned total_vertices() const + { + return m_vertices.size(); + } + + unsigned vertex(unsigned idx, double* x, double* y) const + { + const vertex_type& v = m_vertices[idx]; + *x = v.x; + *y = v.y; + return v.cmd; + } + + unsigned command(unsigned idx) const + { + return m_vertices[idx].cmd; + } + + private: + Container m_vertices; + }; + + //-----------------------------------------------------------path_storage + typedef path_base<vertex_block_storage<double> > path_storage; + + // Example of declarations path_storage with pod_bvector as a container + //----------------------------------------------------------------------- + //typedef path_base<vertex_stl_storage<pod_bvector<vertex_d> > > path_storage; + } +// Example of declarations path_storage with std::vector as a container +//--------------------------------------------------------------------------- +//#include <vector> +//namespace agg +//{ +// typedef path_base<vertex_stl_storage<std::vector<vertex_d> > > stl_path_storage; +//} + + + + #endif diff --git a/agg/inc/agg_path_storage_integer.h b/agg/inc/agg_path_storage_integer.h index 841bd10aa27a..7254522c2570 100755 --- a/agg/inc/agg_path_storage_integer.h +++ b/agg/inc/agg_path_storage_integer.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -21,7 +21,6 @@ namespace agg { - //---------------------------------------------------------vertex_integer template<class T, unsigned CoordShift=6> struct vertex_integer { @@ -33,10 +32,10 @@ namespace agg cmd_curve4 = 3 }; - enum + enum coord_scale_e { coord_shift = CoordShift, - coord_mult = 1 << coord_shift + coord_scale = 1 << coord_shift }; T x,y; @@ -49,8 +48,8 @@ namespace agg double dx=0, double dy=0, double scale=1.0) const { - *x_ = dx + (double(x >> 1) / coord_mult) * scale; - *y_ = dy + (double(y >> 1) / coord_mult) * scale; + *x_ = dx + (double(x >> 1) / coord_scale) * scale; + *y_ = dy + (double(y >> 1) / coord_scale) * scale; switch(((y & 1) << 1) | (x & 1)) { case cmd_move_to: return path_cmd_move_to; @@ -67,6 +66,7 @@ namespace agg template<class T, unsigned CoordShift=6> class path_storage_integer { public: + typedef T value_type; typedef vertex_integer<T, CoordShift> vertex_integer_type; //-------------------------------------------------------------------- @@ -110,12 +110,9 @@ namespace agg //-------------------------------------------------------------------- unsigned size() const { return m_storage.size(); } - unsigned vertex(unsigned idx, T* x, T* y) const + unsigned vertex(unsigned idx, double* x, double* y) const { - const vertex_integer_type& v = m_storage[idx]; - *x = v.x >> 1; - *y = v.y >> 1; - return ((v.y & 1) << 1) | (v.x & 1); + return m_storage[idx].vertex(x, y); } //-------------------------------------------------------------------- @@ -130,7 +127,6 @@ namespace agg } } - //-------------------------------------------------------------------- void rewind(unsigned) { @@ -191,11 +187,10 @@ namespace agg return bounds; } - private: - pod_deque<vertex_integer_type, 6> m_storage; - unsigned m_vertex_idx; - bool m_closed; + pod_bvector<vertex_integer_type, 6> m_storage; + unsigned m_vertex_idx; + bool m_closed; }; diff --git a/agg/inc/agg_pattern_filters_rgba.h b/agg/inc/agg_pattern_filters_rgba.h index 5d194b2e39ba..7e686f1851a7 100755 --- a/agg/inc/agg_pattern_filters_rgba.h +++ b/agg/inc/agg_pattern_filters_rgba.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -67,7 +67,7 @@ namespace agg color_type* p, int x, int y) { calc_type r, g, b, a; - r = g = b = a = line_subpixel_size * line_subpixel_size / 2; + r = g = b = a = line_subpixel_scale * line_subpixel_scale / 2; calc_type weight; int x_lr = x >> line_subpixel_shift; @@ -77,8 +77,8 @@ namespace agg y &= line_subpixel_mask; const color_type* ptr = buf[y_lr] + x_lr; - weight = (line_subpixel_size - x) * - (line_subpixel_size - y); + weight = (line_subpixel_scale - x) * + (line_subpixel_scale - y); r += weight * ptr->r; g += weight * ptr->g; b += weight * ptr->b; @@ -86,7 +86,7 @@ namespace agg ++ptr; - weight = x * (line_subpixel_size - y); + weight = x * (line_subpixel_scale - y); r += weight * ptr->r; g += weight * ptr->g; b += weight * ptr->b; @@ -94,7 +94,7 @@ namespace agg ptr = buf[y_lr + 1] + x_lr; - weight = (line_subpixel_size - x) * y; + weight = (line_subpixel_scale - x) * y; r += weight * ptr->r; g += weight * ptr->g; b += weight * ptr->b; diff --git a/agg/inc/agg_pixfmt_amask_adaptor.h b/agg/inc/agg_pixfmt_amask_adaptor.h index 7f3d5899b1c6..454e1417054e 100755 --- a/agg/inc/agg_pixfmt_amask_adaptor.h +++ b/agg/inc/agg_pixfmt_amask_adaptor.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -18,6 +18,7 @@ #include <string.h> +#include "agg_array.h" #include "agg_rendering_buffer.h" @@ -29,47 +30,50 @@ namespace agg public: typedef PixFmt pixfmt_type; typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; typedef AlphaMask amask_type; typedef typename amask_type::cover_type cover_type; private: - enum { span_extra_tail = 256 }; + enum span_extra_tail_e { span_extra_tail = 256 }; void realloc_span(unsigned len) { - if(len > m_max_len) + if(len > m_span.size()) { - delete [] m_span; - m_span = new cover_type[m_max_len = len + span_extra_tail]; + m_span.resize(len + span_extra_tail); } } void init_span(unsigned len) { realloc_span(len); - - // ATTN! May work incorrectly if cover_type is more that one byte - memset(m_span, amask_type::cover_full, len * sizeof(cover_type)); + memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type)); } void init_span(unsigned len, const cover_type* covers) { realloc_span(len); - memcpy(m_span, covers, len * sizeof(cover_type)); + memcpy(&m_span[0], covers, len * sizeof(cover_type)); } public: - ~pixfmt_amask_adaptor() { delete [] m_span; } - pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) : - m_pixf(&pixf), m_mask(&mask), m_span(0), m_max_len(0) + m_pixf(&pixf), m_mask(&mask), m_span() {} void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; } void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; } //-------------------------------------------------------------------- + template<class PixFmt2> + bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2) + { + return m_pixf->attach(pixf, x1, y1, x2, y2); + } + + //-------------------------------------------------------------------- unsigned width() const { return m_pixf->width(); } unsigned height() const { return m_pixf->height(); } @@ -97,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]); } //-------------------------------------------------------------------- @@ -108,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]); } //-------------------------------------------------------------------- @@ -118,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]); } //-------------------------------------------------------------------- @@ -129,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]); } //-------------------------------------------------------------------- @@ -150,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]); } @@ -162,10 +166,26 @@ 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]); + } + + + //-------------------------------------------------------------------- + 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[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, @@ -177,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); } @@ -198,65 +218,20 @@ namespace agg if(covers) { init_span(len, covers); - m_mask->combine_vspan(x, y, m_span, len); - } - else - { - realloc_span(len); - m_mask->fill_vspan(x, y, m_span, len); - } - m_pixf->blend_color_vspan(x, y, len, colors, m_span, cover); - } - - - //-------------------------------------------------------------------- - void blend_opaque_color_hspan(int x, int y, - unsigned len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - if(covers) - { - init_span(len, covers); - m_mask->combine_hspan(x, y, m_span, len); - } - else - { - realloc_span(len); - m_mask->fill_hspan(x, y, m_span, len); - } - m_pixf->blend_opaque_color_hspan(x, y, len, colors, m_span, cover); - } - - - //-------------------------------------------------------------------- - void blend_opaque_color_vspan(int x, int y, - unsigned len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - 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_opaque_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<cover_type> m_span; }; } diff --git a/agg/inc/agg_pixfmt_gray.h b/agg/inc/agg_pixfmt_gray.h index 48f47d1de32e..32774e140b57 100755 --- a/agg/inc/agg_pixfmt_gray.h +++ b/agg/inc/agg_pixfmt_gray.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -38,10 +38,10 @@ namespace agg typedef ColorT color_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum { base_shift = color_type::base_shift }; + enum base_scale_e { base_shift = color_type::base_shift }; static AGG_INLINE void blend_pix(value_type* p, unsigned cv, - unsigned alpha, unsigned) + unsigned alpha, unsigned cover=0) { *p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift); } @@ -54,7 +54,7 @@ namespace agg typedef ColorT color_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum { base_shift = color_type::base_shift }; + enum base_scale_e { base_shift = color_type::base_shift }; static AGG_INLINE void blend_pix(value_type* p, unsigned cv, unsigned alpha, unsigned cover) @@ -63,6 +63,12 @@ namespace agg cover = (cover + 1) << (base_shift - 8); *p = (value_type)((*p * alpha + cv * cover) >> base_shift); } + + static AGG_INLINE void blend_pix(value_type* p, unsigned cv, + unsigned alpha) + { + *p = (value_type)(((*p * (color_type::base_mask - alpha)) >> base_shift) + cv); + } }; @@ -105,20 +111,26 @@ namespace agg - //======================================================pixel_formats_gray - template<class Blender, unsigned Step=1, unsigned Offset=0> - class pixel_formats_gray + //=================================================pixfmt_alpha_blend_gray + template<class Blender, class RenBuf, unsigned Step=1, unsigned Offset=0> + class pixfmt_alpha_blend_gray { public: - typedef rendering_buffer::row_data row_data; - typedef typename Blender::color_type color_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef int order_type; // A fake one + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e { base_shift = color_type::base_shift, - base_size = color_type::base_size, - base_mask = color_type::base_mask + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(value_type), + pix_step = Step, + pix_offset = Offset }; private: @@ -141,59 +153,94 @@ namespace agg } } - //-------------------------------------------------------------------- - static AGG_INLINE void copy_or_blend_opaque_pix(value_type* p, - const color_type& c, - unsigned cover) + + static AGG_INLINE void copy_or_blend_pix(value_type* p, + const color_type& c) { - if(cover == 255) - { - *p = c.v; - } - else + if (c.a) { - Blender::blend_pix(p, c.v, (cover + 1) << (base_shift - 8), cover); + if(c.a == base_mask) + { + *p = c.v; + } + else + { + Blender::blend_pix(p, c.v, c.a); + } } } + public: //-------------------------------------------------------------------- - pixel_formats_gray(rendering_buffer& rb) : + explicit pixfmt_alpha_blend_gray(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + //-------------------------------------------------------------------- + template<class PixFmt> + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } //-------------------------------------------------------------------- AGG_INLINE unsigned width() const { return m_rbuf->width(); } AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } //-------------------------------------------------------------------- - AGG_INLINE color_type pixel(int x, int y) const + int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + row_data row(int y) const { return m_rbuf->row(y); } + + const int8u* pix_ptr(int x, int y) const { - value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; - return color_type(*p); + return m_rbuf->row_ptr(y) + x * Step + Offset; + } + + int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * Step + Offset; + } + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + *(value_type*)p = c.v; } //-------------------------------------------------------------------- - row_data span(int x, int y) const + AGG_INLINE color_type pixel(int x, int y) const { - return row_data(x, - width() - 1, - m_rbuf->row(y) + - x * Step * sizeof(value_type) + - Offset * sizeof(value_type)); + value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset; + return color_type(*p); } //-------------------------------------------------------------------- AGG_INLINE void copy_pixel(int x, int y, const color_type& c) { - *((value_type*)m_rbuf->row(y) + x * Step + Offset) = c.v; + *((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v; } //-------------------------------------------------------------------- AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) { - copy_or_blend_pix((value_type*)m_rbuf->row(y) + x * Step + Offset, c, cover); + copy_or_blend_pix((value_type*) + m_rbuf->row_ptr(x, y, 1) + x * Step + Offset, + c, + cover); } @@ -202,7 +249,9 @@ namespace agg unsigned len, const color_type& c) { - value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + do { *p = c.v; @@ -217,11 +266,12 @@ namespace agg unsigned len, const color_type& c) { - value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; do { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + *p = c.v; - p = (value_type*)m_rbuf->next_row(p); } while(--len); } @@ -235,7 +285,9 @@ namespace agg { if (c.a) { - value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { @@ -267,14 +319,16 @@ namespace agg { if (c.a) { - value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; + value_type* p; calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { do { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + *p = c.v; - p = (value_type*)m_rbuf->next_row(p); } while(--len); } @@ -282,8 +336,10 @@ namespace agg { do { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + Blender::blend_pix(p, c.v, alpha, cover); - p = (value_type*)m_rbuf->next_row(p); } while(--len); } @@ -299,7 +355,9 @@ namespace agg { if (c.a) { - value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + do { calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; @@ -327,10 +385,13 @@ namespace agg { if (c.a) { - value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; do { calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + if(alpha == base_mask) { *p = c.v; @@ -339,7 +400,6 @@ namespace agg { Blender::blend_pix(p, c.v, alpha, *covers); } - p = (value_type*)m_rbuf->next_row(p); ++covers; } while(--len); @@ -348,13 +408,49 @@ namespace agg //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + + do + { + *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, unsigned len, const color_type* colors, const int8u* covers, int8u cover) { - value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + if(covers) { do @@ -376,7 +472,7 @@ namespace agg } else { - copy_or_blend_pix(p, *colors, 255); + copy_or_blend_pix(p, *colors); } p += Step; ++colors; @@ -404,13 +500,15 @@ namespace agg const int8u* covers, int8u cover) { - value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; + value_type* p; if(covers) { do { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + copy_or_blend_pix(p, *colors++, *covers++); - p = (value_type*)m_rbuf->next_row(p); } while(--len); } @@ -420,15 +518,17 @@ namespace agg { do { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + if(colors->a == base_mask) { *p = colors->v; } else { - copy_or_blend_pix(p, *colors, 255); + copy_or_blend_pix(p, *colors); } - p = (value_type*)m_rbuf->next_row(p); ++colors; } while(--len); @@ -437,8 +537,10 @@ namespace agg { do { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + copy_or_blend_pix(p, *colors++, cover); - p = (value_type*)m_rbuf->next_row(p); } while(--len); } @@ -446,39 +548,22 @@ namespace agg } //-------------------------------------------------------------------- - void blend_opaque_color_hspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) + template<class Function> void for_each_pixel(Function f) { - value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; - if(covers) - { - do - { - copy_or_blend_opaque_pix(p, *colors++, *covers++); - p += Step; - } - while(--len); - } - else + unsigned y; + for(y = 0; y < height(); ++y) { - if(cover == 255) - { - do - { - *p = colors->v; - p += Step; - ++colors; - } - while(--len); - } - else + row_data r = m_rbuf->row(y); + if(r.ptr) { + unsigned len = r.x2 - r.x1 + 1; + + value_type* p = (value_type*) + m_rbuf->row_ptr(r.x1, y, len) + r.x1 * Step + Offset; + do { - copy_or_blend_opaque_pix(p, *colors++, cover); + f(p); p += Step; } while(--len); @@ -486,90 +571,88 @@ namespace agg } } + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_gray<color_type, GammaLut>(g)); + } + + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_gray<color_type, GammaLut>(g)); + } //-------------------------------------------------------------------- - void blend_opaque_color_vspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) + template<class RenBuf2> + void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) { - value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; - if(covers) - { - do - { - copy_or_blend_opaque_pix(p, *colors++, *covers++); - p = (value_type*)m_rbuf->next_row(p); - } - while(--len); - } - else + const int8u* p = from.row_ptr(ysrc); + if(p) { - if(cover == 255) - { - do - { - *p = colors->v; - p = (value_type*)m_rbuf->next_row(p); - ++colors; - } - while(--len); - } - else - { - do - { - copy_or_blend_opaque_pix(p, *colors++, cover); - p = (value_type*)m_rbuf->next_row(p); - } - while(--len); - } + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); } } //-------------------------------------------------------------------- - template<class Function> void for_each_pixel(Function f) + template<class SrcPixelFormatRenderer> + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) { - unsigned y; - for(y = 0; y < height(); ++y) + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) { - unsigned len = width(); - value_type* p = (value_type*)m_rbuf->row(y) + Offset; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; do { - f(p); - p += Step; + copy_or_blend_pix(pdst, + color, + (*psrc * cover + base_mask) >> base_shift); + ++psrc; + ++pdst; } while(--len); } } //-------------------------------------------------------------------- - template<class GammaLut> void apply_gamma_dir(const GammaLut& g) - { - for_each_pixel(apply_gamma_dir_gray<color_type, GammaLut>(g)); - } - - //-------------------------------------------------------------------- - template<class GammaLut> void apply_gamma_inv(const GammaLut& g) - { - for_each_pixel(apply_gamma_inv_gray<color_type, GammaLut>(g)); - } - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) + template<class SrcPixelFormatRenderer> + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) { - memmove((value_type*)m_rbuf->row(ydst) + xdst, - (value_type*)from.row(ysrc) + xsrc, - sizeof(value_type) * len); + 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: - rendering_buffer* m_rbuf; + rbuf_type* m_rbuf; }; typedef blender_gray<gray8> blender_gray8; @@ -577,126 +660,10 @@ namespace agg typedef blender_gray<gray16> blender_gray16; typedef blender_gray_pre<gray16> blender_gray16_pre; - typedef pixel_formats_gray<blender_gray8, 1, 0> pixfmt_gray8; //----pixfmt_gray8 - - typedef pixel_formats_gray<blender_gray8, 3, 0> pixfmt_gray8_rgb24r; //----pixfmt_gray8_rgb24r - typedef pixel_formats_gray<blender_gray8, 3, 1> pixfmt_gray8_rgb24g; //----pixfmt_gray8_rgb24g - typedef pixel_formats_gray<blender_gray8, 3, 2> pixfmt_gray8_rgb24b; //----pixfmt_gray8_rgb24b - - typedef pixel_formats_gray<blender_gray8, 3, 2> pixfmt_gray8_bgr24r; //----pixfmt_gray8_bgr24r - typedef pixel_formats_gray<blender_gray8, 3, 1> pixfmt_gray8_bgr24g; //----pixfmt_gray8_bgr24g - typedef pixel_formats_gray<blender_gray8, 3, 0> pixfmt_gray8_bgr24b; //----pixfmt_gray8_bgr24b - - typedef pixel_formats_gray<blender_gray8, 4, 0> pixfmt_gray8_rgba32r; //----pixfmt_gray8_rgba32r - typedef pixel_formats_gray<blender_gray8, 4, 1> pixfmt_gray8_rgba32g; //----pixfmt_gray8_rgba32g - typedef pixel_formats_gray<blender_gray8, 4, 2> pixfmt_gray8_rgba32b; //----pixfmt_gray8_rgba32b - typedef pixel_formats_gray<blender_gray8, 4, 3> pixfmt_gray8_rgba32a; //----pixfmt_gray8_rgba32a - - typedef pixel_formats_gray<blender_gray8, 4, 1> pixfmt_gray8_argb32r; //----pixfmt_gray8_argb32r - typedef pixel_formats_gray<blender_gray8, 4, 2> pixfmt_gray8_argb32g; //----pixfmt_gray8_argb32g - typedef pixel_formats_gray<blender_gray8, 4, 3> pixfmt_gray8_argb32b; //----pixfmt_gray8_argb32b - typedef pixel_formats_gray<blender_gray8, 4, 0> pixfmt_gray8_argb32a; //----pixfmt_gray8_argb32a - - typedef pixel_formats_gray<blender_gray8, 4, 2> pixfmt_gray8_bgra32r; //----pixfmt_gray8_bgra32r - typedef pixel_formats_gray<blender_gray8, 4, 1> pixfmt_gray8_bgra32g; //----pixfmt_gray8_bgra32g - typedef pixel_formats_gray<blender_gray8, 4, 0> pixfmt_gray8_bgra32b; //----pixfmt_gray8_bgra32b - typedef pixel_formats_gray<blender_gray8, 4, 3> pixfmt_gray8_bgra32a; //----pixfmt_gray8_bgra32a - - typedef pixel_formats_gray<blender_gray8, 4, 3> pixfmt_gray8_abgr32r; //----pixfmt_gray8_abgr32r - typedef pixel_formats_gray<blender_gray8, 4, 2> pixfmt_gray8_abgr32g; //----pixfmt_gray8_abgr32g - typedef pixel_formats_gray<blender_gray8, 4, 1> pixfmt_gray8_abgr32b; //----pixfmt_gray8_abgr32b - typedef pixel_formats_gray<blender_gray8, 4, 0> pixfmt_gray8_abgr32a; //----pixfmt_gray8_abgr32a - - typedef pixel_formats_gray<blender_gray8_pre, 1, 0> pixfmt_gray8_pre; //----pixfmt_gray8_pre - - typedef pixel_formats_gray<blender_gray8_pre, 3, 0> pixfmt_gray8_pre_rgb24r; //----pixfmt_gray8_pre_rgb24r - typedef pixel_formats_gray<blender_gray8_pre, 3, 1> pixfmt_gray8_pre_rgb24g; //----pixfmt_gray8_pre_rgb24g - typedef pixel_formats_gray<blender_gray8_pre, 3, 2> pixfmt_gray8_pre_rgb24b; //----pixfmt_gray8_pre_rgb24b - - typedef pixel_formats_gray<blender_gray8_pre, 3, 2> pixfmt_gray8_pre_bgr24r; //----pixfmt_gray8_pre_bgr24r - typedef pixel_formats_gray<blender_gray8_pre, 3, 1> pixfmt_gray8_pre_bgr24g; //----pixfmt_gray8_pre_bgr24g - typedef pixel_formats_gray<blender_gray8_pre, 3, 0> pixfmt_gray8_pre_bgr24b; //----pixfmt_gray8_pre_bgr24b - - typedef pixel_formats_gray<blender_gray8_pre, 4, 0> pixfmt_gray8_pre_rgba32r; //----pixfmt_gray8_pre_rgba32r - typedef pixel_formats_gray<blender_gray8_pre, 4, 1> pixfmt_gray8_pre_rgba32g; //----pixfmt_gray8_pre_rgba32g - typedef pixel_formats_gray<blender_gray8_pre, 4, 2> pixfmt_gray8_pre_rgba32b; //----pixfmt_gray8_pre_rgba32b - typedef pixel_formats_gray<blender_gray8_pre, 4, 3> pixfmt_gray8_pre_rgba32a; //----pixfmt_gray8_pre_rgba32a - - typedef pixel_formats_gray<blender_gray8_pre, 4, 1> pixfmt_gray8_pre_argb32r; //----pixfmt_gray8_pre_argb32r - typedef pixel_formats_gray<blender_gray8_pre, 4, 2> pixfmt_gray8_pre_argb32g; //----pixfmt_gray8_pre_argb32g - typedef pixel_formats_gray<blender_gray8_pre, 4, 3> pixfmt_gray8_pre_argb32b; //----pixfmt_gray8_pre_argb32b - typedef pixel_formats_gray<blender_gray8_pre, 4, 0> pixfmt_gray8_pre_argb32a; //----pixfmt_gray8_pre_argb32a - - typedef pixel_formats_gray<blender_gray8_pre, 4, 2> pixfmt_gray8_pre_bgra32r; //----pixfmt_gray8_pre_bgra32r - typedef pixel_formats_gray<blender_gray8_pre, 4, 1> pixfmt_gray8_pre_bgra32g; //----pixfmt_gray8_pre_bgra32g - typedef pixel_formats_gray<blender_gray8_pre, 4, 0> pixfmt_gray8_pre_bgra32b; //----pixfmt_gray8_pre_bgra32b - typedef pixel_formats_gray<blender_gray8_pre, 4, 3> pixfmt_gray8_pre_bgra32a; //----pixfmt_gray8_pre_bgra32a - - typedef pixel_formats_gray<blender_gray8_pre, 4, 3> pixfmt_gray8_pre_abgr32r; //----pixfmt_gray8_pre_abgr32r - typedef pixel_formats_gray<blender_gray8_pre, 4, 2> pixfmt_gray8_pre_abgr32g; //----pixfmt_gray8_pre_abgr32g - typedef pixel_formats_gray<blender_gray8_pre, 4, 1> pixfmt_gray8_pre_abgr32b; //----pixfmt_gray8_pre_abgr32b - typedef pixel_formats_gray<blender_gray8_pre, 4, 0> pixfmt_gray8_pre_abgr32a; //----pixfmt_gray8_pre_abgr32a - - typedef pixel_formats_gray<blender_gray16, 1, 0> pixfmt_gray16; //----pixfmt_gray16 - - typedef pixel_formats_gray<blender_gray16, 3, 0> pixfmt_gray16_rgb48r; //----pixfmt_gray16_rgb48r - typedef pixel_formats_gray<blender_gray16, 3, 1> pixfmt_gray16_rgb48g; //----pixfmt_gray16_rgb48g - typedef pixel_formats_gray<blender_gray16, 3, 2> pixfmt_gray16_rgb48b; //----pixfmt_gray16_rgb48b - - typedef pixel_formats_gray<blender_gray16, 3, 2> pixfmt_gray16_bgr48r; //----pixfmt_gray16_bgr48r - typedef pixel_formats_gray<blender_gray16, 3, 1> pixfmt_gray16_bgr48g; //----pixfmt_gray16_bgr48g - typedef pixel_formats_gray<blender_gray16, 3, 0> pixfmt_gray16_bgr48b; //----pixfmt_gray16_bgr48b - - typedef pixel_formats_gray<blender_gray16, 4, 0> pixfmt_gray16_rgba64r; //----pixfmt_gray16_rgba64r - typedef pixel_formats_gray<blender_gray16, 4, 1> pixfmt_gray16_rgba64g; //----pixfmt_gray16_rgba64g - typedef pixel_formats_gray<blender_gray16, 4, 2> pixfmt_gray16_rgba64b; //----pixfmt_gray16_rgba64b - typedef pixel_formats_gray<blender_gray16, 4, 3> pixfmt_gray16_rgba64a; //----pixfmt_gray16_rgba64a - - typedef pixel_formats_gray<blender_gray16, 4, 1> pixfmt_gray16_argb64r; //----pixfmt_gray16_argb64r - typedef pixel_formats_gray<blender_gray16, 4, 2> pixfmt_gray16_argb64g; //----pixfmt_gray16_argb64g - typedef pixel_formats_gray<blender_gray16, 4, 3> pixfmt_gray16_argb64b; //----pixfmt_gray16_argb64b - typedef pixel_formats_gray<blender_gray16, 4, 0> pixfmt_gray16_argb64a; //----pixfmt_gray16_argb64a - - typedef pixel_formats_gray<blender_gray16, 4, 2> pixfmt_gray16_bgra64r; //----pixfmt_gray16_bgra64r - typedef pixel_formats_gray<blender_gray16, 4, 1> pixfmt_gray16_bgra64g; //----pixfmt_gray16_bgra64g - typedef pixel_formats_gray<blender_gray16, 4, 0> pixfmt_gray16_bgra64b; //----pixfmt_gray16_bgra64b - typedef pixel_formats_gray<blender_gray16, 4, 3> pixfmt_gray16_bgra64a; //----pixfmt_gray16_bgra64a - - typedef pixel_formats_gray<blender_gray16, 4, 3> pixfmt_gray16_abgr64r; //----pixfmt_gray16_abgr64r - typedef pixel_formats_gray<blender_gray16, 4, 2> pixfmt_gray16_abgr64g; //----pixfmt_gray16_abgr64g - typedef pixel_formats_gray<blender_gray16, 4, 1> pixfmt_gray16_abgr64b; //----pixfmt_gray16_abgr64b - typedef pixel_formats_gray<blender_gray16, 4, 0> pixfmt_gray16_abgr64a; //----pixfmt_gray16_abgr64a - - typedef pixel_formats_gray<blender_gray16_pre, 1, 0> pixfmt_gray16_pre; //----pixfmt_gray16_pre - - typedef pixel_formats_gray<blender_gray16_pre, 3, 0> pixfmt_gray16_pre_rgb48r; //----pixfmt_gray16_pre_rgb48r - typedef pixel_formats_gray<blender_gray16_pre, 3, 1> pixfmt_gray16_pre_rgb48g; //----pixfmt_gray16_pre_rgb48g - typedef pixel_formats_gray<blender_gray16_pre, 3, 2> pixfmt_gray16_pre_rgb48b; //----pixfmt_gray16_pre_rgb48b - - typedef pixel_formats_gray<blender_gray16_pre, 3, 2> pixfmt_gray16_pre_bgr48r; //----pixfmt_gray16_pre_bgr48r - typedef pixel_formats_gray<blender_gray16_pre, 3, 1> pixfmt_gray16_pre_bgr48g; //----pixfmt_gray16_pre_bgr48g - typedef pixel_formats_gray<blender_gray16_pre, 3, 0> pixfmt_gray16_pre_bgr48b; //----pixfmt_gray16_pre_bgr48b - - typedef pixel_formats_gray<blender_gray16_pre, 4, 0> pixfmt_gray16_pre_rgba64r; //----pixfmt_gray16_pre_rgba64r - typedef pixel_formats_gray<blender_gray16_pre, 4, 1> pixfmt_gray16_pre_rgba64g; //----pixfmt_gray16_pre_rgba64g - typedef pixel_formats_gray<blender_gray16_pre, 4, 2> pixfmt_gray16_pre_rgba64b; //----pixfmt_gray16_pre_rgba64b - typedef pixel_formats_gray<blender_gray16_pre, 4, 3> pixfmt_gray16_pre_rgba64a; //----pixfmt_gray16_pre_rgba64a - - typedef pixel_formats_gray<blender_gray16_pre, 4, 1> pixfmt_gray16_pre_argb64r; //----pixfmt_gray16_pre_argb64r - typedef pixel_formats_gray<blender_gray16_pre, 4, 2> pixfmt_gray16_pre_argb64g; //----pixfmt_gray16_pre_argb64g - typedef pixel_formats_gray<blender_gray16_pre, 4, 3> pixfmt_gray16_pre_argb64b; //----pixfmt_gray16_pre_argb64b - typedef pixel_formats_gray<blender_gray16_pre, 4, 0> pixfmt_gray16_pre_argb64a; //----pixfmt_gray16_pre_argb64a - - typedef pixel_formats_gray<blender_gray16_pre, 4, 2> pixfmt_gray16_pre_bgra64r; //----pixfmt_gray16_pre_bgra64r - typedef pixel_formats_gray<blender_gray16_pre, 4, 1> pixfmt_gray16_pre_bgra64g; //----pixfmt_gray16_pre_bgra64g - typedef pixel_formats_gray<blender_gray16_pre, 4, 0> pixfmt_gray16_pre_bgra64b; //----pixfmt_gray16_pre_bgra64b - typedef pixel_formats_gray<blender_gray16_pre, 4, 3> pixfmt_gray16_pre_bgra64a; //----pixfmt_gray16_pre_bgra64a - - typedef pixel_formats_gray<blender_gray16_pre, 4, 3> pixfmt_gray16_pre_abgr64r; //----pixfmt_gray16_pre_abgr64r - typedef pixel_formats_gray<blender_gray16_pre, 4, 2> pixfmt_gray16_pre_abgr64g; //----pixfmt_gray16_pre_abgr64g - typedef pixel_formats_gray<blender_gray16_pre, 4, 1> pixfmt_gray16_pre_abgr64b; //----pixfmt_gray16_pre_abgr64b - typedef pixel_formats_gray<blender_gray16_pre, 4, 0> pixfmt_gray16_pre_abgr64a; //----pixfmt_gray16_pre_abgr64a - + typedef pixfmt_alpha_blend_gray<blender_gray8, rendering_buffer> pixfmt_gray8; //----pixfmt_gray8 + typedef pixfmt_alpha_blend_gray<blender_gray8_pre, rendering_buffer> pixfmt_gray8_pre; //----pixfmt_gray8_pre + typedef pixfmt_alpha_blend_gray<blender_gray16, rendering_buffer> pixfmt_gray16; //----pixfmt_gray16 + typedef pixfmt_alpha_blend_gray<blender_gray16_pre, rendering_buffer> pixfmt_gray16_pre; //----pixfmt_gray16_pre } #endif diff --git a/agg/inc/agg_pixfmt_rgb.h b/agg/inc/agg_pixfmt_rgb.h index 436dfa4b284f..4c7dbe6d0c1d 100755 --- a/agg/inc/agg_pixfmt_rgb.h +++ b/agg/inc/agg_pixfmt_rgb.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -80,13 +80,13 @@ namespace agg typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum { base_shift = color_type::base_shift }; + enum base_scale_e { base_shift = color_type::base_shift }; //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, - unsigned) + unsigned cover=0) { p[Order::R] += (value_type)(((cr - p[Order::R]) * alpha) >> base_shift); p[Order::G] += (value_type)(((cg - p[Order::G]) * alpha) >> base_shift); @@ -102,7 +102,7 @@ namespace agg typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum { base_shift = color_type::base_shift }; + enum base_scale_e { base_shift = color_type::base_shift }; //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, @@ -116,6 +116,18 @@ namespace agg p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift); p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift); } + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha) + { + alpha = color_type::base_mask - alpha; + p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); + p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); + p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); + } + }; @@ -129,7 +141,7 @@ namespace agg typedef Gamma gamma_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum { base_shift = color_type::base_shift }; + enum base_scale_e { base_shift = color_type::base_shift }; //-------------------------------------------------------------------- blender_rgb_gamma() : m_gamma(0) {} @@ -139,7 +151,7 @@ namespace agg AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, - unsigned) + unsigned cover=0) { calc_type r = m_gamma->dir(p[Order::R]); calc_type g = m_gamma->dir(p[Order::G]); @@ -156,20 +168,23 @@ namespace agg - //==================================================pixel_formats_rgb - template<class Blender> class pixel_formats_rgb + //==================================================pixfmt_alpha_blend_rgb + template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb { public: - typedef rendering_buffer::row_data row_data; - typedef typename Blender::color_type color_type; - typedef typename Blender::order_type order_type; + typedef RenBuf rbuf_type; + typedef Blender blender_type; + typedef typename rbuf_type::row_data row_data; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, - base_size = color_type::base_size, - base_mask = color_type::base_mask + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(value_type) * 3 }; private: @@ -195,28 +210,48 @@ namespace agg } //-------------------------------------------------------------------- - AGG_INLINE void copy_or_blend_opaque_pix(value_type* p, - const color_type& c, - unsigned cover) + AGG_INLINE void copy_or_blend_pix(value_type* p, + const color_type& c) { - if(cover == 255) - { - p[order_type::R] = c.r; - p[order_type::G] = c.g; - p[order_type::B] = c.b; - } - else + if (c.a) { - m_blender.blend_pix(p, c.r, c.g, c.b, (cover + 1) << (base_shift - 8), cover); + if(c.a == base_mask) + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + } + else + { + m_blender.blend_pix(p, c.r, c.g, c.b, c.a); + } } } public: //-------------------------------------------------------------------- - pixel_formats_rgb(rendering_buffer& rb) : + explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template<class PixFmt> + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } //-------------------------------------------------------------------- Blender& blender() { return m_blender; } @@ -224,28 +259,45 @@ 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(); } //-------------------------------------------------------------------- - AGG_INLINE color_type pixel(int x, int y) const + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) { - value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; - return color_type(p[order_type::R], - p[order_type::G], - p[order_type::B]); + 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 span(int x, int y) const + AGG_INLINE static void make_pix(int8u* p, const color_type& c) { - return row_data(x, - width() - 1, - m_rbuf->row(y) + x * 3 * sizeof(value_type)); + ((value_type*)p)[order_type::R] = c.r; + ((value_type*)p)[order_type::G] = c.g; + ((value_type*)p)[order_type::B] = c.b; + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + value_type* p = (value_type*)m_rbuf->row_ptr(y) + x + x + x; + return color_type(p[order_type::R], + p[order_type::G], + p[order_type::B]); } //-------------------------------------------------------------------- AGG_INLINE void copy_pixel(int x, int y, const color_type& c) { - value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x; p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; @@ -254,7 +306,7 @@ namespace agg //-------------------------------------------------------------------- AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) { - copy_or_blend_pix((value_type*)m_rbuf->row(y) + x + x + x, c, cover); + copy_or_blend_pix((value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x, c, cover); } @@ -263,7 +315,7 @@ namespace agg unsigned len, const color_type& c) { - value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + x + x + x; do { p[order_type::R] = c.r; @@ -280,13 +332,13 @@ namespace agg unsigned len, const color_type& c) { - value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; do { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; - p = (value_type*)m_rbuf->next_row(p); } while(--len); } @@ -300,7 +352,9 @@ namespace agg { if (c.a) { - value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x + x + x; + calc_type alpha = (calc_type(c.a) * (calc_type(cover) + 1)) >> 8; if(alpha == base_mask) { @@ -334,16 +388,18 @@ namespace agg { if (c.a) { - value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; + value_type* p; calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { do { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; - p = (value_type*)m_rbuf->next_row(p); } while(--len); } @@ -351,8 +407,10 @@ namespace agg { do { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); - p = (value_type*)m_rbuf->next_row(p); } while(--len); } @@ -368,7 +426,9 @@ namespace agg { if (c.a) { - value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x + x + x; + do { calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; @@ -398,9 +458,11 @@ namespace agg { if (c.a) { - value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; do { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; if(alpha == base_mask) { @@ -412,7 +474,6 @@ namespace agg { m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers); } - p = (value_type*)m_rbuf->next_row(p); ++covers; } while(--len); @@ -421,13 +482,53 @@ namespace agg //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x + x + x; + + do + { + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + ++colors; + p += 3; + } + 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 + 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, const color_type* colors, const int8u* covers, int8u cover) { - value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x + x + x; + if(covers) { do @@ -443,18 +544,8 @@ namespace agg { do { - if(colors->a == base_mask) - { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - } - else - { - copy_or_blend_pix(p, *colors, 255); - } + copy_or_blend_pix(p, *colors++); p += 3; - ++colors; } while(--len); } @@ -479,13 +570,15 @@ namespace agg const int8u* covers, int8u cover) { - value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; + value_type* p; if(covers) { do { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + copy_or_blend_pix(p, *colors++, *covers++); - p = (value_type*)m_rbuf->next_row(p); } while(--len); } @@ -495,18 +588,10 @@ namespace agg { do { - if(colors->a == base_mask) - { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - } - else - { - copy_or_blend_pix(p, *colors, 255); - } - p = (value_type*)m_rbuf->next_row(p); - ++colors; + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + + copy_or_blend_pix(p, *colors++); } while(--len); } @@ -514,51 +599,31 @@ namespace agg { do { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + copy_or_blend_pix(p, *colors++, cover); - p = (value_type*)m_rbuf->next_row(p); } while(--len); } } } - //-------------------------------------------------------------------- - void blend_opaque_color_hspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) + template<class Function> void for_each_pixel(Function f) { - value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; - if(covers) - { - do - { - copy_or_blend_opaque_pix(p, *colors++, *covers++); - p += 3; - } - while(--len); - } - else + unsigned y; + for(y = 0; y < height(); ++y) { - if(cover == 255) + row_data r = m_rbuf->row(y); + if(r.ptr) { + unsigned len = r.x2 - r.x1 + 1; + value_type* p = (value_type*) + m_rbuf->row_ptr(r.x1, y, len) + r.x1 * 3; do { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p += 3; - ++colors; - } - while(--len); - } - else - { - do - { - copy_or_blend_opaque_pix(p, *colors++, cover); + f(p); p += 3; } while(--len); @@ -566,44 +631,91 @@ namespace agg } } + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgb<color_type, order_type, GammaLut>(g)); + } //-------------------------------------------------------------------- - void blend_opaque_color_vspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) + template<class GammaLut> void apply_gamma_inv(const GammaLut& g) { - value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; - if(covers) + for_each_pixel(apply_gamma_inv_rgb<color_type, order_type, GammaLut>(g)); + } + + //-------------------------------------------------------------------- + template<class RenBuf2> + void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) { - do - { - copy_or_blend_opaque_pix(p, *colors++, *covers++); - p = (value_type*)m_rbuf->next_row(p); - } - while(--len); + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); } - else + } + + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + + const value_type* psrc = (const value_type*)from.row_ptr(ysrc); + if(psrc) { + psrc += xsrc * 4; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3; + if(cover == 255) { do { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p = (value_type*)m_rbuf->next_row(p); - ++colors; + value_type alpha = psrc[src_order::A]; + if(alpha) + { + if(alpha == base_mask) + { + pdst[order_type::R] = psrc[src_order::R]; + pdst[order_type::G] = psrc[src_order::G]; + pdst[order_type::B] = psrc[src_order::B]; + } + else + { + m_blender.blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + alpha); + } + } + psrc += 4; + pdst += 3; } while(--len); } else { + color_type color; do { - copy_or_blend_opaque_pix(p, *colors++, cover); - p = (value_type*)m_rbuf->next_row(p); + color.r = psrc[src_order::R]; + color.g = psrc[src_order::G]; + color.b = psrc[src_order::B]; + color.a = psrc[src_order::A]; + copy_or_blend_pix(pdst, color, cover); + psrc += 4; + pdst += 3; } while(--len); } @@ -611,107 +723,95 @@ namespace agg } //-------------------------------------------------------------------- - template<class Function> void for_each_pixel(Function f) + template<class SrcPixelFormatRenderer> + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) { - unsigned y; - for(y = 0; y < height(); ++y) + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) { - unsigned len = width(); - value_type* p = (value_type*)m_rbuf->row(y); + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3; do { - f(p); - p += 3; + copy_or_blend_pix(pdst, + color, + (*psrc * cover + base_mask) >> base_shift); + ++psrc; + pdst += 3; } while(--len); } } //-------------------------------------------------------------------- - template<class GammaLut> void apply_gamma_dir(const GammaLut& g) - { - for_each_pixel(apply_gamma_dir_rgb<color_type, order_type, GammaLut>(g)); - } - - //-------------------------------------------------------------------- - template<class GammaLut> void apply_gamma_inv(const GammaLut& g) - { - for_each_pixel(apply_gamma_inv_rgb<color_type, order_type, GammaLut>(g)); - } - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - memmove((value_type*)m_rbuf->row(ydst) + xdst * 3, - (const value_type*)from.row(ysrc) + xsrc * 3, - sizeof(value_type) * 3 * len); - } - - - //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> - void blend_from(const SrcPixelFormatRenderer& from, - const int8u* psrc_, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) + 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::order_type src_order; - - const value_type* psrc = (const value_type*)psrc_; - value_type* pdst = (value_type*)m_rbuf->row(ydst) + xdst * 3; - do + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) { - value_type alpha = psrc[src_order::A]; - if(alpha) + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3; + + if(cover == 255) { - if(alpha == base_mask) + do { - pdst[order_type::R] = psrc[src_order::R]; - pdst[order_type::G] = psrc[src_order::G]; - pdst[order_type::B] = psrc[src_order::B]; + const color_type& color = color_lut[*psrc]; + m_blender.blend_pix(pdst, + color.r, color.g, color.b, color.a); + ++psrc; + pdst += 3; } - else + while(--len); + } + else + { + do { - m_blender.blend_pix(pdst, - psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B], - alpha, - 255); + copy_or_blend_pix(pdst, color_lut[*psrc], cover); + ++psrc; + pdst += 3; } + while(--len); } - psrc += 4; - pdst += 3; } - while(--len); } private: - rendering_buffer* m_rbuf; - Blender m_blender; + rbuf_type* m_rbuf; + Blender m_blender; }; - typedef pixel_formats_rgb<blender_rgb<rgba8, order_rgb> > pixfmt_rgb24; //----pixfmt_rgb24 - typedef pixel_formats_rgb<blender_rgb<rgba8, order_bgr> > pixfmt_bgr24; //----pixfmt_bgr24 - typedef pixel_formats_rgb<blender_rgb<rgba16, order_rgb> > pixfmt_rgb48; //----pixfmt_rgb48 - typedef pixel_formats_rgb<blender_rgb<rgba16, order_bgr> > pixfmt_bgr48; //----pixfmt_bgr48 + typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24; //----pixfmt_rgb24 + typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24; //----pixfmt_bgr24 + typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48; //----pixfmt_rgb48 + typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48; //----pixfmt_bgr48 - typedef pixel_formats_rgb<blender_rgb_pre<rgba8, order_rgb> > pixfmt_rgb24_pre; //----pixfmt_rgb24_pre - typedef pixel_formats_rgb<blender_rgb_pre<rgba8, order_bgr> > pixfmt_bgr24_pre; //----pixfmt_bgr24_pre - typedef pixel_formats_rgb<blender_rgb_pre<rgba16, order_rgb> > pixfmt_rgb48_pre; //----pixfmt_rgb48_pre - typedef pixel_formats_rgb<blender_rgb_pre<rgba16, order_bgr> > pixfmt_bgr48_pre; //----pixfmt_bgr48_pre + typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24_pre; //----pixfmt_rgb24_pre + typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24_pre; //----pixfmt_bgr24_pre + typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48_pre; //----pixfmt_rgb48_pre + typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48_pre; //----pixfmt_bgr48_pre //-----------------------------------------------------pixfmt_rgb24_gamma template<class Gamma> class pixfmt_rgb24_gamma : - public pixel_formats_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma> > + public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer> { public: pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) : - pixel_formats_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma> >(rb) + pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } @@ -719,11 +819,11 @@ namespace agg //-----------------------------------------------------pixfmt_bgr24_gamma template<class Gamma> class pixfmt_bgr24_gamma : - public pixel_formats_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma> > + public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer> { public: pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) : - pixel_formats_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma> >(rb) + pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } @@ -731,11 +831,11 @@ namespace agg //-----------------------------------------------------pixfmt_rgb48_gamma template<class Gamma> class pixfmt_rgb48_gamma : - public pixel_formats_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma> > + public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer> { public: pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) : - pixel_formats_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma> >(rb) + pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } @@ -743,11 +843,11 @@ namespace agg //-----------------------------------------------------pixfmt_bgr48_gamma template<class Gamma> class pixfmt_bgr48_gamma : - public pixel_formats_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma> > + public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer> { public: pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) : - pixel_formats_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma> >(rb) + pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } diff --git a/agg/inc/agg_pixfmt_rgb_packed.h b/agg/inc/agg_pixfmt_rgb_packed.h index 4f582ed59847..63a308a0bff0 100755 --- a/agg/inc/agg_pixfmt_rgb_packed.h +++ b/agg/inc/agg_pixfmt_rgb_packed.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -788,20 +788,24 @@ namespace agg - //===============================================pixel_formats_rgb_packed - template<class Blender> class pixel_formats_rgb_packed + //===========================================pixfmt_alpha_blend_rgb_packed + template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb_packed { public: - typedef rendering_buffer::row_data row_data; - typedef typename Blender::color_type color_type; - typedef typename Blender::pixel_type pixel_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::pixel_type pixel_type; + typedef int order_type; // A fake one + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e { base_shift = color_type::base_shift, - base_size = color_type::base_size, - base_mask = color_type::base_mask + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(pixel_type) }; private: @@ -822,67 +826,83 @@ namespace agg } } + public: + //-------------------------------------------------------------------- + explicit pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + //-------------------------------------------------------------------- - AGG_INLINE void copy_or_blend_opaque_pix(pixel_type* p, const color_type& c, unsigned cover) + template<class PixFmt> + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) { - if(cover == 255) - { - *p = m_blender.make_pix(c.r, c.g, c.b); - } - else + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) { - m_blender.blend_pix(p, c.r, c.g, c.b, (cover + 1) << (base_shift - 8), cover); + 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; } - public: //-------------------------------------------------------------------- - pixel_formats_rgb_packed(rendering_buffer& rb) : - m_rbuf(&rb) - {} + 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(); } //-------------------------------------------------------------------- - Blender& blender() { return m_blender; } + 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 unsigned width() const { return m_rbuf->width(); } - AGG_INLINE unsigned height() const { return m_rbuf->height(); } + 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; + } //-------------------------------------------------------------------- - AGG_INLINE color_type pixel(int x, int y) const + AGG_INLINE void make_pix(int8u* p, const color_type& c) { - pixel_type* p = (pixel_type*)m_rbuf->row(y) + x; - return m_blender.make_color(((pixel_type*)m_rbuf->row(y))[x]); + *(pixel_type*)p = m_blender.make_pix(c.r, c.g, c.b); } //-------------------------------------------------------------------- - row_data span(int x, int y) const + AGG_INLINE color_type pixel(int x, int y) const { - return row_data(x, - width() - 1, - m_rbuf->row(y) + x * sizeof(pixel_type)); + return m_blender.make_color(((pixel_type*)m_rbuf->row_ptr(y))[x]); } //-------------------------------------------------------------------- AGG_INLINE void copy_pixel(int x, int y, const color_type& c) { - ((pixel_type*)m_rbuf->row(y))[x] = m_blender.make_pix(c.r, c.g, c.b); + ((pixel_type*) + m_rbuf->row_ptr(x, y, 1))[x] = + m_blender.make_pix(c.r, c.g, c.b); } //-------------------------------------------------------------------- AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) { - copy_or_blend_pix((pixel_type*)m_rbuf->row(y) + x, c, cover); + copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y, 1) + x, c, cover); } - //-------------------------------------------------------------------- AGG_INLINE void copy_hline(int x, int y, unsigned len, const color_type& c) { - pixel_type* p = (pixel_type*)m_rbuf->row(y) + x; + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; pixel_type v = m_blender.make_pix(c.r, c.g, c.b); do { @@ -891,23 +911,20 @@ namespace agg while(--len); } - //-------------------------------------------------------------------- AGG_INLINE void copy_vline(int x, int y, unsigned len, const color_type& c) { - pixel_type* p = (pixel_type*)m_rbuf->row(y) + x; pixel_type v = m_blender.make_pix(c.r, c.g, c.b); do { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; *p = v; - p = (pixel_type*)m_rbuf->next_row(p); } while(--len); } - //-------------------------------------------------------------------- void blend_hline(int x, int y, unsigned len, @@ -916,7 +933,7 @@ namespace agg { if (c.a) { - pixel_type* p = (pixel_type*)m_rbuf->row(y) + x; + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { @@ -939,7 +956,6 @@ namespace agg } } - //-------------------------------------------------------------------- void blend_vline(int x, int y, unsigned len, @@ -948,15 +964,13 @@ namespace agg { if (c.a) { - pixel_type* p = (pixel_type*)m_rbuf->row(y) + x; calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { pixel_type v = m_blender.make_pix(c.r, c.g, c.b); do { - *p = v; - p = (pixel_type*)m_rbuf->next_row(p); + ((pixel_type*)m_rbuf->row_ptr(x, y++, 1))[x] = v; } while(--len); } @@ -964,22 +978,22 @@ namespace agg { do { - m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); - p = (pixel_type*)m_rbuf->next_row(p); + m_blender.blend_pix( + (pixel_type*)m_rbuf->row_ptr(x, y++, 1), + c.r, c.g, c.b, alpha, cover); } while(--len); } } } - //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { - pixel_type* p = (pixel_type*)m_rbuf->row(y) + x; + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; do { copy_or_blend_pix(p, c, *covers++); @@ -988,22 +1002,47 @@ namespace agg while(--len); } - //-------------------------------------------------------------------- void blend_solid_vspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { - pixel_type* p = (pixel_type*)m_rbuf->row(y) + x; do { - copy_or_blend_pix(p, c, *covers++); - p = (pixel_type*)m_rbuf->next_row(p); + copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, + c, *covers++); + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + do + { + *p++ = m_blender.make_pix(colors->r, colors->g, colors->b); + ++colors; } 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, @@ -1012,7 +1051,7 @@ namespace agg const int8u* covers, int8u cover) { - pixel_type* p = (pixel_type*)m_rbuf->row(y) + x; + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; do { copy_or_blend_pix(p++, *colors++, covers ? *covers++ : cover); @@ -1020,7 +1059,6 @@ namespace agg while(--len); } - //-------------------------------------------------------------------- void blend_color_vspan(int x, int y, unsigned len, @@ -1028,178 +1066,164 @@ namespace agg const int8u* covers, int8u cover) { - pixel_type* p = (pixel_type*)m_rbuf->row(y) + x; do { - copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover); - p = (pixel_type*)m_rbuf->next_row(p); + copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, + *colors++, covers ? *covers++ : cover); } while(--len); } - //-------------------------------------------------------------------- - void blend_opaque_color_hspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - pixel_type* p = (pixel_type*)m_rbuf->row(y) + x; - if(covers) + template<class RenBuf2> + void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) { - do - { - copy_or_blend_opaque_pix(p++, *colors++, *covers++); - } - while(--len); + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); } - else + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + + const value_type* psrc = (const value_type*)from.row_ptr(ysrc); + if(psrc) { - if(cover == 255) - { - do - { - *p++ = m_blender.make_pix(colors->r, colors->g, colors->b); - ++colors; - } - while(--len); - } - else + psrc += xsrc * 4; + pixel_type* pdst = + (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + do { - do + value_type alpha = psrc[src_order::A]; + if(alpha) { - copy_or_blend_opaque_pix(p++, *colors++, cover); + if(alpha == base_mask && cover == 255) + { + *pdst = m_blender.make_pix(psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B]); + } + else + { + m_blender.blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + alpha, + cover); + } } - while(--len); + psrc += 4; + ++pdst; } + while(--len); } } - //-------------------------------------------------------------------- - void blend_opaque_color_vspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - pixel_type* p = (pixel_type*)m_rbuf->row(y) + x; - if(covers) + template<class SrcPixelFormatRenderer> + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) { + pixel_type* pdst = + (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + do { - copy_or_blend_opaque_pix(p, *colors++, *covers++); - p = (pixel_type*)m_rbuf->next_row(p); + m_blender.blend_pix(pdst, + color.r, color.g, color.b, color.a, + cover); + ++psrc; + ++pdst; } while(--len); } - else - { - if(cover == 255) - { - do - { - *p = m_blender.make_pix(colors->r, colors->g, colors->b); - p = (value_type*)m_rbuf->next_row(p); - ++colors; - } - while(--len); - } - else - { - do - { - copy_or_blend_opaque_pix(p, *colors++, cover); - p = (value_type*)m_rbuf->next_row(p); - } - while(--len); - } - } } - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - memmove((pixel_type*)m_rbuf->row(ydst) + xdst, - (pixel_type*)from.row(ysrc) + xsrc, - sizeof(pixel_type) * len); - } - - //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> - void blend_from(const SrcPixelFormatRenderer& from, - const int8u* psrc_, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - typedef typename SrcPixelFormatRenderer::order_type src_order; - - const value_type* psrc = (const value_type*)psrc_; - pixel_type* pdst = (pixel_type*)m_rbuf->row(ydst) + xdst; - do + 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 alpha = psrc[src_order::A]; - if(alpha) + pixel_type* pdst = + (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + + do { - if(alpha == base_mask) - { - *pdst = m_blender.make_pix(psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B]); - } - else - { - m_blender.blend_pix(pdst, - psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B], - alpha, - 255); - } + const color_type& color = color_lut[*psrc]; + m_blender.blend_pix(pdst, + color.r, color.g, color.b, color.a, + cover); + ++psrc; + ++pdst; } - psrc += 4; - ++pdst; + while(--len); } - while(--len); } + private: - rendering_buffer* m_rbuf; - Blender m_blender; + rbuf_type* m_rbuf; + Blender m_blender; }; - typedef pixel_formats_rgb_packed<blender_rgb555> pixfmt_rgb555; //----pixfmt_rgb555 - typedef pixel_formats_rgb_packed<blender_rgb565> pixfmt_rgb565; //----pixfmt_rgb565 + typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555, rendering_buffer> pixfmt_rgb555; //----pixfmt_rgb555 + typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565, rendering_buffer> pixfmt_rgb565; //----pixfmt_rgb565 - typedef pixel_formats_rgb_packed<blender_rgb555_pre> pixfmt_rgb555_pre; //----pixfmt_rgb555_pre - typedef pixel_formats_rgb_packed<blender_rgb565_pre> pixfmt_rgb565_pre; //----pixfmt_rgb565_pre + typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555_pre, rendering_buffer> pixfmt_rgb555_pre; //----pixfmt_rgb555_pre + typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565_pre, rendering_buffer> pixfmt_rgb565_pre; //----pixfmt_rgb565_pre - typedef pixel_formats_rgb_packed<blender_rgbAAA> pixfmt_rgbAAA; //----pixfmt_rgbAAA - typedef pixel_formats_rgb_packed<blender_bgrAAA> pixfmt_bgrAAA; //----pixfmt_bgrAAA - typedef pixel_formats_rgb_packed<blender_rgbBBA> pixfmt_rgbBBA; //----pixfmt_rgbBBA - typedef pixel_formats_rgb_packed<blender_bgrABB> pixfmt_bgrABB; //----pixfmt_bgrABB + typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA, rendering_buffer> pixfmt_rgbAAA; //----pixfmt_rgbAAA + typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA, rendering_buffer> pixfmt_bgrAAA; //----pixfmt_bgrAAA + typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA, rendering_buffer> pixfmt_rgbBBA; //----pixfmt_rgbBBA + typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB, rendering_buffer> pixfmt_bgrABB; //----pixfmt_bgrABB - typedef pixel_formats_rgb_packed<blender_rgbAAA_pre> pixfmt_rgbAAA_pre; //----pixfmt_rgbAAA_pre - typedef pixel_formats_rgb_packed<blender_bgrAAA_pre> pixfmt_bgrAAA_pre; //----pixfmt_bgrAAA_pre - typedef pixel_formats_rgb_packed<blender_rgbBBA_pre> pixfmt_rgbBBA_pre; //----pixfmt_rgbBBA_pre - typedef pixel_formats_rgb_packed<blender_bgrABB_pre> pixfmt_bgrABB_pre; //----pixfmt_bgrABB_pre + typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_pre, rendering_buffer> pixfmt_rgbAAA_pre; //----pixfmt_rgbAAA_pre + typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_pre, rendering_buffer> pixfmt_bgrAAA_pre; //----pixfmt_bgrAAA_pre + typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_pre, rendering_buffer> pixfmt_rgbBBA_pre; //----pixfmt_rgbBBA_pre + typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB_pre, rendering_buffer> pixfmt_bgrABB_pre; //----pixfmt_bgrABB_pre //-----------------------------------------------------pixfmt_rgb555_gamma template<class Gamma> class pixfmt_rgb555_gamma : - public pixel_formats_rgb_packed<blender_rgb555_gamma<Gamma> > + public pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>, + rendering_buffer> { public: pixfmt_rgb555_gamma(rendering_buffer& rb, const Gamma& g) : - pixel_formats_rgb_packed<blender_rgb555_gamma<Gamma> >(rb) + pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>, + rendering_buffer>(rb) { this->blender().gamma(g); } @@ -1208,11 +1232,11 @@ namespace agg //-----------------------------------------------------pixfmt_rgb565_gamma template<class Gamma> class pixfmt_rgb565_gamma : - public pixel_formats_rgb_packed<blender_rgb565_gamma<Gamma> > + public pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer> { public: pixfmt_rgb565_gamma(rendering_buffer& rb, const Gamma& g) : - pixel_formats_rgb_packed<blender_rgb565_gamma<Gamma> >(rb) + pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer>(rb) { this->blender().gamma(g); } @@ -1221,11 +1245,13 @@ namespace agg //-----------------------------------------------------pixfmt_rgbAAA_gamma template<class Gamma> class pixfmt_rgbAAA_gamma : - public pixel_formats_rgb_packed<blender_rgbAAA_gamma<Gamma> > + public pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>, + rendering_buffer> { public: pixfmt_rgbAAA_gamma(rendering_buffer& rb, const Gamma& g) : - pixel_formats_rgb_packed<blender_rgbAAA_gamma<Gamma> >(rb) + pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>, + rendering_buffer>(rb) { this->blender().gamma(g); } @@ -1234,11 +1260,13 @@ namespace agg //-----------------------------------------------------pixfmt_bgrAAA_gamma template<class Gamma> class pixfmt_bgrAAA_gamma : - public pixel_formats_rgb_packed<blender_bgrAAA_gamma<Gamma> > + public pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>, + rendering_buffer> { public: pixfmt_bgrAAA_gamma(rendering_buffer& rb, const Gamma& g) : - pixel_formats_rgb_packed<blender_bgrAAA_gamma<Gamma> >(rb) + pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>, + rendering_buffer>(rb) { this->blender().gamma(g); } @@ -1247,11 +1275,13 @@ namespace agg //-----------------------------------------------------pixfmt_rgbBBA_gamma template<class Gamma> class pixfmt_rgbBBA_gamma : - public pixel_formats_rgb_packed<blender_rgbBBA_gamma<Gamma> > + public pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>, + rendering_buffer> { public: pixfmt_rgbBBA_gamma(rendering_buffer& rb, const Gamma& g) : - pixel_formats_rgb_packed<blender_rgbBBA_gamma<Gamma> >(rb) + pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>, + rendering_buffer>(rb) { this->blender().gamma(g); } @@ -1260,11 +1290,13 @@ namespace agg //-----------------------------------------------------pixfmt_bgrABB_gamma template<class Gamma> class pixfmt_bgrABB_gamma : - public pixel_formats_rgb_packed<blender_bgrABB_gamma<Gamma> > + public pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>, + rendering_buffer> { public: pixfmt_bgrABB_gamma(rendering_buffer& rb, const Gamma& g) : - pixel_formats_rgb_packed<blender_bgrABB_gamma<Gamma> >(rb) + pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>, + rendering_buffer>(rb) { this->blender().gamma(g); } diff --git a/agg/inc/agg_pixfmt_rgba.h b/agg/inc/agg_pixfmt_rgba.h index 3716877e04f7..f5723a2f8b99 100755 --- a/agg/inc/agg_pixfmt_rgba.h +++ b/agg/inc/agg_pixfmt_rgba.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -25,6 +25,7 @@ #define AGG_PIXFMT_RGBA_INCLUDED #include <string.h> +#include <math.h> #include "agg_basics.h" #include "agg_color_rgba.h" #include "agg_rendering_buffer.h" @@ -49,9 +50,9 @@ namespace agg p[Order::R] = p[Order::G] = p[Order::B] = 0; return; } - p[Order::R] = value_type((p[Order::R] * a) >> ColorT::base_shift); - p[Order::G] = value_type((p[Order::G] * a) >> ColorT::base_shift); - p[Order::B] = value_type((p[Order::B] * a) >> ColorT::base_shift); + p[Order::R] = value_type((p[Order::R] * a + ColorT::base_mask) >> ColorT::base_shift); + p[Order::G] = value_type((p[Order::G] * a + ColorT::base_mask) >> ColorT::base_shift); + p[Order::B] = value_type((p[Order::B] * a + ColorT::base_mask) >> ColorT::base_shift); } } @@ -77,7 +78,6 @@ namespace agg } }; - //=====================================================apply_gamma_dir_rgba template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgba { @@ -97,8 +97,6 @@ namespace agg const GammaLut& m_gamma; }; - - //=====================================================apply_gamma_inv_rgba template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgba { @@ -120,15 +118,21 @@ namespace agg + + + + + + + //=============================================================blender_rgba - template<class ColorT, class Order, class PixelT> struct blender_rgba + template<class ColorT, class Order> struct blender_rgba { typedef ColorT color_type; - typedef PixelT pixel_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask @@ -138,7 +142,7 @@ namespace agg static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, - unsigned) + unsigned cover=0) { calc_type r = p[Order::R]; calc_type g = p[Order::G]; @@ -151,16 +155,14 @@ namespace agg } }; - //=========================================================blender_rgba_pre - template<class ColorT, class Order, class PixelT> struct blender_rgba_pre + template<class ColorT, class Order> struct blender_rgba_pre { typedef ColorT color_type; - typedef PixelT pixel_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask @@ -179,25 +181,34 @@ namespace agg p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift); p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); } - }; - + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha) + { + alpha = color_type::base_mask - alpha; + p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); + p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); + p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); + p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); + } + }; //======================================================blender_rgba_plain - template<class ColorT, class Order, class PixelT> struct blender_rgba_plain + template<class ColorT, class Order> struct blender_rgba_plain { typedef ColorT color_type; - typedef PixelT pixel_type; typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum { base_shift = color_type::base_shift }; + enum base_scale_e { base_shift = color_type::base_shift }; //-------------------------------------------------------------------- static AGG_INLINE void blend_pix(value_type* p, unsigned cr, unsigned cg, unsigned cb, unsigned alpha, - unsigned) + unsigned cover=0) { if(alpha == 0) return; calc_type a = p[Order::A]; @@ -213,67 +224,1521 @@ namespace agg }; - //====================================================blender_rgba_wrapper - template<class Blender> struct blender_rgba_wrapper + + + + + + + + + + //=========================================================comp_op_rgba_clear + template<class ColorT, class Order> struct comp_op_rgba_clear { - typedef typename Blender::color_type color_type; - typedef typename Blender::order_type order_type; - typedef typename Blender::pixel_type pixel_type; + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, unsigned, + unsigned cover) + { + if(cover < 255) + { + cover = 255 - cover; + p[Order::R] = (value_type)((p[Order::R] * cover + 255) >> 8); + p[Order::G] = (value_type)((p[Order::G] * cover + 255) >> 8); + p[Order::B] = (value_type)((p[Order::B] * cover + 255) >> 8); + p[Order::A] = (value_type)((p[Order::A] * cover + 255) >> 8); + } + else + { + p[0] = p[1] = p[2] = p[3] = 0; + } + } + }; + + //===========================================================comp_op_rgba_src + template<class ColorT, class Order> struct comp_op_rgba_src + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); + } + else + { + p[Order::R] = sr; + p[Order::G] = sg; + p[Order::B] = sb; + p[Order::A] = sa; + } + } + }; + + //===========================================================comp_op_rgba_dst + template<class ColorT, class Order> struct comp_op_rgba_dst + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + + static AGG_INLINE void blend_pix(value_type*, + unsigned, unsigned, unsigned, + unsigned, unsigned) + { + } + }; + + //======================================================comp_op_rgba_src_over + template<class ColorT, class Order> struct comp_op_rgba_src_over + { + typedef ColorT color_type; + typedef Order order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, - base_size = color_type::base_size, base_mask = color_type::base_mask }; - //-------------------------------------------------------------------- + // 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; + } + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(sr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + } + }; + + //======================================================comp_op_rgba_dst_over + template<class ColorT, class Order> struct comp_op_rgba_dst_over + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Dca + Sca.(1 - Da) + // 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; + } + calc_type d1a = base_mask - p[Order::A]; + p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + } + }; + + //======================================================comp_op_rgba_src_in + template<class ColorT, class Order> struct comp_op_rgba_src_in + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca.Da + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = p[Order::A]; + if(cover < 255) + { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); + } + else + { + p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); + } + } + }; + + //======================================================comp_op_rgba_dst_in + template<class ColorT, class Order> struct comp_op_rgba_dst_in + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Dca.Sa + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sa = base_mask - ((cover * (base_mask - sa) + 255) >> 8); + } + p[Order::R] = (value_type)((p[Order::R] * sa + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + base_mask) >> base_shift); + p[Order::A] = (value_type)((p[Order::A] * sa + base_mask) >> base_shift); + } + }; + + //======================================================comp_op_rgba_src_out + template<class ColorT, class Order> struct comp_op_rgba_src_out + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca.(1 - Da) + // Da' = Sa.(1 - Da) + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = base_mask - p[Order::A]; + if(cover < 255) + { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); + } + else + { + p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); + } + } + }; + + //======================================================comp_op_rgba_dst_out + template<class ColorT, class Order> struct comp_op_rgba_dst_out + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Dca.(1 - Sa) + // Da' = Da.(1 - Sa) + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sa = (sa * cover + 255) >> 8; + } + sa = base_mask - sa; + p[Order::R] = (value_type)((p[Order::R] * sa + base_shift) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + base_shift) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + base_shift) >> base_shift); + p[Order::A] = (value_type)((p[Order::A] * sa + base_shift) >> base_shift); + } + }; + + //=====================================================comp_op_rgba_src_atop + template<class ColorT, class Order> struct comp_op_rgba_src_atop + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca.Da + Dca.(1 - Sa) + // Da' = 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; + } + calc_type da = p[Order::A]; + sa = base_mask - sa; + p[Order::R] = (value_type)((sr * da + p[Order::R] * sa + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + p[Order::G] * sa + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + p[Order::B] * sa + base_mask) >> base_shift); + } + }; + + //=====================================================comp_op_rgba_dst_atop + template<class ColorT, class Order> struct comp_op_rgba_dst_atop + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Dca.Sa + Sca.(1 - Da) + // Da' = Sa + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = base_mask - p[Order::A]; + if(cover < 255) + { + unsigned alpha = 255 - cover; + sr = (p[Order::R] * sa + sr * da + base_mask) >> base_shift; + sg = (p[Order::G] * sa + sg * da + base_mask) >> base_shift; + sb = (p[Order::B] * sa + sb * da + base_mask) >> base_shift; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); + + } + else + { + p[Order::R] = (value_type)((p[Order::R] * sa + sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)sa; + } + } + }; + + //=========================================================comp_op_rgba_xor + template<class ColorT, class Order> struct comp_op_rgba_xor + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - 2.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 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))); + } + } + }; + + //=========================================================comp_op_rgba_plus + template<class ColorT, class Order> struct comp_op_rgba_plus + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca + Dca + // 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 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; + } + } + }; + + //========================================================comp_op_rgba_minus + template<class ColorT, class Order> struct comp_op_rgba_minus + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Dca - Sca + // Da' = 1 - (1 - Sa).(1 - 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 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)); + } + } + }; + + //=====================================================comp_op_rgba_multiply + template<class ColorT, class Order> struct comp_op_rgba_multiply + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca.Dca + Sca.(1 - Da) + 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 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)); + } + } + }; + + //=====================================================comp_op_rgba_screen + template<class ColorT, class Order> struct comp_op_rgba_screen + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca + Dca - Sca.Dca + // 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 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)); + } + } + }; + + //=====================================================comp_op_rgba_overlay + template<class ColorT, class Order> struct comp_op_rgba_overlay + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // if 2.Dca < Da + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + 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 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_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_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_mask) >> base_shift); + + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + + template<class T> inline T sd_min(T a, T b) { return (a < b) ? a : b; } + template<class T> inline T sd_max(T a, T b) { return (a > b) ? a : b; } + + //=====================================================comp_op_rgba_darken + template<class ColorT, class Order> struct comp_op_rgba_darken + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + 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 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_mask) >> base_shift); + p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_lighten + template<class ColorT, class Order> struct comp_op_rgba_lighten + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + 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 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_mask) >> base_shift); + p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_color_dodge + template<class ColorT, class Order> struct comp_op_rgba_color_dodge + { + 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 + }; + + // if Sca.Da + Dca.Sa >= Sa.Da + // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + 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 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_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_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_mask) >> base_shift : + dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift)); + + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_color_burn + template<class ColorT, class Order> struct comp_op_rgba_color_burn + { + 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 + }; + + // if Sca.Da + Dca.Sa <= Sa.Da + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + 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 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_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_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_mask) >> base_shift); + + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_hard_light + template<class ColorT, class Order> struct comp_op_rgba_hard_light + { + 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 + }; + + // if 2.Sca < Sa + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + 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 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_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_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_mask) >> base_shift); + + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_soft_light + template<class ColorT, class Order> struct comp_op_rgba_soft_light + { + 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 + }; + + // if 2.Sca < Sa + // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise if 8.Dca <= Da + // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + + static AGG_INLINE void blend_pix(value_type* p, + unsigned r, unsigned g, unsigned b, + unsigned a, unsigned cover) + { + double sr = double(r * cover) / (base_mask * 255); + double sg = double(g * cover) / (base_mask * 255); + double sb = double(b * cover) / (base_mask * 255); + double sa = double(a * cover) / (base_mask * 255); + if(sa > 0) + { + double dr = double(p[Order::R]) / base_mask; + double dg = double(p[Order::G]) / base_mask; + double db = double(p[Order::B]) / base_mask; + 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)); + } + } + }; + + //=====================================================comp_op_rgba_difference + template<class ColorT, class Order> struct comp_op_rgba_difference + { + 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_scale = color_type::base_scale, + base_mask = color_type::base_mask + }; + + // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.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 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)); + } + } + }; + + //=====================================================comp_op_rgba_exclusion + template<class ColorT, class Order> struct comp_op_rgba_exclusion + { + 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' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + 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 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)); + } + } + }; + + //=====================================================comp_op_rgba_contrast + template<class ColorT, class Order> struct comp_op_rgba_contrast + { + 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 + }; + + + 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; + } + long_type dr = p[Order::R]; + long_type dg = p[Order::G]; + long_type db = p[Order::B]; + int da = p[Order::A]; + long_type d2a = da >> 1; + unsigned s2a = sa >> 1; + + int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a); + int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a); + int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a); + + r = (r < 0) ? 0 : r; + g = (g < 0) ? 0 : g; + b = (b < 0) ? 0 : b; + + p[Order::R] = (value_type)((r > da) ? da : r); + p[Order::G] = (value_type)((g > da) ? da : g); + p[Order::B] = (value_type)((b > da) ? da : b); + } + }; + + //=====================================================comp_op_rgba_invert + template<class ColorT, class Order> struct comp_op_rgba_invert + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + sa = (sa * cover + 255) >> 8; + if(sa) + { + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=================================================comp_op_rgba_invert_rgb + template<class ColorT, class Order> struct comp_op_rgba_invert_rgb + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + + + + + //======================================================comp_op_table_rgba + template<class ColorT, class Order> struct comp_op_table_rgba + { + typedef typename ColorT::value_type value_type; + typedef void (*comp_op_func_type)(value_type* p, + unsigned cr, + unsigned cg, + unsigned cb, + unsigned ca, + unsigned cover); + static comp_op_func_type g_comp_op_func[]; + }; + + //==========================================================g_comp_op_func + template<class ColorT, class Order> + typename comp_op_table_rgba<ColorT, Order>::comp_op_func_type + comp_op_table_rgba<ColorT, Order>::g_comp_op_func[] = + { + comp_op_rgba_clear <ColorT,Order>::blend_pix, + comp_op_rgba_src <ColorT,Order>::blend_pix, + comp_op_rgba_dst <ColorT,Order>::blend_pix, + comp_op_rgba_src_over <ColorT,Order>::blend_pix, + comp_op_rgba_dst_over <ColorT,Order>::blend_pix, + comp_op_rgba_src_in <ColorT,Order>::blend_pix, + comp_op_rgba_dst_in <ColorT,Order>::blend_pix, + comp_op_rgba_src_out <ColorT,Order>::blend_pix, + comp_op_rgba_dst_out <ColorT,Order>::blend_pix, + comp_op_rgba_src_atop <ColorT,Order>::blend_pix, + comp_op_rgba_dst_atop <ColorT,Order>::blend_pix, + comp_op_rgba_xor <ColorT,Order>::blend_pix, + comp_op_rgba_plus <ColorT,Order>::blend_pix, + comp_op_rgba_minus <ColorT,Order>::blend_pix, + comp_op_rgba_multiply <ColorT,Order>::blend_pix, + comp_op_rgba_screen <ColorT,Order>::blend_pix, + comp_op_rgba_overlay <ColorT,Order>::blend_pix, + comp_op_rgba_darken <ColorT,Order>::blend_pix, + comp_op_rgba_lighten <ColorT,Order>::blend_pix, + comp_op_rgba_color_dodge<ColorT,Order>::blend_pix, + comp_op_rgba_color_burn <ColorT,Order>::blend_pix, + comp_op_rgba_hard_light <ColorT,Order>::blend_pix, + comp_op_rgba_soft_light <ColorT,Order>::blend_pix, + comp_op_rgba_difference <ColorT,Order>::blend_pix, + comp_op_rgba_exclusion <ColorT,Order>::blend_pix, + comp_op_rgba_contrast <ColorT,Order>::blend_pix, + comp_op_rgba_invert <ColorT,Order>::blend_pix, + comp_op_rgba_invert_rgb <ColorT,Order>::blend_pix, + 0 + }; + + + //==============================================================comp_op_e + enum comp_op_e + { + comp_op_clear, //----comp_op_clear + comp_op_src, //----comp_op_src + comp_op_dst, //----comp_op_dst + comp_op_src_over, //----comp_op_src_over + comp_op_dst_over, //----comp_op_dst_over + comp_op_src_in, //----comp_op_src_in + comp_op_dst_in, //----comp_op_dst_in + comp_op_src_out, //----comp_op_src_out + comp_op_dst_out, //----comp_op_dst_out + comp_op_src_atop, //----comp_op_src_atop + comp_op_dst_atop, //----comp_op_dst_atop + comp_op_xor, //----comp_op_xor + comp_op_plus, //----comp_op_plus + comp_op_minus, //----comp_op_minus + comp_op_multiply, //----comp_op_multiply + comp_op_screen, //----comp_op_screen + comp_op_overlay, //----comp_op_overlay + comp_op_darken, //----comp_op_darken + comp_op_lighten, //----comp_op_lighten + comp_op_color_dodge, //----comp_op_color_dodge + comp_op_color_burn, //----comp_op_color_burn + comp_op_hard_light, //----comp_op_hard_light + comp_op_soft_light, //----comp_op_soft_light + 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 + }; + + + + + + + + //====================================================comp_op_adaptor_rgba + template<class ColorT, class Order> struct comp_op_adaptor_rgba + { + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, unsigned cr, unsigned cg, unsigned cb, - unsigned alpha, + unsigned ca, + unsigned cover) + { + comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op] + (p, (cr * ca + base_mask) >> base_shift, + (cg * ca + base_mask) >> base_shift, + (cb * ca + base_mask) >> base_shift, + ca, cover); + } + }; + + //=========================================comp_op_adaptor_clip_to_dst_rgba + template<class ColorT, class Order> struct comp_op_adaptor_clip_to_dst_rgba + { + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + cr = (cr * ca + base_mask) >> base_shift; + cg = (cg * ca + base_mask) >> base_shift; + cb = (cb * ca + base_mask) >> base_shift; + unsigned da = p[Order::A]; + comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op] + (p, (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } + }; + + //================================================comp_op_adaptor_rgba_pre + template<class ColorT, class Order> struct comp_op_adaptor_rgba_pre + { + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op](p, cr, cg, cb, ca, cover); + } + }; + + //=====================================comp_op_adaptor_clip_to_dst_rgba_pre + template<class ColorT, class Order> struct comp_op_adaptor_clip_to_dst_rgba_pre + { + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + unsigned da = p[Order::A]; + comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op] + (p, (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } + }; + + //=======================================================comp_adaptor_rgba + template<class BlenderPre> struct comp_adaptor_rgba + { + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + BlenderPre::blend_pix(p, + (cr * ca + base_mask) >> base_shift, + (cg * ca + base_mask) >> base_shift, + (cb * ca + base_mask) >> base_shift, + ca, cover); + } + }; + + //==========================================comp_adaptor_clip_to_dst_rgba + template<class BlenderPre> struct comp_adaptor_clip_to_dst_rgba + { + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, unsigned cover) { - Blender::blend_pix(p, cr, cg, cb, alpha, cover); + cr = (cr * ca + base_mask) >> base_shift; + cg = (cg * ca + base_mask) >> base_shift; + cb = (cb * ca + base_mask) >> base_shift; + unsigned da = p[order_type::A]; + BlenderPre::blend_pix(p, + (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); } + }; + + //======================================comp_adaptor_clip_to_dst_rgba_pre + template<class BlenderPre> struct comp_adaptor_clip_to_dst_rgba_pre + { + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + unsigned da = p[order_type::A]; + BlenderPre::blend_pix(p, + (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } + }; + + + + + + + //===============================================copy_or_blend_rgba_wrapper + template<class Blender> struct copy_or_blend_rgba_wrapper + { + typedef typename Blender::color_type color_type; + typedef typename Blender::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask + }; //-------------------------------------------------------------------- static AGG_INLINE void copy_or_blend_pix(value_type* p, - const color_type& c, - unsigned cover) + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha) { - if (c.a) + if(alpha) { - calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { - p[order_type::R] = c.r; - p[order_type::G] = c.g; - p[order_type::B] = c.b; - p[order_type::A] = c.a; + p[order_type::R] = cr; + p[order_type::G] = cg; + p[order_type::B] = cb; + p[order_type::A] = base_mask; } else { - Blender::blend_pix(p, c.r, c.g, c.b, alpha, cover); + Blender::blend_pix(p, cr, cg, cb, alpha); } } } //-------------------------------------------------------------------- - static AGG_INLINE void copy_or_blend_opaque_pix(value_type* p, - const color_type& c, - unsigned cover) + static AGG_INLINE void copy_or_blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) { if(cover == 255) { - p[order_type::R] = c.r; - p[order_type::G] = c.g; - p[order_type::B] = c.b; - p[order_type::A] = base_mask; + copy_or_blend_pix(p, cr, cg, cb, alpha); } else { - Blender::blend_pix(p, c.r, c.g, c.b, (cover + 1) << (base_shift - 8), cover); + if(alpha) + { + alpha = (alpha * (cover + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = cr; + p[order_type::G] = cg; + p[order_type::B] = cb; + p[order_type::A] = base_mask; + } + else + { + Blender::blend_pix(p, cr, cg, cb, alpha, cover); + } + } } } }; @@ -281,55 +1746,102 @@ namespace agg - //=======================================================pixel_formats_rgba - template<class Blender> class pixel_formats_rgba + + + //=================================================pixfmt_alpha_blend_rgba + template<class Blender, class RenBuf, class PixelT = int32u> + class pixfmt_alpha_blend_rgba { public: - typedef rendering_buffer::row_data row_data; - typedef typename Blender::color_type color_type; - typedef typename Blender::order_type order_type; - typedef typename Blender::pixel_type pixel_type; + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef PixelT pixel_type; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - typedef blender_rgba_wrapper<Blender> blender_type; - enum + typedef copy_or_blend_rgba_wrapper<blender_type> cob_type; + enum base_scale_e { base_shift = color_type::base_shift, - base_size = color_type::base_size, - base_mask = color_type::base_mask + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(pixel_type) }; //-------------------------------------------------------------------- - pixel_formats_rgba(rendering_buffer& rb) : - m_rbuf(&rb) - {} + pixfmt_alpha_blend_rgba() : m_rbuf(0) {} + explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template<class PixFmt> + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } //-------------------------------------------------------------------- AGG_INLINE unsigned width() const { return m_rbuf->width(); } AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } //-------------------------------------------------------------------- - AGG_INLINE color_type pixel(int x, int y) const + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) { - const value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); - return color_type(p[order_type::R], - p[order_type::G], - p[order_type::B], - p[order_type::A]); + 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; + } + + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((value_type*)p)[order_type::R] = c.r; + ((value_type*)p)[order_type::G] = c.g; + ((value_type*)p)[order_type::B] = c.b; + ((value_type*)p)[order_type::A] = c.a; } //-------------------------------------------------------------------- - row_data span(int x, int y) const + AGG_INLINE color_type pixel(int x, int y) const { - return row_data(x, - width() - 1, - m_rbuf->row(y) + x * 4 * sizeof(value_type)); + const value_type* p = (const value_type*)m_rbuf->row_ptr(y); + if(p) + { + p += x << 2; + return color_type(p[order_type::R], + p[order_type::G], + p[order_type::B], + p[order_type::A]); + } + return color_type::no_color(); } //-------------------------------------------------------------------- AGG_INLINE void copy_pixel(int x, int y, const color_type& c) { - value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2); p[order_type::R] = c.r; p[order_type::G] = c.g; p[order_type::B] = c.b; @@ -339,7 +1851,10 @@ namespace agg //-------------------------------------------------------------------- AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) { - blender_type::copy_or_blend_pix((value_type*)m_rbuf->row(y) + (x << 2), c, cover); + cob_type::copy_or_blend_pix( + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); } @@ -348,7 +1863,7 @@ namespace agg unsigned len, const color_type& c) { - value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); pixel_type v; ((value_type*)&v)[order_type::R] = c.r; ((value_type*)&v)[order_type::G] = c.g; @@ -368,7 +1883,6 @@ namespace agg unsigned len, const color_type& c) { - value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); pixel_type v; ((value_type*)&v)[order_type::R] = c.r; ((value_type*)&v)[order_type::G] = c.g; @@ -376,8 +1890,8 @@ namespace agg ((value_type*)&v)[order_type::A] = c.a; do { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); *(pixel_type*)p = v; - p = (value_type*)m_rbuf->next_row(p); } while(--len); } @@ -391,7 +1905,7 @@ namespace agg { if (c.a) { - value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { @@ -409,12 +1923,24 @@ namespace agg } else { - do + if(cover == 255) { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); - p += 4; + do + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha); + p += 4; + } + while(--len); + } + else + { + do + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); + p += 4; + } + while(--len); } - while(--len); } } } @@ -428,7 +1954,7 @@ namespace agg { if (c.a) { - value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); + value_type* p; calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; if(alpha == base_mask) { @@ -439,19 +1965,31 @@ namespace agg ((value_type*)&v)[order_type::A] = c.a; do { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); *(pixel_type*)p = v; - p = (value_type*)m_rbuf->next_row(p); } while(--len); } else { - do + if(cover == 255) { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); - p = (value_type*)m_rbuf->next_row(p); + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + blender_type::blend_pix(p, c.r, c.g, c.b, alpha); + } + while(--len); + } + else + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); + } + while(--len); } - while(--len); } } } @@ -465,7 +2003,7 @@ namespace agg { if (c.a) { - value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); do { calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; @@ -496,9 +2034,9 @@ namespace agg { if (c.a) { - value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); do { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; if(alpha == base_mask) { @@ -511,7 +2049,6 @@ namespace agg { blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); } - p = (value_type*)m_rbuf->next_row(p); ++covers; } while(--len); @@ -520,124 +2057,62 @@ namespace agg //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) { - value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); - if(covers) - { - do - { - blender_type::copy_or_blend_pix(p, *colors++, *covers++); - p += 4; - } - while(--len); - } - else + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do { - if(cover == 255) - { - do - { - if(colors->a == base_mask) - { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = base_mask; - } - else - { - blender_type::copy_or_blend_pix(p, *colors, 255); - } - p += 4; - ++colors; - } - while(--len); - } - else - { - do - { - blender_type::copy_or_blend_pix(p, *colors++, cover); - p += 4; - } - while(--len); - } + 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; + p += 4; } + while(--len); } - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) { - value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); - if(covers) - { - do - { - blender_type::copy_or_blend_pix(p, *colors++, *covers++); - p = (value_type*)m_rbuf->next_row(p); - } - while(--len); - } - else + do { - if(cover == 255) - { - do - { - if(colors->a == base_mask) - { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = base_mask; - } - else - { - blender_type::copy_or_blend_pix(p, *colors, 255); - } - p = (value_type*)m_rbuf->next_row(p); - ++colors; - } - while(--len); - } - else - { - do - { - blender_type::copy_or_blend_pix(p, *colors++, cover); - p = (value_type*)m_rbuf->next_row(p); - } - while(--len); - } + 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_opaque_color_hspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) { - value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); if(covers) { do { - blender_type::copy_or_blend_opaque_pix(p, *colors++, *covers++); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + *covers++); p += 4; + ++colors; } while(--len); } @@ -647,10 +2122,11 @@ namespace agg { do { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = base_mask; + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a); p += 4; ++colors; } @@ -660,8 +2136,14 @@ namespace agg { do { - blender_type::copy_or_blend_opaque_pix(p, *colors++, cover); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + cover); p += 4; + ++colors; } while(--len); } @@ -669,20 +2151,27 @@ namespace agg } + //-------------------------------------------------------------------- - void blend_opaque_color_vspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) { - value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); + value_type* p; if(covers) { do { - blender_type::copy_or_blend_opaque_pix(p, *colors++, *covers++); - p = (value_type*)m_rbuf->next_row(p); + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + *covers++); + ++colors; } while(--len); } @@ -692,11 +2181,12 @@ namespace agg { do { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = base_mask; - p = (value_type*)m_rbuf->next_row(p); + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a); ++colors; } while(--len); @@ -705,29 +2195,39 @@ namespace agg { do { - blender_type::copy_or_blend_opaque_pix(p, *colors++, cover); - p = (value_type*)m_rbuf->next_row(p); + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + cover); + ++colors; } while(--len); } } } - //-------------------------------------------------------------------- template<class Function> void for_each_pixel(Function f) { unsigned y; for(y = 0; y < height(); ++y) { - unsigned len = width(); - value_type* p = (value_type*)m_rbuf->row(y); - do + row_data r = m_rbuf->row(y); + if(r.ptr) { - f(p); - p += 4; + unsigned len = r.x2 - r.x1 + 1; + value_type* p = + (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); + do + { + f(p); + p += 4; + } + while(--len); } - while(--len); } } @@ -756,144 +2256,268 @@ namespace agg } //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) + template<class RenBuf2> void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) { - memmove((value_type*)m_rbuf->row(ydst) + xdst * 4, - (value_type*)from.row(ysrc) + xsrc * 4, - sizeof(value_type) * 4 * len); + const int8u* p = from.row_ptr(ysrc); + if(p) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } } - //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from(const SrcPixelFormatRenderer& from, - const int8u* psrc_, int xdst, int ydst, int xsrc, int ysrc, - unsigned len) + unsigned len, + int8u cover) { typedef typename SrcPixelFormatRenderer::order_type src_order; + const value_type* psrc = (value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc << 2; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } - const value_type* psrc = (const value_type*)psrc_; - value_type* pdst = (value_type*)m_rbuf->row(ydst) + (xdst << 2); - int incp = 4; - if(xdst > xsrc) + if(cover == 255) + { + do + { + cob_type::copy_or_blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A]); + psrc += incp; + pdst += incp; + } + while(--len); + } + else + { + do + { + cob_type::copy_or_blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A], + cover); + psrc += incp; + pdst += incp; + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) { - psrc += (len-1) << 2; - pdst += (len-1) << 2; - incp = -4; + 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); } - do + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) { - value_type alpha = psrc[src_order::A]; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - if(alpha) + if(cover == 255) { - if(alpha == base_mask) + do { - pdst[order_type::R] = psrc[src_order::R]; - pdst[order_type::G] = psrc[src_order::G]; - pdst[order_type::B] = psrc[src_order::B]; - pdst[order_type::A] = psrc[src_order::A]; + 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; } - else + while(--len); + } + else + { + do { - blender_type::blend_pix(pdst, - psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B], - alpha, - 255); + 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); } - psrc += incp; - pdst += incp; } - while(--len); } private: - rendering_buffer* m_rbuf; + rbuf_type* m_rbuf; }; - //================================================pixfmt_custom_rbuf_rgba - template<class Blender, class RenBuf> class pixfmt_custom_rbuf_rgba + //================================================pixfmt_custom_blend_rgba + template<class Blender, class RenBuf> class pixfmt_custom_blend_rgba { public: - typedef typename Blender::color_type color_type; - typedef typename Blender::order_type order_type; - typedef typename Blender::pixel_type pixel_type; + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - typedef blender_rgba_wrapper<Blender> blender_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, - base_size = color_type::base_size, - base_mask = color_type::base_mask + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(value_type) * 4 }; - typedef RenBuf rbuf_type; - typedef typename rbuf_type::row_data row_data; //-------------------------------------------------------------------- - pixfmt_custom_rbuf_rgba(rbuf_type& rb) : m_rbuf(&rb) {} + pixfmt_custom_blend_rgba() : m_rbuf(0), m_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(); } + template<class PixFmt> + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } //-------------------------------------------------------------------- - color_type pixel(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) { - const value_type* p = m_rbuf->span_ptr(x, y, 1); - return p ? color_type(p[order_type::R], - p[order_type::G], - p[order_type::B], - p[order_type::A]) : - color_type::no_color(); + 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 span(int x, int y) const + 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) + { + ((value_type*)p)[order_type::R] = c.r; + ((value_type*)p)[order_type::G] = c.g; + ((value_type*)p)[order_type::B] = c.b; + ((value_type*)p)[order_type::A] = c.a; + } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const { - return m_rbuf->span(x, y); + const value_type* p = (value_type*)m_rbuf->row_ptr(y) + (x << 2); + return color_type(p[order_type::R], + p[order_type::G], + p[order_type::B], + p[order_type::A]); } //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { - int8u* p = m_rbuf->span_ptr(x, y, 1); - p[order_type::R] = c.r; - p[order_type::G] = c.g; - p[order_type::B] = c.b; - p[order_type::A] = c.b; + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, 255); } //-------------------------------------------------------------------- void blend_pixel(int x, int y, const color_type& c, int8u cover) { - blender_type::copy_or_blend_pix((value_type*)m_rbuf->span_ptr(x, y, 1), c, cover); + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); } //-------------------------------------------------------------------- void copy_hline(int x, int y, unsigned len, const color_type& c) { - value_type* p = (value_type*)m_rbuf->span_ptr(x, y, len); - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);; do { - *(pixel_type*)p = v; + blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, 255); p += 4; } while(--len); @@ -902,14 +2526,12 @@ namespace agg //-------------------------------------------------------------------- void copy_vline(int x, int y, unsigned len, const color_type& c) { - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; do { - *(pixel_type*)(m_rbuf->span_ptr(x, y++, 1)) = v; + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, 255); } while(--len); } @@ -918,218 +2540,141 @@ namespace agg void blend_hline(int x, int y, unsigned len, const color_type& c, int8u cover) { - if (c.a) + + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do { - value_type* p = (value_type*)m_rbuf->span_ptr(x, y, len); - calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; - if(alpha == base_mask) - { - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do - { - *(pixel_type*)p = v; - p += 4; - } - while(--len); - } - else - { - do - { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); - p += 4; - } - while(--len); - } + blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, cover); + p += 4; } + while(--len); } //-------------------------------------------------------------------- void blend_vline(int x, int y, unsigned len, const color_type& c, int8u cover) { - if (c.a) + + do { - calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; - if(alpha == base_mask) - { - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do - { - *(pixel_type*)(m_rbuf->span_ptr(x, y++, 1)) = v; - } - while(--len); - } - else - { - do - { - blender_type::blend_pix(*(pixel_type*)m_rbuf->span_ptr(x, y++, 1), - c.r, c.g, c.b, alpha, cover); - } - while(--len); - } + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); } + while(--len); } - //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { - value_type* p = (value_type*)m_rbuf->span_ptr(x, y, len); + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); do { - blender_type::copy_or_blend_pix(p, c, *covers++); + blender_type::blend_pix(m_comp_op, + p, c.r, c.g, c.b, c.a, + *covers++); p += 4; } while(--len); } - - //-------------------------------------------------------------------- void blend_solid_vspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) { do { - blender_type::copy_or_blend_pix((value_type*)m_rbuf->span_ptr(x, y++, 1), - c, - *covers++); + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, + *covers++); } while(--len); } - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) { - value_type* p = (value_type*)m_rbuf->span_ptr(x, y, len); + + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); do { - blender_type::copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover); + 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; p += 4; } while(--len); } - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) { do { - blender_type::copy_or_blend_pix((value_type*)m_rbuf->span_ptr(x, y++, 1), - *colors++, covers ? *covers++ : cover); + 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_opaque_color_hspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) + void blend_color_hspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) { - value_type* p = (value_type*)m_rbuf->span_ptr(x, y, len); - if(covers) - { - do - { - blender_type::copy_or_blend_opaque_pix(p, *colors++, *covers++); - p += 4; - } - while(--len); - } - else + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do { - if(cover == 255) - { - do - { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = base_mask; - p += 4; - ++colors; - } - while(--len); - } - else - { - do - { - blender_type::copy_or_blend_opaque_pix(p, *colors++, cover); - p += 4; - } - while(--len); - } + blender_type::blend_pix(m_comp_op, + p, + colors->r, + colors->g, + colors->b, + colors->a, + covers ? *covers++ : cover); + p += 4; + ++colors; } + while(--len); } - //-------------------------------------------------------------------- - void blend_opaque_color_vspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) + void blend_color_vspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) { - if(covers) - { - do - { - blender_type::copy_or_blend_opaque_pix((value_type*)m_rbuf->span_ptr(x, y++, 1), - *colors++, *covers++); - } - while(--len); - } - else + do { - if(cover == 255) - { - do - { - value_type* p = (value_type*)m_rbuf->span_ptr(x, y++, 1); - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = base_mask; - ++colors; - } - while(--len); - } - else - { - do - { - blender_type::copy_or_blend_opaque_pix((value_type*)m_rbuf->span_ptr(x, y++, 1), - *colors++, cover); - } - while(--len); - } + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + colors->r, + colors->g, + colors->b, + colors->a, + covers ? *covers++ : cover); + ++colors; } - } - + while(--len); + } //-------------------------------------------------------------------- template<class Function> void for_each_pixel(Function f) @@ -1137,21 +2682,22 @@ namespace agg unsigned y; for(y = 0; y < height(); ++y) { - row_data sp = span(0, y); - if(sp.ptr) + row_data r = m_rbuf->row(y); + if(r.ptr) { - value_type* p = (value_type*)sp.ptr; - while(sp.x1 <= sp.x2) + unsigned len = r.x2 - r.x1 + 1; + value_type* p = + (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); + do { f(p); p += 4; - ++sp.x1; } + while(--len); } } } - //-------------------------------------------------------------------- void premultiply() { @@ -1182,130 +2728,174 @@ namespace agg int xsrc, int ysrc, unsigned len) { - const int8u* p = from.row(ysrc); + const int8u* p = from.row_ptr(ysrc); if(p) { - p += xsrc * 4 * sizeof(value_type); - memmove(m_rbuf->span_ptr(xdst, ydst, len), - p, - len * 4 * sizeof(value_type)); + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); } } - - //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from(const SrcPixelFormatRenderer& from, - const int8u* psrc_, int xdst, int ydst, int xsrc, int ysrc, - unsigned len) + unsigned len, + int8u cover) { typedef typename SrcPixelFormatRenderer::order_type src_order; - const value_type* psrc = (const value_type*)psrc_; - value_type* pdst = (value_type*)m_rbuf->span_ptr(xdst, ydst, len); - - int incp = 4; - if(xdst > xsrc) + const value_type* psrc = (const value_type*)from.row_ptr(ysrc); + if(psrc) { - psrc += (len-1) << 2; - pdst += (len-1) << 2; - incp = -4; + psrc += xsrc << 2; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } + + do + { + blender_type::blend_pix(m_comp_op, + pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A], + cover); + psrc += incp; + pdst += incp; + } + while(--len); } - do - { - value_type alpha = psrc[src_order::A]; + } - if(alpha) + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do { - if(alpha == base_mask) - { - pdst[order_type::R] = psrc[src_order::R]; - pdst[order_type::G] = psrc[src_order::G]; - pdst[order_type::B] = psrc[src_order::B]; - pdst[order_type::A] = psrc[src_order::A]; - } - else - { - blender_type::blend_pix(pdst, - psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B], - alpha, - 255); - } + 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; } - psrc += incp; - pdst += incp; + while(--len); } - while(--len); } + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do + { + const color_type& color = color_lut[*psrc]; + blender_type::blend_pix(m_comp_op, + pdst, + color.r, color.g, color.b, color.a, + cover); + ++psrc; + pdst += 4; + } + while(--len); + } + } private: rbuf_type* m_rbuf; + unsigned m_comp_op; }; - - - //----------------------------------------------------------------------- - typedef blender_rgba<rgba8, order_rgba, int32u> blender_rgba32; //----blender_rgba32 - typedef blender_rgba<rgba8, order_argb, int32u> blender_argb32; //----blender_argb32 - typedef blender_rgba<rgba8, order_abgr, int32u> blender_abgr32; //----blender_abgr32 - typedef blender_rgba<rgba8, order_bgra, int32u> blender_bgra32; //----blender_bgra32 + typedef blender_rgba<rgba8, order_rgba> blender_rgba32; //----blender_rgba32 + typedef blender_rgba<rgba8, order_argb> blender_argb32; //----blender_argb32 + typedef blender_rgba<rgba8, order_abgr> blender_abgr32; //----blender_abgr32 + typedef blender_rgba<rgba8, order_bgra> blender_bgra32; //----blender_bgra32 - typedef blender_rgba_pre<rgba8, order_rgba, int32u> blender_rgba32_pre; //----blender_rgba32_pre - typedef blender_rgba_pre<rgba8, order_argb, int32u> blender_argb32_pre; //----blender_argb32_pre - typedef blender_rgba_pre<rgba8, order_abgr, int32u> blender_abgr32_pre; //----blender_abgr32_pre - typedef blender_rgba_pre<rgba8, order_bgra, int32u> blender_bgra32_pre; //----blender_bgra32_pre + typedef blender_rgba_pre<rgba8, order_rgba> blender_rgba32_pre; //----blender_rgba32_pre + typedef blender_rgba_pre<rgba8, order_argb> blender_argb32_pre; //----blender_argb32_pre + typedef blender_rgba_pre<rgba8, order_abgr> blender_abgr32_pre; //----blender_abgr32_pre + typedef blender_rgba_pre<rgba8, order_bgra> blender_bgra32_pre; //----blender_bgra32_pre - typedef blender_rgba_plain<rgba8, order_rgba, int32u> blender_rgba32_plain; //----blender_rgba32_plain - typedef blender_rgba_plain<rgba8, order_argb, int32u> blender_argb32_plain; //----blender_argb32_plain - typedef blender_rgba_plain<rgba8, order_abgr, int32u> blender_abgr32_plain; //----blender_abgr32_plain - typedef blender_rgba_plain<rgba8, order_bgra, int32u> blender_bgra32_plain; //----blender_bgra32_plain + typedef blender_rgba_plain<rgba8, order_rgba> blender_rgba32_plain; //----blender_rgba32_plain + typedef blender_rgba_plain<rgba8, order_argb> blender_argb32_plain; //----blender_argb32_plain + typedef blender_rgba_plain<rgba8, order_abgr> blender_abgr32_plain; //----blender_abgr32_plain + typedef blender_rgba_plain<rgba8, order_bgra> blender_bgra32_plain; //----blender_bgra32_plain - struct pixel64_type { int16u c[4]; }; - typedef blender_rgba<rgba16, order_rgba, pixel64_type> blender_rgba64; //----blender_rgba64 - typedef blender_rgba<rgba16, order_argb, pixel64_type> blender_argb64; //----blender_argb64 - typedef blender_rgba<rgba16, order_abgr, pixel64_type> blender_abgr64; //----blender_abgr64 - typedef blender_rgba<rgba16, order_bgra, pixel64_type> blender_bgra64; //----blender_bgra64 + typedef blender_rgba<rgba16, order_rgba> blender_rgba64; //----blender_rgba64 + typedef blender_rgba<rgba16, order_argb> blender_argb64; //----blender_argb64 + typedef blender_rgba<rgba16, order_abgr> blender_abgr64; //----blender_abgr64 + typedef blender_rgba<rgba16, order_bgra> blender_bgra64; //----blender_bgra64 - typedef blender_rgba_pre<rgba16, order_rgba, pixel64_type> blender_rgba64_pre; //----blender_rgba64_pre - typedef blender_rgba_pre<rgba16, order_argb, pixel64_type> blender_argb64_pre; //----blender_argb64_pre - typedef blender_rgba_pre<rgba16, order_abgr, pixel64_type> blender_abgr64_pre; //----blender_abgr64_pre - typedef blender_rgba_pre<rgba16, order_bgra, pixel64_type> blender_bgra64_pre; //----blender_bgra64_pre + typedef blender_rgba_pre<rgba16, order_rgba> blender_rgba64_pre; //----blender_rgba64_pre + typedef blender_rgba_pre<rgba16, order_argb> blender_argb64_pre; //----blender_argb64_pre + typedef blender_rgba_pre<rgba16, order_abgr> blender_abgr64_pre; //----blender_abgr64_pre + typedef blender_rgba_pre<rgba16, order_bgra> blender_bgra64_pre; //----blender_bgra64_pre //----------------------------------------------------------------------- - typedef pixel_formats_rgba<blender_rgba32> pixfmt_rgba32; //----pixfmt_rgba32 - typedef pixel_formats_rgba<blender_argb32> pixfmt_argb32; //----pixfmt_argb32 - typedef pixel_formats_rgba<blender_abgr32> pixfmt_abgr32; //----pixfmt_abgr32 - typedef pixel_formats_rgba<blender_bgra32> pixfmt_bgra32; //----pixfmt_bgra32 - - typedef pixel_formats_rgba<blender_rgba32_pre> pixfmt_rgba32_pre; //----pixfmt_rgba32_pre - typedef pixel_formats_rgba<blender_argb32_pre> pixfmt_argb32_pre; //----pixfmt_argb32_pre - typedef pixel_formats_rgba<blender_abgr32_pre> pixfmt_abgr32_pre; //----pixfmt_abgr32_pre - typedef pixel_formats_rgba<blender_bgra32_pre> pixfmt_bgra32_pre; //----pixfmt_bgra32_pre - - typedef pixel_formats_rgba<blender_rgba32_plain> pixfmt_rgba32_plain; //----pixfmt_rgba32_plain - typedef pixel_formats_rgba<blender_argb32_plain> pixfmt_argb32_plain; //----pixfmt_argb32_plain - typedef pixel_formats_rgba<blender_abgr32_plain> pixfmt_abgr32_plain; //----pixfmt_abgr32_plain - typedef pixel_formats_rgba<blender_bgra32_plain> pixfmt_bgra32_plain; //----pixfmt_bgra32_plain - - typedef pixel_formats_rgba<blender_rgba64> pixfmt_rgba64; //----pixfmt_rgba64 - typedef pixel_formats_rgba<blender_argb64> pixfmt_argb64; //----pixfmt_argb64 - typedef pixel_formats_rgba<blender_abgr64> pixfmt_abgr64; //----pixfmt_abgr64 - typedef pixel_formats_rgba<blender_bgra64> pixfmt_bgra64; //----pixfmt_bgra64 - - typedef pixel_formats_rgba<blender_rgba64_pre> pixfmt_rgba64_pre; //----pixfmt_rgba64_pre - typedef pixel_formats_rgba<blender_argb64_pre> pixfmt_argb64_pre; //----pixfmt_argb64_pre - typedef pixel_formats_rgba<blender_abgr64_pre> pixfmt_abgr64_pre; //----pixfmt_abgr64_pre - typedef pixel_formats_rgba<blender_bgra64_pre> pixfmt_bgra64_pre; //----pixfmt_bgra64_pre + typedef int32u pixel32_type; + typedef pixfmt_alpha_blend_rgba<blender_rgba32, rendering_buffer, pixel32_type> pixfmt_rgba32; //----pixfmt_rgba32 + typedef pixfmt_alpha_blend_rgba<blender_argb32, rendering_buffer, pixel32_type> pixfmt_argb32; //----pixfmt_argb32 + typedef pixfmt_alpha_blend_rgba<blender_abgr32, rendering_buffer, pixel32_type> pixfmt_abgr32; //----pixfmt_abgr32 + typedef pixfmt_alpha_blend_rgba<blender_bgra32, rendering_buffer, pixel32_type> pixfmt_bgra32; //----pixfmt_bgra32 + + typedef pixfmt_alpha_blend_rgba<blender_rgba32_pre, rendering_buffer, pixel32_type> pixfmt_rgba32_pre; //----pixfmt_rgba32_pre + typedef pixfmt_alpha_blend_rgba<blender_argb32_pre, rendering_buffer, pixel32_type> pixfmt_argb32_pre; //----pixfmt_argb32_pre + typedef pixfmt_alpha_blend_rgba<blender_abgr32_pre, rendering_buffer, pixel32_type> pixfmt_abgr32_pre; //----pixfmt_abgr32_pre + typedef pixfmt_alpha_blend_rgba<blender_bgra32_pre, rendering_buffer, pixel32_type> pixfmt_bgra32_pre; //----pixfmt_bgra32_pre + + typedef pixfmt_alpha_blend_rgba<blender_rgba32_plain, rendering_buffer, pixel32_type> pixfmt_rgba32_plain; //----pixfmt_rgba32_plain + typedef pixfmt_alpha_blend_rgba<blender_argb32_plain, rendering_buffer, pixel32_type> pixfmt_argb32_plain; //----pixfmt_argb32_plain + typedef pixfmt_alpha_blend_rgba<blender_abgr32_plain, rendering_buffer, pixel32_type> pixfmt_abgr32_plain; //----pixfmt_abgr32_plain + typedef pixfmt_alpha_blend_rgba<blender_bgra32_plain, rendering_buffer, pixel32_type> pixfmt_bgra32_plain; //----pixfmt_bgra32_plain + + struct pixel64_type { int16u c[4]; }; + typedef pixfmt_alpha_blend_rgba<blender_rgba64, rendering_buffer, pixel64_type> pixfmt_rgba64; //----pixfmt_rgba64 + typedef pixfmt_alpha_blend_rgba<blender_argb64, rendering_buffer, pixel64_type> pixfmt_argb64; //----pixfmt_argb64 + typedef pixfmt_alpha_blend_rgba<blender_abgr64, rendering_buffer, pixel64_type> pixfmt_abgr64; //----pixfmt_abgr64 + typedef pixfmt_alpha_blend_rgba<blender_bgra64, rendering_buffer, pixel64_type> pixfmt_bgra64; //----pixfmt_bgra64 + + typedef pixfmt_alpha_blend_rgba<blender_rgba64_pre, rendering_buffer, pixel64_type> pixfmt_rgba64_pre; //----pixfmt_rgba64_pre + typedef pixfmt_alpha_blend_rgba<blender_argb64_pre, rendering_buffer, pixel64_type> pixfmt_argb64_pre; //----pixfmt_argb64_pre + typedef pixfmt_alpha_blend_rgba<blender_abgr64_pre, rendering_buffer, pixel64_type> pixfmt_abgr64_pre; //----pixfmt_abgr64_pre + typedef pixfmt_alpha_blend_rgba<blender_bgra64_pre, rendering_buffer, pixel64_type> pixfmt_bgra64_pre; //----pixfmt_bgra64_pre } #endif diff --git a/agg/inc/agg_rasterizer_cells_aa.h b/agg/inc/agg_rasterizer_cells_aa.h new file mode 100644 index 000000000000..1f99183be103 --- /dev/null +++ b/agg/inc/agg_rasterizer_cells_aa.h @@ -0,0 +1,754 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// libray - in producing this work. See http://www.freetype.org for details. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +#ifndef AGG_RASTERIZER_CELLS_AA_INCLUDED +#define AGG_RASTERIZER_CELLS_AA_INCLUDED + +#include <string.h> +#include <math.h> +#include "agg_math.h" +#include "agg_array.h" + + +namespace agg +{ + + //-----------------------------------------------------rasterizer_cells_aa + // An internal class that implements the main rasterization algorithm. + // Used in the rasterizer. Should not be used direcly. + template<class Cell> class rasterizer_cells_aa + { + enum cell_block_scale_e + { + cell_block_shift = 12, + cell_block_size = 1 << cell_block_shift, + cell_block_mask = cell_block_size - 1, + cell_block_pool = 256, + cell_block_limit = 1024 + }; + + struct sorted_y + { + unsigned start; + unsigned num; + }; + + public: + typedef Cell cell_type; + typedef rasterizer_cells_aa<Cell> self_type; + + ~rasterizer_cells_aa(); + rasterizer_cells_aa(); + + void reset(); + void style(const cell_type& style_cell); + void line(int x1, int y1, int x2, int y2); + + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + void sort_cells(); + + unsigned total_cells() const + { + return m_num_cells; + } + + unsigned scanline_num_cells(unsigned y) const + { + return m_sorted_y[y - m_min_y].num; + } + + const cell_type* const* scanline_cells(unsigned y) const + { + return m_sorted_cells.data() + m_sorted_y[y - m_min_y].start; + } + + bool sorted() const { return m_sorted; } + + private: + rasterizer_cells_aa(const self_type&); + const self_type& operator = (const self_type&); + + void set_curr_cell(int x, int y); + void add_curr_cell(); + void render_hline(int ey, int x1, int y1, int x2, int y2); + 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<cell_type*> m_sorted_cells; + pod_vector<sorted_y> 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; + }; + + + + + //------------------------------------------------------------------------ + template<class Cell> + rasterizer_cells_aa<Cell>::~rasterizer_cells_aa() + { + if(m_num_blocks) + { + cell_type** ptr = m_cells + m_num_blocks - 1; + while(m_num_blocks--) + { + pod_allocator<cell_type>::deallocate(*ptr, cell_block_size); + ptr--; + } + pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks); + } + } + + //------------------------------------------------------------------------ + template<class Cell> + rasterizer_cells_aa<Cell>::rasterizer_cells_aa() : + m_num_blocks(0), + m_max_blocks(0), + m_curr_block(0), + m_num_cells(0), + m_cells(0), + m_curr_cell_ptr(0), + m_sorted_cells(), + m_sorted_y(), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF), + m_sorted(false) + { + m_style_cell.initial(); + m_curr_cell.initial(); + } + + //------------------------------------------------------------------------ + template<class Cell> + void rasterizer_cells_aa<Cell>::reset() + { + m_num_cells = 0; + m_curr_block = 0; + m_curr_cell.initial(); + m_style_cell.initial(); + m_sorted = false; + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + } + + //------------------------------------------------------------------------ + template<class Cell> + AGG_INLINE void rasterizer_cells_aa<Cell>::add_curr_cell() + { + if(m_curr_cell.area | m_curr_cell.cover) + { + if((m_num_cells & cell_block_mask) == 0) + { + if(m_num_blocks >= cell_block_limit) return; + allocate_block(); + } + *m_curr_cell_ptr++ = m_curr_cell; + ++m_num_cells; + } + } + + //------------------------------------------------------------------------ + template<class Cell> + AGG_INLINE void rasterizer_cells_aa<Cell>::set_curr_cell(int x, int y) + { + if(m_curr_cell.not_equal(x, y, m_style_cell)) + { + add_curr_cell(); + m_curr_cell.style(m_style_cell); + m_curr_cell.x = x; + m_curr_cell.y = y; + m_curr_cell.cover = 0; + m_curr_cell.area = 0; + } + } + + //------------------------------------------------------------------------ + template<class Cell> + AGG_INLINE void rasterizer_cells_aa<Cell>::render_hline(int ey, + int x1, int y1, + int x2, int y2) + { + int ex1 = x1 >> poly_subpixel_shift; + int ex2 = x2 >> poly_subpixel_shift; + int fx1 = x1 & poly_subpixel_mask; + int fx2 = x2 & poly_subpixel_mask; + + int delta, p, first, dx; + int incr, lift, mod, rem; + + //trivial case. Happens often + if(y1 == y2) + { + set_curr_cell(ex2, ey); + return; + } + + //everything is located in a single cell. That is easy! + if(ex1 == ex2) + { + delta = y2 - y1; + m_curr_cell.cover += delta; + m_curr_cell.area += (fx1 + fx2) * delta; + return; + } + + //ok, we'll have to render a run of adjacent cells on the same + //hline... + p = (poly_subpixel_scale - fx1) * (y2 - y1); + first = poly_subpixel_scale; + incr = 1; + + dx = x2 - x1; + + if(dx < 0) + { + p = fx1 * (y2 - y1); + first = 0; + incr = -1; + dx = -dx; + } + + delta = p / dx; + mod = p % dx; + + if(mod < 0) + { + delta--; + mod += dx; + } + + m_curr_cell.cover += delta; + m_curr_cell.area += (fx1 + first) * delta; + + ex1 += incr; + set_curr_cell(ex1, ey); + y1 += delta; + + if(ex1 != ex2) + { + p = poly_subpixel_scale * (y2 - y1 + delta); + lift = p / dx; + rem = p % dx; + + if (rem < 0) + { + lift--; + rem += dx; + } + + mod -= dx; + + while (ex1 != ex2) + { + delta = lift; + mod += rem; + if(mod >= 0) + { + mod -= dx; + delta++; + } + + m_curr_cell.cover += delta; + m_curr_cell.area += poly_subpixel_scale * delta; + y1 += delta; + ex1 += incr; + set_curr_cell(ex1, ey); + } + } + delta = y2 - y1; + m_curr_cell.cover += delta; + m_curr_cell.area += (fx2 + poly_subpixel_scale - first) * delta; + } + + //------------------------------------------------------------------------ + template<class Cell> + AGG_INLINE void rasterizer_cells_aa<Cell>::style(const cell_type& style_cell) + { + m_style_cell.style(style_cell); + } + + //------------------------------------------------------------------------ + template<class Cell> + void rasterizer_cells_aa<Cell>::line(int x1, int y1, int x2, int y2) + { + enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift }; + + int dx = x2 - x1; + + if(dx >= dx_limit || dx <= -dx_limit) + { + int cx = (x1 + x2) >> 1; + int cy = (y1 + y2) >> 1; + line(x1, y1, cx, cy); + line(cx, cy, x2, y2); + } + + int dy = y2 - y1; + int ex1 = x1 >> poly_subpixel_shift; + int ex2 = x2 >> poly_subpixel_shift; + int ey1 = y1 >> poly_subpixel_shift; + int ey2 = y2 >> poly_subpixel_shift; + int fy1 = y1 & poly_subpixel_mask; + int fy2 = y2 & poly_subpixel_mask; + + int x_from, x_to; + int p, rem, mod, lift, delta, first, incr; + + if(ex1 < m_min_x) m_min_x = ex1; + if(ex1 > m_max_x) m_max_x = ex1; + if(ey1 < m_min_y) m_min_y = ey1; + if(ey1 > m_max_y) m_max_y = ey1; + if(ex2 < m_min_x) m_min_x = ex2; + if(ex2 > m_max_x) m_max_x = ex2; + if(ey2 < m_min_y) m_min_y = ey2; + if(ey2 > m_max_y) m_max_y = ey2; + + set_curr_cell(ex1, ey1); + + //everything is on a single hline + if(ey1 == ey2) + { + render_hline(ey1, x1, fy1, x2, fy2); + return; + } + + //Vertical line - we have to calculate start and end cells, + //and then - the common values of the area and coverage for + //all cells of the line. We know exactly there's only one + //cell, so, we don't have to call render_hline(). + incr = 1; + if(dx == 0) + { + int ex = x1 >> poly_subpixel_shift; + int two_fx = (x1 - (ex << poly_subpixel_shift)) << 1; + int area; + + first = poly_subpixel_scale; + if(dy < 0) + { + first = 0; + incr = -1; + } + + x_from = x1; + + //render_hline(ey1, x_from, fy1, x_from, first); + delta = first - fy1; + m_curr_cell.cover += delta; + m_curr_cell.area += two_fx * delta; + + ey1 += incr; + set_curr_cell(ex, ey1); + + delta = first + first - poly_subpixel_scale; + area = two_fx * delta; + while(ey1 != ey2) + { + //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, first); + m_curr_cell.cover = delta; + m_curr_cell.area = area; + ey1 += incr; + set_curr_cell(ex, ey1); + } + //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, fy2); + delta = fy2 - poly_subpixel_scale + first; + m_curr_cell.cover += delta; + m_curr_cell.area += two_fx * delta; + return; + } + + //ok, we have to render several hlines + p = (poly_subpixel_scale - fy1) * dx; + first = poly_subpixel_scale; + + if(dy < 0) + { + p = fy1 * dx; + first = 0; + incr = -1; + dy = -dy; + } + + delta = p / dy; + mod = p % dy; + + if(mod < 0) + { + delta--; + mod += dy; + } + + x_from = x1 + delta; + render_hline(ey1, x1, fy1, x_from, first); + + ey1 += incr; + set_curr_cell(x_from >> poly_subpixel_shift, ey1); + + if(ey1 != ey2) + { + p = poly_subpixel_scale * dx; + lift = p / dy; + rem = p % dy; + + if(rem < 0) + { + lift--; + rem += dy; + } + mod -= dy; + + while(ey1 != ey2) + { + delta = lift; + mod += rem; + if (mod >= 0) + { + mod -= dy; + delta++; + } + + x_to = x_from + delta; + render_hline(ey1, x_from, poly_subpixel_scale - first, x_to, first); + x_from = x_to; + + ey1 += incr; + set_curr_cell(x_from >> poly_subpixel_shift, ey1); + } + } + render_hline(ey1, x_from, poly_subpixel_scale - first, x2, fy2); + } + + //------------------------------------------------------------------------ + template<class Cell> + void rasterizer_cells_aa<Cell>::allocate_block() + { + if(m_curr_block >= m_num_blocks) + { + if(m_num_blocks >= m_max_blocks) + { + cell_type** new_cells = + pod_allocator<cell_type*>::allocate(m_max_blocks + + cell_block_pool); + + if(m_cells) + { + memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*)); + pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks); + } + m_cells = new_cells; + m_max_blocks += cell_block_pool; + } + + m_cells[m_num_blocks++] = + pod_allocator<cell_type>::allocate(cell_block_size); + + } + m_curr_cell_ptr = m_cells[m_curr_block++]; + } + + + + //------------------------------------------------------------------------ + template <class T> static AGG_INLINE void swap_cells(T* a, T* b) + { + T temp = *a; + *a = *b; + *b = temp; + } + + + //------------------------------------------------------------------------ + enum + { + qsort_threshold = 9 + }; + + + //------------------------------------------------------------------------ + template<class Cell> + void qsort_cells(Cell** start, unsigned num) + { + Cell** stack[80]; + Cell*** top; + Cell** limit; + Cell** base; + + limit = start + num; + base = start; + top = stack; + + for (;;) + { + int len = int(limit - base); + + Cell** i; + Cell** j; + Cell** pivot; + + if(len > qsort_threshold) + { + // we use base + len/2 as the pivot + pivot = base + len / 2; + swap_cells(base, pivot); + + i = base + 1; + j = limit - 1; + + // now ensure that *i <= *base <= *j + if((*j)->x < (*i)->x) + { + swap_cells(i, j); + } + + if((*base)->x < (*i)->x) + { + swap_cells(base, i); + } + + if((*j)->x < (*base)->x) + { + swap_cells(base, j); + } + + for(;;) + { + int x = (*base)->x; + do i++; while( (*i)->x < x ); + do j--; while( x < (*j)->x ); + + if(i > j) + { + break; + } + + swap_cells(i, j); + } + + swap_cells(base, j); + + // now, push the largest sub-array + if(j - base > limit - i) + { + top[0] = base; + top[1] = j; + base = i; + } + else + { + top[0] = i; + top[1] = limit; + limit = j; + } + top += 2; + } + else + { + // the sub-array is small, perform insertion sort + j = base; + i = j + 1; + + for(; i < limit; j = i, i++) + { + for(; j[1]->x < (*j)->x; j--) + { + swap_cells(j + 1, j); + if (j == base) + { + break; + } + } + } + + if(top > stack) + { + top -= 2; + base = top[0]; + limit = top[1]; + } + else + { + break; + } + } + } + } + + + //------------------------------------------------------------------------ + template<class Cell> + void rasterizer_cells_aa<Cell>::sort_cells() + { + if(m_sorted) return; //Perform sort only the first time. + + add_curr_cell(); + m_curr_cell.x = 0x7FFFFFFF; + m_curr_cell.y = 0x7FFFFFFF; + m_curr_cell.cover = 0; + m_curr_cell.area = 0; + + if(m_num_cells == 0) return; + +// DBG: Check to see if min/max works well. +//for(unsigned nc = 0; nc < m_num_cells; nc++) +//{ +// cell_type* cell = m_cells[nc >> cell_block_shift] + (nc & cell_block_mask); +// if(cell->x < m_min_x || +// cell->y < m_min_y || +// cell->x > m_max_x || +// cell->y > m_max_y) +// { +// cell = cell; // Breakpoint here +// } +//} + // Allocate the array of cell pointers + m_sorted_cells.allocate(m_num_cells, 16); + + // Allocate and zero the Y array + m_sorted_y.allocate(m_max_y - m_min_y + 1, 16); + m_sorted_y.zero(); + + // Create the Y-histogram (count the numbers of cells for each Y) + cell_type** block_ptr = m_cells; + cell_type* cell_ptr; + unsigned nb = m_num_cells >> cell_block_shift; + unsigned i; + while(nb--) + { + cell_ptr = *block_ptr++; + i = cell_block_size; + while(i--) + { + m_sorted_y[cell_ptr->y - m_min_y].start++; + ++cell_ptr; + } + } + + cell_ptr = *block_ptr++; + i = m_num_cells & cell_block_mask; + while(i--) + { + m_sorted_y[cell_ptr->y - m_min_y].start++; + ++cell_ptr; + } + + // Convert the Y-histogram into the array of starting indexes + unsigned start = 0; + for(i = 0; i < m_sorted_y.size(); i++) + { + unsigned v = m_sorted_y[i].start; + m_sorted_y[i].start = start; + start += v; + } + + // Fill the cell pointer array sorted by Y + block_ptr = m_cells; + nb = m_num_cells >> cell_block_shift; + while(nb--) + { + cell_ptr = *block_ptr++; + i = cell_block_size; + while(i--) + { + sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y]; + m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr; + ++curr_y.num; + ++cell_ptr; + } + } + + cell_ptr = *block_ptr++; + i = m_num_cells & cell_block_mask; + while(i--) + { + sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y]; + m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr; + ++curr_y.num; + ++cell_ptr; + } + + // Finally arrange the X-arrays + for(i = 0; i < m_sorted_y.size(); i++) + { + const sorted_y& curr_y = m_sorted_y[i]; + if(curr_y.num) + { + qsort_cells(m_sorted_cells.data() + curr_y.start, curr_y.num); + } + } + 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/inc/agg_rasterizer_compound_aa.h b/agg/inc/agg_rasterizer_compound_aa.h new file mode 100644 index 000000000000..3025c2909eec --- /dev/null +++ b/agg/inc/agg_rasterizer_compound_aa.h @@ -0,0 +1,698 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.3 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// libray - in producing this work. See http://www.freetype.org for details. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +#ifndef AGG_RASTERIZER_COMPOUND_AA_INCLUDED +#define AGG_RASTERIZER_COMPOUND_AA_INCLUDED + +#include "agg_rasterizer_cells_aa.h" +#include "agg_rasterizer_sl_clip.h" + +namespace agg +{ + + //-----------------------------------------------------------cell_style_aa + // A pixel cell. There're no constructors defined and it was done + // intentionally in order to avoid extra overhead when allocating an + // array of cells. + struct cell_style_aa + { + int x; + int y; + int cover; + int area; + int16 left, right; + + void initial() + { + x = 0x7FFFFFFF; + y = 0x7FFFFFFF; + cover = 0; + area = 0; + left = -1; + right = -1; + } + + void style(const cell_style_aa& c) + { + left = c.left; + right = c.right; + } + + int not_equal(int ex, int ey, const cell_style_aa& c) const + { + return (ex - x) | (ey - y) | (left - c.left) | (right - c.right); + } + }; + + + //===========================================================layer_order_e + enum layer_order_e + { + layer_unsorted, //------layer_unsorted + layer_direct, //------layer_direct + layer_inverse //------layer_inverse + }; + + + //==================================================rasterizer_compound_aa + template<class Clip=rasterizer_sl_clip_int> class rasterizer_compound_aa + { + struct style_info + { + unsigned start_cell; + unsigned num_cells; + int last_x; + }; + + struct cell_info + { + int x, area, cover; + }; + + public: + typedef Clip clip_type; + typedef typename Clip::conv_type conv_type; + typedef typename Clip::coord_type coord_type; + + enum aa_scale_e + { + aa_shift = 8, + aa_scale = 1 << aa_shift, + aa_mask = aa_scale - 1, + aa_scale2 = aa_scale * 2, + aa_mask2 = aa_scale2 - 1 + }; + + //-------------------------------------------------------------------- + rasterizer_compound_aa() : + 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_start_x(0), + m_start_y(0), + m_scan_y(0x7FFFFFFF), + m_sl_start(0), + m_sl_len(0) + {} + + //-------------------------------------------------------------------- + void reset(); + 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); + void move_to(int x, int y); + void line_to(int x, int y); + void move_to_d(double x, double y); + void line_to_d(double x, double y); + void add_vertex(double x, double y, unsigned cmd); + + void edge(int x1, int y1, int x2, int y2); + void edge_d(double x1, double y1, double x2, double y2); + + //------------------------------------------------------------------- + template<class VertexSource> + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + if(m_outline.sorted()) reset(); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + } + + + //-------------------------------------------------------------------- + int min_x() const { return m_outline.min_x(); } + int min_y() const { return m_outline.min_y(); } + int max_x() const { return m_outline.max_x(); } + int max_y() const { return m_outline.max_y(); } + int min_style() const { return m_min_style; } + int max_style() const { return m_max_style; } + + //-------------------------------------------------------------------- + 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); + + //-------------------------------------------------------------------- + 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; + if(m_filling_rule == fill_even_odd) + { + cover &= aa_mask2; + if(cover > aa_scale) + { + cover = aa_scale2 - cover; + } + } + if(cover > aa_mask) cover = aa_mask; + return (cover * master_alpha + aa_mask) >> aa_shift; + } + + //-------------------------------------------------------------------- + // Sweeps one scanline with one style index. The style ID can be + // determined by calling style(). + template<class Scanline> bool sweep_scanline(Scanline& sl, int style_idx) + { + int scan_y = m_scan_y - 1; + if(scan_y > m_outline.max_y()) return false; + + sl.reset_spans(); + + 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]]; + + unsigned num_cells = st.num_cells; + cell_info* cell = &m_cells[st.start_cell]; + + int cover = 0; + while(num_cells--) + { + unsigned alpha; + int x = cell->x; + int area = cell->area; + + cover += cell->cover; + + ++cell; + + if(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), + master_alpha); + if(alpha) + { + sl.add_span(x, cell->x - x, alpha); + } + } + } + + 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 + rasterizer_compound_aa(const rasterizer_compound_aa<Clip>&); + const rasterizer_compound_aa<Clip>& + operator = (const rasterizer_compound_aa<Clip>&); + + private: + rasterizer_cells_aa<cell_style_aa> m_outline; + clip_type m_clipper; + filling_rule_e m_filling_rule; + layer_order_e m_layer_order; + pod_vector<style_info> m_styles; // Active Styles + pod_vector<unsigned> m_ast; // Active Style Table (unique values) + pod_vector<int8u> m_asm; // Active Style Mask + pod_vector<cell_info> m_cells; + pod_vector<cover_type> m_cover_buf; + pod_bvector<unsigned> m_master_alpha; + + int m_min_style; + int m_max_style; + coord_type m_start_x; + coord_type m_start_y; + int m_scan_y; + int m_sl_start; + unsigned m_sl_len; + }; + + + + + + + + + + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::reset() + { + m_outline.reset(); + m_min_style = 0x7FFFFFFF; + m_max_style = -0x7FFFFFFF; + m_scan_y = 0x7FFFFFFF; + m_sl_start = 0; + m_sl_len = 0; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::filling_rule(filling_rule_e filling_rule) + { + m_filling_rule = filling_rule; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::layer_order(layer_order_e order) + { + m_layer_order = order; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::clip_box(double x1, double y1, + double x2, double y2) + { + reset(); + m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), + conv_type::upscale(x2), conv_type::upscale(y2)); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::reset_clipping() + { + reset(); + m_clipper.reset_clipping(); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::styles(int left, int right) + { + cell_style_aa cell; + cell.initial(); + cell.left = (int16)left; + cell.right = (int16)right; + m_outline.style(cell); + if(left >= 0 && left < m_min_style) m_min_style = left; + if(left >= 0 && left > m_max_style) m_max_style = left; + if(right >= 0 && right < m_min_style) m_min_style = right; + if(right >= 0 && right > m_max_style) m_max_style = right; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::move_to(int x, int y) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(m_start_x = conv_type::downscale(x), + m_start_y = conv_type::downscale(y)); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::line_to(int x, int y) + { + m_clipper.line_to(m_outline, + conv_type::downscale(x), + conv_type::downscale(y)); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::move_to_d(double x, double y) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(m_start_x = conv_type::upscale(x), + m_start_y = conv_type::upscale(y)); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::line_to_d(double x, double y) + { + m_clipper.line_to(m_outline, + conv_type::upscale(x), + conv_type::upscale(y)); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + move_to_d(x, y); + } + else + if(is_vertex(cmd)) + { + line_to_d(x, y); + } + else + if(is_close(cmd)) + { + m_clipper.line_to(m_outline, m_start_x, m_start_y); + } + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::edge(int x1, int y1, int x2, int y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); + m_clipper.line_to(m_outline, + conv_type::downscale(x2), + conv_type::downscale(y2)); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::edge_d(double x1, double y1, + double x2, double y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); + m_clipper.line_to(m_outline, + conv_type::upscale(x2), + conv_type::upscale(y2)); + } + + //------------------------------------------------------------------------ + template<class Clip> + AGG_INLINE void rasterizer_compound_aa<Clip>::sort() + { + m_outline.sort_cells(); + } + + //------------------------------------------------------------------------ + template<class Clip> + AGG_INLINE bool rasterizer_compound_aa<Clip>::rewind_scanlines() + { + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) + { + return false; + } + if(m_max_style < m_min_style) + { + return false; + } + m_scan_y = m_outline.min_y(); + m_styles.allocate(m_max_style - m_min_style + 2, 128); + allocate_master_alpha(); + return true; + } + + //------------------------------------------------------------------------ + template<class Clip> + AGG_INLINE void rasterizer_compound_aa<Clip>::add_style(int style_id) + { + if(style_id < 0) style_id = 0; + else style_id -= m_min_style - 1; + + unsigned nbyte = style_id >> 3; + unsigned mask = 1 << (style_id & 7); + + style_info* style = &m_styles[style_id]; + if((m_asm[nbyte] & mask) == 0) + { + m_ast.add(style_id); + m_asm[nbyte] |= mask; + style->start_cell = 0; + style->num_cells = 0; + style->last_x = -0x7FFFFFFF; + } + ++style->start_cell; + } + + //------------------------------------------------------------------------ + // Returns the number of styles + template<class Clip> + unsigned rasterizer_compound_aa<Clip>::sweep_styles() + { + for(;;) + { + if(m_scan_y > m_outline.max_y()) return 0; + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + const cell_style_aa* const* cells = m_outline.scanline_cells(m_scan_y); + unsigned num_styles = m_max_style - m_min_style + 2; + const cell_style_aa* curr_cell; + unsigned style_id; + style_info* style; + cell_info* cell; + + m_cells.allocate(num_cells * 2, 256); // Each cell can have two styles + m_ast.capacity(num_styles, 64); + m_asm.allocate((num_styles + 7) >> 3, 8); + m_asm.zero(); + + if(num_cells) + { + // Pre-add zero (for no-fill style, that is, -1). + // We need that to ensure that the "-1 style" would go first. + m_asm[0] |= 1; + m_ast.add(0); + style = &m_styles[0]; + style->start_cell = 0; + style->num_cells = 0; + style->last_x = -0x7FFFFFFF; + + m_sl_start = cells[0]->x; + m_sl_len = cells[num_cells-1]->x - m_sl_start + 1; + while(num_cells--) + { + curr_cell = *cells++; + add_style(curr_cell->left); + add_style(curr_cell->right); + } + + // 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) + { + 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<pod_vector<unsigned> > ra(m_ast, 1, m_ast.size() - 1); + if(m_layer_order == layer_direct) quick_sort(ra, unsigned_greater); + else quick_sort(ra, unsigned_less); + } + + return m_ast.size() - 1; + } + + //------------------------------------------------------------------------ + // Returns style ID depending of the existing style index + template<class Clip> + AGG_INLINE + unsigned rasterizer_compound_aa<Clip>::style(unsigned style_idx) const + { + return m_ast[style_idx + 1] + m_min_style - 1; + } + + //------------------------------------------------------------------------ + template<class Clip> + AGG_INLINE bool rasterizer_compound_aa<Clip>::navigate_scanline(int y) + { + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) + { + return false; + } + if(m_max_style < m_min_style) + { + return false; + } + if(y < m_outline.min_y() || y > m_outline.max_y()) + { + return false; + } + m_scan_y = y; + m_styles.allocate(m_max_style - m_min_style + 2, 128); + allocate_master_alpha(); + return true; + } + + //------------------------------------------------------------------------ + template<class Clip> + bool rasterizer_compound_aa<Clip>::hit_test(int tx, int ty) + { + if(!navigate_scanline(ty)) + { + return false; + } + + unsigned num_styles = sweep_styles(); + if(num_styles <= 0) + { + return false; + } + + scanline_hit_test sl(tx); + sweep_scanline(sl, -1); + return sl.hit(); + } + + //------------------------------------------------------------------------ + template<class Clip> + cover_type* rasterizer_compound_aa<Clip>::allocate_cover_buffer(unsigned len) + { + m_cover_buf.allocate(len, 256); + return &m_cover_buf[0]; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::allocate_master_alpha() + { + while((int)m_master_alpha.size() <= m_max_style) + { + m_master_alpha.add(aa_mask); + } + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::master_alpha(int style, double alpha) + { + if(style >= 0) + { + while((int)m_master_alpha.size() <= style) + { + m_master_alpha.add(aa_mask); + } + m_master_alpha[style] = uround(alpha * aa_mask); + } + } + +} + + + +#endif + diff --git a/agg/inc/agg_rasterizer_outline.h b/agg/inc/agg_rasterizer_outline.h index 18512e76a1ad..4c7c6804d6d2 100755 --- a/agg/inc/agg_rasterizer_outline.h +++ b/agg/inc/agg_rasterizer_outline.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -23,13 +23,14 @@ namespace agg template<class Renderer> class rasterizer_outline { public: - rasterizer_outline(Renderer& ren) : + explicit rasterizer_outline(Renderer& ren) : m_ren(&ren), m_start_x(0), m_start_y(0), m_vertices(0) - { - } + {} + void attach(Renderer& ren) { m_ren = &ren; } + //-------------------------------------------------------------------- void move_to(int x, int y) @@ -90,13 +91,13 @@ namespace agg //-------------------------------------------------------------------- template<class VertexSource> - void add_path(VertexSource& vs, unsigned id=0) + void add_path(VertexSource& vs, unsigned path_id=0) { double x; double y; unsigned cmd; - vs.rewind(id); + vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x, &y))) { add_vertex(x, y, cmd); @@ -108,13 +109,13 @@ namespace agg template<class VertexSource, class ColorStorage, class PathId> void render_all_paths(VertexSource& vs, const ColorStorage& colors, - const PathId& id, + const PathId& path_id, unsigned num_paths) { for(unsigned i = 0; i < num_paths; i++) { m_ren->line_color(colors[i]); - add_path(vs, id[i]); + add_path(vs, path_id[i]); } } diff --git a/agg/inc/agg_rasterizer_outline_aa.h b/agg/inc/agg_rasterizer_outline_aa.h index 3f4d6395fafa..0e00c537c240 100755 --- a/agg/inc/agg_rasterizer_outline_aa.h +++ b/agg/inc/agg_rasterizer_outline_aa.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -49,16 +49,23 @@ namespace agg { double dx = val.x - x; double dy = val.y - y; - return (len = int(sqrt(dx * dx + dy * dy))) > - (line_subpixel_size + line_subpixel_size / 2); + return (len = uround(sqrt(dx * dx + dy * dy))) > + (line_subpixel_scale + line_subpixel_scale / 2); } }; - + //----------------------------------------------------------outline_aa_join_e + enum outline_aa_join_e + { + outline_no_join, //-----outline_no_join + outline_miter_join, //-----outline_miter_join + outline_round_join, //-----outline_round_join + outline_miter_accurate_join //-----outline_accurate_join + }; //=======================================================rasterizer_outline_aa - template<class Renderer> class rasterizer_outline_aa + template<class Renderer, class Coord=line_coord> class rasterizer_outline_aa { private: //------------------------------------------------------------------------ @@ -78,21 +85,25 @@ namespace agg typedef line_aa_vertex vertex_type; typedef vertex_sequence<vertex_type, 6> vertex_storage_type; - rasterizer_outline_aa(Renderer& ren) : - m_ren(ren), - m_accurate_join(m_ren.accurate_join_only()), + 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 accurate_join(bool v) + void line_join(outline_aa_join_e join) { - m_accurate_join = m_ren.accurate_join_only() ? true : v; + m_line_join = m_ren->accurate_join_only() ? + outline_miter_accurate_join : + join; } - bool accurate_join() const { return m_accurate_join; } + bool line_join() const { return m_line_join; } //------------------------------------------------------------------------ void round_cap(bool v) { m_round_cap = v; } @@ -113,13 +124,13 @@ namespace agg //------------------------------------------------------------------------ void move_to_d(double x, double y) { - move_to(line_coord(x), line_coord(y)); + move_to(Coord::conv(x), Coord::conv(y)); } //------------------------------------------------------------------------ void line_to_d(double x, double y) { - line_to(line_coord(x), line_coord(y)); + line_to(Coord::conv(x), Coord::conv(y)); } //------------------------------------------------------------------------ @@ -152,13 +163,13 @@ namespace agg //------------------------------------------------------------------------ template<class VertexSource> - void add_path(VertexSource& vs, unsigned id=0) + void add_path(VertexSource& vs, unsigned path_id=0) { double x; double y; unsigned cmd; - vs.rewind(id); + vs.rewind(path_id); while(!is_stop(cmd = vs.vertex(&x, &y))) { add_vertex(x, y, cmd); @@ -171,13 +182,13 @@ namespace agg template<class VertexSource, class ColorStorage, class PathId> void render_all_paths(VertexSource& vs, const ColorStorage& colors, - const PathId& id, + const PathId& path_id, unsigned num_paths) { for(unsigned i = 0; i < num_paths; i++) { - m_ren.color(colors[i]); - add_path(vs, id[i]); + m_ren->color(colors[i]); + add_path(vs, path_id[i]); } } @@ -188,22 +199,22 @@ 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); } } private: - rasterizer_outline_aa(const rasterizer_outline_aa<Renderer>&); - const rasterizer_outline_aa<Renderer>& operator = - (const rasterizer_outline_aa<Renderer>&); + rasterizer_outline_aa(const rasterizer_outline_aa<Renderer, Coord>&); + const rasterizer_outline_aa<Renderer, Coord>& operator = + (const rasterizer_outline_aa<Renderer, Coord>&); - Renderer& m_ren; + Renderer* m_ren; vertex_storage_type m_src_vertices; - bool m_accurate_join; - bool m_round_cap; - int m_start_x; - int m_start_y; + outline_aa_join_e m_line_join; + bool m_round_cap; + int m_start_x; + int m_start_y; }; @@ -214,20 +225,39 @@ namespace agg //---------------------------------------------------------------------------- - template<class Renderer> - void rasterizer_outline_aa<Renderer>::draw(draw_vars& dv, unsigned start, unsigned end) + template<class Renderer, class Coord> + void rasterizer_outline_aa<Renderer, Coord>::draw(draw_vars& dv, + unsigned start, + unsigned end) { unsigned i; const vertex_storage_type::value_type* v; for(i = start; i < end; i++) { + if(m_line_join == outline_round_join) + { + dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1); + dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1); + dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1); + dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1); + } + 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)); } dv.x1 = dv.x2; @@ -247,20 +277,32 @@ namespace agg dv.xb1 = dv.xb2; dv.yb1 = dv.yb2; - if(m_accurate_join) - { - dv.flags = 0; - } - else + switch(m_line_join) { + case outline_no_join: + dv.flags = 3; + break; + + case outline_miter_join: dv.flags >>= 1; dv.flags |= ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); - } + if((dv.flags & 2) == 0) + { + bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + } + break; - if((dv.flags & 2) == 0) - { + case outline_round_join: + dv.flags >>= 1; + dv.flags |= ((dv.curr.diagonal_quadrant() == + dv.next.diagonal_quadrant()) << 1); + break; + + case outline_miter_accurate_join: + dv.flags = 0; bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + break; } } } @@ -269,8 +311,8 @@ namespace agg //---------------------------------------------------------------------------- - template<class Renderer> - void rasterizer_outline_aa<Renderer>::render(bool close_polygon) + template<class Renderer, class Coord> + void rasterizer_outline_aa<Renderer, Coord>::render(bool close_polygon) { m_src_vertices.close(close_polygon); draw_vars dv; @@ -314,23 +356,30 @@ namespace agg dv.xb2 = 0; dv.yb2 = 0; - if(m_accurate_join) - { - dv.flags = 0; - } - else + switch(m_line_join) { + case outline_no_join: + dv.flags = 3; + break; + + case outline_miter_join: + case outline_round_join: dv.flags = (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); + break; + + case outline_miter_accurate_join: + dv.flags = 0; + break; } - if((dv.flags & 1) == 0) + if((dv.flags & 1) == 0 && m_line_join != outline_round_join) { bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); } - if((dv.flags & 2) == 0) + if((dv.flags & 2) == 0 && m_line_join != outline_round_join) { bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); } @@ -357,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; @@ -388,26 +437,35 @@ namespace agg y3 = v->y; line_parameters lp1(x1, y1, x2, y2, lprev); line_parameters lp2(x2, y2, x3, y3, lnext); - bisectrix(lp1, lp2, &dv.xb1, &dv.yb1); 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->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)); + } + 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(lp2, dv.xb1, dv.yb1, + x3 + (y3 - y2), y3 - (x3 - x2)); } - 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)); 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; @@ -443,37 +501,53 @@ namespace agg dv.xb2 = 0; dv.yb2 = 0; - if(m_accurate_join) - { - dv.flags = 0; - } - else + switch(m_line_join) { + case outline_no_join: + dv.flags = 3; + break; + + case outline_miter_join: + case outline_round_join: dv.flags = (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); + break; + + case outline_miter_accurate_join: + dv.flags = 0; + break; } - if((dv.flags & 1) == 0) + if(m_round_cap) { - bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); - m_ren.line3(prev, - x1 + (y2 - y1), - y1 - (x2 - x1), - dv.xb1, - dv.yb1); + m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); } - else + if((dv.flags & 1) == 0) { - m_ren.line1(prev, - x1 + (y2 - y1), - y1 - (x2 - x1)); + 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)); + } + else + { + bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); + m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), + dv.xb1, dv.yb1); + } } - if(m_round_cap) + else { - m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + m_ren->line1(prev, + x1 + (y2 - y1), + y1 - (x2 - x1)); } - if((dv.flags & 2) == 0) + if((dv.flags & 2) == 0 && m_line_join != outline_round_join) { bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); } @@ -482,23 +556,32 @@ namespace agg if((dv.flags & 1) == 0) { - 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)); + 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)); + } + 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)); + } } 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/inc/agg_rasterizer_scanline_aa.h b/agg/inc/agg_rasterizer_scanline_aa.h index 03be55dcc62a..d07360e45594 100755 --- a/agg/inc/agg_rasterizer_scanline_aa.h +++ b/agg/inc/agg_rasterizer_scanline_aa.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -7,6 +7,8 @@ // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // +//---------------------------------------------------------------------------- +// // The author gratefully acknowleges the support of David Turner, // Robert Wilhelm, and Werner Lemberg - the authors of the FreeType // libray - in producing this work. See http://www.freetype.org for details. @@ -17,43 +19,24 @@ // http://www.antigrain.com //---------------------------------------------------------------------------- // -// Class rasterizer_scanline_aa +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com // +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- #ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED #define AGG_RASTERIZER_SCANLINE_AA_INCLUDED -#include <string.h> -#include <math.h> -#include "agg_basics.h" -#include "agg_math.h" +#include "agg_rasterizer_cells_aa.h" +#include "agg_rasterizer_sl_clip.h" #include "agg_gamma_functions.h" -#include "agg_clip_liang_barsky.h" -#include "agg_render_scanlines.h" namespace agg { - //------------------------------------------------------------------------ - // These constants determine the subpixel accuracy, to be more precise, - // the number of bits of the fractional part of the coordinates. - // The possible coordinate capacity in bits can be calculated by formula: - // sizeof(int) * 8 - poly_base_shift * 2, i.e, for 32-bit integers and - // 8-bits fractional part the capacity is 16 bits or [-32768...32767]. - enum - { - poly_base_shift = 8, //----poly_base_shift - poly_base_size = 1 << poly_base_shift, //----poly_base_size - poly_base_mask = poly_base_size - 1 //----poly_base_mask - }; - - //--------------------------------------------------------------poly_coord - inline int poly_coord(double c) - { - return int(c * poly_base_size); - } //-----------------------------------------------------------------cell_aa // A pixel cell. There're no constructors defined and it was done @@ -61,90 +44,25 @@ namespace agg // array of cells. struct cell_aa { - int16 x; - int16 y; - int packed_coord; - int cover; - int area; - - void set(int x, int y, int c, int a); - void set_coord(int x, int y); - void set_cover(int c, int a); - void add_cover(int c, int a); - }; - + int x; + int y; + int cover; + int area; - //--------------------------------------------------------------outline_aa - // An internal class that implements the main rasterization algorithm. - // Used in the rasterizer. Should not be used direcly. - class outline_aa - { - enum + void initial() { - cell_block_shift = 12, - cell_block_size = 1 << cell_block_shift, - cell_block_mask = cell_block_size - 1, - cell_block_pool = 256, - cell_block_limit = 1024 - }; - - public: - - ~outline_aa(); - outline_aa(); - - void reset(); - - void move_to(int x, int y); - void line_to(int x, int y); - - int min_x() const { return m_min_x; } - int min_y() const { return m_min_y; } - int max_x() const { return m_max_x; } - int max_y() const { return m_max_y; } - - const cell_aa* const* cells(); - unsigned num_cells() { cells(); return m_num_cells; } - bool sorted() const { return m_sorted; } - - private: - outline_aa(const outline_aa&); - const outline_aa& operator = (const outline_aa&); - - void set_cur_cell(int x, int y); - void add_cur_cell(); - void sort_cells(); - void render_hline(int ey, int x1, int y1, int x2, int y2); - void render_line(int x1, int y1, int x2, int y2); - void allocate_block(); - - static void qsort_cells(cell_aa** start, unsigned num); - - private: - unsigned m_num_blocks; - unsigned m_max_blocks; - unsigned m_cur_block; - unsigned m_num_cells; - cell_aa** m_cells; - cell_aa* m_cur_cell_ptr; - cell_aa** m_sorted_cells; - unsigned m_sorted_size; - cell_aa m_cur_cell; - int m_cur_x; - int m_cur_y; - int m_min_x; - int m_min_y; - int m_max_x; - int m_max_y; - bool m_sorted; - }; + x = 0x7FFFFFFF; + y = 0x7FFFFFFF; + cover = 0; + area = 0; + } + void style(const cell_aa&) {} - //----------------------------------------------------------filling_rule_e - enum filling_rule_e - { - fill_non_zero, - fill_even_odd + int not_equal(int ex, int ey, const cell_aa&) const + { + return (ex - x) | (ey - y); + } }; @@ -152,7 +70,7 @@ namespace agg // Polygon rasterizer that is used to render filled polygons with // high-quality Anti-Aliasing. Internally, by default, the class uses // integer coordinates in format 24.8, i.e. 24 bits for integer part - // and 8 bits for fractional - see poly_base_shift. This class can be + // and 8 bits for fractional - see poly_subpixel_shift. This class can be // used in the following way: // // 1. filling_rule(filling_rule_e ft) - optional. @@ -179,79 +97,72 @@ namespace agg // // filling_rule() and gamma() can be called anytime before "sweeping". //------------------------------------------------------------------------ - template<unsigned XScale=1, unsigned AA_Shift=8> class rasterizer_scanline_aa + template<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa { enum status { status_initial, + status_move_to, status_line_to, status_closed }; - struct iterator - { - const cell_aa* const* cells; - int cover; - int last_y; - }; - public: - enum + typedef Clip clip_type; + typedef typename Clip::conv_type conv_type; + typedef typename Clip::coord_type coord_type; + + enum aa_scale_e { - aa_shift = AA_Shift, - aa_num = 1 << aa_shift, - aa_mask = aa_num - 1, - aa_2num = aa_num * 2, - aa_2mask = aa_2num - 1 + aa_shift = 8, + aa_scale = 1 << aa_shift, + aa_mask = aa_scale - 1, + aa_scale2 = aa_scale * 2, + aa_mask2 = aa_scale2 - 1 }; //-------------------------------------------------------------------- rasterizer_scanline_aa() : + m_outline(), + m_clipper(), m_filling_rule(fill_non_zero), - m_clipped_start_x(0), - m_clipped_start_y(0), + m_auto_close(true), m_start_x(0), m_start_y(0), - m_prev_x(0), - m_prev_y(0), - m_prev_flags(0), - m_status(status_initial), - m_clipping(false) + m_status(status_initial) { int i; - for(i = 0; i < aa_num; i++) m_gamma[i] = i; + for(i = 0; i < aa_scale; i++) m_gamma[i] = i; } //-------------------------------------------------------------------- template<class GammaF> rasterizer_scanline_aa(const GammaF& gamma_function) : + m_outline(), + m_clipper(m_outline), m_filling_rule(fill_non_zero), - m_clipped_start_x(0), - m_clipped_start_y(0), + m_auto_close(true), m_start_x(0), m_start_y(0), - m_prev_x(0), - m_prev_y(0), - m_prev_flags(0), - m_status(status_initial), - m_clipping(false) + m_status(status_initial) { gamma(gamma_function); } //-------------------------------------------------------------------- void reset(); - void filling_rule(filling_rule_e filling_rule); - void clip_box(double x1, double y1, double x2, double y2); void reset_clipping(); + void clip_box(double x1, double y1, double x2, double y2); + void filling_rule(filling_rule_e filling_rule); + void auto_close(bool flag) { m_auto_close = flag; } //-------------------------------------------------------------------- template<class GammaF> void gamma(const GammaF& gamma_function) { int i; - for(i = 0; i < aa_num; i++) + for(i = 0; i < aa_scale; i++) { - m_gamma[i] = int(floor(gamma_function(double(i) / aa_mask) * aa_mask + 0.5)); + m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask); } } @@ -262,12 +173,31 @@ namespace agg } //-------------------------------------------------------------------- - void add_vertex(double x, double y, unsigned cmd); void move_to(int x, int y); void line_to(int x, int y); - void close_polygon(); void move_to_d(double x, double y); void line_to_d(double x, double y); + void close_polygon(); + void add_vertex(double x, double y, unsigned cmd); + + void edge(int x1, int y1, int x2, int y2); + void edge_d(double x1, double y1, double x2, double y2); + + //------------------------------------------------------------------- + template<class VertexSource> + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + if(m_outline.sorted()) reset(); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + } //-------------------------------------------------------------------- int min_x() const { return m_outline.min_x(); } @@ -276,17 +206,22 @@ namespace agg int max_y() const { return m_outline.max_y(); } //-------------------------------------------------------------------- + void sort(); + bool rewind_scanlines(); + bool navigate_scanline(int y); + + //-------------------------------------------------------------------- AGG_INLINE unsigned calculate_alpha(int area) const { - int cover = area >> (poly_base_shift*2 + 1 - aa_shift); + int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); if(cover < 0) cover = -cover; if(m_filling_rule == fill_even_odd) { - cover &= aa_2mask; - if(cover > aa_num) + cover &= aa_mask2; + if(cover > aa_scale) { - cover = aa_2num - cover; + cover = aa_scale2 - cover; } } if(cover > aa_mask) cover = aa_mask; @@ -294,164 +229,84 @@ namespace agg } //-------------------------------------------------------------------- - void sort() - { - m_outline.cells(); - } - - - //-------------------------------------------------------------------- - bool rewind_scanlines() - { - close_polygon(); - m_iterator.cells = m_outline.cells(); - if(m_outline.num_cells() == 0) - { - return false; - } - m_iterator.cover = 0; - m_iterator.last_y = (*m_iterator.cells)->y; - return true; - } - - - //-------------------------------------------------------------------- template<class Scanline> bool sweep_scanline(Scanline& sl) { - sl.reset_spans(); for(;;) { - const cell_aa* cur_cell = *m_iterator.cells; - if(cur_cell == 0) return false; - ++m_iterator.cells; - m_iterator.last_y = cur_cell->y; + if(m_scan_y > m_outline.max_y()) return false; + sl.reset_spans(); + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y); + int cover = 0; - for(;;) + while(num_cells) { - int coord = cur_cell->packed_coord; - int area = cur_cell->area; - int last_x = cur_cell->x; + const cell_aa* cur_cell = *cells; + int x = cur_cell->x; + int area = cur_cell->area; + unsigned alpha; - m_iterator.cover += cur_cell->cover; + cover += cur_cell->cover; - //accumulate all cells with the same coordinates - for(; (cur_cell = *m_iterator.cells) != 0; ++m_iterator.cells) + //accumulate all cells with the same X + while(--num_cells) { - if(cur_cell->packed_coord != coord) break; - area += cur_cell->area; - m_iterator.cover += cur_cell->cover; + cur_cell = *++cells; + if(cur_cell->x != x) break; + area += cur_cell->area; + cover += cur_cell->cover; } - int alpha; - if(cur_cell == 0 || cur_cell->y != m_iterator.last_y) - { - - if(area) - { - alpha = calculate_alpha((m_iterator.cover << (poly_base_shift + 1)) - area); - if(alpha) - { - sl.add_cell(last_x, alpha); - } - ++last_x; - } - break; - } - - ++m_iterator.cells; - if(area) { - alpha = calculate_alpha((m_iterator.cover << (poly_base_shift + 1)) - area); + alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area); if(alpha) { - sl.add_cell(last_x, alpha); + sl.add_cell(x, alpha); } - ++last_x; + x++; } - if(cur_cell->x > last_x) + if(num_cells && cur_cell->x > x) { - alpha = calculate_alpha(m_iterator.cover << (poly_base_shift + 1)); + alpha = calculate_alpha(cover << (poly_subpixel_shift + 1)); if(alpha) { - sl.add_span(last_x, cur_cell->x - last_x, alpha); + sl.add_span(x, cur_cell->x - x, alpha); } } } - if(sl.num_spans()) - { - sl.finalize(m_iterator.last_y); - break; - } + + if(sl.num_spans()) break; + ++m_scan_y; } + + sl.finalize(m_scan_y); + ++m_scan_y; return true; } - //-------------------------------------------------------------------- bool hit_test(int tx, int ty); - //-------------------------------------------------------------------- - void add_xy(const double* x, const double* y, unsigned n) - { - if(n > 2) - { - move_to_d(*x++, *y++); - --n; - do - { - line_to_d(*x++, *y++); - } - while(--n); - } - } - - //------------------------------------------------------------------- - template<class VertexSource> - void add_path(VertexSource& vs, unsigned id=0) - { - double x; - double y; - - unsigned cmd; - vs.rewind(id); - while(!is_stop(cmd = vs.vertex(&x, &y))) - { - add_vertex(x, y, cmd); - } - } - - private: //-------------------------------------------------------------------- // Disable copying - rasterizer_scanline_aa(const rasterizer_scanline_aa<XScale, AA_Shift>&); - const rasterizer_scanline_aa<XScale, AA_Shift>& - operator = (const rasterizer_scanline_aa<XScale, AA_Shift>&); - - //-------------------------------------------------------------------- - void move_to_no_clip(int x, int y); - void line_to_no_clip(int x, int y); - void close_polygon_no_clip(); - void clip_segment(int x, int y); + rasterizer_scanline_aa(const rasterizer_scanline_aa<Clip>&); + const rasterizer_scanline_aa<Clip>& + operator = (const rasterizer_scanline_aa<Clip>&); private: - outline_aa m_outline; - int m_gamma[aa_num]; + rasterizer_cells_aa<cell_aa> m_outline; + clip_type m_clipper; + int m_gamma[aa_scale]; filling_rule_e m_filling_rule; - int m_clipped_start_x; - int m_clipped_start_y; - int m_start_x; - int m_start_y; - int m_prev_x; - int m_prev_y; - unsigned m_prev_flags; + bool m_auto_close; + coord_type m_start_x; + coord_type m_start_y; unsigned m_status; - rect m_clip_box; - bool m_clipping; - iterator m_iterator; + int m_scan_y; }; @@ -463,277 +318,189 @@ namespace agg + + //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::reset() + template<class Clip> + void rasterizer_scanline_aa<Clip>::reset() { m_outline.reset(); m_status = status_initial; } //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::filling_rule(filling_rule_e _filling_rule) + template<class Clip> + void rasterizer_scanline_aa<Clip>::filling_rule(filling_rule_e filling_rule) { - m_filling_rule = _filling_rule; + m_filling_rule = filling_rule; } //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::clip_box(double x1, double y1, double x2, double y2) + template<class Clip> + void rasterizer_scanline_aa<Clip>::clip_box(double x1, double y1, + double x2, double y2) { reset(); - m_clip_box = rect(poly_coord(x1), poly_coord(y1), - poly_coord(x2), poly_coord(y2)); - m_clip_box.normalize(); - m_clipping = true; + m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), + conv_type::upscale(x2), conv_type::upscale(y2)); } //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::reset_clipping() + template<class Clip> + void rasterizer_scanline_aa<Clip>::reset_clipping() { reset(); - m_clipping = false; + m_clipper.reset_clipping(); } - - //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::move_to_no_clip(int x, int y) + template<class Clip> + void rasterizer_scanline_aa<Clip>::close_polygon() { if(m_status == status_line_to) { - close_polygon_no_clip(); + m_clipper.line_to(m_outline, m_start_x, m_start_y); + m_status = status_closed; } - m_outline.move_to(x * XScale, y); - m_clipped_start_x = x; - m_clipped_start_y = y; - m_status = status_line_to; } - //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::line_to_no_clip(int x, int y) + template<class Clip> + void rasterizer_scanline_aa<Clip>::move_to(int x, int y) { - if(m_status != status_initial) - { - m_outline.line_to(x * XScale, y); - m_status = status_line_to; - } + if(m_outline.sorted()) reset(); + 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; } - //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::close_polygon_no_clip() + template<class Clip> + void rasterizer_scanline_aa<Clip>::line_to(int x, int y) { - if(m_status == status_line_to) - { - m_outline.line_to(m_clipped_start_x * XScale, m_clipped_start_y); - m_status = status_closed; - } + m_clipper.line_to(m_outline, + conv_type::downscale(x), + conv_type::downscale(y)); + m_status = status_line_to; } - //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::clip_segment(int x, int y) + template<class Clip> + void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y) { - unsigned flags = clipping_flags(x, y, m_clip_box); - if(m_prev_flags == flags) - { - if(flags == 0) - { - if(m_status == status_initial) - { - move_to_no_clip(x, y); - } - else - { - line_to_no_clip(x, y); - } - } - } - else - { - int cx[4]; - int cy[4]; - unsigned n = clip_liang_barsky(m_prev_x, m_prev_y, - x, y, - m_clip_box, - cx, cy); - const int* px = cx; - const int* py = cy; - while(n--) - { - if(m_status == status_initial) - { - move_to_no_clip(*px++, *py++); - } - else - { - line_to_no_clip(*px++, *py++); - } - } - } - m_prev_flags = flags; - m_prev_x = x; - m_prev_y = y; + if(m_outline.sorted()) reset(); + 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; } - - //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::add_vertex(double x, double y, unsigned cmd) + template<class Clip> + void rasterizer_scanline_aa<Clip>::line_to_d(double x, double y) { - if(is_close(cmd)) - { - close_polygon(); - } - else - { - if(is_move_to(cmd)) - { - move_to(poly_coord(x), poly_coord(y)); - } - else - { - if(is_vertex(cmd)) - { - line_to(poly_coord(x), poly_coord(y)); - } - } - } + m_clipper.line_to(m_outline, + conv_type::upscale(x), + conv_type::upscale(y)); + m_status = status_line_to; } - - //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::move_to(int x, int y) + template<class Clip> + void rasterizer_scanline_aa<Clip>::add_vertex(double x, double y, unsigned cmd) { - if(m_clipping) + if(is_move_to(cmd)) { - if(m_outline.sorted()) - { - reset(); - } - if(m_status == status_line_to) - { - close_polygon(); - } - m_prev_x = m_start_x = x; - m_prev_y = m_start_y = y; - m_status = status_initial; - m_prev_flags = clipping_flags(x, y, m_clip_box); - if(m_prev_flags == 0) - { - move_to_no_clip(x, y); - } + move_to_d(x, y); } else + if(is_vertex(cmd)) { - move_to_no_clip(x, y); - } - } - - //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::line_to(int x, int y) - { - if(m_clipping) - { - clip_segment(x, y); + line_to_d(x, y); } else + if(is_close(cmd)) { - line_to_no_clip(x, y); + close_polygon(); } } //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::close_polygon() + template<class Clip> + void rasterizer_scanline_aa<Clip>::edge(int x1, int y1, int x2, int y2) { - if(m_clipping) - { - clip_segment(m_start_x, m_start_y); - } - close_polygon_no_clip(); + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); + m_clipper.line_to(m_outline, + conv_type::downscale(x2), + conv_type::downscale(y2)); + m_status = status_move_to; } //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::move_to_d(double x, double y) + template<class Clip> + void rasterizer_scanline_aa<Clip>::edge_d(double x1, double y1, + double x2, double y2) { - move_to(poly_coord(x), poly_coord(y)); + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); + m_clipper.line_to(m_outline, + conv_type::upscale(x2), + conv_type::upscale(y2)); + m_status = status_move_to; } //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - void rasterizer_scanline_aa<XScale, AA_Shift>::line_to_d(double x, double y) + template<class Clip> + void rasterizer_scanline_aa<Clip>::sort() { - line_to(poly_coord(x), poly_coord(y)); + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); } - //------------------------------------------------------------------------ - template<unsigned XScale, unsigned AA_Shift> - bool rasterizer_scanline_aa<XScale, AA_Shift>::hit_test(int tx, int ty) + template<class Clip> + AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines() { - close_polygon(); - const cell_aa* const* cells = m_outline.cells(); - if(m_outline.num_cells() == 0) return false; - - int cover = 0; - - const cell_aa* cur_cell = *cells++; - for(;;) + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) { - int alpha; - int coord = cur_cell->packed_coord; - int x = cur_cell->x; - int y = cur_cell->y; - - if(y > ty) return false; + return false; + } + m_scan_y = m_outline.min_y(); + return true; + } - int area = cur_cell->area; - cover += cur_cell->cover; - while((cur_cell = *cells++) != 0) - { - if(cur_cell->packed_coord != coord) break; - area += cur_cell->area; - cover += cur_cell->cover; - } + //------------------------------------------------------------------------ + template<class Clip> + AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y) + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + if(m_outline.total_cells() == 0 || + y < m_outline.min_y() || + y > m_outline.max_y()) + { + return false; + } + m_scan_y = y; + return true; + } - if(area) - { - alpha = calculate_alpha((cover << (poly_base_shift + 1)) - area); - if(alpha) - { - if(tx == x && ty == y) return true; - } - x++; - } + //------------------------------------------------------------------------ + template<class Clip> + bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty) + { + if(!navigate_scanline(ty)) return false; + scanline_hit_test sl(tx); + sweep_scanline(sl); + return sl.hit(); + } - if(!cur_cell) break; - if(cur_cell->x > x) - { - alpha = calculate_alpha(cover << (poly_base_shift + 1)); - if(alpha) - { - if(ty == y && tx >= x && tx <= cur_cell->x) return true; - } - } - } - return false; - } } diff --git a/agg/inc/agg_rasterizer_sl_clip.h b/agg/inc/agg_rasterizer_sl_clip.h new file mode 100644 index 000000000000..8b00aeed6605 --- /dev/null +++ b/agg/inc/agg_rasterizer_sl_clip.h @@ -0,0 +1,351 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +#ifndef AGG_RASTERIZER_SL_CLIP_INCLUDED +#define AGG_RASTERIZER_SL_CLIP_INCLUDED + +#include "agg_clip_liang_barsky.h" + +namespace agg +{ + //--------------------------------------------------------poly_max_coord_e + enum poly_max_coord_e + { + poly_max_coord = (1 << 30) - 1 //----poly_max_coord + }; + + //------------------------------------------------------------ras_conv_int + struct ras_conv_int + { + typedef int coord_type; + static AGG_INLINE int mul_div(double a, double b, double c) + { + return iround(a * b / c); + } + static int xi(int v) { return v; } + static int yi(int v) { return v; } + static int upscale(double v) { return iround(v * poly_subpixel_scale); } + static int downscale(int v) { return v; } + }; + + //--------------------------------------------------------ras_conv_int_sat + struct ras_conv_int_sat + { + typedef int coord_type; + static AGG_INLINE int mul_div(double a, double b, double c) + { + return saturation<poly_max_coord>::iround(a * b / c); + } + static int xi(int v) { return v; } + static int yi(int v) { return v; } + static int upscale(double v) + { + return saturation<poly_max_coord>::iround(v * poly_subpixel_scale); + } + static int downscale(int v) { return v; } + }; + + //---------------------------------------------------------ras_conv_int_3x + struct ras_conv_int_3x + { + typedef int coord_type; + static AGG_INLINE int mul_div(double a, double b, double c) + { + return iround(a * b / c); + } + static int xi(int v) { return v * 3; } + static int yi(int v) { return v; } + static int upscale(double v) { return iround(v * poly_subpixel_scale); } + static int downscale(int v) { return v; } + }; + + //-----------------------------------------------------------ras_conv_dbl + struct ras_conv_dbl + { + typedef double coord_type; + static AGG_INLINE double mul_div(double a, double b, double c) + { + return a * b / c; + } + static int xi(double v) { return iround(v * poly_subpixel_scale); } + static int yi(double v) { return iround(v * poly_subpixel_scale); } + static double upscale(double v) { return v; } + static double downscale(int v) { return v / double(poly_subpixel_scale); } + }; + + //--------------------------------------------------------ras_conv_dbl_3x + struct ras_conv_dbl_3x + { + typedef double coord_type; + static AGG_INLINE double mul_div(double a, double b, double c) + { + return a * b / c; + } + static int xi(double v) { return iround(v * poly_subpixel_scale * 3); } + static int yi(double v) { return iround(v * poly_subpixel_scale); } + static double upscale(double v) { return v; } + static double downscale(int v) { return v / double(poly_subpixel_scale); } + }; + + + + + + //------------------------------------------------------rasterizer_sl_clip + template<class Conv> class rasterizer_sl_clip + { + public: + typedef Conv conv_type; + typedef typename Conv::coord_type coord_type; + typedef rect_base<coord_type> rect_type; + + //-------------------------------------------------------------------- + rasterizer_sl_clip() : + m_clip_box(0,0,0,0), + m_x1(0), + m_y1(0), + m_f1(0), + m_clipping(false) + {} + + //-------------------------------------------------------------------- + void reset_clipping() + { + m_clipping = false; + } + + //-------------------------------------------------------------------- + void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) + { + m_clip_box = rect_type(x1, y1, x2, y2); + m_clip_box.normalize(); + m_clipping = true; + } + + //-------------------------------------------------------------------- + void move_to(coord_type x1, coord_type y1) + { + m_x1 = x1; + m_y1 = y1; + if(m_clipping) m_f1 = clipping_flags(x1, y1, m_clip_box); + } + + private: + //------------------------------------------------------------------------ + template<class Rasterizer> + AGG_INLINE void line_clip_y(Rasterizer& ras, + coord_type x1, coord_type y1, + coord_type x2, coord_type y2, + unsigned f1, unsigned f2) const + { + f1 &= 10; + f2 &= 10; + if((f1 | f2) == 0) + { + // Fully visible + ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2)); + } + else + { + if(f1 == f2) + { + // Invisible by Y + return; + } + + coord_type tx1 = x1; + coord_type ty1 = y1; + coord_type tx2 = x2; + coord_type ty2 = y2; + + if(f1 & 8) // y1 < clip.y1 + { + tx1 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1); + ty1 = m_clip_box.y1; + } + + if(f1 & 2) // y1 > clip.y2 + { + tx1 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1); + ty1 = m_clip_box.y2; + } + + if(f2 & 8) // y2 < clip.y1 + { + tx2 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1); + ty2 = m_clip_box.y1; + } + + if(f2 & 2) // y2 > clip.y2 + { + tx2 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1); + ty2 = m_clip_box.y2; + } + ras.line(Conv::xi(tx1), Conv::yi(ty1), + Conv::xi(tx2), Conv::yi(ty2)); + } + } + + + public: + //-------------------------------------------------------------------- + template<class Rasterizer> + void line_to(Rasterizer& ras, coord_type x2, coord_type y2) + { + if(m_clipping) + { + unsigned f2 = clipping_flags(x2, y2, m_clip_box); + + if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0) + { + // Invisible by Y + m_x1 = x2; + m_y1 = y2; + m_f1 = f2; + return; + } + + coord_type x1 = m_x1; + coord_type y1 = m_y1; + unsigned f1 = m_f1; + coord_type y3, y4; + unsigned f3, f4; + + switch(((f1 & 5) << 1) | (f2 & 5)) + { + case 0: // Visible by X + line_clip_y(ras, x1, y1, x2, y2, f1, f2); + break; + + case 1: // x2 > clip.x2 + y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, x1, y1, m_clip_box.x2, y3, f1, f3); + line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x2, y2, f3, f2); + break; + + case 2: // x1 > clip.x2 + y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3); + line_clip_y(ras, m_clip_box.x2, y3, x2, y2, f3, f2); + break; + + case 3: // x1 > clip.x2 && x2 > clip.x2 + line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y2, f1, f2); + break; + + case 4: // x2 < clip.x1 + y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, x1, y1, m_clip_box.x1, y3, f1, f3); + line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x1, y2, f3, f2); + break; + + case 6: // x1 > clip.x2 && x2 < clip.x1 + y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + y4 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + f4 = clipping_flags_y(y4, m_clip_box); + line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3); + line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x1, y4, f3, f4); + line_clip_y(ras, m_clip_box.x1, y4, m_clip_box.x1, y2, f4, f2); + break; + + case 8: // x1 < clip.x1 + y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3); + line_clip_y(ras, m_clip_box.x1, y3, x2, y2, f3, f2); + break; + + case 9: // x1 < clip.x1 && x2 > clip.x2 + y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + y4 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + f4 = clipping_flags_y(y4, m_clip_box); + line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3); + line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x2, y4, f3, f4); + line_clip_y(ras, m_clip_box.x2, y4, m_clip_box.x2, y2, f4, f2); + break; + + case 12: // x1 < clip.x1 && x2 < clip.x1 + line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y2, f1, f2); + break; + } + m_f1 = f2; + } + else + { + ras.line(Conv::xi(m_x1), Conv::yi(m_y1), + Conv::xi(x2), Conv::yi(y2)); + } + m_x1 = x2; + m_y1 = y2; + } + + + private: + rect_type m_clip_box; + coord_type m_x1; + coord_type m_y1; + unsigned m_f1; + bool m_clipping; + }; + + + + + //---------------------------------------------------rasterizer_sl_no_clip + class rasterizer_sl_no_clip + { + public: + typedef ras_conv_int conv_type; + typedef int coord_type; + + rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {} + + void reset_clipping() {} + void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) {} + void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; } + + template<class Rasterizer> + void line_to(Rasterizer& ras, coord_type x2, coord_type y2) + { + ras.line(m_x1, m_y1, x2, y2); + m_x1 = x2; + m_y1 = y2; + } + + private: + int m_x1, m_y1; + }; + + + // -----rasterizer_sl_clip_int + // -----rasterizer_sl_clip_int_sat + // -----rasterizer_sl_clip_int_3x + // -----rasterizer_sl_clip_dbl + // -----rasterizer_sl_clip_dbl_3x + //------------------------------------------------------------------------ + typedef rasterizer_sl_clip<ras_conv_int> rasterizer_sl_clip_int; + typedef rasterizer_sl_clip<ras_conv_int_sat> rasterizer_sl_clip_int_sat; + typedef rasterizer_sl_clip<ras_conv_int_3x> rasterizer_sl_clip_int_3x; + typedef rasterizer_sl_clip<ras_conv_dbl> rasterizer_sl_clip_dbl; + typedef rasterizer_sl_clip<ras_conv_dbl_3x> rasterizer_sl_clip_dbl_3x; + + +} + +#endif diff --git a/agg/inc/agg_render_scanlines.h b/agg/inc/agg_render_scanlines.h deleted file mode 100755 index 60ddecf5c2d6..000000000000 --- a/agg/inc/agg_render_scanlines.h +++ /dev/null @@ -1,66 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_RENDER_SCANLINES_INCLUDED -#define AGG_RENDER_SCANLINES_INCLUDED - -#include "agg_basics.h" - -namespace agg -{ - //========================================================render_scanlines - template<class Rasterizer, class Scanline, class Renderer> - void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren) - { - if(ras.rewind_scanlines()) - { - sl.reset(ras.min_x(), ras.max_x()); - ren.prepare(unsigned(ras.max_x() - ras.min_x() + 2)); - - while(ras.sweep_scanline(sl)) - { - ren.render(sl); - } - } - } - - - //========================================================render_all_paths - template<class Rasterizer, class Scanline, class Renderer, - class VertexSource, class ColorStorage, class PathId> - void render_all_paths(Rasterizer& ras, - Scanline& sl, - Renderer& r, - VertexSource& vs, - const ColorStorage& as, - const PathId& id, - unsigned num_paths) - { - for(unsigned i = 0; i < num_paths; i++) - { - ras.reset(); - ras.add_path(vs, id[i]); - r.color(as[i]); - render_scanlines(ras, sl, r); - } - } - - -} - -#endif - - - diff --git a/agg/inc/agg_renderer_base.h b/agg/inc/agg_renderer_base.h index 1ef44fecc6d2..349309d741d1 100755 --- a/agg/inc/agg_renderer_base.h +++ b/agg/inc/agg_renderer_base.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -32,12 +32,18 @@ namespace agg public: typedef PixelFormat pixfmt_type; typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; //-------------------------------------------------------------------- - renderer_base(pixfmt_type& _ren) : - m_ren(&_ren), - m_clip_box(0, 0, _ren.width() - 1, _ren.height() - 1) + renderer_base() : m_ren(0), m_clip_box(1, 1, 0, 0) {} + explicit renderer_base(pixfmt_type& ren) : + m_ren(&ren), + m_clip_box(0, 0, ren.width() - 1, ren.height() - 1) + {} + void attach(pixfmt_type& ren) { + m_ren = &ren; + m_clip_box = rect_i(0, 0, ren.width() - 1, ren.height() - 1); } //-------------------------------------------------------------------- @@ -51,9 +57,9 @@ namespace agg //-------------------------------------------------------------------- bool clip_box(int x1, int y1, int x2, int y2) { - rect cb(x1, y1, x2, y2); + rect_i cb(x1, y1, x2, y2); cb.normalize(); - if(cb.clip(rect(0, 0, width() - 1, height() - 1))) + if(cb.clip(rect_i(0, 0, width() - 1, height() - 1))) { m_clip_box = cb; return true; @@ -101,22 +107,18 @@ namespace agg } //-------------------------------------------------------------------- - void first_clip_box() {} - bool next_clip_box() { return false; } + const rect_i& clip_box() const { return m_clip_box; } + int xmin() const { return m_clip_box.x1; } + int ymin() const { return m_clip_box.y1; } + int xmax() const { return m_clip_box.x2; } + int ymax() const { return m_clip_box.y2; } //-------------------------------------------------------------------- - const rect& clip_box() const { return m_clip_box; } - int xmin() const { return m_clip_box.x1; } - int ymin() const { return m_clip_box.y1; } - int xmax() const { return m_clip_box.x2; } - int ymax() const { return m_clip_box.y2; } - - //-------------------------------------------------------------------- - const rect& bounding_clip_box() const { return m_clip_box; } - int bounding_xmin() const { return m_clip_box.x1; } - int bounding_ymin() const { return m_clip_box.y1; } - int bounding_xmax() const { return m_clip_box.x2; } - int bounding_ymax() const { return m_clip_box.y2; } + const rect_i& bounding_clip_box() const { return m_clip_box; } + int bounding_xmin() const { return m_clip_box.x1; } + int bounding_ymin() const { return m_clip_box.y1; } + int bounding_xmax() const { return m_clip_box.x2; } + int bounding_ymax() const { return m_clip_box.y2; } //-------------------------------------------------------------------- void clear(const color_type& c) @@ -131,6 +133,7 @@ namespace agg } } + //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { @@ -223,7 +226,7 @@ namespace agg //-------------------------------------------------------------------- void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) { - rect rc(x1, y1, x2, y2); + rect_i rc(x1, y1, x2, y2); rc.normalize(); if(rc.clip(clip_box())) { @@ -239,7 +242,7 @@ namespace agg void blend_bar(int x1, int y1, int x2, int y2, const color_type& c, cover_type cover) { - rect rc(x1, y1, x2, y2); + rect_i rc(x1, y1, x2, y2); rc.normalize(); if(rc.clip(clip_box())) { @@ -255,7 +258,6 @@ namespace agg } } - //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, int len, const color_type& c, @@ -302,11 +304,9 @@ namespace agg m_ren->blend_solid_vspan(x, y, len, c, covers); } + //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) + void copy_color_hspan(int x, int y, int len, const color_type* colors) { if(y > ymax()) return; if(y < ymin()) return; @@ -316,7 +316,6 @@ namespace agg int d = xmin() - x; len -= d; if(len <= 0) return; - if(covers) covers += d; colors += d; x = xmin(); } @@ -325,14 +324,12 @@ namespace agg len = xmax() - x + 1; if(len <= 0) return; } - m_ren->blend_color_hspan(x, y, len, colors, covers, cover); + m_ren->copy_color_hspan(x, y, len, colors); } + //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) + void copy_color_vspan(int x, int y, int len, const color_type* colors) { if(x > xmax()) return; if(x < xmin()) return; @@ -342,7 +339,6 @@ namespace agg int d = ymin() - y; len -= d; if(len <= 0) return; - if(covers) covers += d; colors += d; y = ymin(); } @@ -351,15 +347,15 @@ namespace agg len = ymax() - y + 1; if(len <= 0) return; } - m_ren->blend_color_vspan(x, y, len, colors, covers, cover); + m_ren->copy_color_vspan(x, y, len, colors); } //-------------------------------------------------------------------- - void blend_opaque_color_hspan(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) + void blend_color_hspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = agg::cover_full) { if(y > ymax()) return; if(y < ymin()) return; @@ -378,14 +374,14 @@ namespace agg len = xmax() - x + 1; if(len <= 0) return; } - m_ren->blend_opaque_color_hspan(x, y, len, colors, covers, cover); + m_ren->blend_color_hspan(x, y, len, colors, covers, cover); } //-------------------------------------------------------------------- - void blend_opaque_color_vspan(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) + void blend_color_vspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = agg::cover_full) { if(x > xmax()) return; if(x < xmin()) return; @@ -404,51 +400,14 @@ namespace agg len = ymax() - y + 1; if(len <= 0) return; } - m_ren->blend_opaque_color_vspan(x, y, len, colors, covers, cover); - } - - - //-------------------------------------------------------------------- - void blend_color_hspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - m_ren->blend_color_hspan(x, y, len, colors, covers, cover); - } - - //-------------------------------------------------------------------- - void blend_color_vspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { m_ren->blend_color_vspan(x, y, len, colors, covers, cover); } //-------------------------------------------------------------------- - void blend_opaque_color_hspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) + rect_i clip_rect_area(rect_i& dst, rect_i& src, int wsrc, int hsrc) const { - m_ren->blend_opaque_color_hspan(x, y, len, colors, covers, cover); - } - - //-------------------------------------------------------------------- - void blend_opaque_color_vspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - m_ren->blend_opaque_color_vspan(x, y, len, colors, covers, cover); - } - - //-------------------------------------------------------------------- - rect clip_rect_area(rect& dst, rect& src, int wsrc, int hsrc) const - { - rect rc(0,0,0,0); - rect cb = clip_box(); + rect_i rc(0,0,0,0); + rect_i cb = clip_box(); ++cb.x2; ++cb.y2; @@ -488,14 +447,14 @@ namespace agg return rc; } - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& src, - const rect* rect_src_ptr = 0, + template<class RenBuf> + void copy_from(const RenBuf& src, + const rect_i* rect_src_ptr = 0, int dx = 0, int dy = 0) { - rect rsrc(0, 0, src.width(), src.height()); + rect_i rsrc(0, 0, src.width(), src.height()); if(rect_src_ptr) { rsrc.x1 = rect_src_ptr->x1; @@ -505,12 +464,12 @@ namespace agg } // Version with xdst, ydst (absolute positioning) - //rect rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); // Version with dx, dy (relative positioning) - rect rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); - rect rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); if(rc.x2 > 0) { @@ -534,16 +493,15 @@ namespace agg } } - - //-------------------------------------------------------------------- template<class SrcPixelFormatRenderer> void blend_from(const SrcPixelFormatRenderer& src, - const rect* rect_src_ptr = 0, - int dx = 0, - int dy = 0) + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = agg::cover_full) { - rect rsrc(0, 0, src.width(), src.height()); + rect_i rsrc(0, 0, src.width(), src.height()); if(rect_src_ptr) { rsrc.x1 = rect_src_ptr->x1; @@ -553,12 +511,11 @@ namespace agg } // Version with xdst, ydst (absolute positioning) - //rect rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); // Version with dx, dy (relative positioning) - rect rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); - - rect rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + 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) { @@ -571,30 +528,31 @@ namespace agg } while(rc.y2 > 0) { - typename SrcPixelFormatRenderer::row_data span = src.span(rsrc.x1, rsrc.y1); - if(span.ptr) + 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(span.x1 > x1src) + if(rw.x1 > x1src) { - x1dst += span.x1 - x1src; - len -= span.x1 - x1src; - x1src = span.x1; + x1dst += rw.x1 - x1src; + len -= rw.x1 - x1src; + x1src = rw.x1; } if(len > 0) { - if(x1src + len-1 > span.x2) + if(x1src + len-1 > rw.x2) { - len -= x1src + len - span.x2 - 1; + len -= x1src + len - rw.x2 - 1; } if(len > 0) { - m_ren->blend_from(src, span.ptr, + m_ren->blend_from(src, x1dst, rdst.y1, x1src, rsrc.y1, - len); + len, + cover); } } } @@ -605,11 +563,153 @@ namespace agg } } + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_color(const SrcPixelFormatRenderer& src, + const color_type& color, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = agg::cover_full) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); + if(rw.ptr) + { + int x1src = rsrc.x1; + int x1dst = rdst.x1; + int len = rc.x2; + if(rw.x1 > x1src) + { + x1dst += rw.x1 - x1src; + len -= rw.x1 - x1src; + x1src = rw.x1; + } + if(len > 0) + { + if(x1src + len-1 > rw.x2) + { + len -= x1src + len - rw.x2 - 1; + } + if(len > 0) + { + m_ren->blend_from_color(src, + color, + x1dst, rdst.y1, + x1src, rsrc.y1, + len, + cover); + } + } + } + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_lut(const SrcPixelFormatRenderer& src, + const color_type* color_lut, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = agg::cover_full) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); + if(rw.ptr) + { + int x1src = rsrc.x1; + int x1dst = rdst.x1; + int len = rc.x2; + if(rw.x1 > x1src) + { + x1dst += rw.x1 - x1src; + len -= rw.x1 - x1src; + x1src = rw.x1; + } + if(len > 0) + { + if(x1src + len-1 > rw.x2) + { + len -= x1src + len - rw.x2 - 1; + } + if(len > 0) + { + m_ren->blend_from_lut(src, + color_lut, + x1dst, rdst.y1, + x1src, rsrc.y1, + len, + cover); + } + } + } + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } private: pixfmt_type* m_ren; - rect m_clip_box; + rect_i m_clip_box; }; diff --git a/agg/inc/agg_renderer_markers.h b/agg/inc/agg_renderer_markers.h index ff47995554d9..72c9b16a2757 100755 --- a/agg/inc/agg_renderer_markers.h +++ b/agg/inc/agg_renderer_markers.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -65,13 +65,12 @@ namespace agg //-------------------------------------------------------------------- renderer_markers(base_ren_type& rbuf) : base_type(rbuf) - { - } + {} //-------------------------------------------------------------------- bool visible(int x, int y, int r) const { - rect rc(x-r, y-r, x+y, y+r); + rect_i rc(x-r, y-r, x+y, y+r); return rc.clip(base_type::ren().bounding_clip_box()); } diff --git a/agg/inc/agg_renderer_mclip.h b/agg/inc/agg_renderer_mclip.h index dc758b9ea72d..834ffb23ffac 100755 --- a/agg/inc/agg_renderer_mclip.h +++ b/agg/inc/agg_renderer_mclip.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -33,14 +33,19 @@ namespace agg public: typedef PixelFormat pixfmt_type; typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; typedef renderer_base<pixfmt_type> base_ren_type; //-------------------------------------------------------------------- - renderer_mclip(pixfmt_type& ren) : - m_ren(ren), + explicit renderer_mclip(pixfmt_type& pixf) : + m_ren(pixf), m_curr_cb(0), m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax()) + {} + void attach(pixfmt_type& pixf) { + m_ren.attach(pixf); + reset_clipping(true); } //-------------------------------------------------------------------- @@ -52,18 +57,18 @@ namespace agg unsigned height() const { return m_ren.height(); } //-------------------------------------------------------------------- - const rect& clip_box() const { return m_ren.clip_box(); } - int xmin() const { return m_ren.xmin(); } - int ymin() const { return m_ren.ymin(); } - int xmax() const { return m_ren.xmax(); } - int ymax() const { return m_ren.ymax(); } + const rect_i& clip_box() const { return m_ren.clip_box(); } + int xmin() const { return m_ren.xmin(); } + int ymin() const { return m_ren.ymin(); } + int xmax() const { return m_ren.xmax(); } + int ymax() const { return m_ren.ymax(); } //-------------------------------------------------------------------- - const rect& bounding_clip_box() const { return m_bounds; } - int bounding_xmin() const { return m_bounds.x1; } - int bounding_ymin() const { return m_bounds.y1; } - int bounding_xmax() const { return m_bounds.x2; } - int bounding_ymax() const { return m_bounds.y2; } + const rect_i& bounding_clip_box() const { return m_bounds; } + int bounding_xmin() const { return m_bounds.x1; } + int bounding_ymin() const { return m_bounds.y1; } + int bounding_xmax() const { return m_bounds.x2; } + int bounding_ymax() const { return m_bounds.y2; } //-------------------------------------------------------------------- void first_clip_box() @@ -71,7 +76,7 @@ namespace agg m_curr_cb = 0; if(m_clip.size()) { - const rect& cb = m_clip[0]; + const rect_i& cb = m_clip[0]; m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); } } @@ -81,7 +86,7 @@ namespace agg { if(++m_curr_cb < m_clip.size()) { - const rect& cb = m_clip[m_curr_cb]; + const rect_i& cb = m_clip[m_curr_cb]; m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); return true; } @@ -100,9 +105,9 @@ namespace agg //-------------------------------------------------------------------- void add_clip_box(int x1, int y1, int x2, int y2) { - rect cb(x1, y1, x2, y2); + rect_i cb(x1, y1, x2, y2); cb.normalize(); - if(cb.clip(rect(0, 0, width() - 1, height() - 1))) + if(cb.clip(rect_i(0, 0, width() - 1, height() - 1))) { m_clip.add(cb); if(cb.x1 < m_bounds.x1) m_bounds.x1 = cb.x1; @@ -232,7 +237,6 @@ namespace agg while(next_clip_box()); } - //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, int len, const color_type& c, const cover_type* covers) @@ -257,22 +261,20 @@ namespace agg while(next_clip_box()); } + //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) + void copy_color_hspan(int x, int y, int len, const color_type* colors) { first_clip_box(); do { - m_ren.blend_color_hspan(x, y, len, colors, covers, cover); + m_ren.copy_color_hspan(x, y, len, colors); } while(next_clip_box()); } //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, int len, + void blend_color_hspan(int x, int y, int len, const color_type* colors, const cover_type* covers, cover_type cover = cover_full) @@ -285,96 +287,60 @@ namespace agg while(next_clip_box()); } - //-------------------------------------------------------------------- - void blend_qpaque_color_hspan(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) + void blend_color_vspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) { first_clip_box(); do { - m_ren.blend_opaque_color_hspan(x, y, len, colors, covers, cover); + m_ren.blend_color_vspan(x, y, len, colors, covers, cover); } while(next_clip_box()); } //-------------------------------------------------------------------- - void blend_opaque_color_vspan(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) + void copy_from(const rendering_buffer& from, + const rect_i* rc=0, + int x_to=0, + int y_to=0) { first_clip_box(); do { - m_ren.blend_opaque_color_hspan(x, y, len, colors, covers, cover); + m_ren.copy_from(from, rc, x_to, y_to); } while(next_clip_box()); } - //-------------------------------------------------------------------- - void blend_color_hspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - m_ren.blend_color_hspan_no_clip(x, y, len, colors, covers, cover); - } - - //-------------------------------------------------------------------- - void blend_color_vspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - m_ren.blend_color_vspan_no_clip(x, y, len, colors, covers, cover); - } - - //-------------------------------------------------------------------- - void blend_opaque_color_hspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - m_ren.blend_opaque_color_hspan_no_clip(x, y, len, colors, covers, cover); - } - - //-------------------------------------------------------------------- - void blend_opaque_color_vspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - m_ren.blend_opaque_color_vspan_no_clip(x, y, len, colors, covers, cover); - } - - - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - const rect* rc=0, - int x_to=0, - int y_to=0) + template<class SrcPixelFormatRenderer> + void blend_from(const SrcPixelFormatRenderer& src, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = cover_full) { first_clip_box(); do { - m_ren.copy_from(from, rc, x_to, y_to); + m_ren.blend_from(src, rect_src_ptr, dx, dy, cover); } while(next_clip_box()); } + private: renderer_mclip(const renderer_mclip<PixelFormat>&); const renderer_mclip<PixelFormat>& operator = (const renderer_mclip<PixelFormat>&); - base_ren_type m_ren; - pod_deque<rect, 4> m_clip; - unsigned m_curr_cb; - rect m_bounds; + base_ren_type m_ren; + pod_bvector<rect_i, 4> m_clip; + unsigned m_curr_cb; + rect_i m_bounds; }; diff --git a/agg/inc/agg_renderer_outline_aa.h b/agg/inc/agg_renderer_outline_aa.h index d2f9484c5a1d..d42ebcb049cd 100755 --- a/agg/inc/agg_renderer_outline_aa.h +++ b/agg/inc/agg_renderer_outline_aa.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -15,13 +15,14 @@ #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" #include "agg_ellipse_bresenham.h" #include "agg_renderer_base.h" #include "agg_gamma_functions.h" +#include "agg_clip_liang_barsky.h" namespace agg { @@ -35,8 +36,8 @@ namespace agg distance_interpolator0(int x1, int y1, int x2, int y2, int x, int y) : m_dx(line_mr(x2) - line_mr(x1)), m_dy(line_mr(y2) - line_mr(y1)), - m_dist((line_mr(x + line_subpixel_size/2) - line_mr(x2)) * m_dy - - (line_mr(y + line_subpixel_size/2) - line_mr(y2)) * m_dx) + m_dist((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy - + (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx) { m_dx <<= line_mr_subpixel_shift; m_dy <<= line_mr_subpixel_shift; @@ -44,56 +45,54 @@ namespace agg //--------------------------------------------------------------------- void inc_x() { m_dist += m_dy; } - void dec_x() { m_dist -= m_dy; } - void inc_y() { m_dist -= m_dx; } - void dec_y() { m_dist += m_dx; } - - //--------------------------------------------------------------------- - void inc_x(int _dy) - { - m_dist += m_dy; - if(_dy > 0) m_dist -= m_dx; - if(_dy < 0) m_dist += m_dx; - } - - //--------------------------------------------------------------------- - void dec_x(int _dy) - { - m_dist -= m_dy; - if(_dy > 0) m_dist -= m_dx; - if(_dy < 0) m_dist += m_dx; - } + int dist() const { return m_dist; } + private: //--------------------------------------------------------------------- - void inc_y(int _dx) - { - m_dist -= m_dx; - if(_dx > 0) m_dist += m_dy; - if(_dx < 0) m_dist -= m_dy; - } + int m_dx; + int m_dy; + int m_dist; + }; - void dec_y(int _dx) + //==================================================distance_interpolator00 + class distance_interpolator00 + { + public: //--------------------------------------------------------------------- + distance_interpolator00() {} + distance_interpolator00(int xc, int yc, + int x1, int y1, int x2, int y2, + int x, int y) : + m_dx1(line_mr(x1) - line_mr(xc)), + m_dy1(line_mr(y1) - line_mr(yc)), + m_dx2(line_mr(x2) - line_mr(xc)), + m_dy2(line_mr(y2) - line_mr(yc)), + m_dist1((line_mr(x + line_subpixel_scale/2) - line_mr(x1)) * m_dy1 - + (line_mr(y + line_subpixel_scale/2) - line_mr(y1)) * m_dx1), + m_dist2((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy2 - + (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx2) { - m_dist += m_dx; - if(_dx > 0) m_dist += m_dy; - if(_dx < 0) m_dist -= m_dy; + m_dx1 <<= line_mr_subpixel_shift; + m_dy1 <<= line_mr_subpixel_shift; + m_dx2 <<= line_mr_subpixel_shift; + m_dy2 <<= line_mr_subpixel_shift; } //--------------------------------------------------------------------- - int dist() const { return m_dist; } - int dx() const { return m_dx; } - int dy() const { return m_dy; } + void inc_x() { m_dist1 += m_dy1; m_dist2 += m_dy2; } + int dist1() const { return m_dist1; } + int dist2() const { return m_dist2; } private: //--------------------------------------------------------------------- - int m_dx; - int m_dy; - int m_dist; + int m_dx1; + int m_dy1; + int m_dx2; + int m_dy2; + int m_dist1; + int m_dist2; }; - - //===================================================distance_interpolator1 class distance_interpolator1 { @@ -103,8 +102,8 @@ namespace agg distance_interpolator1(int x1, int y1, int x2, int y2, int x, int y) : m_dx(x2 - x1), m_dy(y2 - y1), - m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) - - double(y + line_subpixel_size/2 - y2) * double(m_dx))) + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))) { m_dx <<= line_subpixel_shift; m_dy <<= line_subpixel_shift; @@ -117,35 +116,35 @@ namespace agg void dec_y() { m_dist += m_dx; } //--------------------------------------------------------------------- - void inc_x(int _dy) + void inc_x(int dy) { m_dist += m_dy; - if(_dy > 0) m_dist -= m_dx; - if(_dy < 0) m_dist += m_dx; + if(dy > 0) m_dist -= m_dx; + if(dy < 0) m_dist += m_dx; } //--------------------------------------------------------------------- - void dec_x(int _dy) + void dec_x(int dy) { m_dist -= m_dy; - if(_dy > 0) m_dist -= m_dx; - if(_dy < 0) m_dist += m_dx; + if(dy > 0) m_dist -= m_dx; + if(dy < 0) m_dist += m_dx; } //--------------------------------------------------------------------- - void inc_y(int _dx) + void inc_y(int dx) { m_dist -= m_dx; - if(_dx > 0) m_dist += m_dy; - if(_dx < 0) m_dist -= m_dy; + if(dx > 0) m_dist += m_dy; + if(dx < 0) m_dist -= m_dy; } - void dec_y(int _dx) + void dec_y(int dx) //--------------------------------------------------------------------- { m_dist += m_dx; - if(_dx > 0) m_dist += m_dy; - if(_dx < 0) m_dist -= m_dy; + if(dx > 0) m_dist += m_dy; + if(dx < 0) m_dist -= m_dy; } //--------------------------------------------------------------------- @@ -177,11 +176,11 @@ namespace agg m_dx_start(line_mr(sx) - line_mr(x1)), m_dy_start(line_mr(sy) - line_mr(y1)), - m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) - - double(y + line_subpixel_size/2 - y2) * double(m_dx))), + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), - m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(sx)) * m_dy_start - - (line_mr(y + line_subpixel_size/2) - line_mr(sy)) * m_dx_start) + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start) { m_dx <<= line_subpixel_shift; m_dy <<= line_subpixel_shift; @@ -196,11 +195,11 @@ namespace agg m_dx_start(line_mr(ex) - line_mr(x2)), m_dy_start(line_mr(ey) - line_mr(y2)), - m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) - - double(y + line_subpixel_size/2 - y2) * double(m_dx))), + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), - m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(ex)) * m_dy_start - - (line_mr(y + line_subpixel_size/2) - line_mr(ey)) * m_dx_start) + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_start) { m_dx <<= line_subpixel_shift; m_dy <<= line_subpixel_shift; @@ -216,16 +215,16 @@ namespace agg void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; } //--------------------------------------------------------------------- - void inc_x(int _dy) + void inc_x(int dy) { m_dist += m_dy; m_dist_start += m_dy_start; - if(_dy > 0) + if(dy > 0) { m_dist -= m_dx; m_dist_start -= m_dx_start; } - if(_dy < 0) + if(dy < 0) { m_dist += m_dx; m_dist_start += m_dx_start; @@ -233,16 +232,16 @@ namespace agg } //--------------------------------------------------------------------- - void dec_x(int _dy) + void dec_x(int dy) { m_dist -= m_dy; m_dist_start -= m_dy_start; - if(_dy > 0) + if(dy > 0) { m_dist -= m_dx; m_dist_start -= m_dx_start; } - if(_dy < 0) + if(dy < 0) { m_dist += m_dx; m_dist_start += m_dx_start; @@ -250,16 +249,16 @@ namespace agg } //--------------------------------------------------------------------- - void inc_y(int _dx) + void inc_y(int dx) { m_dist -= m_dx; m_dist_start -= m_dx_start; - if(_dx > 0) + if(dx > 0) { m_dist += m_dy; m_dist_start += m_dy_start; } - if(_dx < 0) + if(dx < 0) { m_dist -= m_dy; m_dist_start -= m_dy_start; @@ -267,16 +266,16 @@ namespace agg } //--------------------------------------------------------------------- - void dec_y(int _dx) + void dec_y(int dx) { m_dist += m_dx; m_dist_start += m_dx_start; - if(_dx > 0) + if(dx > 0) { m_dist += m_dy; m_dist_start += m_dy_start; } - if(_dx < 0) + if(dx < 0) { m_dist -= m_dy; m_dist_start -= m_dy_start; @@ -327,14 +326,14 @@ namespace agg m_dx_end(line_mr(ex) - line_mr(x2)), m_dy_end(line_mr(ey) - line_mr(y2)), - m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) - - double(y + line_subpixel_size/2 - y2) * double(m_dx))), + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), - m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(sx)) * m_dy_start - - (line_mr(y + line_subpixel_size/2) - line_mr(sy)) * m_dx_start), + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start), - m_dist_end((line_mr(x + line_subpixel_size/2) - line_mr(ex)) * m_dy_end - - (line_mr(y + line_subpixel_size/2) - line_mr(ey)) * m_dx_end) + m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - + (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end) { m_dx <<= line_subpixel_shift; m_dy <<= line_subpixel_shift; @@ -351,18 +350,18 @@ namespace agg void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; } //--------------------------------------------------------------------- - void inc_x(int _dy) + void inc_x(int dy) { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; - if(_dy > 0) + if(dy > 0) { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; } - if(_dy < 0) + if(dy < 0) { m_dist += m_dx; m_dist_start += m_dx_start; @@ -371,18 +370,18 @@ namespace agg } //--------------------------------------------------------------------- - void dec_x(int _dy) + void dec_x(int dy) { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; - if(_dy > 0) + if(dy > 0) { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; } - if(_dy < 0) + if(dy < 0) { m_dist += m_dx; m_dist_start += m_dx_start; @@ -391,18 +390,18 @@ namespace agg } //--------------------------------------------------------------------- - void inc_y(int _dx) + void inc_y(int dx) { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; - if(_dx > 0) + if(dx > 0) { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; } - if(_dx < 0) + if(dx < 0) { m_dist -= m_dy; m_dist_start -= m_dy_start; @@ -411,18 +410,18 @@ namespace agg } //--------------------------------------------------------------------- - void dec_y(int _dx) + void dec_y(int dx) { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; - if(_dx > 0) + if(dx > 0) { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; } - if(_dx < 0) + if(dx < 0) { m_dist -= m_dy; m_dist_start -= m_dy_start; @@ -469,7 +468,7 @@ namespace agg typedef typename Renderer::color_type color_type; //--------------------------------------------------------------------- - enum + enum max_half_width_e { max_half_width = 64 }; @@ -490,7 +489,8 @@ namespace agg m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : abs((lp.x2 >> line_subpixel_shift) - m_x))), m_width(ren.subpixel_width()), - m_max_extent(m_width >> (line_subpixel_shift - 2)), + //m_max_extent(m_width >> (line_subpixel_shift - 2)), + m_max_extent((m_width + line_subpixel_mask) >> line_subpixel_shift), m_step(0) { agg::dda2_line_interpolator li(0, lp.vertical ? @@ -499,7 +499,7 @@ namespace agg lp.len); unsigned i; - int stop = m_width + line_subpixel_size * 2; + int stop = m_width + line_subpixel_scale * 2; for(i = 0; i < max_half_width; ++i) { m_dist[i] = li.y(); @@ -1259,40 +1259,33 @@ namespace agg public: //--------------------------------------------------------------------- typedef int8u value_type; - enum + enum subpixel_scale_e { subpixel_shift = line_subpixel_shift, - subpixel_size = 1 << subpixel_shift, - subpixel_mask = subpixel_size - 1 + subpixel_scale = 1 << subpixel_shift, + subpixel_mask = subpixel_scale - 1 }; - enum + enum aa_scale_e { aa_shift = 8, - aa_num = 1 << aa_shift, - aa_mask = aa_num - 1 + aa_scale = 1 << aa_shift, + 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) { int i; - for(i = 0; i < aa_num; i++) m_gamma[i] = (value_type)i; + for(i = 0; i < aa_scale; i++) m_gamma[i] = (value_type)i; } //--------------------------------------------------------------------- template<class GammaF> line_profile_aa(double w, const GammaF& gamma_function) : - m_size(0), - m_profile(0), m_subpixel_width(0), m_min_width(1.0), m_smoother_width(1.0) @@ -1309,17 +1302,16 @@ namespace agg template<class GammaF> void gamma(const GammaF& gamma_function) { int i; - for(i = 0; i < aa_num; i++) + for(i = 0; i < aa_scale; i++) { m_gamma[i] = value_type( - floor( - gamma_function(double(i) / aa_mask) * aa_mask + 0.5)); + uround(gamma_function(double(i) / aa_mask) * aa_mask)); } } 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; } //--------------------------------------------------------------------- @@ -1329,7 +1321,7 @@ namespace agg //--------------------------------------------------------------------- value_type value(int dist) const { - return m_profile[dist + subpixel_size*2]; + return m_profile[dist + subpixel_scale*2]; } private: @@ -1340,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_num]; - int m_subpixel_width; - double m_min_width; - double m_smoother_width; + pod_array<value_type> m_profile; + value_type m_gamma[aa_scale]; + int m_subpixel_width; + double m_min_width; + double m_smoother_width; }; @@ -1361,9 +1352,11 @@ namespace agg //--------------------------------------------------------------------- renderer_outline_aa(base_ren_type& ren, const line_profile_aa& prof) : m_ren(&ren), - m_profile(&prof) - { - } + 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; } @@ -1372,12 +1365,23 @@ namespace agg //--------------------------------------------------------------------- void profile(const line_profile_aa& prof) { m_profile = &prof; } const line_profile_aa& profile() const { return *m_profile; } - line_profile_aa& profile() { return const_cast<line_profile_aa&>(*m_profile); } + line_profile_aa& profile() { return *m_profile; } //--------------------------------------------------------------------- int subpixel_width() const { return m_profile->subpixel_width(); } //--------------------------------------------------------------------- + void reset_clipping() { m_clipping = false; } + void clip_box(double x1, double y1, double x2, double y2) + { + m_clip_box.x1 = line_coord_sat::conv(x1); + m_clip_box.y1 = line_coord_sat::conv(y1); + m_clip_box.x2 = line_coord_sat::conv(x2); + m_clip_box.y2 = line_coord_sat::conv(y2); + m_clipping = true; + } + + //--------------------------------------------------------------------- int cover(int d) const { return m_profile->value(d); @@ -1411,8 +1415,8 @@ namespace agg int y = y1 << line_subpixel_shift; int w = subpixel_width(); distance_interpolator0 di(xc1, yc1, xc2, yc2, x, y); - x += line_subpixel_size/2; - y += line_subpixel_size/2; + x += line_subpixel_scale/2; + y += line_subpixel_scale/2; int x0 = x1; int dx = x - xc1; @@ -1426,7 +1430,7 @@ namespace agg *p1 = (cover_type)cover(d); } ++p1; - dx += line_subpixel_size; + dx += line_subpixel_scale; di.inc_x(); } while(++x1 <= x2); @@ -1440,6 +1444,8 @@ namespace agg template<class Cmp> void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2) { + if(m_clipping && clipping_flags(xc1, yc1, m_clip_box)) return; + int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); if(r < 1) r = 1; ellipse_bresenham_interpolator ei(r, r); @@ -1469,73 +1475,359 @@ namespace agg } //------------------------------------------------------------------------- - void line0(const line_parameters& lp) + void pie_hline(int xc, int yc, int xp1, int yp1, int xp2, int yp2, + int xh1, int yh1, int xh2) + { + if(m_clipping && clipping_flags(xc, yc, m_clip_box)) return; + + cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4]; + cover_type* p0 = covers; + cover_type* p1 = covers; + int x = xh1 << line_subpixel_shift; + int y = yh1 << line_subpixel_shift; + int w = subpixel_width(); + + distance_interpolator00 di(xc, yc, xp1, yp1, xp2, yp2, x, y); + x += line_subpixel_scale/2; + y += line_subpixel_scale/2; + + int xh0 = xh1; + int dx = x - xc; + int dy = y - yc; + do + { + int d = int(fast_sqrt(dx*dx + dy*dy)); + *p1 = 0; + if(di.dist1() <= 0 && di.dist2() > 0 && d <= w) + { + *p1 = (cover_type)cover(d); + } + ++p1; + dx += line_subpixel_scale; + di.inc_x(); + } + while(++xh1 <= xh2); + m_ren->blend_solid_hspan(xh0, yh1, + unsigned(p1 - p0), + color(), + p0); + } + + + //------------------------------------------------------------------------- + void pie(int xc, int yc, int x1, int y1, int x2, int y2) + { + int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); + if(r < 1) r = 1; + ellipse_bresenham_interpolator ei(r, r); + int dx = 0; + int dy = -r; + int dy0 = dy; + int dx0 = dx; + int x = xc >> line_subpixel_shift; + int y = yc >> line_subpixel_shift; + + do + { + dx += ei.dx(); + dy += ei.dy(); + + if(dy != dy0) + { + pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); + pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y-dy0, x+dx0); + } + dx0 = dx; + dy0 = dy; + ++ei; + } + while(dy < 0); + pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); + } + + //------------------------------------------------------------------------- + void line0_no_clip(const line_parameters& lp) { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + line0_no_clip(lp1); + line0_no_clip(lp2); + return; + } + line_interpolator_aa0<self_type> li(*this, lp); if(li.count()) { if(li.vertical()) { - while(li.step_ver()) ; + while(li.step_ver()); } else { - while(li.step_hor()) ; + while(li.step_hor()); } } } //------------------------------------------------------------------------- - void line1(const line_parameters& lp, int sx, int sy) + void line0(const line_parameters& lp) { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + line0_no_clip(lp2); + } + else + { + line0_no_clip(lp); + } + } + } + else + { + line0_no_clip(lp); + } + } + + //------------------------------------------------------------------------- + void line1_no_clip(const line_parameters& lp, int sx, int sy) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + line1_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1); + line1_no_clip(lp2, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); + return; + } + fix_degenerate_bisectrix_start(lp, &sx, &sy); line_interpolator_aa1<self_type> li(*this, lp, sx, sy); if(li.vertical()) { - while(li.step_ver()) ; + while(li.step_ver()); } else { - while(li.step_hor()) ; + while(li.step_hor()); } } + //------------------------------------------------------------------------- - void line2(const line_parameters& lp, int ex, int ey) + void line1(const line_parameters& lp, int sx, int sy) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 1) + { + sx = x1 + (y2 - y1); + sy = y1 - (x2 - x1); + } + else + { + while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; + } + } + line1_no_clip(lp2, sx, sy); + } + else + { + line1_no_clip(lp, sx, sy); + } + } + } + else + { + line1_no_clip(lp, sx, sy); + } + } + + //------------------------------------------------------------------------- + void line2_no_clip(const line_parameters& lp, int ex, int ey) { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + line2_no_clip(lp1, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); + line2_no_clip(lp2, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); + return; + } + fix_degenerate_bisectrix_end(lp, &ex, &ey); line_interpolator_aa2<self_type> li(*this, lp, ex, ey); if(li.vertical()) { - while(li.step_ver()) ; + while(li.step_ver()); } else { - while(li.step_hor()) ; + while(li.step_hor()); } } //------------------------------------------------------------------------- - void line3(const line_parameters& lp, - int sx, int sy, int ex, int ey) + void line2(const line_parameters& lp, int ex, int ey) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 2) + { + ex = x2 + (y2 - y1); + ey = y2 - (x2 - x1); + } + else + { + while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; + } + } + line2_no_clip(lp2, ex, ey); + } + else + { + line2_no_clip(lp, ex, ey); + } + } + } + else + { + line2_no_clip(lp, ex, ey); + } + } + + //------------------------------------------------------------------------- + void line3_no_clip(const line_parameters& lp, + int sx, int sy, int ex, int ey) { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + int mx = lp1.x2 + (lp1.y2 - lp1.y1); + int my = lp1.y2 - (lp1.x2 - lp1.x1); + line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my); + line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); + return; + } + fix_degenerate_bisectrix_start(lp, &sx, &sy); fix_degenerate_bisectrix_end(lp, &ex, &ey); line_interpolator_aa3<self_type> li(*this, lp, sx, sy, ex, ey); if(li.vertical()) { - while(li.step_ver()) ; + while(li.step_ver()); } else { - while(li.step_hor()) ; + while(li.step_hor()); } } + //------------------------------------------------------------------------- + void line3(const line_parameters& lp, + int sx, int sy, int ex, int ey) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 1) + { + sx = x1 + (y2 - y1); + sy = y1 - (x2 - x1); + } + else + { + while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; + } + } + if(flags & 2) + { + ex = x2 + (y2 - y1); + ey = y2 - (x2 - x1); + } + else + { + while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; + } + } + line3_no_clip(lp2, sx, sy, ex, ey); + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + + private: base_ren_type* m_ren; const line_profile_aa* m_profile; color_type m_color; + rect_i m_clip_box; + bool m_clipping; }; diff --git a/agg/inc/agg_renderer_outline_image.h b/agg/inc/agg_renderer_outline_image.h index d5cd3992448c..0fd703421dd3 100755 --- a/agg/inc/agg_renderer_outline_image.h +++ b/agg/inc/agg_renderer_outline_image.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -15,10 +15,12 @@ #ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED #define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED -#include <math.h> +#include "agg_array.h" +#include "agg_math.h" #include "agg_line_aa_basics.h" #include "agg_dda_line.h" #include "agg_rendering_buffer.h" +#include "agg_clip_liang_barsky.h" namespace agg @@ -42,8 +44,8 @@ namespace agg color_type pixel(int x, int y) const { double src_y = (y + 0.5) * m_scale - 0.5; - int h = int(m_source.height()) - 1; - int y1 = int(floor(src_y)); + int h = m_source.height() - 1; + int y1 = ufloor(src_y); int y2 = y1 + 1; color_type pix1 = (y1 < 0) ? color_type::no_color() : m_source.pixel(x, y1); color_type pix2 = (y2 > h) ? color_type::no_color() : m_source.pixel(x, y2); @@ -69,17 +71,11 @@ namespace agg 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), @@ -95,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), @@ -109,25 +105,24 @@ namespace agg //-------------------------------------------------------------------- template<class Source> void create(const Source& src) { - m_height = unsigned(ceil((double)src.height())); - m_width = unsigned(ceil((double)src.width())); - m_width_hr = int(src.width() * line_subpixel_size); - m_half_height_hr = int(src.height() * line_subpixel_size/2); - m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_size/2; - m_half_height_hr += line_subpixel_size/2; + m_height = uceil(src.height()); + m_width = uceil(src.width()); + m_width_hr = uround(src.width() * line_subpixel_scale); + m_half_height_hr = uround(src.height() * line_subpixel_scale/2); + m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_scale/2; + m_half_height_hr += line_subpixel_scale/2; - 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; for(y = 0; y < m_height; y++) { - d1 = m_buf.row(y + m_dilation) + m_dilation; + d1 = m_buf.row_ptr(y + m_dilation) + m_dilation; for(x = 0; x < m_width; x++) { *d1++ = src.pixel(x, y); @@ -138,10 +133,10 @@ namespace agg const color_type* s2; for(y = 0; y < m_dilation; y++) { - //s1 = m_buf.row(m_height + m_dilation - 1) + m_dilation; - //s2 = m_buf.row(m_dilation) + m_dilation; - d1 = m_buf.row(m_dilation + m_height + y) + m_dilation; - d2 = m_buf.row(m_dilation - y - 1) + m_dilation; + //s1 = m_buf.row_ptr(m_height + m_dilation - 1) + m_dilation; + //s2 = m_buf.row_ptr(m_dilation) + m_dilation; + d1 = m_buf.row_ptr(m_dilation + m_height + y) + m_dilation; + d2 = m_buf.row_ptr(m_dilation - y - 1) + m_dilation; for(x = 0; x < m_width; x++) { //*d1++ = color_type(*s1++, 0); @@ -154,10 +149,10 @@ namespace agg unsigned h = m_height + m_dilation * 2; for(y = 0; y < h; y++) { - s1 = m_buf.row(y) + m_dilation; - s2 = m_buf.row(y) + m_dilation + m_width; - d1 = m_buf.row(y) + m_dilation + m_width; - d2 = m_buf.row(y) + m_dilation; + s1 = m_buf.row_ptr(y) + m_dilation; + s2 = m_buf.row_ptr(y) + m_dilation + m_width; + d1 = m_buf.row_ptr(y) + m_dilation + m_width; + d2 = m_buf.row_ptr(y) + m_dilation; for(x = 0; x < m_dilation; x++) { @@ -170,6 +165,7 @@ namespace agg //-------------------------------------------------------------------- int pattern_width() const { return m_width_hr; } int line_width() const { return m_half_height_hr; } + double width() const { return m_height; } //-------------------------------------------------------------------- void pixel(color_type* p, int x, int y) const @@ -193,7 +189,7 @@ namespace agg const filter_type* m_filter; unsigned m_dilation; int m_dilation_hr; - color_type* m_data; + pod_array<color_type> m_data; unsigned m_width; unsigned m_height; int m_width_hr; @@ -277,23 +273,23 @@ namespace agg m_dx_end(line_mr(ex) - line_mr(x2)), m_dy_end(line_mr(ey) - line_mr(y2)), - m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) - - double(y + line_subpixel_size/2 - y2) * double(m_dx))), + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), - m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(sx)) * m_dy_start - - (line_mr(y + line_subpixel_size/2) - line_mr(sy)) * m_dx_start), + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start), - m_dist_end((line_mr(x + line_subpixel_size/2) - line_mr(ex)) * m_dy_end - - (line_mr(y + line_subpixel_size/2) - line_mr(ey)) * m_dx_end), - m_len(int(len / scale)) + m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - + (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end), + m_len(uround(len / scale)) { double d = len * scale; - int dx = int(((x2 - x1) << line_subpixel_shift) / d); - int dy = int(((y2 - y1) << line_subpixel_shift) / d); + int dx = iround(((x2 - x1) << line_subpixel_shift) / d); + int dy = iround(((y2 - y1) << line_subpixel_shift) / d); m_dx_pict = -dy; m_dy_pict = dx; - m_dist_pict = ((x + line_subpixel_size/2 - (x1 - dy)) * m_dy_pict - - (y + line_subpixel_size/2 - (y1 + dx)) * m_dx_pict) >> + m_dist_pict = ((x + line_subpixel_scale/2 - (x1 - dy)) * m_dy_pict - + (y + line_subpixel_scale/2 - (y1 + dx)) * m_dx_pict) >> line_subpixel_shift; m_dx <<= line_subpixel_shift; @@ -479,7 +475,7 @@ namespace agg typedef typename Renderer::color_type color_type; //--------------------------------------------------------------------- - enum + enum max_half_width_e { max_half_width = 64 }; @@ -504,7 +500,8 @@ namespace agg m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : abs((lp.x2 >> line_subpixel_shift) - m_x))), m_width(ren.subpixel_width()), - m_max_extent(m_width >> (line_subpixel_shift - 2)), + //m_max_extent(m_width >> (line_subpixel_shift - 2)), + m_max_extent((m_width + line_subpixel_scale) >> line_subpixel_shift), m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()), m_step(0) { @@ -514,7 +511,7 @@ namespace agg lp.len); unsigned i; - int stop = m_width + line_subpixel_size * 2; + int stop = m_width + line_subpixel_scale * 2; for(i = 0; i < max_half_width; ++i) { m_dist_pos[i] = li.y(); @@ -823,25 +820,39 @@ namespace agg m_ren(&ren), m_pattern(&patt), m_start(0), - m_scale_x(1.0) - { - } + 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; } const pattern_type& pattern() const { return *m_pattern; } //--------------------------------------------------------------------- + void reset_clipping() { m_clipping = false; } + void clip_box(double x1, double y1, double x2, double y2) + { + m_clip_box.x1 = line_coord_sat::conv(x1); + m_clip_box.y1 = line_coord_sat::conv(y1); + m_clip_box.x2 = line_coord_sat::conv(x2); + m_clip_box.y2 = line_coord_sat::conv(y2); + m_clipping = true; + } + + //--------------------------------------------------------------------- void scale_x(double s) { m_scale_x = s; } double scale_x() const { return m_scale_x; } //--------------------------------------------------------------------- - void start_x(double s) { m_start = int(s * line_subpixel_size); } - double start_x() const { return double(m_start) / line_subpixel_size; } + void start_x(double s) { m_start = iround(s * line_subpixel_scale); } + double start_x() const { return double(m_start) / line_subpixel_scale; } //--------------------------------------------------------------------- int subpixel_width() const { return m_pattern->line_width(); } int pattern_width() const { return m_pattern->pattern_width(); } + double width() const { return double(subpixel_width()) / line_subpixel_scale; } //------------------------------------------------------------------------- void pixel(color_type* p, int x, int y) const @@ -871,6 +882,11 @@ namespace agg } //------------------------------------------------------------------------- + void pie(int, int, int, int, int, int) + { + } + + //------------------------------------------------------------------------- void line0(const line_parameters&) { } @@ -886,9 +902,20 @@ namespace agg } //------------------------------------------------------------------------- - void line3(const line_parameters& lp, - int sx, int sy, int ex, int ey) + void line3_no_clip(const line_parameters& lp, + int sx, int sy, int ex, int ey) { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + int mx = lp1.x2 + (lp1.y2 - lp1.y1); + int my = lp1.y2 - (lp1.x2 - lp1.x1); + line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my); + line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); + return; + } + fix_degenerate_bisectrix_start(lp, &sx, &sy); fix_degenerate_bisectrix_end(lp, &ex, &ey); line_interpolator_image<self_type> li(*this, lp, @@ -903,7 +930,67 @@ namespace agg { while(li.step_hor()); } - m_start = li.pattern_end(); + m_start += uround(lp.len / m_scale_x); + } + + //------------------------------------------------------------------------- + void line3(const line_parameters& lp, + int sx, int sy, int ex, int ey) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + int start = m_start; + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 1) + { + m_start += uround(calc_distance(lp.x1, lp.y1, x1, y1) / m_scale_x); + sx = x1 + (y2 - y1); + sy = y1 - (x2 - x1); + } + else + { + while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; + } + } + if(flags & 2) + { + ex = x2 + (y2 - y1); + ey = y2 - (x2 - x1); + } + else + { + while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; + } + } + line3_no_clip(lp2, sx, sy, ex, ey); + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + m_start = start + uround(lp.len / m_scale_x); + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } } private: @@ -911,6 +998,8 @@ namespace agg const pattern_type* m_pattern; int m_start; double m_scale_x; + rect_i m_clip_box; + bool m_clipping; }; diff --git a/agg/inc/agg_renderer_primitives.h b/agg/inc/agg_renderer_primitives.h index 522432c06df6..dc1623e442cf 100755 --- a/agg/inc/agg_renderer_primitives.h +++ b/agg/inc/agg_renderer_primitives.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -35,19 +35,19 @@ 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) { - return int(c * line_bresenham_interpolator::subpixel_size); + return iround(c * line_bresenham_interpolator::subpixel_scale); } //-------------------------------------------------------------------- diff --git a/agg/inc/agg_renderer_raster_text.h b/agg/inc/agg_renderer_raster_text.h index 957944600332..ea39c0524e14 100755 --- a/agg/inc/agg_renderer_raster_text.h +++ b/agg/inc/agg_renderer_raster_text.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -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; } @@ -219,7 +219,7 @@ namespace agg m_glyph->prepare(&r, x, y, *str, flip); if(r.x2 >= r.x1) { - m_ren->prepare(r.x2 - r.x1 + 1); + m_ren->prepare(); int i; if(flip) { diff --git a/agg/inc/agg_renderer_scanline.h b/agg/inc/agg_renderer_scanline.h index cc33942a3770..3deada41163d 100755 --- a/agg/inc/agg_renderer_scanline.h +++ b/agg/inc/agg_renderer_scanline.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -18,195 +18,303 @@ #include "agg_basics.h" #include "agg_renderer_base.h" -#include "agg_render_scanlines.h" namespace agg { - //====================================================renderer_scanline_aa - template<class BaseRenderer, class SpanGenerator> class renderer_scanline_aa + //================================================render_scanline_aa_solid + template<class Scanline, class BaseRenderer, class ColorT> + void render_scanline_aa_solid(const Scanline& sl, + BaseRenderer& ren, + const ColorT& color) { - public: - typedef BaseRenderer base_ren_type; - - //-------------------------------------------------------------------- - renderer_scanline_aa(base_ren_type& ren, SpanGenerator& span_gen) : - m_ren(&ren), - m_span_gen(&span_gen) - { - } + int y = sl.y(); + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); - //-------------------------------------------------------------------- - void prepare(unsigned max_span_len) + for(;;) { - m_span_gen->prepare(max_span_len); + int x = span->x; + if(span->len > 0) + { + ren.blend_solid_hspan(x, y, (unsigned)span->len, + color, + span->covers); + } + else + { + ren.blend_hline(x, y, (unsigned)(x - span->len - 1), + color, + *(span->covers)); + } + if(--num_spans == 0) break; + ++span; } + } - //-------------------------------------------------------------------- - template<class Scanline> void render(const Scanline& sl) + //===============================================render_scanlines_aa_solid + template<class Rasterizer, class Scanline, + class BaseRenderer, class ColorT> + void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl, + BaseRenderer& ren, const ColorT& color) + { + if(ras.rewind_scanlines()) { - int y = sl.y(); - m_ren->first_clip_box(); - do + // Explicitly convert "color" to the BaseRenderer color type. + // For example, it can be called with color type "rgba", while + // "rgba8" is needed. Otherwise it will be implicitly + // converted in the loop many times. + //---------------------- + typename BaseRenderer::color_type ren_color(color); + + sl.reset(ras.min_x(), ras.max_x()); + while(ras.sweep_scanline(sl)) { - int xmin = m_ren->xmin(); - int xmax = m_ren->xmax(); + //render_scanline_aa_solid(sl, ren, ren_color); + + // This code is equivalent to the above call (copy/paste). + // It's just a "manual" optimization for old compilers, + // like Microsoft Visual C++ v6.0 + //------------------------------- + int y = sl.y(); + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); - if(y >= m_ren->ymin() && y <= m_ren->ymax()) + for(;;) { - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - do + int x = span->x; + if(span->len > 0) { - int x = span->x; - int len = span->len; - bool solid = false; - const typename Scanline::cover_type* covers = span->covers; - - if(len < 0) - { - solid = true; - len = -len; - } - - if(x < xmin) - { - len -= xmin - x; - if(!solid) - { - covers += 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), - solid ? 0 : covers, - *covers); - } - } - ++span; + ren.blend_solid_hspan(x, y, (unsigned)span->len, + ren_color, + span->covers); + } + else + { + ren.blend_hline(x, y, (unsigned)(x - span->len - 1), + ren_color, + *(span->covers)); } - while(--num_spans); + if(--num_spans == 0) break; + ++span; } } - while(m_ren->next_clip_box()); + } + } + + //==============================================renderer_scanline_aa_solid + template<class BaseRenderer> class renderer_scanline_aa_solid + { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + renderer_scanline_aa_solid() : m_ren(0) {} + explicit renderer_scanline_aa_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() {} + + //-------------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + render_scanline_aa_solid(sl, *m_ren, m_color); } private: base_ren_type* m_ren; - SpanGenerator* m_span_gen; + color_type m_color; }; - //==============================================renderer_scanline_aa_opaque - template<class BaseRenderer, class SpanGenerator> class renderer_scanline_aa_opaque + + + + + + + + + + //======================================================render_scanline_aa + template<class Scanline, class BaseRenderer, + class SpanAllocator, class SpanGenerator> + void render_scanline_aa(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; + const typename Scanline::cover_type* covers = span->covers; + + 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, + (span->len < 0) ? 0 : covers, *covers); + + if(--num_spans == 0) break; + ++span; + } + } + + //=====================================================render_scanlines_aa + template<class Rasterizer, class Scanline, class BaseRenderer, + class SpanAllocator, class SpanGenerator> + void render_scanlines_aa(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_aa(sl, ren, alloc, span_gen); + } + } + } + + //====================================================renderer_scanline_aa + template<class BaseRenderer, class SpanAllocator, class SpanGenerator> + class renderer_scanline_aa { public: - typedef BaseRenderer base_ren_type; + typedef BaseRenderer base_ren_type; + typedef SpanAllocator alloc_type; + typedef SpanGenerator span_gen_type; //-------------------------------------------------------------------- - renderer_scanline_aa_opaque(base_ren_type& ren, SpanGenerator& span_gen) : + renderer_scanline_aa() : m_ren(0), m_alloc(0), m_span_gen(0) {} + renderer_scanline_aa(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(unsigned max_span_len) - { - m_span_gen->prepare(max_span_len); - } + void prepare() { m_span_gen->prepare(); } //-------------------------------------------------------------------- template<class Scanline> void render(const Scanline& sl) { - int y = sl.y(); - m_ren->first_clip_box(); - do - { - int xmin = m_ren->xmin(); - int xmax = m_ren->xmax(); - - if(y >= m_ren->ymin() && y <= m_ren->ymax()) - { - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - do - { - int x = span->x; - int len = span->len; - bool solid = false; - const typename Scanline::cover_type* covers = span->covers; - - if(len < 0) - { - solid = true; - len = -len; - } - - if(x < xmin) - { - len -= xmin - x; - if(!solid) - { - covers += xmin - x; - } - x = xmin; - } - - if(len > 0) - { - if(x + len > xmax) - { - len = xmax - x + 1; - } - if(len > 0) - { - m_ren->blend_opaque_color_hspan_no_clip( - x, y, len, - m_span_gen->generate(x, y, len), - solid ? 0 : covers, - *covers); - } - } - ++span; - } - while(--num_spans); - } - } - while(m_ren->next_clip_box()); + render_scanline_aa(sl, *m_ren, *m_alloc, *m_span_gen); } private: base_ren_type* m_ren; - SpanGenerator* m_span_gen; + alloc_type* m_alloc; + span_gen_type* m_span_gen; }; - //==============================================renderer_scanline_aa_solid - template<class BaseRenderer> class renderer_scanline_aa_solid + + + + //===============================================render_scanline_bin_solid + template<class Scanline, class BaseRenderer, class ColorT> + void render_scanline_bin_solid(const Scanline& sl, + BaseRenderer& ren, + const ColorT& color) + { + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + ren.blend_hline(span->x, + sl.y(), + span->x - 1 + ((span->len < 0) ? + -span->len : + span->len), + color, + cover_full); + if(--num_spans == 0) break; + ++span; + } + } + + //==============================================render_scanlines_bin_solid + template<class Rasterizer, class Scanline, + class BaseRenderer, class ColorT> + void render_scanlines_bin_solid(Rasterizer& ras, Scanline& sl, + BaseRenderer& ren, const ColorT& color) + { + if(ras.rewind_scanlines()) + { + // Explicitly convert "color" to the BaseRenderer color type. + // For example, it can be called with color type "rgba", while + // "rgba8" is needed. Otherwise it will be implicitly + // converted in the loop many times. + //---------------------- + typename BaseRenderer::color_type ren_color(color); + + sl.reset(ras.min_x(), ras.max_x()); + while(ras.sweep_scanline(sl)) + { + //render_scanline_bin_solid(sl, ren, ren_color); + + // This code is equivalent to the above call (copy/paste). + // It's just a "manual" optimization for old compilers, + // like Microsoft Visual C++ v6.0 + //------------------------------- + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + ren.blend_hline(span->x, + sl.y(), + span->x - 1 + ((span->len < 0) ? + -span->len : + span->len), + ren_color, + cover_full); + if(--num_spans == 0) break; + ++span; + } + } + } + } + + //=============================================renderer_scanline_bin_solid + template<class BaseRenderer> class renderer_scanline_bin_solid { public: typedef BaseRenderer base_ren_type; typedef typename base_ren_type::color_type color_type; //-------------------------------------------------------------------- - renderer_scanline_aa_solid(base_ren_type& ren) : - m_ren(&ren) + renderer_scanline_bin_solid() : m_ren(0) {} + explicit renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {} + void attach(base_ren_type& ren) { + m_ren = &ren; } //-------------------------------------------------------------------- @@ -214,33 +322,12 @@ namespace agg const color_type& color() const { return m_color; } //-------------------------------------------------------------------- - void prepare(unsigned) {} + void prepare() {} //-------------------------------------------------------------------- template<class Scanline> void render(const Scanline& sl) { - int y = sl.y(); - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - - do - { - int x = span->x; - if(span->len > 0) - { - m_ren->blend_solid_hspan(x, y, (unsigned)span->len, - m_color, - span->covers); - } - else - { - m_ren->blend_hline(x, y, (unsigned)(x - span->len - 1), - m_color, - *(span->covers)); - } - ++span; - } - while(--num_spans); + render_scanline_bin_solid(sl, *m_ren, m_color); } private: @@ -254,196 +341,511 @@ namespace agg - //===================================================renderer_scanline_bin - template<class BaseRenderer, class SpanGenerator> class renderer_scanline_bin + + //======================================================render_scanline_bin + template<class Scanline, class BaseRenderer, + class SpanAllocator, class SpanGenerator> + void render_scanline_bin(const Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + int y = sl.y(); + + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + int x = span->x; + int len = span->len; + if(len < 0) len = -len; + typename BaseRenderer::color_type* colors = alloc.allocate(len); + span_gen.generate(colors, x, y, len); + ren.blend_color_hspan(x, y, len, colors, 0, cover_full); + if(--num_spans == 0) break; + ++span; + } + } + + //=====================================================render_scanlines_bin + template<class Rasterizer, class Scanline, class BaseRenderer, + class SpanAllocator, class SpanGenerator> + void render_scanlines_bin(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + if(ras.rewind_scanlines()) + { + sl.reset(ras.min_x(), ras.max_x()); + span_gen.prepare(); + while(ras.sweep_scanline(sl)) + { + render_scanline_bin(sl, ren, alloc, span_gen); + } + } + } + + //====================================================renderer_scanline_bin + template<class BaseRenderer, class SpanAllocator, class SpanGenerator> + class renderer_scanline_bin { public: - typedef BaseRenderer base_ren_type; + typedef BaseRenderer base_ren_type; + typedef SpanAllocator alloc_type; + typedef SpanGenerator span_gen_type; //-------------------------------------------------------------------- - renderer_scanline_bin(base_ren_type& ren, SpanGenerator& span_gen) : + 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(unsigned max_span_len) - { - m_span_gen->prepare(max_span_len); - } + void prepare() { m_span_gen->prepare(); } //-------------------------------------------------------------------- template<class Scanline> void render(const Scanline& sl) { - int y = sl.y(); - m_ren->first_clip_box(); - do - { - int xmin = m_ren->xmin(); - int xmax = m_ren->xmax(); - - if(y >= m_ren->ymin() && y <= m_ren->ymax()) - { - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - do - { - 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); - } - } - ++span; - } - while(--num_spans); - } - } - while(m_ren->next_clip_box()); + render_scanline_bin(sl, *m_ren, *m_alloc, *m_span_gen); } private: base_ren_type* m_ren; - SpanGenerator* m_span_gen; + alloc_type* m_alloc; + span_gen_type* m_span_gen; }; - //===============================================renderer_scanline_bin_opaque - template<class BaseRenderer, class SpanGenerator> class renderer_scanline_bin_opaque - { - public: - typedef BaseRenderer base_ren_type; - //-------------------------------------------------------------------- - renderer_scanline_bin_opaque(base_ren_type& ren, SpanGenerator& span_gen) : - m_ren(&ren), - m_span_gen(&span_gen) + + + + + + + //========================================================render_scanlines + template<class Rasterizer, class Scanline, class Renderer> + void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren) + { + if(ras.rewind_scanlines()) { + sl.reset(ras.min_x(), ras.max_x()); + ren.prepare(); + while(ras.sweep_scanline(sl)) + { + ren.render(sl); + } } - - //-------------------------------------------------------------------- - void prepare(unsigned max_span_len) + } + + //========================================================render_all_paths + template<class Rasterizer, class Scanline, class Renderer, + class VertexSource, class ColorStorage, class PathId> + void render_all_paths(Rasterizer& ras, + Scanline& sl, + Renderer& r, + VertexSource& vs, + const ColorStorage& as, + const PathId& path_id, + unsigned num_paths) + { + for(unsigned i = 0; i < num_paths; i++) { - m_span_gen->prepare(max_span_len); + ras.reset(); + ras.add_path(vs, path_id[i]); + r.color(as[i]); + render_scanlines(ras, sl, r); } + } - //-------------------------------------------------------------------- - template<class Scanline> void render(const Scanline& sl) + + + + + + //=============================================render_scanlines_compound + template<class Rasterizer, + class ScanlineAA, + class ScanlineBin, + class BaseRenderer, + class SpanAllocator, + class StyleHandler> + void render_scanlines_compound(Rasterizer& ras, + ScanlineAA& sl_aa, + ScanlineBin& sl_bin, + BaseRenderer& ren, + SpanAllocator& alloc, + StyleHandler& sh) + { + if(ras.rewind_scanlines()) { - int y = sl.y(); - m_ren->first_clip_box(); - do + int min_x = ras.min_x(); + int len = ras.max_x() - min_x + 2; + sl_aa.reset(min_x, ras.max_x()); + sl_bin.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; + unsigned num_spans; + + unsigned num_styles; + unsigned style; + bool solid; + while((num_styles = ras.sweep_styles()) > 0) { - int xmin = m_ren->xmin(); - int xmax = m_ren->xmax(); - - if(y >= m_ren->ymin() && y <= m_ren->ymax()) + typename ScanlineAA::const_iterator span_aa; + if(num_styles == 1) { - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - do + // Optimization for a single style. Happens often + //------------------------- + if(ras.sweep_scanline(sl_aa, 0)) { - int x = span->x; - int len = span->len; - - if(len < 0) len = -len; - if(x < xmin) + style = ras.style(0); + if(sh.is_solid(style)) { - len -= xmin - x; - x = xmin; + // Just solid fill + //----------------------- + render_scanline_aa_solid(sl_aa, ren, sh.color(style)); } - if(len > 0) + else { - if(x + len > xmax) - { - len = xmax - x + 1; - } - if(len > 0) + // Arbitrary span generator + //----------------------- + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + for(;;) { - m_ren->blend_opaque_color_hspan_no_clip( - x, y, len, - m_span_gen->generate(x, y, len), - 0); + 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; } } - ++span; } - while(--num_spans); } - } - while(m_ren->next_clip_box()); - } - - private: - base_ren_type* m_ren; - SpanGenerator* m_span_gen; - }; + else + { + if(ras.sweep_scanline(sl_bin, -1)) + { + // Clear the spans of the mix_buffer + //-------------------- + typename ScanlineBin::const_iterator span_bin = sl_bin.begin(); + num_spans = sl_bin.num_spans(); + for(;;) + { + memset(mix_buffer + span_bin->x - min_x, + 0, + span_bin->len * sizeof(color_type)); + if(--num_spans == 0) break; + ++span_bin; + } + 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)) + { + color_type* colors; + color_type* cspan; + typename ScanlineAA::cover_type* covers; + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + if(solid) + { + // Just solid fill + //----------------------- + for(;;) + { + color_type c = sh.color(style); + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; + covers = span_aa->covers; + do + { + if(*covers == cover_full) + { + *colors = c; + } + else + { + colors->add(c, *covers); + } + ++colors; + ++covers; + } + 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); + covers = span_aa->covers; + do + { + if(*covers == cover_full) + { + *colors = *cspan; + } + else + { + colors->add(*cspan, *covers); + } + ++cspan; + ++colors; + ++covers; + } + while(--len); + if(--num_spans == 0) break; + ++span_aa; + } + } + } + } - //=============================================renderer_scanline_bin_solid - template<class BaseRenderer> class renderer_scanline_bin_solid + // Emit the blended result as a color hspan + //------------------------- + span_bin = sl_bin.begin(); + num_spans = sl_bin.num_spans(); + for(;;) + { + ren.blend_color_hspan(span_bin->x, + sl_bin.y(), + span_bin->len, + mix_buffer + span_bin->x - min_x, + 0, + cover_full); + if(--num_spans == 0) break; + ++span_bin; + } + } // if(ras.sweep_scanline(sl_bin, -1)) + } // if(num_styles == 1) ... else + } // while((num_styles = ras.sweep_styles()) > 0) + } // if(ras.rewind_scanlines()) + } + + //=======================================render_scanlines_compound_layered + template<class Rasterizer, + class ScanlineAA, + class BaseRenderer, + class SpanAllocator, + class StyleHandler> + void render_scanlines_compound_layered(Rasterizer& ras, + ScanlineAA& sl_aa, + BaseRenderer& ren, + SpanAllocator& alloc, + StyleHandler& sh) { - public: - typedef BaseRenderer base_ren_type; - typedef typename base_ren_type::color_type color_type; - - //-------------------------------------------------------------------- - renderer_scanline_bin_solid(base_ren_type& ren) : - m_ren(&ren) + 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(); - //-------------------------------------------------------------------- - void color(const color_type& c) { m_color = c; } - const color_type& color() const { return m_color; } + if(sl_len) + { + memset(mix_buffer + sl_start - min_x, + 0, + sl_len * sizeof(color_type)); - //-------------------------------------------------------------------- - void prepare(unsigned) {} + memset(cover_buffer + sl_start - min_x, + 0, + sl_len * sizeof(cover_type)); - //-------------------------------------------------------------------- - template<class Scanline> void render(const Scanline& sl) - { - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - do - { - m_ren->blend_hline(span->x, - sl.y(), - span->x - 1 + ((span->len < 0) ? - -span->len : - span->len), - m_color, - cover_full); - ++span; - } - while(--num_spans); - } + 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()) + } - private: - base_ren_type* m_ren; - color_type m_color; - }; } diff --git a/agg/inc/agg_rendering_buffer.h b/agg/inc/agg_rendering_buffer.h index 50b6a46fdfa8..4a73e1a7185a 100755 --- a/agg/inc/agg_rendering_buffer.h +++ b/agg/inc/agg_rendering_buffer.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -20,119 +20,222 @@ #ifndef AGG_RENDERING_BUFFER_INCLUDED #define AGG_RENDERING_BUFFER_INCLUDED -#include "agg_basics.h" +#include "agg_array.h" namespace agg { - //==========================================================row_ptr_cache - template<class T> class row_ptr_cache + //===========================================================row_accessor + template<class T> class row_accessor { public: + typedef const_row_info<T> row_data; + + //------------------------------------------------------------------- + row_accessor() : + m_buf(0), + m_start(0), + m_width(0), + m_height(0), + m_stride(0) + { + } + //-------------------------------------------------------------------- - struct row_data + row_accessor(T* buf, unsigned width, unsigned height, int stride) : + m_buf(0), + m_start(0), + m_width(0), + m_height(0), + m_stride(0) { - int x1, x2; - const int8u* ptr; - row_data() {} - row_data(int x1_, int x2_, const int8u* ptr_) : - x1(x1_), x2(x2_), ptr(ptr_) {} - }; + attach(buf, width, height, stride); + } - //------------------------------------------------------------------- - ~row_ptr_cache() + + //-------------------------------------------------------------------- + void attach(T* buf, unsigned width, unsigned height, int 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; + } + } + + //-------------------------------------------------------------------- + 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_start + y * m_stride; + } + AGG_INLINE T* row_ptr(int y) { return m_start + y * m_stride; } + AGG_INLINE const T* row_ptr(int y) const { return m_start + y * m_stride; } + AGG_INLINE row_data row (int y) const + { + return row_data(0, m_width-1, row_ptr(y)); + } + + //-------------------------------------------------------------------- + template<class RenBuf> + 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) { - delete [] m_rows; + 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 + 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 T> class row_ptr_cache + { + public: + typedef const_row_info<T> row_data; + //------------------------------------------------------------------- row_ptr_cache() : m_buf(0), - m_rows(0), + m_rows(), 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_ptr_cache(T* buf, unsigned width, unsigned height, int stride) : m_buf(0), - m_rows(0), + m_rows(), m_width(0), m_height(0), - m_stride(0), - m_max_height(0) + m_stride(0) { - attach(_buf, _width, _height, _stride); + attach(buf, width, height, stride); } //-------------------------------------------------------------------- - void attach(T* _buf, unsigned _width, unsigned _height, int _stride) + void attach(T* buf, unsigned width, unsigned height, int stride) { - m_buf = _buf; - m_width = _width; - m_height = _height; - m_stride = _stride; - if(_height > m_max_height) + m_buf = buf; + m_width = width; + m_height = height; + m_stride = stride; + if(height > m_rows.size()) { - delete [] m_rows; - m_rows = new T* [m_max_height = _height]; + m_rows.resize(height); } T* row_ptr = m_buf; - if(_stride < 0) + if(stride < 0) { - row_ptr = m_buf - int(_height - 1) * _stride; + row_ptr = m_buf - int(height - 1) * stride; } - T** _rows = m_rows; + T** rows = &m_rows[0]; - while(_height--) + while(height--) { - *_rows++ = row_ptr; - row_ptr += _stride; + *rows++ = row_ptr; + row_ptr += stride; } } //-------------------------------------------------------------------- - 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); + return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); } //-------------------------------------------------------------------- - T* row(unsigned y) { return m_rows[y]; } - const T* row(unsigned y) const { return m_rows[y]; } - - T* next_row(void* p) { return (T*)p + m_stride; } - const T* next_row(const void* p) const { return (T*)p + 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; } + //-------------------------------------------------------------------- + T const* const* rows() const { return &m_rows[0]; } //-------------------------------------------------------------------- - void copy_from(const row_ptr_cache<T>& mtx) + template<class RenBuf> + void copy_from(const RenBuf& src) { unsigned h = height(); - if(mtx.height() < h) h = mtx.height(); + if(src.height() < h) h = src.height(); unsigned l = stride_abs(); - if(mtx.stride_abs() < l) l = mtx.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(y), mtx.row(y), l); + memcpy(row_ptr(0, y, w), src.row_ptr(y), l); } } @@ -140,38 +243,56 @@ namespace agg void clear(T value) { unsigned y; + unsigned w = width(); + unsigned stride = stride_abs(); for(y = 0; y < height(); y++) { - T* p = row(y); + T* p = row_ptr(0, y, w); unsigned x; - for(x = 0; x < stride_abs(); x++) + for(x = 0; x < stride; x++) { *p++ = value; } } } - private: //-------------------------------------------------------------------- - // Prohibit copying - row_ptr_cache(const row_ptr_cache<T>&); - const row_ptr_cache<T>& operator = (const row_ptr_cache<T>&); - - private: - //-------------------------------------------------------------------- - T* m_buf; // Pointer to renrdering buffer - T** m_rows; // Pointers to each row of the buffer - 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 + pod_array<T*> m_rows; // Pointers to each row of the buffer + unsigned m_width; // Width in pixels + unsigned m_height; // Height in pixels + int m_stride; // Number of bytes per row. Can be < 0 }; + //========================================================rendering_buffer - typedef row_ptr_cache<int8u> rendering_buffer; + // + // The definition of the main type for accessing the rows in the frame + // buffer. It provides functionality to navigate to the rows in a + // rectangular matrix, from top to bottom or from bottom to top depending + // on stride. + // + // row_accessor is cheap to create/destroy, but performs one multiplication + // when calling row_ptr(). + // + // row_ptr_cache creates an array of pointers to rows, so, the access + // via row_ptr() may be faster. But it requires memory allocation + // when creating. For example, on typical Intel Pentium hardware + // row_ptr_cache speeds span_image_filter_rgb_nn up to 10% + // + // It's used only in short hand typedefs like pixfmt_rgba32 and can be + // redefined in agg_config.h + // In real applications you can use both, depending on your needs + //------------------------------------------------------------------------ +#ifdef AGG_RENDERING_BUFFER + typedef AGG_RENDERING_BUFFER rendering_buffer; +#else +// typedef row_ptr_cache<int8u> rendering_buffer; + typedef row_accessor<int8u> rendering_buffer; +#endif } diff --git a/agg/inc/agg_rendering_buffer_dynarow.h b/agg/inc/agg_rendering_buffer_dynarow.h index b6724d99ff78..b4332cad5adb 100755 --- a/agg/inc/agg_rendering_buffer_dynarow.h +++ b/agg/inc/agg_rendering_buffer_dynarow.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -20,7 +20,7 @@ #ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED #define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED -#include "agg_basics.h" +#include "agg_array.h" namespace agg { @@ -32,110 +32,68 @@ namespace agg // Generally it's more efficient to use this class as a temporary buffer // for rendering a few lines and then to blend it with another buffer. // - template<unsigned PixWidth> class rendering_buffer_dynarow + class rendering_buffer_dynarow { public: - //------------------------------------------------------------------- - struct row_data - { - int8u* ptr; - int x1; - int x2; - }; + typedef row_info<int8u> row_data; //------------------------------------------------------------------- ~rendering_buffer_dynarow() { - init(0,0); + init(0,0,0); } //------------------------------------------------------------------- rendering_buffer_dynarow() : - m_rows(0), + m_rows(), m_width(0), - m_height(0) + m_height(0), + m_byte_width(0) { } // Allocate and clear the buffer //-------------------------------------------------------------------- - rendering_buffer_dynarow(unsigned width, unsigned height) : - m_rows(new row_data[height]), + rendering_buffer_dynarow(unsigned width, unsigned height, + unsigned byte_width) : + m_rows(height), m_width(width), - m_height(height) + 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 //-------------------------------------------------------------------- - void init(unsigned width, unsigned height) + void init(unsigned width, unsigned height, unsigned byte_width) { unsigned i; - for(i = 0; i < m_height; ++i) delete [] m_rows[i].ptr; - delete [] m_rows; - m_rows = 0; + for(i = 0; i < m_height; ++i) + { + pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width); + } if(width && height) { m_width = width; m_height = height; - m_rows = new row_data[height]; - memset(m_rows, 0, sizeof(row_data) * height); + m_byte_width = byte_width; + m_rows.resize(height); + memset(&m_rows[0], 0, sizeof(row_data) * height); } } //-------------------------------------------------------------------- - unsigned width() const { return m_width; } - unsigned height() const { return m_height; } - - // Get pointer to the beginning of the row. Memory for the row - // is allocated as needed. - //-------------------------------------------------------------------- - int8u* row(int y) - { - row_data* r = m_rows + y; - if(r->ptr == 0) - { - r->ptr = new int8u [m_width * PixWidth]; - memset(r->ptr, 0, m_width * PixWidth); - } - return r->ptr; - } - - // Get const pointer to the row. The caller must check it for null. - //-------------------------------------------------------------------- - const int8u* row(int y) const - { - return m_rows[y].ptr; - } - - // Get the Y-th span. The pointer r.ptr is automatically adjusted - // to the actual beginning of the span. Use this function as follows: - // - // rendering_buffer_dynarow::row_data r = rbuf.span(x, y); - // if(r.ptr) - // { - // do { blend(r.ptr); r.ptr += PixWidth } while(++r.x1 < r.x2); - // } - //-------------------------------------------------------------------- - row_data span(int x, int y) const - { - row_data r = m_rows[y]; - if(r.ptr) - { - if(x < r.x1) x = r.x1; - r.ptr += x * PixWidth; - } - return r; - } - + unsigned width() const { return m_width; } + unsigned height() const { return m_height; } + unsigned byte_width() const { return m_byte_width; } // The main function used for rendering. Returns pointer to the // pre-allocated span. Memory for the row is allocated as needed. //-------------------------------------------------------------------- - int8u* span_ptr(int x, int y, unsigned len) + int8u* row_ptr(int x, int y, unsigned len) { - row_data* r = m_rows + y; + row_data* r = &m_rows[y]; int x2 = x + len - 1; if(r->ptr) { @@ -144,37 +102,32 @@ namespace agg } else { - r->ptr = new int8u [m_width * PixWidth]; - r->x1 = x; - r->x2 = x2; - memset(r->ptr, 0, m_width * PixWidth); + int8u* p = pod_allocator<int8u>::allocate(m_byte_width); + r->ptr = p; + r->x1 = x; + r->x2 = x2; + memset(p, 0, m_byte_width); } - return r->ptr + x * PixWidth; + return (int8u*)r->ptr; } - // Get const pointer to the span. Used mostly in GetPixel function - // The caller must check the returned pointer for null. //-------------------------------------------------------------------- - const int8u* span_ptr(int x, int y, unsigned) const - { - row_data* r = m_rows + y; - return r->ptr ? r->ptr + x * PixWidth : 0; - } - - + const int8u* row_ptr(int y) const { return m_rows[y].ptr; } + int8u* row_ptr(int y) { return row_ptr(0, y, m_width); } + row_data row (int y) const { return m_rows[y]; } private: //-------------------------------------------------------------------- // Prohibit copying - rendering_buffer_dynarow(const rendering_buffer_dynarow<PixWidth>&); - const rendering_buffer_dynarow<PixWidth>& - operator = (const rendering_buffer_dynarow<PixWidth>&); + rendering_buffer_dynarow(const rendering_buffer_dynarow&); + const rendering_buffer_dynarow& operator = (const rendering_buffer_dynarow&); private: //-------------------------------------------------------------------- - row_data* m_rows; // Pointers to each row of the buffer - unsigned m_width; // Width in pixels - unsigned m_height; // Height in pixels + pod_array<row_data> m_rows; // Pointers to each row of the buffer + unsigned m_width; // Width in pixels + unsigned m_height; // Height in pixels + unsigned m_byte_width; // Width in bytes }; diff --git a/agg/inc/agg_rounded_rect.h b/agg/inc/agg_rounded_rect.h index d4185dafa5b3..e2e621341ec1 100755 --- a/agg/inc/agg_rounded_rect.h +++ b/agg/inc/agg_rounded_rect.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -22,8 +22,6 @@ #include "agg_basics.h" #include "agg_arc.h" -#include "agg_vertex_iterator.h" - namespace agg { @@ -51,11 +49,6 @@ namespace agg void rewind(unsigned); unsigned vertex(double* x, double* y); - typedef rounded_rect source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: double m_x1; double m_y1; diff --git a/agg/inc/agg_scanline_bin.h b/agg/inc/agg_scanline_bin.h index aa60ed061e07..2836447175cb 100755 --- a/agg/inc/agg_scanline_bin.h +++ b/agg/inc/agg_scanline_bin.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -16,10 +16,19 @@ // Class scanline_bin - binary scanline. // //---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates (scanline32_bin) has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + #ifndef AGG_SCANLINE_BIN_INCLUDED #define AGG_SCANLINE_BIN_INCLUDED -#include "agg_basics.h" +#include "agg_array.h" namespace agg { @@ -30,36 +39,12 @@ namespace agg // used in the rasterizer::render(). See description of agg_scanline_u8 // for details. // - // Rendering: - //------------------------------------------------------------------------- - // - // int y = sl.y(); - // - // ************************************ - // ...Perform vertical clipping here... - // ************************************ - // - // unsigned num_spans = sl.num_spans(); - // const agg::scanline_bin::span* cur_span = sl.spans(); - // - // do - // { - // x = cur_span->x; - // len = cur_span->len; - // - // ************************************** - // ...Perform horizontal clipping here... - // ************************************** - // - // hor_line(x, y, len) - // ++cur_span; - // } - // while(--num_spans); - // //------------------------------------------------------------------------ class scanline_bin { public: + typedef int32 coord_type; + struct span { int16 x; @@ -68,103 +53,211 @@ namespace agg typedef const span* const_iterator; - ~scanline_bin() + //-------------------------------------------------------------------- + scanline_bin() : + m_last_x(0x7FFFFFF0), + m_spans(), + m_cur_span(0) { - delete [] m_spans; } - scanline_bin() : - m_max_len(0), - m_last_x(0x7FFF), - m_spans(0), - m_cur_span(0) + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) { + unsigned max_len = max_x - min_x + 3; + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cur_span = &m_spans[0]; } - void reset(int min_x, int max_x); - void add_cell(int x, unsigned); - void add_cells(int x, unsigned len, const void*); - void add_span(int x, unsigned len, unsigned); - void finalize(int y) { m_y = y; } - void reset_spans(); + //-------------------------------------------------------------------- + void add_cell(int x, unsigned) + { + if(x == m_last_x+1) + { + m_cur_span->len++; + } + else + { + ++m_cur_span; + m_cur_span->x = (int16)x; + m_cur_span->len = 1; + } + m_last_x = x; + } + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned) + { + if(x == m_last_x+1) + { + m_cur_span->len = (int16)(m_cur_span->len + len); + } + else + { + ++m_cur_span; + m_cur_span->x = (int16)x; + m_cur_span->len = (int16)len; + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const void*) + { + add_span(x, len, 0); + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + 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<span> m_spans; + span* m_cur_span; }; - //------------------------------------------------------------------------ - inline void scanline_bin::reset(int min_x, int max_x) + + + + + //===========================================================scanline32_bin + class scanline32_bin { - unsigned max_len = max_x - min_x + 3; - if(max_len > m_max_len) + public: + typedef int32 coord_type; + + //-------------------------------------------------------------------- + struct span { - delete [] m_spans; - m_spans = new span [max_len]; - m_max_len = max_len; - } - m_last_x = 0x7FFF; - m_cur_span = m_spans; - } + span() {} + span(coord_type x_, coord_type len_) : x(x_), len(len_) {} + coord_type x; + coord_type len; + }; + typedef pod_bvector<span, 4> span_array_type; - //------------------------------------------------------------------------ - inline void scanline_bin::reset_spans() - { - m_last_x = 0x7FFF; - m_cur_span = m_spans; - } + //-------------------------------------------------------------------- + class const_iterator + { + public: + const_iterator(const span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} - //------------------------------------------------------------------------ - inline void scanline_bin::add_cell(int x, unsigned) - { - if(x == m_last_x+1) + const span& operator*() const { return m_spans[m_span_idx]; } + const span* operator->() const { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + const span_array_type& m_spans; + unsigned m_span_idx; + }; + + + //-------------------------------------------------------------------- + scanline32_bin() : m_max_len(0), m_last_x(0x7FFFFFF0) {} + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + m_last_x = 0x7FFFFFF0; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned) { - m_cur_span->len++; + if(x == m_last_x+1) + { + m_spans.last().len++; + } + else + { + m_spans.add(span(coord_type(x), 1)); + } + m_last_x = x; } - else + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned) { - ++m_cur_span; - m_cur_span->x = (int16)x; - m_cur_span->len = 1; + if(x == m_last_x+1) + { + m_spans.last().len += coord_type(len); + } + else + { + m_spans.add(span(coord_type(x), coord_type(len))); + } + m_last_x = x + len - 1; } - m_last_x = x; - } + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const void*) + { + add_span(x, len, 0); + } - //------------------------------------------------------------------------ - inline void scanline_bin::add_span(int x, unsigned len, unsigned) - { - if(x == m_last_x+1) + //-------------------------------------------------------------------- + void finalize(int y) { - m_cur_span->len = (int16)(m_cur_span->len + len); + m_y = y; } - else + + //-------------------------------------------------------------------- + void reset_spans() { - ++m_cur_span; - m_cur_span->x = (int16)x; - m_cur_span->len = (int16)len; + m_last_x = 0x7FFFFFF0; + m_spans.remove_all(); } - m_last_x = x + len - 1; - } - //------------------------------------------------------------------------ - inline void scanline_bin::add_cells(int x, unsigned len, const void*) - { - add_span(x, len, 0); - } + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return m_spans.size(); } + const_iterator begin() const { return const_iterator(m_spans); } + + private: + scanline32_bin(const scanline32_bin&); + const scanline32_bin operator = (const scanline32_bin&); + + unsigned m_max_len; + int m_last_x; + int m_y; + span_array_type m_spans; + }; + + + + + } diff --git a/agg/inc/agg_scanline_boolean_algebra.h b/agg/inc/agg_scanline_boolean_algebra.h index 7f1a3c5ba774..cad386bac0c4 100755 --- a/agg/inc/agg_scanline_boolean_algebra.h +++ b/agg/inc/agg_scanline_boolean_algebra.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -141,7 +141,7 @@ namespace agg unsigned CoverShift = cover_shift> struct sbool_intersect_spans_aa { - enum + enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, @@ -253,7 +253,7 @@ namespace agg unsigned CoverShift = cover_shift> struct sbool_unite_spans_aa { - enum + enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, @@ -362,7 +362,7 @@ namespace agg template<unsigned CoverShift = cover_shift> struct sbool_xor_formula_linear { - enum + enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, @@ -382,7 +382,7 @@ namespace agg template<unsigned CoverShift = cover_shift> struct sbool_xor_formula_saddle { - enum + enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, @@ -424,7 +424,7 @@ namespace agg unsigned CoverShift = cover_shift> struct sbool_xor_spans_aa { - enum + enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, @@ -513,7 +513,7 @@ namespace agg unsigned CoverShift = cover_shift> struct sbool_subtract_spans_aa { - enum + enum cover_scale_e { cover_shift = CoverShift, cover_size = 1 << cover_shift, @@ -629,14 +629,14 @@ namespace agg AddSpanFunctor add_span) { sl.reset_spans(); - typename Scanline::const_iterator span = sl1.begin(); + typename Scanline1::const_iterator span = sl1.begin(); unsigned num_spans = sl1.num_spans(); - do + for(;;) { add_span(span, span->x, abs((int)span->len), sl); + if(--num_spans == 0) break; ++span; } - while(--num_spans); sl.finalize(sl1.y()); ren.render(sl); } @@ -671,8 +671,8 @@ namespace agg unsigned num2 = sl2.num_spans(); if(num2 == 0) return; - typename Scanline::const_iterator span1 = sl1.begin(); - typename Scanline::const_iterator span2 = sl2.begin(); + typename Scanline1::const_iterator span1 = sl1.begin(); + typename Scanline2::const_iterator span2 = sl2.begin(); while(num1 && num2) { @@ -705,20 +705,20 @@ namespace agg { --num1; --num2; - ++span1; - ++span2; + if(num1) ++span1; + if(num2) ++span2; } else { if(advance_span1) { --num1; - ++span1; + if(num1) ++span1; } else { --num2; - ++span2; + if(num2) ++span2; } } } @@ -765,13 +765,13 @@ namespace agg // Get the bounding boxes //---------------- - rect r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); - rect r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); + rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); + rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); // Calculate the intersection of the bounding // boxes and return if they don't intersect. //----------------- - rect ir = intersect_rectangles(r1, r2); + rect_i ir = intersect_rectangles(r1, r2); if(!ir.is_valid()) return; // Reset the scanlines and get two first ones @@ -782,7 +782,7 @@ namespace agg if(!sg1.sweep_scanline(sl1)) return; if(!sg2.sweep_scanline(sl2)) return; - ren.prepare(unsigned(ir.x2 - ir.x1 + 2)); + ren.prepare(); // The main loop // Here we synchronize the scanlines with @@ -850,10 +850,14 @@ namespace agg unsigned num1 = sl1.num_spans(); unsigned num2 = sl2.num_spans(); - typename Scanline::const_iterator span1; - typename Scanline::const_iterator span2; + typename Scanline1::const_iterator span1;// = sl1.begin(); + typename Scanline2::const_iterator span2;// = sl2.begin(); - enum { invalid_b = 0xFFFFFFF, invalid_e = invalid_b - 1 }; + enum invalidation_e + { + invalid_b = 0xFFFFFFF, + invalid_e = invalid_b - 1 + }; // Initialize the spans as invalid //--------------- @@ -1037,15 +1041,19 @@ namespace agg // Get the bounding boxes //---------------- - rect r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); - rect r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); + rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); + rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); // Calculate the union of the bounding boxes //----------------- - rect ur = unite_rectangles(r1, r2); + rect_i ur(1,1,0,0); + if(flag1 && flag2) ur = unite_rectangles(r1, r2); + else if(flag1) ur = r1; + else if(flag2) ur = r2; + if(!ur.is_valid()) return; - ren.prepare(unsigned(ur.x2 - ur.x2 + 2)); + ren.prepare(); // Reset the scanlines and get two first ones //----------------- @@ -1158,7 +1166,7 @@ namespace agg // Get the bounding box //---------------- - rect r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); + rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); // Reset the scanlines and get two first ones //----------------- @@ -1169,10 +1177,10 @@ namespace agg if(flag2) flag2 = sg2.sweep_scanline(sl2); - ren.prepare(unsigned(sg1.max_x() - sg1.min_x() + 2)); + ren.prepare(); // A fake span2 processor - sbool_add_span_empty<Scanline1, Scanline> add_span2; + sbool_add_span_empty<Scanline2, Scanline> add_span2; // The main loop // Here we synchronize the scanlines with diff --git a/agg/inc/agg_scanline_p.h b/agg/inc/agg_scanline_p.h index f217998578a1..19e1e9d5cb59 100755 --- a/agg/inc/agg_scanline_p.h +++ b/agg/inc/agg_scanline_p.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -16,180 +16,312 @@ // Class scanline_p - a general purpose scanline container with packed spans. // //---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates (scanline32_p) has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- #ifndef AGG_SCANLINE_P_INCLUDED #define AGG_SCANLINE_P_INCLUDED -#include "agg_basics.h" +#include "agg_array.h" namespace agg { - //==============================================================scanline_p + //=============================================================scanline_p8 // // This is a general purpose scaline container which supports the interface - // used in the rasterizer::render(). See description of agg_scanline_u + // used in the rasterizer::render(). See description of scanline_u8 // for details. // //------------------------------------------------------------------------ - template<class T> class scanline_p + class scanline_p8 { public: - typedef T cover_type; + typedef scanline_p8 self_type; + typedef int8u cover_type; + typedef int16 coord_type; + //-------------------------------------------------------------------- struct span { - int16 x; - int16 len; // If negative, it's a solid span, covers is valid - const T* covers; + coord_type x; + coord_type len; // If negative, it's a solid span, covers is valid + const cover_type* covers; }; typedef span* iterator; typedef const span* const_iterator; - ~scanline_p() - { - delete [] m_spans; - delete [] m_covers; - } - - scanline_p() : - m_max_len(0), + scanline_p8() : m_last_x(0x7FFFFFF0), - m_covers(0), + m_covers(), m_cover_ptr(0), - m_spans(0), + m_spans(), m_cur_span(0) { } - void reset(int min_x, int max_x); - void add_cell(int x, unsigned cover); - void add_cells(int x, unsigned len, const T* covers); - void add_span(int x, unsigned len, unsigned cover); - void finalize(int y_) { m_y = y_; } - void reset_spans(); + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_cur_span = &m_spans[0]; + m_cur_span->len = 0; + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + *m_cover_ptr = (cover_type)cover; + if(x == m_last_x+1 && m_cur_span->len > 0) + { + m_cur_span->len++; + } + else + { + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cur_span->x = (int16)x; + m_cur_span->len = 1; + } + m_last_x = x; + m_cover_ptr++; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + memcpy(m_cover_ptr, covers, len * sizeof(cover_type)); + if(x == m_last_x+1 && m_cur_span->len > 0) + { + m_cur_span->len += (int16)len; + } + else + { + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cur_span->x = (int16)x; + m_cur_span->len = (int16)len; + } + m_cover_ptr += len; + m_last_x = x + len - 1; + } + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + if(x == m_last_x+1 && + m_cur_span->len < 0 && + cover == *m_cur_span->covers) + { + m_cur_span->len -= (int16)len; + } + else + { + *m_cover_ptr = (cover_type)cover; + m_cur_span++; + m_cur_span->covers = m_cover_ptr++; + m_cur_span->x = (int16)x; + m_cur_span->len = (int16)(-int(len)); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + 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_p(const scanline_p<T>&); - const scanline_p<T>& operator = (const scanline_p<T>&); - - unsigned m_max_len; - int m_last_x; - int m_y; - T* m_covers; - T* m_cover_ptr; - span* m_spans; - span* m_cur_span; + scanline_p8(const self_type&); + const self_type& operator = (const self_type&); + + int m_last_x; + int m_y; + pod_array<cover_type> m_covers; + cover_type* m_cover_ptr; + pod_array<span> m_spans; + span* m_cur_span; }; - //------------------------------------------------------------------------ - template<class T> - void scanline_p<T>::reset(int min_x, int max_x) - { - unsigned max_len = max_x - min_x + 3; - if(max_len > m_max_len) - { - delete [] m_spans; - delete [] m_covers; - m_covers = new T [max_len]; - m_spans = new span [max_len]; - m_max_len = max_len; - } - m_last_x = 0x7FFFFFF0; - m_cover_ptr = m_covers; - m_cur_span = m_spans; - m_cur_span->len = 0; - } - //------------------------------------------------------------------------ - template<class T> - void scanline_p<T>::reset_spans() - { - m_last_x = 0x7FFFFFF0; - m_cover_ptr = m_covers; - m_cur_span = m_spans; - m_cur_span->len = 0; - } - //------------------------------------------------------------------------ - template<class T> - void scanline_p<T>::add_cell(int x, unsigned cover) + + + //==========================================================scanline32_p8 + class scanline32_p8 { - *m_cover_ptr = (T)cover; - if(x == m_last_x+1 && m_cur_span->len > 0) + public: + typedef scanline32_p8 self_type; + typedef int8u cover_type; + typedef int32 coord_type; + + struct span { - m_cur_span->len++; - } - else + span() {} + span(coord_type x_, coord_type len_, const cover_type* covers_) : + x(x_), len(len_), covers(covers_) {} + + coord_type x; + coord_type len; // If negative, it's a solid span, covers is valid + const cover_type* covers; + }; + typedef pod_bvector<span, 4> span_array_type; + + + //-------------------------------------------------------------------- + class const_iterator + { + public: + const_iterator(const span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + + const span& operator*() const { return m_spans[m_span_idx]; } + const span* operator->() const { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + const span_array_type& m_spans; + unsigned m_span_idx; + }; + + //-------------------------------------------------------------------- + scanline32_p8() : + m_max_len(0), + m_last_x(0x7FFFFFF0), + m_covers(), + m_cover_ptr(0) { - m_cur_span++; - m_cur_span->covers = m_cover_ptr; - m_cur_span->x = (int16)x; - m_cur_span->len = 1; } - m_last_x = x; - m_cover_ptr++; - } + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; + if(max_len > m_covers.size()) + { + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_spans.remove_all(); + } - //------------------------------------------------------------------------ - template<class T> - void scanline_p<T>::add_cells(int x, unsigned len, const T* covers) - { - memcpy(m_cover_ptr, covers, len * sizeof(T)); - if(x == m_last_x+1 && m_cur_span->len > 0) + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) { - m_cur_span->len += (int16)len; + *m_cover_ptr = cover_type(cover); + if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0) + { + m_spans.last().len++; + } + else + { + m_spans.add(span(coord_type(x), 1, m_cover_ptr)); + } + m_last_x = x; + m_cover_ptr++; } - else + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) { - m_cur_span++; - m_cur_span->covers = m_cover_ptr; - m_cur_span->x = (int16)x; - m_cur_span->len = (int16)len; + memcpy(m_cover_ptr, covers, len * sizeof(cover_type)); + if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0) + { + m_spans.last().len += coord_type(len); + } + else + { + m_spans.add(span(coord_type(x), coord_type(len), m_cover_ptr)); + } + m_cover_ptr += len; + m_last_x = x + len - 1; } - m_cover_ptr += len; - m_last_x = x + len - 1; - } + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + if(x == m_last_x+1 && + m_spans.size() && + m_spans.last().len < 0 && + cover == *m_spans.last().covers) + { + m_spans.last().len -= coord_type(len); + } + else + { + *m_cover_ptr = cover_type(cover); + m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++)); + } + m_last_x = x + len - 1; + } - //------------------------------------------------------------------------ - template<class T> - void scanline_p<T>::add_span(int x, unsigned len, unsigned cover) - { - if(x == m_last_x+1 && - m_cur_span->len < 0 && - cover == *m_cur_span->covers) + //-------------------------------------------------------------------- + void finalize(int y) { - m_cur_span->len -= (int16)len; + m_y = y; } - else + + //-------------------------------------------------------------------- + void reset_spans() { - *m_cover_ptr = (T)cover; - m_cur_span++; - m_cur_span->covers = m_cover_ptr++; - m_cur_span->x = (int16)x; - m_cur_span->len = -((int16)len); + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_spans.remove_all(); } - m_last_x = x + len - 1; - } + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return m_spans.size(); } + const_iterator begin() const { return const_iterator(m_spans); } + + private: + scanline32_p8(const self_type&); + const self_type& operator = (const self_type&); - //=============================================================scanline_p8 - typedef scanline_p<int8u> scanline_p8; + unsigned m_max_len; + int m_last_x; + int m_y; + pod_array<cover_type> m_covers; + cover_type* m_cover_ptr; + span_array_type m_spans; + }; - //============================================================scanline_p16 - typedef scanline_p<int16u> scanline_p16; - //============================================================scanline_p32 - typedef scanline_p<int32u> scanline_p32; } diff --git a/agg/inc/agg_scanline_storage_aa.h b/agg/inc/agg_scanline_storage_aa.h index 3d8b5b946cf9..279b9f39bbc1 100755 --- a/agg/inc/agg_scanline_storage_aa.h +++ b/agg/inc/agg_scanline_storage_aa.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -12,6 +12,14 @@ // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- #ifndef AGG_SCANLINE_STORAGE_AA_INCLUDED #define AGG_SCANLINE_STORAGE_AA_INCLUDED @@ -20,7 +28,6 @@ #include <stdlib.h> #include <math.h> #include "agg_array.h" -#include "agg_render_scanlines.h" namespace agg @@ -76,7 +83,8 @@ namespace agg int i; for(i = m_extra_storage.size()-1; i >= 0; --i) { - delete [] m_extra_storage[(unsigned)i].ptr; + pod_allocator<T>::deallocate(m_extra_storage[i].ptr, + m_extra_storage[i].len); } m_extra_storage.remove_all(); m_cells.remove_all(); @@ -94,7 +102,7 @@ namespace agg } extra_span s; s.len = num_cells; - s.ptr = new T [num_cells]; + s.ptr = pod_allocator<T>::allocate(num_cells); memcpy(s.ptr, cells, sizeof(T) * num_cells); m_extra_storage.add(s); return -int(m_extra_storage.size()); @@ -135,14 +143,14 @@ namespace agg const extra_span& src = v.m_extra_storage[i]; extra_span dst; dst.len = src.len; - dst.ptr = new T [dst.len]; + dst.ptr = pod_allocator<T>::allocate(dst.len); memcpy(dst.ptr, src.ptr, dst.len * sizeof(T)); m_extra_storage.add(dst); } } - pod_deque<T, 12> m_cells; - pod_deque<extra_span, 6> m_extra_storage; + pod_bvector<T, 12> m_cells; + pod_bvector<extra_span, 6> m_extra_storage; }; @@ -159,8 +167,8 @@ namespace agg //--------------------------------------------------------------- struct span_data { - int16 x; - int16 len; // If negative, it's a solid span, covers is valid + int32 x; + int32 len; // If negative, it's a solid span, covers is valid int covers_id; // The index of the cells in the scanline_cell_storage }; @@ -184,11 +192,12 @@ namespace agg public: struct span { - int16 x; - int16 len; // If negative, it's a solid span, covers is valid + int32 x; + int32 len; // If negative, it's a solid span, covers is valid const T* covers; }; + const_iterator() : m_storage(0) {} const_iterator(const embedded_scanline& sl) : m_storage(sl.m_storage), m_span_idx(sl.m_scanline.start_span) @@ -270,7 +279,7 @@ namespace agg // Renderer Interface //--------------------------------------------------------------- - void prepare(unsigned) + void prepare() { m_covers.remove_all(); m_scanlines.remove_all(); @@ -297,7 +306,7 @@ namespace agg typename Scanline::const_iterator span_iterator = sl.begin(); unsigned num_spans = sl_this.num_spans; - do + for(;;) { span_data sp; @@ -312,9 +321,9 @@ namespace agg int x2 = sp.x + len - 1; if(x1 < m_min_x) m_min_x = x1; if(x2 > m_max_x) m_max_x = x2; + if(--num_spans == 0) break; ++span_iterator; } - while(--num_spans); m_scanlines.add(sl_this); } @@ -388,11 +397,11 @@ namespace agg unsigned byte_size() const { unsigned i; - unsigned size = sizeof(int16) * 4; // min_x, min_y, max_x, max_y + unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y for(i = 0; i < m_scanlines.size(); ++i) { - size += sizeof(int16) * 3; // scanline size in bytes, Y, num_spans + size += sizeof(int32) * 3; // scanline size in bytes, Y, num_spans const scanline_data& sl_this = m_scanlines[i]; @@ -402,7 +411,7 @@ namespace agg { const span_data& sp = m_spans[span_idx++]; - size += sizeof(int16) * 2; // X, span_len + size += sizeof(int32) * 2; // X, span_len if(sp.len < 0) { size += sizeof(T); // cover @@ -419,10 +428,12 @@ namespace agg //--------------------------------------------------------------- - static void write_int16(int8u* dst, int16 val) + static void write_int32(int8u* dst, int32 val) { dst[0] = ((const int8u*)&val)[0]; dst[1] = ((const int8u*)&val)[1]; + dst[2] = ((const int8u*)&val)[2]; + dst[3] = ((const int8u*)&val)[3]; } @@ -431,27 +442,27 @@ namespace agg { unsigned i; - write_int16(data, int16u(min_x())); // min_x - data += sizeof(int16u); - write_int16(data, int16u(min_y())); // min_y - data += sizeof(int16u); - write_int16(data, int16u(max_x())); // max_x - data += sizeof(int16u); - write_int16(data, int16u(max_y())); // max_y - data += sizeof(int16u); + write_int32(data, min_x()); // min_x + data += sizeof(int32); + write_int32(data, min_y()); // min_y + data += sizeof(int32); + write_int32(data, max_x()); // max_x + data += sizeof(int32); + write_int32(data, max_y()); // max_y + data += sizeof(int32); for(i = 0; i < m_scanlines.size(); ++i) { const scanline_data& sl_this = m_scanlines[i]; int8u* size_ptr = data; - data += sizeof(int16); // Reserve space for scanline size in bytes + data += sizeof(int32); // Reserve space for scanline size in bytes - write_int16(data, int16(sl_this.y)); // Y - data += sizeof(int16); + write_int32(data, sl_this.y); // Y + data += sizeof(int32); - write_int16(data, int16(sl_this.num_spans)); // num_spans - data += sizeof(int16); + write_int32(data, sl_this.num_spans); // num_spans + data += sizeof(int32); unsigned num_spans = sl_this.num_spans; unsigned span_idx = sl_this.start_span; @@ -460,11 +471,11 @@ namespace agg const span_data& sp = m_spans[span_idx++]; const T* covers = covers_by_index(sp.covers_id); - write_int16(data, int16(sp.x)); // X - data += sizeof(int16); + write_int32(data, sp.x); // X + data += sizeof(int32); - write_int16(data, int16(sp.len)); // span_len - data += sizeof(int16); + write_int32(data, sp.len); // span_len + data += sizeof(int32); if(sp.len < 0) { @@ -478,7 +489,7 @@ namespace agg } } while(--num_spans); - write_int16(size_ptr, int16(unsigned(data - size_ptr))); + write_int32(size_ptr, int32(unsigned(data - size_ptr))); } } @@ -502,9 +513,9 @@ namespace agg } private: - scanline_cell_storage<T> m_covers; - pod_deque<span_data, 10> m_spans; - pod_deque<scanline_data, 8> m_scanlines; + scanline_cell_storage<T> m_covers; + pod_bvector<span_data, 10> m_spans; + pod_bvector<scanline_data, 8> m_scanlines; span_data m_fake_span; scanline_data m_fake_scanline; int m_min_x; @@ -540,11 +551,12 @@ namespace agg public: struct span { - int16 x; - int16 len; // If negative, it's a solid span, "covers" is valid + int32 x; + int32 len; // If negative, it's a solid span, "covers" is valid const T* covers; }; + const_iterator() : m_ptr(0) {} const_iterator(const embedded_scanline& sl) : m_ptr(sl.m_ptr), m_dx(sl.m_dx) @@ -569,18 +581,20 @@ namespace agg } private: - int read_int16() + int read_int32() { - int16 val; + int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } void init_span() { - m_span.x = read_int16() + m_dx; - m_span.len = read_int16(); + m_span.x = read_int32() + m_dx; + m_span.len = read_int32(); m_span.covers = m_ptr; } @@ -604,11 +618,13 @@ namespace agg private: //----------------------------------------------------------------- - int read_int16() + int read_int32() { - int16 val; + int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } @@ -617,8 +633,8 @@ namespace agg void init(const int8u* ptr, int dx, int dy) { m_ptr = ptr; - m_y = read_int16() + dy; - m_num_spans = unsigned(read_int16()); + m_y = read_int32() + dy; + m_num_spans = unsigned(read_int32()); m_dx = dx; } @@ -651,8 +667,8 @@ namespace agg m_data(data), m_end(data + size), m_ptr(data), - m_dx(int(floor(dx + 0.5))), - m_dy(int(floor(dy + 0.5))), + m_dx(iround(dx)), + m_dy(iround(dy)), m_min_x(0x7FFFFFFF), m_min_y(0x7FFFFFFF), m_max_x(-0x7FFFFFFF), @@ -665,8 +681,8 @@ namespace agg m_data = data; m_end = data + size; m_ptr = data; - m_dx = int(floor(dx + 0.5)); - m_dy = int(floor(dy + 0.5)); + m_dx = iround(dx); + m_dy = iround(dy); m_min_x = 0x7FFFFFFF; m_min_y = 0x7FFFFFFF; m_max_x = -0x7FFFFFFF; @@ -675,20 +691,24 @@ namespace agg private: //-------------------------------------------------------------------- - int read_int16() + int read_int32() { - int16 val; + int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } //-------------------------------------------------------------------- - unsigned read_int16u() + unsigned read_int32u() { - int16u val; + int32u val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } @@ -700,13 +720,12 @@ namespace agg m_ptr = m_data; if(m_ptr < m_end) { - m_min_x = read_int16() + m_dx; - m_min_y = read_int16() + m_dy; - m_max_x = read_int16() + m_dx; - m_max_y = read_int16() + m_dy; - return true; + m_min_x = read_int32() + m_dx; + m_min_y = read_int32() + m_dy; + m_max_x = read_int32() + m_dx; + m_max_y = read_int32() + m_dy; } - return false; + return m_ptr < m_end; } //-------------------------------------------------------------------- @@ -723,14 +742,14 @@ namespace agg { if(m_ptr >= m_end) return false; - read_int16(); // Skip scanline size in bytes - int y = read_int16() + m_dy; - unsigned num_spans = read_int16(); + read_int32(); // Skip scanline size in bytes + int y = read_int32() + m_dy; + unsigned num_spans = read_int32(); do { - int x = read_int16() + m_dx; - int len = read_int16(); + int x = read_int32() + m_dx; + int len = read_int32(); if(len < 0) { @@ -763,9 +782,9 @@ namespace agg { if(m_ptr >= m_end) return false; - unsigned byte_size = read_int16u(); + unsigned byte_size = read_int32u(); sl.init(m_ptr, m_dx, m_dy); - m_ptr += byte_size - sizeof(int16); + m_ptr += byte_size - sizeof(int32); } while(sl.num_spans() == 0); return true; diff --git a/agg/inc/agg_scanline_storage_bin.h b/agg/inc/agg_scanline_storage_bin.h index 90fa50e4ee6d..b0a322edc817 100755 --- a/agg/inc/agg_scanline_storage_bin.h +++ b/agg/inc/agg_scanline_storage_bin.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -12,6 +12,15 @@ // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + #ifndef AGG_SCANLINE_STORAGE_BIN_INCLUDED #define AGG_SCANLINE_STORAGE_BIN_INCLUDED @@ -20,7 +29,6 @@ #include <stdlib.h> #include <math.h> #include "agg_array.h" -#include "agg_render_scanlines.h" namespace agg @@ -33,8 +41,8 @@ namespace agg //--------------------------------------------------------------- struct span_data { - int16 x; - int16 len; + int32 x; + int32 len; }; //--------------------------------------------------------------- @@ -55,6 +63,7 @@ namespace agg class const_iterator { public: + const_iterator() : m_storage(0) {} const_iterator(const embedded_scanline& sl) : m_storage(sl.m_storage), m_span_idx(sl.m_scanline.start_span) @@ -126,7 +135,7 @@ namespace agg // Renderer Interface //--------------------------------------------------------------- - void prepare(unsigned) + void prepare() { m_scanlines.remove_all(); m_spans.remove_all(); @@ -152,19 +161,19 @@ namespace agg typename Scanline::const_iterator span_iterator = sl.begin(); unsigned num_spans = sl_this.num_spans; - do + for(;;) { span_data sp; sp.x = span_iterator->x; - sp.len = (int16)abs((int)(span_iterator->len)); + sp.len = (int32)abs((int)(span_iterator->len)); m_spans.add(sp); int x1 = sp.x; int x2 = sp.x + sp.len - 1; if(x1 < m_min_x) m_min_x = x1; if(x2 > m_max_x) m_max_x = x2; + if(--num_spans == 0) break; ++span_iterator; } - while(--num_spans); m_scanlines.add(sl_this); } @@ -232,22 +241,24 @@ namespace agg unsigned byte_size() const { unsigned i; - unsigned size = sizeof(int16) * 4; // min_x, min_y, max_x, max_y + unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y for(i = 0; i < m_scanlines.size(); ++i) { - size += sizeof(int16) * 2 + // Y, num_spans - unsigned(m_scanlines[i].num_spans) * sizeof(int16) * 2; // X, span_len + size += sizeof(int32) * 2 + // Y, num_spans + unsigned(m_scanlines[i].num_spans) * sizeof(int32) * 2; // X, span_len } return size; } //--------------------------------------------------------------- - static void write_int16(int8u* dst, int16 val) + static void write_int32(int8u* dst, int32 val) { dst[0] = ((const int8u*)&val)[0]; dst[1] = ((const int8u*)&val)[1]; + dst[2] = ((const int8u*)&val)[2]; + dst[3] = ((const int8u*)&val)[3]; } @@ -256,24 +267,24 @@ namespace agg { unsigned i; - write_int16(data, int16u(min_x())); // min_x - data += sizeof(int16u); - write_int16(data, int16u(min_y())); // min_y - data += sizeof(int16u); - write_int16(data, int16u(max_x())); // max_x - data += sizeof(int16u); - write_int16(data, int16u(max_y())); // max_y - data += sizeof(int16u); + write_int32(data, min_x()); // min_x + data += sizeof(int32); + write_int32(data, min_y()); // min_y + data += sizeof(int32); + write_int32(data, max_x()); // max_x + data += sizeof(int32); + write_int32(data, max_y()); // max_y + data += sizeof(int32); for(i = 0; i < m_scanlines.size(); ++i) { const scanline_data& sl_this = m_scanlines[i]; - write_int16(data, int16(sl_this.y)); // Y - data += sizeof(int16); + write_int32(data, sl_this.y); // Y + data += sizeof(int32); - write_int16(data, int16(sl_this.num_spans)); // num_spans - data += sizeof(int16); + write_int32(data, sl_this.num_spans); // num_spans + data += sizeof(int32); unsigned num_spans = sl_this.num_spans; unsigned span_idx = sl_this.start_span; @@ -281,11 +292,11 @@ namespace agg { const span_data& sp = m_spans[span_idx++]; - write_int16(data, int16(sp.x)); // X - data += sizeof(int16); + write_int32(data, sp.x); // X + data += sizeof(int32); - write_int16(data, int16(sp.len)); // len - data += sizeof(int16); + write_int32(data, sp.len); // len + data += sizeof(int32); } while(--num_spans); } @@ -306,8 +317,8 @@ namespace agg private: - pod_deque<span_data, 10> m_spans; - pod_deque<scanline_data, 8> m_scanlines; + pod_bvector<span_data, 10> m_spans; + pod_bvector<scanline_data, 8> m_scanlines; span_data m_fake_span; scanline_data m_fake_scanline; int m_min_x; @@ -346,16 +357,17 @@ namespace agg public: struct span { - int16 x; - int16 len; + int32 x; + int32 len; }; + const_iterator() : m_ptr(0) {} const_iterator(const embedded_scanline& sl) : m_ptr(sl.m_ptr), m_dx(sl.m_dx) { - m_span.x = read_int16() + m_dx; - m_span.len = read_int16(); + m_span.x = read_int32() + m_dx; + m_span.len = read_int32(); } const span& operator*() const { return m_span; } @@ -363,16 +375,18 @@ namespace agg void operator ++ () { - m_span.x = read_int16() + m_dx; - m_span.len = read_int16(); + m_span.x = read_int32() + m_dx; + m_span.len = read_int32(); } private: - int read_int16() + int read_int32() { - int16 val; + int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } @@ -396,11 +410,13 @@ namespace agg private: //---------------------------------------------------------------- - int read_int16() + int read_int32() { - int16 val; + int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } @@ -409,8 +425,8 @@ namespace agg void init(const int8u* ptr, int dx, int dy) { m_ptr = ptr; - m_y = read_int16() + dy; - m_num_spans = unsigned(read_int16()); + m_y = read_int32() + dy; + m_num_spans = unsigned(read_int32()); m_dx = dx; } @@ -443,8 +459,8 @@ namespace agg m_data(data), m_end(data + size), m_ptr(data), - m_dx(int(floor(dx + 0.5))), - m_dy(int(floor(dy + 0.5))), + m_dx(iround(dx)), + m_dy(iround(dy)), m_min_x(0x7FFFFFFF), m_min_y(0x7FFFFFFF), m_max_x(-0x7FFFFFFF), @@ -457,8 +473,8 @@ namespace agg m_data = data; m_end = data + size; m_ptr = data; - m_dx = int(floor(dx + 0.5)); - m_dy = int(floor(dy + 0.5)); + m_dx = iround(dx); + m_dy = iround(dy); m_min_x = 0x7FFFFFFF; m_min_y = 0x7FFFFFFF; m_max_x = -0x7FFFFFFF; @@ -467,11 +483,13 @@ namespace agg private: //-------------------------------------------------------------------- - int read_int16() + int read_int32() { - int16 val; + int32 val; ((int8u*)&val)[0] = *m_ptr++; ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; return val; } @@ -483,13 +501,12 @@ namespace agg m_ptr = m_data; if(m_ptr < m_end) { - m_min_x = read_int16() + m_dx; - m_min_y = read_int16() + m_dy; - m_max_x = read_int16() + m_dx; - m_max_y = read_int16() + m_dy; - return true; + m_min_x = read_int32() + m_dx; + m_min_y = read_int32() + m_dy; + m_max_x = read_int32() + m_dx; + m_max_y = read_int32() + m_dy; } - return false; + return m_ptr < m_end; } //-------------------------------------------------------------------- @@ -506,13 +523,13 @@ namespace agg { if(m_ptr >= m_end) return false; - int y = read_int16() + m_dy; - unsigned num_spans = read_int16(); + int y = read_int32() + m_dy; + unsigned num_spans = read_int32(); do { - int x = read_int16() + m_dx; - int len = read_int16(); + int x = read_int32() + m_dx; + int len = read_int32(); if(len < 0) len = -len; sl.add_span(x, unsigned(len), cover_full); @@ -541,9 +558,9 @@ namespace agg // Jump to the next scanline //-------------------------- - read_int16(); // Y - int num_spans = read_int16(); // num_spans - m_ptr += num_spans * sizeof(int16) * 2; + read_int32(); // Y + int num_spans = read_int32(); // num_spans + m_ptr += num_spans * sizeof(int32) * 2; } while(sl.num_spans() == 0); return true; diff --git a/agg/inc/agg_scanline_u.h b/agg/inc/agg_scanline_u.h index 749c5b3c0054..561ae5ca89ac 100755 --- a/agg/inc/agg_scanline_u.h +++ b/agg/inc/agg_scanline_u.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -12,20 +12,27 @@ // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- #ifndef AGG_SCANLINE_U_INCLUDED #define AGG_SCANLINE_U_INCLUDED -#include <string.h> -#include "agg_basics.h" +#include "agg_array.h" namespace agg { - //==============================================================scanline_u + //=============================================================scanline_u8 // // Unpacked scanline container class // - // This class is used to transfer data from a scanline rastyerizer + // This class is used to transfer data from a scanline rasterizer // to the rendering buffer. It's organized very simple. The class stores // information of horizontal spans to render it into a pixel-map buffer. // Each span has staring X, length, and an array of bytes that determine the @@ -94,21 +101,23 @@ namespace agg // // The question is: why should we accumulate the whole scanline when we // could render just separate spans when they're ready? - // That's because using the scaline is generally faster. When is consists + // That's because using the scanline is generally faster. When is consists // of more than one span the conditions for the processor cash system // are better, because switching between two different areas of memory - // (that can be very large) occures less frequently. + // (that can be very large) occurs less frequently. //------------------------------------------------------------------------ - template<class T> class scanline_u + class scanline_u8 { public: - typedef T cover_type; + typedef scanline_u8 self_type; + typedef int8u cover_type; + typedef int16 coord_type; //-------------------------------------------------------------------- struct span { - int16 x; - int16 len; + coord_type x; + coord_type len; cover_type* covers; }; @@ -116,181 +125,360 @@ namespace agg typedef const span* const_iterator; //-------------------------------------------------------------------- - ~scanline_u(); - scanline_u(); + scanline_u8() : + m_min_x(0), + m_last_x(0x7FFFFFF0), + m_cur_span(0) + {} - void reset(int min_x, int max_x); - void add_cell(int x, unsigned cover); - void add_cells(int x, unsigned len, const T* covers); - void add_span(int x, unsigned len, unsigned cover); - void finalize(int y) { m_y = y; } - void reset_spans(); + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 2; + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_min_x = min_x; + m_cur_span = &m_spans[0]; + } + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + x -= m_min_x; + m_covers[x] = (cover_type)cover; + if(x == m_last_x+1) + { + m_cur_span->len++; + } + else + { + 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_last_x = x; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + x -= m_min_x; + memcpy(&m_covers[x], covers, len * sizeof(cover_type)); + if(x == m_last_x+1) + { + m_cur_span->len += (coord_type)len; + } + else + { + 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_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + x -= m_min_x; + memset(&m_covers[x], cover, len); + if(x == m_last_x+1) + { + m_cur_span->len += (coord_type)len; + } + else + { + 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_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + 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_u<T>(const scanline_u<T>&); - const scanline_u<T>& operator = (const scanline_u<T>&); + 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<cover_type> m_covers; + pod_array<span> m_spans; + span* m_cur_span; }; - //------------------------------------------------------------------------ - template<class T> scanline_u<T>::~scanline_u() - { - delete [] m_spans; - delete [] m_covers; - } - + //==========================================================scanline_u8_am + // + // The scanline container with alpha-masking + // //------------------------------------------------------------------------ - template<class T> scanline_u<T>::scanline_u() : - m_min_x(0), - m_max_len(0), - m_last_x(0x7FFFFFF0), - m_covers(0), - m_spans(0), - m_cur_span(0) + template<class AlphaMask> + class scanline_u8_am : public scanline_u8 { - } + public: + typedef scanline_u8 base_type; + typedef AlphaMask alpha_mask_type; + typedef base_type::cover_type cover_type; + typedef base_type::coord_type coord_type; + scanline_u8_am() : base_type(), m_alpha_mask(0) {} + scanline_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {} - //------------------------------------------------------------------------ - template<class T> void scanline_u<T>::reset(int min_x, int max_x) - { - unsigned max_len = max_x - min_x + 2; - if(max_len > m_max_len) + //-------------------------------------------------------------------- + void finalize(int span_y) { - delete [] m_spans; - delete [] m_covers; - m_covers = new cover_type [max_len]; - m_spans = new span [max_len]; - m_max_len = max_len; + base_type::finalize(span_y); + if(m_alpha_mask) + { + typename base_type::iterator span = base_type::begin(); + unsigned count = base_type::num_spans(); + do + { + m_alpha_mask->combine_hspan(span->x, + base_type::y(), + span->covers, + span->len); + ++span; + } + while(--count); + } } - m_last_x = 0x7FFFFFF0; - m_min_x = min_x; - m_cur_span = m_spans; - } + private: + const AlphaMask* m_alpha_mask; + }; - //------------------------------------------------------------------------ - template<class T> inline void scanline_u<T>::reset_spans() - { - m_last_x = 0x7FFFFFF0; - m_cur_span = m_spans; - } - //------------------------------------------------------------------------ - template<class T> inline void scanline_u<T>::add_cell(int x, unsigned cover) + + //===========================================================scanline32_u8 + class scanline32_u8 { - x -= m_min_x; - m_covers[x] = (unsigned char)cover; - if(x == m_last_x+1) + public: + typedef scanline32_u8 self_type; + typedef int8u cover_type; + typedef int32 coord_type; + + //-------------------------------------------------------------------- + struct span { - m_cur_span->len++; - } - else + span() {} + span(coord_type x_, coord_type len_, cover_type* covers_) : + x(x_), len(len_), covers(covers_) {} + + coord_type x; + coord_type len; + cover_type* covers; + }; + + typedef pod_bvector<span, 4> span_array_type; + + //-------------------------------------------------------------------- + class const_iterator { - m_cur_span++; - m_cur_span->x = (int16)(x + m_min_x); - m_cur_span->len = 1; - m_cur_span->covers = m_covers + x; - } - m_last_x = x; - } + public: + const_iterator(const span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + const span& operator*() const { return m_spans[m_span_idx]; } + const span* operator->() const { return &m_spans[m_span_idx]; } - //------------------------------------------------------------------------ - template<class T> void scanline_u<T>::add_cells(int x, unsigned len, const T* covers) - { - x -= m_min_x; - memcpy(m_covers + x, covers, len * sizeof(T)); - if(x == m_last_x+1) + void operator ++ () { ++m_span_idx; } + + private: + const span_array_type& m_spans; + unsigned m_span_idx; + }; + + //-------------------------------------------------------------------- + class iterator { - m_cur_span->len += (int16)len; + public: + iterator(span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + + span& operator*() { return m_spans[m_span_idx]; } + span* operator->() { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + span_array_type& m_spans; + unsigned m_span_idx; + }; + + + + //-------------------------------------------------------------------- + scanline32_u8() : + m_min_x(0), + m_last_x(0x7FFFFFF0), + m_covers() + {} + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 2; + if(max_len > m_covers.size()) + { + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_min_x = min_x; + m_spans.remove_all(); } - else + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) { - m_cur_span++; - m_cur_span->x = (int16)(x + m_min_x); - m_cur_span->len = (int16)len; - m_cur_span->covers = m_covers + x; + x -= m_min_x; + m_covers[x] = cover_type(cover); + if(x == m_last_x+1) + { + m_spans.last().len++; + } + else + { + m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x])); + } + m_last_x = x; } - m_last_x = x + len - 1; - } + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + x -= m_min_x; + 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_last_x = x + len - 1; + } - //------------------------------------------------------------------------ - template<class T> void scanline_u<T>::add_span(int x, unsigned len, unsigned cover) - { - x -= m_min_x; - memset(m_covers + x, cover, len); - if(x == m_last_x+1) + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + x -= m_min_x; + 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_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) { - m_cur_span->len += (int16)len; + m_y = y; } - else + + //-------------------------------------------------------------------- + void reset_spans() { - m_cur_span++; - m_cur_span->x = (int16)(x + m_min_x); - m_cur_span->len = (int16)len; - m_cur_span->covers = m_covers + x; + m_last_x = 0x7FFFFFF0; + m_spans.remove_all(); } - m_last_x = x + len - 1; - } + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return m_spans.size(); } + const_iterator begin() const { return const_iterator(m_spans); } + iterator begin() { return iterator(m_spans); } - //=============================================================scanline_u8 - typedef scanline_u<int8u> scanline_u8; + private: + scanline32_u8(const self_type&); + const self_type& operator = (const self_type&); + + private: + int m_min_x; + int m_last_x; + int m_y; + pod_array<cover_type> m_covers; + span_array_type m_spans; + }; - //============================================================scanline_u16 - typedef scanline_u<int16u> scanline_u16; - //============================================================scanline_u32 - typedef scanline_u<int32u> scanline_u32; - //=============================================================scanline_am + //========================================================scanline32_u8_am // // The scanline container with alpha-masking // //------------------------------------------------------------------------ - template<class AlphaMask, class CoverT> - class scanline_am : public scanline_u<CoverT> + template<class AlphaMask> + class scanline32_u8_am : public scanline32_u8 { public: - typedef AlphaMask alpha_mask_type; - typedef CoverT cover_type; - typedef scanline_u<CoverT> scanline_type; + typedef scanline_u8 base_type; + typedef AlphaMask alpha_mask_type; + typedef base_type::cover_type cover_type; + typedef base_type::coord_type coord_type; + - scanline_am() : scanline_type(), m_alpha_mask(0) {} - scanline_am(const AlphaMask& am) : scanline_type(), m_alpha_mask(&am) {} + scanline32_u8_am() : base_type(), m_alpha_mask(0) {} + scanline32_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {} //-------------------------------------------------------------------- void finalize(int span_y) { - scanline_u<CoverT>::finalize(span_y); + base_type::finalize(span_y); if(m_alpha_mask) { - typename scanline_type::iterator span = scanline_type::begin(); - unsigned count = scanline_type::num_spans(); + typename base_type::iterator span = base_type::begin(); + unsigned count = base_type::num_spans(); do { m_alpha_mask->combine_hspan(span->x, - scanline_type::y(), + base_type::y(), span->covers, span->len); ++span; @@ -304,18 +492,6 @@ namespace agg }; - //==========================================================scanline_u8_am - template<class AlphaMask> - class scanline_u8_am : public scanline_am<AlphaMask, int8u> - { - public: - typedef AlphaMask alpha_mask_type; - typedef int8u cover_type; - typedef scanline_am<alpha_mask_type, cover_type> self_type; - - scanline_u8_am() : self_type() {} - scanline_u8_am(const AlphaMask& am) : self_type(am) {} - }; } diff --git a/agg/inc/agg_shorten_path.h b/agg/inc/agg_shorten_path.h index 271d2a7ec572..574c06cc4834 100755 --- a/agg/inc/agg_shorten_path.h +++ b/agg/inc/agg_shorten_path.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_simul_eq.h b/agg/inc/agg_simul_eq.h index f52662e82926..86225ee7efb2 100755 --- a/agg/inc/agg_simul_eq.h +++ b/agg/inc/agg_simul_eq.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_span_allocator.h b/agg/inc/agg_span_allocator.h index d99c5b9d8936..811381a44fbe 100755 --- a/agg/inc/agg_span_allocator.h +++ b/agg/inc/agg_span_allocator.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -16,7 +16,7 @@ #ifndef AGG_SPAN_ALLOCATOR_INCLUDED #define AGG_SPAN_ALLOCATOR_INCLUDED -#include "agg_basics.h" +#include "agg_array.h" namespace agg { @@ -27,42 +27,24 @@ namespace agg typedef ColorT color_type; //-------------------------------------------------------------------- - ~span_allocator() + AGG_INLINE color_type* allocate(unsigned span_len) { - delete [] m_span; - } - - //-------------------------------------------------------------------- - span_allocator() : - m_max_span_len(0), - m_span(0) - { - } - - //-------------------------------------------------------------------- - color_type* allocate(unsigned max_span_len) - { - if(max_span_len > m_max_span_len) + if(span_len > m_span.size()) { - delete [] m_span; - m_span = new color_type[m_max_span_len = max_span_len]; + // 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. + //----------------------- + m_span.resize(((span_len + 255) >> 8) << 8); } - return m_span; + return &m_span[0]; } - //-------------------------------------------------------------------- - color_type* span() - { - return m_span; - } + AGG_INLINE color_type* span() { return &m_span[0]; } + AGG_INLINE unsigned max_span_len() const { return m_span.size(); } private: - //-------------------------------------------------------------------- - span_allocator(const span_allocator<ColorT>&); - const span_allocator<ColorT>& operator = (const span_allocator<ColorT>&); - - unsigned m_max_span_len; - color_type* m_span; + pod_array<color_type> m_span; }; } diff --git a/agg/inc/agg_span_converter.h b/agg/inc/agg_span_converter.h index 104cd7d8e73e..8f80c1919f7e 100755 --- a/agg/inc/agg_span_converter.h +++ b/agg/inc/agg_span_converter.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -21,31 +21,34 @@ namespace agg { //----------------------------------------------------------span_converter - template<class SpanGenerator, class Conv> class span_converter + template<class SpanGenerator, class SpanConverter> class span_converter { public: typedef typename SpanGenerator::color_type color_type; - span_converter(SpanGenerator& span_gen, Conv& conv) : - m_span_gen(&span_gen), m_conv(&conv) {} + 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(unsigned max_span_len) + void prepare() { - m_span_gen->prepare(max_span_len); + m_span_gen->prepare(); + m_span_cnv->prepare(); } //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { - color_type* span = m_span_gen->generate(x, y, len); - m_conv->convert(span, x, y, len); - return span; + m_span_gen->generate(span, x, y, len); + m_span_cnv->generate(span, x, y, len); } private: SpanGenerator* m_span_gen; - Conv* m_conv; + SpanConverter* m_span_cnv; }; } diff --git a/agg/inc/agg_span_generator.h b/agg/inc/agg_span_generator.h deleted file mode 100755 index 82b0ebef95f3..000000000000 --- a/agg/inc/agg_span_generator.h +++ /dev/null @@ -1,50 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_GENERATOR_INCLUDED -#define AGG_SPAN_GENERATOR_INCLUDED - -#include "agg_basics.h" -#include "agg_span_allocator.h" - -namespace agg -{ - - //==========================================================span_generator - template<class ColorT, class Allocator> class span_generator - { - public: - typedef ColorT color_type; - typedef Allocator alloc_type; - - //-------------------------------------------------------------------- - span_generator(alloc_type& alloc) : m_alloc(&alloc) {} - - //-------------------------------------------------------------------- - void allocator(alloc_type& alloc) { m_alloc = &alloc; } - alloc_type& allocator() { return *m_alloc; } - - //-------------------------------------------------------------------- - void prepare(unsigned max_span_len) - { - m_alloc->allocate(max_span_len); - } - - private: - alloc_type* m_alloc; - }; -} - -#endif diff --git a/agg/inc/agg_span_gouraud.h b/agg/inc/agg_span_gouraud.h index 76747899b5fc..87290b7395dd 100755 --- a/agg/inc/agg_span_gouraud.h +++ b/agg/inc/agg_span_gouraud.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -18,18 +18,15 @@ #include "agg_basics.h" #include "agg_math.h" -#include "agg_span_generator.h" namespace agg { //============================================================span_gouraud - template<class ColorT, class Allocator> - class span_gouraud : public span_generator<ColorT, Allocator> + template<class ColorT> class span_gouraud { public: typedef ColorT color_type; - typedef Allocator alloc_type; struct coord_type { @@ -39,23 +36,21 @@ namespace agg }; //-------------------------------------------------------------------- - span_gouraud(alloc_type& alloc) : - span_generator<color_type, alloc_type>(alloc), + span_gouraud() : m_vertex(0) { m_cmd[0] = path_cmd_stop; } //-------------------------------------------------------------------- - span_gouraud(alloc_type& alloc, - const color_type& c1, + span_gouraud(const color_type& c1, const color_type& c2, const color_type& c3, double x1, double y1, double x2, double y2, double x3, double y3, double d) : - span_generator<color_type, alloc_type>(alloc) + m_vertex(0) { colors(c1, c2, c3); triangle(x1, y1, x2, y2, x3, y3, d); @@ -132,8 +127,6 @@ namespace agg return m_cmd[m_vertex++]; } - - protected: //-------------------------------------------------------------------- void arrange_vertices(coord_type* coord) const @@ -164,7 +157,6 @@ namespace agg } } - private: //-------------------------------------------------------------------- coord_type m_coord[3]; diff --git a/agg/inc/agg_span_gouraud_gray.h b/agg/inc/agg_span_gouraud_gray.h index caf288919e93..94efc8380dce 100755 --- a/agg/inc/agg_span_gouraud_gray.h +++ b/agg/inc/agg_span_gouraud_gray.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -33,15 +33,18 @@ namespace agg { //=======================================================span_gouraud_gray - template<class ColorT, class Allocator = span_allocator<ColorT> > - class span_gouraud_gray : public span_gouraud<ColorT, Allocator> + template<class ColorT> class span_gouraud_gray : public span_gouraud<ColorT> { public: - typedef Allocator alloc_type; typedef ColorT color_type; typedef typename color_type::value_type value_type; - typedef span_gouraud<color_type, alloc_type> base_type; + typedef span_gouraud<color_type> base_type; typedef typename base_type::coord_type coord_type; + enum subpixel_scale_e + { + subpixel_shift = 4, + subpixel_scale = 1 << subpixel_shift + }; private: //-------------------------------------------------------------------- @@ -49,30 +52,31 @@ namespace agg { void init(const coord_type& c1, const coord_type& c2) { - m_x1 = c1.x; - m_y1 = c1.y; - m_dx = c2.x - c1.x; - m_dy = 1.0 / (c2.y - c1.y); + m_x1 = c1.x - 0.5; + m_y1 = c1.y - 0.5; + m_dx = c2.x - c1.x; + double dy = c2.y - c1.y; + m_1dy = (fabs(dy) < 1e-10) ? 1e10 : 1.0 / dy; m_v1 = c1.color.v; m_a1 = c1.color.a; m_dv = c2.color.v - m_v1; m_da = c2.color.a - m_a1; } - void calc(int y) + void calc(double y) { - double k = 0.0; - if(y > m_y1) k = (y - m_y1) * m_dy; - gray8 c; - m_v = m_v1 + int(m_dv * k); - m_a = m_a1 + int(m_da * k); - m_x = int(m_x1 + m_dx * k); + double k = (y - m_y1) * m_1dy; + if(k < 0.0) k = 0.0; + if(k > 1.0) k = 1.0; + m_v = m_v1 + iround(m_dv * k); + m_a = m_a1 + iround(m_da * k); + m_x = iround((m_x1 + m_dx * k) * subpixel_scale); } double m_x1; double m_y1; double m_dx; - double m_dy; + double m_1dy; int m_v1; int m_a1; int m_dv; @@ -85,33 +89,28 @@ namespace agg public: //-------------------------------------------------------------------- - span_gouraud_gray(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_gouraud_gray(alloc_type& alloc, - const color_type& c1, + span_gouraud_gray() {} + span_gouraud_gray(const color_type& c1, const color_type& c2, const color_type& c3, double x1, double y1, double x2, double y2, double x3, double y3, double d = 0) : - base_type(alloc, c1, c2, c3, x1, y1, x2, y2, x3, y3, d) + base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d) {} //-------------------------------------------------------------------- - void prepare(unsigned max_span_len) + void prepare() { - base_type::prepare(max_span_len); - coord_type coord[3]; - arrange_vertices(coord); + base_type::arrange_vertices(coord); m_y2 = int(coord[1].y); - m_swap = calc_point_location(coord[0].x, coord[0].y, - coord[2].x, coord[2].y, - coord[1].x, coord[1].y) < 0.0; + m_swap = cross_product(coord[0].x, coord[0].y, + coord[2].x, coord[2].y, + coord[1].x, coord[1].y) < 0.0; m_c1.init(coord[0], coord[2]); m_c2.init(coord[0], coord[1]); @@ -119,7 +118,7 @@ namespace agg } //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { m_c1.calc(y); const gray_calc* pc1 = &m_c1; @@ -127,47 +126,104 @@ namespace agg if(y < m_y2) { - m_c2.calc(y+1); + // Bottom part of the triangle (first subtriangle) + //------------------------- + m_c2.calc(y + m_c2.m_1dy); } else { - m_c3.calc(y); + // Upper part (second subtriangle) + //------------------------- + m_c3.calc(y - m_c3.m_1dy); pc2 = &m_c3; } if(m_swap) { + // It means that the triangle is oriented clockwise, + // so that we need to swap the controlling structures + //------------------------- const gray_calc* t = pc2; pc2 = pc1; pc1 = t; } - int nx = pc1->m_x; - unsigned nlen = pc2->m_x - pc1->m_x + 1; - - if(nlen < len) nlen = len; + // Get the horizontal length with subpixel accuracy + // and protect it from division by zero + //------------------------- + int nlen = abs(pc2->m_x - pc1->m_x); + if(nlen <= 0) nlen = 1; dda_line_interpolator<14> v(pc1->m_v, pc2->m_v, nlen); dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen); - if(nx < x) + // Calculate the starting point of the gradient with subpixel + // accuracy and correct (roll back) the interpolators. + // This operation will also clip the beginning of the span + // if necessary. + //------------------------- + int start = pc1->m_x - (x << subpixel_shift); + v -= start; + a -= start; + nlen += start; + + int vv, va; + enum lim_e { lim = color_type::base_mask }; + + // Beginning part of the span. Since we rolled back the + // interpolators, the color values may have overflow. + // So that, we render the beginning part with checking + // for overflow. It lasts until "start" is positive; + // typically it's 1-2 pixels, but may be more in some cases. + //------------------------- + while(len && start > 0) { - unsigned d = unsigned(x - nx); - v += d; - a += d; + vv = v.y(); + va = a.y(); + if(vv < 0) vv = 0; if(vv > lim) vv = lim; + if(va < 0) va = 0; if(va > lim) va = lim; + span->v = (value_type)vv; + span->a = (value_type)va; + v += subpixel_scale; + a += subpixel_scale; + nlen -= subpixel_scale; + start -= subpixel_scale; + ++span; + --len; } - color_type* span = base_type::allocator().span(); - do + // Middle part, no checking for overflow. + // Actual spans can be longer than the calculated length + // because of anti-aliasing, thus, the interpolators can + // overflow. But while "nlen" is positive we are safe. + //------------------------- + while(len && nlen > 0) { span->v = (value_type)v.y(); span->a = (value_type)a.y(); - ++v; - ++a; + v += subpixel_scale; + a += subpixel_scale; + nlen -= subpixel_scale; + ++span; + --len; + } + + // Ending part; checking for overflow. + // Typically it's 1-2 pixels, but may be more in some cases. + //------------------------- + while(len) + { + vv = v.y(); + va = a.y(); + if(vv < 0) vv = 0; if(vv > lim) vv = lim; + if(va < 0) va = 0; if(va > lim) va = lim; + span->v = (value_type)vv; + span->a = (value_type)va; + v += subpixel_scale; + a += subpixel_scale; ++span; + --len; } - while(--len); - return base_type::allocator().span(); } diff --git a/agg/inc/agg_span_gouraud_rgba.h b/agg/inc/agg_span_gouraud_rgba.h index 75679a9426c2..dbbe840f2fdd 100755 --- a/agg/inc/agg_span_gouraud_rgba.h +++ b/agg/inc/agg_span_gouraud_rgba.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -33,15 +33,18 @@ namespace agg { //=======================================================span_gouraud_rgba - template<class ColorT, class Allocator = span_allocator<ColorT> > - class span_gouraud_rgba : public span_gouraud<ColorT, Allocator> + template<class ColorT> class span_gouraud_rgba : public span_gouraud<ColorT> { public: - typedef Allocator alloc_type; typedef ColorT color_type; typedef typename ColorT::value_type value_type; - typedef span_gouraud<color_type, alloc_type> base_type; + typedef span_gouraud<color_type> base_type; typedef typename base_type::coord_type coord_type; + enum subpixel_scale_e + { + subpixel_shift = 4, + subpixel_scale = 1 << subpixel_shift + }; private: //-------------------------------------------------------------------- @@ -49,36 +52,37 @@ namespace agg { void init(const coord_type& c1, const coord_type& c2) { - m_x1 = c1.x; - m_y1 = c1.y; - m_dx = c2.x - c1.x; - m_dy = 1.0 / (c2.y - c1.y); - m_r1 = c1.color.r; - m_g1 = c1.color.g; - m_b1 = c1.color.b; - m_a1 = c1.color.a; - m_dr = c2.color.r - m_r1; - m_dg = c2.color.g - m_g1; - m_db = c2.color.b - m_b1; - m_da = c2.color.a - m_a1; + m_x1 = c1.x - 0.5; + m_y1 = c1.y - 0.5; + m_dx = c2.x - c1.x; + double dy = c2.y - c1.y; + m_1dy = (dy < 1e-5) ? 1e5 : 1.0 / dy; + m_r1 = c1.color.r; + m_g1 = c1.color.g; + m_b1 = c1.color.b; + m_a1 = c1.color.a; + m_dr = c2.color.r - m_r1; + m_dg = c2.color.g - m_g1; + m_db = c2.color.b - m_b1; + m_da = c2.color.a - m_a1; } - void calc(int y) + void calc(double y) { - double k = 0.0; - if(y > m_y1) k = (y - m_y1) * m_dy; - color_type rgba; - m_r = m_r1 + int(m_dr * k); - m_g = m_g1 + int(m_dg * k); - m_b = m_b1 + int(m_db * k); - m_a = m_a1 + int(m_da * k); - m_x = int(m_x1 + m_dx * k); + double k = (y - m_y1) * m_1dy; + if(k < 0.0) k = 0.0; + if(k > 1.0) k = 1.0; + m_r = m_r1 + iround(m_dr * k); + m_g = m_g1 + iround(m_dg * k); + m_b = m_b1 + iround(m_db * k); + m_a = m_a1 + iround(m_da * k); + m_x = iround((m_x1 + m_dx * k) * subpixel_scale); } double m_x1; double m_y1; double m_dx; - double m_dy; + double m_1dy; int m_r1; int m_g1; int m_b1; @@ -97,33 +101,28 @@ namespace agg public: //-------------------------------------------------------------------- - span_gouraud_rgba(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_gouraud_rgba(alloc_type& alloc, - const color_type& c1, + span_gouraud_rgba() {} + span_gouraud_rgba(const color_type& c1, const color_type& c2, const color_type& c3, double x1, double y1, double x2, double y2, double x3, double y3, double d = 0) : - base_type(alloc, c1, c2, c3, x1, y1, x2, y2, x3, y3, d) + base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d) {} //-------------------------------------------------------------------- - void prepare(unsigned max_span_len) + void prepare() { - base_type::prepare(max_span_len); - coord_type coord[3]; - arrange_vertices(coord); + base_type::arrange_vertices(coord); m_y2 = int(coord[1].y); - m_swap = calc_point_location(coord[0].x, coord[0].y, - coord[2].x, coord[2].y, - coord[1].x, coord[1].y) < 0.0; + m_swap = cross_product(coord[0].x, coord[0].y, + coord[2].x, coord[2].y, + coord[1].x, coord[1].y) < 0.0; m_rgba1.init(coord[0], coord[2]); m_rgba2.init(coord[0], coord[1]); @@ -131,65 +130,137 @@ namespace agg } //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { - m_rgba1.calc(y); + m_rgba1.calc(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y); const rgba_calc* pc1 = &m_rgba1; const rgba_calc* pc2 = &m_rgba2; - if(y < m_y2) + if(y <= m_y2) { - m_rgba2.calc(y+1); + // Bottom part of the triangle (first subtriangle) + //------------------------- + m_rgba2.calc(y + m_rgba2.m_1dy); } else { - m_rgba3.calc(y); + // Upper part (second subtriangle) + m_rgba3.calc(y - m_rgba3.m_1dy); + //------------------------- pc2 = &m_rgba3; } if(m_swap) { + // It means that the triangle is oriented clockwise, + // so that we need to swap the controlling structures + //------------------------- const rgba_calc* t = pc2; pc2 = pc1; pc1 = t; } - int nx = pc1->m_x; - unsigned nlen = pc2->m_x - pc1->m_x + 1; - - if(nlen < len) nlen = len; + // Get the horizontal length with subpixel accuracy + // and protect it from division by zero + //------------------------- + int nlen = abs(pc2->m_x - pc1->m_x); + if(nlen <= 0) nlen = 1; dda_line_interpolator<14> r(pc1->m_r, pc2->m_r, nlen); dda_line_interpolator<14> g(pc1->m_g, pc2->m_g, nlen); dda_line_interpolator<14> b(pc1->m_b, pc2->m_b, nlen); dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen); - if(nx < x) + // Calculate the starting point of the gradient with subpixel + // accuracy and correct (roll back) the interpolators. + // This operation will also clip the beginning of the span + // if necessary. + //------------------------- + int start = pc1->m_x - (x << subpixel_shift); + r -= start; + g -= start; + b -= start; + a -= start; + nlen += start; + + int vr, vg, vb, va; + enum lim_e { lim = color_type::base_mask }; + + // Beginning part of the span. Since we rolled back the + // interpolators, the color values may have overflow. + // So that, we render the beginning part with checking + // for overflow. It lasts until "start" is positive; + // typically it's 1-2 pixels, but may be more in some cases. + //------------------------- + while(len && start > 0) { - unsigned d = unsigned(x - nx); - r += d; - g += d; - b += d; - a += d; + vr = r.y(); + vg = g.y(); + vb = b.y(); + va = a.y(); + if(vr < 0) vr = 0; if(vr > lim) vr = lim; + if(vg < 0) vg = 0; if(vg > lim) vg = lim; + if(vb < 0) vb = 0; if(vb > lim) vb = lim; + if(va < 0) va = 0; if(va > lim) va = lim; + span->r = (value_type)vr; + span->g = (value_type)vg; + span->b = (value_type)vb; + span->a = (value_type)va; + r += subpixel_scale; + g += subpixel_scale; + b += subpixel_scale; + a += subpixel_scale; + nlen -= subpixel_scale; + start -= subpixel_scale; + ++span; + --len; } - color_type* span = base_type::allocator().span(); - do + // Middle part, no checking for overflow. + // Actual spans can be longer than the calculated length + // because of anti-aliasing, thus, the interpolators can + // overflow. But while "nlen" is positive we are safe. + //------------------------- + while(len && nlen > 0) { span->r = (value_type)r.y(); span->g = (value_type)g.y(); span->b = (value_type)b.y(); span->a = (value_type)a.y(); - ++r; - ++g; - ++b; - ++a; + r += subpixel_scale; + g += subpixel_scale; + b += subpixel_scale; + a += subpixel_scale; + nlen -= subpixel_scale; ++span; + --len; } - while(--len); - return base_type::allocator().span(); - } + // Ending part; checking for overflow. + // Typically it's 1-2 pixels, but may be more in some cases. + //------------------------- + while(len) + { + vr = r.y(); + vg = g.y(); + vb = b.y(); + va = a.y(); + if(vr < 0) vr = 0; if(vr > lim) vr = lim; + if(vg < 0) vg = 0; if(vg > lim) vg = lim; + if(vb < 0) vb = 0; if(vb > lim) vb = lim; + if(va < 0) va = 0; if(va > lim) va = lim; + span->r = (value_type)vr; + span->g = (value_type)vg; + span->b = (value_type)vb; + span->a = (value_type)va; + r += subpixel_scale; + g += subpixel_scale; + b += subpixel_scale; + a += subpixel_scale; + ++span; + --len; + } + } private: bool m_swap; diff --git a/agg/inc/agg_span_gradient.h b/agg/inc/agg_span_gradient.h index 6bac1c652a84..fa6e4929855d 100755 --- a/agg/inc/agg_span_gradient.h +++ b/agg/inc/agg_span_gradient.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -20,7 +20,6 @@ #include <stdlib.h> #include <string.h> #include "agg_basics.h" -#include "agg_span_generator.h" #include "agg_math.h" #include "agg_array.h" @@ -28,11 +27,11 @@ namespace agg { - enum + enum gradient_subpixel_scale_e { gradient_subpixel_shift = 4, //-----gradient_subpixel_shift - gradient_subpixel_size = 1 << gradient_subpixel_shift, //-----gradient_subpixel_size - gradient_subpixel_mask = gradient_subpixel_size - 1 //-----gradient_subpixel_mask + gradient_subpixel_scale = 1 << gradient_subpixel_shift, //-----gradient_subpixel_scale + gradient_subpixel_mask = gradient_subpixel_scale - 1 //-----gradient_subpixel_mask }; @@ -41,57 +40,54 @@ namespace agg template<class ColorT, class Interpolator, class GradientF, - class ColorF, - class Allocator = span_allocator<ColorT> > - class span_gradient : public span_generator<ColorT, Allocator> + class ColorF> + class span_gradient { public: typedef Interpolator interpolator_type; - typedef Allocator alloc_type; typedef ColorT color_type; - typedef span_generator<color_type, alloc_type> base_type; - enum + enum downscale_shift_e { downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift }; //-------------------------------------------------------------------- - span_gradient(alloc_type& alloc) : base_type(alloc) {} + span_gradient() {} //-------------------------------------------------------------------- - span_gradient(alloc_type& alloc, - interpolator_type& inter, - const GradientF& gradient_function_, - const ColorF& color_function_, - double d1_, double d2_) : - base_type(alloc), + span_gradient(interpolator_type& inter, + const GradientF& gradient_function, + const ColorF& color_function, + double d1, double d2) : m_interpolator(&inter), - m_gradient_function(&gradient_function_), - m_color_function(&color_function_), - m_d1(int(d1_ * gradient_subpixel_size)), - m_d2(int(d2_ * gradient_subpixel_size)) + m_gradient_function(&gradient_function), + m_color_function(&color_function), + m_d1(iround(d1 * gradient_subpixel_scale)), + m_d2(iround(d2 * gradient_subpixel_scale)) {} //-------------------------------------------------------------------- interpolator_type& interpolator() { return *m_interpolator; } const GradientF& gradient_function() const { return *m_gradient_function; } const ColorF& color_function() const { return *m_color_function; } - double d1() const { return double(m_d1) / gradient_subpixel_size; } - double d2() const { return double(m_d2) / gradient_subpixel_size; } + double d1() const { return double(m_d1) / gradient_subpixel_scale; } + double d2() const { return double(m_d2) / gradient_subpixel_scale; } //-------------------------------------------------------------------- void interpolator(interpolator_type& i) { m_interpolator = &i; } void gradient_function(const GradientF& gf) { m_gradient_function = &gf; } void color_function(const ColorF& cf) { m_color_function = &cf; } - void d1(double v) { m_d1 = int(v * gradient_subpixel_size); } - void d2(double v) { m_d2 = int(v * gradient_subpixel_size); } + void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); } + void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); } //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) { - color_type* span = base_type::allocator().span(); int dd = m_d2 - m_d1; if(dd < 1) dd = 1; m_interpolator->begin(x+0.5, y+0.5, len); @@ -99,7 +95,7 @@ namespace agg { m_interpolator->coordinates(&x, &y); int d = m_gradient_function->calculate(x >> downscale_shift, - y >> downscale_shift, dd); + y >> downscale_shift, m_d2); d = ((d - m_d1) * (int)m_color_function->size()) / dd; if(d < 0) d = 0; if(d >= (int)m_color_function->size()) d = m_color_function->size() - 1; @@ -107,7 +103,6 @@ namespace agg ++(*m_interpolator); } while(--len); - return base_type::allocator().span(); } private: @@ -151,6 +146,10 @@ namespace agg }; + + + + //==========================================================gradient_circle class gradient_circle { @@ -173,36 +172,34 @@ namespace agg } }; - //========================================================gradient_radial_d class gradient_radial_d { public: static AGG_INLINE int calculate(int x, int y, int) { - return int(sqrt(double(x)*double(x) + double(y)*double(y))); + return uround(sqrt(double(x)*double(x) + double(y)*double(y))); } }; - //====================================================gradient_radial_focus class gradient_radial_focus { public: //--------------------------------------------------------------------- gradient_radial_focus() : - m_radius(100 * gradient_subpixel_size), - 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 (int(r * gradient_subpixel_size)), - m_focus_x(int(fx * gradient_subpixel_size)), - m_focus_y(int(fy * gradient_subpixel_size)) + m_r (iround(r * gradient_subpixel_scale)), + m_fx(iround(fx * gradient_subpixel_scale)), + m_fy(iround(fy * gradient_subpixel_scale)) { update_values(); } @@ -210,111 +207,62 @@ namespace agg //--------------------------------------------------------------------- void init(double r, double fx, double fy) { - m_radius = int(r * gradient_subpixel_size); - m_focus_x = int(fx * gradient_subpixel_size); - m_focus_y = int(fy * gradient_subpixel_size); + 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_size; } - double focus_x() const { return double(m_focus_x) / gradient_subpixel_size; } - double focus_y() const { return double(m_focus_y) / gradient_subpixel_size; } + 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 d) const + 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 == int(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 int(sqrt(cur_to_focus / int_to_focus) * d); + 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 quadractic equation - //------------------------------- - m_radius2 = double(m_radius) * double(m_radius); - - double dist = sqrt(double(m_focus_x) * double(m_focus_x) + - double(m_focus_y) * double(m_focus_y)); - - // Test if distance from focus to center is greater than the radius - // For the sake of assurance factor restrict the point to be - // no further than 99% of the radius. - //------------------------------- - double r = m_radius * 0.99; - if(dist > r) + // Calculate the invariant values. In case the focal center + // lies exactly on the gradient circle the divisor degenerates + // into zero. In this case we just move the focal center by + // one subpixel unit possibly in the direction to the origin (0,0) + // and calculate the values again. + //------------------------- + m_r2 = double(m_r) * double(m_r); + m_fx2 = double(m_fx) * double(m_fx); + m_fy2 = double(m_fy) * double(m_fy); + double d = (m_r2 - (m_fx2 + m_fy2)); + if(d == 0) { - // clamp focus to radius - // x = r cos theta, y = r sin theta - //------------------------ - double a = atan2(double(m_focus_y), double(m_focus_x)); - m_focus_x = int(r * cos(a)); - m_focus_y = int(r * sin(a)); + if(m_fx) { if(m_fx < 0) ++m_fx; else --m_fx; } + if(m_fy) { if(m_fy < 0) ++m_fy; else --m_fy; } + m_fx2 = double(m_fx) * double(m_fx); + m_fy2 = double(m_fy) * double(m_fy); + d = (m_r2 - (m_fx2 + m_fy2)); } - - // 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 { @@ -330,7 +278,6 @@ namespace agg static int calculate(int, int y, int) { return y; } }; - //========================================================gradient_diamond class gradient_diamond { @@ -343,7 +290,6 @@ namespace agg } }; - //=============================================================gradient_xy class gradient_xy { @@ -354,7 +300,6 @@ namespace agg } }; - //========================================================gradient_sqrt_xy class gradient_sqrt_xy { @@ -365,18 +310,16 @@ namespace agg } }; - //==========================================================gradient_conic class gradient_conic { public: static AGG_INLINE int calculate(int x, int y, int d) { - return int(fabs(atan2(double(y), double(x))) * double(d) / pi); + return uround(fabs(atan2(double(y), double(x))) * double(d) / pi); } }; - //=================================================gradient_repeat_adaptor template<class GradientF> class gradient_repeat_adaptor { @@ -395,7 +338,6 @@ namespace agg const GradientF* m_gradient; }; - //================================================gradient_reflect_adaptor template<class GradientF> class gradient_reflect_adaptor { diff --git a/agg/inc/agg_span_gradient_alpha.h b/agg/inc/agg_span_gradient_alpha.h index b1444ed8c4bc..a53d66903b1f 100755 --- a/agg/inc/agg_span_gradient_alpha.h +++ b/agg/inc/agg_span_gradient_alpha.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -32,7 +32,7 @@ namespace agg typedef ColorT color_type; typedef typename color_type::value_type alpha_type; - enum + enum downscale_shift_e { downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift }; @@ -49,26 +49,29 @@ namespace agg m_interpolator(&inter), m_gradient_function(&gradient_function), m_alpha_function(&alpha_function), - m_d1(int(d1 * gradient_subpixel_size)), - m_d2(int(d2 * gradient_subpixel_size)) + m_d1(iround(d1 * gradient_subpixel_scale)), + m_d2(iround(d2 * gradient_subpixel_scale)) {} //-------------------------------------------------------------------- interpolator_type& interpolator() { return *m_interpolator; } const GradientF& gradient_function() const { return *m_gradient_function; } const AlphaF& alpha_function() const { return *m_alpha_function; } - double d1() const { return double(m_d1) / gradient_subpixel_size; } - double d2() const { return double(m_d2) / gradient_subpixel_size; } + double d1() const { return double(m_d1) / gradient_subpixel_scale; } + double d2() const { return double(m_d2) / gradient_subpixel_scale; } //-------------------------------------------------------------------- void interpolator(interpolator_type& i) { m_interpolator = &i; } void gradient_function(const GradientF& gf) { m_gradient_function = &gf; } void alpha_function(const AlphaF& af) { m_alpha_function = ⁡ } - void d1(double v) { m_d1 = int(v * gradient_subpixel_size); } - void d2(double v) { m_d2 = int(v * gradient_subpixel_size); } + void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); } + void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); } //-------------------------------------------------------------------- - void convert(color_type* span, int x, int y, unsigned len) + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) { int dd = m_d2 - m_d1; if(dd < 1) dd = 1; @@ -77,7 +80,7 @@ namespace agg { m_interpolator->coordinates(&x, &y); int d = m_gradient_function->calculate(x >> downscale_shift, - y >> downscale_shift, dd); + y >> downscale_shift, m_d2); d = ((d - m_d1) * (int)m_alpha_function->size()) / dd; if(d < 0) d = 0; if(d >= (int)m_alpha_function->size()) d = m_alpha_function->size() - 1; diff --git a/agg/inc/agg_span_image_filter.h b/agg/inc/agg_span_image_filter.h index 34163bb29f24..f35c56989258 100755 --- a/agg/inc/agg_span_image_filter.h +++ b/agg/inc/agg_span_image_filter.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -21,81 +21,63 @@ #include "agg_basics.h" #include "agg_image_filters.h" -#include "agg_rendering_buffer.h" -#include "agg_span_generator.h" - +#include "agg_span_interpolator_linear.h" namespace agg { - //--------------------------------------------------span_image_filter - template<class ColorT, class Interpolator, class Allocator> - class span_image_filter : public span_generator<ColorT, Allocator> + //-------------------------------------------------------span_image_filter + template<class Source, class Interpolator> class span_image_filter { public: - typedef ColorT color_type; - typedef Allocator alloc_type; + typedef Source source_type; typedef Interpolator interpolator_type; - typedef span_generator<color_type, alloc_type> base_type; - - //---------------------------------------------------------------- - span_image_filter(alloc_type& alloc) : - span_generator<color_type, alloc_type>(alloc) - {} - //---------------------------------------------------------------- - span_image_filter(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& interpolator_, - const image_filter_lut* filter_) : - span_generator<color_type, alloc_type>(alloc), + //-------------------------------------------------------------------- + span_image_filter() {} + span_image_filter(source_type& src, + interpolator_type& interpolator, + const image_filter_lut* filter) : m_src(&src), - m_back_color(back_color), - m_interpolator(&interpolator_), - m_filter(filter_), + m_interpolator(&interpolator), + m_filter(filter), m_dx_dbl(0.5), m_dy_dbl(0.5), - m_dx_int(image_subpixel_size / 2), - m_dy_int(image_subpixel_size / 2) + m_dx_int(image_subpixel_scale / 2), + m_dy_int(image_subpixel_scale / 2) {} + void attach(source_type& v) { m_src = &v; } - //---------------------------------------------------------------- - const rendering_buffer& source_image() const { return *m_src; } - const color_type& background_color() const { return m_back_color; } - const image_filter_lut& filter() const { return *m_filter; } - int filter_dx_int() const { return m_dx_int; } - int filter_dy_int() const { return m_dy_int; } - double filter_dx_dbl() const { return m_dx_dbl; } - double filter_dy_dbl() const { return m_dy_dbl; } - - //---------------------------------------------------------------- - void source_image(const rendering_buffer& v) { m_src = &v; } - void background_color(const color_type& v) { m_back_color = v; } - void interpolator(interpolator_type& v) { m_interpolator = &v; } - void filter(const image_filter_lut& v) { m_filter = &v; } + //-------------------------------------------------------------------- + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + const image_filter_lut& filter() const { return *m_filter; } + int filter_dx_int() const { return m_dx_int; } + int filter_dy_int() const { return m_dy_int; } + double filter_dx_dbl() const { return m_dx_dbl; } + double filter_dy_dbl() const { return m_dy_dbl; } + + //-------------------------------------------------------------------- + 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) { m_dx_dbl = dx; m_dy_dbl = dy; - m_dx_int = int(dx * image_subpixel_size); - m_dy_int = int(dy * image_subpixel_size); + m_dx_int = iround(dx * image_subpixel_scale); + m_dy_int = iround(dy * image_subpixel_scale); } void filter_offset(double d) { filter_offset(d, d); } - //---------------------------------------------------------------- + //-------------------------------------------------------------------- interpolator_type& interpolator() { return *m_interpolator; } //-------------------------------------------------------------------- - void prepare(unsigned max_span_len) - { - base_type::prepare(max_span_len); - } + void prepare() {} - //---------------------------------------------------------------- + //-------------------------------------------------------------------- private: - const rendering_buffer* m_src; - color_type m_back_color; + source_type* m_src; interpolator_type* m_interpolator; const image_filter_lut* m_filter; double m_dx_dbl; @@ -105,6 +87,160 @@ namespace agg }; + + + //==============================================span_image_resample_affine + template<class Source> + class span_image_resample_affine : + public span_image_filter<Source, span_interpolator_linear<trans_affine> > + { + public: + typedef Source source_type; + typedef span_interpolator_linear<trans_affine> interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + + //-------------------------------------------------------------------- + span_image_resample_affine() : + m_scale_limit(200.0), + m_blur_x(1.0), + m_blur_y(1.0) + {} + + //-------------------------------------------------------------------- + span_image_resample_affine(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, &filter), + m_scale_limit(200.0), + m_blur_x(1.0), + m_blur_y(1.0) + {} + + + //-------------------------------------------------------------------- + int scale_limit() const { return uround(m_scale_limit); } + void scale_limit(int v) { m_scale_limit = v; } + + //-------------------------------------------------------------------- + double blur_x() const { return m_blur_x; } + double blur_y() const { return m_blur_y; } + void blur_x(double v) { m_blur_x = v; } + void blur_y(double v) { m_blur_y = v; } + void blur(double v) { m_blur_x = m_blur_y = v; } + + //-------------------------------------------------------------------- + void prepare() + { + double scale_x; + double scale_y; + + base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_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) scale_x = 1; + if(scale_y < 1) scale_y = 1; + + if(scale_x > m_scale_limit) scale_x = m_scale_limit; + if(scale_y > m_scale_limit) scale_y = m_scale_limit; + + scale_x *= m_blur_x; + scale_y *= m_blur_y; + + if(scale_x < 1) scale_x = 1; + if(scale_y < 1) scale_y = 1; + + m_rx = uround( scale_x * double(image_subpixel_scale)); + m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale)); + + m_ry = uround( scale_y * double(image_subpixel_scale)); + m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale)); + } + + protected: + int m_rx; + int m_ry; + int m_rx_inv; + int m_ry_inv; + + private: + double m_scale_limit; + double m_blur_x; + double m_blur_y; + }; + + + + //=====================================================span_image_resample + template<class Source, class Interpolator> + class span_image_resample : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + + //-------------------------------------------------------------------- + span_image_resample() : + m_scale_limit(20), + m_blur_x(image_subpixel_scale), + m_blur_y(image_subpixel_scale) + {} + + //-------------------------------------------------------------------- + span_image_resample(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, &filter), + m_scale_limit(20), + m_blur_x(image_subpixel_scale), + m_blur_y(image_subpixel_scale) + {} + + //-------------------------------------------------------------------- + int scale_limit() const { return m_scale_limit; } + void scale_limit(int v) { m_scale_limit = v; } + + //-------------------------------------------------------------------- + double blur_x() const { return double(m_blur_x) / double(image_subpixel_scale); } + double blur_y() const { return double(m_blur_y) / double(image_subpixel_scale); } + void blur_x(double v) { m_blur_x = uround(v * double(image_subpixel_scale)); } + void blur_y(double v) { m_blur_y = uround(v * double(image_subpixel_scale)); } + void blur(double v) { m_blur_x = + 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; + }; + + + + } #endif diff --git a/agg/inc/agg_span_image_filter_gray.h b/agg/inc/agg_span_image_filter_gray.h index 3f7ae6fcfa72..89432dbb8dd8 100755 --- a/agg/inc/agg_span_image_filter_gray.h +++ b/agg/inc/agg_span_image_filter_gray.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -20,7 +20,6 @@ // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- - #ifndef AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED #define AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED @@ -32,132 +31,168 @@ namespace agg { - //==============================================span_image_filter_gray_nn - template<class ColorT, - class Interpolator, - class Allocator = span_allocator<ColorT> > + template<class Source, class Interpolator> class span_image_filter_gray_nn : - public span_image_filter<ColorT, Interpolator, Allocator> + public span_image_filter<Source, Interpolator> { public: - typedef ColorT color_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; + typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- - span_image_filter_gray_nn(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_gray_nn(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, + span_image_filter_gray_nn() {} + span_image_filter_gray_nn(source_type& src, interpolator_type& inter) : - base_type(alloc, src, back_color, inter, 0) + base_type(src, inter, 0) {} //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); + do + { + base_type::interpolator().coordinates(&x, &y); + span->v = *(const value_type*) + base_type::source().span(x >> image_subpixel_shift, + y >> image_subpixel_shift, + 1); + span->a = base_mask; + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; - calc_type fg; - calc_type src_alpha; - color_type* span = base_type::allocator().span(); - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; + //=========================================span_image_filter_gray_bilinear + template<class Source, class Interpolator> + class span_image_filter_gray_bilinear : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_gray_bilinear() {} + span_image_filter_gray_bilinear(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + calc_type fg; + const value_type *fg_ptr; do { - base_type::interpolator().coordinates(&x, &y); + int x_hr; + int y_hr; - x >>= image_subpixel_shift; - y >>= image_subpixel_shift; + base_type::interpolator().coordinates(&x_hr, &y_hr); - if(x >= 0 && y >= 0 && - x <= maxx && y <= maxy) - { - fg = *((const value_type*)base_type::source_image().row(y) + x); - src_alpha = base_mask; - } - else - { - fg = base_type::background_color().v; - src_alpha = base_type::background_color().a; - } + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); - span->v = (value_type)fg; - span->a = (value_type)src_alpha; + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + fg += *fg_ptr * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); + + fg_ptr = (const value_type*)base_type::source().next_x(); + fg += *fg_ptr * x_hr * (image_subpixel_scale - y_hr); + + fg_ptr = (const value_type*)base_type::source().next_y(); + fg += *fg_ptr * (image_subpixel_scale - x_hr) * y_hr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + fg += *fg_ptr * x_hr * y_hr; + + span->v = value_type(fg >> (image_subpixel_shift * 2)); + span->a = base_mask; ++span; ++base_type::interpolator(); } while(--len); - - return base_type::allocator().span(); } }; - - - //========================================span_image_filter_gray_bilinear - template<class ColorT, - class Interpolator, - class Allocator = span_allocator<ColorT> > - class span_image_filter_gray_bilinear : - public span_image_filter<ColorT, Interpolator, Allocator> + //====================================span_image_filter_gray_bilinear_clip + template<class Source, class Interpolator> + class span_image_filter_gray_bilinear_clip : + public span_image_filter<Source, Interpolator> { public: - typedef ColorT color_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; + typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- - span_image_filter_gray_bilinear(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_gray_bilinear(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter) : - base_type(alloc, src, back_color, inter, 0) + span_image_filter_gray_bilinear_clip() {} + span_image_filter_gray_bilinear_clip(source_type& src, + const color_type& back_color, + interpolator_type& inter) : + base_type(src, inter, 0), + m_back_color(back_color) {} + const color_type& background_color() const { return m_back_color; } + void background_color(const color_type& v) { m_back_color = v; } //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg; calc_type src_alpha; - value_type back_v = base_type::background_color().v; - value_type back_a = base_type::background_color().a; + value_type back_v = m_back_color.v; + value_type back_a = m_back_color.a; const value_type *fg_ptr; - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; + int maxx = base_type::source().width() - 1; + int maxy = base_type::source().height() - 1; do { @@ -175,18 +210,19 @@ namespace agg if(x_lr >= 0 && y_lr >= 0 && x_lr < maxx && y_lr < maxy) { - fg = image_subpixel_size * image_subpixel_size / 2; + fg = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr; + fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; - fg += *fg_ptr++ * (image_subpixel_size - x_hr) * (image_subpixel_size - y_hr); - fg += *fg_ptr++ * (image_subpixel_size - y_hr) * x_hr; + fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); + fg += *fg_ptr++ * (image_subpixel_scale - y_hr) * x_hr; - fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - 2); + ++y_lr; + fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; - fg += *fg_ptr++ * (image_subpixel_size - x_hr) * y_hr; + fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * y_hr; fg += *fg_ptr++ * x_hr * y_hr; fg >>= image_subpixel_shift * 2; @@ -204,17 +240,18 @@ namespace agg else { fg = - src_alpha = image_subpixel_size * image_subpixel_size / 2; + src_alpha = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; - weight = (image_subpixel_size - x_hr) * - (image_subpixel_size - y_hr); + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { - fg += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr); + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); src_alpha += weight * base_mask; } else @@ -225,11 +262,12 @@ namespace agg x_lr++; - weight = x_hr * (image_subpixel_size - y_hr); + weight = x_hr * (image_subpixel_scale - y_hr); if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { - fg += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr); + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); src_alpha += weight * base_mask; } else @@ -241,11 +279,12 @@ namespace agg x_lr--; y_lr++; - weight = (image_subpixel_size - x_hr) * y_hr; + weight = (image_subpixel_scale - x_hr) * y_hr; if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { - fg += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr); + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); src_alpha += weight * base_mask; } else @@ -260,7 +299,8 @@ namespace agg if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { - fg += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr); + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); src_alpha += weight * base_mask; } else @@ -280,69 +320,52 @@ namespace agg ++base_type::interpolator(); } while(--len); - - return base_type::allocator().span(); } + private: + color_type m_back_color; }; - - - - - //========================================span_image_filter_gray_2x2 - template<class ColorT, - class Interpolator, - class Allocator = span_allocator<ColorT> > + //==============================================span_image_filter_gray_2x2 + template<class Source, class Interpolator> class span_image_filter_gray_2x2 : - public span_image_filter<ColorT, Interpolator, Allocator> + public span_image_filter<Source, Interpolator> { public: - typedef ColorT color_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; + typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- - span_image_filter_gray_2x2(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_gray_2x2(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, + span_image_filter_gray_2x2() {} + span_image_filter_gray_2x2(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : - base_type(alloc, src, back_color, inter, &filter) + base_type(src, inter, &filter) {} + //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); + calc_type fg; - calc_type src_alpha; - value_type back_v = base_type::background_color().v; - value_type back_a = base_type::background_color().a; const value_type *fg_ptr; - - color_type* span = base_type::allocator().span(); const int16* weight_array = base_type::filter().weight_array() + ((base_type::filter().diameter()/2 - 1) << image_subpixel_shift); - - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - do { int x_hr; @@ -356,214 +379,92 @@ namespace agg int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; - if(x_lr >= 0 && y_lr >= 0 && - x_lr < maxx && y_lr < maxy) - { - fg = image_filter_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr; - - fg += *fg_ptr++ * ((weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift); - fg += *fg_ptr++ * ((weight_array[x_hr] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift); - - fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - 2); - - fg += *fg_ptr++ * ((weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift); - fg += *fg_ptr++ * ((weight_array[x_hr] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift); - - fg >>= image_filter_shift; - if(fg > base_mask) fg = base_mask; - src_alpha = base_mask; - } - else - { - unsigned weight; - if(x_lr < -1 || y_lr < -1 || - x_lr > maxx || y_lr > maxy) - { - fg = back_v; - src_alpha = back_a; - } - else - { - fg = src_alpha = image_filter_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr); - src_alpha += weight * base_mask; - } - else - { - fg += back_v * weight; - src_alpha += back_a * weight; - } - - x_lr++; - - weight = (weight_array[x_hr] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr); - src_alpha += weight * base_mask; - } - else - { - fg += back_v * weight; - src_alpha += back_a * weight; - } - - x_lr--; - y_lr++; - - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr); - src_alpha += weight * base_mask; - } - else - { - fg += back_v * weight; - src_alpha += back_a * weight; - } - - x_lr++; - - weight = (weight_array[x_hr] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg += weight * *((const value_type*)base_type::source_image().row(y_lr) + x_lr); - src_alpha += weight * base_mask; - } - else - { - fg += back_v * weight; - src_alpha += back_a * weight; - } - fg >>= image_filter_shift; - src_alpha >>= image_filter_shift; - - if(src_alpha > base_mask) src_alpha = base_mask; - if(fg > src_alpha) fg = src_alpha; - - } - } + unsigned weight; + fg = image_filter_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg >>= image_filter_shift; + if(fg > base_mask) fg = base_mask; span->v = (value_type)fg; - span->a = (value_type)src_alpha; + span->a = base_mask; ++span; ++base_type::interpolator(); - } while(--len); - - return base_type::allocator().span(); } }; - - - - - - - - - - //================================================span_image_filter_gray - template<class ColorT, - class Interpolator, - class Allocator = span_allocator<ColorT> > + //==================================================span_image_filter_gray + template<class Source, class Interpolator> class span_image_filter_gray : - public span_image_filter<ColorT, Interpolator, Allocator> + public span_image_filter<Source, Interpolator> { public: - typedef ColorT color_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; + typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- - span_image_filter_gray(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_gray(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, + span_image_filter_gray() {} + span_image_filter_gray(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : - base_type(alloc, src, back_color, inter, &filter) + base_type(src, inter, &filter) {} //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); int fg; - int src_alpha; - value_type back_v = base_type::background_color().v; - value_type back_a = base_type::background_color().a; - - const value_type* fg_ptr; + const value_type *fg_ptr; - unsigned diameter = base_type::filter().diameter(); - int start = base_type::filter().start(); - int start1 = start - 1; + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); const int16* weight_array = base_type::filter().weight_array(); - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() + start - 2; - int maxy = base_type::source_image().height() + start - 2; - - int maxx2 = base_type::source_image().width() - start - 1; - int maxy2 = base_type::source_image().height() - start - 1; - int x_count; int weight_y; @@ -580,118 +481,264 @@ namespace agg int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; - fg = image_filter_size / 2; + fg = image_filter_scale / 2; int x_fract = x_hr & image_subpixel_mask; unsigned y_count = diameter; - if(x_lr >= -start && y_lr >= -start && - x_lr <= maxx && y_lr <= maxy) + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + fg_ptr = (const value_type*)base_type::source().span(x_lr + start, + y_lr + start, + diameter); + for(;;) { - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); - fg_ptr = (const value_type*)base_type::source_image().row(y_lr + start) + x_lr + start; - do + x_count = diameter; + weight_y = weight_array[y_hr]; + x_hr = image_subpixel_mask - x_fract; + for(;;) { - x_count = diameter; - weight_y = weight_array[y_hr]; - x_hr = image_subpixel_mask - x_fract; + fg += *fg_ptr * + ((weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + image_filter_shift); + if(--x_count == 0) break; + x_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_x(); + } - do - { - fg += *fg_ptr++ * ((weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift); - x_hr += image_subpixel_size; + if(--y_count == 0) break; + y_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg >>= image_filter_shift; + if(fg < 0) fg = 0; + if(fg > base_mask) fg = base_mask; + span->v = (value_type)fg; + span->a = base_mask; - } while(--x_count); + ++span; + ++base_type::interpolator(); - y_hr += image_subpixel_size; - fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - diameter); + } while(--len); + } + }; - } while(--y_count); - fg >>= image_filter_shift; - if(fg < 0) fg = 0; - if(fg > base_mask) fg = base_mask; - src_alpha = base_mask; - } - else + //=========================================span_image_resample_gray_affine + template<class Source> + class span_image_resample_gray_affine : + public span_image_resample_affine<Source> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef span_image_resample_affine<source_type> base_type; + typedef typename base_type::interpolator_type interpolator_type; + typedef typename color_type::value_type value_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, + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_gray_affine() {} + span_image_resample_gray_affine(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + int radius_x = (diameter * base_type::m_rx) >> 1; + int radius_y = (diameter * base_type::m_ry) >> 1; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + + do + { + base_type::interpolator().coordinates(&x, &y); + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg = image_filter_scale / 2; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; + + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + for(;;) { - if(x_lr < start1 || y_lr < start1 || - x_lr > maxx2 || y_lr > maxy2) + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) { - fg = back_v; - src_alpha = back_a; + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + + fg += *fg_ptr * weight; + total_weight += weight; + x_hr += base_type::m_rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); } - else - { - src_alpha = image_filter_size / 2; - y_lr = (y >> image_subpixel_shift) + start; - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + y_hr += base_type::m_ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } - do - { - x_count = diameter; - weight_y = weight_array[y_hr]; - x_lr = (x >> image_subpixel_shift) + start; - x_hr = image_subpixel_mask - x_fract; - - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift; - - if(x_lr >= 0 && y_lr >= 0 && - x_lr < int(base_type::source_image().width()) && - y_lr < int(base_type::source_image().height())) - { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr; - fg += *fg_ptr++ * weight; - src_alpha += base_mask * weight; - } - else - { - fg += back_v * weight; - src_alpha += back_a * weight; - } - x_hr += image_subpixel_size; - x_lr++; - - } while(--x_count); - - y_hr += image_subpixel_size; - y_lr++; - - } while(--y_count); - - - fg >>= image_filter_shift; - src_alpha >>= image_filter_shift; - - if(fg < 0) fg = 0; - if(src_alpha < 0) src_alpha = 0; - - if(src_alpha > base_mask) src_alpha = base_mask; - if(fg > src_alpha) fg = src_alpha; + fg /= total_weight; + if(fg < 0) fg = 0; + if(fg > base_mask) fg = base_mask; + + span->v = (value_type)fg; + span->a = base_mask; + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //================================================span_image_resample_gray + template<class Source, class Interpolator> + class span_image_resample_gray : + public span_image_resample<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_resample<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_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, + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_gray() {} + span_image_resample_gray(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + do + { + int rx; + int ry; + int rx_inv = image_subpixel_scale; + 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_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; + int len_x_lr = + (diameter * rx + image_subpixel_mask) >> + image_subpixel_shift; + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg = image_filter_scale / 2; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + rx_inv) >> + image_subpixel_shift; + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg += *fg_ptr * weight; + total_weight += weight; + x_hr += rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); } + y_hr += ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); } + fg /= total_weight; + if(fg < 0) fg = 0; + if(fg > base_mask) fg = base_mask; + span->v = (value_type)fg; - span->a = (value_type)src_alpha; + span->a = base_mask; ++span; ++base_type::interpolator(); - } while(--len); - - return base_type::allocator().span(); } }; - } diff --git a/agg/inc/agg_span_image_filter_rgb.h b/agg/inc/agg_span_image_filter_rgb.h index d8f8142bfffb..dc9295e31542 100755 --- a/agg/inc/agg_span_image_filter_rgb.h +++ b/agg/inc/agg_span_image_filter_rgb.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -20,7 +20,6 @@ // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- - #ifndef AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED #define AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED @@ -32,146 +31,198 @@ namespace agg { - - //==============================================span_image_filter_rgb_nn - template<class ColorT, - class Order, - class Interpolator, - class Allocator = span_allocator<ColorT> > + //===============================================span_image_filter_rgb_nn + template<class Source, class Interpolator> class span_image_filter_rgb_nn : - public span_image_filter<ColorT, Interpolator, Allocator> + public span_image_filter<Source, Interpolator> { public: - typedef ColorT color_type; - typedef Order order_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; + typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- - span_image_filter_rgb_nn(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_rgb_nn(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, + span_image_filter_rgb_nn() {} + span_image_filter_rgb_nn(source_type& src, interpolator_type& inter) : - base_type(alloc, src, back_color, inter, 0) + base_type(src, inter, 0) {} //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); + do + { + base_type::interpolator().coordinates(&x, &y); + const value_type* fg_ptr = (const value_type*) + base_type::source().span(x >> image_subpixel_shift, + y >> image_subpixel_shift, + 1); + span->r = fg_ptr[order_type::R]; + span->g = fg_ptr[order_type::G]; + span->b = fg_ptr[order_type::B]; + span->a = base_mask; + ++span; + ++base_type::interpolator(); - calc_type fg[3]; - calc_type src_alpha; + } while(--len); + } + }; - const value_type *fg_ptr; - color_type* span = base_type::allocator().span(); - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; + //==========================================span_image_filter_rgb_bilinear + template<class Source, class Interpolator> + class span_image_filter_rgb_bilinear : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_rgb_bilinear() {} + span_image_filter_rgb_bilinear(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + calc_type fg[3]; + const value_type *fg_ptr; do { - base_type::interpolator().coordinates(&x, &y); + int x_hr; + int y_hr; - x >>= image_subpixel_shift; - y >>= image_subpixel_shift; + base_type::interpolator().coordinates(&x_hr, &y_hr); - if(x >= 0 && y >= 0 && - x <= maxx && y <= maxy) - { - fg_ptr = (const value_type*)base_type::source_image().row(y) + x + x + x; - fg[0] = *fg_ptr++; - fg[1] = *fg_ptr++; - fg[2] = *fg_ptr++; - src_alpha = base_mask; - } - else - { - fg[order_type::R] = base_type::background_color().r; - fg[order_type::G] = base_type::background_color().g; - fg[order_type::B] = base_type::background_color().b; - src_alpha = base_type::background_color().a; - } + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + + fg[0] = + fg[1] = + fg[2] = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + span->r = value_type(fg[order_type::R] >> (image_subpixel_shift * 2)); + span->g = value_type(fg[order_type::G] >> (image_subpixel_shift * 2)); + span->b = value_type(fg[order_type::B] >> (image_subpixel_shift * 2)); + span->a = base_mask; - span->r = (value_type)fg[order_type::R]; - span->g = (value_type)fg[order_type::G]; - span->b = (value_type)fg[order_type::B]; - span->a = (value_type)src_alpha; ++span; ++base_type::interpolator(); } while(--len); - - return base_type::allocator().span(); } }; - - //=========================================span_image_filter_rgb_bilinear - template<class ColorT, - class Order, - class Interpolator, - class Allocator = span_allocator<ColorT> > - class span_image_filter_rgb_bilinear : - public span_image_filter<ColorT, Interpolator, Allocator> + //=====================================span_image_filter_rgb_bilinear_clip + template<class Source, class Interpolator> + class span_image_filter_rgb_bilinear_clip : + public span_image_filter<Source, Interpolator> { public: - typedef ColorT color_type; - typedef Order order_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; + typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- - span_image_filter_rgb_bilinear(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_rgb_bilinear(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter) : - base_type(alloc, src, back_color, inter, 0) + span_image_filter_rgb_bilinear_clip() {} + span_image_filter_rgb_bilinear_clip(source_type& src, + const color_type& back_color, + interpolator_type& inter) : + base_type(src, inter, 0), + m_back_color(back_color) {} + const color_type& background_color() const { return m_back_color; } + void background_color(const color_type& v) { m_back_color = v; } //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg[3]; calc_type src_alpha; - value_type back_r = base_type::background_color().r; - value_type back_g = base_type::background_color().g; - value_type back_b = base_type::background_color().b; - value_type back_a = base_type::background_color().a; + value_type back_r = m_back_color.r; + value_type back_g = m_back_color.g; + value_type back_b = m_back_color.b; + value_type back_a = m_back_color.a; const value_type *fg_ptr; - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; + int maxx = base_type::source().width() - 1; + int maxy = base_type::source().height() - 1; do { @@ -192,26 +243,30 @@ namespace agg { fg[0] = fg[1] = - fg[2] = image_subpixel_size * image_subpixel_size / 2; + fg[2] = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - weight = (image_subpixel_size - x_hr) * - (image_subpixel_size - y_hr); + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; - weight = x_hr * (image_subpixel_size - y_hr); + weight = x_hr * (image_subpixel_scale - y_hr); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; - fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - 6); + ++y_lr; + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; - weight = (image_subpixel_size - x_hr) * y_hr; + weight = (image_subpixel_scale - x_hr) * y_hr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; @@ -241,17 +296,19 @@ namespace agg fg[0] = fg[1] = fg[2] = - src_alpha = image_subpixel_size * image_subpixel_size / 2; + src_alpha = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; - weight = (image_subpixel_size - x_hr) * - (image_subpixel_size - y_hr); + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; @@ -267,11 +324,13 @@ namespace agg x_lr++; - weight = x_hr * (image_subpixel_size - y_hr); + weight = x_hr * (image_subpixel_scale - y_hr); if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; @@ -288,11 +347,13 @@ namespace agg x_lr--; y_lr++; - weight = (image_subpixel_size - x_hr) * y_hr; + weight = (image_subpixel_scale - x_hr) * y_hr; if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; @@ -312,7 +373,9 @@ namespace agg if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; @@ -341,74 +404,53 @@ namespace agg ++base_type::interpolator(); } while(--len); - - return base_type::allocator().span(); } + private: + color_type m_back_color; }; - - - - - - //=========================================span_image_filter_rgb_2x2 - template<class ColorT, - class Order, - class Interpolator, - class Allocator = span_allocator<ColorT> > + //===============================================span_image_filter_rgb_2x2 + template<class Source, class Interpolator> class span_image_filter_rgb_2x2 : - public span_image_filter<ColorT, Interpolator, Allocator> + public span_image_filter<Source, Interpolator> { public: - typedef ColorT color_type; - typedef Order order_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; + typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- - span_image_filter_rgb_2x2(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_rgb_2x2(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, + span_image_filter_rgb_2x2() {} + span_image_filter_rgb_2x2(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : - base_type(alloc, src, back_color, inter, &filter) + base_type(src, inter, &filter) {} + //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); + calc_type fg[3]; - calc_type src_alpha; - value_type back_r = base_type::background_color().r; - value_type back_g = base_type::background_color().g; - value_type back_b = base_type::background_color().b; - value_type back_a = base_type::background_color().a; const value_type *fg_ptr; - - color_type* span = base_type::allocator().span(); const int16* weight_array = base_type::filter().weight_array() + ((base_type::filter().diameter()/2 - 1) << image_subpixel_shift); - - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - do { int x_hr; @@ -421,262 +463,111 @@ namespace agg int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; - unsigned weight; - - if(x_lr >= 0 && y_lr >= 0 && - x_lr < maxx && y_lr < maxy) - { - fg[0] = fg[1] = fg[2] = image_filter_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - - weight = (weight_array[x_hr] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - - fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - 6); - - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - - weight = (weight_array[x_hr] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - src_alpha = base_mask; - - if(fg[0] > base_mask) fg[0] = base_mask; - if(fg[1] > base_mask) fg[1] = base_mask; - if(fg[2] > base_mask) fg[2] = base_mask; - } - else - { - if(x_lr < -1 || y_lr < -1 || - x_lr > maxx || y_lr > maxy) - { - fg[order_type::R] = back_r; - fg[order_type::G] = back_g; - fg[order_type::B] = back_b; - src_alpha = back_a; - } - else - { - fg[0] = fg[1] = fg[2] = src_alpha = image_filter_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - src_alpha += weight * base_mask; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - src_alpha += back_a * weight; - } - - x_lr++; - - weight = (weight_array[x_hr] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - src_alpha += weight * base_mask; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - src_alpha += back_a * weight; - } - - x_lr--; - y_lr++; - - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - src_alpha += weight * base_mask; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - src_alpha += back_a * weight; - } - - x_lr++; - - weight = (weight_array[x_hr] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - src_alpha += weight * base_mask; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - src_alpha += back_a * weight; - } - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - src_alpha >>= image_filter_shift; - if(src_alpha > base_mask) src_alpha = base_mask; - if(fg[0] > src_alpha) fg[0] = src_alpha; - if(fg[1] > src_alpha) fg[1] = src_alpha; - if(fg[2] > src_alpha) fg[2] = src_alpha; - } - } + unsigned weight; + fg[0] = fg[1] = fg[2] = image_filter_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg[0] >>= image_filter_shift; + fg[1] >>= image_filter_shift; + fg[2] >>= image_filter_shift; + + if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; + if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; + if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; - span->a = (value_type)src_alpha; + span->a = base_mask; + ++span; ++base_type::interpolator(); } while(--len); - - return base_type::allocator().span(); } }; - - - - - //=================================================span_image_filter_rgb - template<class ColorT, - class Order, - class Interpolator, - class Allocator = span_allocator<ColorT> > + //===================================================span_image_filter_rgb + template<class Source, class Interpolator> class span_image_filter_rgb : - public span_image_filter<ColorT, Interpolator, Allocator> + public span_image_filter<Source, Interpolator> { public: - typedef ColorT color_type; - typedef Order order_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; + typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- - span_image_filter_rgb(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_rgb(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, back_color, inter, &filter) + span_image_filter_rgb() {} + span_image_filter_rgb(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, &filter) {} //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); int fg[3]; - int src_alpha; - value_type back_r = base_type::background_color().r; - value_type back_g = base_type::background_color().g; - value_type back_b = base_type::background_color().b; - value_type back_a = base_type::background_color().a; - - const value_type* fg_ptr; + const value_type *fg_ptr; - unsigned diameter = base_type::filter().diameter(); - int start = base_type::filter().start(); - int start1 = start - 1; + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); const int16* weight_array = base_type::filter().weight_array(); - unsigned step_back = diameter * 3; - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() + start - 2; - int maxy = base_type::source_image().height() + start - 2; - - int maxx2 = base_type::source_image().width() - start - 1; - int maxy2 = base_type::source_image().height() - start - 1; - int x_count; int weight_y; @@ -693,144 +584,305 @@ namespace agg int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; - fg[0] = fg[1] = fg[2] = image_filter_size / 2; + fg[0] = fg[1] = fg[2] = image_filter_scale / 2; int x_fract = x_hr & image_subpixel_mask; unsigned y_count = diameter; - if(x_lr >= -start && y_lr >= -start && - x_lr <= maxx && y_lr <= maxy) + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + fg_ptr = (const value_type*)base_type::source().span(x_lr + start, + y_lr + start, + diameter); + for(;;) { - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); - fg_ptr = (const value_type*)base_type::source_image().row(y_lr + start) + (x_lr + start) * 3; - do + x_count = diameter; + weight_y = weight_array[y_hr]; + x_hr = image_subpixel_mask - x_fract; + for(;;) { - x_count = diameter; - weight_y = weight_array[y_hr]; - x_hr = image_subpixel_mask - x_fract; + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + image_filter_shift; - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; - fg[0] += *fg_ptr++ * weight; - fg[1] += *fg_ptr++ * weight; - fg[2] += *fg_ptr++ * weight; + if(--x_count == 0) break; + x_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_x(); + } - x_hr += image_subpixel_size; + if(--y_count == 0) break; + y_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_y(); + } - } while(--x_count); + fg[0] >>= image_filter_shift; + fg[1] >>= image_filter_shift; + fg[2] >>= image_filter_shift; - y_hr += image_subpixel_size; - fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - step_back); + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; - } while(--y_count); + if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; + if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; + if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = base_mask; - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; + ++span; + ++base_type::interpolator(); - if(fg[0] > base_mask) fg[0] = base_mask; - if(fg[1] > base_mask) fg[1] = base_mask; - if(fg[2] > base_mask) fg[2] = base_mask; - src_alpha = base_mask; - } - else + } while(--len); + } + }; + + + + //==========================================span_image_resample_rgb_affine + template<class Source> + class span_image_resample_rgb_affine : + public span_image_resample_affine<Source> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef span_image_resample_affine<source_type> base_type; + typedef typename base_type::interpolator_type interpolator_type; + typedef typename color_type::value_type value_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, + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgb_affine() {} + span_image_resample_rgb_affine(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[3]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + int radius_x = (diameter * base_type::m_rx) >> 1; + int radius_y = (diameter * base_type::m_ry) >> 1; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + + do + { + base_type::interpolator().coordinates(&x, &y); + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = image_filter_scale / 2; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; + + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + for(;;) { - if(x_lr < start1 || y_lr < start1 || - x_lr > maxx2 || y_lr > maxy2) + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) { - fg[order_type::R] = back_r; - fg[order_type::G] = back_g; - fg[order_type::B] = back_b; - src_alpha = back_a; + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr * weight; + total_weight += weight; + x_hr += base_type::m_rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); } - else - { - src_alpha = image_filter_size / 2; - y_lr = (y >> image_subpixel_shift) + start; - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + y_hr += base_type::m_ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } - do - { - x_count = diameter; - weight_y = weight_array[y_hr]; - x_lr = (x >> image_subpixel_shift) + start; - x_hr = image_subpixel_mask - x_fract; - - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift; - - if(x_lr >= 0 && y_lr >= 0 && - x_lr < int(base_type::source_image().width()) && - y_lr < int(base_type::source_image().height())) - { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + x_lr * 3; - fg[0] += *fg_ptr++ * weight; - fg[1] += *fg_ptr++ * weight; - fg[2] += *fg_ptr++ * weight; - src_alpha += base_mask * weight; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - src_alpha += back_a * weight; - } - x_hr += image_subpixel_size; - x_lr++; - - } while(--x_count); - - y_hr += image_subpixel_size; - y_lr++; - - } while(--y_count); - - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - src_alpha >>= image_filter_shift; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(src_alpha < 0) src_alpha = 0; - - if(src_alpha > base_mask) src_alpha = base_mask; - if(fg[0] > src_alpha) fg[0] = src_alpha; - if(fg[1] > src_alpha) fg[1] = src_alpha; - if(fg[2] > src_alpha) fg[2] = src_alpha; + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + + if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; + if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; + if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = base_mask; + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //=================================================span_image_resample_rgb + template<class Source, class Interpolator> + class span_image_resample_rgb : + public span_image_resample<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_resample<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_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, + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgb() {} + span_image_resample_rgb(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg[3]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + do + { + int rx; + int ry; + int rx_inv = image_subpixel_scale; + 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_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; + int len_x_lr = + (diameter * rx + image_subpixel_mask) >> + image_subpixel_shift; + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = image_filter_scale / 2; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + rx_inv) >> + image_subpixel_shift; + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr * weight; + total_weight += weight; + x_hr += rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); } + y_hr += ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); } + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + + if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; + if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; + if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; + span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; span->b = (value_type)fg[order_type::B]; - span->a = (value_type)src_alpha; + span->a = base_mask; ++span; ++base_type::interpolator(); - } while(--len); - - return base_type::allocator().span(); } }; - } diff --git a/agg/inc/agg_span_image_filter_rgba.h b/agg/inc/agg_span_image_filter_rgba.h index 42b822c99b9b..60d91e47236d 100755 --- a/agg/inc/agg_span_image_filter_rgba.h +++ b/agg/inc/agg_span_image_filter_rgba.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -20,10 +20,6 @@ // PostScript and PDF technology for software developers. // //---------------------------------------------------------------------------- -// -// classes span_image_filter_rgba32* -// -//---------------------------------------------------------------------------- #ifndef AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED #define AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED @@ -35,149 +31,204 @@ namespace agg { - //=============================================span_image_filter_rgba_nn - template<class ColorT, - class Order, - class Interpolator, - class Allocator = span_allocator<ColorT> > + //==============================================span_image_filter_rgba_nn + template<class Source, class Interpolator> class span_image_filter_rgba_nn : - public span_image_filter<ColorT, Interpolator, Allocator> + public span_image_filter<Source, Interpolator> { public: - typedef ColorT color_type; - typedef Order order_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; + typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- - span_image_filter_rgba_nn(alloc_type& alloc) : base_type(alloc) {} + span_image_filter_rgba_nn() {} + span_image_filter_rgba_nn(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} //-------------------------------------------------------------------- - span_image_filter_rgba_nn(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter) : - base_type(alloc, src, back_color, inter, 0) + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + do + { + base_type::interpolator().coordinates(&x, &y); + const value_type* fg_ptr = (const value_type*) + base_type::source().span(x >> image_subpixel_shift, + y >> image_subpixel_shift, + 1); + span->r = fg_ptr[order_type::R]; + span->g = fg_ptr[order_type::G]; + span->b = fg_ptr[order_type::B]; + span->a = fg_ptr[order_type::A]; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //=========================================span_image_filter_rgba_bilinear + template<class Source, class Interpolator> + class span_image_filter_rgba_bilinear : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_rgba_bilinear() {} + span_image_filter_rgba_bilinear(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) {} + //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg[4]; - const value_type *fg_ptr; - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; do { - base_type::interpolator().coordinates(&x, &y); + int x_hr; + int y_hr; - x >>= image_subpixel_shift; - y >>= image_subpixel_shift; + base_type::interpolator().coordinates(&x_hr, &y_hr); - if(x >= 0 && y >= 0 && - x <= maxx && y <= maxy) - { - fg_ptr = (const value_type*)base_type::source_image().row(y) + (x << 2); - fg[0] = *fg_ptr++; - fg[1] = *fg_ptr++; - fg[2] = *fg_ptr++; - fg[3] = *fg_ptr++; - } - else - { - fg[order_type::R] = base_type::background_color().r; - fg[order_type::G] = base_type::background_color().g; - fg[order_type::B] = base_type::background_color().b; - fg[order_type::A] = base_type::background_color().a; - } + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + + fg[0] = + fg[1] = + fg[2] = + fg[3] = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + span->r = value_type(fg[order_type::R] >> (image_subpixel_shift * 2)); + span->g = value_type(fg[order_type::G] >> (image_subpixel_shift * 2)); + span->b = value_type(fg[order_type::B] >> (image_subpixel_shift * 2)); + span->a = value_type(fg[order_type::A] >> (image_subpixel_shift * 2)); - span->r = fg[order_type::R]; - span->g = fg[order_type::G]; - span->b = fg[order_type::B]; - span->a = fg[order_type::A]; ++span; ++base_type::interpolator(); } while(--len); - - return base_type::allocator().span(); } - }; - - - - - - //=======================================span_image_filter_rgba_bilinear - template<class ColorT, - class Order, - class Interpolator, - class Allocator = span_allocator<ColorT> > - class span_image_filter_rgba_bilinear : - public span_image_filter<ColorT, Interpolator, Allocator> + //====================================span_image_filter_rgba_bilinear_clip + template<class Source, class Interpolator> + class span_image_filter_rgba_bilinear_clip : + public span_image_filter<Source, Interpolator> { public: - typedef ColorT color_type; - typedef Order order_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; + typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- - span_image_filter_rgba_bilinear(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_rgba_bilinear(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter) : - base_type(alloc, src, back_color, inter, 0) + span_image_filter_rgba_bilinear_clip() {} + span_image_filter_rgba_bilinear_clip(source_type& src, + const color_type& back_color, + interpolator_type& inter) : + base_type(src, inter, 0), + m_back_color(back_color) {} + const color_type& background_color() const { return m_back_color; } + void background_color(const color_type& v) { m_back_color = v; } //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg[4]; - value_type back_r = base_type::background_color().r; - value_type back_g = base_type::background_color().g; - value_type back_b = base_type::background_color().b; - value_type back_a = base_type::background_color().a; + value_type back_r = m_back_color.r; + value_type back_g = m_back_color.g; + value_type back_b = m_back_color.b; + value_type back_a = m_back_color.a; const value_type *fg_ptr; - - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; + int maxx = base_type::source().width() - 1; + int maxy = base_type::source().height() - 1; do { @@ -200,29 +251,32 @@ namespace agg fg[0] = fg[1] = fg[2] = - fg[3] = image_subpixel_size * image_subpixel_size / 2; + fg[3] = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + (x_lr << 2); + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); - weight = (image_subpixel_size - x_hr) * - (image_subpixel_size - y_hr); + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr++; - weight = x_hr * (image_subpixel_size - y_hr); + weight = x_hr * (image_subpixel_scale - y_hr); fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; fg[3] += weight * *fg_ptr++; - fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - 8); + ++y_lr; + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); - weight = (image_subpixel_size - x_hr) * y_hr; + weight = (image_subpixel_scale - x_hr) * y_hr; fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; @@ -254,17 +308,19 @@ namespace agg fg[0] = fg[1] = fg[2] = - fg[3] = image_subpixel_size * image_subpixel_size / 2; + fg[3] = image_subpixel_scale * image_subpixel_scale / 2; x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; - weight = (image_subpixel_size - x_hr) * - (image_subpixel_size - y_hr); + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + (x_lr << 2); + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; @@ -280,11 +336,13 @@ namespace agg x_lr++; - weight = x_hr * (image_subpixel_size - y_hr); + weight = x_hr * (image_subpixel_scale - y_hr); if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + (x_lr << 2); + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; @@ -301,11 +359,13 @@ namespace agg x_lr--; y_lr++; - weight = (image_subpixel_size - x_hr) * y_hr; + weight = (image_subpixel_scale - x_hr) * y_hr; if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + (x_lr << 2); + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; @@ -325,7 +385,9 @@ namespace agg if(x_lr >= 0 && y_lr >= 0 && x_lr <= maxx && y_lr <= maxy) { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + (x_lr << 2); + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + fg[0] += weight * *fg_ptr++; fg[1] += weight * *fg_ptr++; fg[2] += weight * *fg_ptr++; @@ -354,74 +416,53 @@ namespace agg ++base_type::interpolator(); } while(--len); - - return base_type::allocator().span(); } + private: + color_type m_back_color; }; - - - - - - //=======================================span_image_filter_rgba_2x2 - template<class ColorT, - class Order, - class Interpolator, - class Allocator = span_allocator<ColorT> > + //==============================================span_image_filter_rgba_2x2 + template<class Source, class Interpolator> class span_image_filter_rgba_2x2 : - public span_image_filter<ColorT, Interpolator, Allocator> + public span_image_filter<Source, Interpolator> { public: - typedef ColorT color_type; - typedef Order order_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; + typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- - span_image_filter_rgba_2x2(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_rgba_2x2(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, + span_image_filter_rgba_2x2() {} + span_image_filter_rgba_2x2(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : - base_type(alloc, src, back_color, inter, &filter) + base_type(src, inter, &filter) {} //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); calc_type fg[4]; - value_type back_r = base_type::background_color().r; - value_type back_g = base_type::background_color().g; - value_type back_b = base_type::background_color().b; - value_type back_a = base_type::background_color().a; const value_type *fg_ptr; - - color_type* span = base_type::allocator().span(); const int16* weight_array = base_type::filter().weight_array() + ((base_type::filter().diameter()/2 - 1) << image_subpixel_shift); - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - do { int x_hr; @@ -436,181 +477,60 @@ namespace agg int y_lr = y_hr >> image_subpixel_shift; unsigned weight; - fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2; - - if(x_lr >= 0 && y_lr >= 0 && - x_lr < maxx && y_lr < maxy) - { - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + (x_lr << 2); - - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - - weight = (weight_array[x_hr] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - - fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - 8); - - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - - weight = (weight_array[x_hr] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - fg[3] >>= image_filter_shift; - - if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; - if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; - if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; - if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; - } - else - { - if(x_lr < -1 || y_lr < -1 || - x_lr > maxx || y_lr > maxy) - { - fg[order_type::R] = back_r; - fg[order_type::G] = back_g; - fg[order_type::B] = back_b; - fg[order_type::A] = back_a; - } - else - { - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + (x_lr << 2); - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - fg[order_type::A] += back_a * weight; - } - - x_lr++; - - weight = (weight_array[x_hr] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + (x_lr << 2); - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - fg[order_type::A] += back_a * weight; - } - - x_lr--; - y_lr++; - - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + (x_lr << 2); - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - fg[order_type::A] += back_a * weight; - } - - x_lr++; - - weight = (weight_array[x_hr] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - if(x_lr >= 0 && y_lr >= 0 && - x_lr <= maxx && y_lr <= maxy) - { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + (x_lr << 2); - fg[0] += weight * *fg_ptr++; - fg[1] += weight * *fg_ptr++; - fg[2] += weight * *fg_ptr++; - fg[3] += weight * *fg_ptr++; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - fg[order_type::A] += back_a * weight; - } - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - fg[3] >>= image_filter_shift; - - if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; - if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; - if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; - if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; - } - } + fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg[0] >>= image_filter_shift; + fg[1] >>= image_filter_shift; + fg[2] >>= image_filter_shift; + fg[3] >>= image_filter_shift; + + if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; + if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; + if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; + if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; span->r = (value_type)fg[order_type::R]; span->g = (value_type)fg[order_type::G]; @@ -620,86 +540,51 @@ namespace agg ++base_type::interpolator(); } while(--len); - - return base_type::allocator().span(); } }; - - - - - - - - - - - //================================================span_image_filter_rgba - template<class ColorT, - class Order, - class Interpolator, - class Allocator = span_allocator<ColorT> > + //==================================================span_image_filter_rgba + template<class Source, class Interpolator> class span_image_filter_rgba : - public span_image_filter<ColorT, Interpolator, Allocator> + public span_image_filter<Source, Interpolator> { public: - typedef ColorT color_type; - typedef Order order_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; + typedef span_image_filter<source_type, interpolator_type> base_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum + enum base_scale_e { base_shift = color_type::base_shift, base_mask = color_type::base_mask }; //-------------------------------------------------------------------- - span_image_filter_rgba(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_filter_rgba(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, + span_image_filter_rgba() {} + span_image_filter_rgba(source_type& src, interpolator_type& inter, const image_filter_lut& filter) : - base_type(alloc, src, back_color, inter, &filter) + base_type(src, inter, &filter) {} //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void generate(color_type* span, int x, int y, unsigned len) { base_type::interpolator().begin(x + base_type::filter_dx_dbl(), y + base_type::filter_dy_dbl(), len); int fg[4]; - - value_type back_r = base_type::background_color().r; - value_type back_g = base_type::background_color().g; - value_type back_b = base_type::background_color().b; - value_type back_a = base_type::background_color().a; - const value_type *fg_ptr; - unsigned diameter = base_type::filter().diameter(); - int start = base_type::filter().start(); - int start1 = start - 1; + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); const int16* weight_array = base_type::filter().weight_array(); - unsigned step_back = diameter << 2; - color_type* span = base_type::allocator().span(); - - int maxx = base_type::source_image().width() + start - 2; - int maxy = base_type::source_image().height() + start - 2; - - int maxx2 = base_type::source_image().width() - start - 1; - int maxy2 = base_type::source_image().height() - start - 1; - int x_count; int weight_y; @@ -716,142 +601,313 @@ namespace agg int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; - fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2; + fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; int x_fract = x_hr & image_subpixel_mask; unsigned y_count = diameter; - if(x_lr >= -start && y_lr >= -start && - x_lr <= maxx && y_lr <= maxy) + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + fg_ptr = (const value_type*)base_type::source().span(x_lr + start, + y_lr + start, + diameter); + for(;;) { - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); - fg_ptr = (const value_type*)base_type::source_image().row(y_lr + start) + ((x_lr + start) << 2); - do + x_count = diameter; + weight_y = weight_array[y_hr]; + x_hr = image_subpixel_mask - x_fract; + for(;;) { - x_count = diameter; - weight_y = weight_array[y_hr]; - x_hr = image_subpixel_mask - x_fract; + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + image_filter_shift; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + if(--x_count == 0) break; + x_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_x(); + } - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift; + if(--y_count == 0) break; + y_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_y(); + } - fg[0] += *fg_ptr++ * weight; - fg[1] += *fg_ptr++ * weight; - fg[2] += *fg_ptr++ * weight; - fg[3] += *fg_ptr++ * weight; + fg[0] >>= image_filter_shift; + fg[1] >>= image_filter_shift; + fg[2] >>= image_filter_shift; + fg[3] >>= image_filter_shift; - x_hr += image_subpixel_size; + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; - } while(--x_count); + if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; + if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; + if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; + if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; - y_hr += image_subpixel_size; - fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - step_back); + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + ++span; + ++base_type::interpolator(); - } while(--y_count); + } while(--len); + } + }; - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - fg[3] >>= image_filter_shift; - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; - if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; - if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; - if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; - if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; - } - else + //========================================span_image_resample_rgba_affine + template<class Source> + class span_image_resample_rgba_affine : + public span_image_resample_affine<Source> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef span_image_resample_affine<source_type> base_type; + typedef typename base_type::interpolator_type interpolator_type; + typedef typename color_type::value_type value_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, + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgba_affine() {} + span_image_resample_rgba_affine(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[4]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + int radius_x = (diameter * base_type::m_rx) >> 1; + int radius_y = (diameter * base_type::m_ry) >> 1; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + + do + { + base_type::interpolator().coordinates(&x, &y); + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; + + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + for(;;) { - if(x_lr < start1 || y_lr < start1 || - x_lr > maxx2 || y_lr > maxy2) + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) { - fg[order_type::R] = back_r; - fg[order_type::G] = back_g; - fg[order_type::B] = back_b; - fg[order_type::A] = back_a; + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr++ * weight; + fg[3] += *fg_ptr++ * weight; + total_weight += weight; + x_hr += base_type::m_rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); } - else - { - y_lr = (y >> image_subpixel_shift) + start; - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + y_hr += base_type::m_ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } - do - { - x_count = diameter; - weight_y = weight_array[y_hr]; - x_lr = (x >> image_subpixel_shift) + start; - x_hr = image_subpixel_mask - x_fract; - - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift; - - if(x_lr >= 0 && y_lr >= 0 && - x_lr < int(base_type::source_image().width()) && - y_lr < int(base_type::source_image().height())) - { - fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + (x_lr << 2); - fg[0] += *fg_ptr++ * weight; - fg[1] += *fg_ptr++ * weight; - fg[2] += *fg_ptr++ * weight; - fg[3] += *fg_ptr++ * weight; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - fg[order_type::A] += back_a * weight; - } - x_hr += image_subpixel_size; - x_lr++; - - } while(--x_count); - - y_hr += image_subpixel_size; - y_lr++; - - } while(--y_count); - - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - fg[3] >>= image_filter_shift; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; - - if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; - if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; - if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; - if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + fg[3] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; + + if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; + if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; + if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; + if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //==============================================span_image_resample_rgba + template<class Source, class Interpolator> + class span_image_resample_rgba : + public span_image_resample<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_resample<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_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, + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgba() {} + span_image_resample_rgba(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg[4]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + do + { + int rx; + int ry; + int rx_inv = image_subpixel_scale; + 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_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; + int len_x_lr = + (diameter * rx + image_subpixel_mask) >> + image_subpixel_shift; + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + rx_inv) >> + image_subpixel_shift; + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr++ * weight; + fg[3] += *fg_ptr++ * weight; + total_weight += weight; + x_hr += rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); } + y_hr += ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); } - span->r = fg[order_type::R]; - span->g = fg[order_type::G]; - span->b = fg[order_type::B]; - span->a = fg[order_type::A]; + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + fg[3] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; + + if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; + if(fg[order_type::R] > fg[order_type::R]) fg[order_type::R] = fg[order_type::R]; + if(fg[order_type::G] > fg[order_type::G]) fg[order_type::G] = fg[order_type::G]; + if(fg[order_type::B] > fg[order_type::B]) fg[order_type::B] = fg[order_type::B]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + ++span; ++base_type::interpolator(); - } while(--len); - - return base_type::allocator().span(); } - }; diff --git a/agg/inc/agg_span_image_resample.h b/agg/inc/agg_span_image_resample.h deleted file mode 100755 index f4dfd57455d7..000000000000 --- a/agg/inc/agg_span_image_resample.h +++ /dev/null @@ -1,180 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -#ifndef AGG_SPAN_IMAGE_RESAMPLE_INCLUDED -#define AGG_SPAN_IMAGE_RESAMPLE_INCLUDED - -#include "agg_span_image_filter.h" -#include "agg_span_interpolator_linear.h" - - -namespace agg -{ - - - //=====================================================span_image_resample - template<class ColorT, class Interpolator, class Allocator> - class span_image_resample : - public span_image_filter<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - - //-------------------------------------------------------------------- - span_image_resample(alloc_type& alloc) : - base_type(alloc), - m_scale_limit(20), - m_blur_x(image_subpixel_size), - m_blur_y(image_subpixel_size) - {} - - //-------------------------------------------------------------------- - span_image_resample(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, back_color, inter, &filter), - m_scale_limit(20), - m_blur_x(image_subpixel_size), - m_blur_y(image_subpixel_size) - {} - - - //-------------------------------------------------------------------- - int scale_limit() const { return m_scale_limit; } - void scale_limit(int v) { m_scale_limit = v; } - - //-------------------------------------------------------------------- - double blur_x() const { return double(m_blur_x) / double(image_subpixel_size); } - double blur_y() const { return double(m_blur_y) / double(image_subpixel_size); } - void blur_x(double v) { m_blur_x = int(v * double(image_subpixel_size) + 0.5); } - void blur_y(double v) { m_blur_y = int(v * double(image_subpixel_size) + 0.5); } - void blur(double v) { m_blur_x = - m_blur_y = int(v * double(image_subpixel_size) + 0.5); } - - protected: - int m_scale_limit; - int m_blur_x; - int m_blur_y; - }; - - - - - - - - - //==============================================span_image_resample_affine - template<class ColorT, class Allocator> - class span_image_resample_affine : - public span_image_filter<ColorT, span_interpolator_linear<trans_affine>, Allocator> - { - public: - typedef ColorT color_type; - typedef span_interpolator_linear<trans_affine> interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - - //-------------------------------------------------------------------- - span_image_resample_affine(alloc_type& alloc) : - base_type(alloc), - m_scale_limit(200.0), - m_blur_x(1.0), - m_blur_y(1.0) - {} - - //-------------------------------------------------------------------- - span_image_resample_affine(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter, - const image_filter_lut& filter_) : - base_type(alloc, src, back_color, inter, &filter_), - m_scale_limit(200.0), - m_blur_x(1.0), - m_blur_y(1.0) - {} - - - //-------------------------------------------------------------------- - int scale_limit() const { return int(m_scale_limit); } - void scale_limit(int v) { m_scale_limit = v; } - - //-------------------------------------------------------------------- - double blur_x() const { return m_blur_x; } - double blur_y() const { return m_blur_y; } - void blur_x(double v) { m_blur_x = v; } - void blur_y(double v) { m_blur_y = v; } - void blur(double v) { m_blur_x = m_blur_y = v; } - - - //-------------------------------------------------------------------- - void prepare(unsigned max_span_len) - { - base_type::prepare(max_span_len); - - double scale_x; - double scale_y; - - base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y); - - m_rx = image_subpixel_size; - m_ry = image_subpixel_size; - m_rx_inv = image_subpixel_size; - m_ry_inv = image_subpixel_size; - - 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 = int( scale_x * double(image_subpixel_size) + 0.5); - m_rx_inv = int(1.0/scale_x * double(image_subpixel_size) + 0.5); - } - - if(scale_y > 1.0001) - { - if(scale_y > m_scale_limit) scale_y = m_scale_limit; - m_ry = int( scale_y * double(image_subpixel_size) + 0.5); - m_ry_inv = int(1.0/scale_y * double(image_subpixel_size) + 0.5); - } - } - - protected: - int m_rx; - int m_ry; - int m_rx_inv; - int m_ry_inv; - - private: - double m_scale_limit; - double m_blur_x; - double m_blur_y; - }; - -} - -#endif diff --git a/agg/inc/agg_span_image_resample_gray.h b/agg/inc/agg_span_image_resample_gray.h deleted file mode 100755 index 3d046462cd8c..000000000000 --- a/agg/inc/agg_span_image_resample_gray.h +++ /dev/null @@ -1,359 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_IMAGE_RESAMPLE_GRAY_INCLUDED -#define AGG_SPAN_IMAGE_RESAMPLE_GRAY_INCLUDED - -#include "agg_color_gray.h" -#include "agg_span_image_resample.h" - -namespace agg -{ - - //========================================span_image_resample_gray_affine - template<class ColorT, - class Allocator = span_allocator<ColorT> > - class span_image_resample_gray_affine : - public span_image_resample_affine<ColorT, Allocator> - { - public: - typedef ColorT color_type; - typedef Allocator alloc_type; - typedef span_image_resample_affine<color_type, alloc_type> base_type; - typedef typename base_type::interpolator_type interpolator_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::long_type long_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask, - downscale_shift = image_filter_shift - }; - - //-------------------------------------------------------------------- - span_image_resample_gray_affine(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_resample_gray_affine(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, back_color, inter, filter) - {} - - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - - long_type fg; - long_type src_alpha; - value_type back_v = base_type::background_color().v; - value_type back_a = base_type::background_color().a; - - color_type* span = base_type::allocator().span(); - - int diameter = base_type::filter().diameter(); - int filter_size = diameter << image_subpixel_shift; - int radius_x = (diameter * base_type::m_rx) >> 1; - int radius_y = (diameter * base_type::m_ry) >> 1; - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - const int16* weight_array = base_type::filter().weight_array(); - - do - { - base_type::interpolator().coordinates(&x, &y); - - x += base_type::filter_dx_int() - radius_x; - y += base_type::filter_dy_int() - radius_y; - - fg = src_alpha = image_filter_size / 2; - - int y_lr = y >> image_subpixel_shift; - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - base_type::m_ry_inv) >> - image_subpixel_shift; - int total_weight = 0; - int x_lr_ini = x >> image_subpixel_shift; - int x_hr_ini = ((image_subpixel_mask - (x & image_subpixel_mask)) * - base_type::m_rx_inv) >> - image_subpixel_shift; - do - { - int weight_y = weight_array[y_hr]; - int x_lr = x_lr_ini; - int x_hr = x_hr_ini; - if(y_lr >= 0 && y_lr <= maxy) - { - const value_type* fg_ptr = (const value_type*) - base_type::source_image().row(y_lr) + x_lr; - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - if(x_lr >= 0 && x_lr <= maxx) - { - fg += *fg_ptr * weight; - src_alpha += base_mask * weight; - } - else - { - fg += back_v * weight; - src_alpha += back_a * weight; - } - total_weight += weight; - x_hr += base_type::m_rx_inv; - ++fg_ptr; - ++x_lr; - } - while(x_hr < filter_size); - } - else - { - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - total_weight += weight; - fg += back_v * weight; - src_alpha += back_a * weight; - x_hr += base_type::m_rx_inv; - } - while(x_hr < filter_size); - } - y_hr += base_type::m_ry_inv; - ++y_lr; - } - while(y_hr < filter_size); - - fg /= total_weight; - src_alpha /= total_weight; - - if(fg < 0) fg = 0; - if(src_alpha < 0) src_alpha = 0; - - if(src_alpha > base_mask) src_alpha = base_mask; - if(fg > src_alpha) fg = src_alpha; - - span->v = (value_type)fg; - span->a = (value_type)src_alpha; - - ++span; - ++base_type::interpolator(); - } while(--len); - return base_type::allocator().span(); - } - }; - - - - - - - - //==============================================span_image_resample_gray - template<class ColorT, - class Interpolator, - class Allocator = span_allocator<ColorT> > - class span_image_resample_gray : - public span_image_resample<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_resample<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::long_type long_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask, - downscale_shift = image_filter_shift - }; - - //-------------------------------------------------------------------- - span_image_resample_gray(alloc_type& alloc) : - base_type(alloc) - {} - - //-------------------------------------------------------------------- - span_image_resample_gray(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, back_color, inter, filter) - {} - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - long_type fg; - long_type src_alpha; - value_type back_v = base_type::background_color().v; - value_type back_a = base_type::background_color().a; - - int diameter = base_type::filter().diameter(); - int filter_size = diameter << image_subpixel_shift; - - const int16* weight_array = base_type::filter().weight_array(); - - do - { - int rx; - int ry; - int rx_inv = image_subpixel_size; - int ry_inv = image_subpixel_size; - base_type::interpolator().coordinates(&x, &y); - base_type::interpolator().local_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_size) - { - rx = image_subpixel_size; - } - else - { - if(rx > image_subpixel_size * base_type::m_scale_limit) - { - rx = image_subpixel_size * base_type::m_scale_limit; - } - rx_inv = image_subpixel_size * image_subpixel_size / rx; - } - - if(ry < image_subpixel_size) - { - ry = image_subpixel_size; - } - else - { - if(ry > image_subpixel_size * base_type::m_scale_limit) - { - ry = image_subpixel_size * base_type::m_scale_limit; - } - ry_inv = image_subpixel_size * image_subpixel_size / ry; - } - - int radius_x = (diameter * rx) >> 1; - int radius_y = (diameter * ry) >> 1; - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - x += base_type::filter_dx_int() - radius_x; - y += base_type::filter_dy_int() - radius_y; - - fg = src_alpha = image_filter_size / 2; - - int y_lr = y >> image_subpixel_shift; - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - ry_inv) >> - image_subpixel_shift; - int total_weight = 0; - int x_lr_ini = x >> image_subpixel_shift; - int x_hr_ini = ((image_subpixel_mask - (x & image_subpixel_mask)) * - rx_inv) >> - image_subpixel_shift; - - do - { - int weight_y = weight_array[y_hr]; - int x_lr = x_lr_ini; - int x_hr = x_hr_ini; - if(y_lr >= 0 && y_lr <= maxy) - { - const value_type* fg_ptr = (const value_type*) - base_type::source_image().row(y_lr) + x_lr; - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - if(x_lr >= 0 && x_lr <= maxx) - { - fg += *fg_ptr * weight; - src_alpha += base_mask * weight; - } - else - { - fg += back_v * weight; - src_alpha += back_a * weight; - } - total_weight += weight; - x_hr += rx_inv; - ++fg_ptr; - ++x_lr; - } - while(x_hr < filter_size); - } - else - { - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - total_weight += weight; - fg += back_v * weight; - src_alpha += back_a * weight; - x_hr += rx_inv; - } - while(x_hr < filter_size); - } - y_hr += ry_inv; - ++y_lr; - } - while(y_hr < filter_size); - - fg /= total_weight; - src_alpha /= total_weight; - - if(fg < 0) fg = 0; - if(src_alpha < 0) src_alpha = 0; - - if(src_alpha > base_mask) src_alpha = base_mask; - if(fg > src_alpha) fg = src_alpha; - - span->v = (value_type)fg; - span->a = (value_type)src_alpha; - - ++span; - ++base_type::interpolator(); - } while(--len); - return base_type::allocator().span(); - } - - }; - -} - - -#endif diff --git a/agg/inc/agg_span_image_resample_rgb.h b/agg/inc/agg_span_image_resample_rgb.h deleted file mode 100755 index de25dd4b382b..000000000000 --- a/agg/inc/agg_span_image_resample_rgb.h +++ /dev/null @@ -1,393 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_IMAGE_RESAMPLE_RGB_INCLUDED -#define AGG_SPAN_IMAGE_RESAMPLE_RGB_INCLUDED - -#include "agg_color_rgba.h" -#include "agg_span_image_resample.h" - -namespace agg -{ - - //=========================================span_image_resample_rgb_affine - template<class ColorT, - class Order, - class Allocator = span_allocator<ColorT> > - class span_image_resample_rgb_affine : - public span_image_resample_affine<ColorT, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Allocator alloc_type; - typedef span_image_resample_affine<color_type, alloc_type> base_type; - typedef typename base_type::interpolator_type interpolator_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::long_type long_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask, - downscale_shift = image_filter_shift - }; - - //-------------------------------------------------------------------- - span_image_resample_rgb_affine(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_resample_rgb_affine(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, back_color, inter, filter) - {} - - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - - long_type fg[4]; - value_type back_r = base_type::background_color().r; - value_type back_g = base_type::background_color().g; - value_type back_b = base_type::background_color().b; - value_type back_a = base_type::background_color().a; - - color_type* span = base_type::allocator().span(); - - int diameter = base_type::filter().diameter(); - int filter_size = diameter << image_subpixel_shift; - int radius_x = (diameter * base_type::m_rx) >> 1; - int radius_y = (diameter * base_type::m_ry) >> 1; - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - const int16* weight_array = base_type::filter().weight_array(); - - do - { - base_type::interpolator().coordinates(&x, &y); - - x += base_type::filter_dx_int() - radius_x; - y += base_type::filter_dy_int() - radius_y; - - fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2; - - int y_lr = y >> image_subpixel_shift; - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - base_type::m_ry_inv) >> - image_subpixel_shift; - int total_weight = 0; - int x_lr_ini = x >> image_subpixel_shift; - int x_hr_ini = ((image_subpixel_mask - (x & image_subpixel_mask)) * - base_type::m_rx_inv) >> - image_subpixel_shift; - do - { - int weight_y = weight_array[y_hr]; - int x_lr = x_lr_ini; - int x_hr = x_hr_ini; - if(y_lr >= 0 && y_lr <= maxy) - { - const value_type* fg_ptr = (const value_type*) - base_type::source_image().row(y_lr) + x_lr * 3; - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - if(x_lr >= 0 && x_lr <= maxx) - { - fg[0] += fg_ptr[0] * weight; - fg[1] += fg_ptr[1] * weight; - fg[2] += fg_ptr[2] * weight; - fg[3] += base_mask * weight; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - fg[3] += back_a * weight; - } - total_weight += weight; - fg_ptr += 3; - x_hr += base_type::m_rx_inv; - ++x_lr; - } - while(x_hr < filter_size); - } - else - { - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - total_weight += weight; - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - fg[3] += back_a * weight; - x_hr += base_type::m_rx_inv; - } - while(x_hr < filter_size); - } - y_hr += base_type::m_ry_inv; - ++y_lr; - } - while(y_hr < filter_size); - - fg[0] /= total_weight; - fg[1] /= total_weight; - fg[2] /= total_weight; - fg[3] /= total_weight; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; - - if(fg[3] > base_mask) fg[3] = base_mask; - if(fg[0] > fg[3]) fg[0] = fg[3]; - if(fg[1] > fg[3]) fg[1] = fg[3]; - if(fg[2] > fg[3]) fg[2] = fg[3]; - - span->r = (value_type)fg[order_type::R]; - span->g = (value_type)fg[order_type::G]; - span->b = (value_type)fg[order_type::B]; - span->a = (value_type)fg[3]; - - ++span; - ++base_type::interpolator(); - } while(--len); - return base_type::allocator().span(); - } - }; - - - - - - - - //===============================================span_image_resample_rgb - template<class ColorT, - class Order, - class Interpolator, - class Allocator = span_allocator<ColorT> > - class span_image_resample_rgb : - public span_image_resample<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_resample<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::long_type long_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask, - downscale_shift = image_filter_shift - }; - - //-------------------------------------------------------------------- - span_image_resample_rgb(alloc_type& alloc) : - base_type(alloc) - {} - - //-------------------------------------------------------------------- - span_image_resample_rgb(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, back_color, inter, filter) - {} - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - long_type fg[4]; - value_type back_r = base_type::background_color().r; - value_type back_g = base_type::background_color().g; - value_type back_b = base_type::background_color().b; - value_type back_a = base_type::background_color().a; - - int diameter = base_type::filter().diameter(); - int filter_size = diameter << image_subpixel_shift; - - const int16* weight_array = base_type::filter().weight_array(); - - do - { - int rx; - int ry; - int rx_inv = image_subpixel_size; - int ry_inv = image_subpixel_size; - base_type::interpolator().coordinates(&x, &y); - base_type::interpolator().local_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_size) - { - rx = image_subpixel_size; - } - else - { - if(rx > image_subpixel_size * base_type::m_scale_limit) - { - rx = image_subpixel_size * base_type::m_scale_limit; - } - rx_inv = image_subpixel_size * image_subpixel_size / rx; - } - - if(ry < image_subpixel_size) - { - ry = image_subpixel_size; - } - else - { - if(ry > image_subpixel_size * base_type::m_scale_limit) - { - ry = image_subpixel_size * base_type::m_scale_limit; - } - ry_inv = image_subpixel_size * image_subpixel_size / ry; - } - - int radius_x = (diameter * rx) >> 1; - int radius_y = (diameter * ry) >> 1; - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - x += base_type::filter_dx_int() - radius_x; - y += base_type::filter_dy_int() - radius_y; - - fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2; - - int y_lr = y >> image_subpixel_shift; - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - ry_inv) >> - image_subpixel_shift; - int total_weight = 0; - int x_lr_ini = x >> image_subpixel_shift; - int x_hr_ini = ((image_subpixel_mask - (x & image_subpixel_mask)) * - rx_inv) >> - image_subpixel_shift; - - do - { - int weight_y = weight_array[y_hr]; - int x_lr = x_lr_ini; - int x_hr = x_hr_ini; - if(y_lr >= 0 && y_lr <= maxy) - { - const value_type* fg_ptr = (const value_type*) - base_type::source_image().row(y_lr) + x_lr * 3; - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - if(x_lr >= 0 && x_lr <= maxx) - { - fg[0] += fg_ptr[0] * weight; - fg[1] += fg_ptr[1] * weight; - fg[2] += fg_ptr[2] * weight; - fg[3] += base_mask * weight; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - fg[3] += back_a * weight; - } - total_weight += weight; - fg_ptr += 3; - x_hr += rx_inv; - ++x_lr; - } - while(x_hr < filter_size); - } - else - { - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - total_weight += weight; - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - fg[3] += back_a * weight; - x_hr += rx_inv; - } - while(x_hr < filter_size); - } - y_hr += ry_inv; - ++y_lr; - } - while(y_hr < filter_size); - - fg[0] /= total_weight; - fg[1] /= total_weight; - fg[2] /= total_weight; - fg[3] /= total_weight; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; - - if(fg[3] > base_mask) fg[3] = base_mask; - if(fg[0] > fg[3]) fg[0] = fg[3]; - if(fg[1] > fg[3]) fg[1] = fg[3]; - if(fg[2] > fg[3]) fg[2] = fg[3]; - - span->r = (value_type)fg[order_type::R]; - span->g = (value_type)fg[order_type::G]; - span->b = (value_type)fg[order_type::B]; - span->a = (value_type)fg[3]; - - ++span; - ++base_type::interpolator(); - } while(--len); - return base_type::allocator().span(); - } - - }; - -} - - -#endif diff --git a/agg/inc/agg_span_image_resample_rgba.h b/agg/inc/agg_span_image_resample_rgba.h deleted file mode 100755 index 40f7ccb42e00..000000000000 --- a/agg/inc/agg_span_image_resample_rgba.h +++ /dev/null @@ -1,393 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_IMAGE_RESAMPLE_RGBA_INCLUDED -#define AGG_SPAN_IMAGE_RESAMPLE_RGBA_INCLUDED - -#include "agg_color_rgba.h" -#include "agg_span_image_resample.h" - -namespace agg -{ - - //========================================span_image_resample_rgba_affine - template<class ColorT, - class Order, - class Allocator = span_allocator<ColorT> > - class span_image_resample_rgba_affine : - public span_image_resample_affine<ColorT, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Allocator alloc_type; - typedef span_image_resample_affine<color_type, alloc_type> base_type; - typedef typename base_type::interpolator_type interpolator_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::long_type long_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask, - downscale_shift = image_filter_shift - }; - - //-------------------------------------------------------------------- - span_image_resample_rgba_affine(alloc_type& alloc) : base_type(alloc) {} - - //-------------------------------------------------------------------- - span_image_resample_rgba_affine(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, back_color, inter, filter) - {} - - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - - long_type fg[4]; - value_type back_r = base_type::background_color().r; - value_type back_g = base_type::background_color().g; - value_type back_b = base_type::background_color().b; - value_type back_a = base_type::background_color().a; - - color_type* span = base_type::allocator().span(); - - int diameter = base_type::filter().diameter(); - int filter_size = diameter << image_subpixel_shift; - int radius_x = (diameter * base_type::m_rx) >> 1; - int radius_y = (diameter * base_type::m_ry) >> 1; - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - const int16* weight_array = base_type::filter().weight_array(); - - do - { - base_type::interpolator().coordinates(&x, &y); - - x += base_type::filter_dx_int() - radius_x; - y += base_type::filter_dy_int() - radius_y; - - fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2; - - int y_lr = y >> image_subpixel_shift; - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - base_type::m_ry_inv) >> - image_subpixel_shift; - int total_weight = 0; - int x_lr_ini = x >> image_subpixel_shift; - int x_hr_ini = ((image_subpixel_mask - (x & image_subpixel_mask)) * - base_type::m_rx_inv) >> - image_subpixel_shift; - do - { - int weight_y = weight_array[y_hr]; - int x_lr = x_lr_ini; - int x_hr = x_hr_ini; - if(y_lr >= 0 && y_lr <= maxy) - { - const value_type* fg_ptr = (const value_type*) - base_type::source_image().row(y_lr) + (x_lr << 2); - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - if(x_lr >= 0 && x_lr <= maxx) - { - fg[0] += fg_ptr[0] * weight; - fg[1] += fg_ptr[1] * weight; - fg[2] += fg_ptr[2] * weight; - fg[3] += fg_ptr[3] * weight; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - fg[order_type::A] += back_a * weight; - } - total_weight += weight; - fg_ptr += 4; - x_hr += base_type::m_rx_inv; - ++x_lr; - } - while(x_hr < filter_size); - } - else - { - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - total_weight += weight; - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - fg[order_type::A] += back_a * weight; - x_hr += base_type::m_rx_inv; - } - while(x_hr < filter_size); - } - y_hr += base_type::m_ry_inv; - ++y_lr; - } - while(y_hr < filter_size); - - fg[0] /= total_weight; - fg[1] /= total_weight; - fg[2] /= total_weight; - fg[3] /= total_weight; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; - - if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; - if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; - if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; - if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; - - span->r = (value_type)fg[order_type::R]; - span->g = (value_type)fg[order_type::G]; - span->b = (value_type)fg[order_type::B]; - span->a = (value_type)fg[order_type::A]; - - ++span; - ++base_type::interpolator(); - } while(--len); - return base_type::allocator().span(); - } - }; - - - - - - - - //==============================================span_image_resample_rgba - template<class ColorT, - class Order, - class Interpolator, - class Allocator = span_allocator<ColorT> > - class span_image_resample_rgba : - public span_image_resample<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_resample<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::long_type long_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask, - downscale_shift = image_filter_shift - }; - - //-------------------------------------------------------------------- - span_image_resample_rgba(alloc_type& alloc) : - base_type(alloc) - {} - - //-------------------------------------------------------------------- - span_image_resample_rgba(alloc_type& alloc, - const rendering_buffer& src, - const color_type& back_color, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, back_color, inter, filter) - {} - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - long_type fg[4]; - value_type back_r = base_type::background_color().r; - value_type back_g = base_type::background_color().g; - value_type back_b = base_type::background_color().b; - value_type back_a = base_type::background_color().a; - - int diameter = base_type::filter().diameter(); - int filter_size = diameter << image_subpixel_shift; - - const int16* weight_array = base_type::filter().weight_array(); - - do - { - int rx; - int ry; - int rx_inv = image_subpixel_size; - int ry_inv = image_subpixel_size; - base_type::interpolator().coordinates(&x, &y); - base_type::interpolator().local_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_size) - { - rx = image_subpixel_size; - } - else - { - if(rx > image_subpixel_size * base_type::m_scale_limit) - { - rx = image_subpixel_size * base_type::m_scale_limit; - } - rx_inv = image_subpixel_size * image_subpixel_size / rx; - } - - if(ry < image_subpixel_size) - { - ry = image_subpixel_size; - } - else - { - if(ry > image_subpixel_size * base_type::m_scale_limit) - { - ry = image_subpixel_size * base_type::m_scale_limit; - } - ry_inv = image_subpixel_size * image_subpixel_size / ry; - } - - int radius_x = (diameter * rx) >> 1; - int radius_y = (diameter * ry) >> 1; - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - x += base_type::filter_dx_int() - radius_x; - y += base_type::filter_dy_int() - radius_y; - - fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2; - - int y_lr = y >> image_subpixel_shift; - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - ry_inv) >> - image_subpixel_shift; - int total_weight = 0; - int x_lr_ini = x >> image_subpixel_shift; - int x_hr_ini = ((image_subpixel_mask - (x & image_subpixel_mask)) * - rx_inv) >> - image_subpixel_shift; - - do - { - int weight_y = weight_array[y_hr]; - int x_lr = x_lr_ini; - int x_hr = x_hr_ini; - if(y_lr >= 0 && y_lr <= maxy) - { - const value_type* fg_ptr = (const value_type*) - base_type::source_image().row(y_lr) + (x_lr << 2); - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - if(x_lr >= 0 && x_lr <= maxx) - { - fg[0] += fg_ptr[0] * weight; - fg[1] += fg_ptr[1] * weight; - fg[2] += fg_ptr[2] * weight; - fg[3] += fg_ptr[3] * weight; - } - else - { - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - fg[order_type::A] += back_a * weight; - } - total_weight += weight; - fg_ptr += 4; - x_hr += rx_inv; - ++x_lr; - } - while(x_hr < filter_size); - } - else - { - do - { - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - total_weight += weight; - fg[order_type::R] += back_r * weight; - fg[order_type::G] += back_g * weight; - fg[order_type::B] += back_b * weight; - fg[order_type::A] += back_a * weight; - x_hr += rx_inv; - } - while(x_hr < filter_size); - } - y_hr += ry_inv; - ++y_lr; - } - while(y_hr < filter_size); - - fg[0] /= total_weight; - fg[1] /= total_weight; - fg[2] /= total_weight; - fg[3] /= total_weight; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; - - if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; - if(fg[order_type::R] > fg[order_type::R]) fg[order_type::R] = fg[order_type::R]; - if(fg[order_type::G] > fg[order_type::G]) fg[order_type::G] = fg[order_type::G]; - if(fg[order_type::B] > fg[order_type::B]) fg[order_type::B] = fg[order_type::B]; - - span->r = (value_type)fg[order_type::R]; - span->g = (value_type)fg[order_type::G]; - span->b = (value_type)fg[order_type::B]; - span->a = (value_type)fg[order_type::A]; - - ++span; - ++base_type::interpolator(); - } while(--len); - return base_type::allocator().span(); - } - - }; - -} - - -#endif diff --git a/agg/inc/agg_span_interpolator_adaptor.h b/agg/inc/agg_span_interpolator_adaptor.h index ead42c13590c..5626f9829cda 100755 --- a/agg/inc/agg_span_interpolator_adaptor.h +++ b/agg/inc/agg_span_interpolator_adaptor.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_span_interpolator_linear.h b/agg/inc/agg_span_interpolator_linear.h index 3cc2426be450..5bbbdf62d6fd 100755 --- a/agg/inc/agg_span_interpolator_linear.h +++ b/agg/inc/agg_span_interpolator_linear.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -30,10 +30,10 @@ namespace agg public: typedef Transformer trans_type; - enum + enum subpixel_scale_e { subpixel_shift = SubpixelShift, - subpixel_size = 1 << subpixel_shift + subpixel_scale = 1 << subpixel_shift }; //-------------------------------------------------------------------- @@ -59,14 +59,14 @@ namespace agg tx = x; ty = y; m_trans->transform(&tx, &ty); - int x1 = int(tx * subpixel_size); - int y1 = int(ty * subpixel_size); + int x1 = iround(tx * subpixel_scale); + int y1 = iround(ty * subpixel_scale); tx = x + len; ty = y; m_trans->transform(&tx, &ty); - int x2 = int(tx * subpixel_size); - int y2 = int(ty * subpixel_size); + int x2 = iround(tx * subpixel_scale); + int y2 = iround(ty * subpixel_scale); m_li_x = dda2_line_interpolator(x1, x2, len); m_li_y = dda2_line_interpolator(y1, y2, len); @@ -76,8 +76,8 @@ namespace agg void resynchronize(double xe, double ye, unsigned len) { m_trans->transform(&xe, &ye); - m_li_x = dda2_line_interpolator(m_li_x.y(), int(xe * subpixel_size), len); - m_li_y = dda2_line_interpolator(m_li_y.y(), int(ye * subpixel_size), len); + m_li_x = dda2_line_interpolator(m_li_x.y(), iround(xe * subpixel_scale), len); + m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ye * subpixel_scale), len); } //---------------------------------------------------------------- @@ -112,10 +112,10 @@ namespace agg public: typedef Transformer trans_type; - enum + enum subpixel_scale_e { subpixel_shift = SubpixelShift, - subpixel_size = 1 << subpixel_shift + subpixel_scale = 1 << subpixel_shift }; @@ -162,7 +162,7 @@ namespace agg double tx; double ty; m_pos = 1; - m_src_x = int(x * subpixel_size) + subpixel_size; + m_src_x = iround(x * subpixel_scale) + subpixel_scale; m_src_y = y; m_len = len; @@ -170,15 +170,15 @@ namespace agg tx = x; ty = y; m_trans->transform(&tx, &ty); - int x1 = int(tx * subpixel_size); - int y1 = int(ty * subpixel_size); + int x1 = iround(tx * subpixel_scale); + int y1 = iround(ty * subpixel_scale); tx = x + len; ty = y; m_trans->transform(&tx, &ty); - m_li_x = dda2_line_interpolator(x1, int(tx * subpixel_size), len); - m_li_y = dda2_line_interpolator(y1, int(ty * subpixel_size), len); + m_li_x = dda2_line_interpolator(x1, iround(tx * subpixel_scale), len); + m_li_y = dda2_line_interpolator(y1, iround(ty * subpixel_scale), len); } //---------------------------------------------------------------- @@ -190,14 +190,14 @@ namespace agg { unsigned len = m_len; if(len > m_subdiv_size) len = m_subdiv_size; - double tx = double(m_src_x) / double(subpixel_size) + len; + double tx = double(m_src_x) / double(subpixel_scale) + len; double ty = m_src_y; m_trans->transform(&tx, &ty); - m_li_x = dda2_line_interpolator(m_li_x.y(), int(tx * subpixel_size), len); - m_li_y = dda2_line_interpolator(m_li_y.y(), int(ty * subpixel_size), len); + m_li_x = dda2_line_interpolator(m_li_x.y(), iround(tx * subpixel_scale), len); + m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ty * subpixel_scale), len); m_pos = 0; } - m_src_x += subpixel_size; + m_src_x += subpixel_scale; ++m_pos; --m_len; } diff --git a/agg/inc/agg_span_interpolator_persp.h b/agg/inc/agg_span_interpolator_persp.h index 632a56449f28..6c43687f11da 100755 --- a/agg/inc/agg_span_interpolator_persp.h +++ b/agg/inc/agg_span_interpolator_persp.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -30,10 +30,10 @@ namespace agg public: typedef trans_perspective trans_type; typedef trans_perspective::iterator_x iterator_type; - enum + enum subpixel_scale_e { subpixel_shift = SubpixelShift, - subpixel_size = 1 << subpixel_shift + subpixel_scale = 1 << subpixel_shift }; //-------------------------------------------------------------------- @@ -112,19 +112,19 @@ namespace agg double dx; double dy; - const double delta = 1/double(subpixel_size); + const double delta = 1/double(subpixel_scale); dx = xt + delta; dy = yt; m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; - int sx1 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; dx = xt; dy = yt + delta; m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; - int sy1 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; x += len; xt = x; @@ -136,13 +136,13 @@ namespace agg m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; - int sx2 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; dx = xt; dy = yt + delta; m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; - int sy2 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; m_scale_x = dda2_line_interpolator(sx1, sx2, len); m_scale_y = dda2_line_interpolator(sy1, sy2, len); @@ -161,7 +161,7 @@ namespace agg double yt = ye; m_trans_dir.transform(&xt, &yt); - const double delta = 1/double(subpixel_size); + const double delta = 1/double(subpixel_scale); double dx; double dy; @@ -171,7 +171,7 @@ namespace agg m_trans_inv.transform(&dx, &dy); dx -= xe; dy -= ye; - int sx2 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Calculate scale by Y at x2,y2 dx = xt; @@ -179,7 +179,7 @@ namespace agg m_trans_inv.transform(&dx, &dy); dx -= xe; dy -= ye; - int sy2 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Initialize the interpolators m_scale_x = dda2_line_interpolator(sx1, sx2, len); @@ -199,8 +199,8 @@ namespace agg //---------------------------------------------------------------- void coordinates(int* x, int* y) const { - *x = int(m_iterator.x * subpixel_size + 0.5); - *y = int(m_iterator.y * subpixel_size + 0.5); + *x = iround(m_iterator.x * subpixel_scale); + *y = iround(m_iterator.y * subpixel_scale); } //---------------------------------------------------------------- @@ -240,10 +240,10 @@ namespace agg { public: typedef trans_perspective trans_type; - enum + enum subpixel_scale_e { subpixel_shift = SubpixelShift, - subpixel_size = 1 << subpixel_shift + subpixel_scale = 1 << subpixel_shift }; //-------------------------------------------------------------------- @@ -320,12 +320,12 @@ namespace agg double xt = x; double yt = y; m_trans_dir.transform(&xt, &yt); - int x1 = int(xt * subpixel_size); - int y1 = int(yt * subpixel_size); + int x1 = iround(xt * subpixel_scale); + int y1 = iround(yt * subpixel_scale); double dx; double dy; - const double delta = 1/double(subpixel_size); + const double delta = 1/double(subpixel_scale); // Calculate scale by X at x1,y1 dx = xt + delta; @@ -333,7 +333,7 @@ namespace agg m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; - int sx1 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Calculate scale by Y at x1,y1 dx = xt; @@ -341,15 +341,15 @@ namespace agg m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; - int sy1 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Calculate transformed coordinates at x2,y2 x += len; xt = x; yt = y; m_trans_dir.transform(&xt, &yt); - int x2 = int(xt * subpixel_size); - int y2 = int(yt * subpixel_size); + int x2 = iround(xt * subpixel_scale); + int y2 = iround(yt * subpixel_scale); // Calculate scale by X at x2,y2 dx = xt + delta; @@ -357,7 +357,7 @@ namespace agg m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; - int sx2 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Calculate scale by Y at x2,y2 dx = xt; @@ -365,7 +365,7 @@ namespace agg m_trans_inv.transform(&dx, &dy); dx -= x; dy -= y; - int sy2 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Initialize the interpolators m_coord_x = dda2_line_interpolator(x1, x2, len); @@ -388,10 +388,10 @@ namespace agg double xt = xe; double yt = ye; m_trans_dir.transform(&xt, &yt); - int x2 = int(xt * subpixel_size); - int y2 = int(yt * subpixel_size); + int x2 = iround(xt * subpixel_scale); + int y2 = iround(yt * subpixel_scale); - const double delta = 1/double(subpixel_size); + const double delta = 1/double(subpixel_scale); double dx; double dy; @@ -401,7 +401,7 @@ namespace agg m_trans_inv.transform(&dx, &dy); dx -= xe; dy -= ye; - int sx2 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Calculate scale by Y at x2,y2 dx = xt; @@ -409,7 +409,7 @@ namespace agg m_trans_inv.transform(&dx, &dy); dx -= xe; dy -= ye; - int sy2 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; // Initialize the interpolators m_coord_x = dda2_line_interpolator(x1, x2, len); diff --git a/agg/inc/agg_span_interpolator_trans.h b/agg/inc/agg_span_interpolator_trans.h index 5caaffe9e5c0..353be406fdc1 100755 --- a/agg/inc/agg_span_interpolator_trans.h +++ b/agg/inc/agg_span_interpolator_trans.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -31,10 +31,10 @@ namespace agg { public: typedef Transformer trans_type; - enum + enum subpixel_scale_e { subpixel_shift = SubpixelShift, - subpixel_size = 1 << subpixel_shift + subpixel_scale = 1 << subpixel_shift }; //-------------------------------------------------------------------- @@ -57,13 +57,8 @@ namespace agg m_x = x; m_y = y; m_trans->transform(&x, &y); - m_ix = int(x * subpixel_size); - m_iy = int(y * subpixel_size); - } - - //---------------------------------------------------------------- - void next(double, double, unsigned) - { + m_ix = iround(x * subpixel_scale); + m_iy = iround(y * subpixel_scale); } //---------------------------------------------------------------- @@ -73,8 +68,8 @@ namespace agg double x = m_x; double y = m_y; m_trans->transform(&x, &y); - m_ix = int(x * subpixel_size); - m_iy = int(y * subpixel_size); + m_ix = iround(x * subpixel_scale); + m_iy = iround(y * subpixel_scale); } //---------------------------------------------------------------- diff --git a/agg/inc/agg_span_pattern.h b/agg/inc/agg_span_pattern.h deleted file mode 100755 index b9e9b135ff84..000000000000 --- a/agg/inc/agg_span_pattern.h +++ /dev/null @@ -1,278 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Adaptation for high precision colors has been sponsored by -// Liberty Technology Systems, Inc., visit http://lib-sys.com -// -// Liberty Technology Systems, Inc. is the provider of -// PostScript and PDF technology for software developers. -// -//---------------------------------------------------------------------------- - - -#ifndef AGG_SPAN_PATTERN_INCLUDED -#define AGG_SPAN_PATTERN_INCLUDED - -#include "agg_basics.h" -#include "agg_rendering_buffer.h" -#include "agg_span_generator.h" - - -namespace agg -{ - - //---------------------------------------------------span_pattern_base - template<class ColorT, class Allocator> - class span_pattern_base : public span_generator<ColorT, Allocator> - { - public: - typedef ColorT color_type; - typedef typename ColorT::value_type value_type; - typedef Allocator alloc_type; - enum { base_mask = color_type::base_mask }; - - //---------------------------------------------------------------- - span_pattern_base(alloc_type& alloc) : - span_generator<color_type, alloc_type>(alloc) - {} - - //---------------------------------------------------------------- - span_pattern_base(alloc_type& alloc, - const rendering_buffer& src, - unsigned offset_x, unsigned offset_y, - double alpha) : - span_generator<color_type, alloc_type>(alloc), - m_src(&src), - m_offset_x(offset_x), - m_offset_y(offset_y), - m_alpha(value_type(alpha * double(base_mask))) - {} - - //---------------------------------------------------------------- - const rendering_buffer& source_image() const { return *m_src; } - unsigned offset_x() const { return m_offset_x; } - unsigned offset_y() const { return m_offset_y; } - double alpha() const { return m_alpha / double(base_mask); } - value_type alpha_int() const { return m_alpha; } - - //---------------------------------------------------------------- - void source_image(const rendering_buffer& v) { m_src = &v; } - void offset_x(unsigned v) { m_offset_x = v; } - void offset_y(unsigned v) { m_offset_y = v; } - void alpha(double v) { m_alpha = value_type(v * double(base_mask)); } - - //---------------------------------------------------------------- - private: - const rendering_buffer* m_src; - unsigned m_offset_x; - unsigned m_offset_y; - value_type m_alpha; - }; - - - //---------------------------------------------------wrap_mode_repeat - class wrap_mode_repeat - { - public: - wrap_mode_repeat(unsigned size) : - m_size(size), - m_add(size * (0x3FFFFFFF / size)), - m_value(0) - {} - - AGG_INLINE unsigned operator() (int v) - { - return m_value = (unsigned(v) + m_add) % m_size; - } - - AGG_INLINE unsigned operator++ () - { - ++m_value; - if(m_value >= m_size) m_value = 0; - return m_value; - } - private: - unsigned m_size; - unsigned m_add; - unsigned m_value; - }; - - - //---------------------------------------------wrap_mode_repeat_pow2 - class wrap_mode_repeat_pow2 - { - public: - wrap_mode_repeat_pow2(unsigned size) : m_value(0) - { - m_mask = 1; - while(m_mask < size) m_mask = (m_mask << 1) | 1; - m_mask >>= 1; - } - AGG_INLINE unsigned operator() (int v) - { - return m_value = unsigned(v) & m_mask; - } - AGG_INLINE unsigned operator++ () - { - ++m_value; - if(m_value > m_mask) m_value = 0; - return m_value; - } - private: - unsigned m_mask; - unsigned m_value; - }; - - - //----------------------------------------wrap_mode_repeat_auto_pow2 - class wrap_mode_repeat_auto_pow2 - { - public: - wrap_mode_repeat_auto_pow2(unsigned size) : - m_size(size), - m_add(size * (0x3FFFFFFF / size)), - m_mask((m_size & (m_size-1)) ? 0 : m_size-1), - m_value(0) - {} - - AGG_INLINE unsigned operator() (int v) - { - if(m_mask) return m_value = unsigned(v) & m_mask; - return m_value = (unsigned(v) + m_add) % m_size; - } - AGG_INLINE unsigned operator++ () - { - ++m_value; - if(m_value >= m_size) m_value = 0; - return m_value; - } - - private: - unsigned m_size; - unsigned m_add; - unsigned m_mask; - unsigned m_value; - }; - - - //--------------------------------------------------wrap_mode_reflect - class wrap_mode_reflect - { - public: - wrap_mode_reflect(unsigned size) : - m_size(size), - m_size2(size * 2), - m_add(m_size2 * (0x3FFFFFFF / m_size2)), - m_value(0) - {} - - AGG_INLINE unsigned operator() (int v) - { - m_value = (unsigned(v) + m_add) % m_size2; - if(m_value >= m_size) return m_size2 - m_value - 1; - return m_value; - } - - AGG_INLINE unsigned operator++ () - { - ++m_value; - if(m_value >= m_size2) m_value = 0; - if(m_value >= m_size) return m_size2 - m_value - 1; - return m_value; - } - private: - unsigned m_size; - unsigned m_size2; - unsigned m_add; - unsigned m_value; - }; - - - - //-------------------------------------------wrap_mode_reflect_pow2 - class wrap_mode_reflect_pow2 - { - public: - wrap_mode_reflect_pow2(unsigned size) : m_value(0) - { - m_mask = 1; - m_size = 1; - while(m_mask < size) - { - m_mask = (m_mask << 1) | 1; - m_size <<= 1; - } - } - AGG_INLINE unsigned operator() (int v) - { - m_value = unsigned(v) & m_mask; - if(m_value >= m_size) return m_mask - m_value; - return m_value; - } - AGG_INLINE unsigned operator++ () - { - ++m_value; - m_value &= m_mask; - if(m_value >= m_size) return m_mask - m_value; - return m_value; - } - private: - unsigned m_size; - unsigned m_mask; - unsigned m_value; - }; - - - - //---------------------------------------wrap_mode_reflect_auto_pow2 - class wrap_mode_reflect_auto_pow2 - { - public: - wrap_mode_reflect_auto_pow2(unsigned size) : - m_size(size), - m_size2(size * 2), - m_add(m_size2 * (0x3FFFFFFF / m_size2)), - m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1), - m_value(0) - {} - - AGG_INLINE unsigned operator() (int v) - { - m_value = m_mask ? unsigned(v) & m_mask : - (unsigned(v) + m_add) % m_size2; - if(m_value >= m_size) return m_size2 - m_value - 1; - return m_value; - } - AGG_INLINE unsigned operator++ () - { - ++m_value; - if(m_value >= m_size2) m_value = 0; - if(m_value >= m_size) return m_size2 - m_value - 1; - return m_value; - } - - private: - unsigned m_size; - unsigned m_size2; - unsigned m_add; - unsigned m_mask; - unsigned m_value; - }; - - -} - -#endif - diff --git a/agg/inc/agg_span_pattern_filter_gray.h b/agg/inc/agg_span_pattern_filter_gray.h deleted file mode 100755 index 17a7984be7fe..000000000000 --- a/agg/inc/agg_span_pattern_filter_gray.h +++ /dev/null @@ -1,472 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// classes span_pattern_filter_gray* -// -//---------------------------------------------------------------------------- -#ifndef AGG_SPAN_PATTERN_FILTER_GRAY_INCLUDED -#define AGG_SPAN_PATTERN_FILTER_GRAY_INCLUDED - -#include "agg_basics.h" -#include "agg_color_gray.h" -#include "agg_span_pattern.h" -#include "agg_span_image_filter.h" - - -namespace agg -{ - - //===========================================span_pattern_filter_gray - template<class ColorT, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_filter_gray_nn : - public span_image_filter<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - span_pattern_filter_gray_nn(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_filter_gray_nn(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter) : - base_type(alloc, src, color_type(0,0), inter, 0), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //-------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - color_type* span = base_type::allocator().span(); - do - { - base_type::interpolator().coordinates(&x, &y); - - x = m_wrap_mode_x(x >> image_subpixel_shift); - y = m_wrap_mode_y(y >> image_subpixel_shift); - - span->v = *((value_type*)base_type::source_image().row(y) + x); - span->a = base_mask; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - - - - - - //====================================span_pattern_filter_gray_bilinear - template<class ColorT, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_filter_gray_bilinear : - public span_image_filter<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - span_pattern_filter_gray_bilinear(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_filter_gray_bilinear(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter) : - base_type(alloc, src, color_type(0,0), inter, 0), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - calc_type fg; - color_type* span = base_type::allocator().span(); - do - { - int x_hr; - int y_hr; - - base_type::interpolator().coordinates(&x_hr, &y_hr); - - x_hr -= base_type::filter_dx_int(); - y_hr -= base_type::filter_dy_int(); - - int x_lr = x_hr >> image_subpixel_shift; - int y_lr = y_hr >> image_subpixel_shift; - - unsigned x1 = m_wrap_mode_x(x_lr); - unsigned x2 = ++m_wrap_mode_x; - - unsigned y1 = m_wrap_mode_y(y_lr); - unsigned y2 = ++m_wrap_mode_y; - const value_type* ptr1 = (value_type*)base_type::source_image().row(y1); - const value_type* ptr2 = (value_type*)base_type::source_image().row(y2); - - fg = image_subpixel_size * image_subpixel_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - - fg += ptr1[x1] * (image_subpixel_size - x_hr) * (image_subpixel_size - y_hr); - fg += ptr1[x2] * x_hr * (image_subpixel_size - y_hr); - fg += ptr2[x1] * (image_subpixel_size - x_hr) * y_hr; - fg += ptr2[x2] * x_hr * y_hr; - - span->v = (value_type)(fg >> image_subpixel_shift * 2); - span->a = base_mask; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - - - - - - - - - //====================================span_pattern_filter_gray_2x2 - template<class ColorT, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_filter_gray_2x2 : - public span_image_filter<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - span_pattern_filter_gray_2x2(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_filter_gray_2x2(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, color_type(0,0), inter, &filter), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - calc_type fg; - color_type* span = base_type::allocator().span(); - const int16* weight_array = base_type::filter().weight_array() + - ((base_type::filter().diameter()/2 - 1) << - image_subpixel_shift); - do - { - int x_hr; - int y_hr; - - base_type::interpolator().coordinates(&x_hr, &y_hr); - - x_hr -= base_type::filter_dx_int(); - y_hr -= base_type::filter_dy_int(); - - int x_lr = x_hr >> image_subpixel_shift; - int y_lr = y_hr >> image_subpixel_shift; - - unsigned x1 = m_wrap_mode_x(x_lr); - unsigned x2 = ++m_wrap_mode_x; - - unsigned y1 = m_wrap_mode_y(y_lr); - unsigned y2 = ++m_wrap_mode_y; - const value_type* ptr1 = (value_type*)base_type::source_image().row(y1); - const value_type* ptr2 = (value_type*)base_type::source_image().row(y2); - - fg = image_filter_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - - fg += ptr1[x1] * ((weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift); - fg += ptr1[x2] * ((weight_array[x_hr] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift); - fg += ptr2[x1] * ((weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift); - fg += ptr2[x2] * ((weight_array[x_hr] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift); - - fg >>= image_filter_shift; - if(fg > base_mask) fg = base_mask; - - span->v = (value_type)fg; - span->a = base_mask; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - - - - - - - - - - - - //==============================================span_pattern_filter_gray - template<class ColorT, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_filter_gray : - public span_image_filter<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - span_pattern_filter_gray(alloc_type& alloc) : - base_type(alloc) - {} - - //-------------------------------------------------------------------- - span_pattern_filter_gray(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, color_type(0,0), inter, &filter), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //-------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - int fg; - - unsigned diameter = base_type::filter().diameter(); - int start = base_type::filter().start(); - const int16* weight_array = base_type::filter().weight_array(); - - color_type* span = base_type::allocator().span(); - - int x_count; - int weight_y; - - do - { - base_type::interpolator().coordinates(&x, &y); - - x -= base_type::filter_dx_int(); - y -= base_type::filter_dy_int(); - - int x_hr = x; - int y_hr = y; - - int x_fract = x_hr & image_subpixel_mask; - unsigned y_count = diameter; - - int y_lr = m_wrap_mode_y((y >> image_subpixel_shift) + start); - int x_int = (x >> image_subpixel_shift) + start; - int x_lr; - - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); - fg = image_filter_size / 2; - - do - { - x_count = diameter; - weight_y = weight_array[y_hr]; - x_hr = image_subpixel_mask - x_fract; - x_lr = m_wrap_mode_x(x_int); - const value_type* row_ptr = (value_type*)base_type::source_image().row(y_lr); - do - { - fg += row_ptr[x_lr] * ((weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift); - x_hr += image_subpixel_size; - x_lr = ++m_wrap_mode_x; - } while(--x_count); - - y_hr += image_subpixel_size; - y_lr = ++m_wrap_mode_y; - } while(--y_count); - - fg >>= image_filter_shift; - - if(fg < 0) fg = 0; - if(fg > base_mask) fg = base_mask; - - span->v = fg; - span->a = base_mask; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - -} - - -#endif - - - diff --git a/agg/inc/agg_span_pattern_filter_rgb.h b/agg/inc/agg_span_pattern_filter_rgb.h deleted file mode 100755 index d4dc1c1797eb..000000000000 --- a/agg/inc/agg_span_pattern_filter_rgb.h +++ /dev/null @@ -1,568 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Adaptation for high precision colors has been sponsored by -// Liberty Technology Systems, Inc., visit http://lib-sys.com -// -// Liberty Technology Systems, Inc. is the provider of -// PostScript and PDF technology for software developers. -// -//---------------------------------------------------------------------------- -// -// classes span_pattern_filter_rgb* -// -//---------------------------------------------------------------------------- -#ifndef AGG_SPAN_PATTERN_FILTER_RGB_INCLUDED -#define AGG_SPAN_PATTERN_FILTER_RGB_INCLUDED - -#include "agg_basics.h" -#include "agg_color_rgba.h" -#include "agg_span_pattern.h" -#include "agg_span_image_filter.h" - - -namespace agg -{ - - //===========================================span_pattern_filter_rgb - template<class ColorT, - class Order, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_filter_rgb_nn : - public span_image_filter<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - span_pattern_filter_rgb_nn(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_filter_rgb_nn(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& intr) : - base_type(alloc, src, color_type(0,0,0,0), intr, 0), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //-------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - interpolator_type& intr = base_type::interpolator(); - intr.begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - const value_type *fg_ptr; - do - { - intr.coordinates(&x, &y); - - x = m_wrap_mode_x(x >> image_subpixel_shift); - y = m_wrap_mode_y(y >> image_subpixel_shift); - - fg_ptr = (const value_type*)base_type::source_image().row(y) + x * 3; - span->r = fg_ptr[order_type::R]; - span->g = fg_ptr[order_type::G]; - span->b = fg_ptr[order_type::B]; - span->a = base_mask; - ++span; - ++intr; - - } while(--len); - return base_type::allocator().span(); - } - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - - - - - - - - - - //=====================================span_pattern_filter_rgb_bilinear - template<class ColorT, - class Order, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_filter_rgb_bilinear : - public span_image_filter<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - span_pattern_filter_rgb_bilinear(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_filter_rgb_bilinear(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& intr) : - base_type(alloc, src, color_type(0,0,0,0), intr, 0), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - interpolator_type& intr = base_type::interpolator(); - intr.begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - calc_type fg[3]; - const value_type *fg_ptr; - - do - { - int x_hr; - int y_hr; - - intr.coordinates(&x_hr, &y_hr); - - x_hr -= base_type::filter_dx_int(); - y_hr -= base_type::filter_dy_int(); - - int x_lr = x_hr >> image_subpixel_shift; - int y_lr = y_hr >> image_subpixel_shift; - - unsigned x1 = m_wrap_mode_x(x_lr); - unsigned x2 = ++m_wrap_mode_x; - x1 *= 3; - x2 *= 3; - - unsigned y1 = m_wrap_mode_y(y_lr); - unsigned y2 = ++m_wrap_mode_y; - const value_type* ptr1 = (const value_type*)base_type::source_image().row(y1); - const value_type* ptr2 = (const value_type*)base_type::source_image().row(y2); - - fg[0] = - fg[1] = - fg[2] = image_subpixel_size * image_subpixel_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - - int weight; - fg_ptr = ptr1 + x1; - weight = (image_subpixel_size - x_hr) * - (image_subpixel_size - y_hr); - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - - fg_ptr = ptr1 + x2; - weight = x_hr * (image_subpixel_size - y_hr); - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - - fg_ptr = ptr2 + x1; - weight = (image_subpixel_size - x_hr) * y_hr; - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - - fg_ptr = ptr2 + x2; - weight = x_hr * y_hr; - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - - span->r = (value_type)(fg[order_type::R] >> image_subpixel_shift * 2); - span->g = (value_type)(fg[order_type::G] >> image_subpixel_shift * 2); - span->b = (value_type)(fg[order_type::B] >> image_subpixel_shift * 2); - span->a = base_mask; - ++span; - ++intr; - } while(--len); - - return base_type::allocator().span(); - } - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - - - - - - - //=====================================span_pattern_filter_rgb_2x2 - template<class ColorT, - class Order, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_filter_rgb_2x2 : - public span_image_filter<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - span_pattern_filter_rgb_2x2(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_filter_rgb_2x2(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& intr, - const image_filter_lut& filter) : - base_type(alloc, src, color_type(0,0,0,0), intr, &filter), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - interpolator_type& intr = base_type::interpolator(); - intr.begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - calc_type fg[3]; - const value_type *fg_ptr; - const int16* weight_array = base_type::filter().weight_array() + - ((base_type::filter().diameter()/2 - 1) << - image_subpixel_shift); - do - { - int x_hr; - int y_hr; - - intr.coordinates(&x_hr, &y_hr); - - x_hr -= base_type::filter_dx_int(); - y_hr -= base_type::filter_dy_int(); - - int x_lr = x_hr >> image_subpixel_shift; - int y_lr = y_hr >> image_subpixel_shift; - - unsigned x1 = m_wrap_mode_x(x_lr); - unsigned x2 = ++m_wrap_mode_x; - x1 *= 3; - x2 *= 3; - - unsigned y1 = m_wrap_mode_y(y_lr); - unsigned y2 = ++m_wrap_mode_y; - const value_type* ptr1 = (const value_type*)base_type::source_image().row(y1); - const value_type* ptr2 = (const value_type*)base_type::source_image().row(y2); - - fg[0] = fg[1] = fg[2] = image_filter_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - - int weight; - fg_ptr = ptr1 + x1; - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - - fg_ptr = ptr1 + x2; - weight = (weight_array[x_hr] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - - fg_ptr = ptr2 + x1; - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - - fg_ptr = ptr2 + x2; - weight = (weight_array[x_hr] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - - if(fg[0] > base_mask) fg[0] = base_mask; - if(fg[1] > base_mask) fg[1] = base_mask; - if(fg[2] > base_mask) fg[2] = base_mask; - - span->r = (value_type)fg[order_type::R]; - span->g = (value_type)fg[order_type::G]; - span->b = (value_type)fg[order_type::B]; - span->a = base_mask; - ++span; - ++intr; - } while(--len); - - return base_type::allocator().span(); - } - - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - - - - - - - - - - //==============================================span_pattern_filter_rgb - template<class ColorT, - class Order, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_filter_rgb : - public span_image_filter<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - span_pattern_filter_rgb(alloc_type& alloc) : - base_type(alloc) - {} - - //-------------------------------------------------------------------- - span_pattern_filter_rgb(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& intr, - const image_filter_lut& filter) : - base_type(alloc, src, color_type(0,0,0,0), intr, &filter), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //-------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - interpolator_type& intr = base_type::interpolator(); - intr.begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - int fg[3]; - - unsigned diameter = base_type::filter().diameter(); - int start = base_type::filter().start(); - const int16* weight_array = base_type::filter().weight_array(); - - int x_count; - int weight_y; - - do - { - intr.coordinates(&x, &y); - - x -= base_type::filter_dx_int(); - y -= base_type::filter_dy_int(); - - int x_hr = x; - int y_hr = y; - - int x_fract = x_hr & image_subpixel_mask; - unsigned y_count = diameter; - - int y_lr = m_wrap_mode_y((y >> image_subpixel_shift) + start); - int x_int = (x >> image_subpixel_shift) + start; - int x_lr; - - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); - fg[0] = fg[1] = fg[2] = image_filter_size / 2; - - do - { - x_count = diameter; - weight_y = weight_array[y_hr]; - x_hr = image_subpixel_mask - x_fract; - x_lr = m_wrap_mode_x(x_int); - const value_type* row_ptr = (const value_type*)base_type::source_image().row(y_lr); - do - { - const value_type* fg_ptr = row_ptr + x_lr * 3; - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift; - - fg[0] += fg_ptr[0] * weight; - fg[1] += fg_ptr[1] * weight; - fg[2] += fg_ptr[2] * weight; - - x_hr += image_subpixel_size; - x_lr = ++m_wrap_mode_x; - } while(--x_count); - - y_hr += image_subpixel_size; - y_lr = ++m_wrap_mode_y; - } while(--y_count); - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - - if(fg[0] > base_mask) fg[0] = base_mask; - if(fg[1] > base_mask) fg[1] = base_mask; - if(fg[2] > base_mask) fg[2] = base_mask; - - span->r = (value_type)fg[order_type::R]; - span->g = (value_type)fg[order_type::G]; - span->b = (value_type)fg[order_type::B]; - span->a = base_mask; - ++span; - ++intr; - } while(--len); - - return base_type::allocator().span(); - } - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - -} - - -#endif - - - diff --git a/agg/inc/agg_span_pattern_filter_rgba.h b/agg/inc/agg_span_pattern_filter_rgba.h deleted file mode 100755 index 8460880fdb79..000000000000 --- a/agg/inc/agg_span_pattern_filter_rgba.h +++ /dev/null @@ -1,584 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Adaptation for high precision colors has been sponsored by -// Liberty Technology Systems, Inc., visit http://lib-sys.com -// -// Liberty Technology Systems, Inc. is the provider of -// PostScript and PDF technology for software developers. -// -//---------------------------------------------------------------------------- -// -// classes span_pattern_filter_rgba* -// -//---------------------------------------------------------------------------- -#ifndef AGG_SPAN_PATTERN_FILTER_RGBA_INCLUDED -#define AGG_SPAN_PATTERN_FILTER_RGBA_INCLUDED - -#include "agg_basics.h" -#include "agg_color_rgba.h" -#include "agg_span_pattern.h" -#include "agg_span_image_filter.h" - - -namespace agg -{ - - //===========================================span_pattern_filter_rgba - template<class ColorT, - class Order, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_filter_rgba_nn : - public span_image_filter<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - span_pattern_filter_rgba_nn(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_filter_rgba_nn(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter) : - base_type(alloc, src, color_type(0,0,0,0), inter, 0), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //-------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - const value_type *fg_ptr; - color_type* span = base_type::allocator().span(); - do - { - base_type::interpolator().coordinates(&x, &y); - - x = m_wrap_mode_x(x >> image_subpixel_shift); - y = m_wrap_mode_y(y >> image_subpixel_shift); - - fg_ptr = (value_type*)base_type::source_image().row(y) + (x << 2); - span->r = fg_ptr[order_type::R]; - span->g = fg_ptr[order_type::G]; - span->b = fg_ptr[order_type::B]; - span->a = fg_ptr[order_type::A]; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - - - - - - - - - - //=====================================span_pattern_filter_rgba_bilinear - template<class ColorT, - class Order, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_filter_rgba_bilinear : - public span_image_filter<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - span_pattern_filter_rgba_bilinear(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_filter_rgba_bilinear(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter) : - base_type(alloc, src, color_type(0,0,0,0), inter, 0), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - calc_type fg[4]; - const value_type *fg_ptr; - color_type* span = base_type::allocator().span(); - - do - { - int x_hr; - int y_hr; - - base_type::interpolator().coordinates(&x_hr, &y_hr); - - x_hr -= base_type::filter_dx_int(); - y_hr -= base_type::filter_dy_int(); - - int x_lr = x_hr >> image_subpixel_shift; - int y_lr = y_hr >> image_subpixel_shift; - - unsigned x1 = m_wrap_mode_x(x_lr); - unsigned x2 = ++m_wrap_mode_x; - x1 <<= 2; - x2 <<= 2; - - unsigned y1 = m_wrap_mode_y(y_lr); - unsigned y2 = ++m_wrap_mode_y; - const value_type* ptr1 = (value_type*)base_type::source_image().row(y1); - const value_type* ptr2 = (value_type*)base_type::source_image().row(y2); - - fg[0] = - fg[1] = - fg[2] = - fg[3] = image_subpixel_size * image_subpixel_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - - int weight; - fg_ptr = ptr1 + x1; - weight = (image_subpixel_size - x_hr) * - (image_subpixel_size - y_hr); - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - fg[3] += weight * fg_ptr[3]; - - fg_ptr = ptr1 + x2; - weight = x_hr * (image_subpixel_size - y_hr); - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - fg[3] += weight * fg_ptr[3]; - - fg_ptr = ptr2 + x1; - weight = (image_subpixel_size - x_hr) * y_hr; - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - fg[3] += weight * fg_ptr[3]; - - fg_ptr = ptr2 + x2; - weight = x_hr * y_hr; - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - fg[3] += weight * fg_ptr[3]; - - span->r = (value_type)(fg[order_type::R] >> image_subpixel_shift * 2); - span->g = (value_type)(fg[order_type::G] >> image_subpixel_shift * 2); - span->b = (value_type)(fg[order_type::B] >> image_subpixel_shift * 2); - span->a = (value_type)(fg[order_type::A] >> image_subpixel_shift * 2); - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - - - - - - - - //=====================================span_pattern_filter_rgba_2x2 - template<class ColorT, - class Order, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_filter_rgba_2x2 : - public span_image_filter<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - span_pattern_filter_rgba_2x2(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_filter_rgba_2x2(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, color_type(0,0,0,0), inter, &filter), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - calc_type fg[4]; - const value_type *fg_ptr; - color_type* span = base_type::allocator().span(); - const int16* weight_array = base_type::filter().weight_array() + - ((base_type::filter().diameter()/2 - 1) << - image_subpixel_shift); - do - { - int x_hr; - int y_hr; - - base_type::interpolator().coordinates(&x_hr, &y_hr); - - x_hr -= base_type::filter_dx_int(); - y_hr -= base_type::filter_dy_int(); - - int x_lr = x_hr >> image_subpixel_shift; - int y_lr = y_hr >> image_subpixel_shift; - - unsigned x1 = m_wrap_mode_x(x_lr); - unsigned x2 = ++m_wrap_mode_x; - x1 <<= 2; - x2 <<= 2; - - unsigned y1 = m_wrap_mode_y(y_lr); - unsigned y2 = ++m_wrap_mode_y; - const value_type* ptr1 = (value_type*)base_type::source_image().row(y1); - const value_type* ptr2 = (value_type*)base_type::source_image().row(y2); - - fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2; - - x_hr &= image_subpixel_mask; - y_hr &= image_subpixel_mask; - - int weight; - fg_ptr = ptr1 + x1; - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - fg[3] += weight * fg_ptr[3]; - - fg_ptr = ptr1 + x2; - weight = (weight_array[x_hr] * - weight_array[y_hr + image_subpixel_size] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - fg[3] += weight * fg_ptr[3]; - - fg_ptr = ptr2 + x1; - weight = (weight_array[x_hr + image_subpixel_size] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - fg[3] += weight * fg_ptr[3]; - - fg_ptr = ptr2 + x2; - weight = (weight_array[x_hr] * - weight_array[y_hr] + - image_filter_size / 2) >> - image_filter_shift; - fg[0] += weight * fg_ptr[0]; - fg[1] += weight * fg_ptr[1]; - fg[2] += weight * fg_ptr[2]; - fg[3] += weight * fg_ptr[3]; - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - fg[3] >>= image_filter_shift; - - if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; - if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; - if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; - if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; - - span->r = (value_type)fg[order_type::R]; - span->g = (value_type)fg[order_type::G]; - span->b = (value_type)fg[order_type::B]; - span->a = (value_type)fg[order_type::A]; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - - - - - - - - - - - - //==============================================span_pattern_filter_rgba - template<class ColorT, - class Order, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_filter_rgba : - public span_image_filter<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_filter<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - span_pattern_filter_rgba(alloc_type& alloc) : - base_type(alloc) - {} - - //-------------------------------------------------------------------- - span_pattern_filter_rgba(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, color_type(0,0,0,0), inter, &filter), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //-------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - base_type::interpolator().begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - int fg[4]; - - unsigned diameter = base_type::filter().diameter(); - int start = base_type::filter().start(); - const int16* weight_array = base_type::filter().weight_array(); - - color_type* span = base_type::allocator().span(); - - int x_count; - int weight_y; - - do - { - base_type::interpolator().coordinates(&x, &y); - - x -= base_type::filter_dx_int(); - y -= base_type::filter_dy_int(); - - int x_hr = x; - int y_hr = y; - - int x_fract = x_hr & image_subpixel_mask; - unsigned y_count = diameter; - - int y_lr = m_wrap_mode_y((y >> image_subpixel_shift) + start); - int x_int = (x >> image_subpixel_shift) + start; - int x_lr; - - y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); - fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2; - - do - { - x_count = diameter; - weight_y = weight_array[y_hr]; - x_hr = image_subpixel_mask - x_fract; - x_lr = m_wrap_mode_x(x_int); - const value_type* row_ptr = (value_type*)base_type::source_image().row(y_lr); - do - { - const value_type* fg_ptr = row_ptr + (x_lr << 2); - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - image_filter_shift; - - fg[0] += fg_ptr[0] * weight; - fg[1] += fg_ptr[1] * weight; - fg[2] += fg_ptr[2] * weight; - fg[3] += fg_ptr[3] * weight; - - x_hr += image_subpixel_size; - x_lr = ++m_wrap_mode_x; - } while(--x_count); - - y_hr += image_subpixel_size; - y_lr = ++m_wrap_mode_y; - } while(--y_count); - - fg[0] >>= image_filter_shift; - fg[1] >>= image_filter_shift; - fg[2] >>= image_filter_shift; - fg[3] >>= image_filter_shift; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; - - if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; - if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; - if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; - if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; - - span->r = fg[order_type::R]; - span->g = fg[order_type::G]; - span->b = fg[order_type::B]; - span->a = fg[order_type::A]; - ++span; - ++base_type::interpolator(); - - } while(--len); - - return base_type::allocator().span(); - } - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - -} - - -#endif - - - diff --git a/agg/inc/agg_span_pattern_gray.h b/agg/inc/agg_span_pattern_gray.h new file mode 100644 index 000000000000..d0254ef3e122 --- /dev/null +++ b/agg/inc/agg_span_pattern_gray.h @@ -0,0 +1,93 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + + +#ifndef AGG_SPAN_PATTERN_GRAY_INCLUDED +#define AGG_SPAN_PATTERN_GRAY_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //=======================================================span_pattern_gray + template<class Source> class span_pattern_gray + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + //-------------------------------------------------------------------- + span_pattern_gray() {} + span_pattern_gray(source_type& src, + unsigned offset_x, unsigned offset_y) : + m_src(&src), + m_offset_x(offset_x), + m_offset_y(offset_y), + m_alpha(color_type::base_mask) + {} + + //-------------------------------------------------------------------- + void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } + void offset_y(unsigned v) { m_offset_y = v; } + unsigned offset_x() const { return m_offset_x; } + unsigned offset_y() const { return m_offset_y; } + void alpha(value_type v) { m_alpha = v; } + value_type alpha() const { return m_alpha; } + + //-------------------------------------------------------------------- + void prepare() {} + void generate(color_type* span, int x, int y, unsigned len) + { + x += m_offset_x; + y += m_offset_y; + const value_type* p = (const value_type*)m_src->span(x, y, len); + do + { + span->v = *p; + span->a = m_alpha; + p = m_src->next_x(); + ++span; + } + while(--len); + } + + private: + source_type* m_src; + unsigned m_offset_x; + unsigned m_offset_y; + value_type m_alpha; + + }; + +} + +#endif + diff --git a/agg/inc/agg_span_pattern_resample_gray.h b/agg/inc/agg_span_pattern_resample_gray.h deleted file mode 100755 index 212209502f5f..000000000000 --- a/agg/inc/agg_span_pattern_resample_gray.h +++ /dev/null @@ -1,320 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_PATTERN_RESAMPLE_GRAY_INCLUDED -#define AGG_SPAN_PATTERN_RESAMPLE_GRAY_INCLUDED - -#include "agg_color_gray.h" -#include "agg_span_image_resample.h" - -namespace agg -{ - - //=======================================span_pattern_resample_gray_affine - template<class ColorT, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_resample_gray_affine : - public span_image_resample_affine<ColorT, Allocator> - { - public: - typedef ColorT color_type; - typedef Allocator alloc_type; - typedef span_image_resample_affine<color_type, alloc_type> base_type; - typedef typename base_type::interpolator_type interpolator_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::long_type long_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask, - downscale_shift = image_filter_shift - }; - - //-------------------------------------------------------------------- - span_pattern_resample_gray_affine(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_resample_gray_affine(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, color_type(0,0), inter, filter), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //-------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - interpolator_type& intr = base_type::interpolator(); - intr.begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - long_type fg; - - int diameter = base_type::filter().diameter(); - int filter_size = diameter << image_subpixel_shift; - int radius_x = (diameter * base_type::m_rx) >> 1; - int radius_y = (diameter * base_type::m_ry) >> 1; - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - const int16* weight_array = base_type::filter().weight_array(); - - do - { - intr.coordinates(&x, &y); - - x += base_type::filter_dx_int() - radius_x; - y += base_type::filter_dy_int() - radius_y; - - fg = image_filter_size / 2; - - int y_lr = m_wrap_mode_y(y >> image_subpixel_shift); - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - base_type::m_ry_inv) >> - image_subpixel_shift; - int total_weight = 0; - int x_lr_ini = x >> image_subpixel_shift; - int x_hr_ini = ((image_subpixel_mask - (x & image_subpixel_mask)) * - base_type::m_rx_inv) >> - image_subpixel_shift; - do - { - int weight_y = weight_array[y_hr]; - int x_lr = m_wrap_mode_x(x_lr_ini); - int x_hr = x_hr_ini; - const value_type* row_ptr = (const value_type*)base_type::source_image().row(y_lr); - do - { - const value_type* fg_ptr = row_ptr + x_lr; - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - fg += *fg_ptr * weight; - total_weight += weight; - x_hr += base_type::m_rx_inv; - x_lr = ++m_wrap_mode_x; - } - while(x_hr < filter_size); - - y_hr += base_type::m_ry_inv; - y_lr = ++m_wrap_mode_y; - } while(y_hr < filter_size); - - fg /= total_weight; - - if(fg < 0) fg = 0; - if(fg > base_mask) fg = base_mask; - - span->v = (value_type)fg; - span->a = (value_type)base_mask; - - ++span; - ++intr; - } while(--len); - return base_type::allocator().span(); - } - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - - - - - - - //============================================span_pattern_resample_gray - template<class ColorT, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_resample_gray : - public span_image_resample<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_resample<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::long_type long_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask, - downscale_shift = image_filter_shift - }; - - //-------------------------------------------------------------------- - span_pattern_resample_gray(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_resample_gray(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, color_type(0,0), inter, filter), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //-------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - interpolator_type& intr = base_type::interpolator(); - intr.begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - long_type fg; - - int diameter = base_type::filter().diameter(); - int filter_size = diameter << image_subpixel_shift; - const int16* weight_array = base_type::filter().weight_array(); - - do - { - int rx; - int ry; - int rx_inv = image_subpixel_size; - int ry_inv = image_subpixel_size; - intr.coordinates(&x, &y); - intr.local_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_size) - { - rx = image_subpixel_size; - } - else - { - if(rx > image_subpixel_size * base_type::m_scale_limit) - { - rx = image_subpixel_size * base_type::m_scale_limit; - } - rx_inv = image_subpixel_size * image_subpixel_size / rx; - } - - if(ry < image_subpixel_size) - { - ry = image_subpixel_size; - } - else - { - if(ry > image_subpixel_size * base_type::m_scale_limit) - { - ry = image_subpixel_size * base_type::m_scale_limit; - } - ry_inv = image_subpixel_size * image_subpixel_size / ry; - } - - int radius_x = (diameter * rx) >> 1; - int radius_y = (diameter * ry) >> 1; - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - x += base_type::filter_dx_int() - radius_x; - y += base_type::filter_dy_int() - radius_y; - - fg = image_filter_size / 2; - - int y_lr = m_wrap_mode_y(y >> image_subpixel_shift); - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - ry_inv) >> - image_subpixel_shift; - int total_weight = 0; - int x_lr_ini = x >> image_subpixel_shift; - int x_hr_ini = ((image_subpixel_mask - (x & image_subpixel_mask)) * - rx_inv) >> - image_subpixel_shift; - - do - { - int weight_y = weight_array[y_hr]; - int x_lr = m_wrap_mode_x(x_lr_ini); - int x_hr = x_hr_ini; - const value_type* row_ptr = (const value_type*)base_type::source_image().row(y_lr); - do - { - const value_type* fg_ptr = row_ptr + x_lr; - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - fg += *fg_ptr * weight; - total_weight += weight; - x_hr += rx_inv; - x_lr = ++m_wrap_mode_x; - } - while(x_hr < filter_size); - y_hr += ry_inv; - y_lr = ++m_wrap_mode_y; - } - while(y_hr < filter_size); - - fg /= total_weight; - - if(fg < 0) fg = 0; - if(fg > base_mask) fg = base_mask; - - span->v = (value_type)fg; - span->a = (value_type)base_mask; - - ++span; - ++intr; - } while(--len); - return base_type::allocator().span(); - } - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - -} - - -#endif diff --git a/agg/inc/agg_span_pattern_resample_rgb.h b/agg/inc/agg_span_pattern_resample_rgb.h deleted file mode 100755 index baef860eb472..000000000000 --- a/agg/inc/agg_span_pattern_resample_rgb.h +++ /dev/null @@ -1,346 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_PATTERN_RESAMPLE_RGB_INCLUDED -#define AGG_SPAN_PATTERN_RESAMPLE_RGB_INCLUDED - -#include "agg_color_rgba.h" -#include "agg_span_image_resample.h" - -namespace agg -{ - - //========================================span_pattern_resample_rgb_affine - template<class ColorT, - class Order, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_resample_rgb_affine : - public span_image_resample_affine<ColorT, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Allocator alloc_type; - typedef span_image_resample_affine<color_type, alloc_type> base_type; - typedef typename base_type::interpolator_type interpolator_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::long_type long_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask, - downscale_shift = image_filter_shift - }; - - //-------------------------------------------------------------------- - span_pattern_resample_rgb_affine(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_resample_rgb_affine(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter, - const image_filter_lut& filter_) : - base_type(alloc, src, color_type(0,0,0,0), inter, filter_), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //-------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - interpolator_type& intr = base_type::interpolator(); - intr.begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - long_type fg[3]; - - int diameter = base_type::filter().diameter(); - int filter_size = diameter << image_subpixel_shift; - int radius_x = (diameter * base_type::m_rx) >> 1; - int radius_y = (diameter * base_type::m_ry) >> 1; - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - const int16* weight_array = base_type::filter().weight_array(); - - do - { - intr.coordinates(&x, &y); - - x += base_type::filter_dx_int() - radius_x; - y += base_type::filter_dy_int() - radius_y; - - fg[0] = fg[1] = fg[2] = image_filter_size / 2; - - int y_lr = m_wrap_mode_y(y >> image_subpixel_shift); - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - base_type::m_ry_inv) >> - image_subpixel_shift; - int total_weight = 0; - int x_lr_ini = x >> image_subpixel_shift; - int x_hr_ini = ((image_subpixel_mask - (x & image_subpixel_mask)) * - base_type::m_rx_inv) >> - image_subpixel_shift; - do - { - int weight_y = weight_array[y_hr]; - int x_lr = m_wrap_mode_x(x_lr_ini); - int x_hr = x_hr_ini; - const value_type* row_ptr = (const value_type*)base_type::source_image().row(y_lr); - do - { - const value_type* fg_ptr = row_ptr + x_lr * 3; - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - fg[0] += fg_ptr[0] * weight; - fg[1] += fg_ptr[1] * weight; - fg[2] += fg_ptr[2] * weight; - total_weight += weight; - x_hr += base_type::m_rx_inv; - x_lr = ++m_wrap_mode_x; - } - while(x_hr < filter_size); - - y_hr += base_type::m_ry_inv; - y_lr = ++m_wrap_mode_y; - } while(y_hr < filter_size); - - fg[0] /= total_weight; - fg[1] /= total_weight; - fg[2] /= total_weight; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - - if(fg[0] > base_mask) fg[0] = base_mask; - if(fg[1] > base_mask) fg[1] = base_mask; - if(fg[2] > base_mask) fg[2] = base_mask; - - span->r = (value_type)fg[order_type::R]; - span->g = (value_type)fg[order_type::G]; - span->b = (value_type)fg[order_type::B]; - span->a = (value_type)base_mask; - - ++span; - ++intr; - } while(--len); - return base_type::allocator().span(); - } - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - - - - - - - //=============================================span_pattern_resample_rgb - template<class ColorT, - class Order, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_resample_rgb : - public span_image_resample<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_resample<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::long_type long_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask, - downscale_shift = image_filter_shift - }; - - //-------------------------------------------------------------------- - span_pattern_resample_rgb(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_resample_rgb(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, color_type(0,0,0,0), inter, filter), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //-------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - interpolator_type& intr = base_type::interpolator(); - intr.begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - long_type fg[3]; - - int diameter = base_type::filter().diameter(); - int filter_size = diameter << image_subpixel_shift; - const int16* weight_array = base_type::filter().weight_array(); - - do - { - int rx; - int ry; - int rx_inv = image_subpixel_size; - int ry_inv = image_subpixel_size; - intr.coordinates(&x, &y); - intr.local_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_size) - { - rx = image_subpixel_size; - } - else - { - if(rx > image_subpixel_size * base_type::m_scale_limit) - { - rx = image_subpixel_size * base_type::m_scale_limit; - } - rx_inv = image_subpixel_size * image_subpixel_size / rx; - } - - if(ry < image_subpixel_size) - { - ry = image_subpixel_size; - } - else - { - if(ry > image_subpixel_size * base_type::m_scale_limit) - { - ry = image_subpixel_size * base_type::m_scale_limit; - } - ry_inv = image_subpixel_size * image_subpixel_size / ry; - } - - int radius_x = (diameter * rx) >> 1; - int radius_y = (diameter * ry) >> 1; - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - x += base_type::filter_dx_int() - radius_x; - y += base_type::filter_dy_int() - radius_y; - - fg[0] = fg[1] = fg[2] = image_filter_size / 2; - - int y_lr = m_wrap_mode_y(y >> image_subpixel_shift); - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - ry_inv) >> - image_subpixel_shift; - int total_weight = 0; - int x_lr_ini = x >> image_subpixel_shift; - int x_hr_ini = ((image_subpixel_mask - (x & image_subpixel_mask)) * - rx_inv) >> - image_subpixel_shift; - - do - { - int weight_y = weight_array[y_hr]; - int x_lr = m_wrap_mode_x(x_lr_ini); - int x_hr = x_hr_ini; - const value_type* row_ptr = (const value_type*)base_type::source_image().row(y_lr); - do - { - const value_type* fg_ptr = row_ptr + x_lr * 3; - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - fg[0] += fg_ptr[0] * weight; - fg[1] += fg_ptr[1] * weight; - fg[2] += fg_ptr[2] * weight; - total_weight += weight; - x_hr += rx_inv; - x_lr = ++m_wrap_mode_x; - } - while(x_hr < filter_size); - y_hr += ry_inv; - y_lr = ++m_wrap_mode_y; - } - while(y_hr < filter_size); - - fg[0] /= total_weight; - fg[1] /= total_weight; - fg[2] /= total_weight; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - - if(fg[0] > base_mask) fg[0] = base_mask; - if(fg[1] > base_mask) fg[1] = base_mask; - if(fg[2] > base_mask) fg[2] = base_mask; - - span->r = (value_type)fg[order_type::R]; - span->g = (value_type)fg[order_type::G]; - span->b = (value_type)fg[order_type::B]; - span->a = (value_type)base_mask; - - ++span; - ++intr; - } while(--len); - return base_type::allocator().span(); - } - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - -} - - -#endif diff --git a/agg/inc/agg_span_pattern_resample_rgba.h b/agg/inc/agg_span_pattern_resample_rgba.h deleted file mode 100755 index 37b4dade16f4..000000000000 --- a/agg/inc/agg_span_pattern_resample_rgba.h +++ /dev/null @@ -1,354 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- - -#ifndef AGG_SPAN_PATTERN_RESAMPLE_RGBA_INCLUDED -#define AGG_SPAN_PATTERN_RESAMPLE_RGBA_INCLUDED - -#include "agg_color_rgba.h" -#include "agg_span_image_resample.h" - -namespace agg -{ - - //=======================================span_pattern_resample_rgba_affine - template<class ColorT, - class Order, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_resample_rgba_affine : - public span_image_resample_affine<ColorT, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Allocator alloc_type; - typedef span_image_resample_affine<color_type, alloc_type> base_type; - typedef typename base_type::interpolator_type interpolator_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::long_type long_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask, - downscale_shift = image_filter_shift - }; - - //-------------------------------------------------------------------- - span_pattern_resample_rgba_affine(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_resample_rgba_affine(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter, - const image_filter_lut& filter_) : - base_type(alloc, src, color_type(0,0,0,0), inter, filter_), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //-------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - interpolator_type& intr = base_type::interpolator(); - intr.begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - long_type fg[4]; - - int diameter = base_type::filter().diameter(); - int filter_size = diameter << image_subpixel_shift; - int radius_x = (diameter * base_type::m_rx) >> 1; - int radius_y = (diameter * base_type::m_ry) >> 1; - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - const int16* weight_array = base_type::filter().weight_array(); - - do - { - intr.coordinates(&x, &y); - - x += base_type::filter_dx_int() - radius_x; - y += base_type::filter_dy_int() - radius_y; - - fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2; - - int y_lr = m_wrap_mode_y(y >> image_subpixel_shift); - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - base_type::m_ry_inv) >> - image_subpixel_shift; - int total_weight = 0; - int x_lr_ini = x >> image_subpixel_shift; - int x_hr_ini = ((image_subpixel_mask - (x & image_subpixel_mask)) * - base_type::m_rx_inv) >> - image_subpixel_shift; - do - { - int weight_y = weight_array[y_hr]; - int x_lr = m_wrap_mode_x(x_lr_ini); - int x_hr = x_hr_ini; - const value_type* row_ptr = (const value_type*)base_type::source_image().row(y_lr); - do - { - const value_type* fg_ptr = row_ptr + (x_lr << 2); - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - - fg[0] += fg_ptr[0] * weight; - fg[1] += fg_ptr[1] * weight; - fg[2] += fg_ptr[2] * weight; - fg[3] += fg_ptr[3] * weight; - total_weight += weight; - x_hr += base_type::m_rx_inv; - x_lr = ++m_wrap_mode_x; - } - while(x_hr < filter_size); - - y_hr += base_type::m_ry_inv; - y_lr = ++m_wrap_mode_y; - } while(y_hr < filter_size); - - fg[0] /= total_weight; - fg[1] /= total_weight; - fg[2] /= total_weight; - fg[3] /= total_weight; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; - - if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; - if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; - if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; - if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; - - span->r = (value_type)fg[order_type::R]; - span->g = (value_type)fg[order_type::G]; - span->b = (value_type)fg[order_type::B]; - span->a = (value_type)fg[order_type::A]; - - ++span; - ++intr; - } while(--len); - return base_type::allocator().span(); - } - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - - - - - - - //============================================span_pattern_resample_rgba - template<class ColorT, - class Order, - class Interpolator, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_resample_rgba : - public span_image_resample<ColorT, Interpolator, Allocator> - { - public: - typedef ColorT color_type; - typedef Order order_type; - typedef Interpolator interpolator_type; - typedef Allocator alloc_type; - typedef span_image_resample<color_type, interpolator_type, alloc_type> base_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::long_type long_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask, - downscale_shift = image_filter_shift - }; - - //-------------------------------------------------------------------- - span_pattern_resample_rgba(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //-------------------------------------------------------------------- - span_pattern_resample_rgba(alloc_type& alloc, - const rendering_buffer& src, - interpolator_type& inter, - const image_filter_lut& filter) : - base_type(alloc, src, color_type(0,0,0,0), inter, filter), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} - - //-------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeX(src.height()); - } - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - interpolator_type& intr = base_type::interpolator(); - intr.begin(x + base_type::filter_dx_dbl(), - y + base_type::filter_dy_dbl(), len); - long_type fg[4]; - - int diameter = base_type::filter().diameter(); - int filter_size = diameter << image_subpixel_shift; - const int16* weight_array = base_type::filter().weight_array(); - - do - { - int rx; - int ry; - int rx_inv = image_subpixel_size; - int ry_inv = image_subpixel_size; - intr.coordinates(&x, &y); - intr.local_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_size) - { - rx = image_subpixel_size; - } - else - { - if(rx > image_subpixel_size * base_type::m_scale_limit) - { - rx = image_subpixel_size * base_type::m_scale_limit; - } - rx_inv = image_subpixel_size * image_subpixel_size / rx; - } - - if(ry < image_subpixel_size) - { - ry = image_subpixel_size; - } - else - { - if(ry > image_subpixel_size * base_type::m_scale_limit) - { - ry = image_subpixel_size * base_type::m_scale_limit; - } - ry_inv = image_subpixel_size * image_subpixel_size / ry; - } - - int radius_x = (diameter * rx) >> 1; - int radius_y = (diameter * ry) >> 1; - int maxx = base_type::source_image().width() - 1; - int maxy = base_type::source_image().height() - 1; - - x += base_type::filter_dx_int() - radius_x; - y += base_type::filter_dy_int() - radius_y; - - fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2; - - int y_lr = m_wrap_mode_y(y >> image_subpixel_shift); - int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * - ry_inv) >> - image_subpixel_shift; - int total_weight = 0; - int x_lr_ini = x >> image_subpixel_shift; - int x_hr_ini = ((image_subpixel_mask - (x & image_subpixel_mask)) * - rx_inv) >> - image_subpixel_shift; - - do - { - int weight_y = weight_array[y_hr]; - int x_lr = m_wrap_mode_x(x_lr_ini); - int x_hr = x_hr_ini; - const value_type* row_ptr = (const value_type*)base_type::source_image().row(y_lr); - do - { - const value_type* fg_ptr = row_ptr + (x_lr << 2); - int weight = (weight_y * weight_array[x_hr] + - image_filter_size / 2) >> - downscale_shift; - fg[0] += fg_ptr[0] * weight; - fg[1] += fg_ptr[1] * weight; - fg[2] += fg_ptr[2] * weight; - fg[3] += fg_ptr[3] * weight; - total_weight += weight; - x_hr += rx_inv; - x_lr = ++m_wrap_mode_x; - } - while(x_hr < filter_size); - y_hr += ry_inv; - y_lr = ++m_wrap_mode_y; - } - while(y_hr < filter_size); - - fg[0] /= total_weight; - fg[1] /= total_weight; - fg[2] /= total_weight; - fg[3] /= total_weight; - - if(fg[0] < 0) fg[0] = 0; - if(fg[1] < 0) fg[1] = 0; - if(fg[2] < 0) fg[2] = 0; - if(fg[3] < 0) fg[3] = 0; - - if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; - if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; - if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; - if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; - - span->r = (value_type)fg[order_type::R]; - span->g = (value_type)fg[order_type::G]; - span->b = (value_type)fg[order_type::B]; - span->a = (value_type)fg[order_type::A]; - - ++span; - ++intr; - } while(--len); - return base_type::allocator().span(); - } - - private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - -} - - -#endif diff --git a/agg/inc/agg_span_pattern_rgb.h b/agg/inc/agg_span_pattern_rgb.h index 2e17f11e7c70..91c550e20fe7 100755 --- a/agg/inc/agg_span_pattern_rgb.h +++ b/agg/inc/agg_span_pattern_rgb.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -26,138 +26,69 @@ #define AGG_SPAN_PATTERN_RGB_INCLUDED #include "agg_basics.h" -#include "agg_pixfmt_rgb.h" -#include "agg_span_pattern.h" namespace agg { - //=======================================================span_pattern_rgb - template<class ColorT, - class Order, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_rgb : public span_pattern_base<ColorT, Allocator> + + //========================================================span_pattern_rgb + template<class Source> class span_pattern_rgb { public: - typedef ColorT color_type; - typedef Order order_type; - typedef Allocator alloc_type; - typedef span_pattern_base<color_type, alloc_type> base_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; //-------------------------------------------------------------------- - span_pattern_rgb(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) + span_pattern_rgb() {} + span_pattern_rgb(source_type& src, + unsigned offset_x, unsigned offset_y) : + m_src(&src), + m_offset_x(offset_x), + m_offset_y(offset_y), + m_alpha(color_type::base_mask) {} - //---------------------------------------------------------------- - span_pattern_rgb(alloc_type& alloc, - const rendering_buffer& src, - unsigned offset_x, - unsigned offset_y, - value_type alpha = base_mask) : - base_type(alloc, src, offset_x, offset_y, alpha), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) - {} + //-------------------------------------------------------------------- + void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } - //------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeY(src.height()); - } + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } + void offset_y(unsigned v) { m_offset_y = v; } + unsigned offset_x() const { return m_offset_x; } + unsigned offset_y() const { return m_offset_y; } + void alpha(value_type v) { m_alpha = v; } + value_type alpha() const { return m_alpha; } //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void prepare() {} + void generate(color_type* span, int x, int y, unsigned len) { - color_type* span = base_type::allocator().span(); - unsigned sx = m_wrap_mode_x(base_type::offset_x() + x); - const value_type* row_ptr = - (const value_type*)base_type::source_image().row( - m_wrap_mode_y( - base_type::offset_y() + y)); + x += m_offset_x; + y += m_offset_y; + const value_type* p = (const value_type*)m_src->span(x, y, len); do { - const value_type* p = row_ptr + sx + sx + sx; span->r = p[order_type::R]; span->g = p[order_type::G]; span->b = p[order_type::B]; - span->a = base_type::alpha_int(); - sx = ++m_wrap_mode_x; + span->a = m_alpha; + p = m_src->next_x(); ++span; } while(--len); - return base_type::allocator().span(); } private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; - }; - - - -/* - //=========================================================span_pattern_rgb - template<class ColorT, class Order, class Allocator = span_allocator<ColorT> > - class span_pattern_rgb : public span_pattern<rgba8, int8u, Allocator> - { - public: - typedef Allocator alloc_type; - typedef rgba8 color_type; - typedef span_pattern<color_type, int8u, alloc_type> base_type; + source_type* m_src; + unsigned m_offset_x; + unsigned m_offset_y; + value_type m_alpha; - //-------------------------------------------------------------------- - span_pattern_rgb24(alloc_type& alloc) : base_type(alloc) {} - - //---------------------------------------------------------------- - span_pattern_rgb24(alloc_type& alloc, - const rendering_buffer& src, - unsigned offset_x, unsigned offset_y, - int8u alpha = 255) : - base_type(alloc, src, offset_x, offset_y, alpha) - {} - - - //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) - { - color_type* span = base_type::allocator().span(); - unsigned sx = (base_type::offset_x() + x) % base_type::source_image().width(); - unsigned wp = base_type::source_image().width() * 3; - const int8u* p = base_type::source_image().row((base_type::offset_y() + y) % base_type::source_image().height()); - p += sx * 3; - do - { - span->r = p[Order::R]; - span->g = p[Order::G]; - span->b = p[Order::B]; - span->a = base_type::alpha(); - p += 3; - ++sx; - ++span; - if(sx >= base_type::source_image().width()) - { - sx -= base_type::source_image().width(); - p -= wp; - } - } - while(--len); - return base_type::allocator().span(); - } }; -*/ } diff --git a/agg/inc/agg_span_pattern_rgba.h b/agg/inc/agg_span_pattern_rgba.h index d952d0733696..ce9e421ae9cc 100755 --- a/agg/inc/agg_span_pattern_rgba.h +++ b/agg/inc/agg_span_pattern_rgba.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -26,83 +26,66 @@ #define AGG_SPAN_PATTERN_RGBA_INCLUDED #include "agg_basics.h" -#include "agg_pixfmt_rgba.h" -#include "agg_span_pattern.h" namespace agg { //======================================================span_pattern_rgba - template<class ColorT, - class Order, - class WrapModeX, - class WrapModeY, - class Allocator = span_allocator<ColorT> > - class span_pattern_rgba : public span_pattern_base<ColorT, Allocator> + template<class Source> class span_pattern_rgba { public: - typedef ColorT color_type; - typedef Order order_type; - typedef Allocator alloc_type; - typedef span_pattern_base<color_type, alloc_type> base_type; + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; //-------------------------------------------------------------------- - span_pattern_rgba(alloc_type& alloc) : - base_type(alloc), - m_wrap_mode_x(1), - m_wrap_mode_y(1) - {} - - //---------------------------------------------------------------- - span_pattern_rgba(alloc_type& alloc, - const rendering_buffer& src, + span_pattern_rgba() {} + span_pattern_rgba(source_type& src, unsigned offset_x, unsigned offset_y) : - base_type(alloc, src, offset_x, offset_y, 0), - m_wrap_mode_x(src.width()), - m_wrap_mode_y(src.height()) + m_src(&src), + m_offset_x(offset_x), + m_offset_y(offset_y) {} - //------------------------------------------------------------------- - void source_image(const rendering_buffer& src) - { - base_type::source_image(src); - m_wrap_mode_x = WrapModeX(src.width()); - m_wrap_mode_y = WrapModeY(src.height()); - } + //-------------------------------------------------------------------- + void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } + void offset_y(unsigned v) { m_offset_y = v; } + unsigned offset_x() const { return m_offset_x; } + unsigned offset_y() const { return m_offset_y; } + void alpha(value_type) {} + value_type alpha() const { return 0; } //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void prepare() {} + void generate(color_type* span, int x, int y, unsigned len) { - color_type* span = base_type::allocator().span(); - unsigned sx = m_wrap_mode_x(base_type::offset_x() + x); - const value_type* row_ptr = - (const value_type*)base_type::source_image().row( - m_wrap_mode_y( - base_type::offset_y() + y)); + x += m_offset_x; + y += m_offset_y; + const value_type* p = (const value_type*)m_src->span(x, y, len); do { - const value_type* p = row_ptr + (sx << 2); span->r = p[order_type::R]; span->g = p[order_type::G]; span->b = p[order_type::B]; span->a = p[order_type::A]; - sx = ++m_wrap_mode_x; + p = (const value_type*)m_src->next_x(); ++span; } while(--len); - return base_type::allocator().span(); } private: - WrapModeX m_wrap_mode_x; - WrapModeY m_wrap_mode_y; + source_type* m_src; + unsigned m_offset_x; + unsigned m_offset_y; + }; } diff --git a/agg/inc/agg_span_solid.h b/agg/inc/agg_span_solid.h index aa8374bfe61f..7955b51cf349 100755 --- a/agg/inc/agg_span_solid.h +++ b/agg/inc/agg_span_solid.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -21,36 +21,26 @@ #define AGG_SPAN_SOLID_INCLUDED #include "agg_basics.h" -#include "agg_span_generator.h" namespace agg { //--------------------------------------------------------------span_solid - template<class ColorT, class Allocator = span_allocator<ColorT> > - class span_solid : public span_generator<ColorT, Allocator> + template<class ColorT> class span_solid { public: - typedef Allocator alloc_type; typedef ColorT color_type; - typedef span_generator<color_type, alloc_type> base_type; - - //-------------------------------------------------------------------- - span_solid(alloc_type& alloc) : base_type(alloc) {} //-------------------------------------------------------------------- void color(const color_type& c) { m_color = c; } const color_type& color() const { return m_color; } //-------------------------------------------------------------------- - color_type* generate(int x, int y, unsigned len) + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) { - color_type* span = base_type::allocator().span(); - do - { - *span++ = m_color; - } - while(--len); - return base_type::allocator().span(); + do { *span++ = m_color; } while(--len); } private: diff --git a/agg/inc/agg_span_subdiv_adaptor.h b/agg/inc/agg_span_subdiv_adaptor.h index 60196d705bdb..2db106cdce60 100755 --- a/agg/inc/agg_span_subdiv_adaptor.h +++ b/agg/inc/agg_span_subdiv_adaptor.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -28,10 +28,10 @@ namespace agg typedef Interpolator interpolator_type; typedef typename interpolator_type::trans_type trans_type; - enum + enum sublixel_scale_e { subpixel_shift = SubpixelShift, - subpixel_size = 1 << subpixel_shift + subpixel_scale = 1 << subpixel_shift }; @@ -87,7 +87,7 @@ namespace agg void begin(double x, double y, unsigned len) { m_pos = 1; - m_src_x = int(x * subpixel_size) + subpixel_size; + m_src_x = iround(x * subpixel_scale) + subpixel_scale; m_src_y = y; m_len = len; if(len > m_subdiv_size) len = m_subdiv_size; @@ -102,12 +102,12 @@ namespace agg { unsigned len = m_len; if(len > m_subdiv_size) len = m_subdiv_size; - m_interpolator->resynchronize(double(m_src_x) / double(subpixel_size) + len, + m_interpolator->resynchronize(double(m_src_x) / double(subpixel_scale) + len, m_src_y, len); m_pos = 0; } - m_src_x += subpixel_size; + m_src_x += subpixel_scale; ++m_pos; --m_len; } diff --git a/agg/inc/agg_trans_affine.h b/agg/inc/agg_trans_affine.h index 5a4098f904de..70dfbc49007b 100755 --- a/agg/inc/agg_trans_affine.h +++ b/agg/inc/agg_trans_affine.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -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,15 +149,27 @@ 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); // Multiply "m" to "this" and assign the result to "this" const trans_affine& premultiply(const trans_affine& m); + // Multiply matrix to inverse of another one + const trans_affine& multiply_inv(const trans_affine& m); + + // Multiply inverse of "m" to "this" and assign the result to "this" + const trans_affine& premultiply_inv(const trans_affine& m); + // Invert matrix. Do not try to invert degenerate matrices, // there's no check for validity. If you set scale to 0 and // then try to invert matrix, expect unpredictable result. @@ -163,31 +185,44 @@ 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 another one and return + // Multiply the matrix by inverse of another one + const trans_affine& operator /= (const trans_affine& m) + { + return multiply_inv(m); + } + + // 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 the matrix by inverse of another one + // and return the result in a separete matrix. + trans_affine operator / (const trans_affine& m) + { + return trans_affine(*this).multiply_inv(m); + } + // Calculate and return the inverse matrix trans_affine operator ~ () const { @@ -208,19 +243,28 @@ namespace agg } //-------------------------------------------- Transformations - // Direct transformation x and y + // Direct transformation of x and y void transform(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() + // 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 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). @@ -228,57 +272,108 @@ 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 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) @@ -287,6 +382,31 @@ namespace agg return *this = t.multiply(*this); } + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::multiply_inv(const trans_affine& m) + { + trans_affine t = m; + t.invert(); + return multiply(t); + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::premultiply_inv(const trans_affine& m) + { + trans_affine t = m; + t.invert(); + 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. @@ -302,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) : @@ -320,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) {} }; @@ -330,12 +450,66 @@ 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) + {} + }; + + + //===============================================trans_affine_line_segment + // Rotate, Scale and Translate, associating 0...dist with line segment + // x1,y1,x2,y2 + class trans_affine_line_segment : public trans_affine + { + public: + trans_affine_line_segment(double x1, double y1, double x2, double y2, + double dist) + { + double dx = x2 - x1; + double dy = y2 - y1; + if(dist > 0.0) + { + multiply(trans_affine_scaling(sqrt(dx * dx + dy * dy) / dist)); + } + multiply(trans_affine_rotation(atan2(dy, dx))); + multiply(trans_affine_translation(x1, y1)); + } + }; + + + //============================================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/inc/agg_trans_bilinear.h b/agg/inc/agg_trans_bilinear.h index 7398a866d3b0..e5367bb1f6eb 100755 --- a/agg/inc/agg_trans_bilinear.h +++ b/agg/inc/agg_trans_bilinear.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_trans_double_path.h b/agg/inc/agg_trans_double_path.h index 16ea9f7264bd..91478a70ed3b 100755 --- a/agg/inc/agg_trans_double_path.h +++ b/agg/inc/agg_trans_double_path.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_trans_perspective.h b/agg/inc/agg_trans_perspective.h index a127c9095ad2..86116625cd8f 100755 --- a/agg/inc/agg_trans_perspective.h +++ b/agg/inc/agg_trans_perspective.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -19,124 +19,211 @@ #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) + const double* quad); + + // Quadrilateral to rectangle + trans_perspective(const double* quad, + 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) + { + return multiply(m); + } + const trans_perspective& operator *= (const trans_affine& m) { - rect_to_quad(x1, y1, x2, y2, quad); + return multiply(m); } + // Multiply the matrix by inverse of another one + const trans_perspective& operator /= (const trans_perspective& m) + { + return multiply_inv(m); + } + const trans_perspective& operator /= (const trans_affine& m) + { + return multiply_inv(m); + } - //-------------------------------------------------------------------- - // Reverse transformations - trans_perspective(const double* quad, - double x1, double y1, double x2, double y2) + // Multiply the matrix by another one and return + // the result in a separete matrix. + trans_perspective operator * (const trans_perspective& m) + { + return trans_perspective(*this).multiply(m); + } + trans_perspective operator * (const trans_affine& m) { - quad_to_rect(quad, x1, y1, x2, y2); + return trans_perspective(*this).multiply(m); } + // Multiply the matrix by inverse of another one + // and return the result in a separete matrix. + trans_perspective operator / (const trans_perspective& m) + { + return trans_perspective(*this).multiply_inv(m); + } + trans_perspective operator / (const trans_affine& m) + { + return trans_perspective(*this).multiply_inv(m); + } - //-------------------------------------------------------------------- - // Set the transformations using two arbitrary quadrangles. - void quad_to_quad(const double* src, const double* dst) + // Calculate and return the inverse matrix + trans_perspective operator ~ () const { + trans_perspective ret = *this; + ret.invert(); + return ret; + } - double left[8][8]; - double right[8][1]; + // Equal operator with default epsilon + bool operator == (const trans_perspective& m) const + { + return is_equal(m, affine_epsilon); + } - 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); + // 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; - //-------------------------------------------------------------------- - // Set the direct transformations, i.e., rectangle -> quadrangle - void rect_to_quad(double x1, double y1, double x2, double y2, - const double* quad) - { - 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); - } + // 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; - //-------------------------------------------------------------------- - // Set the reverse transformations, i.e., quadrangle -> rectangle - void quad_to_rect(const double* quad, - double x1, double y1, double x2, double y2) - { - 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); - } + // 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; - //-------------------------------------------------------------------- - // 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 - { - 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; - } //-------------------------------------------------------------------- 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/inc/agg_trans_single_path.h b/agg/inc/agg_trans_single_path.h index 68369626c396..43bcf836f2da 100755 --- a/agg/inc/agg_trans_single_path.h +++ b/agg/inc/agg_trans_single_path.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/inc/agg_trans_viewport.h b/agg/inc/agg_trans_viewport.h index b77a7204feb9..9915df61a432 100755 --- a/agg/inc/agg_trans_viewport.h +++ b/agg/inc/agg_trans_viewport.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -22,7 +22,7 @@ #define AGG_TRANS_VIEWPORT_INCLUDED #include <string.h> -#include "agg_basics.h" +#include "agg_trans_affine.h" namespace agg @@ -51,6 +51,7 @@ namespace agg m_device_x2(1.0), m_device_y2(1.0), m_aspect(aspect_ratio_stretch), + m_is_valid(true), m_align_x(0.5), m_align_y(0.5), m_wx1(0.0), @@ -123,6 +124,7 @@ namespace agg } //------------------------------------------------------------------- + bool is_valid() const { return m_is_valid; } double align_x() const { return m_align_x; } double align_y() const { return m_align_y; } aspect_ratio_e aspect_ratio() const { return m_aspect; } @@ -135,6 +137,13 @@ namespace agg } //------------------------------------------------------------------- + void transform_scale_only(double* x, double* y) const + { + *x *= m_kx; + *y *= m_ky; + } + + //------------------------------------------------------------------- void inverse_transform(double* x, double* y) const { *x = (*x - m_dx1) / m_kx + m_wx1; @@ -142,6 +151,17 @@ namespace agg } //------------------------------------------------------------------- + void inverse_transform_scale_only(double* x, double* y) const + { + *x /= m_kx; + *y /= m_ky; + } + + //------------------------------------------------------------------- + double device_dx() const { return m_dx1 - m_wx1 * m_kx; } + double device_dy() const { return m_dy1 - m_wy1 * m_ky; } + + //------------------------------------------------------------------- double scale_x() const { return m_kx; @@ -159,76 +179,35 @@ namespace agg return (m_kx + m_ky) * 0.5; } + //------------------------------------------------------------------- + trans_affine to_affine() const + { + trans_affine mtx = trans_affine_translation(-m_wx1, -m_wy1); + mtx *= trans_affine_scaling(m_kx, m_ky); + mtx *= trans_affine_translation(m_dx1, m_dy1); + return mtx; + } + + //------------------------------------------------------------------- + trans_affine to_affine_scale_only() const + { + return trans_affine_scaling(m_kx, m_ky); + } //------------------------------------------------------------------- unsigned byte_size() const { - return - sizeof(m_world_x1) + - sizeof(m_world_y1) + - sizeof(m_world_x2) + - sizeof(m_world_y2) + - sizeof(m_device_x1) + - sizeof(m_device_y1) + - sizeof(m_device_x2) + - sizeof(m_device_y2) + - sizeof(m_aspect) + - sizeof(m_align_x) + - sizeof(m_align_y) + - sizeof(m_wx1) + - sizeof(m_wy1) + - sizeof(m_wx2) + - sizeof(m_wy2) + - sizeof(m_dx1) + - sizeof(m_dy1) + - sizeof(m_kx) + - sizeof(m_ky); + return sizeof(*this); } void serialize(int8u* ptr) const { - memcpy(ptr, &m_world_x1, sizeof(m_world_x1)); ptr += sizeof(m_world_x1); - memcpy(ptr, &m_world_y1, sizeof(m_world_y1)); ptr += sizeof(m_world_y1); - memcpy(ptr, &m_world_x2, sizeof(m_world_x2)); ptr += sizeof(m_world_x2); - memcpy(ptr, &m_world_y2, sizeof(m_world_y2)); ptr += sizeof(m_world_y2); - memcpy(ptr, &m_device_x1, sizeof(m_device_x1)); ptr += sizeof(m_device_x1); - memcpy(ptr, &m_device_y1, sizeof(m_device_y1)); ptr += sizeof(m_device_y1); - memcpy(ptr, &m_device_x2, sizeof(m_device_x2)); ptr += sizeof(m_device_x2); - memcpy(ptr, &m_device_y2, sizeof(m_device_y2)); ptr += sizeof(m_device_y2); - memcpy(ptr, &m_aspect, sizeof(m_aspect)); ptr += sizeof(m_aspect); - memcpy(ptr, &m_align_x, sizeof(m_align_x)); ptr += sizeof(m_align_x); - memcpy(ptr, &m_align_y, sizeof(m_align_y)); ptr += sizeof(m_align_y); - memcpy(ptr, &m_wx1, sizeof(m_wx1)); ptr += sizeof(m_wx1); - memcpy(ptr, &m_wy1, sizeof(m_wy1)); ptr += sizeof(m_wy1); - memcpy(ptr, &m_wx2, sizeof(m_wx2)); ptr += sizeof(m_wx2); - memcpy(ptr, &m_wy2, sizeof(m_wy2)); ptr += sizeof(m_wy2); - memcpy(ptr, &m_dx1, sizeof(m_dx1)); ptr += sizeof(m_dx1); - memcpy(ptr, &m_dy1, sizeof(m_dy1)); ptr += sizeof(m_dy1); - memcpy(ptr, &m_kx, sizeof(m_kx)); ptr += sizeof(m_kx); - memcpy(ptr, &m_ky, sizeof(m_ky)); ptr += sizeof(m_ky); + memcpy(ptr, this, sizeof(*this)); } void deserialize(const int8u* ptr) { - memcpy(&m_world_x1, ptr, sizeof(m_world_x1)); ptr += sizeof(m_world_x1); - memcpy(&m_world_y1, ptr, sizeof(m_world_y1)); ptr += sizeof(m_world_y1); - memcpy(&m_world_x2, ptr, sizeof(m_world_x2)); ptr += sizeof(m_world_x2); - memcpy(&m_world_y2, ptr, sizeof(m_world_y2)); ptr += sizeof(m_world_y2); - memcpy(&m_device_x1, ptr, sizeof(m_device_x1)); ptr += sizeof(m_device_x1); - memcpy(&m_device_y1, ptr, sizeof(m_device_y1)); ptr += sizeof(m_device_y1); - memcpy(&m_device_x2, ptr, sizeof(m_device_x2)); ptr += sizeof(m_device_x2); - memcpy(&m_device_y2, ptr, sizeof(m_device_y2)); ptr += sizeof(m_device_y2); - memcpy(&m_aspect, ptr, sizeof(m_aspect)); ptr += sizeof(m_aspect); - memcpy(&m_align_x, ptr, sizeof(m_align_x)); ptr += sizeof(m_align_x); - memcpy(&m_align_y, ptr, sizeof(m_align_y)); ptr += sizeof(m_align_y); - memcpy(&m_wx1, ptr, sizeof(m_wx1)); ptr += sizeof(m_wx1); - memcpy(&m_wy1, ptr, sizeof(m_wy1)); ptr += sizeof(m_wy1); - memcpy(&m_wx2, ptr, sizeof(m_wx2)); ptr += sizeof(m_wx2); - memcpy(&m_wy2, ptr, sizeof(m_wy2)); ptr += sizeof(m_wy2); - memcpy(&m_dx1, ptr, sizeof(m_dx1)); ptr += sizeof(m_dx1); - memcpy(&m_dy1, ptr, sizeof(m_dy1)); ptr += sizeof(m_dy1); - memcpy(&m_kx, ptr, sizeof(m_kx)); ptr += sizeof(m_kx); - memcpy(&m_ky, ptr, sizeof(m_ky)); ptr += sizeof(m_ky); + memcpy(this, ptr, sizeof(*this)); } private: @@ -243,6 +222,7 @@ namespace agg double m_device_x2; double m_device_y2; aspect_ratio_e m_aspect; + bool m_is_valid; double m_align_x; double m_align_y; double m_wx1; @@ -260,6 +240,24 @@ namespace agg //----------------------------------------------------------------------- inline void trans_viewport::update() { + const double epsilon = 1e-30; + if(fabs(m_world_x1 - m_world_x2) < epsilon || + fabs(m_world_y1 - m_world_y2) < epsilon || + fabs(m_device_x1 - m_device_x2) < epsilon || + fabs(m_device_y1 - m_device_y2) < epsilon) + { + m_wx1 = m_world_x1; + m_wy1 = m_world_y1; + m_wx2 = m_world_x1 + 1.0; + m_wy2 = m_world_y2 + 1.0; + m_dx1 = m_device_x1; + m_dy1 = m_device_y1; + m_kx = 1.0; + m_ky = 1.0; + m_is_valid = false; + return; + } + double world_x1 = m_world_x1; double world_y1 = m_world_y1; double world_x2 = m_world_x2; @@ -295,6 +293,7 @@ namespace agg m_dy1 = device_y1; m_kx = (device_x2 - device_x1) / (world_x2 - world_x1); m_ky = (device_y2 - device_y1) / (world_y2 - world_y1); + m_is_valid = true; } diff --git a/agg/inc/agg_trans_warp_magnifier.h b/agg/inc/agg_trans_warp_magnifier.h index d71f567af2ca..9b36c94892f1 100755 --- a/agg/inc/agg_trans_warp_magnifier.h +++ b/agg/inc/agg_trans_warp_magnifier.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -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/inc/agg_vcgen_bspline.h b/agg/inc/agg_vcgen_bspline.h index 7490a50a6764..277dea436000 100755 --- a/agg/inc/agg_vcgen_bspline.h +++ b/agg/inc/agg_vcgen_bspline.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -37,7 +37,7 @@ namespace agg }; public: - typedef pod_deque<point_type, 6> vertex_storage; + typedef pod_bvector<point_d, 6> vertex_storage; vcgen_bspline(); @@ -49,7 +49,7 @@ namespace agg void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: diff --git a/agg/inc/agg_vcgen_contour.h b/agg/inc/agg_vcgen_contour.h index 1c5428206640..bdf15b1a9a26 100755 --- a/agg/inc/agg_vcgen_contour.h +++ b/agg/inc/agg_vcgen_contour.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -17,7 +17,6 @@ #define AGG_VCGEN_CONTOUR_INCLUDED #include "agg_math_stroke.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -40,55 +39,54 @@ namespace agg public: typedef vertex_sequence<vertex_dist, 6> vertex_storage; - typedef pod_deque<point_type, 6> coord_storage; + typedef pod_bvector<point_d, 6> coord_storage; vcgen_contour(); - void line_join(line_join_e lj) { m_line_join = lj; } - void inner_line_join(line_join_e lj) { m_inner_line_join = lj; } - 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_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); } - line_join_e line_join() const { return m_line_join; } - line_join_e inner_line_join() const { return m_inner_line_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; } + 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(); void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: 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; - line_join_e m_inner_line_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<coord_storage> 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/inc/agg_vcgen_dash.h b/agg/inc/agg_vcgen_dash.h index cc4c86dea833..25d23d3ff26e 100755 --- a/agg/inc/agg_vcgen_dash.h +++ b/agg/inc/agg_vcgen_dash.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -21,7 +21,6 @@ #include "agg_basics.h" #include "agg_vertex_sequence.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -32,7 +31,7 @@ namespace agg // class vcgen_dash { - enum + enum max_dashes_e { max_dashes = 32 }; @@ -62,14 +61,9 @@ namespace agg void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); - typedef vcgen_dash source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: vcgen_dash(const vcgen_dash&); const vcgen_dash& operator = (const vcgen_dash&); diff --git a/agg/inc/agg_vcgen_markers_term.h b/agg/inc/agg_vcgen_markers_term.h index 6f213811c290..b069f1d54154 100755 --- a/agg/inc/agg_vcgen_markers_term.h +++ b/agg/inc/agg_vcgen_markers_term.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -18,7 +18,6 @@ #include "agg_basics.h" #include "agg_vertex_sequence.h" -#include "agg_vertex_iterator.h" namespace agg { @@ -39,14 +38,9 @@ namespace agg void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); - typedef vcgen_markers_term source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: vcgen_markers_term(const vcgen_markers_term&); const vcgen_markers_term& operator = (const vcgen_markers_term&); @@ -59,7 +53,7 @@ namespace agg coord_type(double x_, double y_) : x(x_), y(y_) {} }; - typedef pod_deque<coord_type, 6> coord_storage; + typedef pod_bvector<coord_type, 6> coord_storage; coord_storage m_markers; unsigned m_curr_id; diff --git a/agg/inc/agg_vcgen_smooth_poly1.h b/agg/inc/agg_vcgen_smooth_poly1.h index 61ca14898328..2c0619e62d76 100755 --- a/agg/inc/agg_vcgen_smooth_poly1.h +++ b/agg/inc/agg_vcgen_smooth_poly1.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -57,7 +57,7 @@ namespace agg void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); private: diff --git a/agg/inc/agg_vcgen_stroke.h b/agg/inc/agg_vcgen_stroke.h index a73509acf3d9..b65eddd5c2b7 100755 --- a/agg/inc/agg_vcgen_stroke.h +++ b/agg/inc/agg_vcgen_stroke.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -17,7 +17,6 @@ #define AGG_VCGEN_STROKE_INCLUDED #include "agg_math_stroke.h" -#include "agg_vertex_iterator.h" namespace agg @@ -48,28 +47,28 @@ namespace agg public: typedef vertex_sequence<vertex_dist, 6> vertex_storage; - typedef pod_deque<point_type, 6> coord_storage; + typedef pod_bvector<point_d, 6> coord_storage; 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_line_join(line_join_e lj) { m_inner_line_join = lj; } + 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; } - line_join_e inner_line_join() const { return m_inner_line_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; } @@ -79,33 +78,22 @@ namespace agg void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); - typedef vcgen_stroke source_type; - typedef vertex_iterator<source_type> iterator; - iterator begin(unsigned id) { return iterator(*this, id); } - iterator end() { return iterator(path_cmd_stop); } - private: 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; - line_join_e m_inner_line_join; - unsigned m_closed; - status_e m_status; - status_e m_prev_status; - unsigned m_src_vertex; - unsigned m_out_vertex; + math_stroke<coord_storage> 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/inc/agg_vcgen_vertex_sequence.h b/agg/inc/agg_vcgen_vertex_sequence.h index 7c4e9e4253e5..b9cb0b5e45df 100755 --- a/agg/inc/agg_vcgen_vertex_sequence.h +++ b/agg/inc/agg_vcgen_vertex_sequence.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -43,7 +43,7 @@ namespace agg void add_vertex(double x, double y, unsigned cmd); // Vertex Source Interface - void rewind(unsigned id); + void rewind(unsigned path_id); unsigned vertex(double* x, double* y); void shorten(double s) { m_shorten = s; } diff --git a/agg/inc/agg_vertex_sequence.h b/agg/inc/agg_vertex_sequence.h index 357a3df15fa4..5a14da20c32f 100755 --- a/agg/inc/agg_vertex_sequence.h +++ b/agg/inc/agg_vertex_sequence.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -27,10 +27,10 @@ namespace agg { //----------------------------------------------------------vertex_sequence - // Modified agg::pod_deque. The data is interpreted as a sequence of vertices. - // It means that the type T must expose: + // 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 @@ -64,10 +64,10 @@ namespace agg // necessary. //------------------------------------------------------------------------ template<class T, unsigned S=6> - class vertex_sequence : public pod_deque<T, S> + class vertex_sequence : public pod_bvector<T, S> { public: - typedef pod_deque<T, S> base_type; + typedef pod_bvector<T, S> base_type; void add(const T& val); void modify_last(const T& val); @@ -124,10 +124,6 @@ namespace agg } - - // Coinciding points maximal distance (Epsilon) - const double vertex_dist_epsilon = 1e-14; - //-------------------------------------------------------------vertex_dist // Vertex (x, y) with the distance to the next one. The last vertex has // distance between the last and the first points if the polygon is closed diff --git a/agg/inc/agg_vpgen_clip_polygon.h b/agg/inc/agg_vpgen_clip_polygon.h index d5da460843e6..1b5780e4e443 100755 --- a/agg/inc/agg_vpgen_clip_polygon.h +++ b/agg/inc/agg_vpgen_clip_polygon.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -39,12 +39,12 @@ namespace agg { } - void clip_box(double _x1, double _y1, double _x2, double _y2) + void clip_box(double x1, double y1, double x2, double y2) { - m_clip_box.x1 = _x1; - m_clip_box.y1 = _y1; - m_clip_box.x2 = _x2; - m_clip_box.y2 = _y2; + m_clip_box.x1 = x1; + m_clip_box.y1 = y1; + m_clip_box.x2 = x2; + m_clip_box.y2 = y2; m_clip_box.normalize(); } diff --git a/agg/inc/agg_vpgen_clip_polyline.h b/agg/inc/agg_vpgen_clip_polyline.h index f951966a3293..452d3cda4a23 100755 --- a/agg/inc/agg_vpgen_clip_polyline.h +++ b/agg/inc/agg_vpgen_clip_polyline.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -32,25 +32,21 @@ namespace agg m_clip_box(0, 0, 1, 1), m_x1(0), m_y1(0), - m_f1(0), - m_x2(0), - m_y2(0), - m_f2(0), m_num_vertices(0), - m_vertex(0) + m_vertex(0), + m_move_to(false) { } - void clip_box(double _x1, double _y1, double _x2, double _y2) + void clip_box(double x1, double y1, double x2, double y2) { - m_clip_box.x1 = _x1; - m_clip_box.y1 = _y1; - m_clip_box.x2 = _x2; - m_clip_box.y2 = _y2; + m_clip_box.x1 = x1; + m_clip_box.y1 = y1; + m_clip_box.x2 = x2; + m_clip_box.y2 = y2; m_clip_box.normalize(); } - double x1() const { return m_clip_box.x1; } double y1() const { return m_clip_box.y1; } double x2() const { return m_clip_box.x2; } @@ -65,54 +61,15 @@ namespace agg unsigned vertex(double* x, double* y); private: - enum clipping_flags_def - { - clip_x1 = 1, - clip_x2 = 2, - clip_y1 = 4, - clip_y2 = 8 - }; - - // Determine the clipping code of the vertex according to the - // Cyrus-Beck line clipping algorithm - //-------------------------------------------------------------------- - unsigned clipping_flags_x(double x) - { - unsigned f = 0; - if(x < m_clip_box.x1) f |= clip_x1; - if(x > m_clip_box.x2) f |= clip_x2; - return f; - } - - unsigned clipping_flags_y(double y) - { - unsigned f = 0; - if(y < m_clip_box.y1) f |= clip_y1; - if(y > m_clip_box.y2) f |= clip_y2; - return f; - } - - unsigned clipping_flags(double x, double y) - { - return clipping_flags_x(x) | clipping_flags_y(y); - } - - bool move_point(double& x, double& y, unsigned& flags); - void clip_line_segment(); - - private: rect_d m_clip_box; double m_x1; double m_y1; - unsigned m_f1; - double m_x2; - double m_y2; - unsigned m_f2; double m_x[2]; double m_y[2]; unsigned m_cmd[2]; unsigned m_num_vertices; unsigned m_vertex; + bool m_move_to; }; } diff --git a/agg/inc/agg_vpgen_segmentator.h b/agg/inc/agg_vpgen_segmentator.h index 1acc3531cc6e..0750c59df508 100755 --- a/agg/inc/agg_vpgen_segmentator.h +++ b/agg/inc/agg_vpgen_segmentator.h @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/source/agg_arc.cpp b/agg/source/agg_arc.cpp index eb10f5f7f2fc..154848218533 100755 --- a/agg/source/agg_arc.cpp +++ b/agg/source/agg_arc.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -65,7 +65,7 @@ namespace agg unsigned arc::vertex(double* x, double* y) { if(is_stop(m_path_cmd)) return path_cmd_stop; - if((m_angle < m_end) != m_ccw) + if((m_angle < m_end - m_da/4) != m_ccw) { *x = m_x + cos(m_end) * m_rx; *y = m_y + sin(m_end) * m_ry; @@ -86,7 +86,8 @@ namespace agg //------------------------------------------------------------------------ void arc::normalize(double a1, double a2, bool ccw) { - m_da = fabs(1.0 / ((m_rx + m_ry) * 0.5 * m_scale)); + double ra = (fabs(m_rx) + fabs(m_ry)) / 2; + m_da = acos(ra / (ra + 0.125 / m_scale)) * 2; if(ccw) { while(a2 < a1) a2 += pi * 2.0; diff --git a/agg/source/agg_arrowhead.cpp b/agg/source/agg_arrowhead.cpp index 694ed5ad887b..1ea305277ff3 100755 --- a/agg/source/agg_arrowhead.cpp +++ b/agg/source/agg_arrowhead.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -42,11 +42,11 @@ namespace agg //------------------------------------------------------------------------ - void arrowhead::rewind(unsigned id) + void arrowhead::rewind(unsigned path_id) { - m_curr_id = id; + m_curr_id = path_id; m_curr_coord = 0; - if(id == 0) + if(path_id == 0) { if(!m_tail_flag) { @@ -66,12 +66,12 @@ namespace agg m_cmd[3] = path_cmd_line_to; m_cmd[4] = path_cmd_line_to; m_cmd[5] = path_cmd_line_to; - m_cmd[7] = (unsigned)path_cmd_end_poly | (unsigned)path_flags_close | (unsigned)path_flags_ccw; + m_cmd[7] = path_cmd_end_poly | path_flags_close | path_flags_ccw; m_cmd[6] = path_cmd_stop; return; } - if(id == 1) + if(path_id == 1) { if(!m_head_flag) { @@ -87,7 +87,7 @@ namespace agg m_cmd[1] = path_cmd_line_to; m_cmd[2] = path_cmd_line_to; m_cmd[3] = path_cmd_line_to; - m_cmd[4] = (unsigned)path_cmd_end_poly | (unsigned)path_flags_close | (unsigned)path_flags_ccw; + m_cmd[4] = path_cmd_end_poly | path_flags_close | path_flags_ccw; m_cmd[5] = path_cmd_stop; return; } diff --git a/agg/source/agg_bezier_arc.cpp b/agg/source/agg_bezier_arc.cpp index 6b47fff76fc8..51895a22119a 100755 --- a/agg/source/agg_bezier_arc.cpp +++ b/agg/source/agg_bezier_arc.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -26,6 +26,14 @@ namespace agg { + // This epsilon is used to prevent us from adding degenerate curves + // (converging to a single point). + // The value isn't very critical. Function arc_to_bezier() has a limit + // of the sweep_angle. If fabs(sweep_angle) exceeds pi/2 the curve + // becomes inaccurate. But slight exceeding is quite appropriate. + //-------------------------------------------------bezier_arc_angle_epsilon + const double bezier_arc_angle_epsilon = 0.01; + //------------------------------------------------------------arc_to_bezier void arc_to_bezier(double cx, double cy, double rx, double ry, double start_angle, double sweep_angle, @@ -69,29 +77,44 @@ namespace agg if(sweep_angle >= 2.0 * pi) sweep_angle = 2.0 * pi; if(sweep_angle <= -2.0 * pi) sweep_angle = -2.0 * pi; + if(fabs(sweep_angle) < 1e-10) + { + m_num_vertices = 4; + m_cmd = path_cmd_line_to; + m_vertices[0] = x + rx * cos(start_angle); + m_vertices[1] = y + ry * sin(start_angle); + m_vertices[2] = x + rx * cos(start_angle + sweep_angle); + m_vertices[3] = y + ry * sin(start_angle + sweep_angle); + return; + } + double total_sweep = 0.0; double local_sweep = 0.0; + double prev_sweep; m_num_vertices = 2; + m_cmd = path_cmd_curve4; bool done = false; do { if(sweep_angle < 0.0) { + prev_sweep = total_sweep; local_sweep = -pi * 0.5; total_sweep -= pi * 0.5; - if(total_sweep <= sweep_angle) + if(total_sweep <= sweep_angle + bezier_arc_angle_epsilon) { - local_sweep = sweep_angle - (total_sweep + pi * 0.5); + local_sweep = sweep_angle - prev_sweep; done = true; } } else { + prev_sweep = total_sweep; local_sweep = pi * 0.5; total_sweep += pi * 0.5; - if(total_sweep >= sweep_angle) + if(total_sweep >= sweep_angle - bezier_arc_angle_epsilon) { - local_sweep = sweep_angle - (total_sweep - pi * 0.5); + local_sweep = sweep_angle - prev_sweep; done = true; } } @@ -129,8 +152,6 @@ namespace agg double dx2 = (x0 - x2) / 2.0; double dy2 = (y0 - y2) / 2.0; - // Convert angle from degrees to radians - //------------------------ double cos_a = cos(angle); double sin_a = sin(angle); diff --git a/agg/source/agg_bspline.cpp b/agg/source/agg_bspline.cpp index 8635495ecc9e..b9ff38054eab 100755 --- a/agg/source/agg_bspline.cpp +++ b/agg/source/agg_bspline.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -17,26 +17,16 @@ // //---------------------------------------------------------------------------- - #include "agg_bspline.h" namespace agg { - - //------------------------------------------------------------------------ - bspline::~bspline() - { - delete [] m_am; - } - - //------------------------------------------------------------------------ bspline::bspline() : m_max(0), m_num(0), m_x(0), m_y(0), - m_am(0), m_last_idx(-1) { } @@ -47,7 +37,6 @@ namespace agg m_num(0), m_x(0), m_y(0), - m_am(0), m_last_idx(-1) { init(num); @@ -59,7 +48,6 @@ namespace agg m_num(0), m_x(0), m_y(0), - m_am(0), m_last_idx(-1) { init(num, x, y); @@ -71,11 +59,10 @@ namespace agg { if(max > 2 && max > m_max) { - delete [] m_am; - m_am = new double[max * 3]; + m_am.resize(max * 3); m_max = max; - m_x = m_am + m_max; - m_y = m_am + m_max * 2; + m_x = &m_am[m_max]; + m_y = &m_am[m_max * 2]; } m_num = 0; m_last_idx = -1; @@ -103,7 +90,6 @@ namespace agg double* temp; double* r; double* s; - double* al; double h, p, d, f, e; for(k = 0; k < m_num; k++) @@ -113,8 +99,8 @@ namespace agg n1 = 3 * m_num; - al = new double[n1]; - temp = al; + pod_array<double> al(n1); + temp = &al[0]; for(k = 0; k < n1; k++) { @@ -155,7 +141,6 @@ namespace agg al[k] = al[k] * al[k + 1] + s[k]; m_am[k] = al[k]; } - delete [] al; } m_last_idx = -1; } diff --git a/agg/source/agg_curves.cpp b/agg/source/agg_curves.cpp index bae65f26b5a3..f36069b9ba70 100755 --- a/agg/source/agg_curves.cpp +++ b/agg/source/agg_curves.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -12,21 +12,38 @@ // mcseemagg@yahoo.com // http://www.antigrain.com //---------------------------------------------------------------------------- -// -// classes curve3 and curve4 -// -//---------------------------------------------------------------------------- #include <math.h> #include "agg_curves.h" +#include "agg_math.h" namespace agg { //------------------------------------------------------------------------ - void curve3::init(double x1, double y1, - double x2, double y2, - double x3, double y3) + const double curve_distance_epsilon = 1e-30; + const double curve_collinearity_epsilon = 1e-30; + const double curve_angle_tolerance_epsilon = 0.01; + enum curve_recursion_limit_e { curve_recursion_limit = 32 }; + + + + //------------------------------------------------------------------------ + void curve3_inc::approximation_scale(double s) + { + m_scale = s; + } + + //------------------------------------------------------------------------ + double curve3_inc::approximation_scale() const + { + return m_scale; + } + + //------------------------------------------------------------------------ + void curve3_inc::init(double x1, double y1, + double x2, double y2, + double x3, double y3) { m_start_x = x1; m_start_y = y1; @@ -40,11 +57,11 @@ namespace agg double len = sqrt(dx1 * dx1 + dy1 * dy1) + sqrt(dx2 * dx2 + dy2 * dy2); - m_num_steps = int(len * 0.25 * m_scale); + m_num_steps = uround(len * 0.25 * m_scale); - if(m_num_steps < 2) + if(m_num_steps < 4) { - m_num_steps = 2; + m_num_steps = 4; } double subdivide_step = 1.0 / m_num_steps; @@ -65,11 +82,8 @@ namespace agg m_step = m_num_steps; } - - - //------------------------------------------------------------------------ - void curve3::rewind(unsigned) + void curve3_inc::rewind(unsigned) { if(m_num_steps == 0) { @@ -83,11 +97,8 @@ namespace agg m_dfy = m_saved_dfy; } - - - //------------------------------------------------------------------------ - unsigned curve3::vertex(double* x, double* y) + unsigned curve3_inc::vertex(double* x, double* y) { if(m_step < 0) return path_cmd_stop; if(m_step == m_num_steps) @@ -114,23 +125,141 @@ namespace agg return path_cmd_line_to; } + //------------------------------------------------------------------------ + void curve3_div::init(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_points.remove_all(); + m_distance_tolerance_square = 0.5 / m_approximation_scale; + m_distance_tolerance_square *= m_distance_tolerance_square; + bezier(x1, y1, x2, y2, x3, y3); + m_count = 0; + } + //------------------------------------------------------------------------ + void curve3_div::recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + unsigned level) + { + if(level > curve_recursion_limit) + { + return; + } + // Calculate all the mid-points of the line segments + //---------------------- + double x12 = (x1 + x2) / 2; + double y12 = (y1 + y2) / 2; + double x23 = (x2 + x3) / 2; + double y23 = (y2 + y3) / 2; + double x123 = (x12 + x23) / 2; + double y123 = (y12 + y23) / 2; + + 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 case + //----------------- + if(d * d <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + // If the curvature doesn't exceed the distance_tolerance value + // we tend to finish subdivisions. + //---------------------- + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x123, y123)); + return; + } + + // Angle & Cusp Condition + //---------------------- + da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); + if(da >= pi) da = 2*pi - da; + + if(da < m_angle_tolerance) + { + // Finally we can stop the recursion + //---------------------- + m_points.add(point_d(x123, y123)); + return; + } + } + } + else + { + // Collinear case + //------------------ + da = dx*dx + dy*dy; + if(da == 0) + { + 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 + //---------------------- + recursive_bezier(x1, y1, x12, y12, x123, y123, level + 1); + recursive_bezier(x123, y123, x23, y23, x3, y3, level + 1); + } + //------------------------------------------------------------------------ + void curve3_div::bezier(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_points.add(point_d(x1, y1)); + recursive_bezier(x1, y1, x2, y2, x3, y3, 0); + m_points.add(point_d(x3, y3)); + } + //------------------------------------------------------------------------ + void curve4_inc::approximation_scale(double s) + { + m_scale = s; + } + //------------------------------------------------------------------------ + double curve4_inc::approximation_scale() const + { + return m_scale; + } + //------------------------------------------------------------------------ + static double MSC60_fix_ICE(double v) { return v; } //------------------------------------------------------------------------ - void curve4::init(double x1, double y1, - double x2, double y2, - double x3, double y3, - double x4, double y4) + void curve4_inc::init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) { m_start_x = x1; m_start_y = y1; @@ -144,15 +273,19 @@ namespace agg double dx3 = x4 - x3; double dy3 = y4 - y3; - double len = sqrt(dx1 * dx1 + dy1 * dy1) + - sqrt(dx2 * dx2 + dy2 * dy2) + - sqrt(dx3 * dx3 + dy3 * dy3); + double len = (sqrt(dx1 * dx1 + dy1 * dy1) + + sqrt(dx2 * dx2 + dy2 * dy2) + + sqrt(dx3 * dx3 + dy3 * dy3)) * 0.25 * m_scale; - m_num_steps = int(len * 0.25 * m_scale); +#if defined(_MSC_VER) && _MSC_VER <= 1200 + m_num_steps = uround(MSC60_fix_ICE(len)); +#else + m_num_steps = uround(len); +#endif - if(m_num_steps < 2) + if(m_num_steps < 4) { - m_num_steps = 2; + m_num_steps = 4; } double subdivide_step = 1.0 / m_num_steps; @@ -185,11 +318,8 @@ namespace agg m_step = m_num_steps; } - - - //------------------------------------------------------------------------ - void curve4::rewind(unsigned) + void curve4_inc::rewind(unsigned) { if(m_num_steps == 0) { @@ -205,12 +335,8 @@ namespace agg m_ddfy = m_saved_ddfy; } - - - - //------------------------------------------------------------------------ - unsigned curve4::vertex(double* x, double* y) + unsigned curve4_inc::vertex(double* x, double* y) { if(m_step < 0) return path_cmd_stop; if(m_step == m_num_steps) @@ -220,6 +346,7 @@ namespace agg --m_step; return path_cmd_move_to; } + if(m_step == 0) { *x = m_end_x; @@ -227,12 +354,14 @@ namespace agg --m_step; return path_cmd_line_to; } + m_fx += m_dfx; m_fy += m_dfy; m_dfx += m_ddfx; m_dfy += m_ddfy; m_ddfx += m_dddfx; m_ddfy += m_dddfy; + *x = m_fx; *y = m_fy; --m_step; @@ -242,5 +371,241 @@ namespace agg + //------------------------------------------------------------------------ + void curve4_div::init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_points.remove_all(); + m_distance_tolerance_square = 0.5 / m_approximation_scale; + m_distance_tolerance_square *= m_distance_tolerance_square; + 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, + double x3, double y3, + double x4, double y4, + unsigned level) + { + if(level > curve_recursion_limit) + { + return; + } + + // Calculate all the mid-points of the line segments + //---------------------- + double x12 = (x1 + x2) / 2; + double y12 = (y1 + y2) / 2; + double x23 = (x2 + x3) / 2; + double y23 = (y2 + y3) / 2; + double x34 = (x3 + x4) / 2; + double y34 = (y3 + y4) / 2; + double x123 = (x12 + x23) / 2; + double y123 = (y12 + y23) / 2; + double x234 = (x23 + x34) / 2; + double y234 = (y23 + y34) / 2; + 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; + double dy = y4-y1; + + double d2 = fabs(((x2 - x4) * dy - (y2 - y4) * dx)); + double d3 = fabs(((x3 - x4) * dy - (y3 - y4) * dx)); + double da1, da2, k; + + switch((int(d2 > curve_collinearity_epsilon) << 1) + + int(d3 > curve_collinearity_epsilon)) + { + case 0: + // All collinear OR p1==p4 + //---------------------- + k = dx*dx + dy*dy; + if(k == 0) + { + 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 significant + //---------------------- + if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x23, y23)); + return; + } + + // Angle Condition + //---------------------- + da1 = fabs(atan2(y4 - y3, x4 - x3) - atan2(y3 - y2, x3 - x2)); + if(da1 >= pi) da1 = 2*pi - da1; + + if(da1 < m_angle_tolerance) + { + m_points.add(point_d(x2, y2)); + m_points.add(point_d(x3, y3)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.add(point_d(x3, y3)); + return; + } + } + } + break; + + case 2: + // p1,p3,p4 are collinear, p2 is significant + //---------------------- + if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x23, y23)); + return; + } + + // Angle Condition + //---------------------- + da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); + if(da1 >= pi) da1 = 2*pi - da1; + + if(da1 < m_angle_tolerance) + { + m_points.add(point_d(x2, y2)); + m_points.add(point_d(x3, y3)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.add(point_d(x2, y2)); + return; + } + } + } + break; + + case 3: + // Regular case + //----------------- + if((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + // If the curvature doesn't exceed the distance_tolerance value + // we tend to finish subdivisions. + //---------------------- + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x23, y23)); + return; + } + + // Angle & Cusp Condition + //---------------------- + 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; + + if(da1 + da2 < m_angle_tolerance) + { + // Finally we can stop the recursion + //---------------------- + m_points.add(point_d(x23, y23)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.add(point_d(x2, y2)); + return; + } + + if(da2 > m_cusp_limit) + { + m_points.add(point_d(x3, y3)); + return; + } + } + } + break; + } + + // Continue subdivision + //---------------------- + recursive_bezier(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1); + recursive_bezier(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1); + } + + //------------------------------------------------------------------------ + void curve4_div::bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_points.add(point_d(x1, y1)); + recursive_bezier(x1, y1, x2, y2, x3, y3, x4, y4, 0); + m_points.add(point_d(x4, y4)); + } + } diff --git a/agg/source/agg_embedded_raster_fonts.cpp b/agg/source/agg_embedded_raster_fonts.cpp index b1060fb7e176..cb592fcdbf29 100755 --- a/agg/source/agg_embedded_raster_fonts.cpp +++ b/agg/source/agg_embedded_raster_fonts.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/source/agg_gsv_text.cpp b/agg/source/agg_gsv_text.cpp index fd522cd8de08..6fcbfa5009bf 100755 --- a/agg/source/agg_gsv_text.cpp +++ b/agg/source/agg_gsv_text.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -19,6 +19,8 @@ #include <string.h> #include <stdio.h> #include "agg_gsv_text.h" +#include "agg_bounding_rect.h" + namespace agg @@ -480,16 +482,6 @@ namespace agg 0xf6,0xfa,0x04,0x06,0x08,0xfa }; - - - //------------------------------------------------------------------------- - gsv_text::~gsv_text() - { - if(m_loaded_font) delete [] m_loaded_font; - if(m_text_buf) delete [] m_text_buf; - } - - //------------------------------------------------------------------------- gsv_text::gsv_text() : m_x(0.0), @@ -500,11 +492,10 @@ namespace agg m_space(0.0), m_line_space(0.0), m_text(m_chr), - m_text_buf(0), - m_buf_size(0), + m_text_buf(), m_cur_chr(m_chr), m_font(gsv_default_font), - m_loaded_font(0), + m_loaded_font(), m_status(initial), m_big_endian(false), m_flip(false) @@ -515,13 +506,11 @@ namespace agg if(*(char*)&t == 0) m_big_endian = true; } - - //------------------------------------------------------------------------- - void gsv_text::font(const void* _font) + void gsv_text::font(const void* font) { - m_font = _font; - if(m_font == 0) m_font = m_loaded_font; + m_font = font; + if(m_font == 0) m_font = &m_loaded_font[0]; } //------------------------------------------------------------------------- @@ -532,15 +521,15 @@ namespace agg } //------------------------------------------------------------------------- - void gsv_text::space(double _space) + void gsv_text::space(double space) { - m_space = _space; + m_space = space; } //------------------------------------------------------------------------- - void gsv_text::line_space(double _line_space) + void gsv_text::line_space(double line_space) { - m_line_space = _line_space; + m_line_space = line_space; } //------------------------------------------------------------------------- @@ -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,36 +554,32 @@ 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) + void gsv_text::text(const char* text) { - if(_text == 0) + if(text == 0) { m_chr[0] = 0; m_text = m_chr; return; } - unsigned new_size = strlen(_text) + 1; - if(new_size > m_buf_size) + unsigned new_size = strlen(text) + 1; + if(new_size > m_text_buf.size()) { - if(m_text_buf) delete [] m_text_buf; - m_text_buf = new char [m_buf_size = new_size]; + m_text_buf.resize(new_size); } - memcpy(m_text_buf, _text, new_size); - m_text = m_text_buf; + memcpy(&m_text_buf[0], text, new_size); + m_text = &m_text_buf[0]; } - - //------------------------------------------------------------------------- void gsv_text::rewind(unsigned) { @@ -614,7 +596,6 @@ namespace agg m_cur_chr = m_text; } - //------------------------------------------------------------------------- unsigned gsv_text::vertex(double* x, double* y) { @@ -623,7 +604,6 @@ namespace agg int dx, dy; bool quit = false; - while(!quit) { switch(m_status) @@ -683,6 +663,13 @@ namespace agg return path_cmd_stop; } + //------------------------------------------------------------------------- + double gsv_text::text_width() + { + double x1, y1, x2, y2; + bounding_rect_single(*this, 0, &x1, &y1, &x2, &y2); + return x2 - x1; + } } diff --git a/agg/source/agg_image_filters.cpp b/agg/source/agg_image_filters.cpp index 28dd0654eeb4..234c12bf61b3 100755 --- a/agg/source/agg_image_filters.cpp +++ b/agg/source/agg_image_filters.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -23,32 +23,16 @@ 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(double _radius) + void image_filter_lut::realloc_lut(double radius) { - m_radius = _radius; - m_diameter = unsigned(ceil(_radius)) * 2; + m_radius = radius; + 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); } } @@ -66,7 +50,7 @@ namespace agg unsigned i; int flip = 1; - for(i = 0; i < image_subpixel_size; i++) + for(i = 0; i < image_subpixel_scale; i++) { for(;;) { @@ -74,31 +58,30 @@ namespace agg unsigned j; for(j = 0; j < m_diameter; j++) { - sum += m_weight_array[j * image_subpixel_size + i]; + sum += m_weight_array[j * image_subpixel_scale + i]; } - if(sum == image_filter_size) break; + if(sum == image_filter_scale) break; - double k = double(image_filter_size) / double(sum); + double k = double(image_filter_scale) / double(sum); sum = 0; for(j = 0; j < m_diameter; j++) { - sum += m_weight_array[j * image_subpixel_size + i] = - int16(m_weight_array[j * image_subpixel_size + i] * k); + sum += m_weight_array[j * image_subpixel_scale + i] = + iround(m_weight_array[j * image_subpixel_scale + i] * k); } - sum -= image_filter_size; - int16 inc = (sum > 0) ? -1 : 1; + sum -= image_filter_scale; + int inc = (sum > 0) ? -1 : 1; for(j = 0; j < m_diameter && sum; j++) { flip ^= 1; unsigned idx = flip ? m_diameter/2 + j/2 : m_diameter/2 - j/2; - int v = m_weight_array[idx * image_subpixel_size + i]; - if(v < image_filter_size) + int v = m_weight_array[idx * image_subpixel_scale + i]; + if(v < image_filter_scale) { - m_weight_array[idx * image_subpixel_size + i] = - m_weight_array[idx * image_subpixel_size + i] + inc; + m_weight_array[idx * image_subpixel_scale + i] += inc; sum += inc; } } diff --git a/agg/source/agg_line_aa_basics.cpp b/agg/source/agg_line_aa_basics.cpp index 34103178d7b7..ee6fae5b8161 100755 --- a/agg/source/agg_line_aa_basics.cpp +++ b/agg/source/agg_line_aa_basics.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -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 }; @@ -69,14 +69,14 @@ namespace agg // Check if the bisectrix is too short double dx = tx - l2.x1; double dy = ty - l2.y1; - if((int)sqrt(dx * dx + dy * dy) < line_subpixel_size) + if((int)sqrt(dx * dx + dy * dy) < line_subpixel_scale) { *x = (l2.x1 + l2.x1 + (l2.y1 - l1.y1) + (l2.y2 - l2.y1)) >> 1; *y = (l2.y1 + l2.y1 - (l2.x1 - l1.x1) - (l2.x2 - l2.x1)) >> 1; return; } - *x = int(tx); - *y = int(ty); + *x = iround(tx); + *y = iround(ty); } } diff --git a/agg/source/agg_line_profile_aa.cpp b/agg/source/agg_line_profile_aa.cpp index 1374475b663f..570524b2fdf4 100755 --- a/agg/source/agg_line_profile_aa.cpp +++ b/agg/source/agg_line_profile_aa.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -42,39 +42,38 @@ namespace agg //--------------------------------------------------------------------- line_profile_aa::value_type* line_profile_aa::profile(double w) { - m_subpixel_width = int(w * subpixel_size); - unsigned size = m_subpixel_width + subpixel_size * 6; - if(size > m_size) + m_subpixel_width = uround(w * subpixel_scale); + unsigned size = m_subpixel_width + subpixel_scale * 6; + 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]; } //--------------------------------------------------------------------- - void line_profile_aa::set(double center_width, double _smoother_width) + void line_profile_aa::set(double center_width, double smoother_width) { double base_val = 1.0; - if(center_width == 0.0) center_width = 1.0 / subpixel_size; - if(_smoother_width == 0.0) _smoother_width = 1.0 / subpixel_size; + if(center_width == 0.0) center_width = 1.0 / subpixel_scale; + if(smoother_width == 0.0) smoother_width = 1.0 / subpixel_scale; - double _width = center_width + _smoother_width; - if(_width < m_min_width) + double width = center_width + smoother_width; + if(width < m_min_width) { - double k = _width / m_min_width; + double k = width / m_min_width; base_val *= k; center_width /= k; - _smoother_width /= k; + smoother_width /= k; } - value_type* ch = profile(center_width + _smoother_width); + value_type* ch = profile(center_width + smoother_width); - unsigned subpixel_center_width = unsigned(center_width * subpixel_size); - unsigned subpixel_smoother_width = unsigned(_smoother_width * subpixel_size); + unsigned subpixel_center_width = unsigned(center_width * subpixel_scale); + unsigned subpixel_smoother_width = unsigned(smoother_width * subpixel_scale); - value_type* ch_center = ch + subpixel_size*2; + value_type* ch_center = ch + subpixel_scale*2; value_type* ch_smoother = ch_center + subpixel_center_width; unsigned i; @@ -97,7 +96,7 @@ namespace agg unsigned n_smoother = profile_size() - subpixel_smoother_width - subpixel_center_width - - subpixel_size*2; + subpixel_scale*2; val = m_gamma[0]; for(i = 0; i < n_smoother; i++) @@ -106,7 +105,7 @@ namespace agg } ch = ch_center; - for(i = 0; i < subpixel_size*2; i++) + for(i = 0; i < subpixel_scale*2; i++) { *--ch = *ch_center++; } diff --git a/agg/source/agg_path_storage.cpp b/agg/source/agg_path_storage.cpp deleted file mode 100755 index 60eafffff14f..000000000000 --- a/agg/source/agg_path_storage.cpp +++ /dev/null @@ -1,525 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Class path_storage -// -//---------------------------------------------------------------------------- -#include <string.h> -#include <math.h> -#include "agg_path_storage.h" -#include "agg_math.h" -#include "agg_bezier_arc.h" - - -namespace agg -{ - - //------------------------------------------------------------------------ - path_storage::~path_storage() - { - if(m_total_blocks) - { - double** coord_blk = m_coord_blocks + m_total_blocks - 1; - while(m_total_blocks--) - { - delete [] *coord_blk; - --coord_blk; - } - delete [] m_coord_blocks; - } - } - - - //------------------------------------------------------------------------ - path_storage::path_storage() : - m_total_vertices(0), - m_total_blocks(0), - m_max_blocks(0), - m_coord_blocks(0), - m_cmd_blocks(0), - m_iterator(0) - { - } - - - //------------------------------------------------------------------------ - path_storage::path_storage(const path_storage& ps) : - m_total_vertices(0), - m_total_blocks(0), - m_max_blocks(0), - m_coord_blocks(0), - m_cmd_blocks(0), - m_iterator(0) - { - copy_from(ps); - } - - - //------------------------------------------------------------------------ - void path_storage::remove_all() - { - m_total_vertices = 0; - m_iterator = 0; - } - - - //------------------------------------------------------------------------ - void path_storage::copy_from(const path_storage& ps) - { - remove_all(); - unsigned i; - for(i = 0; i < ps.total_vertices(); i++) - { - double x, y; - unsigned cmd = ps.vertex(i, &x, &y); - add_vertex(x, y, cmd); - } - } - - - //------------------------------------------------------------------------ - void path_storage::allocate_block(unsigned nb) - { - if(nb >= m_max_blocks) - { - double** new_coords = - new double* [(m_max_blocks + block_pool) * 2]; - - unsigned char** new_cmds = - (unsigned char**)(new_coords + m_max_blocks + block_pool); - - if(m_coord_blocks) - { - memcpy(new_coords, - m_coord_blocks, - m_max_blocks * sizeof(double*)); - - memcpy(new_cmds, - m_cmd_blocks, - m_max_blocks * sizeof(unsigned char*)); - - delete [] m_coord_blocks; - } - m_coord_blocks = new_coords; - m_cmd_blocks = new_cmds; - m_max_blocks += block_pool; - } - m_coord_blocks[nb] = - new double [block_size * 2 + - block_size / - (sizeof(double) / sizeof(unsigned char))]; - - m_cmd_blocks[nb] = - (unsigned char*)(m_coord_blocks[nb] + block_size * 2); - - m_total_blocks++; - } - - - //------------------------------------------------------------------------ - void path_storage::rewind(unsigned path_id) - { - m_iterator = path_id; - } - - - - //------------------------------------------------------------------------ - void path_storage::arc_to(double rx, double ry, - double angle, - bool large_arc_flag, - bool sweep_flag, - double x, double y) - { - if(m_total_vertices && is_vertex(command(m_total_vertices - 1))) - { - const double epsilon = 1e-30; - double x0 = 0.0; - double y0 = 0.0; - last_vertex(&x0, &y0); - - rx = fabs(rx); - ry = fabs(ry); - - // Ensure radii are valid - //------------------------- - if(rx < epsilon || ry < epsilon) - { - line_to(x, y); - return; - } - - if(calc_distance(x0, y0, x, y) < epsilon) - { - // If the endpoints (x, y) and (x0, y0) are identical, then this - // is equivalent to omitting the elliptical arc segment entirely. - return; - } - bezier_arc_svg a(x0, y0, rx, ry, angle, large_arc_flag, sweep_flag, x, y); - if(a.radii_ok()) - { - add_path(a, 0, true); - } - else - { - line_to(x, y); - } - } - else - { - move_to(x, y); - } - } - - - //------------------------------------------------------------------------ - void path_storage::arc_rel(double rx, double ry, - double angle, - bool large_arc_flag, - bool sweep_flag, - double dx, double dy) - { - rel_to_abs(&dx, &dy); - arc_to(rx, ry, angle, large_arc_flag, sweep_flag, dx, dy); - } - - - //------------------------------------------------------------------------ - void path_storage::curve3(double x_ctrl, double y_ctrl, - double x_to, double y_to) - { - add_vertex(x_ctrl, y_ctrl, path_cmd_curve3); - add_vertex(x_to, y_to, path_cmd_curve3); - } - - //------------------------------------------------------------------------ - void path_storage::curve3_rel(double dx_ctrl, double dy_ctrl, - double dx_to, double dy_to) - { - rel_to_abs(&dx_ctrl, &dy_ctrl); - rel_to_abs(&dx_to, &dy_to); - add_vertex(dx_ctrl, dy_ctrl, path_cmd_curve3); - add_vertex(dx_to, dy_to, path_cmd_curve3); - } - - //------------------------------------------------------------------------ - void path_storage::curve3(double x_to, double y_to) - { - double x0 = 0; - double y0 = 0; - if(is_vertex(last_vertex(&x0, &y0))) - { - double x_ctrl = 0; - double y_ctrl = 0; - unsigned cmd = prev_vertex(&x_ctrl, &y_ctrl); - if(is_curve(cmd)) - { - x_ctrl = x0 + x0 - x_ctrl; - y_ctrl = y0 + y0 - y_ctrl; - } - else - { - x_ctrl = x0; - y_ctrl = y0; - } - curve3(x_ctrl, y_ctrl, x_to, y_to); - } - } - - - //------------------------------------------------------------------------ - void path_storage::curve3_rel(double dx_to, double dy_to) - { - rel_to_abs(&dx_to, &dy_to); - curve3(dx_to, dy_to); - } - - - //------------------------------------------------------------------------ - void path_storage::curve4(double x_ctrl1, double y_ctrl1, - double x_ctrl2, double y_ctrl2, - double x_to, double y_to) - { - add_vertex(x_ctrl1, y_ctrl1, path_cmd_curve4); - add_vertex(x_ctrl2, y_ctrl2, path_cmd_curve4); - add_vertex(x_to, y_to, path_cmd_curve4); - } - - //------------------------------------------------------------------------ - void path_storage::curve4_rel(double dx_ctrl1, double dy_ctrl1, - double dx_ctrl2, double dy_ctrl2, - double dx_to, double dy_to) - { - rel_to_abs(&dx_ctrl1, &dy_ctrl1); - rel_to_abs(&dx_ctrl2, &dy_ctrl2); - rel_to_abs(&dx_to, &dy_to); - add_vertex(dx_ctrl1, dy_ctrl1, path_cmd_curve4); - add_vertex(dx_ctrl2, dy_ctrl2, path_cmd_curve4); - add_vertex(dx_to, dy_to, path_cmd_curve4); - } - - - //------------------------------------------------------------------------ - void path_storage::curve4(double x_ctrl2, double y_ctrl2, - double x_to, double y_to) - { - double x0 = 0; - double y0 = 0; - if(is_vertex(last_vertex(&x0, &y0))) - { - double x_ctrl1 = 0; - double y_ctrl1 = 0; - unsigned cmd = prev_vertex(&x_ctrl1, &y_ctrl1); - if(is_curve(cmd)) - { - x_ctrl1 = x0 + x0 - x_ctrl1; - y_ctrl1 = y0 + y0 - y_ctrl1; - } - else - { - x_ctrl1 = x0; - y_ctrl1 = y0; - } - curve4(x_ctrl1, y_ctrl1, x_ctrl2, y_ctrl2, x_to, y_to); - } - } - - - //------------------------------------------------------------------------ - void path_storage::curve4_rel(double dx_ctrl2, double dy_ctrl2, - double dx_to, double dy_to) - { - rel_to_abs(&dx_ctrl2, &dy_ctrl2); - rel_to_abs(&dx_to, &dy_to); - curve4(dx_ctrl2, dy_ctrl2, dx_to, dy_to); - } - - - //------------------------------------------------------------------------ - void path_storage::end_poly(unsigned flags) - { - if(m_total_vertices) - { - if(is_vertex(command(m_total_vertices - 1))) - { - add_vertex(0.0, 0.0, path_cmd_end_poly | flags); - } - } - } - - - //------------------------------------------------------------------------ - unsigned path_storage::start_new_path() - { - if(m_total_vertices) - { - if(!is_stop(command(m_total_vertices - 1))) - { - add_vertex(0.0, 0.0, path_cmd_stop); - } - } - return m_total_vertices; - } - - - //------------------------------------------------------------------------ - void path_storage::add_poly(const double* vertices, unsigned num, - bool solid_path, unsigned end_flags) - { - if(num) - { - if(!solid_path) - { - move_to(vertices[0], vertices[1]); - vertices += 2; - --num; - } - while(num--) - { - line_to(vertices[0], vertices[1]); - vertices += 2; - } - if(end_flags) end_poly(end_flags); - } - } - - - //------------------------------------------------------------------------ - unsigned path_storage::perceive_polygon_orientation(unsigned idx, - double xs, double ys, - unsigned* orientation) - { - unsigned i; - double sum = 0.0; - double x, y, xn, yn; - - x = xs; - y = ys; - for(i = idx; i < m_total_vertices; ++i) - { - if(is_next_poly(vertex(i, &xn, &yn))) break; - sum += x * yn - y * xn; - x = xn; - y = yn; - } - if(i > idx) sum += x * ys - y * xs; - *orientation = path_flags_none; - if(sum != 0.0) - { - *orientation = (sum < 0.0) ? path_flags_cw : path_flags_ccw; - } - return i; - } - - - //------------------------------------------------------------------------ - void path_storage::reverse_polygon(unsigned _start, unsigned _end) - { - unsigned i; - unsigned tmp_cmd = command(_start); - - // Shift all commands to one position - for(i = _start; i < _end; i++) - { - modify_command(i, command(i + 1)); - } - - // Assign starting command to the ending command - modify_command(_end, tmp_cmd); - - // Reverse the polygon - while(_end > _start) - { - unsigned start_nb = _start >> block_shift; - unsigned end_nb = _end >> block_shift; - double* start_ptr = m_coord_blocks[start_nb] + ((_start & block_mask) << 1); - double* end_ptr = m_coord_blocks[end_nb] + ((_end & block_mask) << 1); - double tmp_xy; - - tmp_xy = *start_ptr; - *start_ptr++ = *end_ptr; - *end_ptr++ = tmp_xy; - - tmp_xy = *start_ptr; - *start_ptr = *end_ptr; - *end_ptr = tmp_xy; - - tmp_cmd = m_cmd_blocks[start_nb][_start & block_mask]; - m_cmd_blocks[start_nb][_start & block_mask] = m_cmd_blocks[end_nb][_end & block_mask]; - m_cmd_blocks[end_nb][_end & block_mask] = (unsigned char)tmp_cmd; - - ++_start; - --_end; - } - } - - - //------------------------------------------------------------------------ - unsigned path_storage::arrange_orientations(unsigned path_id, - path_flags_e new_orientation) - { - unsigned _end = m_total_vertices; - if(m_total_vertices && new_orientation != path_flags_none) - { - unsigned start = path_id; - - double xs, ys; - unsigned cmd = vertex(start, &xs, &ys); - unsigned inc = 0; - for(;;) - { - unsigned orientation; - _end = perceive_polygon_orientation(start + 1, xs, ys, - &orientation); - if(_end > start + 2 && - orientation && - orientation != unsigned(new_orientation)) - { - reverse_polygon(start + inc, _end - 1); - } - if(_end >= m_total_vertices) break; - cmd = command(_end); - if(is_stop(cmd)) - { - ++_end; - break; - } - if(is_end_poly(cmd)) - { - inc = 1; - modify_command(_end, set_orientation(cmd, new_orientation)); - } - else - { - cmd = vertex(++_end, &xs, &ys); - inc = 0; - } - start = _end; - } - } - return _end; - } - - - - //------------------------------------------------------------------------ - void path_storage::arrange_orientations_all_paths(path_flags_e new_orientation) - { - if(new_orientation != path_flags_none) - { - unsigned start = 0; - while(start < m_total_vertices) - { - start = arrange_orientations(start, new_orientation); - } - } - } - - - - //------------------------------------------------------------------------ - void path_storage::flip_x(double x1, double x2) - { - unsigned i; - double x, y; - for(i = 0; i < m_total_vertices; i++) - { - unsigned cmd = vertex(i, &x, &y); - if(is_vertex(cmd)) - { - modify_vertex(i, x2 - x + x1, y); - } - } - } - - - //------------------------------------------------------------------------ - void path_storage::flip_y(double y1, double y2) - { - unsigned i; - double x, y; - for(i = 0; i < m_total_vertices; i++) - { - unsigned cmd = vertex(i, &x, &y); - if(is_vertex(cmd)) - { - modify_vertex(i, x, y2 - y + y1); - } - } - } - - -} - diff --git a/agg/source/agg_rasterizer_scanline_aa.cpp b/agg/source/agg_rasterizer_scanline_aa.cpp deleted file mode 100755 index 421c0187d0aa..000000000000 --- a/agg/source/agg_rasterizer_scanline_aa.cpp +++ /dev/null @@ -1,621 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// The author gratefully acknowleges the support of David Turner, -// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType -// libray - in producing this work. See http://www.freetype.org for details. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// Class outline_aa - implementation. -// -// Initially the rendering algorithm was designed by David Turner and the -// other authors of the FreeType library - see the above notice. I nearly -// created a similar renderer, but still I was far from David's work. -// I completely redesigned the original code and adapted it for Anti-Grain -// ideas. Two functions - render_line and render_hline are the core of -// the algorithm - they calculate the exact coverage of each pixel cell -// of the polygon. I left these functions almost as is, because there's -// no way to improve the perfection - hats off to David and his group! -// -// All other code is very different from the original. -// -//---------------------------------------------------------------------------- - -#include <string.h> -#include "agg_rasterizer_scanline_aa.h" - - -namespace agg -{ - - //------------------------------------------------------------------------ - AGG_INLINE void cell_aa::set_cover(int c, int a) - { - cover = c; - area = a; - } - - //------------------------------------------------------------------------ - AGG_INLINE void cell_aa::add_cover(int c, int a) - { - cover += c; - area += a; - } - - //------------------------------------------------------------------------ - AGG_INLINE void cell_aa::set_coord(int cx, int cy) - { - x = int16(cx); - y = int16(cy); - packed_coord = (cy << 16) + cx; - } - - //------------------------------------------------------------------------ - AGG_INLINE void cell_aa::set(int cx, int cy, int c, int a) - { - x = int16(cx); - y = int16(cy); - packed_coord = (cy << 16) + cx; - cover = c; - area = a; - } - - //------------------------------------------------------------------------ - outline_aa::~outline_aa() - { - delete [] m_sorted_cells; - if(m_num_blocks) - { - cell_aa** ptr = m_cells + m_num_blocks - 1; - while(m_num_blocks--) - { - delete [] *ptr; - ptr--; - } - delete [] m_cells; - } - } - - - //------------------------------------------------------------------------ - outline_aa::outline_aa() : - m_num_blocks(0), - m_max_blocks(0), - m_cur_block(0), - m_num_cells(0), - m_cells(0), - m_cur_cell_ptr(0), - m_sorted_cells(0), - m_sorted_size(0), - m_cur_x(0), - m_cur_y(0), - m_min_x(0x7FFFFFFF), - m_min_y(0x7FFFFFFF), - m_max_x(-0x7FFFFFFF), - m_max_y(-0x7FFFFFFF), - m_sorted(false) - { - m_cur_cell.set(0x7FFF, 0x7FFF, 0, 0); - } - - - //------------------------------------------------------------------------ - void outline_aa::reset() - { - m_num_cells = 0; - m_cur_block = 0; - m_cur_cell.set(0x7FFF, 0x7FFF, 0, 0); - m_sorted = false; - m_min_x = 0x7FFFFFFF; - m_min_y = 0x7FFFFFFF; - m_max_x = -0x7FFFFFFF; - m_max_y = -0x7FFFFFFF; - } - - - - //------------------------------------------------------------------------ - void outline_aa::allocate_block() - { - if(m_cur_block >= m_num_blocks) - { - if(m_num_blocks >= m_max_blocks) - { - cell_aa** new_cells = new cell_aa* [m_max_blocks + cell_block_pool]; - if(m_cells) - { - memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_aa*)); - delete [] m_cells; - } - m_cells = new_cells; - m_max_blocks += cell_block_pool; - } - m_cells[m_num_blocks++] = new cell_aa [unsigned(cell_block_size)]; - } - m_cur_cell_ptr = m_cells[m_cur_block++]; - } - - - //------------------------------------------------------------------------ - AGG_INLINE void outline_aa::add_cur_cell() - { - if(m_cur_cell.area | m_cur_cell.cover) - { - if((m_num_cells & cell_block_mask) == 0) - { - if(m_num_blocks >= cell_block_limit) return; - allocate_block(); - } - *m_cur_cell_ptr++ = m_cur_cell; - ++m_num_cells; - if(m_cur_cell.x < m_min_x) m_min_x = m_cur_cell.x; - if(m_cur_cell.x > m_max_x) m_max_x = m_cur_cell.x; - } - } - - - - //------------------------------------------------------------------------ - AGG_INLINE void outline_aa::set_cur_cell(int x, int y) - { - if(m_cur_cell.packed_coord != (y << 16) + x) - { - add_cur_cell(); - m_cur_cell.set(x, y, 0, 0); - } - } - - - - //------------------------------------------------------------------------ - AGG_INLINE void outline_aa::render_hline(int ey, int x1, int y1, int x2, int y2) - { - int ex1 = x1 >> poly_base_shift; - int ex2 = x2 >> poly_base_shift; - int fx1 = x1 & poly_base_mask; - int fx2 = x2 & poly_base_mask; - - int delta, p, first, dx; - int incr, lift, mod, rem; - - //trivial case. Happens often - if(y1 == y2) - { - set_cur_cell(ex2, ey); - return; - } - - //everything is located in a single cell. That is easy! - if(ex1 == ex2) - { - delta = y2 - y1; - m_cur_cell.add_cover(delta, (fx1 + fx2) * delta); - return; - } - - //ok, we'll have to render a run of adjacent cells on the same - //hline... - p = (poly_base_size - fx1) * (y2 - y1); - first = poly_base_size; - incr = 1; - - dx = x2 - x1; - - if(dx < 0) - { - p = fx1 * (y2 - y1); - first = 0; - incr = -1; - dx = -dx; - } - - delta = p / dx; - mod = p % dx; - - if(mod < 0) - { - delta--; - mod += dx; - } - - m_cur_cell.add_cover(delta, (fx1 + first) * delta); - - ex1 += incr; - set_cur_cell(ex1, ey); - y1 += delta; - - if(ex1 != ex2) - { - p = poly_base_size * (y2 - y1 + delta); - lift = p / dx; - rem = p % dx; - - if (rem < 0) - { - lift--; - rem += dx; - } - - mod -= dx; - - while (ex1 != ex2) - { - delta = lift; - mod += rem; - if(mod >= 0) - { - mod -= dx; - delta++; - } - - m_cur_cell.add_cover(delta, (poly_base_size) * delta); - y1 += delta; - ex1 += incr; - set_cur_cell(ex1, ey); - } - } - delta = y2 - y1; - m_cur_cell.add_cover(delta, (fx2 + poly_base_size - first) * delta); - } - - - - - - - //------------------------------------------------------------------------ - void outline_aa::render_line(int x1, int y1, int x2, int y2) - { - int ey1 = y1 >> poly_base_shift; - int ey2 = y2 >> poly_base_shift; - int fy1 = y1 & poly_base_mask; - int fy2 = y2 & poly_base_mask; - - int dx, dy, x_from, x_to; - int p, rem, mod, lift, delta, first, incr; - - dx = x2 - x1; - dy = y2 - y1; - - //everything is on a single hline - if(ey1 == ey2) - { - render_hline(ey1, x1, fy1, x2, fy2); - return; - } - - //Vertical line - we have to calculate start and end cells, - //and then - the common values of the area and coverage for - //all cells of the line. We know exactly there's only one - //cell, so, we don't have to call render_hline(). - incr = 1; - if(dx == 0) - { - int ex = x1 >> poly_base_shift; - int two_fx = (x1 - (ex << poly_base_shift)) << 1; - int area; - - first = poly_base_size; - if(dy < 0) - { - first = 0; - incr = -1; - } - - x_from = x1; - - //render_hline(ey1, x_from, fy1, x_from, first); - delta = first - fy1; - m_cur_cell.add_cover(delta, two_fx * delta); - - ey1 += incr; - set_cur_cell(ex, ey1); - - delta = first + first - poly_base_size; - area = two_fx * delta; - while(ey1 != ey2) - { - //render_hline(ey1, x_from, poly_base_size - first, x_from, first); - m_cur_cell.set_cover(delta, area); - ey1 += incr; - set_cur_cell(ex, ey1); - } - //render_hline(ey1, x_from, poly_base_size - first, x_from, fy2); - delta = fy2 - poly_base_size + first; - m_cur_cell.add_cover(delta, two_fx * delta); - return; - } - - //ok, we have to render several hlines - p = (poly_base_size - fy1) * dx; - first = poly_base_size; - - if(dy < 0) - { - p = fy1 * dx; - first = 0; - incr = -1; - dy = -dy; - } - - delta = p / dy; - mod = p % dy; - - if(mod < 0) - { - delta--; - mod += dy; - } - - x_from = x1 + delta; - render_hline(ey1, x1, fy1, x_from, first); - - ey1 += incr; - set_cur_cell(x_from >> poly_base_shift, ey1); - - if(ey1 != ey2) - { - p = poly_base_size * dx; - lift = p / dy; - rem = p % dy; - - if(rem < 0) - { - lift--; - rem += dy; - } - mod -= dy; - - while(ey1 != ey2) - { - delta = lift; - mod += rem; - if (mod >= 0) - { - mod -= dy; - delta++; - } - - x_to = x_from + delta; - render_hline(ey1, x_from, poly_base_size - first, x_to, first); - x_from = x_to; - - ey1 += incr; - set_cur_cell(x_from >> poly_base_shift, ey1); - } - } - render_hline(ey1, x_from, poly_base_size - first, x2, fy2); - } - - - //------------------------------------------------------------------------ - void outline_aa::move_to(int x, int y) - { - if(m_sorted) reset(); - set_cur_cell(x >> poly_base_shift, y >> poly_base_shift); - m_cur_x = x; - m_cur_y = y; - } - - - - //------------------------------------------------------------------------ - void outline_aa::line_to(int x, int y) - { - render_line(m_cur_x, m_cur_y, x, y); - m_cur_x = x; - m_cur_y = y; - m_sorted = false; - } - - - //------------------------------------------------------------------------ - enum - { - qsort_threshold = 9 - }; - - - //------------------------------------------------------------------------ - template <class T> AGG_INLINE void swap_cells(T* a, T* b) - { - T temp = *a; - *a = *b; - *b = temp; - } - - //------------------------------------------------------------------------ - template <class T> AGG_INLINE bool less_than(T* a, T* b) - { - return (*a)->packed_coord < (*b)->packed_coord; - } - - - - //------------------------------------------------------------------------ - void outline_aa::qsort_cells(cell_aa** start, unsigned num) - { - cell_aa** stack[80]; - cell_aa*** top; - cell_aa** limit; - cell_aa** base; - - limit = start + num; - base = start; - top = stack; - - for (;;) - { - int len = int(limit - base); - - cell_aa** i; - cell_aa** j; - cell_aa** pivot; - - if(len > qsort_threshold) - { - // we use base + len/2 as the pivot - pivot = base + len / 2; - swap_cells(base, pivot); - - i = base + 1; - j = limit - 1; - - // now ensure that *i <= *base <= *j - if(less_than(j, i)) - { - swap_cells(i, j); - } - - if(less_than(base, i)) - { - swap_cells(base, i); - } - - if(less_than(j, base)) - { - swap_cells(base, j); - } - - for(;;) - { - do i++; while( less_than(i, base) ); - do j--; while( less_than(base, j) ); - - if ( i > j ) - { - break; - } - - swap_cells(i, j); - } - - swap_cells(base, j); - - // now, push the largest sub-array - if(j - base > limit - i) - { - top[0] = base; - top[1] = j; - base = i; - } - else - { - top[0] = i; - top[1] = limit; - limit = j; - } - top += 2; - } - else - { - // the sub-array is small, perform insertion sort - j = base; - i = j + 1; - - for(; i < limit; j = i, i++) - { - for(; less_than(j + 1, j); j--) - { - swap_cells(j + 1, j); - if (j == base) - { - break; - } - } - } - if(top > stack) - { - top -= 2; - base = top[0]; - limit = top[1]; - } - else - { - break; - } - } - } - } - - - - - - //------------------------------------------------------------------------ - void outline_aa::sort_cells() - { - if(m_num_cells == 0) return; - if(m_num_cells > m_sorted_size) - { - delete [] m_sorted_cells; - m_sorted_size = m_num_cells; - m_sorted_cells = new cell_aa* [m_num_cells + 1]; - } - - cell_aa** sorted_ptr = m_sorted_cells; - cell_aa** block_ptr = m_cells; - cell_aa* cell_ptr; - - unsigned nb = m_num_cells >> cell_block_shift; - unsigned i; - - while(nb--) - { - cell_ptr = *block_ptr++; - i = cell_block_size; - while(i--) - { - *sorted_ptr++ = cell_ptr++; - } - } - - cell_ptr = *block_ptr++; - i = m_num_cells & cell_block_mask; - while(i--) - { - *sorted_ptr++ = cell_ptr++; - } - m_sorted_cells[m_num_cells] = 0; - qsort_cells(m_sorted_cells, m_num_cells); - m_min_y = m_sorted_cells[0]->y; - m_max_y = m_sorted_cells[m_num_cells - 1]->y; - } - - - - - //------------------------------------------------------------------------ - const cell_aa* const* outline_aa::cells() - { - //Perform sort only the first time. - if(!m_sorted) - { - add_cur_cell(); - sort_cells(); - m_sorted = true; - } - return m_sorted_cells; - } - - - - - -} - - - - - diff --git a/agg/source/agg_rounded_rect.cpp b/agg/source/agg_rounded_rect.cpp index 8f6e532e7096..f1fa6522349d 100755 --- a/agg/source/agg_rounded_rect.cpp +++ b/agg/source/agg_rounded_rect.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -152,7 +152,7 @@ namespace agg else return path_cmd_line_to; case 8: - cmd = (unsigned)path_cmd_end_poly | (unsigned)path_flags_close | (unsigned)path_flags_ccw; + cmd = path_cmd_end_poly | path_flags_close | path_flags_ccw; m_status++; break; } diff --git a/agg/source/agg_sqrt_tables.cpp b/agg/source/agg_sqrt_tables.cpp index e2f88f5a7fef..e5ce8ce6dc57 100755 --- a/agg/source/agg_sqrt_tables.cpp +++ b/agg/source/agg_sqrt_tables.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -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/source/agg_trans_affine.cpp b/agg/source/agg_trans_affine.cpp index f81050d3e42f..d1a8e76bddf9 100755 --- a/agg/source/agg_trans_affine.cpp +++ b/agg/source/agg_trans_affine.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -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) + bool trans_affine::is_identity(double epsilon) const { - return fabs(v1 - v2) < 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_identity(double epsilon) const + bool trans_affine::is_valid(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 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/source/agg_trans_double_path.cpp b/agg/source/agg_trans_double_path.cpp index 5fc83ea50391..1756c61569ff 100755 --- a/agg/source/agg_trans_double_path.cpp +++ b/agg/source/agg_trans_double_path.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -21,10 +21,10 @@ namespace agg //------------------------------------------------------------------------ trans_double_path::trans_double_path() : - m_base_length(0.0), - m_base_height(1.0), m_kindex1(0.0), m_kindex2(0.0), + m_base_length(0.0), + m_base_height(1.0), m_status1(initial), m_status2(initial), m_preserve_x_scale(true) @@ -101,6 +101,7 @@ namespace agg double dist; double d; + vertices.close(false); if(vertices.size() > 2) { if(vertices[vertices.size() - 2].dist * 10.0 < @@ -118,7 +119,6 @@ namespace agg } dist = 0; - vertices.close(false); for(i = 0; i < vertices.size(); i++) { vertex_dist& v = vertices[i]; @@ -228,7 +228,7 @@ namespace agg } else { - i = (unsigned)floor(*x * kindex); + i = unsigned(*x * kindex); j = i + 1; dd = vertices[j].dist - vertices[i].dist; d = ((*x * kindex) - i) * dd; diff --git a/agg/source/agg_trans_single_path.cpp b/agg/source/agg_trans_single_path.cpp index cc4fb5356267..cce54be210c6 100755 --- a/agg/source/agg_trans_single_path.cpp +++ b/agg/source/agg_trans_single_path.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -70,6 +70,7 @@ namespace agg double dist; double d; + m_src_vertices.close(false); if(m_src_vertices.size() > 2) { if(m_src_vertices[m_src_vertices.size() - 2].dist * 10.0 < @@ -87,13 +88,12 @@ namespace agg } dist = 0.0; - m_src_vertices.close(false); for(i = 0; i < m_src_vertices.size(); i++) { vertex_dist& v = m_src_vertices[i]; - double _d = v.dist; + double d = v.dist; v.dist = dist; - dist += _d; + dist += d; } m_kindex = (m_src_vertices.size() - 1) / dist; m_status = ready; @@ -180,7 +180,7 @@ namespace agg } else { - i = (unsigned)floor(*x * m_kindex); + i = unsigned(*x * m_kindex); j = i + 1; dd = m_src_vertices[j].dist - m_src_vertices[i].dist; d = ((*x * m_kindex) - i) * dd; diff --git a/agg/source/agg_trans_warp_magnifier.cpp b/agg/source/agg_trans_warp_magnifier.cpp index 4f9d28233907..dc17379e16ed 100755 --- a/agg/source/agg_trans_warp_magnifier.cpp +++ b/agg/source/agg_trans_warp_magnifier.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -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/source/agg_vcgen_bspline.cpp b/agg/source/agg_vcgen_bspline.cpp index 9ca4df9b44f4..fa3be8164f55 100755 --- a/agg/source/agg_vcgen_bspline.cpp +++ b/agg/source/agg_vcgen_bspline.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -47,13 +47,13 @@ namespace agg m_status = initial; if(is_move_to(cmd)) { - m_src_vertices.modify_last(point_type(x, y)); + m_src_vertices.modify_last(point_d(x, y)); } else { if(is_vertex(cmd)) { - m_src_vertices.add(point_type(x, y)); + m_src_vertices.add(point_d(x, y)); } else { @@ -113,8 +113,8 @@ namespace agg } m_spline_x.prepare(); m_spline_y.prepare(); - m_status = ready; } + m_status = ready; } diff --git a/agg/source/agg_vcgen_contour.cpp b/agg/source/agg_vcgen_contour.cpp index 979407417e75..44760fb17e00 100755 --- a/agg/source/agg_vcgen_contour.cpp +++ b/agg/source/agg_vcgen_contour.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -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_line_join(miter_join_revert), - 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_line_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; @@ -169,7 +143,7 @@ namespace agg } else { - const point_type& c = m_out_vertices[m_out_vertex++]; + const point_d& c = m_out_vertices[m_out_vertex++]; *x = c.x; *y = c.y; return cmd; @@ -179,7 +153,7 @@ namespace agg case end_poly: if(!m_closed) return path_cmd_stop; m_status = stop; - return (unsigned)path_cmd_end_poly | (unsigned)path_flags_close | (unsigned)path_flags_ccw; + return path_cmd_end_poly | path_flags_close | path_flags_ccw; case stop: return path_cmd_stop; diff --git a/agg/source/agg_vcgen_dash.cpp b/agg/source/agg_vcgen_dash.cpp index 96783abe9952..1241b07637a9 100755 --- a/agg/source/agg_vcgen_dash.cpp +++ b/agg/source/agg_vcgen_dash.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -169,7 +169,7 @@ namespace agg { double dash_rest = m_dashes[m_curr_dash] - m_curr_dash_start; - unsigned _cmd = (m_curr_dash & 1) ? + unsigned cmd = (m_curr_dash & 1) ? path_cmd_move_to : path_cmd_line_to; @@ -217,11 +217,9 @@ namespace agg } } } - return _cmd; + return cmd; } - - // statement unreachable - //break; + break; case stop: cmd = path_cmd_stop; diff --git a/agg/source/agg_vcgen_markers_term.cpp b/agg/source/agg_vcgen_markers_term.cpp index 0daa40793764..41031329c90a 100755 --- a/agg/source/agg_vcgen_markers_term.cpp +++ b/agg/source/agg_vcgen_markers_term.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -73,9 +73,9 @@ namespace agg //------------------------------------------------------------------------ - void vcgen_markers_term::rewind(unsigned id) + void vcgen_markers_term::rewind(unsigned path_id) { - m_curr_id = id * 2; + m_curr_id = path_id * 2; m_curr_idx = m_curr_id; } diff --git a/agg/source/agg_vcgen_smooth_poly1.cpp b/agg/source/agg_vcgen_smooth_poly1.cpp index 1df1edb5c72c..0534c9753087 100755 --- a/agg/source/agg_vcgen_smooth_poly1.cpp +++ b/agg/source/agg_vcgen_smooth_poly1.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -184,8 +184,7 @@ namespace agg m_status = ctrl1; return path_cmd_curve4; } - // statement unreachable - //break; + break; case ctrl_b: *x = m_ctrl2_x; diff --git a/agg/source/agg_vcgen_stroke.cpp b/agg/source/agg_vcgen_stroke.cpp index a8a4481ec25b..e607272aecbb 100755 --- a/agg/source/agg_vcgen_stroke.cpp +++ b/agg/source/agg_vcgen_stroke.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -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.0 + 1.0/64.0), - m_approx_scale(1.0), m_shorten(0.0), - m_line_cap(butt_cap), - m_line_join(miter_join), - m_inner_line_join(miter_join_revert), 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,7 +66,6 @@ namespace agg } } - //------------------------------------------------------------------------ void vcgen_stroke::rewind(unsigned) { @@ -120,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; @@ -134,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; @@ -164,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_line_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; @@ -195,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_line_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; @@ -220,7 +187,7 @@ namespace agg } else { - const point_type& c = m_out_vertices[m_out_vertex++]; + const point_d& c = m_out_vertices[m_out_vertex++]; *x = c.x; *y = c.y; return cmd; @@ -229,11 +196,11 @@ namespace agg case end_poly1: m_status = m_prev_status; - return (unsigned)path_cmd_end_poly | (unsigned)path_flags_close | (unsigned)path_flags_ccw; + return path_cmd_end_poly | path_flags_close | path_flags_ccw; case end_poly2: m_status = m_prev_status; - return (unsigned)path_cmd_end_poly | (unsigned)path_flags_close | (unsigned)path_flags_cw; + return path_cmd_end_poly | path_flags_close | path_flags_cw; case stop: cmd = path_cmd_stop; diff --git a/agg/source/agg_vpgen_clip_polygon.cpp b/agg/source/agg_vpgen_clip_polygon.cpp index e3a0b71d821b..f3fa7d2b0dce 100755 --- a/agg/source/agg_vpgen_clip_polygon.cpp +++ b/agg/source/agg_vpgen_clip_polygon.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/source/agg_vpgen_clip_polyline.cpp b/agg/source/agg_vpgen_clip_polyline.cpp index b3b60c96a70d..105358740e03 100755 --- a/agg/source/agg_vpgen_clip_polyline.cpp +++ b/agg/source/agg_vpgen_clip_polyline.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software @@ -13,19 +13,17 @@ // http://www.antigrain.com //---------------------------------------------------------------------------- -#include <math.h> #include "agg_vpgen_clip_polyline.h" +#include "agg_clip_liang_barsky.h" namespace agg { - static double clip_epsilon = 1e-10; - - //---------------------------------------------------------------------------- void vpgen_clip_polyline::reset() { m_vertex = 0; m_num_vertices = 0; + m_move_to = false; } //---------------------------------------------------------------------------- @@ -33,99 +31,38 @@ namespace agg { m_vertex = 0; m_num_vertices = 0; - m_f1 = clipping_flags(x, y); - if(m_f1 == 0) - { - m_x[0] = x; - m_y[0] = y; - m_cmd[0] = path_cmd_move_to; - m_num_vertices = 1; - } m_x1 = x; m_y1 = y; + m_move_to = true; } - //---------------------------------------------------------------------------- - bool vpgen_clip_polyline::move_point(double& x, double& y, unsigned& flags) + void vpgen_clip_polyline::line_to(double x, double y) { - double bound; - - if(flags & (clip_x1 | clip_x2)) - { - bound = (flags & clip_x1) ? m_clip_box.x1 : m_clip_box.x2; - y = (bound - m_x1) * (m_y2 - m_y1) / (m_x2 - m_x1) + m_y1; - x = bound; - flags = clipping_flags_y(y); - } - if(fabs(m_y2 - m_y1) < clip_epsilon && fabs(m_x2 - m_x1) < clip_epsilon) - { - return false; - } - if(flags & (clip_y1 | clip_y2)) - { - bound = (flags & clip_y1) ? m_clip_box.y1 : m_clip_box.y2; - x = (bound - m_y1) * (m_x2 - m_x1) / (m_y2 - m_y1) + m_x1; - y = bound; - } - flags = 0; - return true; - } + double x2 = x; + double y2 = y; + unsigned flags = clip_line_segment(&m_x1, &m_y1, &x2, &y2, m_clip_box); - //---------------------------------------------------------------------------- - void vpgen_clip_polyline::clip_line_segment() - { - if((m_f1 & m_f2) == 0) + m_vertex = 0; + m_num_vertices = 0; + if((flags & 4) == 0) { - if(m_f1) + if((flags & 1) != 0 || m_move_to) { - if(!move_point(m_x1, m_y1, m_f1)) return; - if(m_f1) return; m_x[0] = m_x1; m_y[0] = m_y1; m_cmd[0] = path_cmd_move_to; m_num_vertices = 1; } - if(m_f2) - { // Move Point 2 - if(!move_point(m_x2, m_y2, m_f2)) return; - } - m_x[m_num_vertices] = m_x2; - m_y[m_num_vertices] = m_y2; + m_x[m_num_vertices] = x2; + m_y[m_num_vertices] = y2; m_cmd[m_num_vertices++] = path_cmd_line_to; + m_move_to = (flags & 2) != 0; } - } - - - - //---------------------------------------------------------------------------- - void vpgen_clip_polyline::line_to(double x, double y) - { - m_vertex = 0; - m_num_vertices = 0; - unsigned f = m_f2 = clipping_flags(m_x2 = x, m_y2 = y); - - if(m_f2 == m_f1) - { - if(m_f2 == 0) - { - m_x[0] = x; - m_y[0] = y; - m_cmd[0] = path_cmd_line_to; - m_num_vertices = 1; - } - } - else - { - clip_line_segment(); - } - - m_f1 = f; m_x1 = x; m_y1 = y; } - //---------------------------------------------------------------------------- unsigned vpgen_clip_polyline::vertex(double* x, double* y) { @@ -137,6 +74,4 @@ namespace agg } return path_cmd_stop; } - - } diff --git a/agg/source/agg_vpgen_segmentator.cpp b/agg/source/agg_vpgen_segmentator.cpp index 97e76707c1cb..4b7b1f78d554 100755 --- a/agg/source/agg_vpgen_segmentator.cpp +++ b/agg/source/agg_vpgen_segmentator.cpp @@ -1,5 +1,5 @@ //---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 +// Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Permission to copy, use, modify, sell and distribute this software diff --git a/agg/source/makefile.mk b/agg/source/makefile.mk index e29f2c3b8891..8a8c9a488cc1 100755 --- a/agg/source/makefile.mk +++ b/agg/source/makefile.mk @@ -50,8 +50,6 @@ SLOFILES= \ $(SLO)$/agg_image_filters.obj \ $(SLO)$/agg_line_aa_basics.obj \ $(SLO)$/agg_line_profile_aa.obj \ - $(SLO)$/agg_path_storage.obj \ - $(SLO)$/agg_rasterizer_scanline_aa.obj \ $(SLO)$/agg_rounded_rect.obj \ $(SLO)$/agg_sqrt_tables.obj \ $(SLO)$/agg_trans_affine.obj \ diff --git a/configure.in b/configure.in index 341d67b46ccb..f7f2bd3766fa 100644 --- a/configure.in +++ b/configure.in @@ -19,9 +19,9 @@ echo "$@" >config.parms AC_ARG_WITH(gnu-patch, [ --with-gnu-patch Specify location of GNU patch on Solaris or FreeBSD ],,) -AC_ARG_WITH(agg, -[ --without-agg Disable the use of agg altogether -],,with_agg=yes) +AC_ARG_ENABLE(agg, +[ --enable-agg Use of agg altogether +],,) AC_ARG_WITH(gnu-cp, [ --with-gnu-cp Specify location of GNU cp on Solaris or FreeBSD ],,) @@ -5098,15 +5098,15 @@ AC_SUBST(OPENSSL_CFLAGS) AC_SUBST(OPENSSL_LIBS) dnl =================================================================== -dnl Test for disabling agg +dnl Test for enabling agg dnl =================================================================== AC_MSG_CHECKING([whether to enable agg]) -if test "$with_agg" = "no"; then - AC_MSG_RESULT([no]) -else +if test "$enable_agg" = "yes"; then AC_MSG_RESULT([yes]) - ENABLE_AGG=YES AC_SUBST(ENABLE_AGG) +else + AC_MSG_RESULT([no]) + ENABLE_AGG=NO dnl =================================================================== dnl Check for system AGG @@ -5141,7 +5141,7 @@ else else AC_MSG_RESULT([internal]) SYSTEM_AGG=NO - AGG_VERSION=2300 + AGG_VERSION=2400 BUILD_TYPE="$BUILD_TYPE AGG" fi AC_SUBST(SYSTEM_AGG) diff --git a/solenv/config/sooo340.ini b/solenv/config/sooo340.ini index e32aabe82f0e..7cfa227ffb4b 100644 --- a/solenv/config/sooo340.ini +++ b/solenv/config/sooo340.ini @@ -13,7 +13,7 @@ common CONFIG_PROJECT config_office DIC_ALL TRUE ENABLEUNICODE TRUE - ENABLE_AGG YES + ENABLE_AGG NO ENABLE_CUPS TRUE ENABLE_DIRECTX TRUE ENABLE_FONTCONFIG TRUE |