diff options
Diffstat (limited to 'agg/inc')
128 files changed, 36401 insertions, 0 deletions
diff --git a/agg/inc/agg_alpha_mask_u8.h b/agg/inc/agg_alpha_mask_u8.h new file mode 100755 index 000000000000..b7e5c926092f --- /dev/null +++ b/agg/inc/agg_alpha_mask_u8.h @@ -0,0 +1,499 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// scanline_u8 class +// +//---------------------------------------------------------------------------- +#ifndef AGG_ALPHA_MASK_U8_INCLUDED +#define AGG_ALPHA_MASK_U8_INCLUDED + +#include <string.h> +#include "agg_basics.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + //===================================================one_component_mask_u8 + struct one_component_mask_u8 + { + static unsigned calculate(const int8u* p) { return *p; } + }; + + + //=====================================================rgb_to_gray_mask_u8 + template<unsigned R, unsigned G, unsigned B> + struct rgb_to_gray_mask_u8 + { + static unsigned calculate(const int8u* p) + { + return (p[R]*77 + p[G]*150 + p[B]*29) >> 8; + } + }; + + //==========================================================alpha_mask_u8 + template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8> + class alpha_mask_u8 + { + public: + typedef int8u cover_type; + typedef alpha_mask_u8<Step, Offset, MaskF> self_type; + enum + { + cover_shift = 8, + cover_none = 0, + cover_full = 255 + }; + + alpha_mask_u8() : m_rbuf(0) {} + alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {} + + void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; } + + MaskF& mask_function() { return m_mask_function; } + const MaskF& mask_function() const { return m_mask_function; } + + + //-------------------------------------------------------------------- + cover_type pixel(int x, int y) const + { + if(x >= 0 && y >= 0 && + x < (int)m_rbuf->width() && + y <= (int)m_rbuf->height()) + { + return (cover_type)m_mask_function.calculate( + m_rbuf->row(y) + x * Step + Offset); + } + return 0; + } + + //-------------------------------------------------------------------- + cover_type combine_pixel(int x, int y, cover_type val) const + { + if(x >= 0 && y >= 0 && + x < (int)m_rbuf->width() && + y <= (int)m_rbuf->height()) + { + return (cover_type)((val * + m_mask_function.calculate( + m_rbuf->row(y) + x * Step + Offset)) >> + cover_shift); + } + return 0; + } + + + //-------------------------------------------------------------------- + void fill_hspan(int x, int y, cover_type* dst, int num_pix) const + { + int xmax = m_rbuf->width() - 1; + int ymax = m_rbuf->height() - 1; + + int count = num_pix; + cover_type* covers = dst; + + if(y < 0 || y > ymax) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + + if(x < 0) + { + count += x; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers, 0, -x * sizeof(cover_type)); + covers -= x; + x = 0; + } + + if(x + count > xmax) + { + int rest = x + count - xmax - 1; + count -= rest; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers + count, 0, rest * sizeof(cover_type)); + } + + const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + do + { + *covers++ = (cover_type)m_mask_function.calculate(mask); + mask += Step; + } + while(--count); + } + + + //-------------------------------------------------------------------- + void combine_hspan(int x, int y, cover_type* dst, int num_pix) const + { + int xmax = m_rbuf->width() - 1; + int ymax = m_rbuf->height() - 1; + + int count = num_pix; + cover_type* covers = dst; + + if(y < 0 || y > ymax) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + + if(x < 0) + { + count += x; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers, 0, -x * sizeof(cover_type)); + covers -= x; + x = 0; + } + + if(x + count > xmax) + { + int rest = x + count - xmax - 1; + count -= rest; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers + count, 0, rest * sizeof(cover_type)); + } + + const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + do + { + *covers = (cover_type)(((*covers) * + m_mask_function.calculate(mask)) >> + cover_shift); + ++covers; + mask += Step; + } + while(--count); + } + + //-------------------------------------------------------------------- + void fill_vspan(int x, int y, cover_type* dst, int num_pix) const + { + int xmax = m_rbuf->width() - 1; + int ymax = m_rbuf->height() - 1; + + int count = num_pix; + cover_type* covers = dst; + + if(x < 0 || x > xmax) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + + if(y < 0) + { + count += y; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers, 0, -y * sizeof(cover_type)); + covers -= y; + y = 0; + } + + if(y + count > ymax) + { + int rest = y + count - ymax - 1; + count -= rest; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers + count, 0, rest * sizeof(cover_type)); + } + + const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + do + { + *covers++ = (cover_type)m_mask_function.calculate(mask); + mask += m_rbuf->stride(); + } + while(--count); + } + + //-------------------------------------------------------------------- + void combine_vspan(int x, int y, cover_type* dst, int num_pix) const + { + int xmax = m_rbuf->width() - 1; + int ymax = m_rbuf->height() - 1; + + int count = num_pix; + cover_type* covers = dst; + + if(x < 0 || x > xmax) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + + if(y < 0) + { + count += y; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers, 0, -y * sizeof(cover_type)); + covers -= y; + y = 0; + } + + if(y + count > ymax) + { + int rest = y + count - ymax - 1; + count -= rest; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers + count, 0, rest * sizeof(cover_type)); + } + + const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + do + { + *covers = (cover_type)(((*covers) * + m_mask_function.calculate(mask)) >> + cover_shift); + ++covers; + mask += m_rbuf->stride(); + } + while(--count); + } + + + private: + alpha_mask_u8(const self_type&); + const self_type& operator = (const self_type&); + + rendering_buffer* m_rbuf; + MaskF m_mask_function; + }; + + + typedef alpha_mask_u8<1, 0> alpha_mask_gray8; //----alpha_mask_gray8 + + typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r; //----alpha_mask_rgb24r + typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g; //----alpha_mask_rgb24g + typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b; //----alpha_mask_rgb24b + + typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r; //----alpha_mask_bgr24r + typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g; //----alpha_mask_bgr24g + typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b; //----alpha_mask_bgr24b + + typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r + typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g + typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b + typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a + + typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r + typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g + typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b + typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a + + typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r + typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g + typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b + typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a + + typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r + typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g + typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b + typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a + + typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray; //----alpha_mask_rgb24gray + typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray; //----alpha_mask_bgr24gray + typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray + typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray + typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray + typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray + + + + //==========================================================amask_no_clip_u8 + template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8> + class amask_no_clip_u8 + { + public: + typedef int8u cover_type; + typedef amask_no_clip_u8<Step, Offset, MaskF> self_type; + enum + { + cover_shift = 8, + cover_none = 0, + cover_full = 255 + }; + + amask_no_clip_u8() : m_rbuf(0) {} + amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {} + + void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; } + + MaskF& mask_function() { return m_mask_function; } + const MaskF& mask_function() const { return m_mask_function; } + + + //-------------------------------------------------------------------- + cover_type pixel(int x, int y) const + { + return (cover_type)m_mask_function.calculate( + m_rbuf->row(y) + x * Step + Offset); + } + + + //-------------------------------------------------------------------- + cover_type combine_pixel(int x, int y, cover_type val) const + { + return (cover_type)((val * + m_mask_function.calculate( + m_rbuf->row(y) + x * Step + Offset)) >> + cover_shift); + } + + + //-------------------------------------------------------------------- + void fill_hspan(int x, int y, cover_type* dst, int num_pix) const + { + const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + do + { + *dst++ = (cover_type)m_mask_function.calculate(mask); + mask += Step; + } + while(--num_pix); + } + + + + //-------------------------------------------------------------------- + void combine_hspan(int x, int y, cover_type* dst, int num_pix) const + { + const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + do + { + *dst = (cover_type)(((*dst) * + m_mask_function.calculate(mask)) >> + cover_shift); + ++dst; + mask += Step; + } + while(--num_pix); + } + + + //-------------------------------------------------------------------- + void fill_vspan(int x, int y, cover_type* dst, int num_pix) const + { + const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + do + { + *dst++ = (cover_type)m_mask_function.calculate(mask); + mask += m_rbuf->stride(); + } + while(--num_pix); + } + + + //-------------------------------------------------------------------- + void combine_vspan(int x, int y, cover_type* dst, int num_pix) const + { + const int8u* mask = m_rbuf->row(y) + x * Step + Offset; + do + { + *dst = (cover_type)(((*dst) * + m_mask_function.calculate(mask)) >> + cover_shift); + ++dst; + mask += m_rbuf->stride(); + } + while(--num_pix); + } + + private: + amask_no_clip_u8(const self_type&); + const self_type& operator = (const self_type&); + + rendering_buffer* m_rbuf; + MaskF m_mask_function; + }; + + + typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8 + + typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r + typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g; //----amask_no_clip_rgb24g + typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b; //----amask_no_clip_rgb24b + + typedef amask_no_clip_u8<3, 2> amask_no_clip_bgr24r; //----amask_no_clip_bgr24r + typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g; //----amask_no_clip_bgr24g + typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b; //----amask_no_clip_bgr24b + + typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r + typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g + typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b + typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a + + typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r + typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g + typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b + typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a + + typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r + typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g + typedef amask_no_clip_u8<4, 0> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b + typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a + + typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r + typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g + typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b + typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a + + typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgb24gray; //----amask_no_clip_rgb24gray + typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray; //----amask_no_clip_bgr24gray + typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgba32gray; //----amask_no_clip_rgba32gray + typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_argb32gray; //----amask_no_clip_argb32gray + typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgra32gray; //----amask_no_clip_bgra32gray + typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_abgr32gray; //----amask_no_clip_abgr32gray + + +} + + + +#endif diff --git a/agg/inc/agg_arc.h b/agg/inc/agg_arc.h new file mode 100755 index 000000000000..80b148d910d0 --- /dev/null +++ b/agg/inc/agg_arc.h @@ -0,0 +1,74 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Arc vertex generator +// +//---------------------------------------------------------------------------- + +#ifndef AGG_ARC_INCLUDED +#define AGG_ARC_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + + //=====================================================================arc + // + // See Implementation agg_arc.cpp + // + class arc + { + public: + arc() : m_scale(1.0), m_initialized(false) {} + arc(double x, double y, + double rx, double ry, + double a1, double a2, + bool ccw=true); + + void init(double x, double y, + double rx, double ry, + double a1, double a2, + bool ccw=true); + + void approximation_scale(double s); + double approximation_scale() const { return m_scale; } + + void rewind(unsigned); + unsigned vertex(double* x, double* y); + + private: + void normalize(double a1, double a2, bool ccw); + + double m_x; + double m_y; + double m_rx; + double m_ry; + double m_angle; + double m_start; + double m_end; + double m_scale; + double m_da; + bool m_ccw; + bool m_initialized; + unsigned m_path_cmd; + }; + + +} + + +#endif diff --git a/agg/inc/agg_array.h b/agg/inc/agg_array.h new file mode 100755 index 000000000000..2970181c4510 --- /dev/null +++ b/agg/inc/agg_array.h @@ -0,0 +1,887 @@ +//---------------------------------------------------------------------------- +// 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_ARRAY_INCLUDED +#define AGG_ARRAY_INCLUDED + +#include <stddef.h> +#include <string.h> +#include "agg_basics.h" + +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) {} + + unsigned size() const { return m_size; } + const T& operator [] (unsigned idx) const { return m_array[idx]; } + T& operator [] (unsigned idx) { return m_array[idx]; } + private: + T* m_array; + unsigned m_size; + }; + + + + //---------------------------------------------------------pod_auto_array + template<class T, unsigned Size> class pod_auto_array + { + public: + typedef T value_type; + typedef pod_auto_array<T, Size> self_type; + + pod_auto_array() {} + explicit pod_auto_array(const T* c) + { + memcpy(m_array, c, sizeof(T) * Size); + } + + const self_type& operator = (const T* c) + { + memcpy(m_array, c, sizeof(T) * Size); + return *this; + } + + static unsigned size() { return Size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + private: + T m_array[Size]; + }; + + + + + + //---------------------------------------------------------------pod_array + // 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 + { + 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); + + // Copying + pod_array(const pod_array<T>&); + const pod_array<T>& operator = (const pod_array<T>&); + + unsigned capacity() const { return m_capacity; } + void capacity(unsigned cap, unsigned extra_tail=0); + + 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 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]; } + + void remove_all() { m_size = 0; } + void cut_at(unsigned num) { if(num < m_size) m_size = num; } + + private: + unsigned m_size; + unsigned m_capacity; + T* m_array; + }; + + //------------------------------------------------------------------------ + template<class T> + void pod_array<T>::capacity(unsigned cap, unsigned extra_tail) + { + m_size = 0; + if(cap > m_capacity) + { + delete [] m_array; + m_capacity = cap + extra_tail; + m_array = m_capacity ? new T [m_capacity] : 0; + } + } + + //------------------------------------------------------------------------ + template<class T> + void pod_array<T>::resize(unsigned new_size) + { + if(new_size > m_size) + { + if(new_size > m_capacity) + { + T* data = new T[new_size]; + memcpy(data, m_array, m_size * sizeof(T)); + delete [] m_array; + m_array = data; + } + } + else + { + m_size = new_size; + } + } + + //------------------------------------------------------------------------ + 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_array<T>::pod_array(const pod_array<T>& v) : + m_size(v.m_size), + m_capacity(v.m_capacity), + m_array(v.m_capacity ? new T [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) + { + capacity(v.m_capacity); + 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 + { + 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) + { + _byte_size /= sizeof(T); + capacity(_byte_size); + if(_byte_size) memcpy(m_array, data, _byte_size * sizeof(T)); + } + + + + + + //---------------------------------------------------------------pod_deque + // 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, + // so the only valid access method is operator [] or curr(), prev(), next() + // + // There reallocs occure only when the pool of pointers to blocks needs + // to be extended (it happens very rarely). You can control the value + // 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 + { + public: + enum + { + block_shift = S, + block_size = 1 << block_shift, + block_mask = block_size - 1 + }; + + typedef T value_type; + + ~pod_deque(); + pod_deque(); + pod_deque(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); + + void remove_all() { m_size = 0; } + void free_all() { free_tail(0); } + void free_tail(unsigned size); + void add(const T& val); + void modify_last(const T& val); + void remove_last(); + + int allocate_continuous_block(unsigned num_elements); + + void add_array(const T* ptr, unsigned num_elem) + { + while(num_elem--) + { + add(*ptr++); + } + } + + template<class DataAccessor> void add_data(DataAccessor& data) + { + while(data.size()) + { + add(*data); + ++data; + } + } + + void cut_at(unsigned _size) + { + if(_size < m_size) m_size = _size; + } + + unsigned size() const { return m_size; } + + const T& operator [] (unsigned idx) const + { + return m_blocks[idx >> block_shift][idx & block_mask]; + } + + T& operator [] (unsigned idx) + { + return m_blocks[idx >> block_shift][idx & block_mask]; + } + + const T& curr(unsigned idx) const + { + return (*this)[idx]; + } + + T& curr(unsigned idx) + { + return (*this)[idx]; + } + + const T& prev(unsigned idx) const + { + return (*this)[(idx + m_size - 1) % m_size]; + } + + T& prev(unsigned idx) + { + return (*this)[(idx + m_size - 1) % m_size]; + } + + const T& next(unsigned idx) const + { + return (*this)[(idx + 1) % m_size]; + } + + T& next(unsigned idx) + { + return (*this)[(idx + 1) % m_size]; + } + + const T& last() const + { + return (*this)[m_size - 1]; + } + + T& last() + { + return (*this)[m_size - 1]; + } + + unsigned byte_size() const; + void serialize(int8u* ptr) const; + void deserialize(const int8u* data, unsigned byte_size); + void deserialize(unsigned start, const T& empty_val, + const int8u* data, unsigned byte_size); + + template<class ByteAccessor> + void deserialize(ByteAccessor data) + { + remove_all(); + unsigned elem_size = data.size() / sizeof(T); + + for(unsigned i = 0; i < elem_size; ++i) + { + int8u* ptr = (int8u*)data_ptr(); + for(unsigned j = 0; j < sizeof(T); ++j) + { + *ptr++ = *data; + ++data; + } + ++m_size; + } + } + + template<class ByteAccessor> + void deserialize(unsigned start, const T& empty_val, ByteAccessor data) + { + while(m_size < start) + { + add(empty_val); + } + + unsigned elem_size = data.size() / sizeof(T); + for(unsigned i = 0; i < elem_size; ++i) + { + int8u* ptr; + if(start + i < m_size) + { + ptr = (int8u*)(&((*this)[start + i])); + } + else + { + ptr = (int8u*)data_ptr(); + ++m_size; + } + for(unsigned j = 0; j < sizeof(T); ++j) + { + *ptr++ = *data; + ++data; + } + } + } + + const T* block(unsigned nb) const { return m_blocks[nb]; } + + private: + void allocate_block(unsigned nb); + T* data_ptr(); + + unsigned m_size; + unsigned m_num_blocks; + unsigned m_max_blocks; + T** m_blocks; + unsigned m_block_ptr_inc; + }; + + + //------------------------------------------------------------------------ + template<class T, unsigned S> pod_deque<T, S>::~pod_deque() + { + if(m_num_blocks) + { + T** blk = m_blocks + m_num_blocks - 1; + while(m_num_blocks--) + { + delete [] *blk; + --blk; + } + delete [] m_blocks; + } + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void pod_deque<T, S>::free_tail(unsigned _size) + { + if(_size < m_size) + { + unsigned nb = (_size + block_mask) >> block_shift; + while(m_num_blocks > nb) + { + delete [] m_blocks[--m_num_blocks]; + } + m_size = _size; + } + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> pod_deque<T, S>::pod_deque() : + m_size(0), + m_num_blocks(0), + m_max_blocks(0), + m_blocks(0), + m_block_ptr_inc(block_size) + { + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + pod_deque<T, S>::pod_deque(unsigned block_ptr_inc) : + m_size(0), + m_num_blocks(0), + m_max_blocks(0), + m_blocks(0), + m_block_ptr_inc(block_ptr_inc) + { + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + pod_deque<T, S>::pod_deque(const pod_deque<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_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]; + memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); + } + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + const pod_deque<T, S>& pod_deque<T, S>::operator = (const pod_deque<T, S>& v) + { + unsigned i; + for(i = m_num_blocks; i < v.m_num_blocks; ++i) + { + allocate_block(i); + } + for(i = 0; i < v.m_num_blocks; ++i) + { + memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); + } + m_size = v.m_size; + return *this; + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void pod_deque<T, S>::allocate_block(unsigned nb) + { + if(nb >= m_max_blocks) + { + T** new_blocks = new T* [m_max_blocks + m_block_ptr_inc]; + + if(m_blocks) + { + memcpy(new_blocks, + m_blocks, + m_num_blocks * sizeof(T*)); + + delete [] m_blocks; + } + m_blocks = new_blocks; + m_max_blocks += m_block_ptr_inc; + } + m_blocks[nb] = new T [block_size]; + m_num_blocks++; + } + + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + inline T* pod_deque<T, S>::data_ptr() + { + unsigned nb = m_size >> block_shift; + if(nb >= m_num_blocks) + { + allocate_block(nb); + } + return m_blocks[nb] + (m_size & block_mask); + } + + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + inline void pod_deque<T, S>::add(const T& val) + { + *data_ptr() = val; + ++m_size; + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + inline void pod_deque<T, S>::remove_last() + { + if(m_size) --m_size; + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void pod_deque<T, S>::modify_last(const T& val) + { + remove_last(); + add(val); + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + int pod_deque<T, S>::allocate_continuous_block(unsigned num_elements) + { + if(num_elements < block_size) + { + data_ptr(); // Allocate initial block if necessary + unsigned rest = block_size - (m_size & block_mask); + unsigned index; + if(num_elements <= rest) + { + // The rest of the block is good, we can use it + //----------------- + index = m_size; + m_size += num_elements; + return index; + } + + // New block + //--------------- + m_size += rest; + data_ptr(); + index = m_size; + m_size += num_elements; + return index; + } + return -1; // Impossible to allocate + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + unsigned pod_deque<T, S>::byte_size() const + { + return m_size * sizeof(T); + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void pod_deque<T, S>::serialize(int8u* ptr) const + { + unsigned i; + for(i = 0; i < m_size; i++) + { + memcpy(ptr, &(*this)[i], sizeof(T)); + ptr += sizeof(T); + } + } + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void pod_deque<T, S>::deserialize(const int8u* data, unsigned _byte_size) + { + remove_all(); + _byte_size /= sizeof(T); + for(unsigned i = 0; i < _byte_size; ++i) + { + T* ptr = data_ptr(); + memcpy(ptr, data, sizeof(T)); + ++m_size; + data += sizeof(T); + } + } + + + // 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) + { + while(m_size < start) + { + add(empty_val); + } + + _byte_size /= sizeof(T); + for(unsigned i = 0; i < _byte_size; ++i) + { + if(start + i < m_size) + { + memcpy(&((*this)[start + i]), data, sizeof(T)); + } + else + { + T* ptr = data_ptr(); + memcpy(ptr, data, sizeof(T)); + ++m_size; + } + data += sizeof(T); + } + } + + + //-----------------------------------------------------------pod_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 + // the constructor). If required size exceeds the block size the allocator + // 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 + { + public: + void remove_all() + { + if(m_num_blocks) + { + int8u** blk = m_blocks + m_num_blocks - 1; + while(m_num_blocks--) + { + delete [] *blk; + --blk; + } + delete [] m_blocks; + } + m_num_blocks = 0; + m_max_blocks = 0; + m_blocks = 0; + m_buf_ptr = 0; + m_rest = 0; + } + + ~pod_allocator() + { + remove_all(); + } + + pod_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), + m_max_blocks(0), + m_blocks(0), + m_buf_ptr(0), + m_rest(0) + { + } + + + int8u* allocate(unsigned size, unsigned alignment=1) + { + if(size == 0) return 0; + if(size <= m_rest) + { + int8u* ptr = m_buf_ptr; + if(alignment > 1) + { + unsigned align = (alignment - unsigned((size_t)ptr) % alignment) % alignment; + size += align; + ptr += align; + if(size <= m_rest) + { + m_rest -= size; + m_buf_ptr += size; + return ptr; + } + allocate_block(size); + return allocate(size - align, alignment); + } + m_rest -= size; + m_buf_ptr += size; + return ptr; + } + allocate_block(size + alignment - 1); + return allocate(size, alignment); + } + + + private: + void allocate_block(unsigned size) + { + 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]; + + if(m_blocks) + { + memcpy(new_blocks, + m_blocks, + m_num_blocks * sizeof(int8u*)); + + delete [] m_blocks; + } + m_blocks = new_blocks; + m_max_blocks += m_block_ptr_inc; + } + m_blocks[m_num_blocks] = m_buf_ptr = new int8u [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; + }; + + + + + + + + + //------------------------------------------------------------------------ + enum + { + quick_sort_threshold = 9 + }; + + + //-----------------------------------------------------------swap_elements + template<class T> inline void swap_elements(T& a, T& b) + { + T temp = a; + a = b; + b = temp; + } + + + //--------------------------------------------------------------quick_sort + template<class Array, class Less> + void quick_sort(Array& arr, Less less) + { + if(arr.size() < 2) return; + + typename Array::value_type* e1; + typename Array::value_type* e2; + + int stack[80]; + int* top = stack; + int limit = arr.size(); + int base = 0; + + for(;;) + { + int len = limit - base; + + int i; + int j; + int pivot; + + if(len > quick_sort_threshold) + { + // we use base + len/2 as the pivot + pivot = base + len / 2; + swap_elements(arr[base], arr[pivot]); + + i = base + 1; + j = limit - 1; + + // now ensure that *i <= *base <= *j + e1 = &(arr[j]); + e2 = &(arr[i]); + if(less(*e1, *e2)) swap_elements(*e1, *e2); + + e1 = &(arr[base]); + e2 = &(arr[i]); + if(less(*e1, *e2)) swap_elements(*e1, *e2); + + e1 = &(arr[j]); + e2 = &(arr[base]); + if(less(*e1, *e2)) swap_elements(*e1, *e2); + + for(;;) + { + do i++; while( less(arr[i], arr[base]) ); + do j--; while( less(arr[base], arr[j]) ); + + if( i > j ) + { + break; + } + + swap_elements(arr[i], arr[j]); + } + + swap_elements(arr[base], arr[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(*(e1 = &(arr[j + 1])), *(e2 = &(arr[j]))); j--) + { + swap_elements(*e1, *e2); + if(j == base) + { + break; + } + } + } + if(top > stack) + { + top -= 2; + base = top[0]; + limit = top[1]; + } + else + { + break; + } + } + } + } + + + + + //------------------------------------------------------remove_duplicates + // Remove duplicates from a sorted array. It doesn't cut the the + // tail of the array, it just returns the number of remaining elements. + //----------------------------------------------------------------------- + template<class Array, class Equal> + unsigned remove_duplicates(Array& arr, Equal equal) + { + if(arr.size() < 2) return arr.size(); + + unsigned i, j; + for(i = 1, j = 1; i < arr.size(); i++) + { + typename Array::value_type& e = arr[i]; + if(!equal(e, arr[i - 1])) + { + arr[j++] = e; + } + } + return j; + } + + + + +} + +#endif diff --git a/agg/inc/agg_arrowhead.h b/agg/inc/agg_arrowhead.h new file mode 100755 index 000000000000..aac99c5ae980 --- /dev/null +++ b/agg/inc/agg_arrowhead.h @@ -0,0 +1,82 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Simple arrowhead/arrowtail generator +// +//---------------------------------------------------------------------------- +#ifndef AGG_ARROWHEAD_INCLUDED +#define AGG_ARROWHEAD_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //===============================================================arrowhead + // + // See implementation agg_arrowhead.cpp + // + class arrowhead + { + public: + arrowhead(); + + void head(double d1, double d2, double d3, double d4) + { + m_head_d1 = d1; + m_head_d2 = d2; + m_head_d3 = d3; + m_head_d4 = d4; + m_head_flag = true; + } + + void head() { m_head_flag = true; } + void no_head() { m_head_flag = false; } + + void tail(double d1, double d2, double d3, double d4) + { + m_tail_d1 = d1; + m_tail_d2 = d2; + m_tail_d3 = d3; + m_tail_d4 = d4; + m_tail_flag = true; + } + + void tail() { m_tail_flag = true; } + void no_tail() { m_tail_flag = false; } + + void rewind(unsigned id); + unsigned vertex(double* x, double* y); + + private: + double m_head_d1; + double m_head_d2; + double m_head_d3; + double m_head_d4; + double m_tail_d1; + double m_tail_d2; + double m_tail_d3; + double m_tail_d4; + bool m_head_flag; + bool m_tail_flag; + double m_coord[16]; + unsigned m_cmd[8]; + unsigned m_curr_id; + unsigned m_curr_coord; + }; + +} + +#endif diff --git a/agg/inc/agg_basics.h b/agg/inc/agg_basics.h new file mode 100755 index 000000000000..d9ca881ab328 --- /dev/null +++ b/agg/inc/agg_basics.h @@ -0,0 +1,343 @@ +//---------------------------------------------------------------------------- +// 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_BASICS_INCLUDED +#define AGG_BASICS_INCLUDED + +#include "agg_config.h" + +//-------------------------------------------------------- Default basic types +// +// If the compiler has different capacity of the basic types you can redefine +// them via the compiler command line or by generating agg_config.h that is +// empty by default. +// +#ifndef AGG_INT8 +#define AGG_INT8 signed char +#endif + +#ifndef AGG_INT8U +#define AGG_INT8U unsigned char +#endif + +#ifndef AGG_INT16 +#define AGG_INT16 short +#endif + +#ifndef AGG_INT16U +#define AGG_INT16U unsigned short +#endif + +#ifndef AGG_INT32 +#define AGG_INT32 int +#endif + +#ifndef AGG_INT32U +#define AGG_INT32U unsigned +#endif + +#ifndef AGG_INT64 +#if defined(_MSC_VER) +#define AGG_INT64 signed __int64 +#else +#define AGG_INT64 signed long long +#endif +#endif + +#ifndef AGG_INT64U +#if defined(_MSC_VER) +#define AGG_INT64U unsigned __int64 +#else +#define AGG_INT64U unsigned long long +#endif +#endif + +//------------------------------------------------ Some fixes for MS Visual C++ +#if defined(_MSC_VER) +#pragma warning(disable:4786) // Identifier was truncated... +#endif + +#if defined(_MSC_VER) +#define AGG_INLINE __forceinline +#else +#define AGG_INLINE inline +#endif + +namespace agg +{ + //------------------------------------------------------------------------- + typedef AGG_INT8 int8; //----int8 + typedef AGG_INT8U int8u; //----int8u + typedef AGG_INT16 int16; //----int16 + typedef AGG_INT16U int16u; //----int16u + typedef AGG_INT32 int32; //----int32 + typedef AGG_INT32U int32u; //----int32u + typedef AGG_INT64 int64; //----int64 + typedef AGG_INT64U int64u; //----int64u + + //------------------------------------------------------------------------- + typedef unsigned char cover_type; //----cover_type + enum + { + cover_shift = 8, //----cover_shift + cover_size = 1 << cover_shift, //----cover_size + cover_mask = cover_size - 1, //----cover_mask + cover_none = 0, //----cover_none + cover_full = cover_mask //----cover_full + }; + + + //-----------------------------------------------------------------------pi + const double pi = 3.14159265358979323846; + + //------------------------------------------------------------------deg2rad + inline double deg2rad(double deg) + { + return deg * pi / 180.0; + } + + //------------------------------------------------------------------rad2deg + inline double rad2deg(double rad) + { + return rad * 180.0 / pi; + } + + //----------------------------------------------------------------rect_base + template<class T> struct rect_base + { + typedef rect_base<T> self_type; + T x1; + T y1; + T x2; + T y2; + + rect_base() {} + rect_base(T x1_, T y1_, T x2_, T y2_) : + x1(x1_), y1(y1_), x2(x2_), y2(y2_) {} + + const self_type& normalize() + { + T t; + if(x1 > x2) { t = x1; x1 = x2; x2 = t; } + if(y1 > y2) { t = y1; y1 = y2; y2 = t; } + return *this; + } + + bool clip(const self_type& r) + { + if(x2 > r.x2) x2 = r.x2; + if(y2 > r.y2) y2 = r.y2; + if(x1 < r.x1) x1 = r.x1; + if(y1 < r.y1) y1 = r.y1; + return x1 <= x2 && y1 <= y2; + } + + bool is_valid() const + { + return x1 <= x2 && y1 <= y2; + } + }; + + //-----------------------------------------------------intersect_rectangles + template<class Rect> + inline Rect intersect_rectangles(const Rect& r1, const Rect& r2) + { + Rect r = r1; + + // First process x2,y2 because the other order + // results in Internal Compiler Error under + // Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in + // case of "Maximize Speed" optimization option. + //----------------- + if(r.x2 > r2.x2) r.x2 = r2.x2; + if(r.y2 > r2.y2) r.y2 = r2.y2; + if(r.x1 < r2.x1) r.x1 = r2.x1; + if(r.y1 < r2.y1) r.y1 = r2.y1; + return r; + } + + + //---------------------------------------------------------unite_rectangles + template<class Rect> + inline Rect unite_rectangles(const Rect& r1, const Rect& r2) + { + Rect r = r1; + if(r.x2 < r2.x2) r.x2 = r2.x2; + if(r.y2 < r2.y2) r.y2 = r2.y2; + if(r.x1 > r2.x1) r.x1 = r2.x1; + if(r.y1 > r2.y1) r.y1 = r2.y1; + return r; + } + + typedef rect_base<int> rect; //----rect + typedef rect_base<double> rect_d; //----rect_d + + //---------------------------------------------------------path_commands_e + enum path_commands_e + { + path_cmd_stop = 0, //----path_cmd_stop + path_cmd_move_to = 1, //----path_cmd_move_to + 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_mask = 0x0F //----path_cmd_mask + }; + + //------------------------------------------------------------path_flags_e + enum path_flags_e + { + path_flags_none = 0, //----path_flags_none + path_flags_ccw = 0x10, //----path_flags_ccw + path_flags_cw = 0x20, //----path_flags_cw + path_flags_close = 0x40, //----path_flags_close + path_flags_mask = 0xF0 //----path_flags_mask + }; + + //---------------------------------------------------------------is_vertex + inline bool is_vertex(unsigned c) + { + return c >= path_cmd_move_to && c < path_cmd_end_poly; + } + + //-----------------------------------------------------------------is_stop + inline bool is_stop(unsigned c) + { + return c == path_cmd_stop; + } + + //--------------------------------------------------------------is_move_to + inline bool is_move_to(unsigned c) + { + return c == path_cmd_move_to; + } + + //--------------------------------------------------------------is_line_to + inline bool is_line_to(unsigned c) + { + return c == path_cmd_line_to; + } + + //----------------------------------------------------------------is_curve + inline bool is_curve(unsigned c) + { + return c == path_cmd_curve3 || c == path_cmd_curve4; + } + + //---------------------------------------------------------------is_curve3 + inline bool is_curve3(unsigned c) + { + return c == path_cmd_curve3; + } + + //---------------------------------------------------------------is_curve4 + inline bool is_curve4(unsigned c) + { + return c == path_cmd_curve4; + } + + //-------------------------------------------------------------is_end_poly + inline bool is_end_poly(unsigned c) + { + return (c & path_cmd_mask) == path_cmd_end_poly; + } + + //----------------------------------------------------------------is_close + inline bool is_close(unsigned c) + { + return (c & ~(path_flags_cw | path_flags_ccw)) == + (((bool)path_cmd_end_poly) | ((bool)path_flags_close)); + } + + //------------------------------------------------------------is_next_poly + inline bool is_next_poly(unsigned c) + { + return is_stop(c) || is_move_to(c) || is_end_poly(c); + } + + //-------------------------------------------------------------------is_cw + inline bool is_cw(unsigned c) + { + return (c & path_flags_cw) != 0; + } + + //------------------------------------------------------------------is_ccw + inline bool is_ccw(unsigned c) + { + return (c & path_flags_ccw) != 0; + } + + //-------------------------------------------------------------is_oriented + inline bool is_oriented(unsigned c) + { + return (c & (path_flags_cw | path_flags_ccw)) != 0; + } + + //---------------------------------------------------------------is_closed + inline bool is_closed(unsigned c) + { + return (c & path_flags_close) != 0; + } + + //----------------------------------------------------------get_close_flag + inline unsigned get_close_flag(unsigned c) + { + return c & path_flags_close; + } + + //-------------------------------------------------------clear_orientation + inline unsigned clear_orientation(unsigned c) + { + return c & ~(path_flags_cw | path_flags_ccw); + } + + //---------------------------------------------------------get_orientation + inline unsigned get_orientation(unsigned c) + { + return c & (path_flags_cw | path_flags_ccw); + } + + //---------------------------------------------------------set_orientation + inline unsigned set_orientation(unsigned c, unsigned o) + { + return clear_orientation(c) | o; + } + + //--------------------------------------------------------------point_type + struct point_type + { + double x, y; + + point_type() {} + point_type(double x_, double y_) : x(x_), y(y_) {} + }; + + //-------------------------------------------------------------vertex_type + struct vertex_type + { + double x, y; + unsigned cmd; + + vertex_type() {} + vertex_type(double x_, double y_, unsigned cmd_) : + x(x_), y(y_), cmd(cmd_) {} + }; + + +} + + +#endif + diff --git a/agg/inc/agg_bezier_arc.h b/agg/inc/agg_bezier_arc.h new file mode 100755 index 000000000000..f437ab0a00bd --- /dev/null +++ b/agg/inc/agg_bezier_arc.h @@ -0,0 +1,158 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e., +// 4, 7, 10, or 13 vertices. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_BEZIER_ARC_INCLUDED +#define AGG_BEZIER_ARC_INCLUDED + +#include "agg_conv_transform.h" + +namespace agg +{ + + //----------------------------------------------------------------------- + void arc_to_bezier(double cx, double cy, double rx, double ry, + double start_angle, double sweep_angle, + double* curve); + + + //==============================================================bezier_arc + // + // See implemantaion agg_bezier_arc.cpp + // + class bezier_arc + { + public: + //-------------------------------------------------------------------- + bezier_arc() : m_vertex(26) {} + bezier_arc(double x, double y, + double rx, double ry, + double start_angle, + double sweep_angle) + { + init(x, y, rx, ry, start_angle, sweep_angle); + } + + //-------------------------------------------------------------------- + void init(double x, double y, + double rx, double ry, + double start_angle, + double sweep_angle); + + //-------------------------------------------------------------------- + void rewind(unsigned) + { + m_vertex = 0; + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + if(m_vertex >= m_num_vertices) return path_cmd_stop; + *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; + } + + // Supplemantary functions. num_vertices() actually returns doubled + // number of vertices. That is, for 1 vertex it returns 2. + //-------------------------------------------------------------------- + unsigned num_vertices() const { return m_num_vertices; } + const double* vertices() const { return m_vertices; } + double* vertices() { return m_vertices; } + + private: + unsigned m_vertex; + unsigned m_num_vertices; + double m_vertices[26]; + }; + + + + //==========================================================bezier_arc_svg + // Compute an SVG-style bezier arc. + // + // Computes an elliptical arc from (x1, y1) to (x2, y2). The size and + // orientation of the ellipse are defined by two radii (rx, ry) + // and an x-axis-rotation, which indicates how the ellipse as a whole + // is rotated relative to the current coordinate system. The center + // (cx, cy) of the ellipse is calculated automatically to satisfy the + // constraints imposed by the other parameters. + // large-arc-flag and sweep-flag contribute to the automatic calculations + // and help determine how the arc is drawn. + class bezier_arc_svg + { + public: + //-------------------------------------------------------------------- + bezier_arc_svg() : m_arc(), m_radii_ok(false) {} + + bezier_arc_svg(double x1, double y1, + double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x2, double y2) : + m_arc(), m_radii_ok(false) + { + init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2); + } + + //-------------------------------------------------------------------- + void init(double x1, double y1, + double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x2, double y2); + + //-------------------------------------------------------------------- + bool radii_ok() const { return m_radii_ok; } + + //-------------------------------------------------------------------- + void rewind(unsigned) + { + m_arc.rewind(0); + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + return m_arc.vertex(x, y); + } + + // Supplemantary functions. num_vertices() actually returns doubled + // number of vertices. That is, for 1 vertex it returns 2. + //-------------------------------------------------------------------- + unsigned num_vertices() const { return m_arc.num_vertices(); } + const double* vertices() const { return m_arc.vertices(); } + double* vertices() { return m_arc.vertices(); } + + private: + bezier_arc m_arc; + bool m_radii_ok; + }; + + + + +} + + +#endif diff --git a/agg/inc/agg_bitset_iterator.h b/agg/inc/agg_bitset_iterator.h new file mode 100755 index 000000000000..543432b65d54 --- /dev/null +++ b/agg/inc/agg_bitset_iterator.h @@ -0,0 +1,54 @@ +//---------------------------------------------------------------------------- +// 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_BITSET_ITERATOR_INCLUDED +#define AGG_BITSET_ITERATOR_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + class bitset_iterator + { + public: + bitset_iterator(const int8u* bits, unsigned offset = 0) : + m_bits(bits + (offset >> 3)), + m_mask(0x80 >> (offset & 7)) + {} + + void operator ++ () + { + m_mask >>= 1; + if(m_mask == 0) + { + ++m_bits; + m_mask = 0x80; + } + } + + unsigned bit() const + { + return (*m_bits) & m_mask; + } + + private: + const int8u* m_bits; + int8u m_mask; + }; + +} + +#endif diff --git a/agg/inc/agg_bounding_rect.h b/agg/inc/agg_bounding_rect.h new file mode 100755 index 000000000000..9a3c301069d7 --- /dev/null +++ b/agg/inc/agg_bounding_rect.h @@ -0,0 +1,116 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// bounding_rect function template +// +//---------------------------------------------------------------------------- +#ifndef AGG_BOUNDING_RECT_INCLUDED +#define AGG_BOUNDING_RECT_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //-----------------------------------------------------------bounding_rect + template<class VertexSource, class GetId, class CoordT> + bool bounding_rect(VertexSource& vs, GetId& gi, + unsigned start, unsigned num, + CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2) + { + unsigned i; + double x; + double y; + bool first = true; + + *x1 = CoordT(1); + *y1 = CoordT(1); + *x2 = CoordT(0); + *y2 = CoordT(0); + + for(i = 0; i < num; i++) + { + vs.rewind(gi[start + i]); + unsigned cmd; + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + if(is_vertex(cmd)) + { + if(first) + { + *x1 = CoordT(x); + *y1 = CoordT(y); + *x2 = CoordT(x); + *y2 = CoordT(y); + first = false; + } + else + { + if(CoordT(x) < *x1) *x1 = CoordT(x); + if(CoordT(y) < *y1) *y1 = CoordT(y); + if(CoordT(x) > *x2) *x2 = CoordT(x); + if(CoordT(y) > *y2) *y2 = CoordT(y); + } + } + } + } + return *x1 <= *x2 && *y1 <= *y2; + } + + + //-----------------------------------------------------bounding_rect_single + template<class VertexSource, class CoordT> + bool bounding_rect_single(VertexSource& vs, unsigned path_id, + CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2) + { + double x; + double y; + bool first = true; + + *x1 = CoordT(1); + *y1 = CoordT(1); + *x2 = CoordT(0); + *y2 = CoordT(0); + + vs.rewind(path_id); + unsigned cmd; + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + if(is_vertex(cmd)) + { + if(first) + { + *x1 = CoordT(x); + *y1 = CoordT(y); + *x2 = CoordT(x); + *y2 = CoordT(y); + first = false; + } + else + { + if(CoordT(x) < *x1) *x1 = CoordT(x); + if(CoordT(y) < *y1) *y1 = CoordT(y); + if(CoordT(x) > *x2) *x2 = CoordT(x); + if(CoordT(y) > *y2) *y2 = CoordT(y); + } + } + } + return *x1 <= *x2 && *y1 <= *y2; + } + + +} + +#endif diff --git a/agg/inc/agg_bspline.h b/agg/inc/agg_bspline.h new file mode 100755 index 000000000000..ca58fa839b44 --- /dev/null +++ b/agg/inc/agg_bspline.h @@ -0,0 +1,77 @@ +//---------------------------------------------------------------------------- +// 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 bspline +// +//---------------------------------------------------------------------------- + +#ifndef AGG_BSPLINE_INCLUDED +#define AGG_BSPLINE_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //----------------------------------------------------------------bspline + // A very simple class of Bi-cubic Spline interpolation. + // First call init(num, x[], y[]) where num - number of source points, + // x, y - arrays of X and Y values respectively. Here Y must be a function + // of X. It means that all the X-coordinates must be arranged in the ascending + // order. + // Then call get(x) that calculates a value Y for the respective X. + // The class supports extrapolation, i.e. you can call get(x) where x is + // outside the given with init() X-range. Extrapolation is a simple linear + // function. + // + // See Implementation agg_bspline.cpp + //------------------------------------------------------------------------ + class bspline + { + public: + ~bspline(); + bspline(); + bspline(int num); + bspline(int num, const double* x, const double* y); + + void init(int num); + void add_point(double x, double y); + void prepare(); + + void init(int num, const double* x, const double* y); + + double get(double x) const; + double get_stateful(double x) const; + + private: + bspline(const bspline&); + const bspline& operator = (const bspline&); + + static void bsearch(int n, const double *x, double x0, int *i); + double extrapolation_left(double x) const; + 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; + }; + + +} + +#endif diff --git a/agg/inc/agg_clip_liang_barsky.h b/agg/inc/agg_clip_liang_barsky.h new file mode 100755 index 000000000000..e229d52bc6e9 --- /dev/null +++ b/agg/inc/agg_clip_liang_barsky.h @@ -0,0 +1,209 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Liang-Barsky clipping +// +//---------------------------------------------------------------------------- +#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED +#define AGG_CLIP_LIANG_BARSKY_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //----------------------------------------------------------clipping_flags + // Determine the clipping code of the vertex according to the + // Cyrus-Beck line clipping algorithm + // + // | | + // 0110 | 0010 | 0011 + // | | + // -------+--------+-------- clip_box.y2 + // | | + // 0100 | 0000 | 0001 + // | | + // -------+--------+-------- clip_box.y1 + // | | + // 1100 | 1000 | 1001 + // | | + // clip_box.x1 clip_box.x2 + // + // + template<class T> + inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box) + { + return (x > clip_box.x2) | + ((y > clip_box.y2) << 1) | + ((x < clip_box.x1) << 2) | + ((y < clip_box.y1) << 3); + } + + + + //-------------------------------------------------------clip_liang_barsky + template<class T> + /*inline*/ unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, + const rect_base<T>& clip_box, + T* x, T* y) + { + const double nearzero = 1e-30; + + double deltax = x2 - x1; + double deltay = y2 - y1; + double xin; + double xout; + double yin; + double yout; + double tinx; + double tiny; + double toutx; + double touty; + double tin1; + double tin2; + double tout1; + unsigned np = 0; + + if(deltax == 0.0) + { + // bump off of the vertical + deltax = (x1 > clip_box.x1) ? -nearzero : nearzero; + } + + if(deltay == 0.0) + { + // bump off of the horizontal + deltay = (y1 > clip_box.y1) ? -nearzero : nearzero; + } + + if(deltax > 0.0) + { + // points to right + xin = clip_box.x1; + xout = clip_box.x2; + } + else + { + xin = clip_box.x2; + xout = clip_box.x1; + } + + if(deltay > 0.0) + { + // points up + yin = clip_box.y1; + yout = clip_box.y2; + } + else + { + yin = clip_box.y2; + yout = clip_box.y1; + } + + tinx = (xin - x1) / deltax; + tiny = (yin - y1) / deltay; + + if (tinx < tiny) + { + // hits x first + tin1 = tinx; + tin2 = tiny; + } + else + { + // hits y first + tin1 = tiny; + tin2 = tinx; + } + + if(tin1 <= 1.0) + { + if(0.0 < tin1) + { + *x++ = (T)xin; + *y++ = (T)yin; + ++np; + } + + if(tin2 <= 1.0) + { + toutx = (xout - x1) / deltax; + touty = (yout - y1) / deltay; + + tout1 = (toutx < touty) ? toutx : touty; + + if(tin2 > 0.0 || tout1 > 0.0) + { + if(tin2 <= tout1) + { + if(tin2 > 0.0) + { + if(tinx > tiny) + { + *x++ = (T)xin; + *y++ = (T)(y1 + tinx * deltay); + } + else + { + *x++ = (T)(x1 + tiny * deltax); + *y++ = (T)yin; + } + ++np; + } + + if(tout1 < 1.0) + { + if(toutx < touty) + { + *x++ = (T)xout; + *y++ = (T)(y1 + toutx * deltay); + } + else + { + *x++ = (T)(x1 + touty * deltax); + *y++ = (T)yout; + } + } + else + { + *x++ = x2; + *y++ = y2; + } + ++np; + } + else + { + if(tinx > tiny) + { + *x++ = (T)xin; + *y++ = (T)yout; + } + else + { + *x++ = (T)xout; + *y++ = (T)yin; + } + ++np; + } + } + } + } + return np; + } + + +} + +#endif diff --git a/agg/inc/agg_color_gray.h b/agg/inc/agg_color_gray.h new file mode 100755 index 000000000000..1d0ffd8e773d --- /dev/null +++ b/agg/inc/agg_color_gray.h @@ -0,0 +1,364 @@ +//---------------------------------------------------------------------------- +// 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. +// +//---------------------------------------------------------------------------- +// +// color types gray8, gray16 +// +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_GRAY_INCLUDED +#define AGG_COLOR_GRAY_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" + +namespace agg +{ + + //===================================================================gray8 + struct gray8 + { + typedef int8u value_type; + typedef int32u calc_type; + typedef int32 long_type; + enum + { + base_shift = 8, + base_size = 1 << base_shift, + base_mask = base_size - 1 + }; + typedef gray8 self_type; + + value_type v; + value_type a; + + //-------------------------------------------------------------------- + gray8() {} + + //-------------------------------------------------------------------- + gray8(unsigned v_, unsigned a_=base_mask) : + v(int8u(v_)), a(int8u(a_)) {} + + //-------------------------------------------------------------------- + gray8(const self_type& c, unsigned a_) : + v(c.v), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + 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))) {} + + //-------------------------------------------------------------------- + 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))) {} + + //-------------------------------------------------------------------- + gray8(const rgba8& c) : + v((c.r*77 + c.g*150 + c.b*29) >> 8), + a(c.a) {} + + //-------------------------------------------------------------------- + gray8(const rgba8& c, unsigned a_) : + v((c.r*77 + c.g*150 + c.b*29) >> 8), + a(a_) {} + + //-------------------------------------------------------------------- + void clear() + { + v = a = 0; + } + + //-------------------------------------------------------------------- + const self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + void opacity(double a_) + { + if(a_ < 0.0) a_ = 0.0; + if(a_ > 1.0) a_ = 1.0; + a = value_type(a_ * double(base_mask)); + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + + //-------------------------------------------------------------------- + const self_type& premultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + v = 0; + return *this; + } + v = value_type((calc_type(v) * a) >> base_shift); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& premultiply(unsigned a_) + { + if(a == base_mask && a_ >= base_mask) return *this; + if(a == 0 || a_ == 0) + { + v = a = 0; + return *this; + } + calc_type v_ = (calc_type(v) * a_) / a; + v = value_type((v_ > a_) ? a_ : v_); + a = value_type(a_); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& demultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + v = 0; + return *this; + } + calc_type v_ = (calc_type(v) * base_mask) / a; + v = value_type((v_ > base_mask) ? base_mask : v_); + return *this; + } + + //-------------------------------------------------------------------- + self_type gradient(self_type c, double k) const + { + self_type ret; + calc_type ik = calc_type(k * base_size); + 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; + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0); } + }; + + + //-------------------------------------------------------------gray8_pre + inline gray8 gray8_pre(unsigned v, unsigned a = gray8::base_mask) + { + return gray8(v,a).premultiply(); + } + inline gray8 gray8_pre(const gray8& c, unsigned a) + { + return gray8(c,a).premultiply(); + } + inline gray8 gray8_pre(const rgba& c) + { + return gray8(c).premultiply(); + } + inline gray8 gray8_pre(const rgba& c, double a) + { + return gray8(c,a).premultiply(); + } + inline gray8 gray8_pre(const rgba8& c) + { + return gray8(c).premultiply(); + } + inline gray8 gray8_pre(const rgba8& c, unsigned a) + { + return gray8(c,a).premultiply(); + } + + + + + //==================================================================gray16 + struct gray16 + { + typedef int16u value_type; + typedef int32u calc_type; + typedef int64 long_type; + enum + { + base_shift = 16, + base_size = 1 << base_shift, + base_mask = base_size - 1 + }; + typedef gray16 self_type; + + value_type v; + value_type a; + + //-------------------------------------------------------------------- + gray16() {} + + //-------------------------------------------------------------------- + gray16(unsigned v_, unsigned a_=base_mask) : + v(int16u(v_)), a(int16u(a_)) {} + + //-------------------------------------------------------------------- + gray16(const self_type& c, unsigned a_) : + v(c.v), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + 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))) {} + + //-------------------------------------------------------------------- + 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))) {} + + //-------------------------------------------------------------------- + gray16(const rgba8& c) : + v(c.r*77 + c.g*150 + c.b*29), + a((value_type(c.a) << 8) | c.a) {} + + //-------------------------------------------------------------------- + gray16(const rgba8& c, unsigned a_) : + v(c.r*77 + c.g*150 + c.b*29), + a((value_type(a_) << 8) | c.a) {} + + //-------------------------------------------------------------------- + void clear() + { + v = a = 0; + } + + //-------------------------------------------------------------------- + const self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + void opacity(double a_) + { + if(a_ < 0.0) a_ = 0.0; + if(a_ > 1.0) a_ = 1.0; + a = value_type(a_ * double(base_mask)); + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + + //-------------------------------------------------------------------- + const self_type& premultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + v = 0; + return *this; + } + v = value_type((calc_type(v) * a) >> base_shift); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& premultiply(unsigned a_) + { + if(a == base_mask && a_ >= base_mask) return *this; + if(a == 0 || a_ == 0) + { + v = a = 0; + return *this; + } + calc_type v_ = (calc_type(v) * a_) / a; + v = value_type((v_ > a_) ? a_ : v_); + a = value_type(a_); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& demultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + v = 0; + return *this; + } + calc_type v_ = (calc_type(v) * base_mask) / a; + v = value_type((v_ > base_mask) ? base_mask : v_); + return *this; + } + + //-------------------------------------------------------------------- + self_type gradient(self_type c, double k) const + { + self_type ret; + calc_type ik = calc_type(k * base_size); + 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; + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0); } + }; + + + //------------------------------------------------------------gray16_pre + inline gray16 gray16_pre(unsigned v, unsigned a = gray16::base_mask) + { + return gray16(v,a).premultiply(); + } + inline gray16 gray16_pre(const gray16& c, unsigned a) + { + return gray16(c,a).premultiply(); + } + inline gray16 gray16_pre(const rgba& c) + { + return gray16(c).premultiply(); + } + inline gray16 gray16_pre(const rgba& c, double a) + { + return gray16(c,a).premultiply(); + } + inline gray16 gray16_pre(const rgba8& c) + { + return gray16(c).premultiply(); + } + inline gray16 gray16_pre(const rgba8& c, unsigned a) + { + return gray16(c,a).premultiply(); + } + + +} + + + + +#endif diff --git a/agg/inc/agg_color_rgba.h b/agg/inc/agg_color_rgba.h new file mode 100755 index 000000000000..e1f77206cc66 --- /dev/null +++ b/agg/inc/agg_color_rgba.h @@ -0,0 +1,618 @@ +//---------------------------------------------------------------------------- +// 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. +// +//---------------------------------------------------------------------------- +// +// 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. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_RGBA_INCLUDED +#define AGG_COLOR_RGBA_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +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 + + //====================================================================rgba + struct rgba + { + typedef double value_type; + + double r; + double g; + double b; + double a; + + //-------------------------------------------------------------------- + rgba() {} + + //-------------------------------------------------------------------- + rgba(double r_, double g_, double b_, double a_=1.0) : + r(r_), g(g_), b(b_), a(a_) {} + + //-------------------------------------------------------------------- + rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {} + + //-------------------------------------------------------------------- + void clear() + { + r = g = b = a = 0; + } + + //-------------------------------------------------------------------- + const rgba& transparent() + { + a = 0.0; + return *this; + } + + //-------------------------------------------------------------------- + const rgba& opacity(double a_) + { + if(a_ < 0.0) a_ = 0.0; + if(a_ > 1.0) a_ = 1.0; + a = a_; + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return a; + } + + //-------------------------------------------------------------------- + const rgba& premultiply() + { + r *= a; + g *= a; + b *= a; + return *this; + } + + //-------------------------------------------------------------------- + const rgba& premultiply(double a_) + { + if(a <= 0.0 || a_ <= 0.0) + { + r = g = b = a = 0.0; + return *this; + } + a_ /= a; + r *= a_; + g *= a_; + b *= a_; + a = a_; + return *this; + } + + //-------------------------------------------------------------------- + const rgba& demultiply() + { + if(a == 0) + { + r = g = b = 0; + return *this; + } + double a_ = 1.0 / a; + r *= a_; + g *= a_; + b *= a_; + return *this; + } + + + //-------------------------------------------------------------------- + rgba gradient(rgba c, double k) const + { + rgba ret; + ret.r = r + (c.r - r) * k; + ret.g = g + (c.g - g) * k; + ret.b = b + (c.b - b) * k; + ret.a = a + (c.a - a) * k; + return ret; + } + + //-------------------------------------------------------------------- + static rgba no_color() { return rgba(0,0,0,0); } + + //-------------------------------------------------------------------- + static rgba from_wavelength(double wl, double gamma = 1.0); + + //-------------------------------------------------------------------- + rgba(double wavelen, double gamma=1.0) + { + *this = from_wavelength(wavelen, gamma); + } + + }; + + //----------------------------------------------------------------rgba_pre + inline rgba rgba_pre(double r, double g, double b, double a=1.0) + { + return rgba(r, g, b, a).premultiply(); + } + inline rgba rgba_pre(const rgba& c) + { + return rgba(c).premultiply(); + } + inline rgba rgba_pre(const rgba& c, double a) + { + return rgba(c, a).premultiply(); + } + + //------------------------------------------------------------------------ + inline rgba rgba::from_wavelength(double wl, double gamma) + { + rgba t(0.0, 0.0, 0.0); + + if(wl >= 380.0 && wl <= 440.0) + { + t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0); + t.b = 1.0; + } + else + if(wl >= 440.0 && wl <= 490.0) + { + t.g = (wl - 440.0) / (490.0 - 440.0); + t.b = 1.0; + } + else + if(wl >= 490.0 && wl <= 510.0) + { + t.g = 1.0; + t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0); + } + else + if(wl >= 510.0 && wl <= 580.0) + { + t.r = (wl - 510.0) / (580.0 - 510.0); + t.g = 1.0; + } + else + if(wl >= 580.0 && wl <= 645.0) + { + t.r = 1.0; + t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0); + } + else + if(wl >= 645.0 && wl <= 780.0) + { + t.r = 1.0; + } + + double s = 1.0; + if(wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0); + else if(wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0); + + t.r = pow(t.r * s, gamma); + t.g = pow(t.g * s, gamma); + t.b = pow(t.b * s, gamma); + return t; + } + + + + + //===================================================================rgba8 + struct rgba8 + { + typedef int8u value_type; + typedef int32u calc_type; + typedef int32 long_type; + enum + { + base_shift = 8, + base_size = 1 << base_shift, + base_mask = base_size - 1 + }; + typedef rgba8 self_type; + + + value_type r; + value_type g; + value_type b; + value_type a; + + //-------------------------------------------------------------------- + rgba8() {} + + //-------------------------------------------------------------------- + rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) : + r(value_type(r_)), + g(value_type(g_)), + b(value_type(b_)), + a(value_type(a_)) {} + + //-------------------------------------------------------------------- + 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)) {} + + //-------------------------------------------------------------------- + rgba8(const self_type& c, unsigned a_) : + r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + 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)) {} + + //-------------------------------------------------------------------- + void clear() + { + r = g = b = a = 0; + } + + //-------------------------------------------------------------------- + const self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + 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); + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + //-------------------------------------------------------------------- + const self_type& premultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + r = g = b = 0; + return *this; + } + r = value_type((calc_type(r) * a) >> base_shift); + g = value_type((calc_type(g) * a) >> base_shift); + b = value_type((calc_type(b) * a) >> base_shift); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& premultiply(unsigned a_) + { + if(a == base_mask && a_ >= base_mask) return *this; + if(a == 0 || a_ == 0) + { + r = g = b = a = 0; + return *this; + } + calc_type r_ = (calc_type(r) * a_) / a; + calc_type g_ = (calc_type(g) * a_) / a; + calc_type b_ = (calc_type(b) * a_) / a; + r = value_type((r_ > a_) ? a_ : r_); + g = value_type((g_ > a_) ? a_ : g_); + b = value_type((b_ > a_) ? a_ : b_); + a = value_type(a_); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& demultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + r = g = b = 0; + return *this; + } + 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_); + return *this; + } + + //-------------------------------------------------------------------- + self_type gradient(const self_type& c, double k) const + { + self_type ret; + calc_type ik = calc_type(k * base_size); + 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)); + ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); + return ret; + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0,0,0); } + + //-------------------------------------------------------------------- + static self_type from_wavelength(double wl, double gamma = 1.0) + { + return self_type(rgba::from_wavelength(wl, gamma)); + } + }; + + + //-------------------------------------------------------------rgba8_pre + inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, + unsigned a = rgba8::base_mask) + { + return rgba8(r,g,b,a).premultiply(); + } + inline rgba8 rgba8_pre(const rgba8& c) + { + return rgba8(c).premultiply(); + } + inline rgba8 rgba8_pre(const rgba8& c, unsigned a) + { + return rgba8(c,a).premultiply(); + } + inline rgba8 rgba8_pre(const rgba& c) + { + return rgba8(c).premultiply(); + } + inline rgba8 rgba8_pre(const rgba& c, double a) + { + return rgba8(c,a).premultiply(); + } + + + //-----------------------------------------------------------rgb8_packed + inline rgba8 rgb8_packed(unsigned v) + { + return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); + } + + //-----------------------------------------------------------bgr8_packed + inline rgba8 bgr8_packed(unsigned v) + { + return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF); + } + + //----------------------------------------------------------argb8_packed + inline rgba8 argb8_packed(unsigned v) + { + return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24); + } + + + + + + + + + //=================================================================rgba16 + struct rgba16 + { + typedef int16u value_type; + typedef int32u calc_type; + typedef int64 long_type; + enum + { + base_shift = 16, + base_size = 1 << base_shift, + base_mask = base_size - 1 + }; + typedef rgba16 self_type; + + value_type r; + value_type g; + value_type b; + value_type a; + + //-------------------------------------------------------------------- + rgba16() {} + + //-------------------------------------------------------------------- + rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) : + r(value_type(r_)), + g(value_type(g_)), + b(value_type(b_)), + a(value_type(a_)) {} + + //-------------------------------------------------------------------- + rgba16(const self_type& c, unsigned a_) : + r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + 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)) {} + + //-------------------------------------------------------------------- + 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)) {} + + //-------------------------------------------------------------------- + rgba16(const rgba8& c) : + r(value_type((value_type(c.r) << 8) | c.r)), + g(value_type((value_type(c.g) << 8) | c.g)), + b(value_type((value_type(c.b) << 8) | c.b)), + a(value_type((value_type(c.a) << 8) | c.a)) {} + + //-------------------------------------------------------------------- + rgba16(const rgba8& c, unsigned a_) : + r(value_type((value_type(c.r) << 8) | c.r)), + g(value_type((value_type(c.g) << 8) | c.g)), + b(value_type((value_type(c.b) << 8) | c.b)), + a(value_type(( a_ << 8) | c.a)) {} + + //-------------------------------------------------------------------- + void clear() + { + r = g = b = a = 0; + } + + //-------------------------------------------------------------------- + const self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + 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); + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + //-------------------------------------------------------------------- + const self_type& premultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + r = g = b = 0; + return *this; + } + r = value_type((calc_type(r) * a) >> base_shift); + g = value_type((calc_type(g) * a) >> base_shift); + b = value_type((calc_type(b) * a) >> base_shift); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& premultiply(unsigned a_) + { + if(a == base_mask && a_ >= base_mask) return *this; + if(a == 0 || a_ == 0) + { + r = g = b = a = 0; + return *this; + } + calc_type r_ = (calc_type(r) * a_) / a; + calc_type g_ = (calc_type(g) * a_) / a; + calc_type b_ = (calc_type(b) * a_) / a; + r = value_type((r_ > a_) ? a_ : r_); + g = value_type((g_ > a_) ? a_ : g_); + b = value_type((b_ > a_) ? a_ : b_); + a = value_type(a_); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& demultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + r = g = b = 0; + return *this; + } + 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_); + return *this; + } + + //-------------------------------------------------------------------- + self_type gradient(const self_type& c, double k) const + { + self_type ret; + calc_type ik = calc_type(k * base_size); + 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)); + ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); + return ret; + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0,0,0); } + + //-------------------------------------------------------------------- + static self_type from_wavelength(double wl, double gamma = 1.0) + { + return self_type(rgba::from_wavelength(wl, gamma)); + } + }; + + + + //--------------------------------------------------------------rgba16_pre + inline rgba16 rgba16_pre(unsigned r, unsigned g, unsigned b, + unsigned a = rgba16::base_mask) + { + return rgba16(r,g,b,a).premultiply(); + } + inline rgba16 rgba16_pre(const rgba16& c, unsigned a) + { + return rgba16(c,a).premultiply(); + } + inline rgba16 rgba16_pre(const rgba& c) + { + return rgba16(c).premultiply(); + } + inline rgba16 rgba16_pre(const rgba& c, double a) + { + return rgba16(c,a).premultiply(); + } + inline rgba16 rgba16_pre(const rgba8& c) + { + return rgba16(c).premultiply(); + } + inline rgba16 rgba16_pre(const rgba8& c, unsigned a) + { + return rgba16(c,a).premultiply(); + } + +} + + + +#endif diff --git a/agg/inc/agg_config.h b/agg/inc/agg_config.h new file mode 100755 index 000000000000..b412a6dff178 --- /dev/null +++ b/agg/inc/agg_config.h @@ -0,0 +1,31 @@ +#ifndef AGG_CONFIG_INCLUDED +#define AGG_CONFIG_INCLUDED + +// This file can be used to redefine the default basic types such as: +// +// AGG_INT8 +// AGG_INT8U +// AGG_INT16 +// AGG_INT16U +// AGG_INT32 +// AGG_INT32U +// AGG_INT64 +// AGG_INT64U +// +// Just replace this file with new defines if necessary. +// For example, if your compiler doesn't have a 64 bit integer type +// you can still use AGG if you define the follows: +// +// #define AGG_INT64 int +// #define AGG_INT64U unsigned +// +// It will result in overflow in 16 bit-per-component image/pattern resampling +// but it won't result any crash and the rest of the library will remain +// fully functional. + +// #i65318# Passing agg version on to clients +#ifndef AGG_VERSION +# define AGG_VERSION 2300 +#endif + +#endif diff --git a/agg/inc/agg_conv_adaptor_vcgen.h b/agg/inc/agg_conv_adaptor_vcgen.h new file mode 100755 index 000000000000..f8233a388357 --- /dev/null +++ b/agg/inc/agg_conv_adaptor_vcgen.h @@ -0,0 +1,169 @@ +//---------------------------------------------------------------------------- +// 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_CONV_ADAPTOR_VCGEN_INCLUDED +#define AGG_CONV_ADAPTOR_VCGEN_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + //------------------------------------------------------------null_markers + struct null_markers + { + void remove_all() {} + void add_vertex(double, double, unsigned) {} + void prepare_src() {} + + 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); } + }; + + + //------------------------------------------------------conv_adaptor_vcgen + template<class VertexSource, + class Generator, + class Markers=null_markers> class conv_adaptor_vcgen + { + enum status + { + initial, + accumulate, + generate + }; + + public: + conv_adaptor_vcgen(VertexSource& source) : + m_source(&source), + m_status(initial) + {} + + void set_source(VertexSource& source) { m_source = &source; } + + Generator& generator() { return m_generator; } + const Generator& generator() const { return m_generator; } + + Markers& markers() { return m_markers; } + const Markers& markers() const { return m_markers; } + + void rewind(unsigned id) + { + m_source->rewind(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>&); + const conv_adaptor_vcgen<VertexSource, Generator, Markers>& + operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&); + + VertexSource* m_source; + Generator m_generator; + Markers m_markers; + status m_status; + unsigned m_last_cmd; + double m_start_x; + double m_start_y; + }; + + + + + + //------------------------------------------------------------------------ + template<class VertexSource, class Generator, class Markers> + unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + bool done = false; + while(!done) + { + switch(m_status) + { + case initial: + m_markers.remove_all(); + m_last_cmd = m_source->vertex(&m_start_x, &m_start_y); + m_status = accumulate; + + case accumulate: + if(is_stop(m_last_cmd)) return path_cmd_stop; + + m_generator.remove_all(); + m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to); + m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to); + + for(;;) + { + cmd = m_source->vertex(x, y); + if(is_vertex(cmd)) + { + m_last_cmd = cmd; + if(is_move_to(cmd)) + { + m_start_x = *x; + m_start_y = *y; + break; + } + m_generator.add_vertex(*x, *y, cmd); + m_markers.add_vertex(*x, *y, path_cmd_line_to); + } + else + { + if(is_stop(cmd)) + { + m_last_cmd = path_cmd_stop; + break; + } + if(is_end_poly(cmd)) + { + m_generator.add_vertex(*x, *y, cmd); + break; + } + } + } + m_generator.rewind(0); + m_status = generate; + + case generate: + cmd = m_generator.vertex(x, y); + if(is_stop(cmd)) + { + m_status = accumulate; + break; + } + done = true; + break; + } + } + return cmd; + } + +} + +#endif diff --git a/agg/inc/agg_conv_adaptor_vpgen.h b/agg/inc/agg_conv_adaptor_vpgen.h new file mode 100755 index 000000000000..f6afdb4d7f12 --- /dev/null +++ b/agg/inc/agg_conv_adaptor_vpgen.h @@ -0,0 +1,166 @@ +//---------------------------------------------------------------------------- +// 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_CONV_ADAPTOR_VPGEN_INCLUDED +#define AGG_CONV_ADAPTOR_VPGEN_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + + //======================================================conv_adaptor_vpgen + 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; } + + VPGen& vpgen() { return m_vpgen; } + const VPGen& vpgen() const { return m_vpgen; } + + 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>& + operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&); + + VertexSource* m_source; + VPGen m_vpgen; + double m_start_x; + double m_start_y; + unsigned m_poly_flags; + int m_vertices; + }; + + + + //------------------------------------------------------------------------ + template<class VertexSource, class VPGen> + void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id) + { + m_source->rewind(path_id); + m_vpgen.reset(); + m_start_x = 0; + m_start_y = 0; + m_poly_flags = 0; + m_vertices = 0; + } + + + //------------------------------------------------------------------------ + template<class VertexSource, class VPGen> + unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + for(;;) + { + cmd = m_vpgen.vertex(x, y); + if(!is_stop(cmd)) break; + + if(m_poly_flags && !m_vpgen.auto_unclose()) + { + *x = 0.0; + *y = 0.0; + cmd = m_poly_flags; + m_poly_flags = 0; + break; + } + + if(m_vertices < 0) + { + if(m_vertices < -1) + { + m_vertices = 0; + return path_cmd_stop; + } + m_vpgen.move_to(m_start_x, m_start_y); + m_vertices = 1; + continue; + } + + double tx, ty; + cmd = m_source->vertex(&tx, &ty); + if(is_vertex(cmd)) + { + if(is_move_to(cmd)) + { + if(m_vpgen.auto_close() && m_vertices > 2) + { + m_vpgen.line_to(m_start_x, m_start_y); + m_poly_flags = path_cmd_end_poly | path_flags_close; + m_start_x = tx; + m_start_y = ty; + m_vertices = -1; + continue; + } + m_vpgen.move_to(tx, ty); + m_start_x = tx; + m_start_y = ty; + m_vertices = 1; + } + else + { + m_vpgen.line_to(tx, ty); + ++m_vertices; + } + } + else + { + if(is_end_poly(cmd)) + { + m_poly_flags = cmd; + if(is_closed(cmd) || m_vpgen.auto_close()) + { + if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close; + if(m_vertices > 2) + { + m_vpgen.line_to(m_start_x, m_start_y); + } + m_vertices = 0; + } + } + else + { + // path_cmd_stop + if(m_vpgen.auto_close() && m_vertices > 2) + { + m_vpgen.line_to(m_start_x, m_start_y); + m_poly_flags = path_cmd_end_poly | path_flags_close; + m_vertices = -2; + continue; + } + break; + } + } + } + return cmd; + } + + +} + + +#endif + diff --git a/agg/inc/agg_conv_bspline.h b/agg/inc/agg_conv_bspline.h new file mode 100755 index 000000000000..9c504daff209 --- /dev/null +++ b/agg/inc/agg_conv_bspline.h @@ -0,0 +1,48 @@ +//---------------------------------------------------------------------------- +// 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_CONV_BSPLINE_INCLUDED +#define AGG_CONV_BSPLINE_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_bspline.h" +#include "agg_conv_adaptor_vcgen.h" + + +namespace agg +{ + + //---------------------------------------------------------conv_bspline + template<class VertexSource> + struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline> + { + typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type; + + conv_bspline(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) {} + + void interpolation_step(double v) { base_type::generator().interpolation_step(v); } + double interpolation_step() const { return base_type::generator().interpolation_step(); } + + private: + conv_bspline(const conv_bspline<VertexSource>&); + const conv_bspline<VertexSource>& + operator = (const conv_bspline<VertexSource>&); + }; + +} + + +#endif + diff --git a/agg/inc/agg_conv_clip_polygon.h b/agg/inc/agg_conv_clip_polygon.h new file mode 100755 index 000000000000..cbecc51fbdd5 --- /dev/null +++ b/agg/inc/agg_conv_clip_polygon.h @@ -0,0 +1,69 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Polygon clipping converter +// There an optimized Liang-Basky algorithm is used. +// The algorithm doesn't optimize the degenerate edges, i.e. it will never +// break a closed polygon into two or more ones, instead, there will be +// degenerate edges coinciding with the respective clipping boundaries. +// This is a sub-optimal solution, because that optimization would require +// extra, rather expensive math while the rasterizer tolerates it quite well, +// without any considerable overhead. +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_CLIP_POLYGON_INCLUDED +#define AGG_CONV_CLIP_POLYGON_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vpgen.h" +#include "agg_vpgen_clip_polygon.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + + //=======================================================conv_clip_polygon + template<class VertexSource> + struct conv_clip_polygon : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> + { + typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> base_type; + + conv_clip_polygon(VertexSource& vs) : + conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) {} + + void clip_box(double x1, double y1, double x2, double y2) + { + base_type::vpgen().clip_box(x1, y1, x2, y2); + } + + double x1() const { return base_type::vpgen().x1(); } + double y1() const { return base_type::vpgen().y1(); } + 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>& + operator = (const conv_clip_polygon<VertexSource>&); + }; + +} + +#endif diff --git a/agg/inc/agg_conv_clip_polyline.h b/agg/inc/agg_conv_clip_polyline.h new file mode 100755 index 000000000000..4ac66276891c --- /dev/null +++ b/agg/inc/agg_conv_clip_polyline.h @@ -0,0 +1,69 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// polyline clipping converter +// There an optimized Liang-Basky algorithm is used. +// The algorithm doesn't optimize the degenerate edges, i.e. it will never +// break a closed polyline into two or more ones, instead, there will be +// degenerate edges coinciding with the respective clipping boundaries. +// This is a sub-optimal solution, because that optimization would require +// extra, rather expensive math while the rasterizer tolerates it quite well, +// without any considerable overhead. +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_CLIP_polyline_INCLUDED +#define AGG_CONV_CLIP_polyline_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vpgen.h" +#include "agg_vpgen_clip_polyline.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + + //=======================================================conv_clip_polyline + template<class VertexSource> + struct conv_clip_polyline : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> + { + typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> base_type; + + conv_clip_polyline(VertexSource& vs) : + conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(vs) {} + + void clip_box(double x1, double y1, double x2, double y2) + { + base_type::vpgen().clip_box(x1, y1, x2, y2); + } + + double x1() const { return base_type::vpgen().x1(); } + double y1() const { return base_type::vpgen().y1(); } + 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>& + operator = (const conv_clip_polyline<VertexSource>&); + }; + +} + +#endif diff --git a/agg/inc/agg_conv_close_polygon.h b/agg/inc/agg_conv_close_polygon.h new file mode 100755 index 000000000000..60a756a7408a --- /dev/null +++ b/agg/inc/agg_conv_close_polygon.h @@ -0,0 +1,132 @@ +//---------------------------------------------------------------------------- +// 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_CONV_CLOSE_POLYGON_INCLUDED +#define AGG_CONV_CLOSE_POLYGON_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + + //======================================================conv_close_polygon + template<class VertexSource> class conv_close_polygon + { + public: + conv_close_polygon(VertexSource& vs) : m_source(&vs) {} + + void set_source(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>& + operator = (const conv_close_polygon<VertexSource>&); + + VertexSource* m_source; + unsigned m_cmd[2]; + double m_x[2]; + double m_y[2]; + unsigned m_vertex; + bool m_line_to; + }; + + + + //------------------------------------------------------------------------ + template<class VertexSource> + void conv_close_polygon<VertexSource>::rewind(unsigned path_id) + { + m_source->rewind(path_id); + m_vertex = 2; + m_line_to = false; + } + + + + //------------------------------------------------------------------------ + template<class VertexSource> + unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + for(;;) + { + if(m_vertex < 2) + { + *x = m_x[m_vertex]; + *y = m_y[m_vertex]; + cmd = m_cmd[m_vertex]; + ++m_vertex; + break; + } + + cmd = m_source->vertex(x, y); + + if(is_end_poly(cmd)) + { + cmd |= path_flags_close; + break; + } + + if(is_stop(cmd)) + { + if(m_line_to) + { + m_cmd[0] = path_cmd_end_poly | path_flags_close; + m_cmd[1] = path_cmd_stop; + m_vertex = 0; + m_line_to = false; + continue; + } + break; + } + + if(is_move_to(cmd)) + { + if(m_line_to) + { + m_x[0] = 0.0; + m_y[0] = 0.0; + m_cmd[0] = path_cmd_end_poly | path_flags_close; + m_x[1] = *x; + m_y[1] = *y; + m_cmd[1] = cmd; + m_vertex = 0; + m_line_to = false; + continue; + } + break; + } + + if(is_vertex(cmd)) + { + m_line_to = true; + break; + } + } + return cmd; + } + +} + +#endif diff --git a/agg/inc/agg_conv_concat.h b/agg/inc/agg_conv_concat.h new file mode 100755 index 000000000000..2b9886a1be46 --- /dev/null +++ b/agg/inc/agg_conv_concat.h @@ -0,0 +1,80 @@ +//---------------------------------------------------------------------------- +// 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_CONV_CONCAT_INCLUDED +#define AGG_CONV_CONCAT_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + //=============================================================conv_concat + // Concatenation of two paths. Usually used to combine lines or curves + // with markers such as arrowheads + template<class VS1, class VS2> class conv_concat + { + public: + conv_concat(VS1& source1, VS2& source2) : + m_source1(&source1), m_source2(&source2), m_status(2) {} + + void set_source1(VS1& source) { m_source1 = &source; } + void set_source2(VS2& source) { m_source2 = &source; } + + + void rewind(unsigned id) + { + m_source1->rewind(id); + m_source2->rewind(0); + m_status = 0; + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd; + if(m_status == 0) + { + cmd = m_source1->vertex(x, y); + if(!is_stop(cmd)) return cmd; + m_status = 1; + } + if(m_status == 1) + { + cmd = m_source2->vertex(x, y); + if(!is_stop(cmd)) return cmd; + m_status = 2; + } + 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>& + operator = (const conv_concat<VS1, VS2>&); + + VS1* m_source1; + VS2* m_source2; + int m_status; + + }; +} + + +#endif diff --git a/agg/inc/agg_conv_contour.h b/agg/inc/agg_conv_contour.h new file mode 100755 index 000000000000..652a8e1fa4f3 --- /dev/null +++ b/agg/inc/agg_conv_contour.h @@ -0,0 +1,65 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// conv_stroke +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_CONTOUR_INCLUDED +#define AGG_CONV_CONTOUR_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_contour.h" +#include "agg_conv_adaptor_vcgen.h" + +namespace agg +{ + + //-----------------------------------------------------------conv_contour + template<class VertexSource> + struct conv_contour : public conv_adaptor_vcgen<VertexSource, vcgen_contour> + { + typedef conv_adaptor_vcgen<VertexSource, vcgen_contour> base_type; + + conv_contour(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs) + { + } + + 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 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); } + void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); } + void approximation_scale(double as) { base_type::generator().approximation_scale(as); } + 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(); } + 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(); } + double approximation_scale() const { return base_type::generator().approximation_scale(); } + bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); } + + private: + conv_contour(const conv_contour<VertexSource>&); + const conv_contour<VertexSource>& + operator = (const conv_contour<VertexSource>&); + }; + +} + +#endif diff --git a/agg/inc/agg_conv_curve.h b/agg/inc/agg_conv_curve.h new file mode 100755 index 000000000000..3b8e6cff2e2e --- /dev/null +++ b/agg/inc/agg_conv_curve.h @@ -0,0 +1,174 @@ +//---------------------------------------------------------------------------- +// 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 conv_curve +// +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_CURVE_INCLUDED +#define AGG_CONV_CURVE_INCLUDED + +#include "agg_basics.h" +#include "agg_curves.h" + +namespace agg +{ + + + //---------------------------------------------------------------conv_curve + // Curve converter class. Any path storage can have Bezier curves defined + // by their control points. There're two types of curves supported: curve3 + // 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 + // 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 + // 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, + // all we will see is only 2 or 3 straight line segments (for curve3 and + // curve4 respectively). If we need to see real curves drawn we need to + // include this class into the conversion pipeline. + // + // 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 + { + public: + conv_curve(VertexSource& source) : + m_source(&source), m_last_x(0.0), m_last_y(0.0) {} + + void set_source(VertexSource& source) { m_source = &source; } + + void approximation_scale(double s) + { + m_curve3.approximation_scale(s); + m_curve4.approximation_scale(s); + } + + double approximation_scale() const + { + return m_curve3.approximation_scale(); + } + + void rewind(unsigned id); + unsigned vertex(double* x, double* y); + + 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); } + + private: + conv_curve(const conv_curve<VertexSource>&); + const conv_curve<VertexSource>& + operator = (const conv_curve<VertexSource>&); + + VertexSource* m_source; + double m_last_x; + double m_last_y; + curve3 m_curve3; + curve4 m_curve4; + }; + + + + //------------------------------------------------------------------------ + template<class VertexSource> + void conv_curve<VertexSource>::rewind(unsigned id) + { + m_source->rewind(id); + m_last_x = 0.0; + m_last_y = 0.0; + m_curve3.reset(); + m_curve4.reset(); + } + + + //------------------------------------------------------------------------ + template<class VertexSource> + unsigned conv_curve<VertexSource>::vertex(double* x, double* y) + { + if(!is_stop(m_curve3.vertex(x, y))) + { + m_last_x = *x; + m_last_y = *y; + return path_cmd_line_to; + } + + if(!is_stop(m_curve4.vertex(x, y))) + { + m_last_x = *x; + m_last_y = *y; + return path_cmd_line_to; + } + + double ct2_x = 0; + double ct2_y = 0; + double end_x = 0; + double end_y = 0; + + 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); + + m_curve3.init(m_last_x, m_last_y, + *x, *y, + end_x, end_y); + + m_curve3.vertex(x, y); // First call returns path_cmd_move_to + m_curve3.vertex(x, y); // This is the first vertex of the curve + cmd = path_cmd_line_to; + break; + + case path_cmd_curve4: + m_source->vertex(&ct2_x, &ct2_y); + m_source->vertex(&end_x, &end_y); + + m_curve4.init(m_last_x, m_last_y, + *x, *y, + ct2_x, ct2_y, + end_x, end_y); + + m_curve4.vertex(x, y); // First call returns path_cmd_move_to + m_curve4.vertex(x, y); // This is the first vertex of the curve + cmd = path_cmd_line_to; + break; + } + return cmd; + } + + +} + + + +#endif diff --git a/agg/inc/agg_conv_dash.h b/agg/inc/agg_conv_dash.h new file mode 100755 index 000000000000..0520276bbb96 --- /dev/null +++ b/agg/inc/agg_conv_dash.h @@ -0,0 +1,68 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// conv_dash +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_DASH_INCLUDED +#define AGG_CONV_DASH_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_dash.h" +#include "agg_conv_adaptor_vcgen.h" + +namespace agg +{ + + //---------------------------------------------------------------conv_dash + template<class VertexSource, class Markers=null_markers> + struct conv_dash : public conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers> + { + typedef Markers marker_type; + typedef conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers> base_type; + + conv_dash(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs) + { + } + + void remove_all_dashes() + { + base_type::generator().remove_all_dashes(); + } + + void add_dash(double dash_len, double gap_len) + { + base_type::generator().add_dash(dash_len, gap_len); + } + + void dash_start(double ds) + { + base_type::generator().dash_start(ds); + } + + void shorten(double s) { base_type::generator().shorten(s); } + double shorten() const { return base_type::generator().shorten(); } + + private: + conv_dash(const conv_dash<VertexSource, Markers>&); + const conv_dash<VertexSource, Markers>& + operator = (const conv_dash<VertexSource, Markers>&); + }; + + +} + +#endif diff --git a/agg/inc/agg_conv_gpc.h b/agg/inc/agg_conv_gpc.h new file mode 100755 index 000000000000..1810309d208a --- /dev/null +++ b/agg/inc/agg_conv_gpc.h @@ -0,0 +1,443 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// General Polygon Clipper based on the GPC library by Alan Murta +// Union, Intersection, XOR, A-B, B-A +// Contact the author if you intend to use it in commercial applications! +// http://www.cs.man.ac.uk/aig/staff/alan/software/ +// Alan Murta (email: gpc@cs.man.ac.uk) +// +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_GPC_INCLUDED +#define AGG_CONV_GPC_INCLUDED + +#include <math.h> +#include "agg_basics.h" +#include "agg_array.h" +#include "agg_vertex_iterator.h" + +extern "C" +{ +#include "gpc.h" +} + +namespace agg +{ + enum gpc_op_e + { + gpc_or, + gpc_and, + gpc_xor, + gpc_a_minus_b, + gpc_b_minus_a + }; + + + //================================================================conv_gpc + template<class VSA, class VSB> class conv_gpc + { + enum status + { + status_move_to, + status_line_to, + status_stop + }; + + struct contour_header_type + { + int num_vertices; + int hole_flag; + gpc_vertex* vertices; + }; + + typedef pod_deque<gpc_vertex, 8> vertex_array_type; + typedef pod_deque<contour_header_type, 6> contour_header_array_type; + + + public: + typedef VSA source_a_type; + typedef VSB source_b_type; + typedef conv_gpc<source_a_type, source_b_type> self_type; + + ~conv_gpc() + { + free_gpc_data(); + } + + conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) : + m_src_a(&a), + m_src_b(&b), + m_status(status_move_to), + m_vertex(-1), + m_contour(-1), + m_operation(op) + { + memset(&m_poly_a, 0, sizeof(m_poly_a)); + memset(&m_poly_b, 0, sizeof(m_poly_b)); + 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 operation(gpc_op_e v) { m_operation = v; } + + // Vertex Source Interface + void rewind(unsigned 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>&); + + //-------------------------------------------------------------------- + void free_polygon(gpc_polygon& p); + void free_result(); + void free_gpc_data(); + void start_contour(); + void add_vertex(double x, double y); + void end_contour(unsigned orientation); + void make_polygon(gpc_polygon& p); + void start_extracting(); + bool next_contour(); + bool next_vertex(double* x, double* y); + + + //-------------------------------------------------------------------- + template<class VS> void add(VS& src, gpc_polygon& p) + { + unsigned cmd; + double x, y; + double start_x = 0.0; + double start_y = 0.0; + bool line_to = false; + unsigned orientation = 0; + + m_contour_accumulator.remove_all(); + + while(!is_stop(cmd = src.vertex(&x, &y))) + { + if(is_vertex(cmd)) + { + if(is_move_to(cmd)) + { + if(line_to) + { + end_contour(orientation); + orientation = 0; + } + start_contour(); + start_x = x; + start_y = y; + } + add_vertex(x, y); + line_to = true; + } + else + { + if(is_end_poly(cmd)) + { + orientation = get_orientation(cmd); + if(line_to && is_closed(cmd)) + { + add_vertex(start_x, start_y); + } + } + } + } + if(line_to) + { + end_contour(orientation); + } + make_polygon(p); + } + + + private: + //-------------------------------------------------------------------- + source_a_type* m_src_a; + source_b_type* m_src_b; + status m_status; + int m_vertex; + int m_contour; + gpc_op_e m_operation; + vertex_array_type m_vertex_accumulator; + contour_header_array_type m_contour_accumulator; + gpc_polygon m_poly_a; + gpc_polygon m_poly_b; + gpc_polygon m_result; + }; + + + + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::free_polygon(gpc_polygon& p) + { + int i; + for(i = 0; i < p.num_contours; i++) + { + delete [] p.contour[i].vertex; + } + delete [] p.hole; + delete [] p.contour; + memset(&p, 0, sizeof(gpc_polygon)); + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::free_result() + { + if(m_result.contour) + { + gpc_free_polygon(&m_result); + } + memset(&m_result, 0, sizeof(m_result)); + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::free_gpc_data() + { + free_polygon(m_poly_a); + free_polygon(m_poly_b); + free_result(); + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::start_contour() + { + contour_header_type h; + memset(&h, 0, sizeof(h)); + m_contour_accumulator.add(h); + m_vertex_accumulator.remove_all(); + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + inline void conv_gpc<VSA, VSB>::add_vertex(double x, double y) + { + gpc_vertex v; + v.x = x; + v.y = y; + m_vertex_accumulator.add(v); + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::end_contour(unsigned orientation) + { + if(m_contour_accumulator.size()) + { + if(m_vertex_accumulator.size() > 2) + { + contour_header_type& h = + m_contour_accumulator[m_contour_accumulator.size() - 1]; + + h.num_vertices = m_vertex_accumulator.size(); + h.hole_flag = 0; + + // TO DO: Clarify the "holes" + //if(is_cw(orientation)) h.hole_flag = 1; + + h.vertices = new gpc_vertex [h.num_vertices]; + gpc_vertex* d = h.vertices; + int i; + for(i = 0; i < h.num_vertices; i++) + { + const gpc_vertex& s = m_vertex_accumulator[i]; + d->x = s.x; + d->y = s.y; + ++d; + } + } + else + { + m_vertex_accumulator.remove_last(); + } + } + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p) + { + free_polygon(p); + if(m_contour_accumulator.size()) + { + p.num_contours = m_contour_accumulator.size(); + + // TO DO: Clarify the "holes" + //p.hole = new int[p.num_contours]; + p.hole = 0; + + p.contour = new gpc_vertex_list[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; + } + } + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::start_extracting() + { + m_status = status_move_to; + m_contour = -1; + m_vertex = -1; + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + bool conv_gpc<VSA, VSB>::next_contour() + { + if(++m_contour < m_result.num_contours) + { + m_vertex = -1; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + inline bool conv_gpc<VSA, VSB>::next_vertex(double* x, double* y) + { + const gpc_vertex_list& vlist = m_result.contour[m_contour]; + if(++m_vertex < vlist.num_vertices) + { + const gpc_vertex& v = vlist.vertex[m_vertex]; + *x = v.x; + *y = v.y; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::rewind(unsigned id) + { + free_result(); + m_src_a->rewind(id); + m_src_b->rewind(id); + add(*m_src_a, m_poly_a); + add(*m_src_b, m_poly_b); + switch(m_operation) + { + case gpc_or: + gpc_polygon_clip(GPC_UNION, + &m_poly_a, + &m_poly_b, + &m_result); + break; + + case gpc_and: + gpc_polygon_clip(GPC_INT, + &m_poly_a, + &m_poly_b, + &m_result); + break; + + case gpc_xor: + gpc_polygon_clip(GPC_XOR, + &m_poly_a, + &m_poly_b, + &m_result); + break; + + case gpc_a_minus_b: + gpc_polygon_clip(GPC_DIFF, + &m_poly_a, + &m_poly_b, + &m_result); + break; + + case gpc_b_minus_a: + gpc_polygon_clip(GPC_DIFF, + &m_poly_b, + &m_poly_a, + &m_result); + break; + } + start_extracting(); + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + unsigned conv_gpc<VSA, VSB>::vertex(double* x, double* y) + { + if(m_status == status_move_to) + { + if(next_contour()) + { + if(next_vertex(x, y)) + { + m_status = status_line_to; + return path_cmd_move_to; + } + m_status = status_stop; + return path_cmd_end_poly | path_flags_close; + } + } + else + { + if(next_vertex(x, y)) + { + return path_cmd_line_to; + } + else + { + m_status = status_move_to; + } + return path_cmd_end_poly | path_flags_close; + } + return path_cmd_stop; + } + + +} + + +#endif diff --git a/agg/inc/agg_conv_marker.h b/agg/inc/agg_conv_marker.h new file mode 100755 index 000000000000..1ae7fc92307b --- /dev/null +++ b/agg/inc/agg_conv_marker.h @@ -0,0 +1,154 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// conv_marker +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_MARKER_INCLUDED +#define AGG_CONV_MARKER_INCLUDED + +#include "agg_basics.h" +#include "agg_trans_affine.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + //-------------------------------------------------------------conv_marker + template<class MarkerLocator, class MarkerShapes> + class conv_marker + { + public: + conv_marker(MarkerLocator& ml, MarkerShapes& ms); + + trans_affine& transform() { return m_transform; } + const trans_affine& transform() const { return m_transform; } + + void rewind(unsigned 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>& + operator = (const conv_marker<MarkerLocator, MarkerShapes>&); + + enum status_e + { + initial, + markers, + polygon, + stop + }; + + MarkerLocator* m_marker_locator; + MarkerShapes* m_marker_shapes; + trans_affine m_transform; + trans_affine m_mtx; + status_e m_status; + unsigned m_marker; + unsigned m_num_markers; + }; + + + //------------------------------------------------------------------------ + template<class MarkerLocator, class MarkerShapes> + conv_marker<MarkerLocator, MarkerShapes>::conv_marker(MarkerLocator& ml, MarkerShapes& ms) : + m_marker_locator(&ml), + m_marker_shapes(&ms), + m_status(initial), + m_marker(0), + m_num_markers(1) + { + } + + + //------------------------------------------------------------------------ + template<class MarkerLocator, class MarkerShapes> + void conv_marker<MarkerLocator, MarkerShapes>::rewind(unsigned) + { + m_status = initial; + m_marker = 0; + m_num_markers = 1; + } + + + //------------------------------------------------------------------------ + template<class MarkerLocator, class MarkerShapes> + unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_move_to; + double x1, y1, x2, y2; + + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + if(m_num_markers == 0) + { + cmd = path_cmd_stop; + break; + } + m_marker_locator->rewind(m_marker); + ++m_marker; + m_num_markers = 0; + m_status = markers; + + case markers: + if(is_stop(m_marker_locator->vertex(&x1, &y1))) + { + m_status = initial; + break; + } + if(is_stop(m_marker_locator->vertex(&x2, &y2))) + { + m_status = initial; + break; + } + ++m_num_markers; + m_mtx = m_transform; + m_mtx *= trans_affine_rotation(atan2(y2 - y1, x2 - x1)); + m_mtx *= trans_affine_translation(x1, y1); + m_marker_shapes->rewind(m_marker - 1); + m_status = polygon; + + case polygon: + cmd = m_marker_shapes->vertex(x, y); + if(is_stop(cmd)) + { + cmd = path_cmd_move_to; + m_status = markers; + break; + } + m_mtx.transform(x, y); + return cmd; + + case stop: + cmd = path_cmd_stop; + break; + } + } + return cmd; + } + +} + + +#endif + diff --git a/agg/inc/agg_conv_marker_adaptor.h b/agg/inc/agg_conv_marker_adaptor.h new file mode 100755 index 000000000000..282d26eb5afc --- /dev/null +++ b/agg/inc/agg_conv_marker_adaptor.h @@ -0,0 +1,51 @@ +//---------------------------------------------------------------------------- +// 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_CONV_MARKER_ADAPTOR_INCLUDED +#define AGG_CONV_MARKER_ADAPTOR_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vcgen.h" +#include "agg_vcgen_vertex_sequence.h" + +namespace agg +{ + + //=====================================================conv_marker_adaptor + template<class VertexSource, class Markers=null_markers> + struct conv_marker_adaptor : + public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers> + { + typedef Markers marker_type; + typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers> base_type; + + conv_marker_adaptor(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>(vs) + { + } + + void shorten(double s) { base_type::generator().shorten(s); } + double shorten() const { return base_type::generator().shorten(); } + + private: + conv_marker_adaptor(const conv_marker_adaptor<VertexSource, Markers>&); + const conv_marker_adaptor<VertexSource, Markers>& + operator = (const conv_marker_adaptor<VertexSource, Markers>&); + }; + + +} + +#endif diff --git a/agg/inc/agg_conv_segmentator.h b/agg/inc/agg_conv_segmentator.h new file mode 100755 index 000000000000..df81fea9b276 --- /dev/null +++ b/agg/inc/agg_conv_segmentator.h @@ -0,0 +1,48 @@ +//---------------------------------------------------------------------------- +// 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_CONV_SEGMENTATOR_INCLUDED +#define AGG_CONV_SEGMENTATOR_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vpgen.h" +#include "agg_vpgen_segmentator.h" + +namespace agg +{ + + //========================================================conv_segmentator + template<class VertexSource> + struct conv_segmentator : public conv_adaptor_vpgen<VertexSource, vpgen_segmentator> + { + typedef conv_adaptor_vpgen<VertexSource, vpgen_segmentator> base_type; + + conv_segmentator(VertexSource& vs) : + conv_adaptor_vpgen<VertexSource, vpgen_segmentator>(vs) {} + + void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); } + double approximation_scale() const { return base_type::vpgen().approximation_scale(); } + + private: + conv_segmentator(const conv_segmentator<VertexSource>&); + const conv_segmentator<VertexSource>& + operator = (const conv_segmentator<VertexSource>&); + }; + + +} + +#endif + diff --git a/agg/inc/agg_conv_shorten_path.h b/agg/inc/agg_conv_shorten_path.h new file mode 100755 index 000000000000..07bc9357d6ca --- /dev/null +++ b/agg/inc/agg_conv_shorten_path.h @@ -0,0 +1,50 @@ +//---------------------------------------------------------------------------- +// 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_CONV_SHORTEN_PATH_INCLUDED +#define AGG_CONV_SHORTEN_PATH_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vcgen.h" +#include "agg_vcgen_vertex_sequence.h" + +namespace agg +{ + + //=======================================================conv_shorten_path + template<class VertexSource> class conv_shorten_path : + public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> + { + public: + typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> base_type; + + conv_shorten_path(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>(vs) + { + } + + void shorten(double s) { base_type::generator().shorten(s); } + double shorten() const { return base_type::generator().shorten(); } + + private: + conv_shorten_path(const conv_shorten_path<VertexSource>&); + const conv_shorten_path<VertexSource>& + operator = (const conv_shorten_path<VertexSource>&); + }; + + +} + +#endif diff --git a/agg/inc/agg_conv_smooth_poly1.h b/agg/inc/agg_conv_smooth_poly1.h new file mode 100755 index 000000000000..f50a48747f9a --- /dev/null +++ b/agg/inc/agg_conv_smooth_poly1.h @@ -0,0 +1,80 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Smooth polygon generator +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_SMOOTH_POLY1_INCLUDED +#define AGG_CONV_SMOOTH_POLY1_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_smooth_poly1.h" +#include "agg_conv_adaptor_vcgen.h" +#include "agg_conv_curve.h" + + +namespace agg +{ + + //-------------------------------------------------------conv_smooth_poly1 + template<class VertexSource> + struct conv_smooth_poly1 : + public conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1> + { + typedef conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1> base_type; + + conv_smooth_poly1(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>(vs) + { + } + + void smooth_value(double v) { base_type::generator().smooth_value(v); } + double smooth_value() const { return base_type::generator().smooth_value(); } + + private: + conv_smooth_poly1(const conv_smooth_poly1<VertexSource>&); + const conv_smooth_poly1<VertexSource>& + operator = (const conv_smooth_poly1<VertexSource>&); + }; + + + + //-------------------------------------------------conv_smooth_poly1_curve + template<class VertexSource> + struct conv_smooth_poly1_curve : + public conv_curve<conv_smooth_poly1<VertexSource> > + { + conv_smooth_poly1_curve(VertexSource& vs) : + conv_curve<conv_smooth_poly1<VertexSource> >(m_smooth), + m_smooth(vs) + { + } + + void smooth_value(double v) { m_smooth.generator().smooth_value(v); } + double smooth_value() const { return m_smooth.generator().smooth_value(); } + + private: + conv_smooth_poly1_curve(const conv_smooth_poly1_curve<VertexSource>&); + const conv_smooth_poly1_curve<VertexSource>& + operator = (const conv_smooth_poly1_curve<VertexSource>&); + + conv_smooth_poly1<VertexSource> m_smooth; + }; + +} + + +#endif + diff --git a/agg/inc/agg_conv_stroke.h b/agg/inc/agg_conv_stroke.h new file mode 100755 index 000000000000..cbdce446b7be --- /dev/null +++ b/agg/inc/agg_conv_stroke.h @@ -0,0 +1,73 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// conv_stroke +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_STROKE_INCLUDED +#define AGG_CONV_STROKE_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_stroke.h" +#include "agg_conv_adaptor_vcgen.h" + +namespace agg +{ + + //-------------------------------------------------------------conv_stroke + template<class VertexSource, class Markers=null_markers> + struct conv_stroke : + public conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers> + { + typedef Markers marker_type; + typedef conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers> base_type; + + conv_stroke(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs) + { + } + + 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); } + + 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(); } + + 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); } + void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); } + void approximation_scale(double as) { base_type::generator().approximation_scale(as); } + + 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(); } + double approximation_scale() const { return base_type::generator().approximation_scale(); } + + void shorten(double s) { base_type::generator().shorten(s); } + double shorten() const { return base_type::generator().shorten(); } + + private: + conv_stroke(const conv_stroke<VertexSource, Markers>&); + const conv_stroke<VertexSource, Markers>& + operator = (const conv_stroke<VertexSource, Markers>&); + + }; + +} + +#endif diff --git a/agg/inc/agg_conv_transform.h b/agg/inc/agg_conv_transform.h new file mode 100755 index 000000000000..fb2dddcef617 --- /dev/null +++ b/agg/inc/agg_conv_transform.h @@ -0,0 +1,75 @@ +//---------------------------------------------------------------------------- +// 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 conv_transform +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_TRANSFORM_INCLUDED +#define AGG_CONV_TRANSFORM_INCLUDED + +#include "agg_basics.h" +#include "agg_trans_affine.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + + //----------------------------------------------------------conv_transform + template<class VertexSource, class Transformer=trans_affine> class conv_transform + { + public: + conv_transform(VertexSource& source, const Transformer& tr) : + m_source(&source), m_trans(&tr) {} + + void set_source(VertexSource& source) { m_source = &source; } + + void rewind(unsigned id) + { + m_source->rewind(id); + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd = m_source->vertex(x, y); + if(is_vertex(cmd)) + { + m_trans->transform(x, y); + } + return cmd; + } + + void transformer(const Transformer& tr) + { + 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>& + operator = (const conv_transform<VertexSource>&); + + VertexSource* m_source; + const Transformer* m_trans; + }; + + +} + +#endif diff --git a/agg/inc/agg_conv_unclose_polygon.h b/agg/inc/agg_conv_unclose_polygon.h new file mode 100755 index 000000000000..a6ba30a1119e --- /dev/null +++ b/agg/inc/agg_conv_unclose_polygon.h @@ -0,0 +1,59 @@ +//---------------------------------------------------------------------------- +// 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_CONV_UNCLOSE_POLYGON_INCLUDED +#define AGG_CONV_UNCLOSE_POLYGON_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + //====================================================conv_unclose_polygon + template<class VertexSource> class conv_unclose_polygon + { + public: + conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {} + + void set_source(VertexSource& source) { m_source = &source; } + + void rewind(unsigned path_id) + { + m_source->rewind(path_id); + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd = m_source->vertex(x, y); + if(is_end_poly(cmd)) cmd &= ~path_flags_close; + 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>& + operator = (const conv_unclose_polygon<VertexSource>&); + + VertexSource* m_source; + }; + +} + +#endif diff --git a/agg/inc/agg_curves.h b/agg/inc/agg_curves.h new file mode 100755 index 000000000000..bfb02e91ab96 --- /dev/null +++ b/agg/inc/agg_curves.h @@ -0,0 +1,150 @@ +//---------------------------------------------------------------------------- +// 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 curve3 and curve4 +// +//---------------------------------------------------------------------------- + +#ifndef AGG_CURVES_INCLUDED +#define AGG_CURVES_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + + // See Implemantation agg_curves.cpp + + + //------------------------------------------------------------------curve3 + class curve3 + { + public: + curve3() : + 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) + { + init(x1, y1, x2, y2, x3, y3); + } + + void reset() { m_num_steps = 0; m_step = -1; } + 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); + + 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); } + + private: + int m_num_steps; + int m_step; + double m_scale; + double m_start_x; + double m_start_y; + double m_end_x; + double m_end_y; + double m_fx; + double m_fy; + double m_dfx; + double m_dfy; + double m_ddfx; + double m_ddfy; + double m_saved_fx; + double m_saved_fy; + double m_saved_dfx; + double m_saved_dfy; + }; + + + + + + + + //-----------------------------------------------------------------curve4 + class curve4 + { + public: + curve4() : + 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) + { + init(x1, y1, x2, y2, x3, y3, x4, y4); + } + + 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 rewind(unsigned id); + unsigned vertex(double* x, double* y); + + 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); } + + private: + int m_num_steps; + int m_step; + double m_scale; + double m_start_x; + double m_start_y; + double m_end_x; + double m_end_y; + double m_fx; + double m_fy; + double m_dfx; + double m_dfy; + double m_ddfx; + double m_ddfy; + double m_dddfx; + double m_dddfy; + double m_saved_fx; + double m_saved_fy; + double m_saved_dfx; + double m_saved_dfy; + double m_saved_ddfx; + double m_saved_ddfy; + }; + + + + +} + +#endif diff --git a/agg/inc/agg_dda_line.h b/agg/inc/agg_dda_line.h new file mode 100755 index 000000000000..6e7335c6dfec --- /dev/null +++ b/agg/inc/agg_dda_line.h @@ -0,0 +1,290 @@ +//---------------------------------------------------------------------------- +// 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 dda_line_interpolator, dda2_line_interpolator +// +//---------------------------------------------------------------------------- + +#ifndef AGG_DDA_LINE_INCLUDED +#define AGG_DDA_LINE_INCLUDED + +#include <stdlib.h> +#include "agg_basics.h" + +namespace agg +{ + + //===================================================dda_line_interpolator + template<int FractionShift, int YShift=0> class dda_line_interpolator + { + public: + //-------------------------------------------------------------------- + dda_line_interpolator() {} + + //-------------------------------------------------------------------- + dda_line_interpolator(int y1, int y2, unsigned count) : + m_y(y1), + m_inc(((y2 - y1) << FractionShift) / int(count)), + m_dy(0) + { + } + + //-------------------------------------------------------------------- + void operator ++ () + { + m_dy += m_inc; + } + + //-------------------------------------------------------------------- + void operator -- () + { + m_dy -= m_inc; + } + + //-------------------------------------------------------------------- + void operator += (unsigned n) + { + m_dy += m_inc * n; + } + + //-------------------------------------------------------------------- + void operator -= (unsigned n) + { + m_dy -= m_inc * n; + } + + + //-------------------------------------------------------------------- + int y() const { return m_y + (m_dy >> (FractionShift-YShift)); } + int dy() const { return m_dy; } + + + private: + int m_y; + int m_inc; + int m_dy; + }; + + + + + + //=================================================dda2_line_interpolator + class dda2_line_interpolator + { + public: + typedef int save_data_type; + enum { save_size = 2 }; + + //-------------------------------------------------------------------- + dda2_line_interpolator() {} + + //-------------------------------------------- Forward-adjusted line + dda2_line_interpolator(int y1, int y2, int count) : + m_cnt(count <= 0 ? 1 : count), + m_lft((y2 - y1) / m_cnt), + m_rem((y2 - y1) % m_cnt), + m_mod(m_rem), + m_y(y1) + { + if(m_mod <= 0) + { + m_mod += count; + m_rem += count; + m_lft--; + } + m_mod -= count; + } + + //-------------------------------------------- Backward-adjusted line + dda2_line_interpolator(int y1, int y2, int count, int) : + m_cnt(count <= 0 ? 1 : count), + m_lft((y2 - y1) / m_cnt), + m_rem((y2 - y1) % m_cnt), + m_mod(m_rem), + m_y(y1) + { + if(m_mod <= 0) + { + m_mod += count; + m_rem += count; + m_lft--; + } + } + + //-------------------------------------------- Backward-adjusted line + dda2_line_interpolator(int _y, int count) : + m_cnt(count <= 0 ? 1 : count), + m_lft(_y / m_cnt), + m_rem(_y % m_cnt), + m_mod(m_rem), + m_y(0) + { + if(m_mod <= 0) + { + m_mod += count; + m_rem += count; + m_lft--; + } + } + + + //-------------------------------------------------------------------- + void save(save_data_type* data) const + { + data[0] = m_mod; + data[1] = m_y; + } + + //-------------------------------------------------------------------- + void load(const save_data_type* data) + { + m_mod = data[0]; + m_y = data[1]; + } + + //-------------------------------------------------------------------- + void operator++() + { + m_mod += m_rem; + m_y += m_lft; + if(m_mod > 0) + { + m_mod -= m_cnt; + m_y++; + } + } + + //-------------------------------------------------------------------- + void operator--() + { + if(m_mod <= m_rem) + { + m_mod += m_cnt; + m_y--; + } + m_mod -= m_rem; + m_y -= m_lft; + } + + //-------------------------------------------------------------------- + void adjust_forward() + { + m_mod -= m_cnt; + } + + //-------------------------------------------------------------------- + void adjust_backward() + { + m_mod += m_cnt; + } + + //-------------------------------------------------------------------- + int mod() const { return m_mod; } + int rem() const { return m_rem; } + int lft() const { return m_lft; } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + + private: + int m_cnt; + int m_lft; + int m_rem; + int m_mod; + int m_y; + }; + + + + + + + + //---------------------------------------------line_bresenham_interpolator + class line_bresenham_interpolator + { + public: + enum + { + subpixel_shift = 8, + subpixel_size = 1 << subpixel_shift, + subpixel_mask = subpixel_size - 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)), + 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_len) + { + } + + //-------------------------------------------------------------------- + bool is_ver() const { return m_ver; } + unsigned len() const { return m_len; } + int inc() const { return m_inc; } + + //-------------------------------------------------------------------- + void hstep() + { + ++m_interpolator; + m_x1_lr += m_inc; + } + + //-------------------------------------------------------------------- + void vstep() + { + ++m_interpolator; + m_y1_lr += m_inc; + } + + //-------------------------------------------------------------------- + int x1() const { return m_x1_lr; } + int y1() const { return m_y1_lr; } + int x2() const { return line_lr(m_interpolator.y()); } + int y2() const { return line_lr(m_interpolator.y()); } + int x2_hr() const { return m_interpolator.y(); } + int y2_hr() const { return m_interpolator.y(); } + + private: + int m_x1_lr; + int m_y1_lr; + int m_x2_lr; + int m_y2_lr; + bool m_ver; + unsigned m_len; + int m_inc; + dda2_line_interpolator m_interpolator; + + }; + + +} + + + +#endif diff --git a/agg/inc/agg_ellipse.h b/agg/inc/agg_ellipse.h new file mode 100755 index 000000000000..158ecf8b55ed --- /dev/null +++ b/agg/inc/agg_ellipse.h @@ -0,0 +1,98 @@ +//---------------------------------------------------------------------------- +// 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 ellipse +// +//---------------------------------------------------------------------------- + +#ifndef AGG_ELLIPSE_INCLUDED +#define AGG_ELLIPSE_INCLUDED + +#include "agg_basics.h" +#include <math.h> + +namespace agg +{ + + //----------------------------------------------------------------ellipse + 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) {} + + void init(double x, double y, double rx, double ry, unsigned num_steps); + void approximation_scale(double scale); + void rewind(unsigned id); + unsigned vertex(double* x, double* y); + + private: + double m_x; + double m_y; + double m_rx; + double m_ry; + unsigned m_num; + unsigned m_step; + }; + + + //------------------------------------------------------------------------ + inline void ellipse::init(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; + } + + //------------------------------------------------------------------------ + 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; + } + + //------------------------------------------------------------------------ + inline void ellipse::rewind(unsigned) + { + m_step = 0; + } + + //------------------------------------------------------------------------ + inline unsigned ellipse::vertex(double* x, double* y) + { + if(m_step == m_num) + { + ++m_step; + return path_cmd_end_poly | path_flags_close | path_flags_ccw; + } + if(m_step > m_num) return path_cmd_stop; + double angle = double(m_step) / double(m_num) * 2.0 * pi; + *x = m_x + cos(angle) * m_rx; + *y = m_y + sin(angle) * m_ry; + m_step++; + return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to); + } + +} + + + +#endif + + diff --git a/agg/inc/agg_ellipse_bresenham.h b/agg/inc/agg_ellipse_bresenham.h new file mode 100755 index 000000000000..41133a473d9e --- /dev/null +++ b/agg/inc/agg_ellipse_bresenham.h @@ -0,0 +1,113 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Simple Bresenham interpolator for ellipsees +// +//---------------------------------------------------------------------------- + +#ifndef AGG_ELLIPSE_BRESENHAM_INCLUDED +#define AGG_ELLIPSE_BRESENHAM_INCLUDED + + +#include "agg_basics.h" + + +namespace agg +{ + + //------------------------------------------ellipse_bresenham_interpolator + class ellipse_bresenham_interpolator + { + public: + ellipse_bresenham_interpolator(int rx, int ry) : + m_rx2(rx * rx), + m_ry2(ry * ry), + m_two_rx2(m_rx2 << 1), + m_two_ry2(m_ry2 << 1), + m_dx(0), + m_dy(0), + m_inc_x(0), + m_inc_y(-ry * m_two_rx2), + m_cur_f(0) + {} + + int dx() const { return m_dx; } + int dy() const { return m_dy; } + + void operator++ () + { + int mx, my, mxy, min_m; + int fx, fy, fxy; + + mx = fx = m_cur_f + m_inc_x + m_ry2; + if(mx < 0) mx = -mx; + + my = fy = m_cur_f + m_inc_y + m_rx2; + if(my < 0) my = -my; + + mxy = fxy = m_cur_f + m_inc_x + m_ry2 + m_inc_y + m_rx2; + if(mxy < 0) mxy = -mxy; + + min_m = mx; + bool flag = true; + + if(min_m > my) + { + min_m = my; + flag = false; + } + + m_dx = m_dy = 0; + + if(min_m > mxy) + { + m_inc_x += m_two_ry2; + m_inc_y += m_two_rx2; + m_cur_f = fxy; + m_dx = 1; + m_dy = 1; + return; + } + + if(flag) + { + m_inc_x += m_two_ry2; + m_cur_f = fx; + m_dx = 1; + return; + } + + m_inc_y += m_two_rx2; + m_cur_f = fy; + m_dy = 1; + } + + private: + int m_rx2; + int m_ry2; + int m_two_rx2; + int m_two_ry2; + int m_dx; + int m_dy; + int m_inc_x; + int m_inc_y; + int m_cur_f; + + }; + +} + +#endif + diff --git a/agg/inc/agg_embedded_raster_fonts.h b/agg/inc/agg_embedded_raster_fonts.h new file mode 100755 index 000000000000..f30fedfebe39 --- /dev/null +++ b/agg/inc/agg_embedded_raster_fonts.h @@ -0,0 +1,59 @@ +//---------------------------------------------------------------------------- +// 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_EMBEDDED_RASTER_FONTS_INCLUDED +#define AGG_EMBEDDED_RASTER_FONTS_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + extern const int8u gse4x6[]; + extern const int8u gse4x8[]; + extern const int8u gse5x7[]; + extern const int8u gse5x9[]; + extern const int8u gse6x12[]; + extern const int8u gse6x9[]; + extern const int8u gse7x11[]; + extern const int8u gse7x11_bold[]; + extern const int8u gse7x15[]; + extern const int8u gse7x15_bold[]; + extern const int8u gse8x16[]; + extern const int8u gse8x16_bold[]; + extern const int8u mcs11_prop[]; + extern const int8u mcs11_prop_condensed[]; + extern const int8u mcs12_prop[]; + extern const int8u mcs13_prop[]; + extern const int8u mcs5x10_mono[]; + extern const int8u mcs5x11_mono[]; + extern const int8u mcs6x10_mono[]; + extern const int8u mcs6x11_mono[]; + extern const int8u mcs7x12_mono_high[]; + extern const int8u mcs7x12_mono_low[]; + extern const int8u verdana12[]; + extern const int8u verdana12_bold[]; + extern const int8u verdana13[]; + extern const int8u verdana13_bold[]; + extern const int8u verdana14[]; + extern const int8u verdana14_bold[]; + extern const int8u verdana16[]; + extern const int8u verdana16_bold[]; + extern const int8u verdana17[]; + extern const int8u verdana17_bold[]; + extern const int8u verdana18[]; + extern const int8u verdana18_bold[]; +} + +#endif diff --git a/agg/inc/agg_font_cache_manager.h b/agg/inc/agg_font_cache_manager.h new file mode 100755 index 000000000000..55c4d39db75d --- /dev/null +++ b/agg/inc/agg_font_cache_manager.h @@ -0,0 +1,397 @@ +//---------------------------------------------------------------------------- +// 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_FONT_CACHE_MANAGER_INCLUDED +#define AGG_FONT_CACHE_MANAGER_INCLUDED + +#include <string.h> +#include "agg_array.h" + +namespace agg +{ + + //---------------------------------------------------------glyph_data_type + enum glyph_data_type + { + glyph_data_invalid = 0, + glyph_data_mono = 1, + glyph_data_gray8 = 2, + glyph_data_outline = 3 + }; + + + //-------------------------------------------------------------glyph_cache + struct glyph_cache + { + unsigned glyph_index; + int8u* data; + unsigned data_size; + glyph_data_type data_type; + rect bounds; + double advance_x; + double advance_y; + }; + + + //--------------------------------------------------------------font_cache + class font_cache + { + public: + enum { block_size = 16384-16 }; + + //-------------------------------------------------------------------- + font_cache(const char* font_signature) : + m_allocator(block_size), + m_font_signature(0) + { + m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1); + strcpy(m_font_signature, font_signature); + memset(m_glyphs, 0, sizeof(m_glyphs)); + } + + //-------------------------------------------------------------------- + bool font_is(const char* font_signature) const + { + return strcmp(font_signature, m_font_signature) == 0; + } + + //-------------------------------------------------------------------- + const glyph_cache* find_glyph(unsigned glyph_code) const + { + unsigned msb = (glyph_code >> 8) & 0xFF; + if(m_glyphs[msb]) + { + return m_glyphs[msb][glyph_code & 0xFF]; + } + return 0; + } + + //-------------------------------------------------------------------- + glyph_cache* cache_glyph(unsigned glyph_code, + unsigned glyph_index, + unsigned data_size, + glyph_data_type data_type, + const rect& bounds, + double advance_x, + double advance_y) + { + unsigned msb = (glyph_code >> 8) & 0xFF; + if(m_glyphs[msb] == 0) + { + m_glyphs[msb] = + (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256, + sizeof(glyph_cache*)); + memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256); + } + + unsigned lsb = glyph_code & 0xFF; + if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite + + glyph_cache* glyph = + (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; + return m_glyphs[msb][lsb] = glyph; + } + + private: + pod_allocator m_allocator; + glyph_cache** m_glyphs[256]; + char* m_font_signature; + }; + + + + + + + + //---------------------------------------------------------font_cache_pool + class font_cache_pool + { + public: + //-------------------------------------------------------------------- + ~font_cache_pool() + { + unsigned i; + for(i = 0; i < m_num_fonts; ++i) + { + delete m_fonts[i]; + } + delete [] m_fonts; + } + + //-------------------------------------------------------------------- + font_cache_pool(unsigned max_fonts=32) : + m_fonts(new font_cache* [max_fonts]), + m_max_fonts(max_fonts), + m_num_fonts(0), + m_cur_font(0) + {} + + + //-------------------------------------------------------------------- + void font(const char* font_signature, bool reset_cache = false) + { + int idx = find_font(font_signature); + if(idx >= 0) + { + if(reset_cache) + { + delete m_fonts[idx]; + m_fonts[idx] = new font_cache(font_signature); + } + m_cur_font = m_fonts[idx]; + } + else + { + if(m_num_fonts >= m_max_fonts) + { + delete 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_cur_font = m_fonts[m_num_fonts]; + ++m_num_fonts; + } + } + + //-------------------------------------------------------------------- + const font_cache* font() const + { + return m_cur_font; + } + + //-------------------------------------------------------------------- + const glyph_cache* find_glyph(unsigned glyph_code) const + { + if(m_cur_font) return m_cur_font->find_glyph(glyph_code); + return 0; + } + + //-------------------------------------------------------------------- + glyph_cache* cache_glyph(unsigned glyph_code, + unsigned glyph_index, + unsigned data_size, + glyph_data_type data_type, + const rect& bounds, + double advance_x, + double advance_y) + { + if(m_cur_font) + { + return m_cur_font->cache_glyph(glyph_code, + glyph_index, + data_size, + data_type, + bounds, + advance_x, + advance_y); + } + return 0; + } + + + //-------------------------------------------------------------------- + int find_font(const char* font_signature) + { + unsigned i; + for(i = 0; i < m_num_fonts; i++) + { + if(m_fonts[i]->font_is(font_signature)) return int(i); + } + return -1; + } + + private: + font_cache** m_fonts; + unsigned m_max_fonts; + unsigned m_num_fonts; + font_cache* m_cur_font; + }; + + + + + //------------------------------------------------------------------------ + enum glyph_rendering + { + glyph_ren_native_mono, + glyph_ren_native_gray8, + glyph_ren_outline, + glyph_ren_agg_mono, + glyph_ren_agg_gray8 + }; + + + + + //------------------------------------------------------font_cache_manager + template<class FontEngine> class font_cache_manager + { + public: + typedef FontEngine font_engine_type; + typedef font_cache_manager<FontEngine> self_type; + typedef typename font_engine_type::path_adaptor_type path_adaptor_type; + typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type; + typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type; + typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type; + typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type; + + //-------------------------------------------------------------------- + font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) : + m_fonts(max_fonts), + m_engine(engine), + m_change_stamp(-1), + m_prev_glyph(0), + m_last_glyph(0) + {} + + //-------------------------------------------------------------------- + const glyph_cache* glyph(unsigned glyph_code) + { + synchronize(); + const glyph_cache* gl = m_fonts.find_glyph(glyph_code); + if(gl) + { + m_prev_glyph = m_last_glyph; + return m_last_glyph = gl; + } + else + { + if(m_engine.prepare_glyph(glyph_code)) + { + m_prev_glyph = m_last_glyph; + m_last_glyph = m_fonts.cache_glyph(glyph_code, + m_engine.glyph_index(), + m_engine.data_size(), + m_engine.data_type(), + m_engine.bounds(), + m_engine.advance_x(), + m_engine.advance_y()); + m_engine.write_glyph_to(m_last_glyph->data); + return m_last_glyph; + } + } + return 0; + } + + //-------------------------------------------------------------------- + void init_embedded_adaptors(const glyph_cache* gl, + double x, double y, + double scale=1.0) + { + if(gl) + { + switch(gl->data_type) + { + default: return; + case glyph_data_mono: + m_mono_adaptor.init(gl->data, gl->data_size, x, y); + break; + + case glyph_data_gray8: + m_gray8_adaptor.init(gl->data, gl->data_size, x, y); + break; + + case glyph_data_outline: + m_path_adaptor.init(gl->data, gl->data_size, x, y, scale); + break; + } + } + } + + + //-------------------------------------------------------------------- + path_adaptor_type& path_adaptor() { return m_path_adaptor; } + gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; } + gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; } + mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; } + mono_scanline_type& mono_scanline() { return m_mono_scanline; } + + //-------------------------------------------------------------------- + const glyph_cache* perv_glyph() const { return m_prev_glyph; } + const glyph_cache* last_glyph() const { return m_last_glyph; } + + //-------------------------------------------------------------------- + bool add_kerning(double* x, double* y) + { + if(m_prev_glyph && m_last_glyph) + { + return m_engine.add_kerning(m_prev_glyph->glyph_index, + m_last_glyph->glyph_index, + x, y); + } + return false; + } + + //-------------------------------------------------------------------- + void precache(unsigned from, unsigned to) + { + for(; from <= to; ++from) glyph(from); + } + + //-------------------------------------------------------------------- + void reset_cache() + { + m_fonts.font(m_engine.font_signature(), true); + m_change_stamp = m_engine.change_stamp(); + m_prev_glyph = m_last_glyph = 0; + } + + private: + //-------------------------------------------------------------------- + font_cache_manager(const self_type&); + const self_type& operator = (const self_type&); + + //-------------------------------------------------------------------- + void synchronize() + { + if(m_change_stamp != m_engine.change_stamp()) + { + m_fonts.font(m_engine.font_signature()); + m_change_stamp = m_engine.change_stamp(); + m_prev_glyph = m_last_glyph = 0; + } + } + + font_cache_pool m_fonts; + font_engine_type& m_engine; + int m_change_stamp; + double m_dx; + double m_dy; + const glyph_cache* m_prev_glyph; + const glyph_cache* m_last_glyph; + path_adaptor_type m_path_adaptor; + gray8_adaptor_type m_gray8_adaptor; + gray8_scanline_type m_gray8_scanline; + mono_adaptor_type m_mono_adaptor; + mono_scanline_type m_mono_scanline; + }; + +} + +#endif + diff --git a/agg/inc/agg_gamma_functions.h b/agg/inc/agg_gamma_functions.h new file mode 100755 index 000000000000..09a8305faedb --- /dev/null +++ b/agg/inc/agg_gamma_functions.h @@ -0,0 +1,123 @@ +//---------------------------------------------------------------------------- +// 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_GAMMA_FUNCTIONS_INCLUDED +#define AGG_GAMMA_FUNCTIONS_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + //===============================================================gamma_none + struct gamma_none + { + double operator()(double x) const { return x; } + }; + + + //==============================================================gamma_power + class gamma_power + { + public: + gamma_power() : m_gamma(1.0) {} + gamma_power(double g) : m_gamma(g) {} + + void gamma(double g) { m_gamma = g; } + double gamma() const { return m_gamma; } + + double operator() (double x) const + { + return pow(x, m_gamma); + } + + private: + double m_gamma; + }; + + + //==========================================================gamma_threshold + class gamma_threshold + { + public: + gamma_threshold() : m_threshold(0.5) {} + gamma_threshold(double t) : m_threshold(t) {} + + void threshold(double t) { m_threshold = t; } + double threshold() const { return m_threshold; } + + double operator() (double x) const + { + return (x < m_threshold) ? 0.0 : 1.0; + } + + private: + double m_threshold; + }; + + + //============================================================gamma_linear + class gamma_linear + { + public: + gamma_linear() : m_start(0.0), m_end(1.0) {} + gamma_linear(double s, double e) : m_start(s), m_end(e) {} + + void set(double s, double e) { m_start = s; m_end = e; } + void start(double s) { m_start = s; } + void end(double e) { m_end = e; } + double start() const { return m_start; } + double end() const { return m_end; } + + double operator() (double x) const + { + if(x < m_start) return 0.0; + if(x > m_end) return 1.0; + return (x - m_start) / (m_end - m_start); + } + + private: + double m_start; + double m_end; + }; + + + //==========================================================gamma_multiply + class gamma_multiply + { + public: + gamma_multiply() : m_mul(1.0) {} + gamma_multiply(double v) : m_mul(v) {} + + void value(double v) { m_mul = v; } + double value() const { return m_mul; } + + double operator() (double x) const + { + double y = x * m_mul; + if(y > 1.0) y = 1.0; + return y; + } + + private: + double m_mul; + }; + +} + +#endif + + + diff --git a/agg/inc/agg_gamma_lut.h b/agg/inc/agg_gamma_lut.h new file mode 100755 index 000000000000..30e3b3c89d04 --- /dev/null +++ b/agg/inc/agg_gamma_lut.h @@ -0,0 +1,114 @@ +//---------------------------------------------------------------------------- +// 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_GAMMA_LUT_INCLUDED +#define AGG_GAMMA_LUT_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + template<class LoResT=int8u, + class HiResT=int8u, + unsigned GammaShift=8, + unsigned HiResShift=8> class gamma_lut + { + public: + enum + { + gamma_shift = GammaShift, + gamma_size = 1 << gamma_shift, + gamma_mask = gamma_size - 1 + }; + + enum + { + hi_res_shift = HiResShift, + hi_res_size = 1 << hi_res_shift, + hi_res_mask = hi_res_size - 1 + }; + + ~gamma_lut() + { + delete [] m_inv_gamma; + delete [] m_dir_gamma; + } + + gamma_lut() : + m_gamma(1.0), + m_dir_gamma(new HiResT[gamma_size]), + m_inv_gamma(new LoResT[hi_res_size]) + { + unsigned i; + for(i = 0; i < gamma_size; i++) + { + m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift)); + } + + for(i = 0; i < hi_res_size; i++) + { + m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift)); + } + } + + gamma_lut(double g) : + m_gamma(1.0), + m_dir_gamma(new HiResT[gamma_size]), + m_inv_gamma(new LoResT[hi_res_size]) + { + gamma(g); + } + + void gamma(double g) + { + m_gamma = g; + + 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); + } + + 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); + } + } + + double gamma() const + { + return m_gamma; + } + + HiResT dir(LoResT v) const + { + return m_dir_gamma[unsigned(v)]; + } + + LoResT inv(HiResT v) const + { + return m_inv_gamma[unsigned(v)]; + } + + private: + double m_gamma; + HiResT* m_dir_gamma; + LoResT* m_inv_gamma; + }; +} + +#endif diff --git a/agg/inc/agg_glyph_raster_bin.h b/agg/inc/agg_glyph_raster_bin.h new file mode 100755 index 000000000000..851d9f94bd72 --- /dev/null +++ b/agg/inc/agg_glyph_raster_bin.h @@ -0,0 +1,155 @@ +//---------------------------------------------------------------------------- +// 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_GLYPH_RASTER_BIN_INCLUDED +#define AGG_GLYPH_RASTER_BIN_INCLUDED + +#include <string.h> +#include "agg_basics.h" + +namespace agg +{ + + //========================================================glyph_raster_bin + template<class ColorT> class glyph_raster_bin + { + public: + typedef ColorT color_type; + + //-------------------------------------------------------------------- + struct glyph_rect + { + int x1,y1,x2,y2; + double dx, dy; + }; + + //-------------------------------------------------------------------- + glyph_raster_bin(const int8u* font) : + m_font(font), + m_big_endian(false) + { + int t = 1; + if(*(char*)&t == 0) m_big_endian = true; + memset(m_span, 0, sizeof(m_span)); + } + + //-------------------------------------------------------------------- + const int8u* font() const { return m_font; } + void font(const int8u* f) { m_font = f; } + + //-------------------------------------------------------------------- + double height() const { return m_font[0]; } + double base_line() const { return m_font[1]; } + + //-------------------------------------------------------------------- + template<class CharT> + double width(const CharT* str) const + { + unsigned start_char = m_font[2]; + unsigned num_chars = m_font[3]; + + unsigned w = 0; + while(*str) + { + unsigned glyph = *str; + const int8u* bits = m_font + 4 + num_chars * 2 + + value(m_font + 4 + (glyph - start_char) * 2); + w += *bits; + ++str; + } + return w; + } + + //-------------------------------------------------------------------- + void prepare(glyph_rect* r, double x, double y, unsigned glyph, bool flip) + { + unsigned start_char = m_font[2]; + unsigned num_chars = m_font[3]; + + m_bits = m_font + 4 + num_chars * 2 + + value(m_font + 4 + (glyph - start_char) * 2); + + m_glyph_width = *m_bits++; + m_glyph_byte_width = (m_glyph_width + 7) >> 3; + + r->x1 = int(x); + r->x2 = r->x1 + m_glyph_width - 1; + if(flip) + { + r->y1 = int(y) - m_font[0] + m_font[1]; + r->y2 = r->y1 + m_font[0] - 1; + } + else + { + r->y1 = int(y) - m_font[1] + 1; + r->y2 = r->y1 + m_font[0] - 1; + } + r->dx = m_glyph_width; + r->dy = 0; + } + + //-------------------------------------------------------------------- + const cover_type* span(unsigned i) + { + i = m_font[0] - i - 1; + const int8u* bits = m_bits + i * m_glyph_byte_width; + unsigned j; + unsigned val = *bits; + unsigned nb = 0; + for(j = 0; j < m_glyph_width; ++j) + { + m_span[j] = (cover_type)((val & 0x80) ? cover_full : cover_none); + val <<= 1; + if(++nb >= 8) + { + val = *++bits; + nb = 0; + } + } + return m_span; + } + + private: + //-------------------------------------------------------------------- + int16u value(const int8u* p) const + { + int16u v; + if(m_big_endian) + { + *(int8u*)&v = p[1]; + *((int8u*)&v + 1) = p[0]; + } + else + { + *(int8u*)&v = p[0]; + *((int8u*)&v + 1) = p[1]; + } + return v; + } + + + //-------------------------------------------------------------------- + const int8u* m_font; + bool m_big_endian; + cover_type m_span[32]; + const int8u* m_bits; + unsigned m_glyph_width; + unsigned m_glyph_byte_width; + }; + + +} + +#endif diff --git a/agg/inc/agg_gsv_text.h b/agg/inc/agg_gsv_text.h new file mode 100755 index 000000000000..5d8e1cf63bab --- /dev/null +++ b/agg/inc/agg_gsv_text.h @@ -0,0 +1,154 @@ +//---------------------------------------------------------------------------- +// 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 gsv_text +// +//---------------------------------------------------------------------------- + +#ifndef AGG_GSV_TEXT_INCLUDED +#define AGG_GSV_TEXT_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_stroke.h" +#include "agg_conv_transform.h" + +namespace agg +{ + + + //---------------------------------------------------------------gsv_text + // + // See Implementation agg_gsv_text.cpp + // + class gsv_text + { + enum status + { + initial, + next_char, + start_glyph, + glyph + }; + + public: + ~gsv_text(); + gsv_text(); + + void font(const void* font); + void flip(bool flip_y) { m_flip = flip_y; } + void load_font(const char* file); + void size(double height, double width=0.0); + void space(double space); + void line_space(double line_space); + void start_point(double x, double y); + void text(const char* text); + + void rewind(unsigned id); + unsigned vertex(double* x, double* y); + + private: + // not supposed to be copied + gsv_text(const gsv_text&); + const gsv_text& operator = (const gsv_text&); + + int16u value(const int8u* p) const + { + int16u v; + if(m_big_endian) + { + *(int8u*)&v = p[1]; + *((int8u*)&v + 1) = p[0]; + } + else + { + *(int8u*)&v = p[0]; + *((int8u*)&v + 1) = p[1]; + } + return v; + } + + 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; + }; + + + + + //--------------------------------------------------------gsv_text_outline + template<class Transformer = trans_affine> class gsv_text_outline + { + public: + gsv_text_outline(gsv_text& text, const Transformer& trans) : + m_polyline(text), + m_trans(m_polyline, trans) + { + } + + void width(double w) + { + m_polyline.width(w); + } + + void transformer(const Transformer* trans) + { + m_trans->transformer(trans); + } + + void rewind(unsigned id) + { + m_trans.rewind(id); + m_polyline.line_join(round_join); + m_polyline.line_cap(round_cap); + } + + unsigned vertex(double* x, double* y) + { + return m_trans.vertex(x, y); + } + + private: + conv_stroke<gsv_text> m_polyline; + conv_transform<conv_stroke<gsv_text>, Transformer> m_trans; + }; + + + +} + + +#endif diff --git a/agg/inc/agg_image_filters.h b/agg/inc/agg_image_filters.h new file mode 100755 index 000000000000..a2037fe0eff1 --- /dev/null +++ b/agg/inc/agg_image_filters.h @@ -0,0 +1,449 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Image transformation filters, +// Filtering classes (image_filter_lut, image_filter), +// Basic filter shape classes +//---------------------------------------------------------------------------- +#ifndef AGG_IMAGE_FILTERS_INCLUDED +#define AGG_IMAGE_FILTERS_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + + // See Implementation agg_image_filters.cpp + + enum + { + 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_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_filter_lut + 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); + unsigned i; + unsigned pivot = diameter() << (image_subpixel_shift - 1); + for(i = 0; i < pivot; i++) + { + double x = double(i) / double(image_subpixel_size); + double y = filter.calc_weight(x); + m_weight_array[pivot + i] = + m_weight_array[pivot - i] = int16(y * image_filter_size + 0.5); + } + unsigned end = (diameter() << image_subpixel_shift) - 1; + m_weight_array[0] = m_weight_array[end]; + if(normalization) + { + normalize(); + } + } + + template<class FilterF> image_filter_lut(const FilterF& filter, + bool normalization=true) : + m_weight_array(0), + m_max_size(0) + { + 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; } + void normalize(); + + private: + void realloc(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; + }; + + + + //--------------------------------------------------------image_filter + template<class FilterF> class image_filter : public image_filter_lut + { + public: + image_filter() + { + calculate(m_filter_function); + } + private: + FilterF m_filter_function; + }; + + + //-----------------------------------------------image_filter_bilinear + struct image_filter_bilinear + { + static double radius() { return 1.0; } + static double calc_weight(double x) + { + return 1.0 - x; + } + }; + + + //-----------------------------------------------image_filter_hanning + struct image_filter_hanning + { + static double radius() { return 1.0; } + static double calc_weight(double x) + { + return 0.5 + 0.5 * cos(pi * x); + } + }; + + + //-----------------------------------------------image_filter_hamming + struct image_filter_hamming + { + static double radius() { return 1.0; } + static double calc_weight(double x) + { + return 0.54 + 0.46 * cos(pi * x); + } + }; + + //-----------------------------------------------image_filter_hermite + struct image_filter_hermite + { + static double radius() { return 1.0; } + static double calc_weight(double x) + { + return (2.0 * x - 3.0) * x * x + 1.0; + } + }; + + //------------------------------------------------image_filter_quadric + struct image_filter_quadric + { + static double radius() { return 1.5; } + static double calc_weight(double x) + { + double t; + if(x < 0.5) return 0.75 - x * x; + if(x < 1.5) {t = x - 1.5; return 0.5 * t * t;} + return 0.0; + } + }; + + //------------------------------------------------image_filter_bicubic + class image_filter_bicubic + { + static double pow3(double x) + { + return (x <= 0.0) ? 0.0 : x * x * x; + } + + public: + static double radius() { return 2.0; } + static double calc_weight(double x) + { + return + (1.0/6.0) * + (pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1)); + } + }; + + //-------------------------------------------------image_filter_kaiser + class image_filter_kaiser + { + double a; + double i0a; + double epsilon; + + public: + image_filter_kaiser(double b = 6.33) : + a(b), epsilon(1e-12) + { + i0a = 1.0 / bessel_i0(b); + } + + static double radius() { return 1.0; } + double calc_weight(double x) const + { + return bessel_i0(a * sqrt(1. - x * x)) * i0a; + } + + private: + double bessel_i0(double x) const + { + int i; + double sum, y, t; + + sum = 1.; + y = x * x / 4.; + t = y; + + for(i = 2; t > epsilon; i++) + { + sum += t; + t *= (double)y / (i * i); + } + return sum; + } + }; + + //----------------------------------------------image_filter_catrom + struct image_filter_catrom + { + static double radius() { return 2.0; } + static double calc_weight(double x) + { + if(x < 1.0) return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0)); + if(x < 2.0) return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x))); + return 0.; + } + }; + + //---------------------------------------------image_filter_mitchell + class image_filter_mitchell + { + double p0, p2, p3; + double q0, q1, q2, q3; + + public: + image_filter_mitchell(double b = 1.0/3.0, double c = 1.0/3.0) : + p0((6.0 - 2.0 * b) / 6.0), + p2((-18.0 + 12.0 * b + 6.0 * c) / 6.0), + p3((12.0 - 9.0 * b - 6.0 * c) / 6.0), + q0((8.0 * b + 24.0 * c) / 6.0), + q1((-12.0 * b - 48.0 * c) / 6.0), + q2((6.0 * b + 30.0 * c) / 6.0), + q3((-b - 6.0 * c) / 6.0) + {} + + static double radius() { return 2.0; } + double calc_weight(double x) const + { + if(x < 1.0) return p0 + x * x * (p2 + x * p3); + if(x < 2.0) return q0 + x * (q1 + x * (q2 + x * q3)); + return 0.0; + } + }; + + + //----------------------------------------------image_filter_spline16 + struct image_filter_spline16 + { + static double radius() { return 2.0; } + static double calc_weight(double x) + { + if(x < 1.0) + { + return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0; + } + return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1); + } + }; + + + //---------------------------------------------image_filter_spline36 + struct image_filter_spline36 + { + static double radius() { return 3.0; } + static double calc_weight(double x) + { + if(x < 1.0) + { + return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0; + } + if(x < 2.0) + { + return ((-6.0/11.0 * (x-1) + 270.0/209.0) * (x-1) - 156.0/ 209.0) * (x-1); + } + return ((1.0/11.0 * (x-2) - 45.0/209.0) * (x-2) + 26.0/209.0) * (x-2); + } + }; + + + //----------------------------------------------image_filter_gaussian + struct image_filter_gaussian + { + static double radius() { return 2.0; } + static double calc_weight(double x) + { + return exp(-2.0 * x * x) * sqrt(2.0 / pi); + } + }; + + + //------------------------------------------------image_filter_bessel + struct image_filter_bessel + { + 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); + } + }; + + + //-------------------------------------------------image_filter_sinc + class image_filter_sinc + { + public: + image_filter_sinc(double r) : m_radius(r < 2.0 ? 2.0 : r) {} + double radius() const { return m_radius; } + double calc_weight(double x) const + { + if(x == 0.0) return 1.0; + x *= pi; + return sin(x) / x; + } + private: + double m_radius; + }; + + + //-----------------------------------------------image_filter_lanczos + class image_filter_lanczos + { + public: + image_filter_lanczos(double r) : m_radius(r < 2.0 ? 2.0 : r) {} + double radius() const { return m_radius; } + double calc_weight(double x) const + { + if(x == 0.0) return 1.0; + if(x > m_radius) return 0.0; + x *= pi; + double xr = x / m_radius; + return (sin(x) / x) * (sin(xr) / xr); + } + private: + double m_radius; + }; + + + //----------------------------------------------image_filter_blackman + class image_filter_blackman + { + public: + image_filter_blackman(double r) : m_radius(r < 2.0 ? 2.0 : r) {} + double radius() const { return m_radius; } + double calc_weight(double x) const + { + if(x == 0.0) return 1.0; + if(x > m_radius) return 0.0; + x *= pi; + double xr = x / m_radius; + return (sin(x) / x) * (0.42 + 0.5*cos(xr) + 0.08*cos(2*xr)); + } + private: + double m_radius; + }; + + //------------------------------------------------image_filter_sinc36 + class image_filter_sinc36 : public image_filter_sinc + { public: image_filter_sinc36() : image_filter_sinc(3.0){} }; + + //------------------------------------------------image_filter_sinc64 + class image_filter_sinc64 : public image_filter_sinc + { public: image_filter_sinc64() : image_filter_sinc(4.0){} }; + + //-----------------------------------------------image_filter_sinc100 + class image_filter_sinc100 : public image_filter_sinc + { public: image_filter_sinc100() : image_filter_sinc(5.0){} }; + + //-----------------------------------------------image_filter_sinc144 + class image_filter_sinc144 : public image_filter_sinc + { public: image_filter_sinc144() : image_filter_sinc(6.0){} }; + + //-----------------------------------------------image_filter_sinc196 + class image_filter_sinc196 : public image_filter_sinc + { public: image_filter_sinc196() : image_filter_sinc(7.0){} }; + + //-----------------------------------------------image_filter_sinc256 + class image_filter_sinc256 : public image_filter_sinc + { public: image_filter_sinc256() : image_filter_sinc(8.0){} }; + + //---------------------------------------------image_filter_lanczos36 + class image_filter_lanczos36 : public image_filter_lanczos + { public: image_filter_lanczos36() : image_filter_lanczos(3.0){} }; + + //---------------------------------------------image_filter_lanczos64 + class image_filter_lanczos64 : public image_filter_lanczos + { public: image_filter_lanczos64() : image_filter_lanczos(4.0){} }; + + //--------------------------------------------image_filter_lanczos100 + class image_filter_lanczos100 : public image_filter_lanczos + { public: image_filter_lanczos100() : image_filter_lanczos(5.0){} }; + + //--------------------------------------------image_filter_lanczos144 + class image_filter_lanczos144 : public image_filter_lanczos + { public: image_filter_lanczos144() : image_filter_lanczos(6.0){} }; + + //--------------------------------------------image_filter_lanczos196 + class image_filter_lanczos196 : public image_filter_lanczos + { public: image_filter_lanczos196() : image_filter_lanczos(7.0){} }; + + //--------------------------------------------image_filter_lanczos256 + class image_filter_lanczos256 : public image_filter_lanczos + { public: image_filter_lanczos256() : image_filter_lanczos(8.0){} }; + + //--------------------------------------------image_filter_blackman36 + class image_filter_blackman36 : public image_filter_blackman + { public: image_filter_blackman36() : image_filter_blackman(3.0){} }; + + //--------------------------------------------image_filter_blackman64 + class image_filter_blackman64 : public image_filter_blackman + { public: image_filter_blackman64() : image_filter_blackman(4.0){} }; + + //-------------------------------------------image_filter_blackman100 + class image_filter_blackman100 : public image_filter_blackman + { public: image_filter_blackman100() : image_filter_blackman(5.0){} }; + + //-------------------------------------------image_filter_blackman144 + class image_filter_blackman144 : public image_filter_blackman + { public: image_filter_blackman144() : image_filter_blackman(6.0){} }; + + //-------------------------------------------image_filter_blackman196 + class image_filter_blackman196 : public image_filter_blackman + { public: image_filter_blackman196() : image_filter_blackman(7.0){} }; + + //-------------------------------------------image_filter_blackman256 + class image_filter_blackman256 : public image_filter_blackman + { public: image_filter_blackman256() : image_filter_blackman(8.0){} }; + + +} + +#endif diff --git a/agg/inc/agg_line_aa_basics.h b/agg/inc/agg_line_aa_basics.h new file mode 100755 index 000000000000..ab8e94715019 --- /dev/null +++ b/agg/inc/agg_line_aa_basics.h @@ -0,0 +1,152 @@ +//---------------------------------------------------------------------------- +// 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_LINE_AA_BASICS_INCLUDED +#define AGG_LINE_AA_BASICS_INCLUDED + +#include <stdlib.h> +#include "agg_basics.h" + +namespace agg +{ + + // See Implementation agg_line_aa_basics.cpp + + //------------------------------------------------------------------------- + enum + { + 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 + }; + + //------------------------------------------------------------------------- + enum + { + 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 + inline int line_mr(int x) + { + return x >> ((int)line_subpixel_shift - (int)line_mr_subpixel_shift); + } + + //-------------------------------------------------------------------line_hr + inline int line_hr(int x) + { + return x << ((int)line_subpixel_shift - (int)line_mr_subpixel_shift); + } + + //---------------------------------------------------------------line_dbl_hr + inline int line_dbl_hr(int x) + { + return x << line_subpixel_shift; + } + + //---------------------------------------------------------------line_coord + inline int line_coord(double x) + { + return int(x * line_subpixel_size); + } + + //==========================================================line_parameters + struct line_parameters + { + //--------------------------------------------------------------------- + line_parameters() {} + line_parameters(int x1_, int y1_, int x2_, int y2_, int len_) : + x1(x1_), y1(y1_), x2(x2_), y2(y2_), + dx(abs(x2_ - x1_)), + dy(abs(y2_ - y1_)), + sx((x2_ > x1_) ? 1 : -1), + sy((y2_ > y1_) ? 1 : -1), + vertical(dy >= dx), + inc(vertical ? sy : sx), + len(len_), + octant((sy & 4) | (sx & 2) | int(vertical)) + { + } + + //--------------------------------------------------------------------- + unsigned orthogonal_quadrant() const { return s_orthogonal_quadrant[octant]; } + unsigned diagonal_quadrant() const { return s_diagonal_quadrant[octant]; } + + //--------------------------------------------------------------------- + bool same_orthogonal_quadrant(const line_parameters& lp) const + { + return s_orthogonal_quadrant[octant] == s_orthogonal_quadrant[lp.octant]; + } + + //--------------------------------------------------------------------- + bool same_diagonal_quadrant(const line_parameters& lp) const + { + return s_diagonal_quadrant[octant] == s_diagonal_quadrant[lp.octant]; + } + + //--------------------------------------------------------------------- + int x1, y1, x2, y2, dx, dy, sx, sy; + bool vertical; + int inc; + int len; + int octant; + + //--------------------------------------------------------------------- + static int8u s_orthogonal_quadrant[8]; + static int8u s_diagonal_quadrant[8]; + }; + + + + // See Implementation agg_line_aa_basics.cpp + + //----------------------------------------------------------------bisectrix + void bisectrix(const line_parameters& l1, + const line_parameters& l2, + int* x, int* y); + + + //-------------------------------------------fix_degenerate_bisectrix_start + 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) + { + *x = lp.x1 + (lp.y2 - lp.y1); + *y = lp.y1 - (lp.x2 - lp.x1); + } + } + + + //---------------------------------------------fix_degenerate_bisectrix_end + 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) + { + *x = lp.x2 + (lp.y2 - lp.y1); + *y = lp.y2 - (lp.x2 - lp.x1); + } + } + + +} + +#endif diff --git a/agg/inc/agg_math.h b/agg/inc/agg_math.h new file mode 100755 index 000000000000..4aef4df9638e --- /dev/null +++ b/agg/inc/agg_math.h @@ -0,0 +1,247 @@ +//---------------------------------------------------------------------------- +// 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_MATH_INCLUDED +#define AGG_MATH_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + + const double intersection_epsilon = 1.0e-8; + + //------------------------------------------------------calc_point_location + AGG_INLINE double calc_point_location(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; + return cp1 == cp2 && cp2 == cp3 && cp3 == cp1; + } + + + //-----------------------------------------------------------calc_distance + AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2) + { + double dx = x2-x1; + double dy = y2-y1; + return sqrt(dx * dx + dy * dy); + } + + + //------------------------------------------------calc_point_line_distance + AGG_INLINE double calc_point_line_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); + } + + + //-------------------------------------------------------calc_intersection + AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by, + double cx, double cy, double dx, double dy, + double* x, double* y) + { + double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy); + double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx); + if(fabs(den) < intersection_epsilon) return false; + double r = num / den; + *x = ax + r * (bx-ax); + *y = ay + r * (by-ay); + return true; + } + + + //--------------------------------------------------------calc_orthogonal + AGG_INLINE void calc_orthogonal(double thickness, + double x1, double y1, + double x2, double y2, + double* x, double* y) + { + double dx = x2 - x1; + double dy = y2 - y1; + double d = sqrt(dx*dx + dy*dy); + *x = thickness * dy / d; + *y = thickness * dx / d; + } + + + //--------------------------------------------------------dilate_triangle + AGG_INLINE void dilate_triangle(double x1, double y1, + double x2, double y2, + double x3, double y3, + double *x, double* y, + double d) + { + double dx1=0.0; + double dy1=0.0; + double dx2=0.0; + double dy2=0.0; + double dx3=0.0; + double dy3=0.0; + double loc = calc_point_location(x1, y1, x2, y2, x3, y3); + if(fabs(loc) > intersection_epsilon) + { + if(calc_point_location(x1, y1, x2, y2, x3, y3) > 0.0) + { + d = -d; + } + calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1); + 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; + } + + //-------------------------------------------------------calc_polygon_area + template<class Storage> double calc_polygon_area(const Storage& st) + { + unsigned i; + double sum = 0.0; + double x = st[0].x; + double y = st[0].y; + double xs = x; + double ys = y; + + for(i = 1; i < st.size(); i++) + { + const typename Storage::value_type& v = st[i]; + sum += x * v.y - y * v.x; + x = v.x; + y = v.y; + } + return (sum + x * ys - y * xs) * 0.5; + } + + //------------------------------------------------------------------------ + // Tables for fast sqrt + extern int16u g_sqrt_table[1024]; + extern int8 g_elder_bit_table[256]; + + + //---------------------------------------------------------------fast_sqrt + //Fast integer Sqrt - really fast: no cycles, divisions or multiplications + #if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 4035) //Disable warning "no return value" + #endif + AGG_INLINE unsigned fast_sqrt(unsigned val) + { + #if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM) + //For Ix86 family processors this assembler code is used. + //The key command here is bsr - determination the number of the most + //significant bit of the value. For other processors + //(and maybe compilers) the pure C "#else" section is used. + __asm + { + mov ebx, val + mov edx, 11 + bsr ecx, ebx + sub ecx, 9 + jle less_than_9_bits + shr ecx, 1 + adc ecx, 0 + sub edx, ecx + shl ecx, 1 + shr ebx, cl + less_than_9_bits: + xor eax, eax + mov ax, g_sqrt_table[ebx*2] + mov ecx, edx + shr eax, cl + } + #else + + //This code is actually pure C and portable to most + //arcitectures including 64bit ones. + unsigned t = val; + int bit=0; + unsigned shift = 11; + + //The following piece of code is just an emulation of the + //Ix86 assembler command "bsr" (see above). However on old + //Intels (like Intel MMX 233MHz) this code is about twice + //faster (sic!) then just one "bsr". On PIII and PIV the + //bsr is optimized quite well. + bit = t >> 24; + if(bit) + { + bit = g_elder_bit_table[bit] + 24; + } + else + { + bit = (t >> 16) & 0xFF; + if(bit) + { + bit = g_elder_bit_table[bit] + 16; + } + else + { + bit = (t >> 8) & 0xFF; + if(bit) + { + bit = g_elder_bit_table[bit] + 8; + } + else + { + bit = g_elder_bit_table[t]; + } + } + } + + //This is calculation sqrt itself. + bit -= 9; + if(bit > 0) + { + bit = (bit >> 1) + (bit & 1); + shift -= bit; + val >>= (bit << 1); + } + return g_sqrt_table[val] >> shift; + #endif + } + #if defined(_MSC_VER) + #pragma warning(pop) + #endif + + + + +} + + +#endif diff --git a/agg/inc/agg_math_stroke.h b/agg/inc/agg_math_stroke.h new file mode 100755 index 000000000000..84d83738a9cd --- /dev/null +++ b/agg/inc/agg_math_stroke.h @@ -0,0 +1,340 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Stroke math +// +//---------------------------------------------------------------------------- + +#ifndef AGG_STROKE_MATH_INCLUDED +#define AGG_STROKE_MATH_INCLUDED + +#include "agg_math.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + //-------------------------------------------------------------line_cap_e + enum line_cap_e + { + butt_cap, + square_cap, + round_cap + }; + + //------------------------------------------------------------line_join_e + enum line_join_e + { + miter_join, + miter_join_revert, + round_join, + bevel_join + }; + + // Minimal angle to calculate round joins, less than 0.1 degree. + const double stroke_theta = 0.001; //----stroke_theta + + + //--------------------------------------------------------stroke_calc_arc + template<class VertexConsumer> + void stroke_calc_arc(VertexConsumer& out_vertices, + double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double width, + double approximation_scale) + { + 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; + + if(fabs(da) < stroke_theta) + { + out_vertices.add(coord_type((x + x + dx1 + dx2) * 0.5, + (y + y + dy1 + dy2) * 0.5)); + return; + } + + bool ccw = da > 0.0 && da < pi; + + if(width < 0) width = -width; + da = fabs(1.0 / (width * approximation_scale)); + if(!ccw) + { + if(a1 > a2) a2 += 2 * pi; + while(a1 < a2) + { + out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width)); + a1 += da; + } + } + else + { + if(a1 < a2) a2 -= 2 * pi; + while(a1 > a2) + { + out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width)); + a1 -= da; + } + } + out_vertices.add(coord_type(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) + { + 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)) + { + // The calculation didn't succeed, most probaly + // the three points lie one straight line + //---------------- + if(calc_distance(dx1, -dy1, dx2, -dy2) < width * 0.025) + { + // 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)); + } + } + } + else + { + double d1 = calc_distance(v1.x, v1.y, xi, yi); + double lim = width * miter_limit; + if(d1 > lim) + { + // Miter limit exceeded + //------------------------ + if(revert_flag) + { + // 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)); + } + 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)); + } + } + else + { + // Inside the miter limit + //--------------------- + out_vertices.add(coord_type(xi, yi)); + } + } + } + + + + + + + //--------------------------------------------------------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) + { + typedef typename VertexConsumer::value_type coord_type; + + out_vertices.remove_all(); + + double dx1 = width * (v1.y - v0.y) / len; + double dy1 = width * (v1.x - v0.x) / len; + double dx2 = 0; + double dy2 = 0; + + if(line_cap == square_cap) + { + dx2 = dy1; + dy2 = dx1; + } + + if(line_cap == round_cap) + { + double a1 = atan2(dy1, -dx1); + double a2 = a1 + pi; + double da = fabs(1.0 / (width * approximation_scale)); + while(a1 < a2) + { + out_vertices.add(coord_type(v0.x + cos(a1) * width, + v0.y + sin(a1) * width)); + a1 += da; + } + out_vertices.add(coord_type(v0.x + dx1, v0.y - dy1)); + } + 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)); + } + } + + + + //-------------------------------------------------------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) + { + 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; + + out_vertices.remove_all(); + + if(calc_point_location(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y) > 0.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); + } + else + { + // Outer join + //--------------- + switch(line_join) + { + case miter_join: + stroke_calc_miter(out_vertices, + v0, v1, v2, dx1, dy1, dx2, dy2, + width, + false, + miter_limit); + break; + + case miter_join_revert: + stroke_calc_miter(out_vertices, + v0, v1, v2, dx1, dy1, dx2, dy2, + width, + true, + miter_limit); + break; + + case round_join: + stroke_calc_arc(out_vertices, + v1.x, v1.y, dx1, -dy1, dx2, -dy2, + width, approximation_scale); + 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)); + } + break; + } + } + } + + + + +} + +#endif diff --git a/agg/inc/agg_path_storage.h b/agg/inc/agg_path_storage.h new file mode 100755 index 000000000000..8cdb9b9bbeb6 --- /dev/null +++ b/agg/inc/agg_path_storage.h @@ -0,0 +1,364 @@ +//---------------------------------------------------------------------------- +// 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_PATH_STORAGE_INCLUDED +#define AGG_PATH_STORAGE_INCLUDED + +#include "agg_basics.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 + { + // Allocation parameters + enum + { + block_shift = 8, + block_size = 1 << block_shift, + block_mask = block_size - 1, + block_pool = 256 + }; + + public: + + //-------------------------------------------------------------------- + class const_iterator + { + void vertex() + { + 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; + } + } + + 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) + { + } + + const_iterator(const path_storage& p, unsigned id) : + m_path(&p), + m_vertex_idx(id) + { + vertex(); + } + + const_iterator& operator++() + { + ++m_vertex_idx; + vertex(); + return *this; + } + + const vertex_type& operator*() const { return m_vertex; } + const vertex_type* operator->() const { return &m_vertex; } + + bool operator != (const const_iterator& i) + { + return m_vertex.cmd != i.m_vertex.cmd; + } + + private: + const path_storage* m_path; + unsigned m_vertex_idx; + vertex_type m_vertex; + }; + + ~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; + + void move_to(double x, double y); + void move_rel(double dx, double dy); + + void line_to(double x, double y); + void line_rel(double dx, double dy); + + void arc_to(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x, double y); + + void arc_rel(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double dx, double dy); + + void curve3(double x_ctrl, double y_ctrl, + double x_to, double y_to); + + void curve3_rel(double dx_ctrl, double dy_ctrl, + double dx_to, double dy_to); + + void curve3(double x_to, double y_to); + + void curve3_rel(double dx_to, double dy_to); + + void curve4(double x_ctrl1, double y_ctrl1, + double x_ctrl2, double y_ctrl2, + double x_to, double y_to); + + void curve4_rel(double dx_ctrl1, double dy_ctrl1, + double dx_ctrl2, double dy_ctrl2, + double dx_to, double dy_to); + + void curve4(double x_ctrl2, double y_ctrl2, + double x_to, double y_to); + + void curve4_rel(double x_ctrl2, double y_ctrl2, + double x_to, double y_to); + + + void end_poly(unsigned flags = path_flags_close); + + void close_polygon(unsigned flags = path_flags_none) + { + end_poly(path_flags_close | flags); + } + + void add_poly(const double* vertices, unsigned num, + bool solid_path = false, + unsigned end_flags = path_flags_none); + + template<class VertexSource> + void add_path(VertexSource& vs, + unsigned path_id = 0, + bool solid_path = true) + { + 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) + { + cmd = path_cmd_line_to; + } + add_vertex(x, y, cmd); + } + } + + unsigned start_new_path(); + + void copy_from(const path_storage& ps); + const path_storage& operator = (const path_storage& ps) + { + copy_from(ps); + return *this; + } + + + unsigned total_vertices() const { return m_total_vertices; } + unsigned vertex(unsigned idx, double* x, double* y) const + { + 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 command(unsigned idx) const + { + return m_cmd_blocks[idx >> block_shift][idx & block_mask]; + } + + 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); + + // 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); + + // Allows you to modify vertex coordinates. The caller must know + // the index of the vertex. + void modify_vertex(unsigned idx, double x, double y) + { + double* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1); + *pv++ = x; + *pv = y; + } + + // Allows you to modify vertex command. The caller must know + // the index of the vertex. + void modify_command(unsigned idx, unsigned cmd) + { + m_cmd_blocks[idx >> block_shift][idx & block_mask] = (unsigned char)cmd; + } + + + 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); + + 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; + }; + + + //------------------------------------------------------------------------ + inline unsigned path_storage::vertex(double* x, double* y) + { + if(m_iterator >= m_total_vertices) return path_cmd_stop; + return vertex(m_iterator++, x, y); + } + + //------------------------------------------------------------------------ + inline unsigned path_storage::prev_vertex(double* x, double* y) const + { + if(m_total_vertices > 1) + { + return vertex(m_total_vertices - 2, x, y); + } + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + inline unsigned path_storage::last_vertex(double* x, double* y) const + { + if(m_total_vertices) + { + return vertex(m_total_vertices - 1, x, y); + } + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + inline void path_storage::rel_to_abs(double* x, double* y) const + { + if(m_total_vertices) + { + double x2; + double y2; + if(is_vertex(vertex(m_total_vertices - 1, &x2, &y2))) + { + *x += x2; + *y += y2; + } + } + } + + //------------------------------------------------------------------------ + inline unsigned char* path_storage::storage_ptrs(double** 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); + } + + + //------------------------------------------------------------------------ + inline void path_storage::add_vertex(double x, double y, unsigned cmd) + { + 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++; + } + + //------------------------------------------------------------------------ + inline void path_storage::move_to(double x, double y) + { + add_vertex(x, y, path_cmd_move_to); + } + + //------------------------------------------------------------------------ + inline void path_storage::move_rel(double dx, double dy) + { + rel_to_abs(&dx, &dy); + add_vertex(dx, dy, path_cmd_move_to); + } + + //------------------------------------------------------------------------ + inline void path_storage::line_to(double x, double y) + { + add_vertex(x, y, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + inline void path_storage::line_rel(double dx, double dy) + { + rel_to_abs(&dx, &dy); + add_vertex(dx, dy, path_cmd_line_to); + } +} + + + +#endif diff --git a/agg/inc/agg_path_storage_integer.h b/agg/inc/agg_path_storage_integer.h new file mode 100755 index 000000000000..841bd10aa27a --- /dev/null +++ b/agg/inc/agg_path_storage_integer.h @@ -0,0 +1,300 @@ +//---------------------------------------------------------------------------- +// 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_PATH_STORAGE_INTEGER_INCLUDED +#define AGG_PATH_STORAGE_INTEGER_INCLUDED + +#include <string.h> +#include "agg_array.h" + +namespace agg +{ + + //---------------------------------------------------------vertex_integer + template<class T, unsigned CoordShift=6> struct vertex_integer + { + enum path_cmd + { + cmd_move_to = 0, + cmd_line_to = 1, + cmd_curve3 = 2, + cmd_curve4 = 3 + }; + + enum + { + coord_shift = CoordShift, + coord_mult = 1 << coord_shift + }; + + T x,y; + vertex_integer() {} + vertex_integer(T x_, T y_, unsigned flag) : + x(((x_ << 1) & ~1) | (flag & 1)), + y(((y_ << 1) & ~1) | (flag >> 1)) {} + + unsigned vertex(double* x_, double* y_, + 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; + switch(((y & 1) << 1) | (x & 1)) + { + case cmd_move_to: return path_cmd_move_to; + case cmd_line_to: return path_cmd_line_to; + case cmd_curve3: return path_cmd_curve3; + case cmd_curve4: return path_cmd_curve4; + } + return path_cmd_stop; + } + }; + + + //---------------------------------------------------path_storage_integer + template<class T, unsigned CoordShift=6> class path_storage_integer + { + public: + typedef vertex_integer<T, CoordShift> vertex_integer_type; + + //-------------------------------------------------------------------- + path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {} + + //-------------------------------------------------------------------- + void remove_all() { m_storage.remove_all(); } + + //-------------------------------------------------------------------- + void move_to(T x, T y) + { + m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to)); + } + + //-------------------------------------------------------------------- + void line_to(T x, T y) + { + m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_line_to)); + } + + //-------------------------------------------------------------------- + void curve3(T x_ctrl, T y_ctrl, + T x_to, T y_to) + { + m_storage.add(vertex_integer_type(x_ctrl, y_ctrl, vertex_integer_type::cmd_curve3)); + m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve3)); + } + + //-------------------------------------------------------------------- + void curve4(T x_ctrl1, T y_ctrl1, + T x_ctrl2, T y_ctrl2, + T x_to, T y_to) + { + m_storage.add(vertex_integer_type(x_ctrl1, y_ctrl1, vertex_integer_type::cmd_curve4)); + m_storage.add(vertex_integer_type(x_ctrl2, y_ctrl2, vertex_integer_type::cmd_curve4)); + m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve4)); + } + + //-------------------------------------------------------------------- + void close_polygon() {} + + //-------------------------------------------------------------------- + unsigned size() const { return m_storage.size(); } + unsigned vertex(unsigned idx, T* x, T* 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); + } + + //-------------------------------------------------------------------- + unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); } + void serialize(int8u* ptr) const + { + unsigned i; + for(i = 0; i < m_storage.size(); i++) + { + memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type)); + ptr += sizeof(vertex_integer_type); + } + } + + + //-------------------------------------------------------------------- + void rewind(unsigned) + { + m_vertex_idx = 0; + m_closed = true; + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + if(m_storage.size() < 2 || m_vertex_idx > m_storage.size()) + { + *x = 0; + *y = 0; + return path_cmd_stop; + } + if(m_vertex_idx == m_storage.size()) + { + *x = 0; + *y = 0; + ++m_vertex_idx; + return path_cmd_end_poly | path_flags_close; + } + unsigned cmd = m_storage[m_vertex_idx].vertex(x, y); + if(is_move_to(cmd) && !m_closed) + { + *x = 0; + *y = 0; + m_closed = true; + return path_cmd_end_poly | path_flags_close; + } + m_closed = false; + ++m_vertex_idx; + return cmd; + } + + //-------------------------------------------------------------------- + rect_d bounding_rect() const + { + rect_d bounds(1e100, 1e100, -1e100, -1e100); + if(m_storage.size() == 0) + { + bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0; + } + else + { + unsigned i; + for(i = 0; i < m_storage.size(); i++) + { + double x, y; + m_storage[i].vertex(&x, &y); + if(x < bounds.x1) bounds.x1 = x; + if(y < bounds.y1) bounds.y1 = y; + if(x > bounds.x2) bounds.x2 = x; + if(y > bounds.y2) bounds.y2 = y; + } + } + return bounds; + } + + + private: + pod_deque<vertex_integer_type, 6> m_storage; + unsigned m_vertex_idx; + bool m_closed; + }; + + + + + //-----------------------------------------serialized_integer_path_adaptor + template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor + { + public: + typedef vertex_integer<T, CoordShift> vertex_integer_type; + + //-------------------------------------------------------------------- + serialized_integer_path_adaptor() : + m_data(0), + m_end(0), + m_ptr(0), + m_dx(0.0), + m_dy(0.0), + m_scale(1.0), + m_vertices(0) + {} + + //-------------------------------------------------------------------- + serialized_integer_path_adaptor(const int8u* data, unsigned size, + double dx, double dy) : + m_data(data), + m_end(data + size), + m_ptr(data), + m_dx(dx), + m_dy(dy), + m_vertices(0) + {} + + //-------------------------------------------------------------------- + void init(const int8u* data, unsigned size, + double dx, double dy, double scale=1.0) + { + m_data = data; + m_end = data + size; + m_ptr = data; + m_dx = dx; + m_dy = dy; + m_scale = scale; + m_vertices = 0; + } + + + //-------------------------------------------------------------------- + void rewind(unsigned) + { + m_ptr = m_data; + m_vertices = 0; + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + if(m_data == 0 || m_ptr > m_end) + { + *x = 0; + *y = 0; + return path_cmd_stop; + } + + if(m_ptr == m_end) + { + *x = 0; + *y = 0; + m_ptr += sizeof(vertex_integer_type); + return path_cmd_end_poly | path_flags_close; + } + + vertex_integer_type v; + memcpy(&v, m_ptr, sizeof(vertex_integer_type)); + unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale); + if(is_move_to(cmd) && m_vertices > 2) + { + *x = 0; + *y = 0; + m_vertices = 0; + return path_cmd_end_poly | path_flags_close; + } + ++m_vertices; + m_ptr += sizeof(vertex_integer_type); + return cmd; + } + + private: + const int8u* m_data; + const int8u* m_end; + const int8u* m_ptr; + double m_dx; + double m_dy; + double m_scale; + unsigned m_vertices; + }; + +} + + +#endif + diff --git a/agg/inc/agg_pattern_filters_rgba.h b/agg/inc/agg_pattern_filters_rgba.h new file mode 100755 index 000000000000..5d194b2e39ba --- /dev/null +++ b/agg/inc/agg_pattern_filters_rgba.h @@ -0,0 +1,122 @@ +//---------------------------------------------------------------------------- +// 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_PATTERN_FILTERS_RGBA8_INCLUDED +#define AGG_PATTERN_FILTERS_RGBA8_INCLUDED + +#include "agg_basics.h" +#include "agg_line_aa_basics.h" +#include "agg_color_rgba.h" + + +namespace agg +{ + + //=======================================================pattern_filter_nn + template<class ColorT> struct pattern_filter_nn + { + typedef ColorT color_type; + static unsigned dilation() { return 0; } + + static void AGG_INLINE pixel_low_res(color_type const* const* buf, + color_type* p, int x, int y) + { + *p = buf[y][x]; + } + + static void AGG_INLINE pixel_high_res(color_type const* const* buf, + color_type* p, int x, int y) + { + *p = buf[y >> line_subpixel_shift] + [x >> line_subpixel_shift]; + } + }; + + typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8; + typedef pattern_filter_nn<rgba16> pattern_filter_nn_rgba16; + + + //===========================================pattern_filter_bilinear_rgba + template<class ColorT> struct pattern_filter_bilinear_rgba + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + + static unsigned dilation() { return 1; } + + static AGG_INLINE void pixel_low_res(color_type const* const* buf, + color_type* p, int x, int y) + { + *p = buf[y][x]; + } + + static AGG_INLINE void pixel_high_res(color_type const* const* buf, + color_type* p, int x, int y) + { + calc_type r, g, b, a; + r = g = b = a = line_subpixel_size * line_subpixel_size / 2; + + calc_type weight; + int x_lr = x >> line_subpixel_shift; + int y_lr = y >> line_subpixel_shift; + + x &= line_subpixel_mask; + y &= line_subpixel_mask; + const color_type* ptr = buf[y_lr] + x_lr; + + weight = (line_subpixel_size - x) * + (line_subpixel_size - y); + r += weight * ptr->r; + g += weight * ptr->g; + b += weight * ptr->b; + a += weight * ptr->a; + + ++ptr; + + weight = x * (line_subpixel_size - y); + r += weight * ptr->r; + g += weight * ptr->g; + b += weight * ptr->b; + a += weight * ptr->a; + + ptr = buf[y_lr + 1] + x_lr; + + weight = (line_subpixel_size - x) * y; + r += weight * ptr->r; + g += weight * ptr->g; + b += weight * ptr->b; + a += weight * ptr->a; + + ++ptr; + + weight = x * y; + r += weight * ptr->r; + g += weight * ptr->g; + b += weight * ptr->b; + a += weight * ptr->a; + + p->r = (value_type)(r >> line_subpixel_shift * 2); + p->g = (value_type)(g >> line_subpixel_shift * 2); + p->b = (value_type)(b >> line_subpixel_shift * 2); + p->a = (value_type)(a >> line_subpixel_shift * 2); + } + }; + + typedef pattern_filter_bilinear_rgba<rgba8> pattern_filter_bilinear_rgba8; + typedef pattern_filter_bilinear_rgba<rgba16> pattern_filter_bilinear_rgba16; +} + +#endif diff --git a/agg/inc/agg_pixfmt_amask_adaptor.h b/agg/inc/agg_pixfmt_amask_adaptor.h new file mode 100755 index 000000000000..7f3d5899b1c6 --- /dev/null +++ b/agg/inc/agg_pixfmt_amask_adaptor.h @@ -0,0 +1,265 @@ +//---------------------------------------------------------------------------- +// 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_PIXFMT_AMASK_ADAPTOR_INCLUDED +#define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED + + +#include <string.h> +#include "agg_rendering_buffer.h" + + +namespace agg +{ + //==================================================pixfmt_amask_adaptor + template<class PixFmt, class AlphaMask> class pixfmt_amask_adaptor + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef AlphaMask amask_type; + typedef typename amask_type::cover_type cover_type; + + private: + enum { span_extra_tail = 256 }; + + void realloc_span(unsigned len) + { + if(len > m_max_len) + { + delete [] m_span; + m_span = new cover_type[m_max_len = 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)); + } + + void init_span(unsigned len, const cover_type* covers) + { + realloc_span(len); + memcpy(m_span, 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) + {} + + void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; } + void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; } + + //-------------------------------------------------------------------- + unsigned width() const { return m_pixf->width(); } + unsigned height() const { return m_pixf->height(); } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) + { + return m_pixf->pixel(x, y); + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y)); + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, cover_type cover) + { + m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover)); + } + + //-------------------------------------------------------------------- + void copy_hline(int x, int y, + unsigned len, + 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); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + 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); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y, + unsigned len, + 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); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + 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); + } + + //-------------------------------------------------------------------- + void copy_from(const rendering_buffer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len); + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + 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); + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + 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); + } + + + //-------------------------------------------------------------------- + void blend_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_color_hspan(x, y, len, colors, m_span, cover); + } + + + //-------------------------------------------------------------------- + void blend_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); + } + 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); + } + else + { + realloc_span(len); + m_mask->fill_vspan(x, y, m_span, len); + } + m_pixf->blend_opaque_color_vspan(x, y, len, colors, m_span, cover); + } + + + private: + pixfmt_type* m_pixf; + const amask_type* m_mask; + + cover_type* m_span; + unsigned m_max_len; + }; + +} + +#endif + diff --git a/agg/inc/agg_pixfmt_gray.h b/agg/inc/agg_pixfmt_gray.h new file mode 100755 index 000000000000..48f47d1de32e --- /dev/null +++ b/agg/inc/agg_pixfmt_gray.h @@ -0,0 +1,703 @@ +//---------------------------------------------------------------------------- +// 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_PIXFMT_GRAY_INCLUDED +#define AGG_PIXFMT_GRAY_INCLUDED + +#include <string.h> +#include "agg_basics.h" +#include "agg_color_gray.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + + //============================================================blender_gray + template<class ColorT> struct blender_gray + { + 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 }; + + static AGG_INLINE void blend_pix(value_type* p, unsigned cv, + unsigned alpha, unsigned) + { + *p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift); + } + }; + + + //======================================================blender_gray_pre + template<class ColorT> struct blender_gray_pre + { + 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 }; + + static AGG_INLINE void blend_pix(value_type* p, unsigned cv, + unsigned alpha, unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (base_shift - 8); + *p = (value_type)((*p * alpha + cv * cover) >> base_shift); + } + }; + + + + //=====================================================apply_gamma_dir_gray + template<class ColorT, class GammaLut> class apply_gamma_dir_gray + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + *p = m_gamma.dir(*p); + } + + private: + const GammaLut& m_gamma; + }; + + + + //=====================================================apply_gamma_inv_gray + template<class ColorT, class GammaLut> class apply_gamma_inv_gray + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + *p = m_gamma.inv(*p); + } + + private: + const GammaLut& m_gamma; + }; + + + + //======================================================pixel_formats_gray + template<class Blender, unsigned Step=1, unsigned Offset=0> + class pixel_formats_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 + { + base_shift = color_type::base_shift, + base_size = color_type::base_size, + base_mask = color_type::base_mask + }; + + private: + //-------------------------------------------------------------------- + static AGG_INLINE void copy_or_blend_pix(value_type* p, + const color_type& c, + unsigned cover) + { + if (c.a) + { + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + *p = c.v; + } + else + { + Blender::blend_pix(p, c.v, alpha, cover); + } + } + } + + //-------------------------------------------------------------------- + static AGG_INLINE void copy_or_blend_opaque_pix(value_type* p, + const color_type& c, + unsigned cover) + { + if(cover == 255) + { + *p = c.v; + } + else + { + Blender::blend_pix(p, c.v, (cover + 1) << (base_shift - 8), cover); + } + } + + public: + //-------------------------------------------------------------------- + pixel_formats_gray(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 color_type pixel(int x, int y) const + { + value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; + return color_type(*p); + } + + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return row_data(x, + width() - 1, + m_rbuf->row(y) + + x * Step * sizeof(value_type) + + Offset * sizeof(value_type)); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + *((value_type*)m_rbuf->row(y) + 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); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; + do + { + *p = c.v; + p += Step; + } + while(--len); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; + do + { + *p = c.v; + p = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } + + + //-------------------------------------------------------------------- + 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(y) + x * Step + Offset; + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + do + { + *p = c.v; + p += Step; + } + while(--len); + } + else + { + do + { + Blender::blend_pix(p, c.v, alpha, cover); + p += Step; + } + while(--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + do + { + *p = c.v; + p = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } + else + { + do + { + Blender::blend_pix(p, c.v, alpha, cover); + p = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + 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; + if(alpha == base_mask) + { + *p = c.v; + } + else + { + Blender::blend_pix(p, c.v, alpha, *covers); + } + p += Step; + ++covers; + } + while(--len); + } + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + 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; + if(alpha == base_mask) + { + *p = c.v; + } + else + { + Blender::blend_pix(p, c.v, alpha, *covers); + } + p = (value_type*)m_rbuf->next_row(p); + ++covers; + } + 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; + if(covers) + { + do + { + copy_or_blend_pix(p, *colors++, *covers++); + p += Step; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + if(colors->a == base_mask) + { + *p = colors->v; + } + else + { + copy_or_blend_pix(p, *colors, 255); + } + p += Step; + ++colors; + } + while(--len); + } + else + { + do + { + copy_or_blend_pix(p, *colors++, cover); + p += Step; + } + while(--len); + } + } + } + + + + //-------------------------------------------------------------------- + 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 * Step + Offset; + if(covers) + { + do + { + copy_or_blend_pix(p, *colors++, *covers++); + p = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + if(colors->a == base_mask) + { + *p = colors->v; + } + else + { + copy_or_blend_pix(p, *colors, 255); + } + p = (value_type*)m_rbuf->next_row(p); + ++colors; + } + while(--len); + } + else + { + do + { + 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) + { + 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 + { + if(cover == 255) + { + do + { + *p = colors->v; + p += Step; + ++colors; + } + while(--len); + } + else + { + do + { + copy_or_blend_opaque_pix(p, *colors++, cover); + p += Step; + } + while(--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_opaque_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 * Step + Offset; + if(covers) + { + do + { + copy_or_blend_opaque_pix(p, *colors++, *covers++); + p = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } + else + { + 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); + } + } + } + + //-------------------------------------------------------------------- + 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) + Offset; + do + { + f(p); + p += Step; + } + 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) + { + memmove((value_type*)m_rbuf->row(ydst) + xdst, + (value_type*)from.row(ysrc) + xsrc, + sizeof(value_type) * len); + } + + private: + rendering_buffer* m_rbuf; + }; + + typedef blender_gray<gray8> blender_gray8; + typedef blender_gray_pre<gray8> blender_gray8_pre; + 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 + +} + +#endif + diff --git a/agg/inc/agg_pixfmt_rgb.h b/agg/inc/agg_pixfmt_rgb.h new file mode 100755 index 000000000000..436dfa4b284f --- /dev/null +++ b/agg/inc/agg_pixfmt_rgb.h @@ -0,0 +1,760 @@ +//---------------------------------------------------------------------------- +// 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_PIXFMT_RGB_INCLUDED +#define AGG_PIXFMT_RGB_INCLUDED + +#include <string.h> +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + + //=====================================================apply_gamma_dir_rgb + template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgb + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_dir_rgb(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.dir(p[Order::R]); + p[Order::G] = m_gamma.dir(p[Order::G]); + p[Order::B] = m_gamma.dir(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + + + //=====================================================apply_gamma_inv_rgb + template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgb + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_inv_rgb(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.inv(p[Order::R]); + p[Order::G] = m_gamma.inv(p[Order::G]); + p[Order::B] = m_gamma.inv(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + + //=========================================================blender_rgb + template<class ColorT, class Order> struct blender_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; + enum { base_shift = color_type::base_shift }; + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + p[Order::R] += (value_type)(((cr - p[Order::R]) * alpha) >> base_shift); + p[Order::G] += (value_type)(((cg - p[Order::G]) * alpha) >> base_shift); + p[Order::B] += (value_type)(((cb - p[Order::B]) * alpha) >> base_shift); + } + }; + + + //======================================================blender_rgb_pre + template<class ColorT, class Order> struct blender_rgb_pre + { + 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_shift = color_type::base_shift }; + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (base_shift - 8); + p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift); + 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); + } + }; + + + + //===================================================blender_rgb_gamma + template<class ColorT, class Order, class Gamma> class blender_rgb_gamma + { + public: + typedef ColorT color_type; + typedef Order order_type; + 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 }; + + //-------------------------------------------------------------------- + blender_rgb_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + calc_type r = m_gamma->dir(p[Order::R]); + calc_type g = m_gamma->dir(p[Order::G]); + calc_type b = m_gamma->dir(p[Order::B]); + p[Order::R] = m_gamma->inv((((m_gamma->dir(cr) - r) * alpha) >> base_shift) + r); + p[Order::G] = m_gamma->inv((((m_gamma->dir(cg) - g) * alpha) >> base_shift) + g); + p[Order::B] = m_gamma->inv((((m_gamma->dir(cb) - b) * alpha) >> base_shift) + b); + } + + private: + const gamma_type* m_gamma; + }; + + + + + //==================================================pixel_formats_rgb + template<class Blender> class pixel_formats_rgb + { + public: + typedef rendering_buffer::row_data row_data; + 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_shift = color_type::base_shift, + base_size = color_type::base_size, + base_mask = color_type::base_mask + }; + + private: + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(value_type* p, + const color_type& c, + unsigned cover) + { + if (c.a) + { + 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; + } + else + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + } + } + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_opaque_pix(value_type* p, + const color_type& c, + unsigned cover) + { + if(cover == 255) + { + 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, (cover + 1) << (base_shift - 8), cover); + } + } + + + public: + //-------------------------------------------------------------------- + pixel_formats_rgb(rendering_buffer& rb) : + m_rbuf(&rb) + {} + + //-------------------------------------------------------------------- + Blender& blender() { return m_blender; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + 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]); + } + + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return row_data(x, + width() - 1, + m_rbuf->row(y) + x * 3 * sizeof(value_type)); + } + + //-------------------------------------------------------------------- + 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; + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + } + + //-------------------------------------------------------------------- + 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); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; + do + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p += 3; + } + while(--len); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; + do + { + 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); + } + + + //-------------------------------------------------------------------- + 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(y) + x + x + x; + calc_type alpha = (calc_type(c.a) * (calc_type(cover) + 1)) >> 8; + if(alpha == base_mask) + { + do + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p += 3; + } + while(--len); + } + else + { + do + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + p += 3; + } + while(--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + do + { + 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); + } + else + { + do + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + p = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; + do + { + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + if(alpha == 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, alpha, *covers); + } + p += 3; + ++covers; + } + while(--len); + } + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row(y) + x + x + x; + do + { + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + if(alpha == 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, alpha, *covers); + } + p = (value_type*)m_rbuf->next_row(p); + ++covers; + } + 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; + if(covers) + { + do + { + copy_or_blend_pix(p, *colors++, *covers++); + p += 3; + } + while(--len); + } + else + { + 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; + } + else + { + copy_or_blend_pix(p, *colors, 255); + } + p += 3; + ++colors; + } + while(--len); + } + else + { + do + { + copy_or_blend_pix(p, *colors++, cover); + p += 3; + } + while(--len); + } + } + } + + + + //-------------------------------------------------------------------- + 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 + x + x; + if(covers) + { + do + { + copy_or_blend_pix(p, *colors++, *covers++); + p = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } + else + { + 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; + } + else + { + copy_or_blend_pix(p, *colors, 255); + } + p = (value_type*)m_rbuf->next_row(p); + ++colors; + } + while(--len); + } + else + { + do + { + 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) + { + 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 + { + if(cover == 255) + { + 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); + p += 3; + } + while(--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_opaque_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 + x + x; + if(covers) + { + do + { + copy_or_blend_opaque_pix(p, *colors++, *covers++); + p = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } + else + { + 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; + } + while(--len); + } + else + { + do + { + copy_or_blend_opaque_pix(p, *colors++, cover); + p = (value_type*)m_rbuf->next_row(p); + } + 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 + { + f(p); + p += 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) + { + 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 + { + 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, + 255); + } + } + psrc += 4; + pdst += 3; + } + while(--len); + } + + private: + rendering_buffer* 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 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 + + //-----------------------------------------------------pixfmt_rgb24_gamma + template<class Gamma> class pixfmt_rgb24_gamma : + public pixel_formats_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma> > + { + public: + pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) : + pixel_formats_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma> >(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_bgr24_gamma + template<class Gamma> class pixfmt_bgr24_gamma : + public pixel_formats_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma> > + { + public: + pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) : + pixel_formats_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma> >(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_rgb48_gamma + template<class Gamma> class pixfmt_rgb48_gamma : + public pixel_formats_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma> > + { + public: + pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) : + pixel_formats_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma> >(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_bgr48_gamma + template<class Gamma> class pixfmt_bgr48_gamma : + public pixel_formats_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma> > + { + public: + pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) : + pixel_formats_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma> >(rb) + { + this->blender().gamma(g); + } + }; + + +} + +#endif + diff --git a/agg/inc/agg_pixfmt_rgb_packed.h b/agg/inc/agg_pixfmt_rgb_packed.h new file mode 100755 index 000000000000..4f582ed59847 --- /dev/null +++ b/agg/inc/agg_pixfmt_rgb_packed.h @@ -0,0 +1,1277 @@ +//---------------------------------------------------------------------------- +// 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_PIXFMT_RGB_PACKED_INCLUDED +#define AGG_PIXFMT_RGB_PACKED_INCLUDED + +#include <string.h> +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + //=========================================================blender_rgb555 + struct blender_rgb555 + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 7) & 0xF8; + calc_type g = (rgb >> 2) & 0xF8; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 8)) >> 1) & 0x7C00) | + ((((cg - g) * alpha + (g << 8)) >> 6) & 0x03E0) | + (((cb - b) * alpha + (b << 8)) >> 11) | 0x8000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 7) & 0xF8, + (p >> 2) & 0xF8, + (p << 3) & 0xF8); + } + }; + + + //=====================================================blender_rgb555_pre + struct blender_rgb555_pre + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + pixel_type rgb = *p; + calc_type r = (rgb >> 7) & 0xF8; + calc_type g = (rgb >> 2) & 0xF8; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + ((((r * alpha + cr * cover) >> 1) & 0x7C00) | + (((g * alpha + cg * cover) >> 6) & 0x03E0) | + ((b * alpha + cb * cover) >> 11) | 0x8000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 7) & 0xF8, + (p >> 2) & 0xF8, + (p << 3) & 0xF8); + } + }; + + + + + //=====================================================blender_rgb555_gamma + template<class Gamma> class blender_rgb555_gamma + { + public: + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + typedef Gamma gamma_type; + + blender_rgb555_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 7) & 0xF8); + calc_type g = m_gamma->dir((rgb >> 2) & 0xF8); + calc_type b = m_gamma->dir((rgb << 3) & 0xF8); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 7) & 0x7C00) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 2) & 0x03E0) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3) | 0x8000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 7) & 0xF8, + (p >> 2) & 0xF8, + (p << 3) & 0xF8); + } + + private: + const Gamma* m_gamma; + }; + + + + + + //=========================================================blender_rgb565 + struct blender_rgb565 + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 8) & 0xF8; + calc_type g = (rgb >> 3) & 0xFC; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 8)) ) & 0xF800) | + ((((cg - g) * alpha + (g << 8)) >> 5) & 0x07E0) | + (((cb - b) * alpha + (b << 8)) >> 11)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 8) & 0xF8, + (p >> 3) & 0xFC, + (p << 3) & 0xF8); + } + }; + + + + //=====================================================blender_rgb565_pre + struct blender_rgb565_pre + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + pixel_type rgb = *p; + calc_type r = (rgb >> 8) & 0xF8; + calc_type g = (rgb >> 3) & 0xFC; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + ((((r * alpha + cr * cover) ) & 0xF800) | + (((g * alpha + cg * cover) >> 5 ) & 0x07E0) | + ((b * alpha + cb * cover) >> 11)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 8) & 0xF8, + (p >> 3) & 0xFC, + (p << 3) & 0xF8); + } + }; + + + + //=====================================================blender_rgb565_gamma + template<class Gamma> class blender_rgb565_gamma + { + public: + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + typedef Gamma gamma_type; + + blender_rgb565_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 8) & 0xF8); + calc_type g = m_gamma->dir((rgb >> 3) & 0xFC); + calc_type b = m_gamma->dir((rgb << 3) & 0xF8); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 8) & 0xF800) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 3) & 0x07E0) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 8) & 0xF8, + (p >> 3) & 0xFC, + (p << 3) & 0xF8); + } + + private: + const Gamma* m_gamma; + }; + + + + //=====================================================blender_rgbAAA + struct blender_rgbAAA + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 14) & 0xFFC0; + calc_type g = (rgb >> 4) & 0xFFC0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 16)) >> 2) & 0x3FF00000) | + ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | + (((cb - b) * alpha + (b << 16)) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (b >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 14) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p << 6) & 0xFFC0); + } + }; + + + + //==================================================blender_rgbAAA_pre + struct blender_rgbAAA_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type rgb = *p; + calc_type r = (rgb >> 14) & 0xFFC0; + calc_type g = (rgb >> 4) & 0xFFC0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + ((((r * alpha + cr * cover) >> 2) & 0x3FF00000) | + (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | + ((b * alpha + cb * cover) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (b >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 14) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p << 6) & 0xFFC0); + } + }; + + + + //=================================================blender_rgbAAA_gamma + template<class Gamma> class blender_rgbAAA_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_rgbAAA_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 14) & 0xFFC0); + calc_type g = m_gamma->dir((rgb >> 4) & 0xFFC0); + calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 14) & 0x3FF00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 ) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (b >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 14) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p << 6) & 0xFFC0); + } + private: + const Gamma* m_gamma; + }; + + + //=====================================================blender_bgrAAA + struct blender_bgrAAA + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = (bgr >> 14) & 0xFFC0; + calc_type g = (bgr >> 4) & 0xFFC0; + calc_type r = (bgr << 6) & 0xFFC0; + *p = (pixel_type) + (((((cb - b) * alpha + (b << 16)) >> 2) & 0x3FF00000) | + ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | + (((cr - r) * alpha + (r << 16)) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (r >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 6) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p >> 14) & 0xFFC0); + } + }; + + + + //=================================================blender_bgrAAA_pre + struct blender_bgrAAA_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type bgr = *p; + calc_type b = (bgr >> 14) & 0xFFC0; + calc_type g = (bgr >> 4) & 0xFFC0; + calc_type r = (bgr << 6) & 0xFFC0; + *p = (pixel_type) + ((((b * alpha + cb * cover) >> 2) & 0x3FF00000) | + (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | + ((r * alpha + cr * cover) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (r >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 6) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p >> 14) & 0xFFC0); + } + }; + + + + //=================================================blender_bgrAAA_gamma + template<class Gamma> class blender_bgrAAA_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_bgrAAA_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = m_gamma->dir((bgr >> 14) & 0xFFC0); + calc_type g = m_gamma->dir((bgr >> 4) & 0xFFC0); + calc_type r = m_gamma->dir((bgr << 6) & 0xFFC0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 14) & 0x3FF00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | + (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 6 ) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (r >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 6) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p >> 14) & 0xFFC0); + } + + private: + const Gamma* m_gamma; + }; + + + + //=====================================================blender_rgbBBA + struct blender_rgbBBA + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 16) & 0xFFE0; + calc_type g = (rgb >> 5) & 0xFFE0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 16)) ) & 0xFFE00000) | + ((((cg - g) * alpha + (g << 16)) >> 11) & 0x001FFC00) | + (((cb - b) * alpha + (b << 16)) >> 22)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 16) & 0xFFE0, + (p >> 5) & 0xFFE0, + (p << 6) & 0xFFC0); + } + }; + + + //=================================================blender_rgbBBA_pre + struct blender_rgbBBA_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type rgb = *p; + calc_type r = (rgb >> 16) & 0xFFE0; + calc_type g = (rgb >> 5) & 0xFFE0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + ((((r * alpha + cr * cover) ) & 0xFFE00000) | + (((g * alpha + cg * cover) >> 11) & 0x001FFC00) | + ((b * alpha + cb * cover) >> 22)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 16) & 0xFFE0, + (p >> 5) & 0xFFE0, + (p << 6) & 0xFFC0); + } + }; + + + + //=================================================blender_rgbBBA_gamma + template<class Gamma> class blender_rgbBBA_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_rgbBBA_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 16) & 0xFFE0); + calc_type g = m_gamma->dir((rgb >> 5) & 0xFFE0); + calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 16) & 0xFFE00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 5 ) & 0x001FFC00) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 )); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 16) & 0xFFE0, + (p >> 5) & 0xFFE0, + (p << 6) & 0xFFC0); + } + + private: + const Gamma* m_gamma; + }; + + + //=====================================================blender_bgrABB + struct blender_bgrABB + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = (bgr >> 16) & 0xFFC0; + calc_type g = (bgr >> 6) & 0xFFE0; + calc_type r = (bgr << 5) & 0xFFE0; + *p = (pixel_type) + (((((cb - b) * alpha + (b << 16)) ) & 0xFFC00000) | + ((((cg - g) * alpha + (g << 16)) >> 10) & 0x003FF800) | + (((cr - r) * alpha + (r << 16)) >> 21)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 5) & 0xFFE0, + (p >> 6) & 0xFFE0, + (p >> 16) & 0xFFC0); + } + }; + + + //=================================================blender_bgrABB_pre + struct blender_bgrABB_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type bgr = *p; + calc_type b = (bgr >> 16) & 0xFFC0; + calc_type g = (bgr >> 6) & 0xFFE0; + calc_type r = (bgr << 5) & 0xFFE0; + *p = (pixel_type) + ((((b * alpha + cb * cover) ) & 0xFFC00000) | + (((g * alpha + cg * cover) >> 10) & 0x003FF800) | + ((r * alpha + cr * cover) >> 21)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 5) & 0xFFE0, + (p >> 6) & 0xFFE0, + (p >> 16) & 0xFFC0); + } + }; + + + + //=================================================blender_bgrABB_gamma + template<class Gamma> class blender_bgrABB_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_bgrABB_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = m_gamma->dir((bgr >> 16) & 0xFFC0); + calc_type g = m_gamma->dir((bgr >> 6) & 0xFFE0); + calc_type r = m_gamma->dir((bgr << 5) & 0xFFE0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 16) & 0xFFC00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 6 ) & 0x003FF800) | + (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 5 )); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 5) & 0xFFE0, + (p >> 6) & 0xFFE0, + (p >> 16) & 0xFFC0); + } + + private: + const Gamma* m_gamma; + }; + + + + //===============================================pixel_formats_rgb_packed + template<class Blender> class pixel_formats_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 + { + base_shift = color_type::base_shift, + base_size = color_type::base_size, + base_mask = color_type::base_mask + }; + + private: + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + if (c.a) + { + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + *p = m_blender.make_pix(c.r, c.g, c.b); + } + else + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + } + } + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_opaque_pix(pixel_type* p, const color_type& c, unsigned cover) + { + if(cover == 255) + { + *p = m_blender.make_pix(c.r, c.g, c.b); + } + else + { + m_blender.blend_pix(p, c.r, c.g, c.b, (cover + 1) << (base_shift - 8), cover); + } + } + + + public: + //-------------------------------------------------------------------- + pixel_formats_rgb_packed(rendering_buffer& rb) : + m_rbuf(&rb) + {} + + //-------------------------------------------------------------------- + Blender& blender() { return m_blender; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + pixel_type* p = (pixel_type*)m_rbuf->row(y) + x; + return m_blender.make_color(((pixel_type*)m_rbuf->row(y))[x]); + } + + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return row_data(x, + width() - 1, + m_rbuf->row(y) + x * sizeof(pixel_type)); + } + + //-------------------------------------------------------------------- + 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); + } + + //-------------------------------------------------------------------- + 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); + } + + + //-------------------------------------------------------------------- + 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 v = m_blender.make_pix(c.r, c.g, c.b); + do + { + *p++ = v; + } + 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 + { + *p = v; + p = (pixel_type*)m_rbuf->next_row(p); + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + 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; + } + while(--len); + } + else + { + do + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + ++p; + } + while(--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + 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); + } + while(--len); + } + else + { + do + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + p = (pixel_type*)m_rbuf->next_row(p); + } + 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; + do + { + copy_or_blend_pix(p, c, *covers++); + ++p; + } + 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); + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_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; + do + { + copy_or_blend_pix(p++, *colors++, covers ? *covers++ : cover); + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_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; + do + { + copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover); + p = (pixel_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) + { + pixel_type* p = (pixel_type*)m_rbuf->row(y) + x; + if(covers) + { + do + { + copy_or_blend_opaque_pix(p++, *colors++, *covers++); + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + *p++ = m_blender.make_pix(colors->r, colors->g, colors->b); + ++colors; + } + while(--len); + } + else + { + do + { + copy_or_blend_opaque_pix(p++, *colors++, cover); + } + 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) + { + do + { + copy_or_blend_opaque_pix(p, *colors++, *covers++); + p = (pixel_type*)m_rbuf->next_row(p); + } + 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 + { + value_type alpha = psrc[src_order::A]; + if(alpha) + { + 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); + } + } + psrc += 4; + ++pdst; + } + while(--len); + } + + + private: + rendering_buffer* 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 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 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 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 + + + //-----------------------------------------------------pixfmt_rgb555_gamma + template<class Gamma> class pixfmt_rgb555_gamma : + public pixel_formats_rgb_packed<blender_rgb555_gamma<Gamma> > + { + public: + pixfmt_rgb555_gamma(rendering_buffer& rb, const Gamma& g) : + pixel_formats_rgb_packed<blender_rgb555_gamma<Gamma> >(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_rgb565_gamma + template<class Gamma> class pixfmt_rgb565_gamma : + public pixel_formats_rgb_packed<blender_rgb565_gamma<Gamma> > + { + public: + pixfmt_rgb565_gamma(rendering_buffer& rb, const Gamma& g) : + pixel_formats_rgb_packed<blender_rgb565_gamma<Gamma> >(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_rgbAAA_gamma + template<class Gamma> class pixfmt_rgbAAA_gamma : + public pixel_formats_rgb_packed<blender_rgbAAA_gamma<Gamma> > + { + public: + pixfmt_rgbAAA_gamma(rendering_buffer& rb, const Gamma& g) : + pixel_formats_rgb_packed<blender_rgbAAA_gamma<Gamma> >(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_bgrAAA_gamma + template<class Gamma> class pixfmt_bgrAAA_gamma : + public pixel_formats_rgb_packed<blender_bgrAAA_gamma<Gamma> > + { + public: + pixfmt_bgrAAA_gamma(rendering_buffer& rb, const Gamma& g) : + pixel_formats_rgb_packed<blender_bgrAAA_gamma<Gamma> >(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_rgbBBA_gamma + template<class Gamma> class pixfmt_rgbBBA_gamma : + public pixel_formats_rgb_packed<blender_rgbBBA_gamma<Gamma> > + { + public: + pixfmt_rgbBBA_gamma(rendering_buffer& rb, const Gamma& g) : + pixel_formats_rgb_packed<blender_rgbBBA_gamma<Gamma> >(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_bgrABB_gamma + template<class Gamma> class pixfmt_bgrABB_gamma : + public pixel_formats_rgb_packed<blender_bgrABB_gamma<Gamma> > + { + public: + pixfmt_bgrABB_gamma(rendering_buffer& rb, const Gamma& g) : + pixel_formats_rgb_packed<blender_bgrABB_gamma<Gamma> >(rb) + { + this->blender().gamma(g); + } + }; + + +} + +#endif + diff --git a/agg/inc/agg_pixfmt_rgba.h b/agg/inc/agg_pixfmt_rgba.h new file mode 100755 index 000000000000..3716877e04f7 --- /dev/null +++ b/agg/inc/agg_pixfmt_rgba.h @@ -0,0 +1,1312 @@ +//---------------------------------------------------------------------------- +// 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_PIXFMT_RGBA_INCLUDED +#define AGG_PIXFMT_RGBA_INCLUDED + +#include <string.h> +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + + //=========================================================multiplier_rgba + template<class ColorT, class Order> struct multiplier_rgba + { + typedef typename ColorT::value_type value_type; + typedef typename ColorT::calc_type calc_type; + + //-------------------------------------------------------------------- + static AGG_INLINE void premultiply(value_type* p) + { + calc_type a = p[Order::A]; + if(a < ColorT::base_mask) + { + if(a == 0) + { + 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); + } + } + + + //-------------------------------------------------------------------- + static AGG_INLINE void demultiply(value_type* p) + { + calc_type a = p[Order::A]; + if(a < ColorT::base_mask) + { + if(a == 0) + { + p[Order::R] = p[Order::G] = p[Order::B] = 0; + return; + } + calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a; + calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a; + calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a; + p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r); + p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g); + p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b); + } + } + }; + + + //=====================================================apply_gamma_dir_rgba + template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgba + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.dir(p[Order::R]); + p[Order::G] = m_gamma.dir(p[Order::G]); + p[Order::B] = m_gamma.dir(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + + + //=====================================================apply_gamma_inv_rgba + template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgba + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.inv(p[Order::R]); + p[Order::G] = m_gamma.inv(p[Order::G]); + p[Order::B] = m_gamma.inv(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + + + //=============================================================blender_rgba + template<class ColorT, class Order, class PixelT> 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 + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + calc_type r = p[Order::R]; + calc_type g = p[Order::G]; + calc_type b = p[Order::B]; + calc_type a = p[Order::A]; + p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift); + p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift); + p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift); + p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift)); + } + }; + + + //=========================================================blender_rgba_pre + template<class ColorT, class Order, class PixelT> 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 + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (base_shift - 8); + p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift); + 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); + 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 + { + 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 }; + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + if(alpha == 0) return; + calc_type a = p[Order::A]; + calc_type r = p[Order::R] * a; + calc_type g = p[Order::G] * a; + calc_type b = p[Order::B] * a; + a = ((alpha + a) << base_shift) - alpha * a; + p[Order::A] = (value_type)(a >> base_shift); + p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a); + p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a); + p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a); + } + }; + + + //====================================================blender_rgba_wrapper + template<class Blender> struct blender_rgba_wrapper + { + typedef typename Blender::color_type color_type; + typedef typename Blender::order_type order_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 + { + base_shift = color_type::base_shift, + base_size = color_type::base_size, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + Blender::blend_pix(p, cr, cg, cb, alpha, cover); + } + + //-------------------------------------------------------------------- + static AGG_INLINE void copy_or_blend_pix(value_type* p, + const color_type& c, + unsigned cover) + { + if (c.a) + { + 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; + } + else + { + Blender::blend_pix(p, c.r, c.g, c.b, alpha, cover); + } + } + } + + //-------------------------------------------------------------------- + static AGG_INLINE void copy_or_blend_opaque_pix(value_type* p, + const color_type& c, + 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; + } + else + { + Blender::blend_pix(p, c.r, c.g, c.b, (cover + 1) << (base_shift - 8), cover); + } + } + }; + + + + + //=======================================================pixel_formats_rgba + template<class Blender> class pixel_formats_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 typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef blender_rgba_wrapper<Blender> blender_type; + enum + { + base_shift = color_type::base_shift, + base_size = color_type::base_size, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + pixel_formats_rgba(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 color_type pixel(int x, int y) const + { + 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]); + } + + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return row_data(x, + width() - 1, + m_rbuf->row(y) + x * 4 * sizeof(value_type)); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p[order_type::A] = c.a; + } + + //-------------------------------------------------------------------- + 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); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + 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; + ((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); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + 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; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + *(pixel_type*)p = v; + p = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } + + + //-------------------------------------------------------------------- + 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(y) + (x << 2); + 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); + } + } + } + + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); + 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 = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } + else + { + do + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); + p = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); + do + { + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 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] = base_mask; + } + else + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); + } + p += 4; + ++covers; + } + while(--len); + } + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row(y) + (x << 2); + do + { + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 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] = base_mask; + } + else + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); + } + p = (value_type*)m_rbuf->next_row(p); + ++covers; + } + 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 << 2); + if(covers) + { + do + { + blender_type::copy_or_blend_pix(p, *colors++, *covers++); + p += 4; + } + while(--len); + } + else + { + 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); + } + } + } + + + + //-------------------------------------------------------------------- + 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); + if(covers) + { + do + { + blender_type::copy_or_blend_pix(p, *colors++, *covers++); + p = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } + else + { + 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); + } + } + } + + + //-------------------------------------------------------------------- + void blend_opaque_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); + if(covers) + { + do + { + blender_type::copy_or_blend_opaque_pix(p, *colors++, *covers++); + p += 4; + } + while(--len); + } + else + { + 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); + } + } + } + + + //-------------------------------------------------------------------- + void blend_opaque_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); + if(covers) + { + do + { + blender_type::copy_or_blend_opaque_pix(p, *colors++, *covers++); + p = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } + else + { + 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 = (value_type*)m_rbuf->next_row(p); + ++colors; + } + while(--len); + } + else + { + do + { + blender_type::copy_or_blend_opaque_pix(p, *colors++, cover); + p = (value_type*)m_rbuf->next_row(p); + } + 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 + { + f(p); + p += 4; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply); + } + + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply); + } + + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g)); + } + + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba<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 * 4, + (value_type*)from.row(ysrc) + xsrc * 4, + sizeof(value_type) * 4 * 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_; + value_type* pdst = (value_type*)m_rbuf->row(ydst) + (xdst << 2); + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } + do + { + 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]; + 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); + } + } + psrc += incp; + pdst += incp; + } + while(--len); + } + + private: + rendering_buffer* m_rbuf; + }; + + + + + //================================================pixfmt_custom_rbuf_rgba + template<class Blender, class RenBuf> class pixfmt_custom_rbuf_rgba + { + public: + typedef typename Blender::color_type color_type; + typedef typename Blender::order_type order_type; + typedef typename Blender::pixel_type pixel_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 + { + base_shift = color_type::base_shift, + base_size = color_type::base_size, + base_mask = color_type::base_mask + }; + + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + + //-------------------------------------------------------------------- + pixfmt_custom_rbuf_rgba(rbuf_type& rb) : m_rbuf(&rb) {} + + //-------------------------------------------------------------------- + unsigned width() const { return m_rbuf->width(); } + unsigned height() const { return m_rbuf->height(); } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + 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(); + } + + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return m_rbuf->span(x, y); + } + + //-------------------------------------------------------------------- + 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; + } + + //-------------------------------------------------------------------- + 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); + } + + //-------------------------------------------------------------------- + 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; + do + { + *(pixel_type*)p = v; + p += 4; + } + while(--len); + } + + //-------------------------------------------------------------------- + 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; + } + while(--len); + } + + //-------------------------------------------------------------------- + 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->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); + } + } + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { + if (c.a) + { + 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); + } + } + } + + + //-------------------------------------------------------------------- + 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); + do + { + blender_type::copy_or_blend_pix(p, c, *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++); + } + 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->span_ptr(x, y, len); + do + { + blender_type::copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover); + p += 4; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + do + { + blender_type::copy_or_blend_pix((value_type*)m_rbuf->span_ptr(x, y++, 1), + *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) + { + 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 + { + 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); + } + } + } + + + //-------------------------------------------------------------------- + void blend_opaque_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 + { + 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); + } + } + } + + + + //-------------------------------------------------------------------- + template<class Function> void for_each_pixel(Function f) + { + unsigned y; + for(y = 0; y < height(); ++y) + { + row_data sp = span(0, y); + if(sp.ptr) + { + value_type* p = (value_type*)sp.ptr; + while(sp.x1 <= sp.x2) + { + f(p); + p += 4; + ++sp.x1; + } + } + } + } + + + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply); + } + + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply); + } + + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g)); + } + + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba<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(ysrc); + if(p) + { + p += xsrc * 4 * sizeof(value_type); + memmove(m_rbuf->span_ptr(xdst, ydst, len), + p, + len * 4 * sizeof(value_type)); + } + } + + + + //-------------------------------------------------------------------- + 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_; + value_type* pdst = (value_type*)m_rbuf->span_ptr(xdst, ydst, len); + + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } + do + { + 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]; + 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); + } + } + psrc += incp; + pdst += incp; + } + while(--len); + } + + + private: + rbuf_type* m_rbuf; + }; + + + + + + + + //----------------------------------------------------------------------- + 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_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_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 + + 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_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 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 +} + +#endif + diff --git a/agg/inc/agg_rasterizer_outline.h b/agg/inc/agg_rasterizer_outline.h new file mode 100755 index 000000000000..18512e76a1ad --- /dev/null +++ b/agg/inc/agg_rasterizer_outline.h @@ -0,0 +1,146 @@ +//---------------------------------------------------------------------------- +// 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_RASTERIZER_OUTLINE_INCLUDED +#define AGG_RASTERIZER_OUTLINE_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //======================================================rasterizer_outline + template<class Renderer> class rasterizer_outline + { + public: + rasterizer_outline(Renderer& ren) : + m_ren(&ren), + m_start_x(0), + m_start_y(0), + m_vertices(0) + { + } + + //-------------------------------------------------------------------- + void move_to(int x, int y) + { + m_vertices = 1; + m_ren->move_to(m_start_x = x, m_start_y = y); + } + + //-------------------------------------------------------------------- + void line_to(int x, int y) + { + ++m_vertices; + m_ren->line_to(x, y); + } + + //-------------------------------------------------------------------- + void move_to_d(double x, double y) + { + move_to(m_ren->coord(x), m_ren->coord(y)); + } + + //-------------------------------------------------------------------- + void line_to_d(double x, double y) + { + line_to(m_ren->coord(x), m_ren->coord(y)); + } + + //-------------------------------------------------------------------- + void close() + { + if(m_vertices > 2) + { + line_to(m_start_x, m_start_y); + } + m_vertices = 0; + } + + //-------------------------------------------------------------------- + void add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + move_to_d(x, y); + } + else + { + if(is_end_poly(cmd)) + { + if(is_closed(cmd)) close(); + } + else + { + line_to_d(x, y); + } + } + } + + + //-------------------------------------------------------------------- + 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); + } + } + + + //-------------------------------------------------------------------- + template<class VertexSource, class ColorStorage, class PathId> + void render_all_paths(VertexSource& vs, + const ColorStorage& colors, + const PathId& id, + unsigned num_paths) + { + for(unsigned i = 0; i < num_paths; i++) + { + m_ren->line_color(colors[i]); + add_path(vs, id[i]); + } + } + + + //-------------------------------------------------------------------- + template<class Ctrl> void render_ctrl(Ctrl& c) + { + unsigned i; + for(i = 0; i < c.num_paths(); i++) + { + m_ren->line_color(c.color(i)); + add_path(c, i); + } + } + + + private: + Renderer* m_ren; + int m_start_x; + int m_start_y; + unsigned m_vertices; + }; + + +} + + +#endif + diff --git a/agg/inc/agg_rasterizer_outline_aa.h b/agg/inc/agg_rasterizer_outline_aa.h new file mode 100755 index 000000000000..3f4d6395fafa --- /dev/null +++ b/agg/inc/agg_rasterizer_outline_aa.h @@ -0,0 +1,516 @@ +//---------------------------------------------------------------------------- +// 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_RASTERIZER_OUTLINE_AA_INCLUDED +#define AGG_RASTERIZER_OUTLINE_AA_INCLUDED + +#include "agg_basics.h" +#include "agg_line_aa_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + //------------------------------------------------------------------------- + inline bool cmp_dist_start(int d) { return d > 0; } + inline bool cmp_dist_end(int d) { return d <= 0; } + + + + //-----------------------------------------------------------line_aa_vertex + // Vertex (x, y) with the distance to the next one. The last vertex has + // the distance between the last and the first points + struct line_aa_vertex + { + int x; + int y; + int len; + + line_aa_vertex() {} + line_aa_vertex(int x_, int y_) : + x(x_), + y(y_), + len(0) + { + } + + bool operator () (const line_aa_vertex& val) + { + 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); + } + }; + + + + + //=======================================================rasterizer_outline_aa + template<class Renderer> class rasterizer_outline_aa + { + private: + //------------------------------------------------------------------------ + struct draw_vars + { + unsigned idx; + int x1, y1, x2, y2; + line_parameters curr, next; + int lcurr, lnext; + int xb1, yb1, xb2, yb2; + unsigned flags; + }; + + void draw(draw_vars& dv, unsigned start, unsigned end); + + public: + 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()), + m_round_cap(false), + m_start_x(0), + m_start_y(0) + { + } + + //------------------------------------------------------------------------ + void accurate_join(bool v) + { + m_accurate_join = m_ren.accurate_join_only() ? true : v; + } + bool accurate_join() const { return m_accurate_join; } + + //------------------------------------------------------------------------ + void round_cap(bool v) { m_round_cap = v; } + bool round_cap() const { return m_round_cap; } + + //------------------------------------------------------------------------ + void move_to(int x, int y) + { + m_src_vertices.modify_last(vertex_type(m_start_x = x, m_start_y = y)); + } + + //------------------------------------------------------------------------ + void line_to(int x, int y) + { + m_src_vertices.add(vertex_type(x, y)); + } + + //------------------------------------------------------------------------ + void move_to_d(double x, double y) + { + move_to(line_coord(x), line_coord(y)); + } + + //------------------------------------------------------------------------ + void line_to_d(double x, double y) + { + line_to(line_coord(x), line_coord(y)); + } + + //------------------------------------------------------------------------ + void render(bool close_polygon); + + //------------------------------------------------------------------------ + void add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + render(false); + move_to_d(x, y); + } + else + { + if(is_end_poly(cmd)) + { + render(is_closed(cmd)); + if(is_closed(cmd)) + { + move_to(m_start_x, m_start_y); + } + } + else + { + line_to_d(x, y); + } + } + } + + //------------------------------------------------------------------------ + 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); + } + render(false); + } + + + //------------------------------------------------------------------------ + template<class VertexSource, class ColorStorage, class PathId> + void render_all_paths(VertexSource& vs, + const ColorStorage& colors, + const PathId& id, + unsigned num_paths) + { + for(unsigned i = 0; i < num_paths; i++) + { + m_ren.color(colors[i]); + add_path(vs, id[i]); + } + } + + + //------------------------------------------------------------------------ + template<class Ctrl> void render_ctrl(Ctrl& c) + { + unsigned i; + for(i = 0; i < c.num_paths(); 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>&); + + 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; + }; + + + + + + + + + //---------------------------------------------------------------------------- + template<class Renderer> + void rasterizer_outline_aa<Renderer>::draw(draw_vars& dv, unsigned start, unsigned end) + { + unsigned i; + const vertex_storage_type::value_type* v; + + for(i = start; i < end; i++) + { + 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; + } + + dv.x1 = dv.x2; + dv.y1 = dv.y2; + dv.lcurr = dv.lnext; + dv.lnext = m_src_vertices[dv.idx].len; + + ++dv.idx; + if(dv.idx >= m_src_vertices.size()) dv.idx = 0; + + v = &m_src_vertices[dv.idx]; + dv.x2 = v->x; + dv.y2 = v->y; + + dv.curr = dv.next; + dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); + dv.xb1 = dv.xb2; + dv.yb1 = dv.yb2; + + if(m_accurate_join) + { + dv.flags = 0; + } + else + { + 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); + } + } + } + + + + + //---------------------------------------------------------------------------- + template<class Renderer> + void rasterizer_outline_aa<Renderer>::render(bool close_polygon) + { + m_src_vertices.close(close_polygon); + draw_vars dv; + const vertex_storage_type::value_type* v; + int x1; + int y1; + int x2; + int y2; + int lprev; + + if(close_polygon) + { + if(m_src_vertices.size() >= 3) + { + dv.idx = 2; + + v = &m_src_vertices[m_src_vertices.size() - 1]; + x1 = v->x; + y1 = v->y; + lprev = v->len; + + v = &m_src_vertices[0]; + x2 = v->x; + y2 = v->y; + dv.lcurr = v->len; + line_parameters prev(x1, y1, x2, y2, lprev); + + v = &m_src_vertices[1]; + dv.x1 = v->x; + dv.y1 = v->y; + dv.lnext = v->len; + dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr); + + v = &m_src_vertices[dv.idx]; + dv.x2 = v->x; + dv.y2 = v->y; + dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); + + dv.xb1 = 0; + dv.yb1 = 0; + dv.xb2 = 0; + dv.yb2 = 0; + + if(m_accurate_join) + { + dv.flags = 0; + } + else + { + dv.flags = + (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | + ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); + } + + if((dv.flags & 1) == 0) + { + bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); + } + + if((dv.flags & 2) == 0) + { + bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + } + draw(dv, 0, m_src_vertices.size()); + } + } + else + { + switch(m_src_vertices.size()) + { + case 0: + case 1: + break; + + case 2: + { + v = &m_src_vertices[0]; + x1 = v->x; + y1 = v->y; + lprev = v->len; + v = &m_src_vertices[1]; + x2 = v->x; + y2 = v->y; + 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.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)); + } + } + break; + + case 3: + { + int x3, y3; + int lnext; + v = &m_src_vertices[0]; + x1 = v->x; + y1 = v->y; + lprev = v->len; + v = &m_src_vertices[1]; + x2 = v->x; + y2 = v->y; + lnext = v->len; + v = &m_src_vertices[2]; + x3 = v->x; + 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.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)); + } + } + break; + + default: + { + dv.idx = 3; + + v = &m_src_vertices[0]; + x1 = v->x; + y1 = v->y; + lprev = v->len; + + v = &m_src_vertices[1]; + x2 = v->x; + y2 = v->y; + dv.lcurr = v->len; + line_parameters prev(x1, y1, x2, y2, lprev); + + v = &m_src_vertices[2]; + dv.x1 = v->x; + dv.y1 = v->y; + dv.lnext = v->len; + dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr); + + v = &m_src_vertices[dv.idx]; + dv.x2 = v->x; + dv.y2 = v->y; + dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); + + dv.xb1 = 0; + dv.yb1 = 0; + dv.xb2 = 0; + dv.yb2 = 0; + + if(m_accurate_join) + { + dv.flags = 0; + } + else + { + dv.flags = + (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | + ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); + } + + if((dv.flags & 1) == 0) + { + bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); + m_ren.line3(prev, + x1 + (y2 - y1), + y1 - (x2 - x1), + dv.xb1, + dv.yb1); + } + else + { + m_ren.line1(prev, + x1 + (y2 - y1), + y1 - (x2 - x1)); + } + if(m_round_cap) + { + m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + } + if((dv.flags & 2) == 0) + { + bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + } + + draw(dv, 1, m_src_vertices.size() - 2); + + 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)); + } + else + { + 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)); + } + + } + break; + } + } + m_src_vertices.remove_all(); + } + + +} + + +#endif + diff --git a/agg/inc/agg_rasterizer_scanline_aa.h b/agg/inc/agg_rasterizer_scanline_aa.h new file mode 100755 index 000000000000..03be55dcc62a --- /dev/null +++ b/agg/inc/agg_rasterizer_scanline_aa.h @@ -0,0 +1,743 @@ +//---------------------------------------------------------------------------- +// 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 rasterizer_scanline_aa +// +// +//---------------------------------------------------------------------------- +#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_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 + // intentionally in order to avoid extra overhead when allocating an + // 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); + }; + + + //--------------------------------------------------------------outline_aa + // An internal class that implements the main rasterization algorithm. + // Used in the rasterizer. Should not be used direcly. + class outline_aa + { + enum + { + 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; + }; + + + //----------------------------------------------------------filling_rule_e + enum filling_rule_e + { + fill_non_zero, + fill_even_odd + }; + + + //==================================================rasterizer_scanline_aa + // 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 + // used in the following way: + // + // 1. filling_rule(filling_rule_e ft) - optional. + // + // 2. gamma() - optional. + // + // 3. reset() + // + // 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create + // more than one contour, but each contour must consist of at least 3 + // vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3); + // is the absolute minimum of vertices that define a triangle. + // The algorithm does not check either the number of vertices nor + // coincidence of their coordinates, but in the worst case it just + // won't draw anything. + // The orger of the vertices (clockwise or counterclockwise) + // is important when using the non-zero filling rule (fill_non_zero). + // In this case the vertex order of all the contours must be the same + // if you want your intersecting polygons to be without "holes". + // You actually can use different vertices order. If the contours do not + // intersect each other the order is not important anyway. If they do, + // contours with the same vertex order will be rendered without "holes" + // while the intersecting contours with different orders will have "holes". + // + // filling_rule() and gamma() can be called anytime before "sweeping". + //------------------------------------------------------------------------ + template<unsigned XScale=1, unsigned AA_Shift=8> class rasterizer_scanline_aa + { + enum status + { + status_initial, + status_line_to, + status_closed + }; + + struct iterator + { + const cell_aa* const* cells; + int cover; + int last_y; + }; + + public: + enum + { + aa_shift = AA_Shift, + aa_num = 1 << aa_shift, + aa_mask = aa_num - 1, + aa_2num = aa_num * 2, + aa_2mask = aa_2num - 1 + }; + + //-------------------------------------------------------------------- + rasterizer_scanline_aa() : + m_filling_rule(fill_non_zero), + m_clipped_start_x(0), + m_clipped_start_y(0), + 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) + { + int i; + for(i = 0; i < aa_num; i++) m_gamma[i] = i; + } + + //-------------------------------------------------------------------- + template<class GammaF> + rasterizer_scanline_aa(const GammaF& gamma_function) : + m_filling_rule(fill_non_zero), + m_clipped_start_x(0), + m_clipped_start_y(0), + 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) + { + 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(); + + //-------------------------------------------------------------------- + template<class GammaF> void gamma(const GammaF& gamma_function) + { + int i; + for(i = 0; i < aa_num; i++) + { + m_gamma[i] = int(floor(gamma_function(double(i) / aa_mask) * aa_mask + 0.5)); + } + } + + //-------------------------------------------------------------------- + unsigned apply_gamma(unsigned cover) const + { + return m_gamma[cover]; + } + + //-------------------------------------------------------------------- + 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); + + //-------------------------------------------------------------------- + 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(); } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned calculate_alpha(int area) const + { + int cover = area >> (poly_base_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_2num - cover; + } + } + if(cover > aa_mask) cover = aa_mask; + return m_gamma[cover]; + } + + //-------------------------------------------------------------------- + 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; + + for(;;) + { + int coord = cur_cell->packed_coord; + int area = cur_cell->area; + int last_x = cur_cell->x; + + m_iterator.cover += cur_cell->cover; + + //accumulate all cells with the same coordinates + for(; (cur_cell = *m_iterator.cells) != 0; ++m_iterator.cells) + { + if(cur_cell->packed_coord != coord) break; + area += cur_cell->area; + m_iterator.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); + if(alpha) + { + sl.add_cell(last_x, alpha); + } + ++last_x; + } + + if(cur_cell->x > last_x) + { + alpha = calculate_alpha(m_iterator.cover << (poly_base_shift + 1)); + if(alpha) + { + sl.add_span(last_x, cur_cell->x - last_x, alpha); + } + } + } + if(sl.num_spans()) + { + sl.finalize(m_iterator.last_y); + break; + } + } + 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); + + private: + outline_aa m_outline; + int m_gamma[aa_num]; + 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; + unsigned m_status; + rect m_clip_box; + bool m_clipping; + iterator m_iterator; + }; + + + + + + + + + + + //------------------------------------------------------------------------ + template<unsigned XScale, unsigned AA_Shift> + void rasterizer_scanline_aa<XScale, AA_Shift>::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) + { + 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) + { + reset(); + m_clip_box = rect(poly_coord(x1), poly_coord(y1), + poly_coord(x2), poly_coord(y2)); + m_clip_box.normalize(); + m_clipping = true; + } + + //------------------------------------------------------------------------ + template<unsigned XScale, unsigned AA_Shift> + void rasterizer_scanline_aa<XScale, AA_Shift>::reset_clipping() + { + reset(); + m_clipping = false; + } + + + + //------------------------------------------------------------------------ + template<unsigned XScale, unsigned AA_Shift> + void rasterizer_scanline_aa<XScale, AA_Shift>::move_to_no_clip(int x, int y) + { + if(m_status == status_line_to) + { + close_polygon_no_clip(); + } + 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) + { + if(m_status != status_initial) + { + m_outline.line_to(x * XScale, y); + m_status = status_line_to; + } + } + + + //------------------------------------------------------------------------ + template<unsigned XScale, unsigned AA_Shift> + void rasterizer_scanline_aa<XScale, AA_Shift>::close_polygon_no_clip() + { + if(m_status == status_line_to) + { + m_outline.line_to(m_clipped_start_x * XScale, m_clipped_start_y); + m_status = status_closed; + } + } + + + //------------------------------------------------------------------------ + template<unsigned XScale, unsigned AA_Shift> + void rasterizer_scanline_aa<XScale, AA_Shift>::clip_segment(int x, int 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; + } + + + + //------------------------------------------------------------------------ + template<unsigned XScale, unsigned AA_Shift> + void rasterizer_scanline_aa<XScale, AA_Shift>::add_vertex(double x, double y, unsigned cmd) + { + 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)); + } + } + } + } + + + + //------------------------------------------------------------------------ + template<unsigned XScale, unsigned AA_Shift> + void rasterizer_scanline_aa<XScale, AA_Shift>::move_to(int x, int y) + { + if(m_clipping) + { + 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); + } + } + else + { + 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); + } + else + { + line_to_no_clip(x, y); + } + } + + //------------------------------------------------------------------------ + template<unsigned XScale, unsigned AA_Shift> + void rasterizer_scanline_aa<XScale, AA_Shift>::close_polygon() + { + if(m_clipping) + { + clip_segment(m_start_x, m_start_y); + } + close_polygon_no_clip(); + } + + //------------------------------------------------------------------------ + template<unsigned XScale, unsigned AA_Shift> + void rasterizer_scanline_aa<XScale, AA_Shift>::move_to_d(double x, double y) + { + move_to(poly_coord(x), poly_coord(y)); + } + + //------------------------------------------------------------------------ + template<unsigned XScale, unsigned AA_Shift> + void rasterizer_scanline_aa<XScale, AA_Shift>::line_to_d(double x, double y) + { + line_to(poly_coord(x), poly_coord(y)); + } + + + //------------------------------------------------------------------------ + template<unsigned XScale, unsigned AA_Shift> + bool rasterizer_scanline_aa<XScale, AA_Shift>::hit_test(int tx, int ty) + { + 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(;;) + { + int alpha; + int coord = cur_cell->packed_coord; + int x = cur_cell->x; + int y = cur_cell->y; + + if(y > ty) return false; + + 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; + } + + if(area) + { + alpha = calculate_alpha((cover << (poly_base_shift + 1)) - area); + if(alpha) + { + if(tx == x && ty == y) return true; + } + x++; + } + + 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; + } + +} + + + +#endif + diff --git a/agg/inc/agg_render_scanlines.h b/agg/inc/agg_render_scanlines.h new file mode 100755 index 000000000000..60ddecf5c2d6 --- /dev/null +++ b/agg/inc/agg_render_scanlines.h @@ -0,0 +1,66 @@ +//---------------------------------------------------------------------------- +// 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 new file mode 100755 index 000000000000..1ef44fecc6d2 --- /dev/null +++ b/agg/inc/agg_renderer_base.h @@ -0,0 +1,618 @@ +//---------------------------------------------------------------------------- +// 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 renderer_base +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_BASE_INCLUDED +#define AGG_RENDERER_BASE_INCLUDED + +#include "agg_basics.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + + //-----------------------------------------------------------renderer_base + template<class PixelFormat> class renderer_base + { + public: + typedef PixelFormat pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + + //-------------------------------------------------------------------- + renderer_base(pixfmt_type& _ren) : + m_ren(&_ren), + m_clip_box(0, 0, _ren.width() - 1, _ren.height() - 1) + { + } + + //-------------------------------------------------------------------- + const pixfmt_type& ren() const { return *m_ren; } + pixfmt_type& ren() { return *m_ren; } + + //-------------------------------------------------------------------- + unsigned width() const { return m_ren->width(); } + unsigned height() const { return m_ren->height(); } + + //-------------------------------------------------------------------- + bool clip_box(int x1, int y1, int x2, int y2) + { + rect cb(x1, y1, x2, y2); + cb.normalize(); + if(cb.clip(rect(0, 0, width() - 1, height() - 1))) + { + m_clip_box = cb; + return true; + } + m_clip_box.x1 = 1; + m_clip_box.y1 = 1; + m_clip_box.x2 = 0; + m_clip_box.y2 = 0; + return false; + } + + //-------------------------------------------------------------------- + void reset_clipping(bool visibility) + { + if(visibility) + { + m_clip_box.x1 = 0; + m_clip_box.y1 = 0; + m_clip_box.x2 = width() - 1; + m_clip_box.y2 = height() - 1; + } + else + { + m_clip_box.x1 = 1; + m_clip_box.y1 = 1; + m_clip_box.x2 = 0; + m_clip_box.y2 = 0; + } + } + + //-------------------------------------------------------------------- + void clip_box_naked(int x1, int y1, int x2, int y2) + { + m_clip_box.x1 = x1; + m_clip_box.y1 = y1; + m_clip_box.x2 = x2; + m_clip_box.y2 = y2; + } + + //-------------------------------------------------------------------- + bool inbox(int x, int y) const + { + return x >= m_clip_box.x1 && y >= m_clip_box.y1 && + x <= m_clip_box.x2 && y <= m_clip_box.y2; + } + + //-------------------------------------------------------------------- + void first_clip_box() {} + bool next_clip_box() { return false; } + + //-------------------------------------------------------------------- + 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; } + + //-------------------------------------------------------------------- + void clear(const color_type& c) + { + unsigned y; + if(width()) + { + for(y = 0; y < height(); y++) + { + m_ren->copy_hline(0, y, width(), c); + } + } + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + if(inbox(x, y)) + { + m_ren->copy_pixel(x, y, c); + } + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, cover_type cover) + { + if(inbox(x, y)) + { + m_ren->blend_pixel(x, y, c, cover); + } + } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + return inbox(x, y) ? + m_ren->pixel(x, y) : + color_type::no_color(); + } + + //-------------------------------------------------------------------- + void copy_hline(int x1, int y, int x2, const color_type& c) + { + if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } + if(y > ymax()) return; + if(y < ymin()) return; + if(x1 > xmax()) return; + if(x2 < xmin()) return; + + if(x1 < xmin()) x1 = xmin(); + if(x2 > xmax()) x2 = xmax(); + + m_ren->copy_hline(x1, y, x2 - x1 + 1, c); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y1, int y2, const color_type& c) + { + if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } + if(x > xmax()) return; + if(x < xmin()) return; + if(y1 > ymax()) return; + if(y2 < ymin()) return; + + if(y1 < ymin()) y1 = ymin(); + if(y2 > ymax()) y2 = ymax(); + + m_ren->copy_vline(x, y1, y2 - y1 + 1, c); + } + + //-------------------------------------------------------------------- + void blend_hline(int x1, int y, int x2, + const color_type& c, cover_type cover) + { + if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } + if(y > ymax()) return; + if(y < ymin()) return; + if(x1 > xmax()) return; + if(x2 < xmin()) return; + + if(x1 < xmin()) x1 = xmin(); + if(x2 > xmax()) x2 = xmax(); + + m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y1, int y2, + const color_type& c, cover_type cover) + { + if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } + if(x > xmax()) return; + if(x < xmin()) return; + if(y1 > ymax()) return; + if(y2 < ymin()) return; + + if(y1 < ymin()) y1 = ymin(); + if(y2 > ymax()) y2 = ymax(); + + m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover); + } + + + //-------------------------------------------------------------------- + void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) + { + rect rc(x1, y1, x2, y2); + rc.normalize(); + if(rc.clip(clip_box())) + { + int y; + for(y = rc.y1; y <= rc.y2; y++) + { + m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c); + } + } + } + + //-------------------------------------------------------------------- + void blend_bar(int x1, int y1, int x2, int y2, + const color_type& c, cover_type cover) + { + rect rc(x1, y1, x2, y2); + rc.normalize(); + if(rc.clip(clip_box())) + { + int y; + for(y = rc.y1; y <= rc.y2; y++) + { + m_ren->blend_hline(rc.x1, + y, + unsigned(rc.x2 - rc.x1 + 1), + c, + cover); + } + } + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, int len, + const color_type& c, + const cover_type* covers) + { + if(y > ymax()) return; + if(y < ymin()) return; + + if(x < xmin()) + { + len -= xmin() - x; + if(len <= 0) return; + covers += xmin() - x; + x = xmin(); + } + if(x + len > xmax()) + { + len = xmax() - x + 1; + if(len <= 0) return; + } + m_ren->blend_solid_hspan(x, y, len, c, covers); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, int len, + const color_type& c, + const cover_type* covers) + { + if(x > xmax()) return; + if(x < xmin()) return; + + if(y < ymin()) + { + len -= ymin() - y; + if(len <= 0) return; + covers += ymin() - y; + y = ymin(); + } + if(y + len > ymax()) + { + len = ymax() - y + 1; + if(len <= 0) return; + } + 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) + { + if(y > ymax()) return; + if(y < ymin()) return; + + if(x < xmin()) + { + int d = xmin() - x; + len -= d; + if(len <= 0) return; + if(covers) covers += d; + colors += d; + x = xmin(); + } + if(x + len > xmax()) + { + len = xmax() - x + 1; + if(len <= 0) return; + } + m_ren->blend_color_hspan(x, y, len, colors, covers, cover); + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + if(x > xmax()) return; + if(x < xmin()) return; + + if(y < ymin()) + { + int d = ymin() - y; + len -= d; + if(len <= 0) return; + if(covers) covers += d; + colors += d; + y = ymin(); + } + if(y + len > ymax()) + { + len = ymax() - y + 1; + if(len <= 0) return; + } + m_ren->blend_color_vspan(x, y, len, colors, covers, cover); + } + + + //-------------------------------------------------------------------- + void blend_opaque_color_hspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + if(y > ymax()) return; + if(y < ymin()) return; + + if(x < xmin()) + { + int d = xmin() - x; + len -= d; + if(len <= 0) return; + if(covers) covers += d; + colors += d; + x = xmin(); + } + if(x + len > xmax()) + { + len = xmax() - x + 1; + if(len <= 0) return; + } + m_ren->blend_opaque_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) + { + if(x > xmax()) return; + if(x < xmin()) return; + + if(y < ymin()) + { + int d = ymin() - y; + len -= d; + if(len <= 0) return; + if(covers) covers += d; + colors += d; + y = ymin(); + } + if(y + len > ymax()) + { + 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) + { + 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(); + ++cb.x2; + ++cb.y2; + + if(src.x1 < 0) + { + dst.x1 -= src.x1; + src.x1 = 0; + } + if(src.y1 < 0) + { + dst.y1 -= src.y1; + src.y1 = 0; + } + + if(src.x2 > wsrc) src.x2 = wsrc; + if(src.y2 > hsrc) src.y2 = hsrc; + + if(dst.x1 < cb.x1) + { + src.x1 += cb.x1 - dst.x1; + dst.x1 = cb.x1; + } + if(dst.y1 < cb.y1) + { + src.y1 += cb.y1 - dst.y1; + dst.y1 = cb.y1; + } + + if(dst.x2 > cb.x2) dst.x2 = cb.x2; + if(dst.y2 > cb.y2) dst.y2 = cb.y2; + + rc.x2 = dst.x2 - dst.x1; + rc.y2 = dst.y2 - dst.y1; + + if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1; + if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1; + return rc; + } + + + //-------------------------------------------------------------------- + void copy_from(const rendering_buffer& src, + const rect* rect_src_ptr = 0, + int dx = 0, + int dy = 0) + { + rect 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 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()); + + 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) + { + m_ren->copy_from(src, + rdst.x1, rdst.y1, + rsrc.x1, rsrc.y1, + rc.x2); + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from(const SrcPixelFormatRenderer& src, + const rect* rect_src_ptr = 0, + int dx = 0, + int dy = 0) + { + rect 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 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()); + + 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 span = src.span(rsrc.x1, rsrc.y1); + if(span.ptr) + { + int x1src = rsrc.x1; + int x1dst = rdst.x1; + int len = rc.x2; + if(span.x1 > x1src) + { + x1dst += span.x1 - x1src; + len -= span.x1 - x1src; + x1src = span.x1; + } + if(len > 0) + { + if(x1src + len-1 > span.x2) + { + len -= x1src + len - span.x2 - 1; + } + if(len > 0) + { + m_ren->blend_from(src, span.ptr, + x1dst, rdst.y1, + x1src, rsrc.y1, + len); + } + } + } + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + + + private: + pixfmt_type* m_ren; + rect m_clip_box; + }; + + +} + +#endif diff --git a/agg/inc/agg_renderer_markers.h b/agg/inc/agg_renderer_markers.h new file mode 100755 index 000000000000..ff47995554d9 --- /dev/null +++ b/agg/inc/agg_renderer_markers.h @@ -0,0 +1,707 @@ +//---------------------------------------------------------------------------- +// 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 renderer_markers +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_MARKERS_INCLUDED +#define AGG_RENDERER_MARKERS_INCLUDED + +#include "agg_basics.h" +#include "agg_renderer_primitives.h" + +namespace agg +{ + + //---------------------------------------------------------------marker_e + enum marker_e + { + marker_square, + marker_diamond, + marker_circle, + marker_crossed_circle, + marker_semiellipse_left, + marker_semiellipse_right, + marker_semiellipse_up, + marker_semiellipse_down, + marker_triangle_left, + marker_triangle_right, + marker_triangle_up, + marker_triangle_down, + marker_four_rays, + marker_cross, + marker_x, + marker_dash, + marker_dot, + marker_pixel, + + end_of_markers + }; + + + + //--------------------------------------------------------renderer_markers + template<class BaseRenderer> class renderer_markers : + public renderer_primitives<BaseRenderer> + { + public: + typedef renderer_primitives<BaseRenderer> base_type; + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + 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); + return rc.clip(base_type::ren().bounding_clip_box()); + } + + //-------------------------------------------------------------------- + void square(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) base_type::outlined_rectangle(x-r, y-r, x+r, y+r); + else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + //-------------------------------------------------------------------- + void diamond(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + do + { + base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); + base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + ++dx; + } + while(dy <= 0); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + //-------------------------------------------------------------------- + void circle(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) base_type::outlined_ellipse(x, y, r, r); + else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + + + //-------------------------------------------------------------------- + void crossed_circle(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + base_type::outlined_ellipse(x, y, r, r); + int r6 = r + (r >> 1); + if(r <= 2) r6++; + r >>= 1; + base_type::ren().blend_hline(x-r6, y, x-r, base_type::line_color(), cover_full); + base_type::ren().blend_hline(x+r, y, x+r6, base_type::line_color(), cover_full); + base_type::ren().blend_vline(x, y-r6, y-r, base_type::line_color(), cover_full); + base_type::ren().blend_vline(x, y+r, y+r6, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //------------------------------------------------------------------------ + void semiellipse_left(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int r8 = r * 4 / 5; + int dy = -r; + int dx = 0; + ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); + do + { + dx += ei.dx(); + dy += ei.dy(); + + base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full); + + if(ei.dy() && dx) + { + base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++ei; + } + while(dy < r8); + base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void semiellipse_right(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int r8 = r * 4 / 5; + int dy = -r; + int dx = 0; + ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); + do + { + dx += ei.dx(); + dy += ei.dy(); + + base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full); + + if(ei.dy() && dx) + { + base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++ei; + } + while(dy < r8); + base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void semiellipse_up(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int r8 = r * 4 / 5; + int dy = -r; + int dx = 0; + ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); + do + { + dx += ei.dx(); + dy += ei.dy(); + + base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); + + if(ei.dy() && dx) + { + base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++ei; + } + while(dy < r8); + base_type::ren().blend_hline(x-dx, y-dy-1, x+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void semiellipse_down(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int r8 = r * 4 / 5; + int dy = -r; + int dx = 0; + ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); + do + { + dx += ei.dx(); + dy += ei.dy(); + + base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); + + if(ei.dy() && dx) + { + base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++ei; + } + while(dy < r8); + base_type::ren().blend_hline(x-dx, y+dy+1, x+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void triangle_left(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r6 = r * 3 / 5; + do + { + base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy < r6); + base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void triangle_right(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r6 = r * 3 / 5; + do + { + base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy < r6); + base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void triangle_up(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r6 = r * 3 / 5; + do + { + base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy < r6); + base_type::ren().blend_hline(x-dx, y-dy, x+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void triangle_down(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r6 = r * 3 / 5; + do + { + base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy < r6); + base_type::ren().blend_hline(x-dx, y+dy, x+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void four_rays(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r3 = -(r / 3); + do + { + base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); + base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); + base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy <= r3); + base_type::solid_rectangle(x+r3+1, y+r3+1, x-r3-1, y-r3-1); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void cross(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + base_type::ren().blend_vline(x, y-r, y+r, base_type::line_color(), cover_full); + base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void xing(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r * 7 / 10; + do + { + base_type::ren().blend_pixel(x + dy, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y - dy, base_type::line_color(), cover_full); + ++dy; + } + while(dy < 0); + } + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + + //-------------------------------------------------------------------- + void dash(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full); + else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + + //-------------------------------------------------------------------- + void dot(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) base_type::solid_ellipse(x, y, r, r); + else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + //-------------------------------------------------------------------- + void pixel(int x, int y, int) + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + + //-------------------------------------------------------------------- + void marker(int x, int y, int r, marker_e type) + { + switch(type) + { + case marker_square: square(x, y, r); break; + case marker_diamond: diamond(x, y, r); break; + case marker_circle: circle(x, y, r); break; + case marker_crossed_circle: crossed_circle(x, y, r); break; + case marker_semiellipse_left: semiellipse_left(x, y, r); break; + case marker_semiellipse_right: semiellipse_right(x, y, r); break; + case marker_semiellipse_up: semiellipse_up(x, y, r); break; + case marker_semiellipse_down: semiellipse_down(x, y, r); break; + case marker_triangle_left: triangle_left(x, y, r); break; + case marker_triangle_right: triangle_right(x, y, r); break; + case marker_triangle_up: triangle_up(x, y, r); break; + case marker_triangle_down: triangle_down(x, y, r); break; + case marker_four_rays: four_rays(x, y, r); break; + case marker_cross: cross(x, y, r); break; + case marker_x: xing(x, y, r); break; + case marker_dash: dash(x, y, r); break; + case marker_dot: dot(x, y, r); break; + case marker_pixel: pixel(x, y, r); break; + } + } + + + //-------------------------------------------------------------------- + template<class T> + void markers(int n, const T* x, const T* y, T r, marker_e type) + { + if(n <= 0) return; + if(r == 0) + { + do + { + base_type::ren().blend_pixel(int(*x), int(*y), base_type::fill_color(), cover_full); + ++x; + ++y; + } + while(--n); + return; + } + + switch(type) + { + case marker_square: do { square (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_diamond: do { diamond (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_circle: do { circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_four_rays: do { four_rays (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_cross: do { cross (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_x: do { xing (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_dash: do { dash (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_dot: do { dot (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_pixel: do { pixel (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + } + } + + //-------------------------------------------------------------------- + template<class T> + void markers(int n, const T* x, const T* y, const T* r, marker_e type) + { + if(n <= 0) return; + switch(type) + { + case marker_square: do { square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_diamond: do { diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_circle: do { circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_four_rays: do { four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_cross: do { cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_x: do { xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_dash: do { dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_dot: do { dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_pixel: do { pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + } + } + + //-------------------------------------------------------------------- + template<class T> + void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, marker_e type) + { + if(n <= 0) return; + switch(type) + { + case marker_square: do { base_type::fill_color(*fc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_diamond: do { base_type::fill_color(*fc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_circle: do { base_type::fill_color(*fc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_crossed_circle: do { base_type::fill_color(*fc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_semiellipse_left: do { base_type::fill_color(*fc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_semiellipse_right: do { base_type::fill_color(*fc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_semiellipse_up: do { base_type::fill_color(*fc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_semiellipse_down: do { base_type::fill_color(*fc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_triangle_left: do { base_type::fill_color(*fc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_triangle_right: do { base_type::fill_color(*fc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_triangle_up: do { base_type::fill_color(*fc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_triangle_down: do { base_type::fill_color(*fc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_four_rays: do { base_type::fill_color(*fc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_cross: do { base_type::fill_color(*fc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_x: do { base_type::fill_color(*fc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_dash: do { base_type::fill_color(*fc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_dot: do { base_type::fill_color(*fc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_pixel: do { base_type::fill_color(*fc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + } + } + + //-------------------------------------------------------------------- + template<class T> + void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, const color_type* lc, marker_e type) + { + if(n <= 0) return; + switch(type) + { + case marker_square: do { base_type::fill_color(*fc); base_type::line_color(*lc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_diamond: do { base_type::fill_color(*fc); base_type::line_color(*lc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_crossed_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_semiellipse_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_semiellipse_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_semiellipse_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_semiellipse_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_triangle_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_triangle_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_triangle_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_triangle_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_four_rays: do { base_type::fill_color(*fc); base_type::line_color(*lc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_cross: do { base_type::fill_color(*fc); base_type::line_color(*lc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_x: do { base_type::fill_color(*fc); base_type::line_color(*lc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_dash: do { base_type::fill_color(*fc); base_type::line_color(*lc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_dot: do { base_type::fill_color(*fc); base_type::line_color(*lc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_pixel: do { base_type::fill_color(*fc); base_type::line_color(*lc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + } + } + }; + +} + +#endif diff --git a/agg/inc/agg_renderer_mclip.h b/agg/inc/agg_renderer_mclip.h new file mode 100755 index 000000000000..dc758b9ea72d --- /dev/null +++ b/agg/inc/agg_renderer_mclip.h @@ -0,0 +1,383 @@ +//---------------------------------------------------------------------------- +// 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 renderer_mclip +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_MCLIP_INCLUDED +#define AGG_RENDERER_MCLIP_INCLUDED + +#include "agg_basics.h" +#include "agg_array.h" +#include "agg_renderer_base.h" + +namespace agg +{ + + //----------------------------------------------------------renderer_mclip + template<class PixelFormat> class renderer_mclip + { + public: + typedef PixelFormat pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef renderer_base<pixfmt_type> base_ren_type; + + //-------------------------------------------------------------------- + renderer_mclip(pixfmt_type& ren) : + m_ren(ren), + m_curr_cb(0), + m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax()) + { + } + + //-------------------------------------------------------------------- + const pixfmt_type& ren() const { return m_ren.ren(); } + pixfmt_type& ren() { return m_ren.ren(); } + + //-------------------------------------------------------------------- + unsigned width() const { return m_ren.width(); } + 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& 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() + { + m_curr_cb = 0; + if(m_clip.size()) + { + const rect& cb = m_clip[0]; + m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); + } + } + + //-------------------------------------------------------------------- + bool next_clip_box() + { + if(++m_curr_cb < m_clip.size()) + { + const rect& cb = m_clip[m_curr_cb]; + m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + void reset_clipping(bool visibility) + { + m_ren.reset_clipping(visibility); + m_clip.remove_all(); + m_curr_cb = 0; + m_bounds = m_ren.clip_box(); + } + + //-------------------------------------------------------------------- + void add_clip_box(int x1, int y1, int x2, int y2) + { + rect cb(x1, y1, x2, y2); + cb.normalize(); + if(cb.clip(rect(0, 0, width() - 1, height() - 1))) + { + m_clip.add(cb); + if(cb.x1 < m_bounds.x1) m_bounds.x1 = cb.x1; + if(cb.y1 < m_bounds.y1) m_bounds.y1 = cb.y1; + if(cb.x2 > m_bounds.x2) m_bounds.x2 = cb.x2; + if(cb.y2 > m_bounds.y2) m_bounds.y2 = cb.y2; + } + } + + //-------------------------------------------------------------------- + void clear(const color_type& c) + { + m_ren.clear(c); + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + first_clip_box(); + do + { + if(m_ren.inbox(x, y)) + { + m_ren.ren().copy_pixel(x, y, c); + break; + } + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + if(m_ren.inbox(x, y)) + { + m_ren.ren().blend_pixel(x, y, c, cover); + break; + } + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + first_clip_box(); + do + { + if(m_ren.inbox(x, y)) + { + return m_ren.ren().pixel(x, y); + } + } + while(next_clip_box()); + return color_type::no_color(); + } + + //-------------------------------------------------------------------- + void copy_hline(int x1, int y, int x2, const color_type& c) + { + first_clip_box(); + do + { + m_ren.copy_hline(x1, y, x2, c); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y1, int y2, const color_type& c) + { + first_clip_box(); + do + { + m_ren.copy_vline(x, y1, y2, c); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_hline(int x1, int y, int x2, + const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + m_ren.blend_hline(x1, y, x2, c, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y1, int y2, + const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + m_ren.blend_vline(x, y1, y2, c, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) + { + first_clip_box(); + do + { + m_ren.copy_bar(x1, y1, x2, y2, c); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_bar(int x1, int y1, int x2, int y2, + const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + m_ren.blend_bar(x1, y1, x2, y2, c, cover); + } + while(next_clip_box()); + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, int len, + const color_type& c, const cover_type* covers) + { + first_clip_box(); + do + { + m_ren.blend_solid_hspan(x, y, len, c, covers); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, int len, + const color_type& c, const cover_type* covers) + { + first_clip_box(); + do + { + m_ren.blend_solid_vspan(x, y, len, c, covers); + } + 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) + { + first_clip_box(); + do + { + m_ren.blend_color_hspan(x, y, len, colors, covers, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + 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_color_hspan(x, y, len, colors, covers, cover); + } + 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) + { + first_clip_box(); + do + { + m_ren.blend_opaque_color_hspan(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) + { + first_clip_box(); + do + { + m_ren.blend_opaque_color_hspan(x, y, len, colors, covers, cover); + } + 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) + { + first_clip_box(); + do + { + m_ren.copy_from(from, rc, x_to, y_to); + } + 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; + }; + + +} + +#endif diff --git a/agg/inc/agg_renderer_outline_aa.h b/agg/inc/agg_renderer_outline_aa.h new file mode 100755 index 000000000000..d2f9484c5a1d --- /dev/null +++ b/agg/inc/agg_renderer_outline_aa.h @@ -0,0 +1,1545 @@ +//---------------------------------------------------------------------------- +// 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_RENDERER_OUTLINE_AA_INCLUDED +#define AGG_RENDERER_OUTLINE_AA_INCLUDED + +#include "agg_basics.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" + +namespace agg +{ + + //===================================================distance_interpolator0 + class distance_interpolator0 + { + public: + //--------------------------------------------------------------------- + distance_interpolator0() {} + 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_dx <<= line_mr_subpixel_shift; + m_dy <<= line_mr_subpixel_shift; + } + + //--------------------------------------------------------------------- + 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; + } + + //--------------------------------------------------------------------- + void inc_y(int _dx) + { + m_dist -= m_dx; + if(_dx > 0) m_dist += m_dy; + if(_dx < 0) m_dist -= m_dy; + } + + void dec_y(int _dx) + //--------------------------------------------------------------------- + { + m_dist += m_dx; + if(_dx > 0) m_dist += m_dy; + if(_dx < 0) m_dist -= m_dy; + } + + //--------------------------------------------------------------------- + int dist() const { return m_dist; } + int dx() const { return m_dx; } + int dy() const { return m_dy; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dist; + }; + + + + //===================================================distance_interpolator1 + class distance_interpolator1 + { + public: + //--------------------------------------------------------------------- + distance_interpolator1() {} + 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_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + } + + //--------------------------------------------------------------------- + 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; + } + + //--------------------------------------------------------------------- + void inc_y(int _dx) + { + m_dist -= m_dx; + if(_dx > 0) m_dist += m_dy; + if(_dx < 0) m_dist -= m_dy; + } + + void dec_y(int _dx) + //--------------------------------------------------------------------- + { + m_dist += m_dx; + if(_dx > 0) m_dist += m_dy; + if(_dx < 0) m_dist -= m_dy; + } + + //--------------------------------------------------------------------- + int dist() const { return m_dist; } + int dx() const { return m_dx; } + int dy() const { return m_dy; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dist; + }; + + + + + + //===================================================distance_interpolator2 + class distance_interpolator2 + { + public: + //--------------------------------------------------------------------- + distance_interpolator2() {} + distance_interpolator2(int x1, int y1, int x2, int y2, + int sx, int sy, int x, int y) : + m_dx(x2 - x1), + m_dy(y2 - y1), + 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_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_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + m_dx_start <<= line_mr_subpixel_shift; + m_dy_start <<= line_mr_subpixel_shift; + } + + distance_interpolator2(int x1, int y1, int x2, int y2, + int ex, int ey, int x, int y, int) : + m_dx(x2 - x1), + m_dy(y2 - y1), + 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_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_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + m_dx_start <<= line_mr_subpixel_shift; + m_dy_start <<= line_mr_subpixel_shift; + } + + + //--------------------------------------------------------------------- + void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; } + void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; } + void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; } + void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; } + + //--------------------------------------------------------------------- + void inc_x(int _dy) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + if(_dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + } + if(_dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + } + } + + //--------------------------------------------------------------------- + void dec_x(int _dy) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + if(_dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + } + if(_dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + } + } + + //--------------------------------------------------------------------- + void inc_y(int _dx) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + if(_dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + } + if(_dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + } + } + + //--------------------------------------------------------------------- + void dec_y(int _dx) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + if(_dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + } + if(_dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + } + } + + //--------------------------------------------------------------------- + int dist() const { return m_dist; } + int dist_start() const { return m_dist_start; } + int dist_end() const { return m_dist_start; } + + //--------------------------------------------------------------------- + int dx() const { return m_dx; } + int dy() const { return m_dy; } + int dx_start() const { return m_dx_start; } + int dy_start() const { return m_dy_start; } + int dx_end() const { return m_dx_start; } + int dy_end() const { return m_dy_start; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dx_start; + int m_dy_start; + + int m_dist; + int m_dist_start; + }; + + + + + + //===================================================distance_interpolator3 + class distance_interpolator3 + { + public: + //--------------------------------------------------------------------- + distance_interpolator3() {} + distance_interpolator3(int x1, int y1, int x2, int y2, + int sx, int sy, int ex, int ey, + int x, int y) : + m_dx(x2 - x1), + m_dy(y2 - y1), + m_dx_start(line_mr(sx) - line_mr(x1)), + m_dy_start(line_mr(sy) - line_mr(y1)), + 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_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_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_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + m_dx_start <<= line_mr_subpixel_shift; + m_dy_start <<= line_mr_subpixel_shift; + m_dx_end <<= line_mr_subpixel_shift; + m_dy_end <<= line_mr_subpixel_shift; + } + + //--------------------------------------------------------------------- + void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; } + void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; } + void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; } + void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; } + + //--------------------------------------------------------------------- + void inc_x(int _dy) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_end += m_dy_end; + if(_dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_end -= m_dx_end; + } + if(_dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_end += m_dx_end; + } + } + + //--------------------------------------------------------------------- + void dec_x(int _dy) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_end -= m_dy_end; + if(_dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_end -= m_dx_end; + } + if(_dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_end += m_dx_end; + } + } + + //--------------------------------------------------------------------- + void inc_y(int _dx) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_end -= m_dx_end; + if(_dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_end += m_dy_end; + } + if(_dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_end -= m_dy_end; + } + } + + //--------------------------------------------------------------------- + void dec_y(int _dx) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_end += m_dx_end; + if(_dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_end += m_dy_end; + } + if(_dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_end -= m_dy_end; + } + } + + //--------------------------------------------------------------------- + int dist() const { return m_dist; } + int dist_start() const { return m_dist_start; } + int dist_end() const { return m_dist_end; } + + //--------------------------------------------------------------------- + int dx() const { return m_dx; } + int dy() const { return m_dy; } + int dx_start() const { return m_dx_start; } + int dy_start() const { return m_dy_start; } + int dx_end() const { return m_dx_end; } + int dy_end() const { return m_dy_end; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dx_start; + int m_dy_start; + int m_dx_end; + int m_dy_end; + + int m_dist; + int m_dist_start; + int m_dist_end; + }; + + + + + + //================================================line_interpolator_aa_base + template<class Renderer> class line_interpolator_aa_base + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + + //--------------------------------------------------------------------- + enum + { + max_half_width = 64 + }; + + //--------------------------------------------------------------------- + line_interpolator_aa_base(renderer_type& ren, const line_parameters& lp) : + m_lp(&lp), + m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : + line_dbl_hr(lp.y2 - lp.y1), + lp.vertical ? abs(lp.y2 - lp.y1) : + abs(lp.x2 - lp.x1) + 1), + m_ren(ren), + m_len((lp.vertical == (lp.inc > 0)) ? -lp.len : lp.len), + m_x(lp.x1 >> line_subpixel_shift), + m_y(lp.y1 >> line_subpixel_shift), + m_old_x(m_x), + m_old_y(m_y), + 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_step(0) + { + agg::dda2_line_interpolator li(0, lp.vertical ? + (lp.dy << agg::line_subpixel_shift) : + (lp.dx << agg::line_subpixel_shift), + lp.len); + + unsigned i; + int stop = m_width + line_subpixel_size * 2; + for(i = 0; i < max_half_width; ++i) + { + m_dist[i] = li.y(); + if(m_dist[i] >= stop) break; + ++li; + } + m_dist[i++] = 0x7FFF0000; + } + + //--------------------------------------------------------------------- + template<class DI> int step_hor_base(DI& di) + { + ++m_li; + m_x += m_lp->inc; + m_y = (m_lp->y1 + m_li.y()) >> line_subpixel_shift; + + if(m_lp->inc > 0) di.inc_x(m_y - m_old_y); + else di.dec_x(m_y - m_old_y); + + m_old_y = m_y; + + return di.dist() / m_len; + } + + //--------------------------------------------------------------------- + template<class DI> int step_ver_base(DI& di) + { + ++m_li; + m_y += m_lp->inc; + m_x = (m_lp->x1 + m_li.y()) >> line_subpixel_shift; + + if(m_lp->inc > 0) di.inc_y(m_x - m_old_x); + else di.dec_y(m_x - m_old_x); + + m_old_x = m_x; + + return di.dist() / m_len; + } + + //--------------------------------------------------------------------- + bool vertical() const { return m_lp->vertical; } + int width() const { return m_width; } + int count() const { return m_count; } + + private: + line_interpolator_aa_base(const line_interpolator_aa_base<Renderer>&); + const line_interpolator_aa_base<Renderer>& + operator = (const line_interpolator_aa_base<Renderer>&); + + protected: + const line_parameters* m_lp; + dda2_line_interpolator m_li; + renderer_type& m_ren; + int m_len; + int m_x; + int m_y; + int m_old_x; + int m_old_y; + int m_count; + int m_width; + int m_max_extent; + int m_step; + int m_dist[max_half_width + 1]; + cover_type m_covers[max_half_width * 2 + 4]; + }; + + + + + + + + //====================================================line_interpolator_aa0 + template<class Renderer> class line_interpolator_aa0 : + public line_interpolator_aa_base<Renderer> + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + typedef line_interpolator_aa_base<Renderer> base_type; + + //--------------------------------------------------------------------- + line_interpolator_aa0(renderer_type& ren, const line_parameters& lp) : + line_interpolator_aa_base<Renderer>(ren, lp), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) + { + base_type::m_li.adjust_forward(); + } + + //--------------------------------------------------------------------- + bool step_hor() + { + int dist; + int dy; + int s1 = base_type::step_hor_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + *p1++ = (cover_type)base_type::m_ren.cover(s1); + + dy = 1; + while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) + { + *p1++ = (cover_type)base_type::m_ren.cover(dist); + ++dy; + } + + dy = 1; + while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) + { + *--p0 = (cover_type)base_type::m_ren.cover(dist); + ++dy; + } + base_type::m_ren.blend_solid_vspan(base_type::m_x, + base_type::m_y - dy + 1, + unsigned(p1 - p0), + p0); + return ++base_type::m_step < base_type::m_count; + } + + //--------------------------------------------------------------------- + bool step_ver() + { + int dist; + int dx; + int s1 = base_type::step_ver_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + *p1++ = (cover_type)base_type::m_ren.cover(s1); + + dx = 1; + while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) + { + *p1++ = (cover_type)base_type::m_ren.cover(dist); + ++dx; + } + + dx = 1; + while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) + { + *--p0 = (cover_type)base_type::m_ren.cover(dist); + ++dx; + } + base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, + base_type::m_y, + unsigned(p1 - p0), + p0); + return ++base_type::m_step < base_type::m_count; + } + + private: + line_interpolator_aa0(const line_interpolator_aa0<Renderer>&); + const line_interpolator_aa0<Renderer>& + operator = (const line_interpolator_aa0<Renderer>&); + + //--------------------------------------------------------------------- + distance_interpolator1 m_di; + }; + + + + + + + //====================================================line_interpolator_aa1 + template<class Renderer> class line_interpolator_aa1 : + public line_interpolator_aa_base<Renderer> + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + typedef line_interpolator_aa_base<Renderer> base_type; + + //--------------------------------------------------------------------- + line_interpolator_aa1(renderer_type& ren, const line_parameters& lp, + int sx, int sy) : + line_interpolator_aa_base<Renderer>(ren, lp), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) + { + int dist1_start; + int dist2_start; + + int npix = 1; + + if(lp.vertical) + { + do + { + --base_type::m_li; + base_type::m_y -= lp.inc; + base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x); + else m_di.inc_y(base_type::m_x - base_type::m_old_x); + + base_type::m_old_x = base_type::m_x; + + dist1_start = dist2_start = m_di.dist_start(); + + int dx = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start += m_di.dy_start(); + dist2_start -= m_di.dy_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dx; + } + while(base_type::m_dist[dx] <= base_type::m_width); + --base_type::m_step; + if(npix == 0) break; + npix = 0; + } + while(base_type::m_step >= -base_type::m_max_extent); + } + else + { + do + { + --base_type::m_li; + base_type::m_x -= lp.inc; + base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y); + else m_di.inc_x(base_type::m_y - base_type::m_old_y); + + base_type::m_old_y = base_type::m_y; + + dist1_start = dist2_start = m_di.dist_start(); + + int dy = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start -= m_di.dx_start(); + dist2_start += m_di.dx_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dy; + } + while(base_type::m_dist[dy] <= base_type::m_width); + --base_type::m_step; + if(npix == 0) break; + npix = 0; + } + while(base_type::m_step >= -base_type::m_max_extent); + } + base_type::m_li.adjust_forward(); + } + + //--------------------------------------------------------------------- + bool step_hor() + { + int dist_start; + int dist; + int dy; + int s1 = base_type::step_hor_base(m_di); + + dist_start = m_di.dist_start(); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + *p1 = 0; + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + } + ++p1; + + dy = 1; + while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) + { + dist_start -= m_di.dx_start(); + *p1 = 0; + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + } + ++p1; + ++dy; + } + + dy = 1; + dist_start = m_di.dist_start(); + while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) + { + dist_start += m_di.dx_start(); + *--p0 = 0; + if(dist_start <= 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + } + ++dy; + } + + base_type::m_ren.blend_solid_vspan(base_type::m_x, + base_type::m_y - dy + 1, + unsigned(p1 - p0), + p0); + return ++base_type::m_step < base_type::m_count; + } + + //--------------------------------------------------------------------- + bool step_ver() + { + int dist_start; + int dist; + int dx; + int s1 = base_type::step_ver_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_start = m_di.dist_start(); + + *p1 = 0; + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + } + ++p1; + + dx = 1; + while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) + { + dist_start += m_di.dy_start(); + *p1 = 0; + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + } + ++p1; + ++dx; + } + + dx = 1; + dist_start = m_di.dist_start(); + while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) + { + dist_start -= m_di.dy_start(); + *--p0 = 0; + if(dist_start <= 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + } + ++dx; + } + base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, + base_type::m_y, + unsigned(p1 - p0), + p0); + return ++base_type::m_step < base_type::m_count; + } + + private: + line_interpolator_aa1(const line_interpolator_aa1<Renderer>&); + const line_interpolator_aa1<Renderer>& + operator = (const line_interpolator_aa1<Renderer>&); + + //--------------------------------------------------------------------- + distance_interpolator2 m_di; + }; + + + + + + + + + + + + + //====================================================line_interpolator_aa2 + template<class Renderer> class line_interpolator_aa2 : + public line_interpolator_aa_base<Renderer> + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + typedef line_interpolator_aa_base<Renderer> base_type; + + //--------------------------------------------------------------------- + line_interpolator_aa2(renderer_type& ren, const line_parameters& lp, + int ex, int ey) : + line_interpolator_aa_base<Renderer>(ren, lp), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, ex, ey, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask, + 0) + { + base_type::m_li.adjust_forward(); + base_type::m_step -= base_type::m_max_extent; + } + + //--------------------------------------------------------------------- + bool step_hor() + { + int dist_end; + int dist; + int dy; + int s1 = base_type::step_hor_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_end = m_di.dist_end(); + + int npix = 0; + *p1 = 0; + if(dist_end > 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + ++npix; + } + ++p1; + + dy = 1; + while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) + { + dist_end -= m_di.dx_end(); + *p1 = 0; + if(dist_end > 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++p1; + ++dy; + } + + dy = 1; + dist_end = m_di.dist_end(); + while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) + { + dist_end += m_di.dx_end(); + *--p0 = 0; + if(dist_end > 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++dy; + } + base_type::m_ren.blend_solid_vspan(base_type::m_x, + base_type::m_y - dy + 1, + unsigned(p1 - p0), + p0); + return npix && ++base_type::m_step < base_type::m_count; + } + + //--------------------------------------------------------------------- + bool step_ver() + { + int dist_end; + int dist; + int dx; + int s1 = base_type::step_ver_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_end = m_di.dist_end(); + + int npix = 0; + *p1 = 0; + if(dist_end > 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + ++npix; + } + ++p1; + + dx = 1; + while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) + { + dist_end += m_di.dy_end(); + *p1 = 0; + if(dist_end > 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++p1; + ++dx; + } + + dx = 1; + dist_end = m_di.dist_end(); + while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) + { + dist_end -= m_di.dy_end(); + *--p0 = 0; + if(dist_end > 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++dx; + } + base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, + base_type::m_y, + unsigned(p1 - p0), + p0); + return npix && ++base_type::m_step < base_type::m_count; + } + + private: + line_interpolator_aa2(const line_interpolator_aa2<Renderer>&); + const line_interpolator_aa2<Renderer>& + operator = (const line_interpolator_aa2<Renderer>&); + + //--------------------------------------------------------------------- + distance_interpolator2 m_di; + }; + + + + + + + + + + + //====================================================line_interpolator_aa3 + template<class Renderer> class line_interpolator_aa3 : + public line_interpolator_aa_base<Renderer> + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + typedef line_interpolator_aa_base<Renderer> base_type; + + //--------------------------------------------------------------------- + line_interpolator_aa3(renderer_type& ren, const line_parameters& lp, + int sx, int sy, int ex, int ey) : + line_interpolator_aa_base<Renderer>(ren, lp), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) + { + int dist1_start; + int dist2_start; + int npix = 1; + if(lp.vertical) + { + do + { + --base_type::m_li; + base_type::m_y -= lp.inc; + base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x); + else m_di.inc_y(base_type::m_x - base_type::m_old_x); + + base_type::m_old_x = base_type::m_x; + + dist1_start = dist2_start = m_di.dist_start(); + + int dx = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start += m_di.dy_start(); + dist2_start -= m_di.dy_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dx; + } + while(base_type::m_dist[dx] <= base_type::m_width); + if(npix == 0) break; + npix = 0; + } + while(--base_type::m_step >= -base_type::m_max_extent); + } + else + { + do + { + --base_type::m_li; + base_type::m_x -= lp.inc; + base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y); + else m_di.inc_x(base_type::m_y - base_type::m_old_y); + + base_type::m_old_y = base_type::m_y; + + dist1_start = dist2_start = m_di.dist_start(); + + int dy = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start -= m_di.dx_start(); + dist2_start += m_di.dx_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dy; + } + while(base_type::m_dist[dy] <= base_type::m_width); + if(npix == 0) break; + npix = 0; + } + while(--base_type::m_step >= -base_type::m_max_extent); + } + base_type::m_li.adjust_forward(); + base_type::m_step -= base_type::m_max_extent; + } + + + //--------------------------------------------------------------------- + bool step_hor() + { + int dist_start; + int dist_end; + int dist; + int dy; + int s1 = base_type::step_hor_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_start = m_di.dist_start(); + dist_end = m_di.dist_end(); + + int npix = 0; + *p1 = 0; + if(dist_end > 0) + { + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + } + ++npix; + } + ++p1; + + dy = 1; + while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) + { + dist_start -= m_di.dx_start(); + dist_end -= m_di.dx_end(); + *p1 = 0; + if(dist_end > 0 && dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++p1; + ++dy; + } + + dy = 1; + dist_start = m_di.dist_start(); + dist_end = m_di.dist_end(); + while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) + { + dist_start += m_di.dx_start(); + dist_end += m_di.dx_end(); + *--p0 = 0; + if(dist_end > 0 && dist_start <= 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++dy; + } + base_type::m_ren.blend_solid_vspan(base_type::m_x, + base_type::m_y - dy + 1, + unsigned(p1 - p0), + p0); + return npix && ++base_type::m_step < base_type::m_count; + } + + //--------------------------------------------------------------------- + bool step_ver() + { + int dist_start; + int dist_end; + int dist; + int dx; + int s1 = base_type::step_ver_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_start = m_di.dist_start(); + dist_end = m_di.dist_end(); + + int npix = 0; + *p1 = 0; + if(dist_end > 0) + { + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + } + ++npix; + } + ++p1; + + dx = 1; + while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) + { + dist_start += m_di.dy_start(); + dist_end += m_di.dy_end(); + *p1 = 0; + if(dist_end > 0 && dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++p1; + ++dx; + } + + dx = 1; + dist_start = m_di.dist_start(); + dist_end = m_di.dist_end(); + while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) + { + dist_start -= m_di.dy_start(); + dist_end -= m_di.dy_end(); + *--p0 = 0; + if(dist_end > 0 && dist_start <= 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++dx; + } + base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, + base_type::m_y, + unsigned(p1 - p0), + p0); + return npix && ++base_type::m_step < base_type::m_count; + } + + private: + line_interpolator_aa3(const line_interpolator_aa3<Renderer>&); + const line_interpolator_aa3<Renderer>& + operator = (const line_interpolator_aa3<Renderer>&); + + //--------------------------------------------------------------------- + distance_interpolator3 m_di; + }; + + + + + //==========================================================line_profile_aa + // + // See Implementation agg_line_profile_aa.cpp + // + class line_profile_aa + { + public: + //--------------------------------------------------------------------- + typedef int8u value_type; + enum + { + subpixel_shift = line_subpixel_shift, + subpixel_size = 1 << subpixel_shift, + subpixel_mask = subpixel_size - 1 + }; + + enum + { + aa_shift = 8, + aa_num = 1 << aa_shift, + aa_mask = aa_num - 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; + } + + //--------------------------------------------------------------------- + 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) + { + gamma(gamma_function); + width(w); + } + + //--------------------------------------------------------------------- + void min_width(double w) { m_min_width = w; } + void smoother_width(double w) { m_smoother_width = w; } + + //--------------------------------------------------------------------- + template<class GammaF> void gamma(const GammaF& gamma_function) + { + int i; + for(i = 0; i < aa_num; i++) + { + m_gamma[i] = value_type( + floor( + gamma_function(double(i) / aa_mask) * aa_mask + 0.5)); + } + } + + void width(double w); + + unsigned profile_size() const { return m_size; } + int subpixel_width() const { return m_subpixel_width; } + + //--------------------------------------------------------------------- + double min_width() const { return m_min_width; } + double smoother_width() const { return m_smoother_width; } + + //--------------------------------------------------------------------- + value_type value(int dist) const + { + return m_profile[dist + subpixel_size*2]; + } + + private: + line_profile_aa(const line_profile_aa&); + const line_profile_aa& operator = (const line_profile_aa&); + + value_type* profile(double w); + 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; + }; + + + //======================================================renderer_outline_aa + template<class BaseRenderer> class renderer_outline_aa + { + public: + //--------------------------------------------------------------------- + typedef BaseRenderer base_ren_type; + typedef renderer_outline_aa<base_ren_type> self_type; + typedef typename base_ren_type::color_type color_type; + + //--------------------------------------------------------------------- + renderer_outline_aa(base_ren_type& ren, const line_profile_aa& prof) : + m_ren(&ren), + m_profile(&prof) + { + } + + //--------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //--------------------------------------------------------------------- + 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); } + + //--------------------------------------------------------------------- + int subpixel_width() const { return m_profile->subpixel_width(); } + + //--------------------------------------------------------------------- + int cover(int d) const + { + return m_profile->value(d); + } + + //------------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, unsigned len, const cover_type* covers) + { + m_ren->blend_solid_hspan(x, y, len, m_color, covers); + } + + //------------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, unsigned len, const cover_type* covers) + { + m_ren->blend_solid_vspan(x, y, len, m_color, covers); + } + + //------------------------------------------------------------------------- + static bool accurate_join_only() { return false; } + + //------------------------------------------------------------------------- + template<class Cmp> + void semidot_hline(Cmp cmp, + int xc1, int yc1, int xc2, int yc2, + int x1, int y1, int x2) + { + cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4]; + cover_type* p0 = covers; + cover_type* p1 = covers; + int x = x1 << line_subpixel_shift; + 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; + + int x0 = x1; + int dx = x - xc1; + int dy = y - yc1; + do + { + int d = int(fast_sqrt(dx*dx + dy*dy)); + *p1 = 0; + if(cmp(di.dist()) && d <= w) + { + *p1 = (cover_type)cover(d); + } + ++p1; + dx += line_subpixel_size; + di.inc_x(); + } + while(++x1 <= x2); + m_ren->blend_solid_hspan(x0, y1, + unsigned(p1 - p0), + color(), + p0); + } + + //------------------------------------------------------------------------- + template<class Cmp> + void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2) + { + 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 = xc1 >> line_subpixel_shift; + int y = yc1 >> line_subpixel_shift; + + do + { + dx += ei.dx(); + dy += ei.dy(); + + if(dy != dy0) + { + semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0); + semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y-dy0, x+dx0); + } + dx0 = dx; + dy0 = dy; + ++ei; + } + while(dy < 0); + semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0); + } + + //------------------------------------------------------------------------- + void line0(const line_parameters& lp) + { + line_interpolator_aa0<self_type> li(*this, lp); + if(li.count()) + { + if(li.vertical()) + { + while(li.step_ver()) ; + } + else + { + while(li.step_hor()) ; + } + } + } + + //------------------------------------------------------------------------- + void line1(const line_parameters& lp, int sx, int sy) + { + fix_degenerate_bisectrix_start(lp, &sx, &sy); + line_interpolator_aa1<self_type> li(*this, lp, sx, sy); + if(li.vertical()) + { + while(li.step_ver()) ; + } + else + { + while(li.step_hor()) ; + } + } + + //------------------------------------------------------------------------- + void line2(const line_parameters& lp, int ex, int ey) + { + fix_degenerate_bisectrix_end(lp, &ex, &ey); + line_interpolator_aa2<self_type> li(*this, lp, ex, ey); + if(li.vertical()) + { + while(li.step_ver()) ; + } + else + { + while(li.step_hor()) ; + } + } + + //------------------------------------------------------------------------- + void line3(const line_parameters& lp, + int sx, int sy, int ex, int ey) + { + 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()) ; + } + else + { + while(li.step_hor()) ; + } + } + + private: + base_ren_type* m_ren; + const line_profile_aa* m_profile; + color_type m_color; + }; + + + +} + +#endif diff --git a/agg/inc/agg_renderer_outline_image.h b/agg/inc/agg_renderer_outline_image.h new file mode 100755 index 000000000000..d5cd3992448c --- /dev/null +++ b/agg/inc/agg_renderer_outline_image.h @@ -0,0 +1,924 @@ +//---------------------------------------------------------------------------- +// 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_RENDERER_OUTLINE_IMAGE_INCLUDED +#define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED + +#include <math.h> +#include "agg_line_aa_basics.h" +#include "agg_dda_line.h" +#include "agg_rendering_buffer.h" + + +namespace agg +{ + //========================================================line_image_scale + template<class Source> class line_image_scale + { + public: + typedef typename Source::color_type color_type; + + line_image_scale(const Source& src, double height) : + m_source(src), + m_height(height), + m_scale(src.height() / height) + { + } + + double width() const { return m_source.width(); } + double height() const { return m_height; } + + 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 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); + return pix1.gradient(pix2, src_y - y1); + } + + private: + line_image_scale(const line_image_scale<Source>&); + const line_image_scale<Source>& operator = (const line_image_scale<Source>&); + + const Source& m_source; + double m_height; + double m_scale; + }; + + + + //======================================================line_image_pattern + template<class Filter> class line_image_pattern + { + public: + typedef Filter filter_type; + typedef typename filter_type::color_type color_type; + + //-------------------------------------------------------------------- + ~line_image_pattern() + { + delete [] m_data; + } + + //-------------------------------------------------------------------- + line_image_pattern(const Filter& filter) : + m_filter(&filter), + m_dilation(filter.dilation() + 1), + m_dilation_hr(m_dilation << line_subpixel_shift), + m_data(0), + m_width(0), + m_height(0), + m_width_hr(0), + m_half_height_hr(0), + m_offset_y_hr(0) + { + } + + // Create + //-------------------------------------------------------------------- + template<class Source> + line_image_pattern(const Filter& filter, const Source& src) : + m_filter(&filter), + m_dilation(filter.dilation() + 1), + m_dilation_hr(m_dilation << line_subpixel_shift), + m_data(0), + m_width(0), + m_height(0), + m_width_hr(0), + m_half_height_hr(0), + m_offset_y_hr(0) + { + create(src); + } + + // Create + //-------------------------------------------------------------------- + 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; + + delete [] m_data; + m_data = new color_type [(m_width + m_dilation * 2) * (m_height + m_dilation * 2)]; + + m_buf.attach(m_data, m_width + m_dilation * 2, + m_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; + for(x = 0; x < m_width; x++) + { + *d1++ = src.pixel(x, y); + } + } + + const color_type* s1; + 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; + for(x = 0; x < m_width; x++) + { + //*d1++ = color_type(*s1++, 0); + //*d2++ = color_type(*s2++, 0); + *d1++ = color_type::no_color(); + *d2++ = color_type::no_color(); + } + } + + 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; + + for(x = 0; x < m_dilation; x++) + { + *d1++ = *s1++; + *--d2 = *--s2; + } + } + } + + //-------------------------------------------------------------------- + int pattern_width() const { return m_width_hr; } + int line_width() const { return m_half_height_hr; } + + //-------------------------------------------------------------------- + void pixel(color_type* p, int x, int y) const + { + m_filter->pixel_high_res(m_buf.rows(), + p, + x % m_width_hr + m_dilation_hr, + y + m_offset_y_hr); + } + + //-------------------------------------------------------------------- + const filter_type& filter() const { return *m_filter; } + + private: + line_image_pattern(const line_image_pattern<filter_type>&); + const line_image_pattern<filter_type>& + operator = (const line_image_pattern<filter_type>&); + + protected: + row_ptr_cache<color_type> m_buf; + const filter_type* m_filter; + unsigned m_dilation; + int m_dilation_hr; + color_type* m_data; + unsigned m_width; + unsigned m_height; + int m_width_hr; + int m_half_height_hr; + int m_offset_y_hr; + }; + + + + + + + //=================================================line_image_pattern_pow2 + template<class Filter> class line_image_pattern_pow2 : + public line_image_pattern<Filter> + { + public: + typedef Filter filter_type; + typedef typename filter_type::color_type color_type; + typedef line_image_pattern<Filter> base_type; + + //-------------------------------------------------------------------- + line_image_pattern_pow2(const Filter& filter) : + line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) {} + + //-------------------------------------------------------------------- + template<class Source> + line_image_pattern_pow2(const Filter& filter, const Source& src) : + line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) + { + create(src); + } + + //-------------------------------------------------------------------- + template<class Source> void create(const Source& src) + { + line_image_pattern<Filter>::create(src); + m_mask = 1; + while(m_mask < base_type::m_width) + { + m_mask <<= 1; + m_mask |= 1; + } + m_mask <<= line_subpixel_shift - 1; + m_mask |= line_subpixel_mask; + base_type::m_width_hr = m_mask + 1; + } + + //-------------------------------------------------------------------- + void pixel(color_type* p, int x, int y) const + { + base_type::m_filter->pixel_high_res( + base_type::m_buf.rows(), + p, + (x & m_mask) + base_type::m_dilation_hr, + y + base_type::m_offset_y_hr); + } + private: + unsigned m_mask; + }; + + + + + + + + //===================================================distance_interpolator4 + class distance_interpolator4 + { + public: + //--------------------------------------------------------------------- + distance_interpolator4() {} + distance_interpolator4(int x1, int y1, int x2, int y2, + int sx, int sy, int ex, int ey, + int len, double scale, int x, int y) : + m_dx(x2 - x1), + m_dy(y2 - y1), + m_dx_start(line_mr(sx) - line_mr(x1)), + m_dy_start(line_mr(sy) - line_mr(y1)), + 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_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_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)) + { + double d = len * scale; + int dx = int(((x2 - x1) << line_subpixel_shift) / d); + int dy = int(((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) >> + line_subpixel_shift; + + m_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + m_dx_start <<= line_mr_subpixel_shift; + m_dy_start <<= line_mr_subpixel_shift; + m_dx_end <<= line_mr_subpixel_shift; + m_dy_end <<= line_mr_subpixel_shift; + } + + //--------------------------------------------------------------------- + void inc_x() + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_pict += m_dy_pict; + m_dist_end += m_dy_end; + } + + //--------------------------------------------------------------------- + void dec_x() + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_pict -= m_dy_pict; + m_dist_end -= m_dy_end; + } + + //--------------------------------------------------------------------- + void inc_y() + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_pict -= m_dx_pict; + m_dist_end -= m_dx_end; + } + + //--------------------------------------------------------------------- + void dec_y() + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_pict += m_dx_pict; + m_dist_end += m_dx_end; + } + + //--------------------------------------------------------------------- + void inc_x(int dy) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_pict += m_dy_pict; + m_dist_end += m_dy_end; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_pict -= m_dx_pict; + m_dist_end -= m_dx_end; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_pict += m_dx_pict; + m_dist_end += m_dx_end; + } + } + + //--------------------------------------------------------------------- + void dec_x(int dy) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_pict -= m_dy_pict; + m_dist_end -= m_dy_end; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_pict -= m_dx_pict; + m_dist_end -= m_dx_end; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_pict += m_dx_pict; + m_dist_end += m_dx_end; + } + } + + //--------------------------------------------------------------------- + void inc_y(int dx) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_pict -= m_dx_pict; + m_dist_end -= m_dx_end; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_pict += m_dy_pict; + m_dist_end += m_dy_end; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_pict -= m_dy_pict; + m_dist_end -= m_dy_end; + } + } + + //--------------------------------------------------------------------- + void dec_y(int dx) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_pict += m_dx_pict; + m_dist_end += m_dx_end; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_pict += m_dy_pict; + m_dist_end += m_dy_end; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_pict -= m_dy_pict; + m_dist_end -= m_dy_end; + } + } + + //--------------------------------------------------------------------- + int dist() const { return m_dist; } + int dist_start() const { return m_dist_start; } + int dist_pict() const { return m_dist_pict; } + int dist_end() const { return m_dist_end; } + + //--------------------------------------------------------------------- + int dx() const { return m_dx; } + int dy() const { return m_dy; } + int dx_start() const { return m_dx_start; } + int dy_start() const { return m_dy_start; } + int dx_pict() const { return m_dx_pict; } + int dy_pict() const { return m_dy_pict; } + int dx_end() const { return m_dx_end; } + int dy_end() const { return m_dy_end; } + int len() const { return m_len; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dx_start; + int m_dy_start; + int m_dx_pict; + int m_dy_pict; + int m_dx_end; + int m_dy_end; + + int m_dist; + int m_dist_start; + int m_dist_pict; + int m_dist_end; + int m_len; + }; + + + + + + //==================================================line_interpolator_image + template<class Renderer> class line_interpolator_image + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + + //--------------------------------------------------------------------- + enum + { + max_half_width = 64 + }; + + //--------------------------------------------------------------------- + line_interpolator_image(renderer_type& ren, const line_parameters& lp, + int sx, int sy, int ex, int ey, + int pattern_start, + double scale_x) : + m_lp(lp), + m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : + line_dbl_hr(lp.y2 - lp.y1), + lp.vertical ? abs(lp.y2 - lp.y1) : + abs(lp.x2 - lp.x1) + 1), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask), + m_ren(ren), + m_x(lp.x1 >> line_subpixel_shift), + m_y(lp.y1 >> line_subpixel_shift), + m_old_x(m_x), + m_old_y(m_y), + 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_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()), + m_step(0) + { + agg::dda2_line_interpolator li(0, lp.vertical ? + (lp.dy << agg::line_subpixel_shift) : + (lp.dx << agg::line_subpixel_shift), + lp.len); + + unsigned i; + int stop = m_width + line_subpixel_size * 2; + for(i = 0; i < max_half_width; ++i) + { + m_dist_pos[i] = li.y(); + if(m_dist_pos[i] >= stop) break; + ++li; + } + m_dist_pos[i] = 0x7FFF0000; + + int dist1_start; + int dist2_start; + int npix = 1; + + if(lp.vertical) + { + do + { + --m_li; + m_y -= lp.inc; + m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_y(m_x - m_old_x); + else m_di.inc_y(m_x - m_old_x); + + m_old_x = m_x; + + dist1_start = dist2_start = m_di.dist_start(); + + int dx = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start += m_di.dy_start(); + dist2_start -= m_di.dy_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dx; + } + while(m_dist_pos[dx] <= m_width); + if(npix == 0) break; + + npix = 0; + } + while(--m_step >= -m_max_extent); + } + else + { + do + { + --m_li; + + m_x -= lp.inc; + m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_x(m_y - m_old_y); + else m_di.inc_x(m_y - m_old_y); + + m_old_y = m_y; + + dist1_start = dist2_start = m_di.dist_start(); + + int dy = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start -= m_di.dx_start(); + dist2_start += m_di.dx_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dy; + } + while(m_dist_pos[dy] <= m_width); + if(npix == 0) break; + + npix = 0; + } + while(--m_step >= -m_max_extent); + } + m_li.adjust_forward(); + m_step -= m_max_extent; + } + + //--------------------------------------------------------------------- + bool step_hor() + { + ++m_li; + m_x += m_lp.inc; + m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift; + + if(m_lp.inc > 0) m_di.inc_x(m_y - m_old_y); + else m_di.dec_x(m_y - m_old_y); + + m_old_y = m_y; + + int s1 = m_di.dist() / m_lp.len; + int s2 = -s1; + + if(m_lp.inc < 0) s1 = -s1; + + int dist_start; + int dist_pict; + int dist_end; + int dy; + int dist; + + dist_start = m_di.dist_start(); + dist_pict = m_di.dist_pict() + m_start; + dist_end = m_di.dist_end(); + color_type* p0 = m_colors + max_half_width + 2; + color_type* p1 = p0; + + int npix = 0; + p1->clear(); + if(dist_end > 0) + { + if(dist_start <= 0) + { + m_ren.pixel(p1, dist_pict, s2); + } + ++npix; + } + ++p1; + + dy = 1; + while((dist = m_dist_pos[dy]) - s1 <= m_width) + { + dist_start -= m_di.dx_start(); + dist_pict -= m_di.dx_pict(); + dist_end -= m_di.dx_end(); + p1->clear(); + if(dist_end > 0 && dist_start <= 0) + { + if(m_lp.inc > 0) dist = -dist; + m_ren.pixel(p1, dist_pict, s2 - dist); + ++npix; + } + ++p1; + ++dy; + } + + dy = 1; + dist_start = m_di.dist_start(); + dist_pict = m_di.dist_pict() + m_start; + dist_end = m_di.dist_end(); + while((dist = m_dist_pos[dy]) + s1 <= m_width) + { + dist_start += m_di.dx_start(); + dist_pict += m_di.dx_pict(); + dist_end += m_di.dx_end(); + --p0; + p0->clear(); + if(dist_end > 0 && dist_start <= 0) + { + if(m_lp.inc > 0) dist = -dist; + m_ren.pixel(p0, dist_pict, s2 + dist); + ++npix; + } + ++dy; + } + m_ren.blend_color_vspan(m_x, + m_y - dy + 1, + unsigned(p1 - p0), + p0); + return npix && ++m_step < m_count; + } + + + + //--------------------------------------------------------------------- + bool step_ver() + { + ++m_li; + m_y += m_lp.inc; + m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift; + + if(m_lp.inc > 0) m_di.inc_y(m_x - m_old_x); + else m_di.dec_y(m_x - m_old_x); + + m_old_x = m_x; + + int s1 = m_di.dist() / m_lp.len; + int s2 = -s1; + + if(m_lp.inc > 0) s1 = -s1; + + int dist_start; + int dist_pict; + int dist_end; + int dist; + int dx; + + dist_start = m_di.dist_start(); + dist_pict = m_di.dist_pict() + m_start; + dist_end = m_di.dist_end(); + color_type* p0 = m_colors + max_half_width + 2; + color_type* p1 = p0; + + int npix = 0; + p1->clear(); + if(dist_end > 0) + { + if(dist_start <= 0) + { + m_ren.pixel(p1, dist_pict, s2); + } + ++npix; + } + ++p1; + + dx = 1; + while((dist = m_dist_pos[dx]) - s1 <= m_width) + { + dist_start += m_di.dy_start(); + dist_pict += m_di.dy_pict(); + dist_end += m_di.dy_end(); + p1->clear(); + if(dist_end > 0 && dist_start <= 0) + { + if(m_lp.inc > 0) dist = -dist; + m_ren.pixel(p1, dist_pict, s2 + dist); + ++npix; + } + ++p1; + ++dx; + } + + dx = 1; + dist_start = m_di.dist_start(); + dist_pict = m_di.dist_pict() + m_start; + dist_end = m_di.dist_end(); + while((dist = m_dist_pos[dx]) + s1 <= m_width) + { + dist_start -= m_di.dy_start(); + dist_pict -= m_di.dy_pict(); + dist_end -= m_di.dy_end(); + --p0; + p0->clear(); + if(dist_end > 0 && dist_start <= 0) + { + if(m_lp.inc > 0) dist = -dist; + m_ren.pixel(p0, dist_pict, s2 - dist); + ++npix; + } + ++dx; + } + m_ren.blend_color_hspan(m_x - dx + 1, + m_y, + unsigned(p1 - p0), + p0); + return npix && ++m_step < m_count; + } + + + //--------------------------------------------------------------------- + int pattern_end() const { return m_start + m_di.len(); } + + //--------------------------------------------------------------------- + bool vertical() const { return m_lp.vertical; } + int width() const { return m_width; } + int count() const { return m_count; } + + private: + line_interpolator_image(const line_interpolator_image<Renderer>&); + const line_interpolator_image<Renderer>& + operator = (const line_interpolator_image<Renderer>&); + + protected: + const line_parameters& m_lp; + dda2_line_interpolator m_li; + distance_interpolator4 m_di; + renderer_type& m_ren; + int m_plen; + int m_x; + int m_y; + int m_old_x; + int m_old_y; + int m_count; + int m_width; + int m_max_extent; + int m_start; + int m_step; + int m_dist_pos[max_half_width + 1]; + color_type m_colors[max_half_width * 2 + 4]; + }; + + + + + + + + + //===================================================renderer_outline_image + template<class BaseRenderer, class ImagePattern> + class renderer_outline_image + { + public: + //--------------------------------------------------------------------- + typedef BaseRenderer base_ren_type; + typedef renderer_outline_image<BaseRenderer, ImagePattern> self_type; + typedef typename base_ren_type::color_type color_type; + typedef ImagePattern pattern_type; + + + //--------------------------------------------------------------------- + renderer_outline_image(base_ren_type& ren, const pattern_type& patt) : + m_ren(&ren), + m_pattern(&patt), + m_start(0), + m_scale_x(1.0) + { + } + + //--------------------------------------------------------------------- + void pattern(const pattern_type& p) { m_pattern = &p; } + const pattern_type& pattern() const { return *m_pattern; } + + //--------------------------------------------------------------------- + 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; } + + //--------------------------------------------------------------------- + int subpixel_width() const { return m_pattern->line_width(); } + int pattern_width() const { return m_pattern->pattern_width(); } + + //------------------------------------------------------------------------- + void pixel(color_type* p, int x, int y) const + { + m_pattern->pixel(p, x, y); + } + + //------------------------------------------------------------------------- + void blend_color_hspan(int x, int y, unsigned len, const color_type* colors) + { + m_ren->blend_color_hspan(x, y, len, colors, 0); + } + + //------------------------------------------------------------------------- + void blend_color_vspan(int x, int y, unsigned len, const color_type* colors) + { + m_ren->blend_color_vspan(x, y, len, colors, 0); + } + + //------------------------------------------------------------------------- + static bool accurate_join_only() { return true; } + + //------------------------------------------------------------------------- + template<class Cmp> + void semidot(Cmp, int, int, int, int) + { + } + + //------------------------------------------------------------------------- + void line0(const line_parameters&) + { + } + + //------------------------------------------------------------------------- + void line1(const line_parameters&, int, int) + { + } + + //------------------------------------------------------------------------- + void line2(const line_parameters&, int, int) + { + } + + //------------------------------------------------------------------------- + void line3(const line_parameters& lp, + int sx, int sy, int ex, int ey) + { + fix_degenerate_bisectrix_start(lp, &sx, &sy); + fix_degenerate_bisectrix_end(lp, &ex, &ey); + line_interpolator_image<self_type> li(*this, lp, + sx, sy, + ex, ey, + m_start, m_scale_x); + if(li.vertical()) + { + while(li.step_ver()); + } + else + { + while(li.step_hor()); + } + m_start = li.pattern_end(); + } + + private: + base_ren_type* m_ren; + const pattern_type* m_pattern; + int m_start; + double m_scale_x; + }; + + + + + +} + + + +#endif diff --git a/agg/inc/agg_renderer_primitives.h b/agg/inc/agg_renderer_primitives.h new file mode 100755 index 000000000000..522432c06df6 --- /dev/null +++ b/agg/inc/agg_renderer_primitives.h @@ -0,0 +1,224 @@ +//---------------------------------------------------------------------------- +// 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 renderer_primitives +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_PRIMITIVES_INCLUDED +#define AGG_RENDERER_PRIMITIVES_INCLUDED + +#include "agg_basics.h" +#include "agg_renderer_base.h" +#include "agg_dda_line.h" +#include "agg_ellipse_bresenham.h" + +namespace agg +{ + //-----------------------------------------------------renderer_primitives + template<class BaseRenderer> class renderer_primitives + { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + renderer_primitives(base_ren_type& ren) : + m_ren(&ren), + m_fill_color(), + m_line_color(), + m_curr_x(0), + m_curr_y(0) + { + } + + //-------------------------------------------------------------------- + static int coord(double c) + { + return int(c * line_bresenham_interpolator::subpixel_size); + } + + //-------------------------------------------------------------------- + void fill_color(const color_type& c) { m_fill_color = c; } + void line_color(const color_type& c) { m_line_color = c; } + const color_type& fill_color() const { return m_fill_color; } + const color_type& line_color() const { return m_line_color; } + + //-------------------------------------------------------------------- + void rectangle(int x1, int y1, int x2, int y2) + { + m_ren->blend_hline(x1, y1, x2-1, m_line_color, cover_full); + m_ren->blend_vline(x2, y1, y2-1, m_line_color, cover_full); + m_ren->blend_hline(x1+1, y2, x2, m_line_color, cover_full); + m_ren->blend_vline(x1, y1+1, y2, m_line_color, cover_full); + } + + //-------------------------------------------------------------------- + void solid_rectangle(int x1, int y1, int x2, int y2) + { + m_ren->blend_bar(x1, y1, x2, y2, m_fill_color, cover_full); + } + + //-------------------------------------------------------------------- + void outlined_rectangle(int x1, int y1, int x2, int y2) + { + rectangle(x1, y1, x2, y2); + m_ren->blend_bar(x1+1, y1+1, x2-1, y2-1, m_fill_color, cover_full); + } + + //-------------------------------------------------------------------- + void ellipse(int x, int y, int rx, int ry) + { + ellipse_bresenham_interpolator ei(rx, ry); + int dx = 0; + int dy = -ry; + do + { + dx += ei.dx(); + dy += ei.dy(); + m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full); + m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full); + m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full); + m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full); + ++ei; + } + while(dy < 0); + } + + //-------------------------------------------------------------------- + void solid_ellipse(int x, int y, int rx, int ry) + { + ellipse_bresenham_interpolator ei(rx, ry); + int dx = 0; + int dy = -ry; + int dy0 = dy; + int dx0 = dx; + + do + { + dx += ei.dx(); + dy += ei.dy(); + + if(dy != dy0) + { + m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full); + m_ren->blend_hline(x-dx0, y-dy0, x+dx0, m_fill_color, cover_full); + } + dx0 = dx; + dy0 = dy; + ++ei; + } + while(dy < 0); + m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full); + } + + //-------------------------------------------------------------------- + void outlined_ellipse(int x, int y, int rx, int ry) + { + ellipse_bresenham_interpolator ei(rx, ry); + int dx = 0; + int dy = -ry; + + do + { + dx += ei.dx(); + dy += ei.dy(); + + m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full); + m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full); + m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full); + m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full); + + if(ei.dy() && dx) + { + m_ren->blend_hline(x-dx+1, y+dy, x+dx-1, m_fill_color, cover_full); + m_ren->blend_hline(x-dx+1, y-dy, x+dx-1, m_fill_color, cover_full); + } + ++ei; + } + while(dy < 0); + } + + //-------------------------------------------------------------------- + void line(int x1, int y1, int x2, int y2, bool last=false) + { + line_bresenham_interpolator li(x1, y1, x2, y2); + + unsigned len = li.len(); + if(len == 0) + { + if(last) + { + m_ren->blend_pixel(li.line_lr(x1), li.line_lr(y1), m_line_color, cover_full); + } + return; + } + + if(last) ++len; + + if(li.is_ver()) + { + do + { + m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full); + li.vstep(); + } + while(--len); + } + else + { + do + { + m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full); + li.hstep(); + } + while(--len); + } + } + + //-------------------------------------------------------------------- + void move_to(int x, int y) + { + m_curr_x = x; + m_curr_y = y; + } + + //-------------------------------------------------------------------- + void line_to(int x, int y, bool last=false) + { + line(m_curr_x, m_curr_y, x, y, last); + m_curr_x = x; + m_curr_y = y; + } + + //-------------------------------------------------------------------- + const base_ren_type& ren() const { return *m_ren; } + base_ren_type& ren() { return *m_ren; } + + //-------------------------------------------------------------------- + const rendering_buffer& rbuf() const { return m_ren->rbuf(); } + rendering_buffer& rbuf() { return m_ren->rbuf(); } + + private: + base_ren_type* m_ren; + color_type m_fill_color; + color_type m_line_color; + int m_curr_x; + int m_curr_y; + }; + +} + +#endif diff --git a/agg/inc/agg_renderer_raster_text.h b/agg/inc/agg_renderer_raster_text.h new file mode 100755 index 000000000000..957944600332 --- /dev/null +++ b/agg/inc/agg_renderer_raster_text.h @@ -0,0 +1,264 @@ +//---------------------------------------------------------------------------- +// 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_RENDERER_RASTER_TEXT_INCLUDED +#define AGG_RENDERER_RASTER_TEXT_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //==============================================renderer_raster_htext_solid + template<class BaseRenderer, class GlyphGenerator> + class renderer_raster_htext_solid + { + public: + typedef BaseRenderer ren_type; + typedef GlyphGenerator glyph_gen_type; + typedef typename glyph_gen_type::glyph_rect glyph_rect; + typedef typename ren_type::color_type color_type; + + renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph) : + m_ren(&ren), + m_glyph(&glyph) + { + } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + template<class CharT> + void render_text(double x, double y, const CharT* str, bool flip=false) + { + glyph_rect r; + while(*str) + { + m_glyph->prepare(&r, x, y, *str, flip); + if(r.x2 >= r.x1) + { + int i; + if(flip) + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1), + m_color, + m_glyph->span(r.y2 - i)); + } + } + else + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1), + m_color, + m_glyph->span(i - r.y1)); + } + } + } + x += r.dx; + y += r.dy; + ++str; + } + } + + private: + ren_type* m_ren; + glyph_gen_type* m_glyph; + color_type m_color; + }; + + + + //=============================================renderer_raster_vtext_solid + template<class BaseRenderer, class GlyphGenerator> + class renderer_raster_vtext_solid + { + public: + typedef BaseRenderer ren_type; + typedef GlyphGenerator glyph_gen_type; + typedef typename glyph_gen_type::glyph_rect glyph_rect; + typedef typename ren_type::color_type color_type; + + renderer_raster_vtext_solid(ren_type& ren, glyph_gen_type& glyph) : + m_ren(&ren), + m_glyph(&glyph) + { + } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + template<class CharT> + void render_text(double x, double y, const CharT* str, bool flip=false) + { + glyph_rect r; + while(*str) + { + m_glyph->prepare(&r, x, y, *str, !flip); + if(r.x2 >= r.x1) + { + int i; + if(flip) + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1), + m_color, + m_glyph->span(i - r.y1)); + } + } + else + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1), + m_color, + m_glyph->span(r.y2 - i)); + } + } + } + x += r.dx; + y += r.dy; + ++str; + } + } + + private: + ren_type* m_ren; + glyph_gen_type* m_glyph; + color_type m_color; + }; + + + + + + + //===================================================renderer_raster_htext + template<class ScanlineRenderer, class GlyphGenerator> + class renderer_raster_htext + { + public: + typedef ScanlineRenderer ren_type; + typedef GlyphGenerator glyph_gen_type; + typedef typename glyph_gen_type::glyph_rect glyph_rect; + + class scanline_single_span + { + public: + typedef agg::cover_type cover_type; + + //---------------------------------------------------------------- + struct const_span + { + int x; + unsigned len; + const cover_type* covers; + + const_span() {} + const_span(int x_, unsigned len_, const cover_type* covers_) : + x(x_), len(len_), covers(covers_) + {} + }; + + typedef const const_span* const_iterator; + + //---------------------------------------------------------------- + scanline_single_span(int x, int y, unsigned len, + const cover_type* covers) : + m_y(y), + m_span(x, len, covers) + {} + + //---------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return 1; } + const_iterator begin() const { return &m_span; } + + private: + //---------------------------------------------------------------- + int m_y; + const_span m_span; + }; + + + + //-------------------------------------------------------------------- + renderer_raster_htext(ren_type& ren, glyph_gen_type& glyph) : + m_ren(&ren), + m_glyph(&glyph) + { + } + + + //-------------------------------------------------------------------- + template<class CharT> + void render_text(double x, double y, const CharT* str, bool flip=false) + { + glyph_rect r; + while(*str) + { + m_glyph->prepare(&r, x, y, *str, flip); + if(r.x2 >= r.x1) + { + m_ren->prepare(r.x2 - r.x1 + 1); + int i; + if(flip) + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->render( + scanline_single_span(r.x1, + i, + (r.x2 - r.x1 + 1), + m_glyph->span(r.y2 - i))); + } + } + else + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->render( + scanline_single_span(r.x1, + i, + (r.x2 - r.x1 + 1), + m_glyph->span(i - r.y1))); + } + } + } + x += r.dx; + y += r.dy; + ++str; + } + } + + private: + ren_type* m_ren; + glyph_gen_type* m_glyph; + }; + + + + +} + +#endif + diff --git a/agg/inc/agg_renderer_scanline.h b/agg/inc/agg_renderer_scanline.h new file mode 100755 index 000000000000..cc33942a3770 --- /dev/null +++ b/agg/inc/agg_renderer_scanline.h @@ -0,0 +1,450 @@ +//---------------------------------------------------------------------------- +// 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_RENDERER_SCANLINE_INCLUDED +#define AGG_RENDERER_SCANLINE_INCLUDED + +#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 + { + public: + typedef BaseRenderer base_ren_type; + + //-------------------------------------------------------------------- + renderer_scanline_aa(base_ren_type& ren, SpanGenerator& span_gen) : + m_ren(&ren), + m_span_gen(&span_gen) + { + } + + //-------------------------------------------------------------------- + void prepare(unsigned max_span_len) + { + m_span_gen->prepare(max_span_len); + } + + //-------------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + int y = sl.y(); + m_ren->first_clip_box(); + do + { + int xmin = m_ren->xmin(); + int xmax = m_ren->xmax(); + + if(y >= m_ren->ymin() && y <= m_ren->ymax()) + { + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + 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_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()); + } + + private: + base_ren_type* m_ren; + SpanGenerator* m_span_gen; + }; + + + + + //==============================================renderer_scanline_aa_opaque + template<class BaseRenderer, class SpanGenerator> class renderer_scanline_aa_opaque + { + public: + typedef BaseRenderer base_ren_type; + + //-------------------------------------------------------------------- + renderer_scanline_aa_opaque(base_ren_type& ren, SpanGenerator& span_gen) : + m_ren(&ren), + m_span_gen(&span_gen) + { + } + + //-------------------------------------------------------------------- + void prepare(unsigned max_span_len) + { + m_span_gen->prepare(max_span_len); + } + + //-------------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + int y = sl.y(); + m_ren->first_clip_box(); + do + { + int xmin = m_ren->xmin(); + int xmax = m_ren->xmax(); + + if(y >= m_ren->ymin() && y <= m_ren->ymax()) + { + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + 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()); + } + + private: + base_ren_type* m_ren; + SpanGenerator* m_span_gen; + }; + + + + //==============================================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(base_ren_type& ren) : + m_ren(&ren) + { + } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + void prepare(unsigned) {} + + //-------------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + 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); + } + + private: + base_ren_type* m_ren; + color_type m_color; + }; + + + + + + + + //===================================================renderer_scanline_bin + template<class BaseRenderer, class SpanGenerator> class renderer_scanline_bin + { + public: + typedef BaseRenderer base_ren_type; + + //-------------------------------------------------------------------- + renderer_scanline_bin(base_ren_type& ren, SpanGenerator& span_gen) : + m_ren(&ren), + m_span_gen(&span_gen) + { + } + + //-------------------------------------------------------------------- + void prepare(unsigned max_span_len) + { + m_span_gen->prepare(max_span_len); + } + + //-------------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + int y = sl.y(); + m_ren->first_clip_box(); + do + { + int xmin = m_ren->xmin(); + int xmax = m_ren->xmax(); + + if(y >= m_ren->ymin() && y <= m_ren->ymax()) + { + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + 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()); + } + + private: + base_ren_type* m_ren; + SpanGenerator* 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) + { + } + + //-------------------------------------------------------------------- + void prepare(unsigned max_span_len) + { + m_span_gen->prepare(max_span_len); + } + + //-------------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + int y = sl.y(); + m_ren->first_clip_box(); + do + { + int xmin = m_ren->xmin(); + int xmax = m_ren->xmax(); + + if(y >= m_ren->ymin() && y <= m_ren->ymax()) + { + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + 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_opaque_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()); + } + + private: + base_ren_type* m_ren; + SpanGenerator* m_span_gen; + }; + + + + + //=============================================renderer_scanline_bin_solid + template<class BaseRenderer> class renderer_scanline_bin_solid + { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + renderer_scanline_bin_solid(base_ren_type& ren) : + m_ren(&ren) + { + } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + void prepare(unsigned) {} + + //-------------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + 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); + } + + private: + base_ren_type* m_ren; + color_type m_color; + }; + +} + +#endif diff --git a/agg/inc/agg_rendering_buffer.h b/agg/inc/agg_rendering_buffer.h new file mode 100755 index 000000000000..50b6a46fdfa8 --- /dev/null +++ b/agg/inc/agg_rendering_buffer.h @@ -0,0 +1,179 @@ +//---------------------------------------------------------------------------- +// 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 rendering_buffer +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERING_BUFFER_INCLUDED +#define AGG_RENDERING_BUFFER_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //==========================================================row_ptr_cache + template<class T> class row_ptr_cache + { + public: + //-------------------------------------------------------------------- + struct row_data + { + int x1, x2; + const int8u* ptr; + row_data() {} + row_data(int x1_, int x2_, const int8u* ptr_) : + x1(x1_), x2(x2_), ptr(ptr_) {} + }; + + //------------------------------------------------------------------- + ~row_ptr_cache() + { + delete [] m_rows; + } + + //------------------------------------------------------------------- + row_ptr_cache() : + m_buf(0), + m_rows(0), + m_width(0), + m_height(0), + m_stride(0), + m_max_height(0) + { + } + + //-------------------------------------------------------------------- + row_ptr_cache(T* _buf, unsigned _width, unsigned _height, int _stride) : + m_buf(0), + m_rows(0), + m_width(0), + m_height(0), + m_stride(0), + m_max_height(0) + { + attach(_buf, _width, _height, _stride); + } + + //-------------------------------------------------------------------- + void attach(T* _buf, unsigned _width, unsigned _height, int _stride) + { + m_buf = _buf; + m_width = _width; + m_height = _height; + m_stride = _stride; + if(_height > m_max_height) + { + delete [] m_rows; + m_rows = new T* [m_max_height = _height]; + } + + T* row_ptr = m_buf; + + if(_stride < 0) + { + row_ptr = m_buf - int(_height - 1) * _stride; + } + + T** _rows = m_rows; + + while(_height--) + { + *_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 + { + 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; } + + T const* const* rows() const { return m_rows; } + + //-------------------------------------------------------------------- + void copy_from(const row_ptr_cache<T>& mtx) + { + unsigned h = height(); + if(mtx.height() < h) h = mtx.height(); + + unsigned l = stride_abs(); + if(mtx.stride_abs() < l) l = mtx.stride_abs(); + + l *= sizeof(T); + + unsigned y; + for (y = 0; y < h; y++) + { + memcpy(row(y), mtx.row(y), l); + } + } + + //-------------------------------------------------------------------- + void clear(T value) + { + unsigned y; + for(y = 0; y < height(); y++) + { + T* p = row(y); + unsigned x; + for(x = 0; x < stride_abs(); 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) + }; + + + + //========================================================rendering_buffer + typedef row_ptr_cache<int8u> rendering_buffer; + +} + + +#endif diff --git a/agg/inc/agg_rendering_buffer_dynarow.h b/agg/inc/agg_rendering_buffer_dynarow.h new file mode 100755 index 000000000000..b6724d99ff78 --- /dev/null +++ b/agg/inc/agg_rendering_buffer_dynarow.h @@ -0,0 +1,184 @@ +//---------------------------------------------------------------------------- +// 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 rendering_buffer_dynarow +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED +#define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //===============================================rendering_buffer_dynarow + // Rendering buffer class with dynamic allocation of the rows. + // The rows are allocated as needed when requesting for span_ptr(). + // The class automatically calculates min_x and max_x for each row. + // 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 + { + public: + //------------------------------------------------------------------- + struct row_data + { + int8u* ptr; + int x1; + int x2; + }; + + //------------------------------------------------------------------- + ~rendering_buffer_dynarow() + { + init(0,0); + } + + //------------------------------------------------------------------- + rendering_buffer_dynarow() : + m_rows(0), + m_width(0), + m_height(0) + { + } + + // Allocate and clear the buffer + //-------------------------------------------------------------------- + rendering_buffer_dynarow(unsigned width, unsigned height) : + m_rows(new row_data[height]), + m_width(width), + m_height(height) + { + memset(m_rows, 0, sizeof(row_data) * height); + } + + // Allocate and clear the buffer + //-------------------------------------------------------------------- + void init(unsigned width, unsigned height) + { + unsigned i; + for(i = 0; i < m_height; ++i) delete [] m_rows[i].ptr; + delete [] m_rows; + m_rows = 0; + if(width && height) + { + m_width = width; + m_height = height; + m_rows = new row_data[height]; + memset(m_rows, 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; + } + + + // 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) + { + row_data* r = m_rows + y; + int x2 = x + len - 1; + if(r->ptr) + { + if(x < r->x1) { r->x1 = x; } + if(x2 > r->x2) { r->x2 = x2; } + } + else + { + r->ptr = new int8u [m_width * PixWidth]; + r->x1 = x; + r->x2 = x2; + memset(r->ptr, 0, m_width * PixWidth); + } + return r->ptr + x * PixWidth; + } + + // 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; + } + + + + private: + //-------------------------------------------------------------------- + // Prohibit copying + rendering_buffer_dynarow(const rendering_buffer_dynarow<PixWidth>&); + const rendering_buffer_dynarow<PixWidth>& + operator = (const rendering_buffer_dynarow<PixWidth>&); + + private: + //-------------------------------------------------------------------- + row_data* m_rows; // Pointers to each row of the buffer + unsigned m_width; // Width in pixels + unsigned m_height; // Height in pixels + }; + + +} + + +#endif diff --git a/agg/inc/agg_rounded_rect.h b/agg/inc/agg_rounded_rect.h new file mode 100755 index 000000000000..d4185dafa5b3 --- /dev/null +++ b/agg/inc/agg_rounded_rect.h @@ -0,0 +1,79 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Rounded rectangle vertex generator +// +//---------------------------------------------------------------------------- + +#ifndef AGG_ROUNDED_RECT_INCLUDED +#define AGG_ROUNDED_RECT_INCLUDED + +#include "agg_basics.h" +#include "agg_arc.h" +#include "agg_vertex_iterator.h" + + +namespace agg +{ + //------------------------------------------------------------rounded_rect + // + // See Implemantation agg_rounded_rect.cpp + // + class rounded_rect + { + public: + rounded_rect() {} + rounded_rect(double x1, double y1, double x2, double y2, double r); + + void rect(double x1, double y1, double x2, double y2); + void radius(double r); + void radius(double rx, double ry); + void radius(double rx_bottom, double ry_bottom, double rx_top, double ry_top); + void radius(double rx1, double ry1, double rx2, double ry2, + double rx3, double ry3, double rx4, double ry4); + void normalize_radius(); + + void approximation_scale(double s) { m_arc.approximation_scale(s); } + double approximation_scale() const { return m_arc.approximation_scale(); } + + 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; + double m_x2; + double m_y2; + double m_rx1; + double m_ry1; + double m_rx2; + double m_ry2; + double m_rx3; + double m_ry3; + double m_rx4; + double m_ry4; + unsigned m_status; + arc m_arc; + }; + +} + +#endif + diff --git a/agg/inc/agg_scanline_bin.h b/agg/inc/agg_scanline_bin.h new file mode 100755 index 000000000000..aa60ed061e07 --- /dev/null +++ b/agg/inc/agg_scanline_bin.h @@ -0,0 +1,171 @@ +//---------------------------------------------------------------------------- +// 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 scanline_bin - binary scanline. +// +//---------------------------------------------------------------------------- +#ifndef AGG_SCANLINE_BIN_INCLUDED +#define AGG_SCANLINE_BIN_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //=============================================================scanline_bin + // + // This is binary scaline container which supports the interface + // 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: + struct span + { + int16 x; + int16 len; + }; + + typedef const span* const_iterator; + + ~scanline_bin() + { + 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); + 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(); + + 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; } + + 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; + }; + + + //------------------------------------------------------------------------ + inline void scanline_bin::reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; + if(max_len > m_max_len) + { + delete [] m_spans; + m_spans = new span [max_len]; + m_max_len = max_len; + } + m_last_x = 0x7FFF; + m_cur_span = m_spans; + } + + + //------------------------------------------------------------------------ + inline void scanline_bin::reset_spans() + { + m_last_x = 0x7FFF; + m_cur_span = m_spans; + } + + + //------------------------------------------------------------------------ + inline void scanline_bin::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; + } + + + //------------------------------------------------------------------------ + inline void scanline_bin::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; + } + + //------------------------------------------------------------------------ + inline void scanline_bin::add_cells(int x, unsigned len, const void*) + { + add_span(x, len, 0); + } +} + + +#endif diff --git a/agg/inc/agg_scanline_boolean_algebra.h b/agg/inc/agg_scanline_boolean_algebra.h new file mode 100755 index 000000000000..7f1a3c5ba774 --- /dev/null +++ b/agg/inc/agg_scanline_boolean_algebra.h @@ -0,0 +1,1559 @@ +//---------------------------------------------------------------------------- +// 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_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED +#define AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED + +#include <stdlib.h> +#include <math.h> +#include "agg_basics.h" + + +namespace agg +{ + + //-----------------------------------------------sbool_combine_spans_bin + // Functor. + // Combine two binary encoded spans, i.e., when we don't have any + // anti-aliasing information, but only X and Length. The function + // is compatible with any type of scanlines. + //---------------- + template<class Scanline1, + class Scanline2, + class Scanline> + struct sbool_combine_spans_bin + { + void operator () (const typename Scanline1::const_iterator&, + const typename Scanline2::const_iterator&, + int x, unsigned len, + Scanline& sl) const + { + sl.add_span(x, len, cover_full); + } + }; + + + + //---------------------------------------------sbool_combine_spans_empty + // Functor. + // Combine two spans as empty ones. The functor does nothing + // and is used to XOR binary spans. + //---------------- + template<class Scanline1, + class Scanline2, + class Scanline> + struct sbool_combine_spans_empty + { + void operator () (const typename Scanline1::const_iterator&, + const typename Scanline2::const_iterator&, + int, unsigned, + Scanline&) const + {} + }; + + + + //--------------------------------------------------sbool_add_span_empty + // Functor. + // Add nothing. Used in conbine_shapes_sub + //---------------- + template<class Scanline1, + class Scanline> + struct sbool_add_span_empty + { + void operator () (const typename Scanline1::const_iterator&, + int, unsigned, + Scanline&) const + {} + }; + + + //----------------------------------------------------sbool_add_span_bin + // Functor. + // Add a binary span + //---------------- + template<class Scanline1, + class Scanline> + struct sbool_add_span_bin + { + void operator () (const typename Scanline1::const_iterator&, + int x, unsigned len, + Scanline& sl) const + { + sl.add_span(x, len, cover_full); + } + }; + + + + + //-----------------------------------------------------sbool_add_span_aa + // Functor. + // Add an anti-aliased span + // anti-aliasing information, but only X and Length. The function + // is compatible with any type of scanlines. + //---------------- + template<class Scanline1, + class Scanline> + struct sbool_add_span_aa + { + void operator () (const typename Scanline1::const_iterator& span, + int x, unsigned len, + Scanline& sl) const + { + if(span->len < 0) + { + sl.add_span(x, len, *span->covers); + } + else + if(span->len > 0) + { + const typename Scanline1::cover_type* covers = span->covers; + if(span->x < x) covers += x - span->x; + sl.add_cells(x, len, covers); + } + } + }; + + + + + //----------------------------------------------sbool_intersect_spans_aa + // Functor. + // Intersect two spans preserving the anti-aliasing information. + // The result is added to the "sl" scanline. + //------------------ + template<class Scanline1, + class Scanline2, + class Scanline, + unsigned CoverShift = cover_shift> + struct sbool_intersect_spans_aa + { + enum + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1, + cover_full = cover_mask + }; + + + void operator () (const typename Scanline1::const_iterator& span1, + const typename Scanline2::const_iterator& span2, + int x, unsigned len, + Scanline& sl) const + { + unsigned cover; + const typename Scanline1::cover_type* covers1; + const typename Scanline2::cover_type* covers2; + + // Calculate the operation code and choose the + // proper combination algorithm. + // 0 = Both spans are of AA type + // 1 = span1 is solid, span2 is AA + // 2 = span1 is AA, span2 is solid + // 3 = Both spans are of solid type + //----------------- + switch((span1->len < 0) | ((span2->len < 0) << 1)) + { + case 0: // Both are AA spans + covers1 = span1->covers; + covers2 = span2->covers; + if(span1->x < x) covers1 += x - span1->x; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = *covers1++ * *covers2++; + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + break; + + case 1: // span1 is solid, span2 is AA + covers2 = span2->covers; + if(span2->x < x) covers2 += x - span2->x; + if(*(span1->covers) == cover_full) + { + sl.add_cells(x, len, covers2); + } + else + { + do + { + cover = *(span1->covers) * *covers2++; + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + } + break; + + case 2: // span1 is AA, span2 is solid + covers1 = span1->covers; + if(span1->x < x) covers1 += x - span1->x; + if(*(span2->covers) == cover_full) + { + sl.add_cells(x, len, covers1); + } + else + { + do + { + cover = *covers1++ * *(span2->covers); + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + } + break; + + case 3: // Both are solid spans + cover = *(span1->covers) * *(span2->covers); + sl.add_span(x, len, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + break; + } + } + }; + + + + + + + //--------------------------------------------------sbool_unite_spans_aa + // Functor. + // Unite two spans preserving the anti-aliasing information. + // The result is added to the "sl" scanline. + //------------------ + template<class Scanline1, + class Scanline2, + class Scanline, + unsigned CoverShift = cover_shift> + struct sbool_unite_spans_aa + { + enum + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1, + cover_full = cover_mask + }; + + + void operator () (const typename Scanline1::const_iterator& span1, + const typename Scanline2::const_iterator& span2, + int x, unsigned len, + Scanline& sl) const + { + unsigned cover; + const typename Scanline1::cover_type* covers1; + const typename Scanline2::cover_type* covers2; + + // Calculate the operation code and choose the + // proper combination algorithm. + // 0 = Both spans are of AA type + // 1 = span1 is solid, span2 is AA + // 2 = span1 is AA, span2 is solid + // 3 = Both spans are of solid type + //----------------- + switch((span1->len < 0) | ((span2->len < 0) << 1)) + { + case 0: // Both are AA spans + covers1 = span1->covers; + covers2 = span2->covers; + if(span1->x < x) covers1 += x - span1->x; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = cover_mask * cover_mask - + (cover_mask - *covers1++) * + (cover_mask - *covers2++); + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + break; + + case 1: // span1 is solid, span2 is AA + covers2 = span2->covers; + if(span2->x < x) covers2 += x - span2->x; + if(*(span1->covers) == cover_full) + { + sl.add_span(x, len, cover_full); + } + else + { + do + { + cover = cover_mask * cover_mask - + (cover_mask - *(span1->covers)) * + (cover_mask - *covers2++); + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + } + break; + + case 2: // span1 is AA, span2 is solid + covers1 = span1->covers; + if(span1->x < x) covers1 += x - span1->x; + if(*(span2->covers) == cover_full) + { + sl.add_span(x, len, cover_full); + } + else + { + do + { + cover = cover_mask * cover_mask - + (cover_mask - *covers1++) * + (cover_mask - *(span2->covers)); + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + } + break; + + case 3: // Both are solid spans + cover = cover_mask * cover_mask - + (cover_mask - *(span1->covers)) * + (cover_mask - *(span2->covers)); + sl.add_span(x, len, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + break; + } + } + }; + + + //---------------------------------------------sbool_xor_formula_linear + template<unsigned CoverShift = cover_shift> + struct sbool_xor_formula_linear + { + enum + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1 + }; + + static AGG_INLINE unsigned calculate(unsigned a, unsigned b) + { + unsigned cover = a + b; + if(cover > cover_mask) cover = cover_mask + cover_mask - cover; + return cover; + } + }; + + + //---------------------------------------------sbool_xor_formula_saddle + template<unsigned CoverShift = cover_shift> + struct sbool_xor_formula_saddle + { + enum + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1 + }; + + static AGG_INLINE unsigned calculate(unsigned a, unsigned b) + { + unsigned k = a * b; + if(k == cover_mask * cover_mask) return 0; + + a = (cover_mask * cover_mask - (a << cover_shift) + k) >> cover_shift; + b = (cover_mask * cover_mask - (b << cover_shift) + k) >> cover_shift; + return cover_mask - ((a * b) >> cover_shift); + } + }; + + + //-------------------------------------------sbool_xor_formula_abs_diff + struct sbool_xor_formula_abs_diff + { + static AGG_INLINE unsigned calculate(unsigned a, unsigned b) + { + return unsigned(abs(int(a) - int(b))); + } + }; + + + + //----------------------------------------------------sbool_xor_spans_aa + // Functor. + // XOR two spans preserving the anti-aliasing information. + // The result is added to the "sl" scanline. + //------------------ + template<class Scanline1, + class Scanline2, + class Scanline, + class XorFormula, + unsigned CoverShift = cover_shift> + struct sbool_xor_spans_aa + { + enum + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1, + cover_full = cover_mask + }; + + + void operator () (const typename Scanline1::const_iterator& span1, + const typename Scanline2::const_iterator& span2, + int x, unsigned len, + Scanline& sl) const + { + unsigned cover; + const typename Scanline1::cover_type* covers1; + const typename Scanline2::cover_type* covers2; + + // Calculate the operation code and choose the + // proper combination algorithm. + // 0 = Both spans are of AA type + // 1 = span1 is solid, span2 is AA + // 2 = span1 is AA, span2 is solid + // 3 = Both spans are of solid type + //----------------- + switch((span1->len < 0) | ((span2->len < 0) << 1)) + { + case 0: // Both are AA spans + covers1 = span1->covers; + covers2 = span2->covers; + if(span1->x < x) covers1 += x - span1->x; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = XorFormula::calculate(*covers1++, *covers2++); + if(cover) sl.add_cell(x, cover); + ++x; + } + while(--len); + break; + + case 1: // span1 is solid, span2 is AA + covers2 = span2->covers; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = XorFormula::calculate(*(span1->covers), *covers2++); + if(cover) sl.add_cell(x, cover); + ++x; + } + while(--len); + break; + + case 2: // span1 is AA, span2 is solid + covers1 = span1->covers; + if(span1->x < x) covers1 += x - span1->x; + do + { + cover = XorFormula::calculate(*covers1++, *(span2->covers)); + if(cover) sl.add_cell(x, cover); + ++x; + } + while(--len); + break; + + case 3: // Both are solid spans + cover = XorFormula::calculate(*(span1->covers), *(span2->covers)); + if(cover) sl.add_span(x, len, cover); + break; + + } + } + }; + + + + + + //-----------------------------------------------sbool_subtract_spans_aa + // Functor. + // Unite two spans preserving the anti-aliasing information. + // The result is added to the "sl" scanline. + //------------------ + template<class Scanline1, + class Scanline2, + class Scanline, + unsigned CoverShift = cover_shift> + struct sbool_subtract_spans_aa + { + enum + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1, + cover_full = cover_mask + }; + + + void operator () (const typename Scanline1::const_iterator& span1, + const typename Scanline2::const_iterator& span2, + int x, unsigned len, + Scanline& sl) const + { + unsigned cover; + const typename Scanline1::cover_type* covers1; + const typename Scanline2::cover_type* covers2; + + // Calculate the operation code and choose the + // proper combination algorithm. + // 0 = Both spans are of AA type + // 1 = span1 is solid, span2 is AA + // 2 = span1 is AA, span2 is solid + // 3 = Both spans are of solid type + //----------------- + switch((span1->len < 0) | ((span2->len < 0) << 1)) + { + case 0: // Both are AA spans + covers1 = span1->covers; + covers2 = span2->covers; + if(span1->x < x) covers1 += x - span1->x; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = *covers1++ * (cover_mask - *covers2++); + if(cover) + { + sl.add_cell(x, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + ++x; + } + while(--len); + break; + + case 1: // span1 is solid, span2 is AA + covers2 = span2->covers; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = *(span1->covers) * (cover_mask - *covers2++); + if(cover) + { + sl.add_cell(x, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + ++x; + } + while(--len); + break; + + case 2: // span1 is AA, span2 is solid + covers1 = span1->covers; + if(span1->x < x) covers1 += x - span1->x; + if(*(span2->covers) != cover_full) + { + do + { + cover = *covers1++ * (cover_mask - *(span2->covers)); + if(cover) + { + sl.add_cell(x, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + ++x; + } + while(--len); + } + break; + + case 3: // Both are solid spans + cover = *(span1->covers) * (cover_mask - *(span2->covers)); + if(cover) + { + sl.add_span(x, len, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + break; + } + } + }; + + + + + + + //--------------------------------------------sbool_add_spans_and_render + template<class Scanline1, + class Scanline, + class Renderer, + class AddSpanFunctor> + void sbool_add_spans_and_render(const Scanline1& sl1, + Scanline& sl, + Renderer& ren, + AddSpanFunctor add_span) + { + sl.reset_spans(); + typename Scanline::const_iterator span = sl1.begin(); + unsigned num_spans = sl1.num_spans(); + do + { + add_span(span, span->x, abs((int)span->len), sl); + ++span; + } + while(--num_spans); + sl.finalize(sl1.y()); + ren.render(sl); + } + + + + + + + + //---------------------------------------------sbool_intersect_scanlines + // Intersect two scanlines, "sl1" and "sl2" and generate a new "sl" one. + // The combine_spans functor can be of type sbool_combine_spans_bin or + // sbool_intersect_spans_aa. First is a general functor to combine + // two spans without Anti-Aliasing, the second preserves the AA + // information, but works slower + // + template<class Scanline1, + class Scanline2, + class Scanline, + class CombineSpansFunctor> + void sbool_intersect_scanlines(const Scanline1& sl1, + const Scanline2& sl2, + Scanline& sl, + CombineSpansFunctor combine_spans) + { + sl.reset_spans(); + + unsigned num1 = sl1.num_spans(); + if(num1 == 0) return; + + unsigned num2 = sl2.num_spans(); + if(num2 == 0) return; + + typename Scanline::const_iterator span1 = sl1.begin(); + typename Scanline::const_iterator span2 = sl2.begin(); + + while(num1 && num2) + { + int xb1 = span1->x; + int xb2 = span2->x; + int xe1 = xb1 + abs((int)span1->len) - 1; + int xe2 = xb2 + abs((int)span2->len) - 1; + + // Determine what spans we should advance in the next step + // The span with the least ending X should be advanced + // advance_both is just an optimization when we ending + // coordinates are the same and we can advance both + //-------------- + bool advance_span1 = xe1 < xe2; + bool advance_both = xe1 == xe2; + + // Find the intersection of the spans + // and check if they intersect + //-------------- + if(xb1 < xb2) xb1 = xb2; + if(xe1 > xe2) xe1 = xe2; + if(xb1 <= xe1) + { + combine_spans(span1, span2, xb1, xe1 - xb1 + 1, sl); + } + + // Advance the spans + //-------------- + if(advance_both) + { + --num1; + --num2; + ++span1; + ++span2; + } + else + { + if(advance_span1) + { + --num1; + ++span1; + } + else + { + --num2; + ++span2; + } + } + } + } + + + + + + + + + //------------------------------------------------sbool_intersect_shapes + // Intersect the scanline shapes. Here the "Scanline Generator" + // abstraction is used. ScanlineGen1 and ScanlineGen2 are + // the generators, and can be of type rasterizer_scanline_aa<>. + // There function requires three scanline containers that can be of + // different types. + // "sl1" and "sl2" are used to retrieve scanlines from the generators, + // "sl" is ised as the resulting scanline to render it. + // The external "sl1" and "sl2" are used only for the sake of + // optimization and reusing of the scanline objects. + // the function calls sbool_intersect_scanlines with CombineSpansFunctor + // as the last argument. See sbool_intersect_scanlines for details. + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer, + class CombineSpansFunctor> + void sbool_intersect_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren, + CombineSpansFunctor combine_spans) + { + // Prepare the scanline generators. + // If anyone of them doesn't contain + // any scanlines, then return. + //----------------- + if(!sg1.rewind_scanlines()) return; + if(!sg2.rewind_scanlines()) return; + + // 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()); + + // Calculate the intersection of the bounding + // boxes and return if they don't intersect. + //----------------- + rect ir = intersect_rectangles(r1, r2); + if(!ir.is_valid()) return; + + // Reset the scanlines and get two first ones + //----------------- + sl.reset(ir.x1, ir.x2); + sl1.reset(sg1.min_x(), sg1.max_x()); + sl2.reset(sg2.min_x(), sg2.max_x()); + if(!sg1.sweep_scanline(sl1)) return; + if(!sg2.sweep_scanline(sl2)) return; + + ren.prepare(unsigned(ir.x2 - ir.x1 + 2)); + + // The main loop + // Here we synchronize the scanlines with + // the same Y coordinate, ignoring all other ones. + // Only scanlines having the same Y-coordinate + // are to be combined. + //----------------- + for(;;) + { + while(sl1.y() < sl2.y()) + { + if(!sg1.sweep_scanline(sl1)) return; + } + while(sl2.y() < sl1.y()) + { + if(!sg2.sweep_scanline(sl2)) return; + } + + if(sl1.y() == sl2.y()) + { + // The Y coordinates are the same. + // Combine the scanlines, render if they contain any spans, + // and advance both generators to the next scanlines + //---------------------- + sbool_intersect_scanlines(sl1, sl2, sl, combine_spans); + if(sl.num_spans()) + { + sl.finalize(sl1.y()); + ren.render(sl); + } + if(!sg1.sweep_scanline(sl1)) return; + if(!sg2.sweep_scanline(sl2)) return; + } + } + } + + + + + + + + //-------------------------------------------------sbool_unite_scanlines + // Unite two scanlines, "sl1" and "sl2" and generate a new "sl" one. + // The combine_spans functor can be of type sbool_combine_spans_bin or + // sbool_intersect_spans_aa. First is a general functor to combine + // two spans without Anti-Aliasing, the second preserves the AA + // information, but works slower + // + template<class Scanline1, + class Scanline2, + class Scanline, + class AddSpanFunctor1, + class AddSpanFunctor2, + class CombineSpansFunctor> + void sbool_unite_scanlines(const Scanline1& sl1, + const Scanline2& sl2, + Scanline& sl, + AddSpanFunctor1 add_span1, + AddSpanFunctor2 add_span2, + CombineSpansFunctor combine_spans) + { + sl.reset_spans(); + + unsigned num1 = sl1.num_spans(); + unsigned num2 = sl2.num_spans(); + + typename Scanline::const_iterator span1; + typename Scanline::const_iterator span2; + + enum { invalid_b = 0xFFFFFFF, invalid_e = invalid_b - 1 }; + + // Initialize the spans as invalid + //--------------- + int xb1 = invalid_b; + int xb2 = invalid_b; + int xe1 = invalid_e; + int xe2 = invalid_e; + + // Initialize span1 if there are spans + //--------------- + if(num1) + { + span1 = sl1.begin(); + xb1 = span1->x; + xe1 = xb1 + abs((int)span1->len) - 1; + --num1; + } + + // Initialize span2 if there are spans + //--------------- + if(num2) + { + span2 = sl2.begin(); + xb2 = span2->x; + xe2 = xb2 + abs((int)span2->len) - 1; + --num2; + } + + + for(;;) + { + // Retrieve a new span1 if it's invalid + //---------------- + if(num1 && xb1 > xe1) + { + --num1; + ++span1; + xb1 = span1->x; + xe1 = xb1 + abs((int)span1->len) - 1; + } + + // Retrieve a new span2 if it's invalid + //---------------- + if(num2 && xb2 > xe2) + { + --num2; + ++span2; + xb2 = span2->x; + xe2 = xb2 + abs((int)span2->len) - 1; + } + + if(xb1 > xe1 && xb2 > xe2) break; + + // Calculate the intersection + //---------------- + int xb = xb1; + int xe = xe1; + if(xb < xb2) xb = xb2; + if(xe > xe2) xe = xe2; + int len = xe - xb + 1; // The length of the intersection + if(len > 0) + { + // The spans intersect, + // add the beginning of the span + //---------------- + if(xb1 < xb2) + { + add_span1(span1, xb1, xb2 - xb1, sl); + xb1 = xb2; + } + else + if(xb2 < xb1) + { + add_span2(span2, xb2, xb1 - xb2, sl); + xb2 = xb1; + } + + // Add the combination part of the spans + //---------------- + combine_spans(span1, span2, xb, len, sl); + + + // Invalidate the fully processed span or both + //---------------- + if(xe1 < xe2) + { + // Invalidate span1 and eat + // the processed part of span2 + //-------------- + xb1 = invalid_b; + xe1 = invalid_e; + xb2 += len; + } + else + if(xe2 < xe1) + { + // Invalidate span2 and eat + // the processed part of span1 + //-------------- + xb2 = invalid_b; + xe2 = invalid_e; + xb1 += len; + } + else + { + xb1 = invalid_b; // Invalidate both + xb2 = invalid_b; + xe1 = invalid_e; + xe2 = invalid_e; + } + } + else + { + // The spans do not intersect + //-------------- + if(xb1 < xb2) + { + // Advance span1 + //--------------- + if(xb1 <= xe1) + { + add_span1(span1, xb1, xe1 - xb1 + 1, sl); + } + xb1 = invalid_b; // Invalidate + xe1 = invalid_e; + } + else + { + // Advance span2 + //--------------- + if(xb2 <= xe2) + { + add_span2(span2, xb2, xe2 - xb2 + 1, sl); + } + xb2 = invalid_b; // Invalidate + xe2 = invalid_e; + } + } + } + } + + + + + //----------------------------------------------------sbool_unite_shapes + // Unite the scanline shapes. Here the "Scanline Generator" + // abstraction is used. ScanlineGen1 and ScanlineGen2 are + // the generators, and can be of type rasterizer_scanline_aa<>. + // There function requires three scanline containers that can be + // of different type. + // "sl1" and "sl2" are used to retrieve scanlines from the generators, + // "sl" is ised as the resulting scanline to render it. + // The external "sl1" and "sl2" are used only for the sake of + // optimization and reusing of the scanline objects. + // the function calls sbool_unite_scanlines with CombineSpansFunctor + // as the last argument. See sbool_unite_scanlines for details. + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer, + class AddSpanFunctor1, + class AddSpanFunctor2, + class CombineSpansFunctor> + void sbool_unite_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren, + AddSpanFunctor1 add_span1, + AddSpanFunctor2 add_span2, + CombineSpansFunctor combine_spans) + { + // Prepare the scanline generators. + // If anyone of them doesn't contain + // any scanlines, then return. + //----------------- + bool flag1 = sg1.rewind_scanlines(); + bool flag2 = sg2.rewind_scanlines(); + if(!flag1 && !flag2) return; + + // 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()); + + // Calculate the union of the bounding boxes + //----------------- + rect ur = unite_rectangles(r1, r2); + if(!ur.is_valid()) return; + + ren.prepare(unsigned(ur.x2 - ur.x2 + 2)); + + // Reset the scanlines and get two first ones + //----------------- + sl.reset(ur.x1, ur.x2); + if(flag1) + { + sl1.reset(sg1.min_x(), sg1.max_x()); + flag1 = sg1.sweep_scanline(sl1); + } + + if(flag2) + { + sl2.reset(sg2.min_x(), sg2.max_x()); + flag2 = sg2.sweep_scanline(sl2); + } + + // The main loop + // Here we synchronize the scanlines with + // the same Y coordinate. + //----------------- + while(flag1 || flag2) + { + if(flag1 && flag2) + { + if(sl1.y() == sl2.y()) + { + // The Y coordinates are the same. + // Combine the scanlines, render if they contain any spans, + // and advance both generators to the next scanlines + //---------------------- + sbool_unite_scanlines(sl1, sl2, sl, + add_span1, add_span2, combine_spans); + if(sl.num_spans()) + { + sl.finalize(sl1.y()); + ren.render(sl); + } + flag1 = sg1.sweep_scanline(sl1); + flag2 = sg2.sweep_scanline(sl2); + } + else + { + if(sl1.y() < sl2.y()) + { + sbool_add_spans_and_render(sl1, sl, ren, add_span1); + flag1 = sg1.sweep_scanline(sl1); + } + else + { + sbool_add_spans_and_render(sl2, sl, ren, add_span2); + flag2 = sg2.sweep_scanline(sl2); + } + } + } + else + { + if(flag1) + { + sbool_add_spans_and_render(sl1, sl, ren, add_span1); + flag1 = sg1.sweep_scanline(sl1); + } + if(flag2) + { + sbool_add_spans_and_render(sl2, sl, ren, add_span2); + flag2 = sg2.sweep_scanline(sl2); + } + } + } + } + + + + + + + + + //-------------------------------------------------sbool_subtract_shapes + // Subtract the scanline shapes, "sg1-sg2". Here the "Scanline Generator" + // abstraction is used. ScanlineGen1 and ScanlineGen2 are + // the generators, and can be of type rasterizer_scanline_aa<>. + // There function requires three scanline containers that can be of + // different types. + // "sl1" and "sl2" are used to retrieve scanlines from the generators, + // "sl" is ised as the resulting scanline to render it. + // The external "sl1" and "sl2" are used only for the sake of + // optimization and reusing of the scanline objects. + // the function calls sbool_intersect_scanlines with CombineSpansFunctor + // as the last argument. See combine_scanlines_sub for details. + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer, + class AddSpanFunctor1, + class CombineSpansFunctor> + void sbool_subtract_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren, + AddSpanFunctor1 add_span1, + CombineSpansFunctor combine_spans) + { + // Prepare the scanline generators. + // Here "sg1" is master, "sg2" is slave. + //----------------- + if(!sg1.rewind_scanlines()) return; + bool flag2 = sg2.rewind_scanlines(); + + // Get the bounding box + //---------------- + rect r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); + + // Reset the scanlines and get two first ones + //----------------- + sl.reset(sg1.min_x(), sg1.max_x()); + sl1.reset(sg1.min_x(), sg1.max_x()); + sl2.reset(sg2.min_x(), sg2.max_x()); + if(!sg1.sweep_scanline(sl1)) return; + + if(flag2) flag2 = sg2.sweep_scanline(sl2); + + ren.prepare(unsigned(sg1.max_x() - sg1.min_x() + 2)); + + // A fake span2 processor + sbool_add_span_empty<Scanline1, Scanline> add_span2; + + // The main loop + // Here we synchronize the scanlines with + // the same Y coordinate, ignoring all other ones. + // Only scanlines having the same Y-coordinate + // are to be combined. + //----------------- + bool flag1 = true; + do + { + // Synchronize "slave" with "master" + //----------------- + while(flag2 && sl2.y() < sl1.y()) + { + flag2 = sg2.sweep_scanline(sl2); + } + + + if(flag2 && sl2.y() == sl1.y()) + { + // The Y coordinates are the same. + // Combine the scanlines and render if they contain any spans. + //---------------------- + sbool_unite_scanlines(sl1, sl2, sl, add_span1, add_span2, combine_spans); + if(sl.num_spans()) + { + sl.finalize(sl1.y()); + ren.render(sl); + } + } + else + { + sbool_add_spans_and_render(sl1, sl, ren, add_span1); + } + + // Advance the "master" + flag1 = sg1.sweep_scanline(sl1); + } + while(flag1); + } + + + + + + + + //---------------------------------------------sbool_intersect_shapes_aa + // Intersect two anti-aliased scanline shapes. + // Here the "Scanline Generator" abstraction is used. + // ScanlineGen1 and ScanlineGen2 are the generators, and can be of + // type rasterizer_scanline_aa<>. There function requires three + // scanline containers that can be of different types. + // "sl1" and "sl2" are used to retrieve scanlines from the generators, + // "sl" is ised as the resulting scanline to render it. + // The external "sl1" and "sl2" are used only for the sake of + // optimization and reusing of the scanline objects. + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_intersect_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_intersect_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; + sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor); + } + + + + + + //--------------------------------------------sbool_intersect_shapes_bin + // Intersect two binary scanline shapes (without anti-aliasing). + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_intersect_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor; + sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor); + } + + + + + + //-------------------------------------------------sbool_unite_shapes_aa + // Unite two anti-aliased scanline shapes + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_unite_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa<Scanline1, Scanline> add_functor1; + sbool_add_span_aa<Scanline2, Scanline> add_functor2; + sbool_unite_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + + + //------------------------------------------------sbool_unite_shapes_bin + // Unite two binary scanline shapes (without anti-aliasing). + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_unite_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_bin<Scanline1, Scanline> add_functor1; + sbool_add_span_bin<Scanline2, Scanline> add_functor2; + sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + + + + + + + //---------------------------------------------------sbool_xor_shapes_aa + // Apply eXclusive OR to two anti-aliased scanline shapes. There's + // a modified "Linear" XOR used instead of classical "Saddle" one. + // The reason is to have the result absolutely conststent with what + // the scanline rasterizer produces. + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_xor_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa<Scanline1, Scanline> add_functor1; + sbool_add_span_aa<Scanline2, Scanline> add_functor2; + sbool_xor_spans_aa<Scanline1, Scanline2, Scanline, + sbool_xor_formula_linear<> > combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + //------------------------------------------sbool_xor_shapes_saddle_aa + // Apply eXclusive OR to two anti-aliased scanline shapes. + // There's the classical "Saddle" used to calculate the + // Anti-Aliasing values, that is: + // a XOR b : 1-((1-a+a*b)*(1-b+a*b)) + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_xor_shapes_saddle_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa<Scanline1, Scanline> add_functor1; + sbool_add_span_aa<Scanline2, Scanline> add_functor2; + sbool_xor_spans_aa<Scanline1, + Scanline2, + Scanline, + sbool_xor_formula_saddle<> > combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + //--------------------------------------sbool_xor_shapes_abs_diff_aa + // Apply eXclusive OR to two anti-aliased scanline shapes. + // There's the absolute difference used to calculate + // Anti-Aliasing values, that is: + // a XOR b : abs(a-b) + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_xor_shapes_abs_diff_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa<Scanline1, Scanline> add_functor1; + sbool_add_span_aa<Scanline2, Scanline> add_functor2; + sbool_xor_spans_aa<Scanline1, + Scanline2, + Scanline, + sbool_xor_formula_abs_diff> combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + //--------------------------------------------------sbool_xor_shapes_bin + // Apply eXclusive OR to two binary scanline shapes (without anti-aliasing). + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_xor_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_bin<Scanline1, Scanline> add_functor1; + sbool_add_span_bin<Scanline2, Scanline> add_functor2; + sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + + + + //----------------------------------------------sbool_subtract_shapes_aa + // Subtract shapes "sg1-sg2" with anti-aliasing + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_subtract_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa<Scanline1, Scanline> add_functor; + sbool_subtract_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; + sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor, combine_functor); + } + + + + + + //---------------------------------------------sbool_subtract_shapes_bin + // Subtract binary shapes "sg1-sg2" without anti-aliasing + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_subtract_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_bin<Scanline1, Scanline> add_functor; + sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor; + sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor, combine_functor); + } + + + + + + + //------------------------------------------------------------sbool_op_e + enum sbool_op_e + { + sbool_or, //----sbool_or + sbool_and, //----sbool_and + sbool_xor, //----sbool_xor + sbool_xor_saddle, //----sbool_xor_saddle + sbool_xor_abs_diff, //----sbool_xor_abs_diff + sbool_a_minus_b, //----sbool_a_minus_b + sbool_b_minus_a //----sbool_b_minus_a + }; + + + + + + + //----------------------------------------------sbool_combine_shapes_bin + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_combine_shapes_bin(sbool_op_e op, + ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + switch(op) + { + case sbool_or : sbool_unite_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_and : sbool_intersect_shapes_bin(sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor : + case sbool_xor_saddle : + case sbool_xor_abs_diff: sbool_xor_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_a_minus_b : sbool_subtract_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_b_minus_a : sbool_subtract_shapes_bin (sg2, sg1, sl2, sl1, sl, ren); break; + } + } + + + + + //-----------------------------------------------sbool_combine_shapes_aa + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_combine_shapes_aa(sbool_op_e op, + ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + switch(op) + { + case sbool_or : sbool_unite_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_and : sbool_intersect_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor : sbool_xor_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor_saddle : sbool_xor_shapes_saddle_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor_abs_diff: sbool_xor_shapes_abs_diff_aa(sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_a_minus_b : sbool_subtract_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_b_minus_a : sbool_subtract_shapes_aa (sg2, sg1, sl2, sl1, sl, ren); break; + } + } + +} + + +#endif + diff --git a/agg/inc/agg_scanline_p.h b/agg/inc/agg_scanline_p.h new file mode 100755 index 000000000000..f217998578a1 --- /dev/null +++ b/agg/inc/agg_scanline_p.h @@ -0,0 +1,197 @@ +//---------------------------------------------------------------------------- +// 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 scanline_p - a general purpose scanline container with packed spans. +// +//---------------------------------------------------------------------------- +#ifndef AGG_SCANLINE_P_INCLUDED +#define AGG_SCANLINE_P_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //==============================================================scanline_p + // + // This is a general purpose scaline container which supports the interface + // used in the rasterizer::render(). See description of agg_scanline_u + // for details. + // + //------------------------------------------------------------------------ + template<class T> class scanline_p + { + public: + typedef T cover_type; + + struct span + { + int16 x; + int16 len; // If negative, it's a solid span, covers is valid + const T* covers; + }; + + typedef span* iterator; + typedef const span* const_iterator; + + ~scanline_p() + { + delete [] m_spans; + delete [] m_covers; + } + + scanline_p() : + m_max_len(0), + m_last_x(0x7FFFFFF0), + m_covers(0), + m_cover_ptr(0), + m_spans(0), + 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(); + + 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; } + + 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; + }; + + + //------------------------------------------------------------------------ + 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) + { + *m_cover_ptr = (T)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++; + } + + + //------------------------------------------------------------------------ + 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) + { + 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; + } + + + //------------------------------------------------------------------------ + 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) + { + m_cur_span->len -= (int16)len; + } + else + { + *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 = x + len - 1; + } + + + //=============================================================scanline_p8 + typedef scanline_p<int8u> scanline_p8; + + //============================================================scanline_p16 + typedef scanline_p<int16u> scanline_p16; + + //============================================================scanline_p32 + typedef scanline_p<int32u> scanline_p32; +} + + +#endif + diff --git a/agg/inc/agg_scanline_storage_aa.h b/agg/inc/agg_scanline_storage_aa.h new file mode 100755 index 000000000000..3d8b5b946cf9 --- /dev/null +++ b/agg/inc/agg_scanline_storage_aa.h @@ -0,0 +1,796 @@ +//---------------------------------------------------------------------------- +// 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_SCANLINE_STORAGE_AA_INCLUDED +#define AGG_SCANLINE_STORAGE_AA_INCLUDED + +#include <string.h> +#include <stdlib.h> +#include <math.h> +#include "agg_array.h" +#include "agg_render_scanlines.h" + + +namespace agg +{ + + //----------------------------------------------scanline_cell_storage + template<class T> class scanline_cell_storage + { + struct extra_span + { + unsigned len; + T* ptr; + }; + + public: + typedef T value_type; + + //--------------------------------------------------------------- + ~scanline_cell_storage() + { + remove_all(); + } + + //--------------------------------------------------------------- + scanline_cell_storage() : + m_cells(128-2), + m_extra_storage() + {} + + + // Copying + //--------------------------------------------------------------- + scanline_cell_storage(const scanline_cell_storage<T>& v) : + m_cells(v.m_cells), + m_extra_storage() + { + copy_extra_storage(v); + } + + //--------------------------------------------------------------- + const scanline_cell_storage<T>& + operator = (const scanline_cell_storage<T>& v) + { + remove_all(); + m_cells = v.m_cells; + copy_extra_storage(v); + return *this; + } + + //--------------------------------------------------------------- + void remove_all() + { + int i; + for(i = m_extra_storage.size()-1; i >= 0; --i) + { + delete [] m_extra_storage[(unsigned)i].ptr; + } + m_extra_storage.remove_all(); + m_cells.remove_all(); + } + + //--------------------------------------------------------------- + int add_cells(const T* cells, unsigned num_cells) + { + int idx = m_cells.allocate_continuous_block(num_cells); + if(idx >= 0) + { + T* ptr = &m_cells[idx]; + memcpy(ptr, cells, sizeof(T) * num_cells); + return idx; + } + extra_span s; + s.len = num_cells; + s.ptr = new T [num_cells]; + memcpy(s.ptr, cells, sizeof(T) * num_cells); + m_extra_storage.add(s); + return -int(m_extra_storage.size()); + } + + //--------------------------------------------------------------- + const T* operator [] (int idx) const + { + if(idx >= 0) + { + if((unsigned)idx >= m_cells.size()) return 0; + return &m_cells[(unsigned)idx]; + } + unsigned i = unsigned(-idx - 1); + if(i >= m_extra_storage.size()) return 0; + return m_extra_storage[i].ptr; + } + + //--------------------------------------------------------------- + T* operator [] (int idx) + { + if(idx >= 0) + { + if((unsigned)idx >= m_cells.size()) return 0; + return &m_cells[(unsigned)idx]; + } + unsigned i = unsigned(-idx - 1); + if(i >= m_extra_storage.size()) return 0; + return m_extra_storage[i].ptr; + } + + private: + void copy_extra_storage(const scanline_cell_storage<T>& v) + { + unsigned i; + for(i = 0; i < v.m_extra_storage.size(); ++i) + { + const extra_span& src = v.m_extra_storage[i]; + extra_span dst; + dst.len = src.len; + dst.ptr = new T [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; + }; + + + + + + + //-----------------------------------------------scanline_storage_aa + template<class T> class scanline_storage_aa + { + public: + typedef T cover_type; + + //--------------------------------------------------------------- + struct span_data + { + int16 x; + int16 len; // If negative, it's a solid span, covers is valid + int covers_id; // The index of the cells in the scanline_cell_storage + }; + + //--------------------------------------------------------------- + struct scanline_data + { + int y; + unsigned num_spans; + unsigned start_span; + }; + + + //--------------------------------------------------------------- + class embedded_scanline + { + public: + + //----------------------------------------------------------- + class const_iterator + { + public: + struct span + { + int16 x; + int16 len; // If negative, it's a solid span, covers is valid + const T* covers; + }; + + const_iterator(const embedded_scanline& sl) : + m_storage(sl.m_storage), + m_span_idx(sl.m_scanline.start_span) + { + init_span(); + } + + const span& operator*() const { return m_span; } + const span* operator->() const { return &m_span; } + + void operator ++ () + { + ++m_span_idx; + init_span(); + } + + private: + void init_span() + { + const span_data& s = m_storage->span_by_index(m_span_idx); + m_span.x = s.x; + m_span.len = s.len; + m_span.covers = m_storage->covers_by_index(s.covers_id); + } + + const scanline_storage_aa* m_storage; + unsigned m_span_idx; + span m_span; + }; + + friend class const_iterator; + + + //----------------------------------------------------------- + embedded_scanline(const scanline_storage_aa& storage) : + m_storage(&storage) + { + init(0); + } + + //----------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_scanline.num_spans; } + int y() const { return m_scanline.y; } + const_iterator begin() const { return const_iterator(*this); } + + //----------------------------------------------------------- + void init(unsigned scanline_idx) + { + m_scanline_idx = scanline_idx; + m_scanline = m_storage->scanline_by_index(m_scanline_idx); + } + + private: + const scanline_storage_aa* m_storage; + scanline_data m_scanline; + unsigned m_scanline_idx; + }; + + + //--------------------------------------------------------------- + scanline_storage_aa() : + m_covers(), + m_spans(256-2), // Block increment size + m_scanlines(), + m_min_x( 0x7FFFFFFF), + m_min_y( 0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF), + m_cur_scanline(0) + { + m_fake_scanline.y = 0; + m_fake_scanline.num_spans = 0; + m_fake_scanline.start_span = 0; + m_fake_span.x = 0; + m_fake_span.len = 0; + m_fake_span.covers_id = 0; + } + + // Renderer Interface + //--------------------------------------------------------------- + void prepare(unsigned) + { + m_covers.remove_all(); + m_scanlines.remove_all(); + m_spans.remove_all(); + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + m_cur_scanline = 0; + } + + //--------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + scanline_data sl_this; + + int y = sl.y(); + if(y < m_min_y) m_min_y = y; + if(y > m_max_y) m_max_y = y; + + sl_this.y = y; + sl_this.num_spans = sl.num_spans(); + sl_this.start_span = m_spans.size(); + typename Scanline::const_iterator span_iterator = sl.begin(); + + unsigned num_spans = sl_this.num_spans; + do + { + span_data sp; + + sp.x = span_iterator->x; + sp.len = span_iterator->len; + int len = abs(int(sp.len)); + sp.covers_id = + m_covers.add_cells(span_iterator->covers, + unsigned(len)); + m_spans.add(sp); + int x1 = sp.x; + int x2 = sp.x + len - 1; + if(x1 < m_min_x) m_min_x = x1; + if(x2 > m_max_x) m_max_x = x2; + ++span_iterator; + } + while(--num_spans); + m_scanlines.add(sl_this); + } + + + //--------------------------------------------------------------- + // Iterate scanlines interface + 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; } + + //--------------------------------------------------------------- + bool rewind_scanlines() + { + m_cur_scanline = 0; + return m_scanlines.size() > 0; + } + + + //--------------------------------------------------------------- + template<class Scanline> bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + if(m_cur_scanline >= m_scanlines.size()) return false; + const scanline_data& sl_this = m_scanlines[m_cur_scanline]; + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + const T* covers = covers_by_index(sp.covers_id); + if(sp.len < 0) + { + sl.add_span(sp.x, unsigned(-sp.len), *covers); + } + else + { + sl.add_cells(sp.x, sp.len, covers); + } + } + while(--num_spans); + ++m_cur_scanline; + if(sl.num_spans()) + { + sl.finalize(sl_this.y); + break; + } + } + return true; + } + + + //--------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_cur_scanline >= m_scanlines.size()) return false; + sl.init(m_cur_scanline); + ++m_cur_scanline; + } + while(sl.num_spans() == 0); + return true; + } + + //--------------------------------------------------------------- + unsigned byte_size() const + { + unsigned i; + unsigned size = sizeof(int16) * 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 + + const scanline_data& sl_this = m_scanlines[i]; + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + + size += sizeof(int16) * 2; // X, span_len + if(sp.len < 0) + { + size += sizeof(T); // cover + } + else + { + size += sizeof(T) * unsigned(sp.len); // covers + } + } + while(--num_spans); + } + return size; + } + + + //--------------------------------------------------------------- + static void write_int16(int8u* dst, int16 val) + { + dst[0] = ((const int8u*)&val)[0]; + dst[1] = ((const int8u*)&val)[1]; + } + + + //--------------------------------------------------------------- + void serialize(int8u* data) const + { + 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); + + 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 + + write_int16(data, int16(sl_this.y)); // Y + data += sizeof(int16); + + write_int16(data, int16(sl_this.num_spans)); // num_spans + data += sizeof(int16); + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + 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_int16(data, int16(sp.len)); // span_len + data += sizeof(int16); + + if(sp.len < 0) + { + memcpy(data, covers, sizeof(T)); + data += sizeof(T); + } + else + { + memcpy(data, covers, unsigned(sp.len) * sizeof(T)); + data += sizeof(T) * unsigned(sp.len); + } + } + while(--num_spans); + write_int16(size_ptr, int16(unsigned(data - size_ptr))); + } + } + + + //--------------------------------------------------------------- + const scanline_data& scanline_by_index(unsigned i) const + { + return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline; + } + + //--------------------------------------------------------------- + const span_data& span_by_index(unsigned i) const + { + return (i < m_spans.size()) ? m_spans[i] : m_fake_span; + } + + //--------------------------------------------------------------- + const T* covers_by_index(int i) const + { + return m_covers[i]; + } + + private: + scanline_cell_storage<T> m_covers; + pod_deque<span_data, 10> m_spans; + pod_deque<scanline_data, 8> m_scanlines; + span_data m_fake_span; + scanline_data m_fake_scanline; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + unsigned m_cur_scanline; + }; + + + typedef scanline_storage_aa<int8u> scanline_storage_aa8; //--------scanline_storage_aa8 + typedef scanline_storage_aa<int16u> scanline_storage_aa16; //--------scanline_storage_aa16 + typedef scanline_storage_aa<int32u> scanline_storage_aa32; //--------scanline_storage_aa32 + + + + + //------------------------------------------serialized_scanlines_adaptor_aa + template<class T> class serialized_scanlines_adaptor_aa + { + public: + typedef T cover_type; + + //--------------------------------------------------------------------- + class embedded_scanline + { + public: + typedef T cover_type; + + //----------------------------------------------------------------- + class const_iterator + { + public: + struct span + { + int16 x; + int16 len; // If negative, it's a solid span, "covers" is valid + const T* covers; + }; + + const_iterator(const embedded_scanline& sl) : + m_ptr(sl.m_ptr), + m_dx(sl.m_dx) + { + init_span(); + } + + const span& operator*() const { return m_span; } + const span* operator->() const { return &m_span; } + + void operator ++ () + { + if(m_span.len < 0) + { + m_ptr += sizeof(T); + } + else + { + m_ptr += m_span.len * sizeof(T); + } + init_span(); + } + + private: + int read_int16() + { + int16 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + return val; + } + + void init_span() + { + m_span.x = read_int16() + m_dx; + m_span.len = read_int16(); + m_span.covers = m_ptr; + } + + const int8u* m_ptr; + span m_span; + int m_dx; + }; + + friend class const_iterator; + + + //----------------------------------------------------------------- + embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {} + + //----------------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_num_spans; } + int y() const { return m_y; } + const_iterator begin() const { return const_iterator(*this); } + + + private: + //----------------------------------------------------------------- + int read_int16() + { + int16 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + return val; + } + + public: + //----------------------------------------------------------------- + void init(const int8u* ptr, int dx, int dy) + { + m_ptr = ptr; + m_y = read_int16() + dy; + m_num_spans = unsigned(read_int16()); + m_dx = dx; + } + + private: + const int8u* m_ptr; + int m_y; + unsigned m_num_spans; + int m_dx; + }; + + + + public: + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_aa() : + m_data(0), + m_end(0), + m_ptr(0), + m_dx(0), + m_dy(0), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_aa(const int8u* data, unsigned size, + double dx, double dy) : + 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_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + void init(const int8u* data, unsigned size, double dx, double dy) + { + 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_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + } + + private: + //-------------------------------------------------------------------- + int read_int16() + { + int16 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + return val; + } + + //-------------------------------------------------------------------- + unsigned read_int16u() + { + int16u val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + return val; + } + + public: + // Iterate scanlines interface + //-------------------------------------------------------------------- + bool rewind_scanlines() + { + 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; + } + return false; + } + + //-------------------------------------------------------------------- + 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; } + + //-------------------------------------------------------------------- + template<class Scanline> bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + 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(); + + do + { + int x = read_int16() + m_dx; + int len = read_int16(); + + if(len < 0) + { + sl.add_span(x, unsigned(-len), *m_ptr); + m_ptr += sizeof(T); + } + else + { + sl.add_cells(x, len, m_ptr); + m_ptr += len * sizeof(T); + } + } + while(--num_spans); + + if(sl.num_spans()) + { + sl.finalize(y); + break; + } + } + return true; + } + + + //-------------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_ptr >= m_end) return false; + + unsigned byte_size = read_int16u(); + sl.init(m_ptr, m_dx, m_dy); + m_ptr += byte_size - sizeof(int16); + } + while(sl.num_spans() == 0); + return true; + } + + private: + const int8u* m_data; + const int8u* m_end; + const int8u* m_ptr; + int m_dx; + int m_dy; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + }; + + + + typedef serialized_scanlines_adaptor_aa<int8u> serialized_scanlines_adaptor_aa8; //----serialized_scanlines_adaptor_aa8 + typedef serialized_scanlines_adaptor_aa<int16u> serialized_scanlines_adaptor_aa16; //----serialized_scanlines_adaptor_aa16 + typedef serialized_scanlines_adaptor_aa<int32u> serialized_scanlines_adaptor_aa32; //----serialized_scanlines_adaptor_aa32 + +} + + +#endif + diff --git a/agg/inc/agg_scanline_storage_bin.h b/agg/inc/agg_scanline_storage_bin.h new file mode 100755 index 000000000000..90fa50e4ee6d --- /dev/null +++ b/agg/inc/agg_scanline_storage_bin.h @@ -0,0 +1,569 @@ +//---------------------------------------------------------------------------- +// 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_SCANLINE_STORAGE_BIN_INCLUDED +#define AGG_SCANLINE_STORAGE_BIN_INCLUDED + +#include <string.h> +#include <stdlib.h> +#include <math.h> +#include "agg_array.h" +#include "agg_render_scanlines.h" + + +namespace agg +{ + + //-----------------------------------------------scanline_storage_bin + class scanline_storage_bin + { + public: + //--------------------------------------------------------------- + struct span_data + { + int16 x; + int16 len; + }; + + //--------------------------------------------------------------- + struct scanline_data + { + int y; + unsigned num_spans; + unsigned start_span; + }; + + + //--------------------------------------------------------------- + class embedded_scanline + { + public: + + //----------------------------------------------------------- + class const_iterator + { + public: + const_iterator(const embedded_scanline& sl) : + m_storage(sl.m_storage), + m_span_idx(sl.m_scanline.start_span) + { + m_span = m_storage->span_by_index(m_span_idx); + } + + const span_data& operator*() const { return m_span; } + const span_data* operator->() const { return &m_span; } + + void operator ++ () + { + ++m_span_idx; + m_span = m_storage->span_by_index(m_span_idx); + } + + private: + const scanline_storage_bin* m_storage; + unsigned m_span_idx; + span_data m_span; + }; + + friend class const_iterator; + + + //----------------------------------------------------------- + embedded_scanline(const scanline_storage_bin& storage) : + m_storage(&storage) + { + setup(0); + } + + //----------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_scanline.num_spans; } + int y() const { return m_scanline.y; } + const_iterator begin() const { return const_iterator(*this); } + + //----------------------------------------------------------- + void setup(unsigned scanline_idx) + { + m_scanline_idx = scanline_idx; + m_scanline = m_storage->scanline_by_index(m_scanline_idx); + } + + private: + const scanline_storage_bin* m_storage; + scanline_data m_scanline; + unsigned m_scanline_idx; + }; + + + //--------------------------------------------------------------- + scanline_storage_bin() : + m_spans(256-2), // Block increment size + m_scanlines(), + m_min_x( 0x7FFFFFFF), + m_min_y( 0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF), + m_cur_scanline(0) + { + m_fake_scanline.y = 0; + m_fake_scanline.num_spans = 0; + m_fake_scanline.start_span = 0; + m_fake_span.x = 0; + m_fake_span.len = 0; + } + + // Renderer Interface + //--------------------------------------------------------------- + void prepare(unsigned) + { + m_scanlines.remove_all(); + m_spans.remove_all(); + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + m_cur_scanline = 0; + } + + //--------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + scanline_data sl_this; + + int y = sl.y(); + if(y < m_min_y) m_min_y = y; + if(y > m_max_y) m_max_y = y; + + sl_this.y = y; + sl_this.num_spans = sl.num_spans(); + sl_this.start_span = m_spans.size(); + typename Scanline::const_iterator span_iterator = sl.begin(); + + unsigned num_spans = sl_this.num_spans; + do + { + span_data sp; + sp.x = span_iterator->x; + sp.len = (int16)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; + ++span_iterator; + } + while(--num_spans); + m_scanlines.add(sl_this); + } + + + //--------------------------------------------------------------- + // Iterate scanlines interface + 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; } + + //--------------------------------------------------------------- + bool rewind_scanlines() + { + m_cur_scanline = 0; + return m_scanlines.size() > 0; + } + + + //--------------------------------------------------------------- + template<class Scanline> bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + if(m_cur_scanline >= m_scanlines.size()) return false; + const scanline_data& sl_this = m_scanlines[m_cur_scanline]; + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + sl.add_span(sp.x, sp.len, cover_full); + } + while(--num_spans); + + ++m_cur_scanline; + if(sl.num_spans()) + { + sl.finalize(sl_this.y); + break; + } + } + return true; + } + + + //--------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_cur_scanline >= m_scanlines.size()) return false; + sl.setup(m_cur_scanline); + ++m_cur_scanline; + } + while(sl.num_spans() == 0); + return true; + } + + + //--------------------------------------------------------------- + unsigned byte_size() const + { + unsigned i; + unsigned size = sizeof(int16) * 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 + } + return size; + } + + + //--------------------------------------------------------------- + static void write_int16(int8u* dst, int16 val) + { + dst[0] = ((const int8u*)&val)[0]; + dst[1] = ((const int8u*)&val)[1]; + } + + + //--------------------------------------------------------------- + void serialize(int8u* data) const + { + 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); + + 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_int16(data, int16(sl_this.num_spans)); // num_spans + data += sizeof(int16); + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + + write_int16(data, int16(sp.x)); // X + data += sizeof(int16); + + write_int16(data, int16(sp.len)); // len + data += sizeof(int16); + } + while(--num_spans); + } + } + + + //--------------------------------------------------------------- + const scanline_data& scanline_by_index(unsigned i) const + { + return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline; + } + + //--------------------------------------------------------------- + const span_data& span_by_index(unsigned i) const + { + return (i < m_spans.size()) ? m_spans[i] : m_fake_span; + } + + + private: + pod_deque<span_data, 10> m_spans; + pod_deque<scanline_data, 8> m_scanlines; + span_data m_fake_span; + scanline_data m_fake_scanline; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + unsigned m_cur_scanline; + }; + + + + + + + + + + + + + + //---------------------------------------serialized_scanlines_adaptor_bin + class serialized_scanlines_adaptor_bin + { + public: + typedef bool cover_type; + + //-------------------------------------------------------------------- + class embedded_scanline + { + public: + + //---------------------------------------------------------------- + class const_iterator + { + public: + struct span + { + int16 x; + int16 len; + }; + + 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(); + } + + const span& operator*() const { return m_span; } + const span* operator->() const { return &m_span; } + + void operator ++ () + { + m_span.x = read_int16() + m_dx; + m_span.len = read_int16(); + } + + private: + int read_int16() + { + int16 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + return val; + } + + const int8u* m_ptr; + span m_span; + int m_dx; + }; + + friend class const_iterator; + + + //---------------------------------------------------------------- + embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {} + + //---------------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_num_spans; } + int y() const { return m_y; } + const_iterator begin() const { return const_iterator(*this); } + + + private: + //---------------------------------------------------------------- + int read_int16() + { + int16 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + return val; + } + + public: + //---------------------------------------------------------------- + void init(const int8u* ptr, int dx, int dy) + { + m_ptr = ptr; + m_y = read_int16() + dy; + m_num_spans = unsigned(read_int16()); + m_dx = dx; + } + + private: + const int8u* m_ptr; + int m_y; + unsigned m_num_spans; + int m_dx; + }; + + + + public: + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_bin() : + m_data(0), + m_end(0), + m_ptr(0), + m_dx(0), + m_dy(0), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_bin(const int8u* data, unsigned size, + double dx, double dy) : + 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_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + void init(const int8u* data, unsigned size, double dx, double dy) + { + 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_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + } + + private: + //-------------------------------------------------------------------- + int read_int16() + { + int16 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + return val; + } + + public: + // Iterate scanlines interface + //-------------------------------------------------------------------- + bool rewind_scanlines() + { + 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; + } + return false; + } + + //-------------------------------------------------------------------- + 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; } + + //-------------------------------------------------------------------- + template<class Scanline> bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + if(m_ptr >= m_end) return false; + + int y = read_int16() + m_dy; + unsigned num_spans = read_int16(); + + do + { + int x = read_int16() + m_dx; + int len = read_int16(); + + if(len < 0) len = -len; + sl.add_span(x, unsigned(len), cover_full); + } + while(--num_spans); + + if(sl.num_spans()) + { + sl.finalize(y); + break; + } + } + return true; + } + + + //-------------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_ptr >= m_end) return false; + + sl.init(m_ptr, m_dx, m_dy); + + // Jump to the next scanline + //-------------------------- + read_int16(); // Y + int num_spans = read_int16(); // num_spans + m_ptr += num_spans * sizeof(int16) * 2; + } + while(sl.num_spans() == 0); + return true; + } + + private: + const int8u* m_data; + const int8u* m_end; + const int8u* m_ptr; + int m_dx; + int m_dy; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + }; + + + +} + +#endif + diff --git a/agg/inc/agg_scanline_u.h b/agg/inc/agg_scanline_u.h new file mode 100755 index 000000000000..749c5b3c0054 --- /dev/null +++ b/agg/inc/agg_scanline_u.h @@ -0,0 +1,323 @@ +//---------------------------------------------------------------------------- +// 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_SCANLINE_U_INCLUDED +#define AGG_SCANLINE_U_INCLUDED + +#include <string.h> +#include "agg_basics.h" + +namespace agg +{ + //==============================================================scanline_u + // + // Unpacked scanline container class + // + // This class is used to transfer data from a scanline rastyerizer + // 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 + // cover-values for each pixel. + // Before using this class you should know the minimal and maximal pixel + // coordinates of your scanline. The protocol of using is: + // 1. reset(min_x, max_x) + // 2. add_cell() / add_span() - accumulate scanline. + // When forming one scanline the next X coordinate must be always greater + // than the last stored one, i.e. it works only with ordered coordinates. + // 3. Call finalize(y) and render the scanline. + // 3. Call reset_spans() to prepare for the new scanline. + // + // 4. Rendering: + // + // Scanline provides an iterator class that allows you to extract + // the spans and the cover values for each pixel. Be aware that clipping + // has not been done yet, so you should perform it yourself. + // Use scanline_u8::iterator to render spans: + //------------------------------------------------------------------------- + // + // int y = sl.y(); // Y-coordinate of the scanline + // + // ************************************ + // ...Perform vertical clipping here... + // ************************************ + // + // scanline_u8::const_iterator span = sl.begin(); + // + // unsigned char* row = m_rbuf->row(y); // The the address of the beginning + // // of the current row + // + // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that + // // num_spans is always greater than 0. + // + // do + // { + // const scanline_u8::cover_type* covers = + // span->covers; // The array of the cover values + // + // int num_pix = span->len; // Number of pixels of the span. + // // Always greater than 0, still it's + // // better to use "int" instead of + // // "unsigned" because it's more + // // convenient for clipping + // int x = span->x; + // + // ************************************** + // ...Perform horizontal clipping here... + // ...you have x, covers, and pix_count.. + // ************************************** + // + // unsigned char* dst = row + x; // Calculate the start address of the row. + // // In this case we assume a simple + // // grayscale image 1-byte per pixel. + // do + // { + // *dst++ = *covers++; // Hypotetical rendering. + // } + // while(--num_pix); + // + // ++span; + // } + // while(--num_spans); // num_spans cannot be 0, so this loop is quite safe + //------------------------------------------------------------------------ + // + // 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 + // 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. + //------------------------------------------------------------------------ + template<class T> class scanline_u + { + public: + typedef T cover_type; + + //-------------------------------------------------------------------- + struct span + { + int16 x; + int16 len; + cover_type* covers; + }; + + typedef span* iterator; + typedef const span* const_iterator; + + //-------------------------------------------------------------------- + ~scanline_u(); + scanline_u(); + + 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(); + + 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; } + + private: + scanline_u<T>(const scanline_u<T>&); + const scanline_u<T>& operator = (const scanline_u<T>&); + + 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; + }; + + + + //------------------------------------------------------------------------ + template<class T> scanline_u<T>::~scanline_u() + { + delete [] m_spans; + delete [] m_covers; + } + + + //------------------------------------------------------------------------ + 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 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) + { + delete [] m_spans; + delete [] m_covers; + m_covers = new cover_type [max_len]; + m_spans = new span [max_len]; + m_max_len = max_len; + } + m_last_x = 0x7FFFFFF0; + m_min_x = min_x; + m_cur_span = m_spans; + } + + + //------------------------------------------------------------------------ + 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) + { + x -= m_min_x; + m_covers[x] = (unsigned char)cover; + if(x == m_last_x+1) + { + m_cur_span->len++; + } + else + { + 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; + } + + + //------------------------------------------------------------------------ + 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) + { + m_cur_span->len += (int16)len; + } + else + { + 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 = 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) + { + m_cur_span->len += (int16)len; + } + else + { + 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 = x + len - 1; + } + + + //=============================================================scanline_u8 + typedef scanline_u<int8u> scanline_u8; + + //============================================================scanline_u16 + typedef scanline_u<int16u> scanline_u16; + + //============================================================scanline_u32 + typedef scanline_u<int32u> scanline_u32; + + + //=============================================================scanline_am + // + // The scanline container with alpha-masking + // + //------------------------------------------------------------------------ + template<class AlphaMask, class CoverT> + class scanline_am : public scanline_u<CoverT> + { + public: + typedef AlphaMask alpha_mask_type; + typedef CoverT cover_type; + typedef scanline_u<CoverT> scanline_type; + + scanline_am() : scanline_type(), m_alpha_mask(0) {} + scanline_am(const AlphaMask& am) : scanline_type(), m_alpha_mask(&am) {} + + //-------------------------------------------------------------------- + void finalize(int span_y) + { + scanline_u<CoverT>::finalize(span_y); + if(m_alpha_mask) + { + typename scanline_type::iterator span = scanline_type::begin(); + unsigned count = scanline_type::num_spans(); + do + { + m_alpha_mask->combine_hspan(span->x, + scanline_type::y(), + span->covers, + span->len); + ++span; + } + while(--count); + } + } + + private: + const AlphaMask* m_alpha_mask; + }; + + + //==========================================================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) {} + }; + +} + +#endif + diff --git a/agg/inc/agg_shorten_path.h b/agg/inc/agg_shorten_path.h new file mode 100755 index 000000000000..271d2a7ec572 --- /dev/null +++ b/agg/inc/agg_shorten_path.h @@ -0,0 +1,66 @@ +//---------------------------------------------------------------------------- +// 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_SHORTEN_PATH_INCLUDED +#define AGG_SHORTEN_PATH_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + //===========================================================shorten_path + template<class VertexSequence> + void shorten_path(VertexSequence& vs, double s, unsigned closed = 0) + { + typedef typename VertexSequence::value_type vertex_type; + + if(s > 0.0 && vs.size() > 1) + { + double d; + int n = int(vs.size() - 2); + while(n) + { + d = vs[n].dist; + if(d > s) break; + vs.remove_last(); + s -= d; + --n; + } + if(vs.size() < 2) + { + vs.remove_all(); + } + else + { + n = vs.size() - 1; + vertex_type& prev = vs[n-1]; + vertex_type& last = vs[n]; + d = (prev.dist - s) / prev.dist; + double x = prev.x + (last.x - prev.x) * d; + double y = prev.y + (last.y - prev.y) * d; + last.x = x; + last.y = y; + if(!prev(last)) vs.remove_last(); + vs.close(closed != 0); + } + } + } + + +} + +#endif diff --git a/agg/inc/agg_simul_eq.h b/agg/inc/agg_simul_eq.h new file mode 100755 index 000000000000..f52662e82926 --- /dev/null +++ b/agg/inc/agg_simul_eq.h @@ -0,0 +1,147 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Solving simultaneous equations +// +//---------------------------------------------------------------------------- +#ifndef AGG_SIMUL_EQ_INCLUDED +#define AGG_SIMUL_EQ_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + + //=============================================================swap_arrays + template<class T> void swap_arrays(T* a1, T* a2, unsigned n) + { + unsigned i; + for(i = 0; i < n; i++) + { + T tmp = *a1; + *a1++ = *a2; + *a2++ = tmp; + } + } + + + //============================================================matrix_pivot + template<unsigned Rows, unsigned Cols> + struct matrix_pivot + { + static int pivot(double m[Rows][Cols], unsigned row) + { + int k = int(row); + double max_val, tmp; + + max_val = -1.0; + unsigned i; + for(i = row; i < Rows; i++) + { + if((tmp = fabs(m[i][row])) > max_val && tmp != 0.0) + { + max_val = tmp; + k = i; + } + } + + if(m[k][row] == 0.0) + { + return -1; + } + + if(k != int(row)) + { + swap_arrays(m[k], m[row], Cols); + return k; + } + return 0; + } + }; + + + + //===============================================================simul_eq + template<unsigned Size, unsigned RightCols> + struct simul_eq + { + static bool solve(const double left[Size][Size], + const double right[Size][RightCols], + double result[Size][RightCols]) + { + unsigned i, j, k; + double a1; + + double tmp[Size][Size + RightCols]; + + for(i = 0; i < Size; i++) + { + for(j = 0; j < Size; j++) + { + tmp[i][j] = left[i][j]; + } + for(j = 0; j < RightCols; j++) + { + tmp[i][Size + j] = right[i][j]; + } + } + + for(k = 0; k < Size; k++) + { + if(matrix_pivot<Size, Size + RightCols>::pivot(tmp, k) < 0) + { + return false; // Singularity.... + } + + a1 = tmp[k][k]; + + for(j = k; j < Size + RightCols; j++) + { + tmp[k][j] /= a1; + } + + for(i = k + 1; i < Size; i++) + { + a1 = tmp[i][k]; + for (j = k; j < Size + RightCols; j++) + { + tmp[i][j] -= a1 * tmp[k][j]; + } + } + } + + + for(k = 0; k < RightCols; k++) + { + int m; + for(m = int(Size - 1); m >= 0; m--) + { + result[m][k] = tmp[m][Size + k]; + for(j = m + 1; j < Size; j++) + { + result[m][k] -= tmp[m][j] * result[j][k]; + } + } + } + return true; + } + + }; + + +} + +#endif diff --git a/agg/inc/agg_span_allocator.h b/agg/inc/agg_span_allocator.h new file mode 100755 index 000000000000..d99c5b9d8936 --- /dev/null +++ b/agg/inc/agg_span_allocator.h @@ -0,0 +1,72 @@ +//---------------------------------------------------------------------------- +// 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_ALLOCATOR_INCLUDED +#define AGG_SPAN_ALLOCATOR_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //----------------------------------------------------------span_allocator + template<class ColorT> class span_allocator + { + public: + typedef ColorT color_type; + + //-------------------------------------------------------------------- + ~span_allocator() + { + 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) + { + delete [] m_span; + m_span = new color_type[m_max_span_len = max_span_len]; + } + return m_span; + } + + //-------------------------------------------------------------------- + color_type* span() + { + return m_span; + } + + 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; + }; +} + + +#endif + + diff --git a/agg/inc/agg_span_converter.h b/agg/inc/agg_span_converter.h new file mode 100755 index 000000000000..104cd7d8e73e --- /dev/null +++ b/agg/inc/agg_span_converter.h @@ -0,0 +1,53 @@ +//---------------------------------------------------------------------------- +// 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_CONVERTER_INCLUDED +#define AGG_SPAN_CONVERTER_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //----------------------------------------------------------span_converter + template<class SpanGenerator, class Conv> 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) {} + + //-------------------------------------------------------------------- + void prepare(unsigned max_span_len) + { + m_span_gen->prepare(max_span_len); + } + + //-------------------------------------------------------------------- + color_type* generate(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; + } + + private: + SpanGenerator* m_span_gen; + Conv* m_conv; + }; + +} + +#endif diff --git a/agg/inc/agg_span_generator.h b/agg/inc/agg_span_generator.h new file mode 100755 index 000000000000..82b0ebef95f3 --- /dev/null +++ b/agg/inc/agg_span_generator.h @@ -0,0 +1,50 @@ +//---------------------------------------------------------------------------- +// 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 new file mode 100755 index 000000000000..76747899b5fc --- /dev/null +++ b/agg/inc/agg_span_gouraud.h @@ -0,0 +1,180 @@ +//---------------------------------------------------------------------------- +// 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_GOURAUD_INCLUDED +#define AGG_SPAN_GOURAUD_INCLUDED + +#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> + { + public: + typedef ColorT color_type; + typedef Allocator alloc_type; + + struct coord_type + { + double x; + double y; + color_type color; + }; + + //-------------------------------------------------------------------- + span_gouraud(alloc_type& alloc) : + span_generator<color_type, alloc_type>(alloc), + m_vertex(0) + { + m_cmd[0] = path_cmd_stop; + } + + //-------------------------------------------------------------------- + span_gouraud(alloc_type& alloc, + 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) + { + colors(c1, c2, c3); + triangle(x1, y1, x2, y2, x3, y3, d); + } + + //-------------------------------------------------------------------- + void colors(ColorT c1, ColorT c2, ColorT c3) + { + m_coord[0].color = c1; + m_coord[1].color = c2; + m_coord[2].color = c3; + } + + //-------------------------------------------------------------------- + // Sets the triangle and dilates it if needed. + // The trick here is to calculate beveled joins in the vertices of the + // triangle and render it as a 6-vertex polygon. + // It's necessary to achieve numerical stability. + // However, the coordinates to interpolate colors are calculated + // as miter joins (calc_intersection). + void triangle(double x1, double y1, + double x2, double y2, + double x3, double y3, + double d) + { + m_coord[0].x = m_x[0] = x1; + m_coord[0].y = m_y[0] = y1; + m_coord[1].x = m_x[1] = x2; + m_coord[1].y = m_y[1] = y2; + m_coord[2].x = m_x[2] = x3; + m_coord[2].y = m_y[2] = y3; + m_cmd[0] = path_cmd_move_to; + m_cmd[1] = path_cmd_line_to; + m_cmd[2] = path_cmd_line_to; + m_cmd[3] = path_cmd_stop; + + if(d != 0.0) + { + dilate_triangle(m_coord[0].x, m_coord[0].y, + m_coord[1].x, m_coord[1].y, + m_coord[2].x, m_coord[2].y, + m_x, m_y, d); + + calc_intersection(m_x[4], m_y[4], m_x[5], m_y[5], + m_x[0], m_y[0], m_x[1], m_y[1], + &m_coord[0].x, &m_coord[0].y); + + calc_intersection(m_x[0], m_y[0], m_x[1], m_y[1], + m_x[2], m_y[2], m_x[3], m_y[3], + &m_coord[1].x, &m_coord[1].y); + + calc_intersection(m_x[2], m_y[2], m_x[3], m_y[3], + m_x[4], m_y[4], m_x[5], m_y[5], + &m_coord[2].x, &m_coord[2].y); + m_cmd[3] = path_cmd_line_to; + m_cmd[4] = path_cmd_line_to; + m_cmd[5] = path_cmd_line_to; + m_cmd[6] = path_cmd_stop; + } + } + + //-------------------------------------------------------------------- + // Vertex Source Interface to feed the coordinates to the rasterizer + void rewind(unsigned) + { + m_vertex = 0; + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + *x = m_x[m_vertex]; + *y = m_y[m_vertex]; + return m_cmd[m_vertex++]; + } + + + + protected: + //-------------------------------------------------------------------- + void arrange_vertices(coord_type* coord) const + { + coord[0] = m_coord[0]; + coord[1] = m_coord[1]; + coord[2] = m_coord[2]; + + if(m_coord[0].y > m_coord[2].y) + { + coord[0] = m_coord[2]; + coord[2] = m_coord[0]; + } + + coord_type tmp; + if(coord[0].y > coord[1].y) + { + tmp = coord[1]; + coord[1] = coord[0]; + coord[0] = tmp; + } + + if(coord[1].y > coord[2].y) + { + tmp = coord[2]; + coord[2] = coord[1]; + coord[1] = tmp; + } + } + + + private: + //-------------------------------------------------------------------- + coord_type m_coord[3]; + double m_x[8]; + double m_y[8]; + unsigned m_cmd[8]; + unsigned m_vertex; + }; + +} + +#endif + diff --git a/agg/inc/agg_span_gouraud_gray.h b/agg/inc/agg_span_gouraud_gray.h new file mode 100755 index 000000000000..caf288919e93 --- /dev/null +++ b/agg/inc/agg_span_gouraud_gray.h @@ -0,0 +1,185 @@ +//---------------------------------------------------------------------------- +// 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_GOURAUD_GRAY_INCLUDED +#define AGG_SPAN_GOURAUD_GRAY_INCLUDED + +#include "agg_basics.h" +#include "agg_color_gray.h" +#include "agg_dda_line.h" +#include "agg_span_gouraud.h" + +namespace agg +{ + + //=======================================================span_gouraud_gray + template<class ColorT, class Allocator = span_allocator<ColorT> > + class span_gouraud_gray : public span_gouraud<ColorT, Allocator> + { + 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 typename base_type::coord_type coord_type; + + private: + //-------------------------------------------------------------------- + struct gray_calc + { + 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_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) + { + 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 m_x1; + double m_y1; + double m_dx; + double m_dy; + int m_v1; + int m_a1; + int m_dv; + int m_da; + int m_v; + int m_a; + int m_x; + }; + + + public: + //-------------------------------------------------------------------- + span_gouraud_gray(alloc_type& alloc) : base_type(alloc) {} + + //-------------------------------------------------------------------- + span_gouraud_gray(alloc_type& alloc, + 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) + {} + + //-------------------------------------------------------------------- + void prepare(unsigned max_span_len) + { + base_type::prepare(max_span_len); + + coord_type coord[3]; + 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_c1.init(coord[0], coord[2]); + m_c2.init(coord[0], coord[1]); + m_c3.init(coord[1], coord[2]); + } + + //-------------------------------------------------------------------- + color_type* generate(int x, int y, unsigned len) + { + m_c1.calc(y); + const gray_calc* pc1 = &m_c1; + const gray_calc* pc2 = &m_c2; + + if(y < m_y2) + { + m_c2.calc(y+1); + } + else + { + m_c3.calc(y); + pc2 = &m_c3; + } + + if(m_swap) + { + 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; + + 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) + { + unsigned d = unsigned(x - nx); + v += d; + a += d; + } + + color_type* span = base_type::allocator().span(); + do + { + span->v = (value_type)v.y(); + span->a = (value_type)a.y(); + ++v; + ++a; + ++span; + } + while(--len); + return base_type::allocator().span(); + } + + + private: + bool m_swap; + int m_y2; + gray_calc m_c1; + gray_calc m_c2; + gray_calc m_c3; + }; + + +} + +#endif diff --git a/agg/inc/agg_span_gouraud_rgba.h b/agg/inc/agg_span_gouraud_rgba.h new file mode 100755 index 000000000000..75679a9426c2 --- /dev/null +++ b/agg/inc/agg_span_gouraud_rgba.h @@ -0,0 +1,206 @@ +//---------------------------------------------------------------------------- +// 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_GOURAUD_RGBA_INCLUDED +#define AGG_SPAN_GOURAUD_RGBA_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_dda_line.h" +#include "agg_span_gouraud.h" + +namespace agg +{ + + //=======================================================span_gouraud_rgba + template<class ColorT, class Allocator = span_allocator<ColorT> > + class span_gouraud_rgba : public span_gouraud<ColorT, Allocator> + { + 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 typename base_type::coord_type coord_type; + + private: + //-------------------------------------------------------------------- + struct rgba_calc + { + 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; + } + + void calc(int 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 m_x1; + double m_y1; + double m_dx; + double m_dy; + int m_r1; + int m_g1; + int m_b1; + int m_a1; + int m_dr; + int m_dg; + int m_db; + int m_da; + int m_r; + int m_g; + int m_b; + int m_a; + int m_x; + }; + + public: + + //-------------------------------------------------------------------- + span_gouraud_rgba(alloc_type& alloc) : base_type(alloc) {} + + //-------------------------------------------------------------------- + span_gouraud_rgba(alloc_type& alloc, + 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) + {} + + //-------------------------------------------------------------------- + void prepare(unsigned max_span_len) + { + base_type::prepare(max_span_len); + + coord_type coord[3]; + 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_rgba1.init(coord[0], coord[2]); + m_rgba2.init(coord[0], coord[1]); + m_rgba3.init(coord[1], coord[2]); + } + + //-------------------------------------------------------------------- + color_type* generate(int x, int y, unsigned len) + { + m_rgba1.calc(y); + const rgba_calc* pc1 = &m_rgba1; + const rgba_calc* pc2 = &m_rgba2; + + if(y < m_y2) + { + m_rgba2.calc(y+1); + } + else + { + m_rgba3.calc(y); + pc2 = &m_rgba3; + } + + if(m_swap) + { + 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; + + 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) + { + unsigned d = unsigned(x - nx); + r += d; + g += d; + b += d; + a += d; + } + + color_type* span = base_type::allocator().span(); + do + { + 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; + ++span; + } + while(--len); + return base_type::allocator().span(); + } + + + private: + bool m_swap; + int m_y2; + rgba_calc m_rgba1; + rgba_calc m_rgba2; + rgba_calc m_rgba3; + }; + + + +} + +#endif diff --git a/agg/inc/agg_span_gradient.h b/agg/inc/agg_span_gradient.h new file mode 100755 index 000000000000..6bac1c652a84 --- /dev/null +++ b/agg/inc/agg_span_gradient.h @@ -0,0 +1,422 @@ +//---------------------------------------------------------------------------- +// 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_GRADIENT_INCLUDED +#define AGG_SPAN_GRADIENT_INCLUDED + +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include "agg_basics.h" +#include "agg_span_generator.h" +#include "agg_math.h" +#include "agg_array.h" + + +namespace agg +{ + + enum + { + 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 + }; + + + + //==========================================================span_gradient + template<class ColorT, + class Interpolator, + class GradientF, + class ColorF, + class Allocator = span_allocator<ColorT> > + class span_gradient : public span_generator<ColorT, Allocator> + { + public: + typedef Interpolator interpolator_type; + typedef Allocator alloc_type; + typedef ColorT color_type; + typedef span_generator<color_type, alloc_type> base_type; + + enum + { + downscale_shift = interpolator_type::subpixel_shift - + gradient_subpixel_shift + }; + + //-------------------------------------------------------------------- + span_gradient(alloc_type& alloc) : base_type(alloc) {} + + //-------------------------------------------------------------------- + span_gradient(alloc_type& alloc, + interpolator_type& inter, + const GradientF& gradient_function_, + const ColorF& color_function_, + double d1_, double d2_) : + base_type(alloc), + 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)) + {} + + //-------------------------------------------------------------------- + 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; } + + //-------------------------------------------------------------------- + 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); } + + //-------------------------------------------------------------------- + color_type* generate(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); + do + { + m_interpolator->coordinates(&x, &y); + int d = m_gradient_function->calculate(x >> downscale_shift, + y >> downscale_shift, dd); + 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; + *span++ = (*m_color_function)[d]; + ++(*m_interpolator); + } + while(--len); + return base_type::allocator().span(); + } + + private: + interpolator_type* m_interpolator; + const GradientF* m_gradient_function; + const ColorF* m_color_function; + int m_d1; + int m_d2; + }; + + + + + //=====================================================gradient_linear_color + template<class ColorT> + struct gradient_linear_color + { + typedef ColorT color_type; + + gradient_linear_color() {} + gradient_linear_color(const color_type& c1, const color_type& c2, + unsigned size = 256) : + m_c1(c1), m_c2(c2), m_size(size) {} + + unsigned size() const { return m_size; } + color_type operator [] (unsigned v) const + { + return m_c1.gradient(m_c2, double(v) / double(m_size - 1)); + } + + void colors(const color_type& c1, const color_type& c2, unsigned size = 256) + { + m_c1 = c1; + m_c2 = c2; + m_size = size; + } + + color_type m_c1; + color_type m_c2; + unsigned m_size; + }; + + + //==========================================================gradient_circle + class gradient_circle + { + // Actually the same as radial. Just for compatibility + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return int(fast_sqrt(x*x + y*y)); + } + }; + + + //==========================================================gradient_radial + class gradient_radial + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return int(fast_sqrt(x*x + y*y)); + } + }; + + + //========================================================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))); + } + }; + + + //====================================================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) + { + 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)) + { + update_values(); + } + + //--------------------------------------------------------------------- + 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); + 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; } + + //--------------------------------------------------------------------- + int calculate(int x, int y, int d) 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); + } + + 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) + { + // 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)); + } + + // Calculate the solution to be used in the case where x == focus_x + //------------------------------ + m_trivial = sqrt(m_radius2 - (m_focus_x * m_focus_x)); + } + + int m_radius; + int m_focus_x; + int m_focus_y; + double m_radius2; + double m_trivial; + }; + + + + //==============================================================gradient_x + class gradient_x + { + public: + static int calculate(int x, int, int) { return x; } + }; + + + //==============================================================gradient_y + class gradient_y + { + public: + static int calculate(int, int y, int) { return y; } + }; + + + //========================================================gradient_diamond + class gradient_diamond + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + int ax = abs(x); + int ay = abs(y); + return ax > ay ? ax : ay; + } + }; + + + //=============================================================gradient_xy + class gradient_xy + { + public: + static AGG_INLINE int calculate(int x, int y, int d) + { + return abs(x) * abs(y) / d; + } + }; + + + //========================================================gradient_sqrt_xy + class gradient_sqrt_xy + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return fast_sqrt(abs(x) * abs(y)); + } + }; + + + //==========================================================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); + } + }; + + + //=================================================gradient_repeat_adaptor + template<class GradientF> class gradient_repeat_adaptor + { + public: + gradient_repeat_adaptor(const GradientF& gradient) : + m_gradient(&gradient) {} + + AGG_INLINE int calculate(int x, int y, int d) const + { + int ret = m_gradient->calculate(x, y, d) % d; + if(ret < 0) ret += d; + return ret; + } + + private: + const GradientF* m_gradient; + }; + + + //================================================gradient_reflect_adaptor + template<class GradientF> class gradient_reflect_adaptor + { + public: + gradient_reflect_adaptor(const GradientF& gradient) : + m_gradient(&gradient) {} + + AGG_INLINE int calculate(int x, int y, int d) const + { + int d2 = d << 1; + int ret = m_gradient->calculate(x, y, d) % d2; + if(ret < 0) ret += d2; + if(ret >= d) ret = d2 - ret; + return ret; + } + + private: + const GradientF* m_gradient; + }; + + +} + +#endif diff --git a/agg/inc/agg_span_gradient_alpha.h b/agg/inc/agg_span_gradient_alpha.h new file mode 100755 index 000000000000..b1444ed8c4bc --- /dev/null +++ b/agg/inc/agg_span_gradient_alpha.h @@ -0,0 +1,123 @@ +//---------------------------------------------------------------------------- +// 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_GRADIENT_ALPHA_INCLUDED +#define AGG_SPAN_GRADIENT_ALPHA_INCLUDED + +#include "agg_span_gradient.h" + +namespace agg +{ + //======================================================span_gradient_alpha + template<class ColorT, + class Interpolator, + class GradientF, + class AlphaF> + class span_gradient_alpha + { + public: + typedef Interpolator interpolator_type; + typedef ColorT color_type; + typedef typename color_type::value_type alpha_type; + + enum + { + downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift + }; + + + //-------------------------------------------------------------------- + span_gradient_alpha() {} + + //-------------------------------------------------------------------- + span_gradient_alpha(interpolator_type& inter, + const GradientF& gradient_function, + const AlphaF& alpha_function, + double d1, double d2) : + 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)) + {} + + //-------------------------------------------------------------------- + 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; } + + //-------------------------------------------------------------------- + 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 convert(color_type* span, int x, int y, unsigned len) + { + int dd = m_d2 - m_d1; + if(dd < 1) dd = 1; + m_interpolator->begin(x+0.5, y+0.5, len); + do + { + m_interpolator->coordinates(&x, &y); + int d = m_gradient_function->calculate(x >> downscale_shift, + y >> downscale_shift, dd); + 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; + span->a = (*m_alpha_function)[d]; + ++span; + ++(*m_interpolator); + } + while(--len); + } + + private: + interpolator_type* m_interpolator; + const GradientF* m_gradient_function; + const AlphaF* m_alpha_function; + int m_d1; + int m_d2; + }; + + + //=======================================================gradient_alpha_x + template<class ColorT> struct gradient_alpha_x + { + typedef typename ColorT::value_type alpha_type; + alpha_type operator [] (alpha_type x) const { return x; } + }; + + //====================================================gradient_alpha_x_u8 + struct gradient_alpha_x_u8 + { + typedef int8u alpha_type; + alpha_type operator [] (alpha_type x) const { return x; } + }; + + //==========================================gradient_alpha_one_munus_x_u8 + struct gradient_alpha_one_munus_x_u8 + { + typedef int8u alpha_type; + alpha_type operator [] (alpha_type x) const { return 255-x; } + }; + +} + +#endif diff --git a/agg/inc/agg_span_image_filter.h b/agg/inc/agg_span_image_filter.h new file mode 100755 index 000000000000..34163bb29f24 --- /dev/null +++ b/agg/inc/agg_span_image_filter.h @@ -0,0 +1,110 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Image transformations with filtering. Span generator base class +// +//---------------------------------------------------------------------------- +#ifndef AGG_SPAN_IMAGE_FILTER_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_INCLUDED + +#include "agg_basics.h" +#include "agg_image_filters.h" +#include "agg_rendering_buffer.h" +#include "agg_span_generator.h" + + +namespace agg +{ + + //--------------------------------------------------span_image_filter + template<class ColorT, class Interpolator, class Allocator> + class span_image_filter : public span_generator<ColorT, Allocator> + { + public: + typedef ColorT color_type; + typedef Allocator alloc_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), + m_src(&src), + m_back_color(back_color), + 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) + {} + + //---------------------------------------------------------------- + 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; } + 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); + } + 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); + } + + //---------------------------------------------------------------- + private: + const rendering_buffer* m_src; + color_type m_back_color; + interpolator_type* m_interpolator; + const image_filter_lut* m_filter; + double m_dx_dbl; + double m_dy_dbl; + unsigned m_dx_int; + unsigned m_dy_int; + }; + + +} + +#endif diff --git a/agg/inc/agg_span_image_filter_gray.h b/agg/inc/agg_span_image_filter_gray.h new file mode 100755 index 000000000000..3f7ae6fcfa72 --- /dev/null +++ b/agg/inc/agg_span_image_filter_gray.h @@ -0,0 +1,701 @@ +//---------------------------------------------------------------------------- +// 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_IMAGE_FILTER_GRAY_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED + +#include "agg_basics.h" +#include "agg_color_gray.h" +#include "agg_span_image_filter.h" + + +namespace agg +{ + + + //==============================================span_image_filter_gray_nn + template<class ColorT, + class Interpolator, + class Allocator = span_allocator<ColorT> > + class span_image_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_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, + interpolator_type& inter) : + base_type(alloc, src, back_color, inter, 0) + {} + + //-------------------------------------------------------------------- + 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; + 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; + + do + { + base_type::interpolator().coordinates(&x, &y); + + x >>= image_subpixel_shift; + y >>= image_subpixel_shift; + + 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; + } + + span->v = (value_type)fg; + span->a = (value_type)src_alpha; + ++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> + { + 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_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) + {} + + //-------------------------------------------------------------------- + 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; + 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(); + + int maxx = base_type::source_image().width() - 1; + int maxy = base_type::source_image().height() - 1; + + 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; + + if(x_lr >= 0 && y_lr >= 0 && + x_lr < maxx && y_lr < maxy) + { + fg = image_subpixel_size * image_subpixel_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++ * (image_subpixel_size - x_hr) * (image_subpixel_size - y_hr); + fg += *fg_ptr++ * (image_subpixel_size - y_hr) * x_hr; + + fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - 2); + + fg += *fg_ptr++ * (image_subpixel_size - x_hr) * y_hr; + fg += *fg_ptr++ * x_hr * y_hr; + + fg >>= image_subpixel_shift * 2; + 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_subpixel_size * image_subpixel_size / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + weight = (image_subpixel_size - x_hr) * + (image_subpixel_size - 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); + src_alpha += weight * base_mask; + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = x_hr * (image_subpixel_size - 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); + src_alpha += weight * base_mask; + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + x_lr--; + y_lr++; + + weight = (image_subpixel_size - 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); + src_alpha += weight * base_mask; + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = 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); + src_alpha += weight * base_mask; + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + fg >>= image_subpixel_shift * 2; + src_alpha >>= image_subpixel_shift * 2; + } + } + + span->v = (value_type)fg; + span->a = (value_type)src_alpha; + ++span; + ++base_type::interpolator(); + + } while(--len); + + return base_type::allocator().span(); + } + }; + + + + + + + + //========================================span_image_filter_gray_2x2 + template<class ColorT, + class Interpolator, + class Allocator = span_allocator<ColorT> > + class span_image_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_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, + 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); + 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; + 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; + + 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; + + } + } + + span->v = (value_type)fg; + span->a = (value_type)src_alpha; + ++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> > + class span_image_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_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, + 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); + + 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; + + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); + int start1 = start - 1; + 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; + + 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_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg = image_filter_size / 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_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; + + do + { + fg += *fg_ptr++ * ((weight_y * weight_array[x_hr] + + image_filter_size / 2) >> + image_filter_shift); + x_hr += image_subpixel_size; + + } while(--x_count); + + y_hr += image_subpixel_size; + fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - diameter); + + } while(--y_count); + + fg >>= image_filter_shift; + + if(fg < 0) fg = 0; + if(fg > base_mask) fg = base_mask; + src_alpha = base_mask; + } + else + { + if(x_lr < start1 || y_lr < start1 || + x_lr > maxx2 || y_lr > maxy2) + { + fg = back_v; + src_alpha = back_a; + } + else + { + src_alpha = image_filter_size / 2; + y_lr = (y >> image_subpixel_shift) + start; + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + + 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; + } + } + + 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_filter_rgb.h b/agg/inc/agg_span_image_filter_rgb.h new file mode 100755 index 000000000000..d8f8142bfffb --- /dev/null +++ b/agg/inc/agg_span_image_filter_rgb.h @@ -0,0 +1,840 @@ +//---------------------------------------------------------------------------- +// 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_IMAGE_FILTER_RGB_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_span_image_filter.h" + + +namespace agg +{ + + + //==============================================span_image_filter_rgb_nn + template<class ColorT, + class Order, + class Interpolator, + class Allocator = span_allocator<ColorT> > + class span_image_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_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, + interpolator_type& inter) : + base_type(alloc, src, back_color, inter, 0) + {} + + //-------------------------------------------------------------------- + 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[3]; + calc_type src_alpha; + + 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); + + x >>= image_subpixel_shift; + y >>= image_subpixel_shift; + + 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; + } + + 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> + { + 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_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) + {} + + //-------------------------------------------------------------------- + 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[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(); + + int maxx = base_type::source_image().width() - 1; + int maxy = base_type::source_image().height() - 1; + + 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 weight; + + if(x_lr >= 0 && y_lr >= 0 && + x_lr < maxx && y_lr < maxy) + { + fg[0] = + fg[1] = + fg[2] = image_subpixel_size * image_subpixel_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 = (image_subpixel_size - x_hr) * + (image_subpixel_size - 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); + 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 = (image_subpixel_size - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + fg[0] >>= image_subpixel_shift * 2; + fg[1] >>= image_subpixel_shift * 2; + fg[2] >>= image_subpixel_shift * 2; + src_alpha = 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_subpixel_size * image_subpixel_size / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + weight = (image_subpixel_size - x_hr) * + (image_subpixel_size - 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[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 = x_hr * (image_subpixel_size - 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[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 = (image_subpixel_size - 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[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 = 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[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_subpixel_shift * 2; + fg[1] >>= image_subpixel_shift * 2; + fg[2] >>= image_subpixel_shift * 2; + src_alpha >>= image_subpixel_shift * 2; + } + } + + 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_2x2 + template<class ColorT, + class Order, + class Interpolator, + class Allocator = span_allocator<ColorT> > + class span_image_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_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, + 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); + 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; + 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 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; + } + } + + 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 + template<class ColorT, + class Order, + class Interpolator, + class Allocator = span_allocator<ColorT> > + class span_image_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_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) + {} + + //-------------------------------------------------------------------- + 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[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; + + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); + int start1 = start - 1; + 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; + + 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_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg[0] = fg[1] = fg[2] = image_filter_size / 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_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; + + do + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_size / 2) >> + image_filter_shift; + + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr++ * weight; + + x_hr += image_subpixel_size; + + } while(--x_count); + + y_hr += image_subpixel_size; + fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - step_back); + + } 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; + src_alpha = base_mask; + } + else + { + if(x_lr < start1 || y_lr < start1 || + x_lr > maxx2 || y_lr > maxy2) + { + fg[order_type::R] = back_r; + fg[order_type::G] = back_g; + fg[order_type::B] = back_b; + src_alpha = back_a; + } + else + { + src_alpha = image_filter_size / 2; + y_lr = (y >> image_subpixel_shift) + start; + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + + 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; + } + } + + 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(); + } + }; + + + +} + + +#endif + + + diff --git a/agg/inc/agg_span_image_filter_rgba.h b/agg/inc/agg_span_image_filter_rgba.h new file mode 100755 index 000000000000..42b822c99b9b --- /dev/null +++ b/agg/inc/agg_span_image_filter_rgba.h @@ -0,0 +1,864 @@ +//---------------------------------------------------------------------------- +// 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_image_filter_rgba32* +// +//---------------------------------------------------------------------------- +#ifndef AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_span_image_filter.h" + + +namespace agg +{ + + //=============================================span_image_filter_rgba_nn + template<class ColorT, + class Order, + class Interpolator, + class Allocator = span_allocator<ColorT> > + class span_image_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_image_filter_rgba_nn(alloc_type& alloc) : base_type(alloc) {} + + //-------------------------------------------------------------------- + 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) + {} + + //-------------------------------------------------------------------- + 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(); + + int maxx = base_type::source_image().width() - 1; + int maxy = base_type::source_image().height() - 1; + + do + { + base_type::interpolator().coordinates(&x, &y); + + x >>= image_subpixel_shift; + y >>= image_subpixel_shift; + + 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; + } + + 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> + { + 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_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) + {} + + + //-------------------------------------------------------------------- + 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]; + 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(); + + int maxx = base_type::source_image().width() - 1; + int maxy = base_type::source_image().height() - 1; + + 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 weight; + + if(x_lr >= 0 && y_lr >= 0 && + x_lr < maxx && y_lr < maxy) + { + 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; + + fg_ptr = (const value_type*)base_type::source_image().row(y_lr) + (x_lr << 2); + + weight = (image_subpixel_size - x_hr) * + (image_subpixel_size - 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); + 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 = (image_subpixel_size - x_hr) * 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 * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + + fg[0] >>= image_subpixel_shift * 2; + fg[1] >>= image_subpixel_shift * 2; + fg[2] >>= image_subpixel_shift * 2; + fg[3] >>= image_subpixel_shift * 2; + } + 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 + { + 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; + + weight = (image_subpixel_size - x_hr) * + (image_subpixel_size - 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[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 = x_hr * (image_subpixel_size - 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[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 = (image_subpixel_size - 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[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 = 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[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_subpixel_shift * 2; + fg[1] >>= image_subpixel_shift * 2; + fg[2] >>= image_subpixel_shift * 2; + fg[3] >>= image_subpixel_shift * 2; + } + } + + 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_filter_rgba_2x2 + template<class ColorT, + class Order, + class Interpolator, + class Allocator = span_allocator<ColorT> > + class span_image_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_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, + 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); + + 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; + 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 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]; + } + } + + 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_filter_rgba + template<class ColorT, + class Order, + class Interpolator, + class Allocator = span_allocator<ColorT> > + class span_image_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_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, + 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); + + 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; + 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; + + 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_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; + + 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_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; + + do + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_size / 2) >> + image_filter_shift; + + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr++ * weight; + fg[3] += *fg_ptr++ * weight; + + x_hr += image_subpixel_size; + + } while(--x_count); + + y_hr += image_subpixel_size; + fg_ptr = (const value_type*)base_type::source_image().next_row(fg_ptr - step_back); + + } 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]; + } + else + { + if(x_lr < start1 || y_lr < start1 || + x_lr > maxx2 || y_lr > maxy2) + { + 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 + { + y_lr = (y >> image_subpixel_shift) + start; + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + + 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]; + } + } + + 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(); + } + + }; + + +} + + +#endif + + + diff --git a/agg/inc/agg_span_image_resample.h b/agg/inc/agg_span_image_resample.h new file mode 100755 index 000000000000..f4dfd57455d7 --- /dev/null +++ b/agg/inc/agg_span_image_resample.h @@ -0,0 +1,180 @@ +//---------------------------------------------------------------------------- +// 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 new file mode 100755 index 000000000000..3d046462cd8c --- /dev/null +++ b/agg/inc/agg_span_image_resample_gray.h @@ -0,0 +1,359 @@ +//---------------------------------------------------------------------------- +// 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 new file mode 100755 index 000000000000..de25dd4b382b --- /dev/null +++ b/agg/inc/agg_span_image_resample_rgb.h @@ -0,0 +1,393 @@ +//---------------------------------------------------------------------------- +// 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 new file mode 100755 index 000000000000..40f7ccb42e00 --- /dev/null +++ b/agg/inc/agg_span_image_resample_rgba.h @@ -0,0 +1,393 @@ +//---------------------------------------------------------------------------- +// 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 new file mode 100755 index 000000000000..ead42c13590c --- /dev/null +++ b/agg/inc/agg_span_interpolator_adaptor.h @@ -0,0 +1,77 @@ +//---------------------------------------------------------------------------- +// 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_INTERPOLATOR_ADAPTOR_INCLUDED +#define AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //===============================================span_interpolator_adaptor + template<class Interpolator, class Distortion> + class span_interpolator_adaptor : public Interpolator + { + public: + typedef Interpolator base_type; + typedef typename base_type::trans_type trans_type; + typedef Distortion distortion_type; + + //-------------------------------------------------------------------- + span_interpolator_adaptor() {} + span_interpolator_adaptor(const trans_type& trans, + const distortion_type& dist) : + base_type(trans), + m_distortion(&dist) + { + } + + //-------------------------------------------------------------------- + span_interpolator_adaptor(const trans_type& trans, + const distortion_type& dist, + double x, double y, unsigned len) : + base_type(trans, x, y, len), + m_distortion(&dist) + { + } + + //-------------------------------------------------------------------- + const distortion_type& distortion() const + { + return *m_distortion; + } + + //-------------------------------------------------------------------- + void distortion(const distortion_type& dist) + { + m_distortion = dist; + } + + //-------------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + base_type::coordinates(x, y); + m_distortion->calculate(x, y); + } + + private: + //-------------------------------------------------------------------- + const distortion_type* m_distortion; + }; +} + + +#endif diff --git a/agg/inc/agg_span_interpolator_linear.h b/agg/inc/agg_span_interpolator_linear.h new file mode 100755 index 000000000000..3cc2426be450 --- /dev/null +++ b/agg/inc/agg_span_interpolator_linear.h @@ -0,0 +1,232 @@ +//---------------------------------------------------------------------------- +// 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_INTERPOLATOR_LINEAR_INCLUDED +#define AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED + +#include "agg_basics.h" +#include "agg_dda_line.h" +#include "agg_trans_affine.h" + +namespace agg +{ + + //================================================span_interpolator_linear + template<class Transformer = trans_affine, unsigned SubpixelShift = 8> + class span_interpolator_linear + { + public: + typedef Transformer trans_type; + + enum + { + subpixel_shift = SubpixelShift, + subpixel_size = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_linear() {} + span_interpolator_linear(const trans_type& trans) : m_trans(&trans) {} + span_interpolator_linear(const trans_type& trans, + double x, double y, unsigned len) : + m_trans(&trans) + { + begin(x, y, len); + } + + //---------------------------------------------------------------- + const trans_type& transformer() const { return *m_trans; } + void transformer(const trans_type& trans) { m_trans = &trans; } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + double tx; + double ty; + + tx = x; + ty = y; + m_trans->transform(&tx, &ty); + int x1 = int(tx * subpixel_size); + int y1 = int(ty * subpixel_size); + + tx = x + len; + ty = y; + m_trans->transform(&tx, &ty); + int x2 = int(tx * subpixel_size); + int y2 = int(ty * subpixel_size); + + m_li_x = dda2_line_interpolator(x1, x2, len); + m_li_y = dda2_line_interpolator(y1, y2, len); + } + + //---------------------------------------------------------------- + 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); + } + + //---------------------------------------------------------------- + void operator++() + { + ++m_li_x; + ++m_li_y; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_li_x.y(); + *y = m_li_y.y(); + } + + private: + const trans_type* m_trans; + dda2_line_interpolator m_li_x; + dda2_line_interpolator m_li_y; + }; + + + + + + + //=====================================span_interpolator_linear_subdiv + template<class Transformer = trans_affine, unsigned SubpixelShift = 8> + class span_interpolator_linear_subdiv + { + public: + typedef Transformer trans_type; + + enum + { + subpixel_shift = SubpixelShift, + subpixel_size = 1 << subpixel_shift + }; + + + //---------------------------------------------------------------- + span_interpolator_linear_subdiv() : + m_subdiv_shift(4), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1) {} + + span_interpolator_linear_subdiv(const trans_type& trans, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_trans(&trans) {} + + span_interpolator_linear_subdiv(const trans_type& trans, + double x, double y, unsigned len, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_trans(&trans) + { + begin(x, y, len); + } + + //---------------------------------------------------------------- + const trans_type& transformer() const { return *m_trans; } + void transformer(const trans_type& trans) { m_trans = &trans; } + + //---------------------------------------------------------------- + unsigned subdiv_shift() const { return m_subdiv_shift; } + void subdiv_shift(unsigned shift) + { + m_subdiv_shift = shift; + m_subdiv_size = 1 << m_subdiv_shift; + m_subdiv_mask = m_subdiv_size - 1; + } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + double tx; + double ty; + m_pos = 1; + m_src_x = int(x * subpixel_size) + subpixel_size; + m_src_y = y; + m_len = len; + + if(len > m_subdiv_size) len = m_subdiv_size; + tx = x; + ty = y; + m_trans->transform(&tx, &ty); + int x1 = int(tx * subpixel_size); + int y1 = int(ty * subpixel_size); + + 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); + } + + //---------------------------------------------------------------- + void operator++() + { + ++m_li_x; + ++m_li_y; + if(m_pos >= m_subdiv_size) + { + unsigned len = m_len; + if(len > m_subdiv_size) len = m_subdiv_size; + double tx = double(m_src_x) / double(subpixel_size) + 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_pos = 0; + } + m_src_x += subpixel_size; + ++m_pos; + --m_len; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_li_x.y(); + *y = m_li_y.y(); + } + + private: + unsigned m_subdiv_shift; + unsigned m_subdiv_size; + unsigned m_subdiv_mask; + const trans_type* m_trans; + dda2_line_interpolator m_li_x; + dda2_line_interpolator m_li_y; + int m_src_x; + double m_src_y; + unsigned m_pos; + unsigned m_len; + }; + + +} + + + +#endif + + diff --git a/agg/inc/agg_span_interpolator_persp.h b/agg/inc/agg_span_interpolator_persp.h new file mode 100755 index 000000000000..632a56449f28 --- /dev/null +++ b/agg/inc/agg_span_interpolator_persp.h @@ -0,0 +1,462 @@ +//---------------------------------------------------------------------------- +// 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_INTERPOLATOR_PERSP_INCLUDED +#define AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED + +#include "agg_trans_perspective.h" +#include "agg_dda_line.h" + +namespace agg +{ + + + + //===========================================span_interpolator_persp_exact + template<unsigned SubpixelShift = 8> + class span_interpolator_persp_exact + { + public: + typedef trans_perspective trans_type; + typedef trans_perspective::iterator_x iterator_type; + enum + { + subpixel_shift = SubpixelShift, + subpixel_size = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_persp_exact() {} + + //-------------------------------------------------------------------- + // Arbitrary quadrangle transformations + span_interpolator_persp_exact(const double* src, const double* dst) + { + quad_to_quad(src, dst); + } + + //-------------------------------------------------------------------- + // Direct transformations + span_interpolator_persp_exact(double x1, double y1, + double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + //-------------------------------------------------------------------- + // Reverse transformations + span_interpolator_persp_exact(const double* quad, + double x1, double y1, + double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + //-------------------------------------------------------------------- + // Set the transformations using two arbitrary quadrangles. + void quad_to_quad(const double* src, const double* dst) + { + m_trans_dir.quad_to_quad(src, dst); + m_trans_inv.quad_to_quad(dst, src); + } + + //-------------------------------------------------------------------- + // 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); + } + + + //-------------------------------------------------------------------- + // 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); + } + + //-------------------------------------------------------------------- + // Check if the equations were solved successfully + bool is_valid() const { return m_trans_dir.is_valid(); } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + m_iterator = m_trans_dir.begin(x, y, 1.0); + double xt = m_iterator.x; + double yt = m_iterator.y; + + double dx; + double dy; + const double delta = 1/double(subpixel_size); + 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; + 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; + + x += len; + xt = x; + yt = y; + m_trans_dir.transform(&xt, &yt); + + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx2 = int(subpixel_size/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; + + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + //---------------------------------------------------------------- + void resynchronize(double xe, double ye, unsigned len) + { + // Assume x1,y1 are equal to the ones at the previous end point + int sx1 = m_scale_x.y(); + int sy1 = m_scale_y.y(); + + // Calculate transformed coordinates at x2,y2 + double xt = xe; + double yt = ye; + m_trans_dir.transform(&xt, &yt); + + const double delta = 1/double(subpixel_size); + double dx; + double dy; + + // Calculate scale by X at x2,y2 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sx2 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x2,y2 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sy2 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Initialize the interpolators + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + + //---------------------------------------------------------------- + void operator++() + { + ++m_iterator; + ++m_scale_x; + ++m_scale_y; + } + + //---------------------------------------------------------------- + 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); + } + + //---------------------------------------------------------------- + void local_scale(int* x, int* y) + { + *x = m_scale_x.y(); + *y = m_scale_y.y(); + } + + //---------------------------------------------------------------- + void transform(double* x, double* y) const + { + m_trans_dir.transform(x, y); + } + + private: + trans_type m_trans_dir; + trans_type m_trans_inv; + iterator_type m_iterator; + dda2_line_interpolator m_scale_x; + dda2_line_interpolator m_scale_y; + }; + + + + + + + + + + + + //============================================span_interpolator_persp_lerp + template<unsigned SubpixelShift = 8> + class span_interpolator_persp_lerp + { + public: + typedef trans_perspective trans_type; + enum + { + subpixel_shift = SubpixelShift, + subpixel_size = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_persp_lerp() {} + + //-------------------------------------------------------------------- + // Arbitrary quadrangle transformations + span_interpolator_persp_lerp(const double* src, const double* dst) + { + quad_to_quad(src, dst); + } + + //-------------------------------------------------------------------- + // Direct transformations + span_interpolator_persp_lerp(double x1, double y1, + double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + //-------------------------------------------------------------------- + // Reverse transformations + span_interpolator_persp_lerp(const double* quad, + double x1, double y1, + double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + //-------------------------------------------------------------------- + // Set the transformations using two arbitrary quadrangles. + void quad_to_quad(const double* src, const double* dst) + { + m_trans_dir.quad_to_quad(src, dst); + m_trans_inv.quad_to_quad(dst, src); + } + + //-------------------------------------------------------------------- + // 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); + } + + + //-------------------------------------------------------------------- + // 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); + } + + //-------------------------------------------------------------------- + // Check if the equations were solved successfully + bool is_valid() const { return m_trans_dir.is_valid(); } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + // Calculate transformed coordinates at x1,y1 + double xt = x; + double yt = y; + m_trans_dir.transform(&xt, &yt); + int x1 = int(xt * subpixel_size); + int y1 = int(yt * subpixel_size); + + double dx; + double dy; + const double delta = 1/double(subpixel_size); + + // Calculate scale by X at x1,y1 + 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; + + // Calculate scale by Y at x1,y1 + 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; + + // 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); + + // Calculate scale by X at x2,y2 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx2 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x2,y2 + 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; + + // Initialize the interpolators + m_coord_x = dda2_line_interpolator(x1, x2, len); + m_coord_y = dda2_line_interpolator(y1, y2, len); + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + //---------------------------------------------------------------- + void resynchronize(double xe, double ye, unsigned len) + { + // Assume x1,y1 are equal to the ones at the previous end point + int x1 = m_coord_x.y(); + int y1 = m_coord_y.y(); + int sx1 = m_scale_x.y(); + int sy1 = m_scale_y.y(); + + // Calculate transformed coordinates at x2,y2 + double xt = xe; + double yt = ye; + m_trans_dir.transform(&xt, &yt); + int x2 = int(xt * subpixel_size); + int y2 = int(yt * subpixel_size); + + const double delta = 1/double(subpixel_size); + double dx; + double dy; + + // Calculate scale by X at x2,y2 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sx2 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x2,y2 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sy2 = int(subpixel_size/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Initialize the interpolators + m_coord_x = dda2_line_interpolator(x1, x2, len); + m_coord_y = dda2_line_interpolator(y1, y2, len); + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + //---------------------------------------------------------------- + void operator++() + { + ++m_coord_x; + ++m_coord_y; + ++m_scale_x; + ++m_scale_y; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_coord_x.y(); + *y = m_coord_y.y(); + } + + //---------------------------------------------------------------- + void local_scale(int* x, int* y) + { + *x = m_scale_x.y(); + *y = m_scale_y.y(); + } + + //---------------------------------------------------------------- + void transform(double* x, double* y) const + { + m_trans_dir.transform(x, y); + } + + private: + trans_type m_trans_dir; + trans_type m_trans_inv; + dda2_line_interpolator m_coord_x; + dda2_line_interpolator m_coord_y; + dda2_line_interpolator m_scale_x; + dda2_line_interpolator m_scale_y; + }; + +} + +#endif diff --git a/agg/inc/agg_span_interpolator_trans.h b/agg/inc/agg_span_interpolator_trans.h new file mode 100755 index 000000000000..5caaffe9e5c0 --- /dev/null +++ b/agg/inc/agg_span_interpolator_trans.h @@ -0,0 +1,97 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Horizontal span interpolator for use with an arbitrary transformer +// The efficiency highly depends on the operations done in the transformer +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED +#define AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //=================================================span_interpolator_trans + template<class Transformer, unsigned SubpixelShift = 8> + class span_interpolator_trans + { + public: + typedef Transformer trans_type; + enum + { + subpixel_shift = SubpixelShift, + subpixel_size = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_trans() {} + span_interpolator_trans(const trans_type& trans) : m_trans(&trans) {} + span_interpolator_trans(const trans_type& trans, + double x, double y, unsigned) : + m_trans(&trans) + { + begin(x, y, 0); + } + + //---------------------------------------------------------------- + const trans_type& transformer() const { return *m_trans; } + void transformer(const trans_type& trans) { m_trans = &trans; } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned) + { + 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) + { + } + + //---------------------------------------------------------------- + void operator++() + { + m_x += 1.0; + 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); + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_ix; + *y = m_iy; + } + + private: + const trans_type* m_trans; + double m_x; + double m_y; + int m_ix; + int m_iy; + }; + +} + +#endif diff --git a/agg/inc/agg_span_pattern.h b/agg/inc/agg_span_pattern.h new file mode 100755 index 000000000000..b9e9b135ff84 --- /dev/null +++ b/agg/inc/agg_span_pattern.h @@ -0,0 +1,278 @@ +//---------------------------------------------------------------------------- +// 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 new file mode 100755 index 000000000000..17a7984be7fe --- /dev/null +++ b/agg/inc/agg_span_pattern_filter_gray.h @@ -0,0 +1,472 @@ +//---------------------------------------------------------------------------- +// 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 new file mode 100755 index 000000000000..d4dc1c1797eb --- /dev/null +++ b/agg/inc/agg_span_pattern_filter_rgb.h @@ -0,0 +1,568 @@ +//---------------------------------------------------------------------------- +// 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 new file mode 100755 index 000000000000..8460880fdb79 --- /dev/null +++ b/agg/inc/agg_span_pattern_filter_rgba.h @@ -0,0 +1,584 @@ +//---------------------------------------------------------------------------- +// 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_resample_gray.h b/agg/inc/agg_span_pattern_resample_gray.h new file mode 100755 index 000000000000..212209502f5f --- /dev/null +++ b/agg/inc/agg_span_pattern_resample_gray.h @@ -0,0 +1,320 @@ +//---------------------------------------------------------------------------- +// 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 new file mode 100755 index 000000000000..baef860eb472 --- /dev/null +++ b/agg/inc/agg_span_pattern_resample_rgb.h @@ -0,0 +1,346 @@ +//---------------------------------------------------------------------------- +// 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 new file mode 100755 index 000000000000..37b4dade16f4 --- /dev/null +++ b/agg/inc/agg_span_pattern_resample_rgba.h @@ -0,0 +1,354 @@ +//---------------------------------------------------------------------------- +// 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 new file mode 100755 index 000000000000..2e17f11e7c70 --- /dev/null +++ b/agg/inc/agg_span_pattern_rgb.h @@ -0,0 +1,165 @@ +//---------------------------------------------------------------------------- +// 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_RGB_INCLUDED +#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> + { + public: + typedef ColorT color_type; + typedef Order order_type; + typedef Allocator alloc_type; + typedef span_pattern_base<color_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_rgb(alloc_type& alloc) : + base_type(alloc), + m_wrap_mode_x(1), + m_wrap_mode_y(1) + {} + + //---------------------------------------------------------------- + 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 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()); + } + + //-------------------------------------------------------------------- + color_type* generate(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)); + 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; + } + 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; + + //-------------------------------------------------------------------- + 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(); + } + }; +*/ + +} + +#endif + diff --git a/agg/inc/agg_span_pattern_rgba.h b/agg/inc/agg_span_pattern_rgba.h new file mode 100755 index 000000000000..d952d0733696 --- /dev/null +++ b/agg/inc/agg_span_pattern_rgba.h @@ -0,0 +1,111 @@ +//---------------------------------------------------------------------------- +// 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_RGBA_INCLUDED +#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> + { + public: + typedef ColorT color_type; + typedef Order order_type; + typedef Allocator alloc_type; + typedef span_pattern_base<color_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_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, + 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()) + {} + + //------------------------------------------------------------------- + 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()); + } + + //-------------------------------------------------------------------- + color_type* generate(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)); + 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; + ++span; + } + 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_solid.h b/agg/inc/agg_span_solid.h new file mode 100755 index 000000000000..aa8374bfe61f --- /dev/null +++ b/agg/inc/agg_span_solid.h @@ -0,0 +1,63 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// span_solid_rgba8 +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_SOLID_INCLUDED +#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> + { + 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) + { + color_type* span = base_type::allocator().span(); + do + { + *span++ = m_color; + } + while(--len); + return base_type::allocator().span(); + } + + private: + color_type m_color; + }; + + +} + +#endif diff --git a/agg/inc/agg_span_subdiv_adaptor.h b/agg/inc/agg_span_subdiv_adaptor.h new file mode 100755 index 000000000000..60196d705bdb --- /dev/null +++ b/agg/inc/agg_span_subdiv_adaptor.h @@ -0,0 +1,141 @@ +//---------------------------------------------------------------------------- +// 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_SUBDIV_ADAPTOR_INCLUDED +#define AGG_SPAN_SUBDIV_ADAPTOR_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //=================================================span_subdiv_adaptor + template<class Interpolator, unsigned SubpixelShift = 8> + class span_subdiv_adaptor + { + public: + typedef Interpolator interpolator_type; + typedef typename interpolator_type::trans_type trans_type; + + enum + { + subpixel_shift = SubpixelShift, + subpixel_size = 1 << subpixel_shift + }; + + + //---------------------------------------------------------------- + span_subdiv_adaptor() : + m_subdiv_shift(4), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1) {} + + span_subdiv_adaptor(interpolator_type& interpolator, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_interpolator(&interpolator) {} + + span_subdiv_adaptor(interpolator_type& interpolator, + double x, double y, unsigned len, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_interpolator(&interpolator) + { + begin(x, y, len); + } + + + //---------------------------------------------------------------- + const interpolator_type& interpolator() const { return *m_interpolator; } + void interpolator(interpolator_type& intr) { m_interpolator = &intr; } + + //---------------------------------------------------------------- + const trans_type& transformer() const + { + return *m_interpolator->transformer(); + } + void transformer(const trans_type& trans) + { + m_interpolator->transformer(trans); + } + + //---------------------------------------------------------------- + unsigned subdiv_shift() const { return m_subdiv_shift; } + void subdiv_shift(unsigned shift) + { + m_subdiv_shift = shift; + m_subdiv_size = 1 << m_subdiv_shift; + m_subdiv_mask = m_subdiv_size - 1; + } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + m_pos = 1; + m_src_x = int(x * subpixel_size) + subpixel_size; + m_src_y = y; + m_len = len; + if(len > m_subdiv_size) len = m_subdiv_size; + m_interpolator->begin(x, y, len); + } + + //---------------------------------------------------------------- + void operator++() + { + ++(*m_interpolator); + if(m_pos >= m_subdiv_size) + { + 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_src_y, + len); + m_pos = 0; + } + m_src_x += subpixel_size; + ++m_pos; + --m_len; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + m_interpolator->coordinates(x, y); + } + + //---------------------------------------------------------------- + void local_scale(int* x, int* y) const + { + m_interpolator->local_scale(x, y); + } + + + private: + unsigned m_subdiv_shift; + unsigned m_subdiv_size; + unsigned m_subdiv_mask; + interpolator_type* m_interpolator; + int m_src_x; + double m_src_y; + unsigned m_pos; + unsigned m_len; + }; + +} + +#endif diff --git a/agg/inc/agg_trans_affine.h b/agg/inc/agg_trans_affine.h new file mode 100755 index 000000000000..5a4098f904de --- /dev/null +++ b/agg/inc/agg_trans_affine.h @@ -0,0 +1,344 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Affine transformation classes. +// +//---------------------------------------------------------------------------- +#ifndef AGG_TRANS_AFFINE_INCLUDED +#define AGG_TRANS_AFFINE_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + const double affine_epsilon = 1e-14; // About of precision of doubles + + //============================================================trans_affine + // + // See Implementation agg_trans_affine.cpp + // + // Affine transformation are linear transformations in Cartesian coordinates + // (strictly speaking not only in Cartesian, but for the beginning we will + // think so). They are rotation, scaling, translation and skewing. + // After any affine transformation a line segment remains a line segment + // and it will never become a curve. + // + // There will be no math about matrix calculations, since it has been + // described many times. Ask yourself a very simple question: + // "why do we need to understand and use some matrix stuff instead of just + // rotating, scaling and so on". The answers are: + // + // 1. Any combination of transformations can be done by only 4 multiplications + // and 4 additions in floating point. + // 2. One matrix transformation is equivalent to the number of consecutive + // discrete transformations, i.e. the matrix "accumulates" all transformations + // in the order of their settings. Suppose we have 4 transformations: + // * rotate by 30 degrees, + // * scale X to 2.0, + // * scale Y to 1.5, + // * move to (100, 100). + // The result will depend on the order of these transformations, + // and the advantage of matrix is that the sequence of discret calls: + // rotate(30), scaleX(2.0), scaleY(1.5), move(100,100) + // will have exactly the same result as the following matrix transformations: + // + // affine_matrix m; + // m *= rotate_matrix(30); + // m *= scaleX_matrix(2.0); + // m *= scaleY_matrix(1.5); + // m *= move_matrix(100,100); + // + // m.transform_my_point_at_last(x, y); + // + // What is the good of it? In real life we will set-up the matrix only once + // and then transform many points, let alone the convenience to set any + // combination of transformations. + // + // So, how to use it? Very easy - literally as it's shown above. Not quite, + // let us write a correct example: + // + // agg::trans_affine m; + // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); + // m *= agg::trans_affine_scaling(2.0, 1.5); + // m *= agg::trans_affine_translation(100.0, 100.0); + // m.transform(&x, &y); + // + // The affine matrix is all you need to perform any linear transformation, + // but all transformations have origin point (0,0). It means that we need to + // use 2 translations if we want to rotate someting around (100,100): + // + // m *= agg::trans_affine_translation(-100.0, -100.0); // move to (0,0) + // 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 + { + public: + //------------------------------------------ Construction + // Construct an identity matrix - it does not transform anything + trans_affine() : + m0(1.0), m1(0.0), m2(0.0), m3(1.0), m4(0.0), m5(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) + {} + + // Construct a matrix to transform a parallelogram to another one. + trans_affine(const double* rect, const double* parl) + { + parl_to_parl(rect, parl); + } + + // Construct a matrix to transform a 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. + trans_affine(const double* parl, + double x1, double y1, double x2, double y2) + { + parl_to_rect(parl, x1, y1, x2, y2); + } + + + //---------------------------------- 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 + const trans_affine& parl_to_parl(const double* src, + const double* dst); + + const trans_affine& rect_to_parl(double x1, double y1, + double x2, double y2, + const double* parl); + + const trans_affine& parl_to_rect(const double* parl, + double x1, double y1, + double x2, double y2); + + + //------------------------------------------ Operations + // Reset - actually load an identity matrix + const trans_affine& reset(); + + // 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); + + // 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. + const trans_affine& invert(); + + // Mirroring around X + const trans_affine& flip_x(); + + // Mirroring around Y + const trans_affine& flip_y(); + + //------------------------------------------- Load/Store + // 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; + } + + // 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++; + return *this; + } + + //------------------------------------------- Operators + + // Multiply current matrix to another one + const trans_affine& operator *= (const trans_affine& m) + { + return multiply(m); + } + + // Multiply current matrix to another one and return + // the result in a separete matrix. + trans_affine operator * (const trans_affine& m) + { + return trans_affine(*this).multiply(m); + } + + // Calculate and return the inverse matrix + trans_affine operator ~ () const + { + trans_affine ret = *this; + return ret.invert(); + } + + // Equal operator with default epsilon + bool operator == (const trans_affine& m) const + { + return is_equal(m, affine_epsilon); + } + + // Not Equal operator with default epsilon + bool operator != (const trans_affine& m) const + { + return !is_equal(m, affine_epsilon); + } + + //-------------------------------------------- Transformations + // Direct transformation 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() + void inverse_transform(double* x, double* y) const; + + //-------------------------------------------- Auxiliary + // Calculate the determinant of matrix + double determinant() const + { + return 1.0 / (m0 * m3 - m1 * m2); + } + + // Get the average scale (by X and Y). + // Basically used to calculate the approximation_scale when + // decomposinting curves into line segments. + double scale() 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 + 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; + }; + + //------------------------------------------------------------------------ + 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; + } + + //------------------------------------------------------------------------ + 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; + } + + //------------------------------------------------------------------------ + inline double trans_affine::scale() const + { + double x = 0.707106781 * m0 + 0.707106781 * m2; + double y = 0.707106781 * m1 + 0.707106781 * m3; + return sqrt(x*x + y*y); + } + + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::premultiply(const trans_affine& m) + { + trans_affine t = m; + return *this = t.multiply(*this); + } + + + //====================================================trans_affine_rotation + // Rotation matrix. sin() and cos() are calculated twice for the same angle. + // There's no harm because the performance of sin()/cos() is very good on all + // modern processors. Besides, this operation is not going to be invoked too + // often. + class trans_affine_rotation : public trans_affine + { + public: + trans_affine_rotation(double a) : + trans_affine(cos(a), sin(a), -sin(a), cos(a), 0.0, 0.0) + {} + }; + + //====================================================trans_affine_scaling + // Scaling matrix. sx, sy - 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 s) : + trans_affine(s, 0.0, 0.0, s, 0.0, 0.0) + {} + }; + + //================================================trans_affine_translation + // Translation matrix + 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_skewing + // Sckewing (shear) matrix + 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) + {} + }; + + + +} + + +#endif + diff --git a/agg/inc/agg_trans_bilinear.h b/agg/inc/agg_trans_bilinear.h new file mode 100755 index 000000000000..7398a866d3b0 --- /dev/null +++ b/agg/inc/agg_trans_bilinear.h @@ -0,0 +1,166 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Bilinear 2D transformations +// +//---------------------------------------------------------------------------- +#ifndef AGG_TRANS_BILINEAR_INCLUDED +#define AGG_TRANS_BILINEAR_INCLUDED + +#include "agg_basics.h" +#include "agg_simul_eq.h" + +namespace agg +{ + + //==========================================================trans_bilinear + class trans_bilinear + { + public: + //-------------------------------------------------------------------- + trans_bilinear() : m_valid(false) {} + + //-------------------------------------------------------------------- + // Arbitrary quadrangle transformations + trans_bilinear(const double* src, const double* dst) + { + quad_to_quad(src, dst); + } + + + //-------------------------------------------------------------------- + // Direct transformations + trans_bilinear(double x1, double y1, double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + + //-------------------------------------------------------------------- + // Reverse transformations + trans_bilinear(const double* quad, + double x1, double y1, double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + + //-------------------------------------------------------------------- + // Set the transformations using two arbitrary quadrangles. + void quad_to_quad(const double* src, const double* dst) + { + double left[4][4]; + double right[4][2]; + + unsigned i; + for(i = 0; i < 4; i++) + { + unsigned ix = i * 2; + unsigned iy = ix + 1; + left[i][0] = 1.0; + left[i][1] = src[ix] * src[iy]; + left[i][2] = src[ix]; + left[i][3] = src[iy]; + + right[i][0] = dst[ix]; + right[i][1] = dst[iy]; + } + m_valid = simul_eq<4, 2>::solve(left, right, m_mtx); + } + + + //-------------------------------------------------------------------- + // 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); + } + + + //-------------------------------------------------------------------- + // 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); + } + + //-------------------------------------------------------------------- + // 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 xy = tx * ty; + *x = m_mtx[0][0] + m_mtx[1][0] * xy + m_mtx[2][0] * tx + m_mtx[3][0] * ty; + *y = m_mtx[0][1] + m_mtx[1][1] * xy + m_mtx[2][1] * tx + m_mtx[3][1] * ty; + } + + + //-------------------------------------------------------------------- + class iterator_x + { + double inc_x; + double inc_y; + + public: + double x; + double y; + + iterator_x() {} + iterator_x(double tx, double ty, double step, const double m[4][2]) : + inc_x(m[1][0] * step * ty + m[2][0] * step), + inc_y(m[1][1] * step * ty + m[2][1] * step), + x(m[0][0] + m[1][0] * tx * ty + m[2][0] * tx + m[3][0] * ty), + y(m[0][1] + m[1][1] * tx * ty + m[2][1] * tx + m[3][1] * ty) + { + } + + void operator ++ () + { + x += inc_x; + y += inc_y; + } + }; + + iterator_x begin(double x, double y, double step) const + { + return iterator_x(x, y, step, m_mtx); + } + + private: + double m_mtx[4][2]; + bool m_valid; + }; + +} + +#endif diff --git a/agg/inc/agg_trans_double_path.h b/agg/inc/agg_trans_double_path.h new file mode 100755 index 000000000000..16ea9f7264bd --- /dev/null +++ b/agg/inc/agg_trans_double_path.h @@ -0,0 +1,131 @@ +//---------------------------------------------------------------------------- +// 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_TRANS_DOUBLE_PATH_INCLUDED +#define AGG_TRANS_DOUBLE_PATH_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + // See also: agg_trans_double_path.cpp + // + //-------------------------------------------------------trans_double_path + class trans_double_path + { + enum status_e + { + initial, + making_path, + ready + }; + + public: + typedef vertex_sequence<vertex_dist, 6> vertex_storage; + + trans_double_path(); + + //-------------------------------------------------------------------- + void base_length(double v) { m_base_length = v; } + double base_length() const { return m_base_length; } + + //-------------------------------------------------------------------- + void base_height(double v) { m_base_height = v; } + double base_height() const { return m_base_height; } + + //-------------------------------------------------------------------- + void preserve_x_scale(bool f) { m_preserve_x_scale = f; } + bool preserve_x_scale() const { return m_preserve_x_scale; } + + //-------------------------------------------------------------------- + void reset(); + void move_to1(double x, double y); + void line_to1(double x, double y); + void move_to2(double x, double y); + void line_to2(double x, double y); + void finalize_paths(); + + //-------------------------------------------------------------------- + template<class VertexSource1, class VertexSource2> + void add_paths(VertexSource1& vs1, VertexSource2& vs2, + unsigned path1_id=0, unsigned path2_id=0) + { + double x; + double y; + + unsigned cmd; + + vs1.rewind(path1_id); + while(!is_stop(cmd = vs1.vertex(&x, &y))) + { + if(is_move_to(cmd)) + { + move_to1(x, y); + } + else + { + if(is_vertex(cmd)) + { + line_to1(x, y); + } + } + } + + vs2.rewind(path2_id); + while(!is_stop(cmd = vs2.vertex(&x, &y))) + { + if(is_move_to(cmd)) + { + move_to2(x, y); + } + else + { + if(is_vertex(cmd)) + { + line_to2(x, y); + } + } + } + finalize_paths(); + } + + //-------------------------------------------------------------------- + double total_length1() const; + double total_length2() const; + void transform(double *x, double *y) const; + + private: + double finalize_path(vertex_storage& vertices); + void transform1(const vertex_storage& vertices, + double kindex, double kx, + double *x, double* y) const; + + vertex_storage m_src_vertices1; + vertex_storage m_src_vertices2; + double m_base_length; + double m_base_height; + double m_kindex1; + double m_kindex2; + status_e m_status1; + status_e m_status2; + bool m_preserve_x_scale; + }; + +} + + +#endif diff --git a/agg/inc/agg_trans_lens.h b/agg/inc/agg_trans_lens.h new file mode 100755 index 000000000000..ad900686c3fd --- /dev/null +++ b/agg/inc/agg_trans_lens.h @@ -0,0 +1,79 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.1 +// 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_WARP_MAGNIFIER_INCLUDED +#define AGG_WARP_MAGNIFIER_INCLUDED + +#include <math.h> +#include "agg_basics.h" + + +namespace agg +{ + + class trans_warp_magnifier + { + public: + trans_warp_magnifier() : m_xc(0.0), m_yc(0.0), m_magn(1.0), m_radius(1.0), m_warp(false) {} + + void center(double x, double y) { m_xc = x; m_yc = y; } + void magnification(double m) { m_magn = m; } + void radius(double r) { m_radius = r; } + void warp(bool w) { m_warp = w; } + + void transform(double* x, double* y) const + { + double dx = *x - m_xc; + double dy = *y - m_yc; + double r = sqrt(dx * dx + dy * dy); + double rm = m_radius / m_magn; + if(r < rm) + { + *x = m_xc + dx * m_magn; + *y = m_yc + dy * m_magn; + return; + } + + if(m_warp) + { + double m = (r + rm * (m_magn - 1.0)) / r; + *x = m_xc + dx * m; + *y = m_yc + dy * m; + return; + } + + if(r < m_radius) + { + double m = m_radius / r; + *x = m_xc + dx * m; + *y = m_yc + dy * m; + } + } + + private: + double m_xc; + double m_yc; + double m_magn; + double m_radius; + bool m_warp; + }; + + + +} + + +#endif + diff --git a/agg/inc/agg_trans_perspective.h b/agg/inc/agg_trans_perspective.h new file mode 100755 index 000000000000..a127c9095ad2 --- /dev/null +++ b/agg/inc/agg_trans_perspective.h @@ -0,0 +1,192 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Perspective 2D transformations +// +//---------------------------------------------------------------------------- +#ifndef AGG_TRANS_PERSPECTIVE_INCLUDED +#define AGG_TRANS_PERSPECTIVE_INCLUDED + +#include "agg_basics.h" +#include "agg_simul_eq.h" + +namespace agg +{ + //=======================================================trans_perspective + class trans_perspective + { + public: + //-------------------------------------------------------------------- + trans_perspective() : m_valid(false) {} + + + //-------------------------------------------------------------------- + // Arbitrary quadrangle transformations + trans_perspective(const double* src, const double* dst) + { + quad_to_quad(src, dst); + } + + + //-------------------------------------------------------------------- + // Direct transformations + trans_perspective(double x1, double y1, double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + + //-------------------------------------------------------------------- + // Reverse transformations + trans_perspective(const double* quad, + double x1, double y1, double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + + //-------------------------------------------------------------------- + // Set the transformations using two arbitrary quadrangles. + void quad_to_quad(const double* src, const double* dst) + { + + double left[8][8]; + double right[8][1]; + + unsigned i; + for (i = 0; i < 4; i++) + { + unsigned ix = i * 2; + unsigned iy = ix + 1; + + left[ix][0] = 1.0; + left[ix][1] = src[ix]; + left[ix][2] = src[iy]; + left[ix][3] = 0.0; + left[ix][4] = 0.0; + left[ix][5] = 0.0; + left[ix][6] = -src[ix] * dst[ix]; + left[ix][7] = -src[iy] * dst[ix]; + right[ix][0] = dst[ix]; + + left[iy][0] = 0.0; + left[iy][1] = 0.0; + left[iy][2] = 0.0; + left[iy][3] = 1.0; + left[iy][4] = src[ix]; + left[iy][5] = src[iy]; + left[iy][6] = -src[ix] * dst[iy]; + left[iy][7] = -src[iy] * dst[iy]; + right[iy][0] = dst[iy]; + } + m_valid = simul_eq<8, 1>::solve(left, right, m_mtx); + } + + + //-------------------------------------------------------------------- + // 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); + } + + + //-------------------------------------------------------------------- + // 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); + } + + //-------------------------------------------------------------------- + // 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 + { + double den; + double den_step; + double nom_x; + double nom_x_step; + double nom_y; + double nom_y_step; + + public: + double x; + 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), + x(nom_x / den), + y(nom_y / den) + { + } + + void operator ++ () + { + den += den_step; + nom_x += nom_x_step; + nom_y += nom_y_step; + double d = 1.0 / den; + x = nom_x * d; + y = nom_y * d; + } + }; + + //-------------------------------------------------------------------- + iterator_x begin(double x, double y, double step) const + { + return iterator_x(x, y, step, m_mtx); + } + + private: + double m_mtx[8][1]; + bool m_valid; + }; + +} + +#endif diff --git a/agg/inc/agg_trans_single_path.h b/agg/inc/agg_trans_single_path.h new file mode 100755 index 000000000000..68369626c396 --- /dev/null +++ b/agg/inc/agg_trans_single_path.h @@ -0,0 +1,97 @@ +//---------------------------------------------------------------------------- +// 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_TRANS_SINGLE_PATH_INCLUDED +#define AGG_TRANS_SINGLE_PATH_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + // See also: agg_trans_single_path.cpp + // + //-------------------------------------------------------trans_single_path + class trans_single_path + { + enum status_e + { + initial, + making_path, + ready + }; + + public: + typedef vertex_sequence<vertex_dist, 6> vertex_storage; + + trans_single_path(); + + //-------------------------------------------------------------------- + void base_length(double v) { m_base_length = v; } + double base_length() const { return m_base_length; } + + //-------------------------------------------------------------------- + void preserve_x_scale(bool f) { m_preserve_x_scale = f; } + bool preserve_x_scale() const { return m_preserve_x_scale; } + + //-------------------------------------------------------------------- + void reset(); + void move_to(double x, double y); + void line_to(double x, double y); + void finalize_path(); + + //-------------------------------------------------------------------- + template<class VertexSource> + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + if(is_move_to(cmd)) + { + move_to(x, y); + } + else + { + if(is_vertex(cmd)) + { + line_to(x, y); + } + } + } + finalize_path(); + } + + //-------------------------------------------------------------------- + double total_length() const; + void transform(double *x, double *y) const; + + private: + vertex_storage m_src_vertices; + double m_base_length; + double m_kindex; + status_e m_status; + bool m_preserve_x_scale; + }; + + +} + +#endif diff --git a/agg/inc/agg_trans_viewport.h b/agg/inc/agg_trans_viewport.h new file mode 100755 index 000000000000..b77a7204feb9 --- /dev/null +++ b/agg/inc/agg_trans_viewport.h @@ -0,0 +1,304 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Viewport transformer - simple orthogonal conversions from world coordinates +// to screen (device) ones. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_TRANS_VIEWPORT_INCLUDED +#define AGG_TRANS_VIEWPORT_INCLUDED + +#include <string.h> +#include "agg_basics.h" + + +namespace agg +{ + + enum aspect_ratio_e + { + aspect_ratio_stretch, + aspect_ratio_meet, + aspect_ratio_slice + }; + + + //----------------------------------------------------------trans_viewport + class trans_viewport + { + public: + //------------------------------------------------------------------- + trans_viewport() : + m_world_x1(0.0), + m_world_y1(0.0), + m_world_x2(1.0), + m_world_y2(1.0), + m_device_x1(0.0), + m_device_y1(0.0), + m_device_x2(1.0), + m_device_y2(1.0), + m_aspect(aspect_ratio_stretch), + m_align_x(0.5), + m_align_y(0.5), + m_wx1(0.0), + m_wy1(0.0), + m_wx2(1.0), + m_wy2(1.0), + m_dx1(0.0), + m_dy1(0.0), + m_kx(1.0), + m_ky(1.0) + {} + + //------------------------------------------------------------------- + void preserve_aspect_ratio(double alignx, + double aligny, + aspect_ratio_e aspect) + { + m_align_x = alignx; + m_align_y = aligny; + m_aspect = aspect; + update(); + } + + //------------------------------------------------------------------- + void device_viewport(double x1, double y1, double x2, double y2) + { + m_device_x1 = x1; + m_device_y1 = y1; + m_device_x2 = x2; + m_device_y2 = y2; + update(); + } + + //------------------------------------------------------------------- + void world_viewport(double x1, double y1, double x2, double y2) + { + m_world_x1 = x1; + m_world_y1 = y1; + m_world_x2 = x2; + m_world_y2 = y2; + update(); + } + + //------------------------------------------------------------------- + void device_viewport(double* x1, double* y1, double* x2, double* y2) const + { + *x1 = m_device_x1; + *y1 = m_device_y1; + *x2 = m_device_x2; + *y2 = m_device_y2; + } + + //------------------------------------------------------------------- + void world_viewport(double* x1, double* y1, double* x2, double* y2) const + { + *x1 = m_world_x1; + *y1 = m_world_y1; + *x2 = m_world_x2; + *y2 = m_world_y2; + } + + //------------------------------------------------------------------- + void world_viewport_actual(double* x1, double* y1, + double* x2, double* y2) const + { + *x1 = m_wx1; + *y1 = m_wy1; + *x2 = m_wx2; + *y2 = m_wy2; + } + + //------------------------------------------------------------------- + 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; } + + //------------------------------------------------------------------- + void transform(double* x, double* y) const + { + *x = (*x - m_wx1) * m_kx + m_dx1; + *y = (*y - m_wy1) * m_ky + m_dy1; + } + + //------------------------------------------------------------------- + void inverse_transform(double* x, double* y) const + { + *x = (*x - m_dx1) / m_kx + m_wx1; + *y = (*y - m_dy1) / m_ky + m_wy1; + } + + //------------------------------------------------------------------- + double scale_x() const + { + return m_kx; + } + + //------------------------------------------------------------------- + double scale_y() const + { + return m_ky; + } + + //------------------------------------------------------------------- + double scale() const + { + return (m_kx + m_ky) * 0.5; + } + + + //------------------------------------------------------------------- + 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); + } + + 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); + } + + 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); + } + + private: + void update(); + + double m_world_x1; + double m_world_y1; + double m_world_x2; + double m_world_y2; + double m_device_x1; + double m_device_y1; + double m_device_x2; + double m_device_y2; + aspect_ratio_e m_aspect; + double m_align_x; + double m_align_y; + double m_wx1; + double m_wy1; + double m_wx2; + double m_wy2; + double m_dx1; + double m_dy1; + double m_kx; + double m_ky; + }; + + + + //----------------------------------------------------------------------- + inline void trans_viewport::update() + { + double world_x1 = m_world_x1; + double world_y1 = m_world_y1; + double world_x2 = m_world_x2; + double world_y2 = m_world_y2; + double device_x1 = m_device_x1; + double device_y1 = m_device_y1; + double device_x2 = m_device_x2; + double device_y2 = m_device_y2; + if(m_aspect != aspect_ratio_stretch) + { + double d; + m_kx = (device_x2 - device_x1) / (world_x2 - world_x1); + m_ky = (device_y2 - device_y1) / (world_y2 - world_y1); + + if((m_aspect == aspect_ratio_meet) == (m_kx < m_ky)) + { + d = (world_y2 - world_y1) * m_ky / m_kx; + world_y1 += (world_y2 - world_y1 - d) * m_align_y; + world_y2 = world_y1 + d; + } + else + { + d = (world_x2 - world_x1) * m_kx / m_ky; + world_x1 += (world_x2 - world_x1 - d) * m_align_x; + world_x2 = world_x1 + d; + } + } + m_wx1 = world_x1; + m_wy1 = world_y1; + m_wx2 = world_x2; + m_wy2 = world_y2; + m_dx1 = device_x1; + m_dy1 = device_y1; + m_kx = (device_x2 - device_x1) / (world_x2 - world_x1); + m_ky = (device_y2 - device_y1) / (world_y2 - world_y1); + } + + +} + + +#endif diff --git a/agg/inc/agg_trans_warp_magnifier.h b/agg/inc/agg_trans_warp_magnifier.h new file mode 100755 index 000000000000..d71f567af2ca --- /dev/null +++ b/agg/inc/agg_trans_warp_magnifier.h @@ -0,0 +1,51 @@ +//---------------------------------------------------------------------------- +// 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_WARP_MAGNIFIER_INCLUDED +#define AGG_WARP_MAGNIFIER_INCLUDED + + +namespace agg +{ + + //----------------------------------------------------trans_warp_magnifier + // + // See Inmplementation agg_trans_warp_magnifier.cpp + // + class trans_warp_magnifier + { + public: + trans_warp_magnifier() : m_xc(0.0), m_yc(0.0), m_magn(1.0), m_radius(1.0) {} + + void center(double x, double y) { m_xc = x; m_yc = y; } + void magnification(double m) { m_magn = m; } + void radius(double r) { m_radius = r; } + + void transform(double* x, double* y) const; + void inverse_transform(double* x, double* y) const; + + private: + double m_xc; + double m_yc; + double m_magn; + double m_radius; + }; + + +} + + +#endif + diff --git a/agg/inc/agg_vcgen_bspline.h b/agg/inc/agg_vcgen_bspline.h new file mode 100755 index 000000000000..7490a50a6764 --- /dev/null +++ b/agg/inc/agg_vcgen_bspline.h @@ -0,0 +1,74 @@ +//---------------------------------------------------------------------------- +// 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_VCGEN_BSPLINE_INCLUDED +#define AGG_VCGEN_BSPLINE_INCLUDED + +#include "agg_basics.h" +#include "agg_array.h" +#include "agg_bspline.h" + + +namespace agg +{ + + //==========================================================vcgen_bspline + class vcgen_bspline + { + enum status_e + { + initial, + ready, + polygon, + end_poly, + stop + }; + + public: + typedef pod_deque<point_type, 6> vertex_storage; + + vcgen_bspline(); + + void interpolation_step(double v) { m_interpolation_step = v; } + double interpolation_step() const { return m_interpolation_step; } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned id); + unsigned vertex(double* x, double* y); + + private: + vcgen_bspline(const vcgen_bspline&); + const vcgen_bspline& operator = (const vcgen_bspline&); + + vertex_storage m_src_vertices; + bspline m_spline_x; + bspline m_spline_y; + double m_interpolation_step; + unsigned m_closed; + status_e m_status; + unsigned m_src_vertex; + double m_cur_abscissa; + double m_max_abscissa; + }; + +} + + +#endif + diff --git a/agg/inc/agg_vcgen_contour.h b/agg/inc/agg_vcgen_contour.h new file mode 100755 index 000000000000..1c5428206640 --- /dev/null +++ b/agg/inc/agg_vcgen_contour.h @@ -0,0 +1,96 @@ +//---------------------------------------------------------------------------- +// 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_VCGEN_CONTOUR_INCLUDED +#define AGG_VCGEN_CONTOUR_INCLUDED + +#include "agg_math_stroke.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + + //----------------------------------------------------------vcgen_contour + // + // See Implementation agg_vcgen_contour.cpp + // + class vcgen_contour + { + enum status_e + { + initial, + ready, + outline, + out_vertices, + end_poly, + stop + }; + + public: + typedef vertex_sequence<vertex_dist, 6> vertex_storage; + typedef pod_deque<point_type, 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; } + + 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; } + + // Generator interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned 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; + }; + +} + +#endif diff --git a/agg/inc/agg_vcgen_dash.h b/agg/inc/agg_vcgen_dash.h new file mode 100755 index 000000000000..cc4c86dea833 --- /dev/null +++ b/agg/inc/agg_vcgen_dash.h @@ -0,0 +1,99 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Line dash generator +// +//---------------------------------------------------------------------------- +#ifndef AGG_VCGEN_DASH_INCLUDED +#define AGG_VCGEN_DASH_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + + //---------------------------------------------------------------vcgen_dash + // + // See Implementation agg_vcgen_dash.cpp + // + class vcgen_dash + { + enum + { + max_dashes = 32 + }; + + enum status_e + { + initial, + ready, + polyline, + stop + }; + + public: + typedef vertex_sequence<vertex_dist, 6> vertex_storage; + + vcgen_dash(); + + void remove_all_dashes(); + void add_dash(double dash_len, double gap_len); + void dash_start(double ds); + + void shorten(double s) { m_shorten = s; } + double shorten() const { return m_shorten; } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned 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&); + + void calc_dash_start(double ds); + + double m_dashes[max_dashes]; + double m_total_dash_len; + unsigned m_num_dashes; + double m_dash_start; + double m_shorten; + double m_curr_dash_start; + unsigned m_curr_dash; + double m_curr_rest; + const vertex_dist* m_v1; + const vertex_dist* m_v2; + + vertex_storage m_src_vertices; + unsigned m_closed; + status_e m_status; + unsigned m_src_vertex; + }; + + +} + +#endif diff --git a/agg/inc/agg_vcgen_markers_term.h b/agg/inc/agg_vcgen_markers_term.h new file mode 100755 index 000000000000..6f213811c290 --- /dev/null +++ b/agg/inc/agg_vcgen_markers_term.h @@ -0,0 +1,72 @@ +//---------------------------------------------------------------------------- +// 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_VCGEN_MARKERS_TERM_INCLUDED +#define AGG_VCGEN_MARKERS_TERM_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + + //======================================================vcgen_markers_term + // + // See Implemantation agg_vcgen_markers_term.cpp + // Terminal markers generator (arrowhead/arrowtail) + // + //------------------------------------------------------------------------ + class vcgen_markers_term + { + public: + vcgen_markers_term() : m_curr_id(0), m_curr_idx(0) {} + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned 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&); + + struct coord_type + { + double x, y; + + coord_type() {} + coord_type(double x_, double y_) : x(x_), y(y_) {} + }; + + typedef pod_deque<coord_type, 6> coord_storage; + + coord_storage m_markers; + unsigned m_curr_id; + unsigned m_curr_idx; + }; + + +} + +#endif diff --git a/agg/inc/agg_vcgen_smooth_poly1.h b/agg/inc/agg_vcgen_smooth_poly1.h new file mode 100755 index 000000000000..61ca14898328 --- /dev/null +++ b/agg/inc/agg_vcgen_smooth_poly1.h @@ -0,0 +1,87 @@ +//---------------------------------------------------------------------------- +// 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_VCGEN_SMOOTH_POLY1_INCLUDED +#define AGG_VCGEN_SMOOTH_POLY1_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + + +namespace agg +{ + + //======================================================vcgen_smooth_poly1 + // + // See Implementation agg_vcgen_smooth_poly1.cpp + // Smooth polygon generator + // + //------------------------------------------------------------------------ + class vcgen_smooth_poly1 + { + enum status_e + { + initial, + ready, + polygon, + ctrl_b, + ctrl_e, + ctrl1, + ctrl2, + end_poly, + stop + }; + + public: + typedef vertex_sequence<vertex_dist, 6> vertex_storage; + + vcgen_smooth_poly1(); + + void smooth_value(double v) { m_smooth_value = v * 0.5; } + double smooth_value() const { return m_smooth_value * 2.0; } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned id); + unsigned vertex(double* x, double* y); + + private: + vcgen_smooth_poly1(const vcgen_smooth_poly1&); + const vcgen_smooth_poly1& operator = (const vcgen_smooth_poly1&); + + void calculate(const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + const vertex_dist& v3); + + vertex_storage m_src_vertices; + double m_smooth_value; + unsigned m_closed; + status_e m_status; + unsigned m_src_vertex; + double m_ctrl1_x; + double m_ctrl1_y; + double m_ctrl2_x; + double m_ctrl2_y; + }; + +} + + +#endif + diff --git a/agg/inc/agg_vcgen_stroke.h b/agg/inc/agg_vcgen_stroke.h new file mode 100755 index 000000000000..a73509acf3d9 --- /dev/null +++ b/agg/inc/agg_vcgen_stroke.h @@ -0,0 +1,114 @@ +//---------------------------------------------------------------------------- +// 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_VCGEN_STROKE_INCLUDED +#define AGG_VCGEN_STROKE_INCLUDED + +#include "agg_math_stroke.h" +#include "agg_vertex_iterator.h" + + +namespace agg +{ + + //============================================================vcgen_stroke + // + // See Implementation agg_vcgen_stroke.cpp + // Stroke generator + // + //------------------------------------------------------------------------ + class vcgen_stroke + { + enum status_e + { + initial, + ready, + cap1, + cap2, + outline1, + close_first, + outline2, + out_vertices, + end_poly1, + end_poly2, + stop + }; + + public: + typedef vertex_sequence<vertex_dist, 6> vertex_storage; + typedef pod_deque<point_type, 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; } + + 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; } + + 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; } + + 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 shorten(double s) { m_shorten = s; } + double shorten() const { return m_shorten; } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned 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; + }; + + +} + +#endif diff --git a/agg/inc/agg_vcgen_vertex_sequence.h b/agg/inc/agg_vcgen_vertex_sequence.h new file mode 100755 index 000000000000..7c4e9e4253e5 --- /dev/null +++ b/agg/inc/agg_vcgen_vertex_sequence.h @@ -0,0 +1,135 @@ +//---------------------------------------------------------------------------- +// 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_VCGEN_VERTEX_SEQUENCE_INCLUDED +#define AGG_VCGEN_VERTEX_SEQUENCE_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" +#include "agg_shorten_path.h" + +namespace agg +{ + + //===================================================vcgen_vertex_sequence + class vcgen_vertex_sequence + { + public: + typedef vertex_dist_cmd vertex_type; + typedef vertex_sequence<vertex_type, 6> vertex_storage; + + vcgen_vertex_sequence() : + m_flags(0), + m_cur_vertex(0), + m_shorten(0.0), + m_ready(false) + { + } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned id); + unsigned vertex(double* x, double* y); + + void shorten(double s) { m_shorten = s; } + double shorten() const { return m_shorten; } + + private: + vcgen_vertex_sequence(const vcgen_vertex_sequence&); + const vcgen_vertex_sequence& operator = (const vcgen_vertex_sequence&); + + vertex_storage m_src_vertices; + unsigned m_flags; + unsigned m_cur_vertex; + double m_shorten; + bool m_ready; + }; + + + //------------------------------------------------------------------------ + inline void vcgen_vertex_sequence::remove_all() + { + m_ready = false; + m_src_vertices.remove_all(); + m_cur_vertex = 0; + m_flags = 0; + } + + //------------------------------------------------------------------------ + inline void vcgen_vertex_sequence::add_vertex(double x, double y, unsigned cmd) + { + m_ready = false; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(vertex_dist_cmd(x, y, cmd)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(vertex_dist_cmd(x, y, cmd)); + } + else + { + m_flags = cmd & path_flags_mask; + } + } + } + + + //------------------------------------------------------------------------ + inline void vcgen_vertex_sequence::rewind(unsigned) + { + if(!m_ready) + { + m_src_vertices.close(is_closed(m_flags)); + shorten_path(m_src_vertices, m_shorten, get_close_flag(m_flags)); + } + m_ready = true; + m_cur_vertex = 0; + } + + //------------------------------------------------------------------------ + inline unsigned vcgen_vertex_sequence::vertex(double* x, double* y) + { + if(!m_ready) + { + rewind(0); + } + + if(m_cur_vertex == m_src_vertices.size()) + { + ++m_cur_vertex; + return path_cmd_end_poly | m_flags; + } + + if(m_cur_vertex > m_src_vertices.size()) + { + return path_cmd_stop; + } + + vertex_type& v = m_src_vertices[m_cur_vertex++]; + *x = v.x; + *y = v.y; + return v.cmd; + } + + +} + +#endif diff --git a/agg/inc/agg_vertex_iterator.h b/agg/inc/agg_vertex_iterator.h new file mode 100755 index 000000000000..f22af0acb888 --- /dev/null +++ b/agg/inc/agg_vertex_iterator.h @@ -0,0 +1,133 @@ +//---------------------------------------------------------------------------- +// 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: vertex_iterator +// vertex_source_adaptor +// vertex_source_adaptor_with_id +// +//---------------------------------------------------------------------------- +#ifndef AGG_VERTEX_ITERATOR_INCLUDED +#define AGG_VERTEX_ITERATOR_INCLUDED + +#include "agg_basics.h" + + +namespace agg +{ + + //---------------------------------------------------------vertex_iterator + template<class VertexSource> class vertex_iterator + { + public: + vertex_iterator() {} + vertex_iterator(unsigned cmd) { m_vertex.cmd = cmd; } + vertex_iterator(const vertex_iterator& i) : m_vs(i.m_vs), m_vertex(i.m_vertex) {} + vertex_iterator(VertexSource& vs, unsigned id) : m_vs(&vs) + { + m_vs->rewind(id); + m_vertex.cmd = m_vs->vertex(&m_vertex.x, &m_vertex.y); + } + vertex_iterator& operator++() + { + m_vertex.cmd = m_vs->vertex(&m_vertex.x, &m_vertex.y); + return *this; + } + + const vertex_type& operator*() const { return m_vertex; } + const vertex_type* operator->() const { return &m_vertex; } + + bool operator != (const vertex_iterator& i) + { + return m_vertex.cmd != i.m_vertex.cmd; + } + + private: + VertexSource* m_vs; + vertex_type m_vertex; + }; + + + //---------------------------------------------------vertex_source_adaptor + template<class VertexContainer> class vertex_source_adaptor + { + public: + vertex_source_adaptor(const VertexContainer& container) : + m_container(&container) {} + + void rewind(unsigned) + { + m_iterator = m_container->begin(); + m_end = m_container->end(); + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + if(m_iterator != m_end) + { + *x = m_iterator->x; + *y = m_iterator->y; + cmd = m_iterator->cmd; + ++m_iterator; + } + return cmd; + } + + private: + const VertexContainer* m_container; + typename VertexContainer::const_iterator m_iterator; + typename VertexContainer::const_iterator m_end; + }; + + + + //-------------------------------------------vertex_source_adaptor_with_id + template<class VertexContainer> class vertex_source_adaptor_with_id + { + public: + vertex_source_adaptor_with_id(const VertexContainer& container) : + m_container(&container) {} + + void rewind(unsigned id) + { + m_iterator = m_container->begin(id); + m_end = m_container->end(); + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + if(m_iterator != m_end) + { + *x = m_iterator->x; + *y = m_iterator->y; + cmd = m_iterator->cmd; + ++m_iterator; + } + return cmd; + } + + private: + const VertexContainer* m_container; + typename VertexContainer::const_iterator m_iterator; + typename VertexContainer::const_iterator m_end; + }; + + + +} + + +#endif diff --git a/agg/inc/agg_vertex_sequence.h b/agg/inc/agg_vertex_sequence.h new file mode 100755 index 000000000000..357a3df15fa4 --- /dev/null +++ b/agg/inc/agg_vertex_sequence.h @@ -0,0 +1,176 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// vertex_sequence container and vertex_dist struct +// +//---------------------------------------------------------------------------- +#ifndef AGG_VERTEX_SEQUENCE_INCLUDED +#define AGG_VERTEX_SEQUENCE_INCLUDED + +#include "agg_basics.h" +#include "agg_array.h" +#include "agg_math.h" + +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: + // + // bool 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 + // adding and to return true if the vertex fits some criteria or false if + // it doesn't. In the last case the new vertex is not added. + // + // The simple example is filtering coinciding vertices with calculation + // of the distance between the current and previous ones: + // + // struct vertex_dist + // { + // double x; + // double y; + // double dist; + // + // vertex_dist() {} + // vertex_dist(double x_, double y_) : + // x(x_), + // y(y_), + // dist(0.0) + // { + // } + // + // bool operator () (const vertex_dist& val) + // { + // return (dist = calc_distance(x, y, val.x, val.y)) > EPSILON; + // } + // }; + // + // Function close() calls this operator and removes the last vertex if + // necessary. + //------------------------------------------------------------------------ + template<class T, unsigned S=6> + class vertex_sequence : public pod_deque<T, S> + { + public: + typedef pod_deque<T, S> base_type; + + void add(const T& val); + void modify_last(const T& val); + void close(bool remove_flag); + }; + + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void vertex_sequence<T, S>::add(const T& val) + { + if(base_type::size() > 1) + { + if(!(*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) + { + base_type::remove_last(); + } + } + base_type::add(val); + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void vertex_sequence<T, S>::modify_last(const T& val) + { + base_type::remove_last(); + add(val); + } + + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void vertex_sequence<T, S>::close(bool closed) + { + while(base_type::size() > 1) + { + if((*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) break; + T t = (*this)[base_type::size() - 1]; + base_type::remove_last(); + modify_last(t); + } + + if(closed) + { + while(base_type::size() > 1) + { + if((*this)[base_type::size() - 1]((*this)[0])) break; + base_type::remove_last(); + } + } + } + + + + // 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 + // and 0.0 if it's a polyline. + struct vertex_dist + { + double x; + double y; + double dist; + + vertex_dist() {} + vertex_dist(double x_, double y_) : + x(x_), + y(y_), + dist(0.0) + { + } + + bool operator () (const vertex_dist& val) + { + bool ret = (dist = calc_distance(x, y, val.x, val.y)) > vertex_dist_epsilon; + if(!ret) dist = 1.0 / vertex_dist_epsilon; + return ret; + } + }; + + + + //--------------------------------------------------------vertex_dist_cmd + // Save as the above but with additional "command" value + struct vertex_dist_cmd : public vertex_dist + { + unsigned cmd; + + vertex_dist_cmd() {} + vertex_dist_cmd(double x_, double y_, unsigned cmd_) : + vertex_dist(x_, y_), + cmd(cmd_) + { + } + }; + + +} + +#endif diff --git a/agg/inc/agg_vpgen_clip_polygon.h b/agg/inc/agg_vpgen_clip_polygon.h new file mode 100755 index 000000000000..d5da460843e6 --- /dev/null +++ b/agg/inc/agg_vpgen_clip_polygon.h @@ -0,0 +1,83 @@ +//---------------------------------------------------------------------------- +// 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_VPGEN_CLIP_POLYGON_INCLUDED +#define AGG_VPGEN_CLIP_POLYGON_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================vpgen_clip_polygon + // + // See Implementation agg_vpgen_clip_polygon.cpp + // + class vpgen_clip_polygon + { + public: + vpgen_clip_polygon() : + m_clip_box(0, 0, 1, 1), + m_x1(0), + m_y1(0), + m_clip_flags(0), + m_num_vertices(0), + m_vertex(0), + m_cmd(path_cmd_move_to) + { + } + + 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.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; } + double y2() const { return m_clip_box.y2; } + + static bool auto_close() { return true; } + static bool auto_unclose() { return false; } + + void reset(); + void move_to(double x, double y); + void line_to(double x, double y); + unsigned vertex(double* x, double* y); + + private: + unsigned clipping_flags(double x, double y); + + private: + rect_d m_clip_box; + double m_x1; + double m_y1; + unsigned m_clip_flags; + double m_x[4]; + double m_y[4]; + unsigned m_num_vertices; + unsigned m_vertex; + unsigned m_cmd; + }; + +} + + +#endif diff --git a/agg/inc/agg_vpgen_clip_polyline.h b/agg/inc/agg_vpgen_clip_polyline.h new file mode 100755 index 000000000000..f951966a3293 --- /dev/null +++ b/agg/inc/agg_vpgen_clip_polyline.h @@ -0,0 +1,121 @@ +//---------------------------------------------------------------------------- +// 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_VPGEN_CLIP_POLYLINE_INCLUDED +#define AGG_VPGEN_CLIP_POLYLINE_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================vpgen_clip_polyline + // + // See Implementation agg_vpgen_clip_polyline.cpp + // + class vpgen_clip_polyline + { + public: + vpgen_clip_polyline() : + 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) + { + } + + 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.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; } + double y2() const { return m_clip_box.y2; } + + static bool auto_close() { return false; } + static bool auto_unclose() { return true; } + + void reset(); + void move_to(double x, double y); + void line_to(double x, double y); + 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; + }; + +} + + +#endif diff --git a/agg/inc/agg_vpgen_segmentator.h b/agg/inc/agg_vpgen_segmentator.h new file mode 100755 index 000000000000..1acc3531cc6e --- /dev/null +++ b/agg/inc/agg_vpgen_segmentator.h @@ -0,0 +1,61 @@ +//---------------------------------------------------------------------------- +// 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_VPGEN_SEGMENTATOR_INCLUDED +#define AGG_VPGEN_SEGMENTATOR_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + + //=======================================================vpgen_segmentator + // + // See Implementation agg_vpgen_segmentator.cpp + // + class vpgen_segmentator + { + public: + vpgen_segmentator() : m_approximation_scale(1.0) {} + + void approximation_scale(double s) { m_approximation_scale = s; } + double approximation_scale() const { return m_approximation_scale; } + + static bool auto_close() { return false; } + static bool auto_unclose() { return false; } + + void reset() { m_cmd = path_cmd_stop; } + void move_to(double x, double y); + void line_to(double x, double y); + unsigned vertex(double* x, double* y); + + private: + double m_approximation_scale; + double m_x1; + double m_y1; + double m_dx; + double m_dy; + double m_dl; + double m_ddl; + unsigned m_cmd; + }; + + + +} + +#endif + |