From 1f8b03e68d107468f08fea4f49f54937d6cffc06 Mon Sep 17 00:00:00 2001 From: Jerome Duval Date: Mon, 17 Sep 2018 20:41:46 +0200 Subject: [PATCH] clockwerk: update agg to build with gcc7. --- haiku-apps/clockwerk/clockwerk-1.0~git.recipe | 3 +- .../patches/clockwerk-1.0~git.patchset | 10427 ++++++++++++++++ 2 files changed, 10429 insertions(+), 1 deletion(-) create mode 100644 haiku-apps/clockwerk/patches/clockwerk-1.0~git.patchset diff --git a/haiku-apps/clockwerk/clockwerk-1.0~git.recipe b/haiku-apps/clockwerk/clockwerk-1.0~git.recipe index 4b35b945f..77118f75c 100644 --- a/haiku-apps/clockwerk/clockwerk-1.0~git.recipe +++ b/haiku-apps/clockwerk/clockwerk-1.0~git.recipe @@ -9,12 +9,13 @@ HOMEPAGE="https://github.com/stippi/Clockwerk" COPYRIGHT="2001-2009 Stephan Aßmus 2000-2006 Ingo Weinhold" LICENSE="GNU GPL v2" -REVISION="6" +REVISION="7" srcGitRev="c44c3ec92c59a6b0937ba5162de96634054b104c" SOURCE_URI="$HOMEPAGE/archive/$srcGitRev.tar.gz" CHECKSUM_SHA256="55b4dc171edc4594e699a53aaaec2527b68af5971d636077c6b70193549bc25c" SOURCE_FILENAME="$portName-$srcGitRev.tar.gz" SOURCE_DIR="Clockwerk-$srcGitRev" +PATCHES="clockwerk-$portVersion.patchset" ARCHITECTURES="x86_gcc2 x86_64" diff --git a/haiku-apps/clockwerk/patches/clockwerk-1.0~git.patchset b/haiku-apps/clockwerk/patches/clockwerk-1.0~git.patchset new file mode 100644 index 000000000..f9bce01c9 --- /dev/null +++ b/haiku-apps/clockwerk/patches/clockwerk-1.0~git.patchset @@ -0,0 +1,10427 @@ +From c0ae410f5f2b381e5d1a8bd873270a242b5017f5 Mon Sep 17 00:00:00 2001 +From: Jerome Duval +Date: Mon, 17 Sep 2018 20:33:30 +0200 +Subject: update agg to version 2.4 from Haiku tree. + + +diff --git a/src/editor/tools/transform/DragStates.cpp b/src/editor/tools/transform/DragStates.cpp +index 165aba8..9ae6b39 100644 +--- a/src/editor/tools/transform/DragStates.cpp ++++ b/src/editor/tools/transform/DragStates.cpp +@@ -48,6 +48,25 @@ snap_scale(double scale) + return scale * sign; + } + ++ ++// from 2.x agg_trans_affine.cpp ++static inline void ++rect_to_rect(agg::trans_affine& a, double x1, double y1, ++ double x2, double y2, double x3, double y3, ++ double x4, double y4) { ++ double src[6]; ++ src[0] = x1; src[1] = y1; ++ src[2] = x2; src[3] = y1; ++ src[4] = x2; src[5] = y2; ++ ++ double dst[6]; ++ dst[0] = x3; dst[1] = y3; ++ dst[2] = x4; dst[3] = y3; ++ dst[4] = x4; dst[5] = y4; ++ ++ a.parl_to_parl(src, dst); ++} ++ + //------------------------------------------------------------------ + // DragState + +@@ -200,7 +219,7 @@ DragCornerState::DragTo(BPoint current, uint32 modifiers) + // distortion of the box with the opposite + // corner of the one being dragged staying fixed + AffineTransform s; +- s.rect_to_rect(oldBox.left, oldBox.top, oldBox.right, oldBox.bottom, ++ rect_to_rect(s, oldBox.left, oldBox.top, oldBox.right, oldBox.bottom, + newBox.left, newBox.top, newBox.right, newBox.bottom); + + // construct a transformation that +@@ -473,7 +492,7 @@ DragSideState::DragTo(BPoint current, uint32 modifiers) + // distortion of the box with the opposite + // corner of the one being dragged staying fixed + AffineTransform s; +- s.rect_to_rect(oldBox.left, oldBox.top, oldBox.right, oldBox.bottom, ++ rect_to_rect(s, oldBox.left, oldBox.top, oldBox.right, oldBox.bottom, + newBox.left, newBox.top, newBox.right, newBox.bottom); + + // construct a transformation that +diff --git a/src/shared/generic/regex.cpp b/src/shared/generic/regex.cpp +index c6405b8..766f208 100644 +--- a/src/shared/generic/regex.cpp ++++ b/src/shared/generic/regex.cpp +@@ -2874,7 +2874,7 @@ re_set_registers (struct re_pattern_buffer * bufp, struct re_registers * regs, + { + bufp->regs_allocated = REGS_UNALLOCATED; + regs->num_regs = 0; +- regs->start = regs->end = (regoff_t) 0; ++ regs->start = regs->end = NULL; + } + } + +diff --git a/src/shared/painter/FontCacheEntry.cpp b/src/shared/painter/FontCacheEntry.cpp +index 7c36f61..3fb475f 100644 +--- a/src/shared/painter/FontCacheEntry.cpp ++++ b/src/shared/painter/FontCacheEntry.cpp +@@ -82,7 +82,7 @@ class FontCacheEntry::GlyphCachePool { + } + + private: +- agg::pod_allocator fAllocator; ++ agg::block_allocator fAllocator; + GlyphCache** fGlyphs[256]; + }; + +diff --git a/src/third_party/agg/include/agg_alpha_mask_u8.h b/src/third_party/agg/include/agg_alpha_mask_u8.h +index b325c54..50081a8 100644 +--- a/src/third_party/agg/include/agg_alpha_mask_u8.h ++++ b/src/third_party/agg/include/agg_alpha_mask_u8.h +@@ -70,7 +70,7 @@ namespace agg + { + if(x >= 0 && y >= 0 && + x < (int)m_rbuf->width() && +- y <= (int)m_rbuf->height()) ++ y < (int)m_rbuf->height()) + { + return (cover_type)m_mask_function.calculate( + m_rbuf->row_ptr(y) + x * Step + Offset); +@@ -83,7 +83,7 @@ namespace agg + { + if(x >= 0 && y >= 0 && + x < (int)m_rbuf->width() && +- y <= (int)m_rbuf->height()) ++ y < (int)m_rbuf->height()) + { + return (cover_type)((cover_full + val * + m_mask_function.calculate( +diff --git a/src/third_party/agg/include/agg_array.h b/src/third_party/agg/include/agg_array.h +index 57f8ae6..8d56683 100644 +--- a/src/third_party/agg/include/agg_array.h ++++ b/src/third_party/agg/include/agg_array.h +@@ -109,20 +109,27 @@ namespace agg + typedef T value_type; + typedef pod_array self_type; + +- ~pod_array() { delete [] m_array; } ++ ~pod_array() { pod_allocator::deallocate(m_array, m_size); } + pod_array() : m_array(0), m_size(0) {} +- pod_array(unsigned size) : m_array(new T[size]), m_size(size) {} ++ ++ pod_array(unsigned size) : ++ m_array(pod_allocator::allocate(size)), ++ m_size(size) ++ {} ++ + pod_array(const self_type& v) : +- m_array(new T[v.m_size]), m_size(v.m_size) ++ m_array(pod_allocator::allocate(v.m_size)), ++ m_size(v.m_size) + { + memcpy(m_array, v.m_array, sizeof(T) * m_size); + } ++ + void resize(unsigned size) + { + if(size != m_size) + { +- delete [] m_array; +- m_array = new T[m_size = size]; ++ pod_allocator::deallocate(m_array, m_size); ++ m_array = pod_allocator::allocate(m_size = size); + } + } + const self_type& operator = (const self_type& v) +@@ -157,7 +164,7 @@ namespace agg + public: + typedef T value_type; + +- ~pod_vector() { delete [] m_array; } ++ ~pod_vector() { pod_allocator::deallocate(m_array, m_capacity); } + pod_vector() : m_size(0), m_capacity(0), m_array(0) {} + pod_vector(unsigned cap, unsigned extra_tail=0); + +@@ -215,9 +222,9 @@ namespace agg + m_size = 0; + if(cap > m_capacity) + { +- delete [] m_array; ++ pod_allocator::deallocate(m_array, m_capacity); + m_capacity = cap + extra_tail; +- m_array = m_capacity ? new T [m_capacity] : 0; ++ m_array = m_capacity ? pod_allocator::allocate(m_capacity) : 0; + } + } + +@@ -238,9 +245,9 @@ namespace agg + { + if(new_size > m_capacity) + { +- T* data = new T[new_size]; ++ T* data = pod_allocator::allocate(new_size); + memcpy(data, m_array, m_size * sizeof(T)); +- delete [] m_array; ++ pod_allocator::deallocate(m_array, m_capacity); + m_array = data; + } + } +@@ -252,13 +259,15 @@ namespace agg + + //------------------------------------------------------------------------ + template pod_vector::pod_vector(unsigned cap, unsigned extra_tail) : +- m_size(0), m_capacity(cap + extra_tail), m_array(new T[m_capacity]) {} ++ m_size(0), ++ m_capacity(cap + extra_tail), ++ m_array(pod_allocator::allocate(m_capacity)) {} + + //------------------------------------------------------------------------ + template pod_vector::pod_vector(const pod_vector& v) : + m_size(v.m_size), + m_capacity(v.m_capacity), +- m_array(v.m_capacity ? new T [v.m_capacity] : 0) ++ m_array(v.m_capacity ? pod_allocator::allocate(v.m_capacity) : 0) + { + memcpy(m_array, v.m_array, sizeof(T) * v.m_size); + } +@@ -509,11 +518,11 @@ namespace agg + T** blk = m_blocks + m_num_blocks - 1; + while(m_num_blocks--) + { +- delete [] *blk; ++ pod_allocator::deallocate(*blk, block_size); + --blk; + } +- delete [] m_blocks; + } ++ pod_allocator::deallocate(m_blocks, m_max_blocks); + } + + +@@ -526,7 +535,13 @@ namespace agg + unsigned nb = (size + block_mask) >> block_shift; + while(m_num_blocks > nb) + { +- delete [] m_blocks[--m_num_blocks]; ++ pod_allocator::deallocate(m_blocks[--m_num_blocks], block_size); ++ } ++ if(m_num_blocks == 0) ++ { ++ pod_allocator::deallocate(m_blocks, m_max_blocks); ++ m_blocks = 0; ++ m_max_blocks = 0; + } + m_size = size; + } +@@ -562,13 +577,15 @@ namespace agg + m_size(v.m_size), + m_num_blocks(v.m_num_blocks), + m_max_blocks(v.m_max_blocks), +- m_blocks(v.m_max_blocks ? new T* [v.m_max_blocks] : 0), ++ m_blocks(v.m_max_blocks ? ++ pod_allocator::allocate(v.m_max_blocks) : ++ 0), + m_block_ptr_inc(v.m_block_ptr_inc) + { + unsigned i; + for(i = 0; i < v.m_num_blocks; ++i) + { +- m_blocks[i] = new T [block_size]; ++ m_blocks[i] = pod_allocator::allocate(block_size); + memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); + } + } +@@ -599,7 +616,7 @@ namespace agg + { + if(nb >= m_max_blocks) + { +- T** new_blocks = new T* [m_max_blocks + m_block_ptr_inc]; ++ T** new_blocks = pod_allocator::allocate(m_max_blocks + m_block_ptr_inc); + + if(m_blocks) + { +@@ -607,12 +624,12 @@ namespace agg + m_blocks, + m_num_blocks * sizeof(T*)); + +- delete [] m_blocks; ++ pod_allocator::deallocate(m_blocks, m_max_blocks); + } + m_blocks = new_blocks; + m_max_blocks += m_block_ptr_inc; + } +- m_blocks[nb] = new T [block_size]; ++ m_blocks[nb] = pod_allocator::allocate(block_size); + m_num_blocks++; + } + +@@ -753,7 +770,7 @@ namespace agg + } + + +- //-----------------------------------------------------------pod_allocator ++ //---------------------------------------------------------block_allocator + // Allocator for arbitrary POD data. Most usable in different cache + // systems for efficient memory allocations. + // Memory is allocated with blocks of fixed size ("block_size" in +@@ -761,20 +778,26 @@ namespace agg + // creates a new block of the required size. However, the most efficient + // use is when the average reqired size is much less than the block size. + //------------------------------------------------------------------------ +- class pod_allocator ++ class block_allocator + { ++ struct block_type ++ { ++ int8u* data; ++ unsigned size; ++ }; ++ + public: + void remove_all() + { + if(m_num_blocks) + { +- int8u** blk = m_blocks + m_num_blocks - 1; ++ block_type* blk = m_blocks + m_num_blocks - 1; + while(m_num_blocks--) + { +- delete [] *blk; ++ pod_allocator::deallocate(blk->data, blk->size); + --blk; + } +- delete [] m_blocks; ++ pod_allocator::deallocate(m_blocks, m_max_blocks); + } + m_num_blocks = 0; + m_max_blocks = 0; +@@ -783,12 +806,12 @@ namespace agg + m_rest = 0; + } + +- ~pod_allocator() ++ ~block_allocator() + { + remove_all(); + } + +- pod_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) : ++ block_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) : + m_block_size(block_size), + m_block_ptr_inc(block_ptr_inc), + m_num_blocks(0), +@@ -808,7 +831,9 @@ namespace agg + int8u* ptr = m_buf_ptr; + if(alignment > 1) + { +- unsigned align = (alignment - unsigned((size_t)ptr) % alignment) % alignment; ++ unsigned align = ++ (alignment - unsigned((size_t)ptr) % alignment) % alignment; ++ + size += align; + ptr += align; + if(size <= m_rest) +@@ -835,31 +860,36 @@ namespace agg + if(size < m_block_size) size = m_block_size; + if(m_num_blocks >= m_max_blocks) + { +- int8u** new_blocks = new int8u* [m_max_blocks + m_block_ptr_inc]; ++ block_type* new_blocks = ++ pod_allocator::allocate(m_max_blocks + m_block_ptr_inc); + + if(m_blocks) + { + memcpy(new_blocks, + m_blocks, +- m_num_blocks * sizeof(int8u*)); +- +- delete [] m_blocks; ++ m_num_blocks * sizeof(block_type)); ++ pod_allocator::deallocate(m_blocks, m_max_blocks); + } + m_blocks = new_blocks; + m_max_blocks += m_block_ptr_inc; + } +- m_blocks[m_num_blocks] = m_buf_ptr = new int8u [size]; ++ ++ m_blocks[m_num_blocks].size = size; ++ m_blocks[m_num_blocks].data = ++ m_buf_ptr = ++ pod_allocator::allocate(size); ++ + m_num_blocks++; + m_rest = size; + } + +- unsigned m_block_size; +- unsigned m_block_ptr_inc; +- unsigned m_num_blocks; +- unsigned m_max_blocks; +- int8u** m_blocks; +- int8u* m_buf_ptr; +- unsigned m_rest; ++ unsigned m_block_size; ++ unsigned m_block_ptr_inc; ++ unsigned m_num_blocks; ++ unsigned m_max_blocks; ++ block_type* m_blocks; ++ int8u* m_buf_ptr; ++ unsigned m_rest; + }; + + +@@ -1014,6 +1044,16 @@ namespace agg + return j; + } + ++ //--------------------------------------------------------invert_container ++ template void invert_container(Array& arr) ++ { ++ int i = 0; ++ int j = arr.size() - 1; ++ while(i < j) ++ { ++ swap_elements(arr[i++], arr[j--]); ++ } ++ } + + //------------------------------------------------------binary_search_pos + template +@@ -1033,16 +1073,47 @@ namespace agg + if(less(val, arr[mid])) end = mid; + else beg = mid; + } +-/* +- if(beg <= 0 && +- less(val, arr[0])) return 0; + +- if(end >= arr.size() - 1 && +- less(arr[end], val)) ++end; +-*/ ++ //if(beg <= 0 && less(val, arr[0])) return 0; ++ //if(end >= arr.size() - 1 && less(arr[end], val)) ++end; ++ + return end; + } + ++ //----------------------------------------------------------range_adaptor ++ template class range_adaptor ++ { ++ public: ++ typedef typename Array::value_type value_type; ++ ++ range_adaptor(Array& array, unsigned start, unsigned size) : ++ m_array(array), m_start(start), m_size(size) ++ {} ++ ++ unsigned size() const { return m_size; } ++ const value_type& operator [] (unsigned i) const { return m_array[m_start + i]; } ++ value_type& operator [] (unsigned i) { return m_array[m_start + i]; } ++ const value_type& at(unsigned i) const { return m_array[m_start + i]; } ++ value_type& at(unsigned i) { return m_array[m_start + i]; } ++ value_type value_at(unsigned i) const { return m_array[m_start + i]; } ++ ++ private: ++ Array& m_array; ++ unsigned m_start; ++ unsigned m_size; ++ }; ++ ++ //---------------------------------------------------------------int_less ++ inline bool int_less(int a, int b) { return a < b; } ++ ++ //------------------------------------------------------------int_greater ++ inline bool int_greater(int a, int b) { return a > b; } ++ ++ //----------------------------------------------------------unsigned_less ++ inline bool unsigned_less(unsigned a, unsigned b) { return a < b; } ++ ++ //-------------------------------------------------------unsigned_greater ++ inline bool unsigned_greater(unsigned a, unsigned b) { return a > b; } + } + + #endif +diff --git a/src/third_party/agg/include/agg_basics.h b/src/third_party/agg/include/agg_basics.h +index cf3cc5f..3097130 100644 +--- a/src/third_party/agg/include/agg_basics.h ++++ b/src/third_party/agg/include/agg_basics.h +@@ -19,6 +19,43 @@ + #include + #include "agg_config.h" + ++//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR ++#ifdef AGG_CUSTOM_ALLOCATOR ++#include "agg_allocator.h" ++#else ++namespace agg ++{ ++ // The policy of all AGG containers and memory allocation strategy ++ // in general is that no allocated data requires explicit construction. ++ // It means that the allocator can be really simple; you can even ++ // replace new/delete to malloc/free. The constructors and destructors ++ // won't be called in this case, however everything will remain working. ++ // The second argument of deallocate() is the size of the allocated ++ // block. You can use this information if you wish. ++ //------------------------------------------------------------pod_allocator ++ template struct pod_allocator ++ { ++ static T* allocate(unsigned num) { return new T [num]; } ++ static void deallocate(T* ptr, unsigned) { delete [] ptr; } ++ }; ++ ++ // Single object allocator. It's also can be replaced with your custom ++ // allocator. The difference is that it can only allocate a single ++ // object and the constructor and destructor must be called. ++ // In AGG there is no need to allocate an array of objects with ++ // calling their constructors (only single ones). So that, if you ++ // replace these new/delete to malloc/free make sure that the in-place ++ // new is called and take care of calling the destructor too. ++ //------------------------------------------------------------obj_allocator ++ template struct obj_allocator ++ { ++ static T* allocate() { return new T; } ++ static void deallocate(T* ptr) { delete ptr; } ++ }; ++} ++#endif ++ ++ + //-------------------------------------------------------- Default basic types + // + // If the compiler has different capacity of the basic types you can redefine +@@ -93,21 +130,31 @@ namespace agg + #pragma warning(disable : 4035) //Disable warning "no return value" + AGG_INLINE int iround(double v) //-------iround + { ++ int t; + __asm fld qword ptr [v] +- __asm fistp dword ptr [ebp-8] +- __asm mov eax, dword ptr [ebp-8] ++ __asm fistp dword ptr [t] ++ __asm mov eax, dword ptr [t] + } + AGG_INLINE unsigned uround(double v) //-------uround + { ++ unsigned t; + __asm fld qword ptr [v] +- __asm fistp dword ptr [ebp-8] +- __asm mov eax, dword ptr [ebp-8] ++ __asm fistp dword ptr [t] ++ __asm mov eax, dword ptr [t] + } + #pragma warning(pop) ++ AGG_INLINE int ifloor(double v) ++ { ++ return int(floor(v)); ++ } + AGG_INLINE unsigned ufloor(double v) //-------ufloor + { + return unsigned(floor(v)); + } ++ AGG_INLINE int iceil(double v) ++ { ++ return int(ceil(v)); ++ } + AGG_INLINE unsigned uceil(double v) //--------uceil + { + return unsigned(ceil(v)); +@@ -121,10 +168,18 @@ namespace agg + { + return unsigned(v); + } ++ AGG_INLINE int ifloor(double v) ++ { ++ return int(floor(v)); ++ } + AGG_INLINE unsigned ufloor(double v) + { + return unsigned(floor(v)); + } ++ AGG_INLINE int iceil(double v) ++ { ++ return int(ceil(v)); ++ } + AGG_INLINE unsigned uceil(double v) + { + return unsigned(ceil(v)); +@@ -138,10 +193,19 @@ namespace agg + { + return unsigned(v + 0.5); + } ++ AGG_INLINE int ifloor(double v) ++ { ++ int i = int(v); ++ return i - (i > v); ++ } + AGG_INLINE unsigned ufloor(double v) + { + return unsigned(v); + } ++ AGG_INLINE int iceil(double v) ++ { ++ return int(ceil(v)); ++ } + AGG_INLINE unsigned uceil(double v) + { + return unsigned(ceil(v)); +@@ -164,7 +228,7 @@ namespace agg + { + AGG_INLINE static unsigned mul(unsigned a, unsigned b) + { +- register unsigned q = a * b + (1 << (Shift-1)); ++ unsigned q = a * b + (1 << (Shift-1)); + return (q + (q >> Shift)) >> Shift; + } + }; +@@ -190,7 +254,14 @@ namespace agg + { + poly_subpixel_shift = 8, //----poly_subpixel_shift + poly_subpixel_scale = 1< struct rect_base + { ++ typedef T value_type; + typedef rect_base self_type; +- T x1; +- T y1; +- T x2; +- T y2; ++ T x1, y1, x2, y2; + + rect_base() {} + rect_base(T x1_, T y1_, T x2_, T y2_) : + x1(x1_), y1(y1_), x2(x2_), y2(y2_) {} + ++ void init(T x1_, T y1_, T x2_, T y2_) ++ { ++ x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_; ++ } ++ + const self_type& normalize() + { + T t; +@@ -242,6 +316,17 @@ namespace agg + { + return x1 <= x2 && y1 <= y2; + } ++ ++ bool hit_test(T x, T y) const ++ { ++ return (x >= x1 && x <= x2 && y >= y1 && y <= y2); ++ } ++ ++ bool overlaps(const self_type& r) const ++ { ++ return !(r.x1 > x2 || r.x2 < x1 ++ || r.y1 > y2 || r.y2 < y1); ++ } + }; + + //-----------------------------------------------------intersect_rectangles +@@ -444,6 +529,30 @@ namespace agg + typedef vertex_base vertex_f; //-----vertex_f + typedef vertex_base vertex_d; //-----vertex_d + ++ //----------------------------------------------------------------row_info ++ template struct row_info ++ { ++ int x1, x2; ++ T* ptr; ++ row_info() {} ++ row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {} ++ }; ++ ++ //----------------------------------------------------------const_row_info ++ template struct const_row_info ++ { ++ int x1, x2; ++ const T* ptr; ++ const_row_info() {} ++ const_row_info(int x1_, int x2_, const T* ptr_) : ++ x1(x1_), x2(x2_), ptr(ptr_) {} ++ }; ++ ++ //------------------------------------------------------------is_equal_eps ++ template inline bool is_equal_eps(T v1, T v2, T epsilon) ++ { ++ return fabs(v1 - v2) <= double(epsilon); ++ } + } + + +diff --git a/src/third_party/agg/include/agg_blur.h b/src/third_party/agg/include/agg_blur.h +new file mode 100644 +index 0000000..0860f52 +--- /dev/null ++++ b/src/third_party/agg/include/agg_blur.h +@@ -0,0 +1,1294 @@ ++//---------------------------------------------------------------------------- ++// Anti-Grain Geometry - Version 2.4 ++// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) ++// ++// Permission to copy, use, modify, sell and distribute this software ++// is granted provided this copyright notice appears in all copies. ++// This software is provided "as is" without express or implied ++// warranty, and with no claim as to its suitability for any purpose. ++// ++//---------------------------------------------------------------------------- ++// Contact: mcseem@antigrain.com ++// mcseemagg@yahoo.com ++// http://www.antigrain.com ++//---------------------------------------------------------------------------- ++// ++// The Stack Blur Algorithm was invented by Mario Klingemann, ++// mario@quasimondo.com and described here: ++// http://incubator.quasimondo.com/processing/fast_blur_deluxe.php ++// (search phrase "Stackblur: Fast But Goodlooking"). ++// The major improvement is that there's no more division table ++// that was very expensive to create for large blur radii. Insted, ++// for 8-bit per channel and radius not exceeding 254 the division is ++// replaced by multiplication and shift. ++// ++//---------------------------------------------------------------------------- ++ ++#ifndef AGG_BLUR_INCLUDED ++#define AGG_BLUR_INCLUDED ++ ++#include "agg_array.h" ++#include "agg_pixfmt_transposer.h" ++ ++namespace agg ++{ ++ ++ template struct stack_blur_tables ++ { ++ static int16u const g_stack_blur8_mul[255]; ++ static int8u const g_stack_blur8_shr[255]; ++ }; ++ ++ //------------------------------------------------------------------------ ++ template ++ int16u const stack_blur_tables::g_stack_blur8_mul[255] = ++ { ++ 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512, ++ 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512, ++ 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456, ++ 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512, ++ 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328, ++ 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456, ++ 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335, ++ 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512, ++ 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405, ++ 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328, ++ 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271, ++ 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456, ++ 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388, ++ 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335, ++ 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292, ++ 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259 ++ }; ++ ++ //------------------------------------------------------------------------ ++ template ++ int8u const stack_blur_tables::g_stack_blur8_shr[255] = ++ { ++ 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, ++ 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, ++ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, ++ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, ++ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, ++ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, ++ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, ++ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, ++ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, ++ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, ++ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, ++ 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, ++ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, ++ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, ++ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, ++ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 ++ }; ++ ++ ++ ++ //==============================================================stack_blur ++ template class stack_blur ++ { ++ public: ++ typedef ColorT color_type; ++ typedef CalculatorT calculator_type; ++ ++ //-------------------------------------------------------------------- ++ template void blur_x(Img& img, unsigned radius) ++ { ++ if(radius < 1) return; ++ ++ unsigned x, y, xp, i; ++ unsigned stack_ptr; ++ unsigned stack_start; ++ ++ color_type pix; ++ color_type* stack_pix; ++ calculator_type sum; ++ calculator_type sum_in; ++ calculator_type sum_out; ++ ++ unsigned w = img.width(); ++ unsigned h = img.height(); ++ unsigned wm = w - 1; ++ unsigned div = radius * 2 + 1; ++ ++ unsigned div_sum = (radius + 1) * (radius + 1); ++ unsigned mul_sum = 0; ++ unsigned shr_sum = 0; ++ unsigned max_val = color_type::base_mask; ++ ++ if(max_val <= 255 && radius < 255) ++ { ++ mul_sum = stack_blur_tables::g_stack_blur8_mul[radius]; ++ shr_sum = stack_blur_tables::g_stack_blur8_shr[radius]; ++ } ++ ++ m_buf.allocate(w, 128); ++ m_stack.allocate(div, 32); ++ ++ for(y = 0; y < h; y++) ++ { ++ sum.clear(); ++ sum_in.clear(); ++ sum_out.clear(); ++ ++ pix = img.pixel(0, y); ++ for(i = 0; i <= radius; i++) ++ { ++ m_stack[i] = pix; ++ sum.add(pix, i + 1); ++ sum_out.add(pix); ++ } ++ for(i = 1; i <= radius; i++) ++ { ++ pix = img.pixel((i > wm) ? wm : i, y); ++ m_stack[i + radius] = pix; ++ sum.add(pix, radius + 1 - i); ++ sum_in.add(pix); ++ } ++ ++ stack_ptr = radius; ++ for(x = 0; x < w; x++) ++ { ++ if(mul_sum) sum.calc_pix(m_buf[x], mul_sum, shr_sum); ++ else sum.calc_pix(m_buf[x], div_sum); ++ ++ sum.sub(sum_out); ++ ++ stack_start = stack_ptr + div - radius; ++ if(stack_start >= div) stack_start -= div; ++ stack_pix = &m_stack[stack_start]; ++ ++ sum_out.sub(*stack_pix); ++ ++ xp = x + radius + 1; ++ if(xp > wm) xp = wm; ++ pix = img.pixel(xp, y); ++ ++ *stack_pix = pix; ++ ++ sum_in.add(pix); ++ sum.add(sum_in); ++ ++ ++stack_ptr; ++ if(stack_ptr >= div) stack_ptr = 0; ++ stack_pix = &m_stack[stack_ptr]; ++ ++ sum_out.add(*stack_pix); ++ sum_in.sub(*stack_pix); ++ } ++ img.copy_color_hspan(0, y, w, &m_buf[0]); ++ } ++ } ++ ++ //-------------------------------------------------------------------- ++ template void blur_y(Img& img, unsigned radius) ++ { ++ pixfmt_transposer img2(img); ++ blur_x(img2, radius); ++ } ++ ++ //-------------------------------------------------------------------- ++ template void blur(Img& img, unsigned radius) ++ { ++ blur_x(img, radius); ++ pixfmt_transposer img2(img); ++ blur_x(img2, radius); ++ } ++ ++ private: ++ pod_vector m_buf; ++ pod_vector m_stack; ++ }; ++ ++ //====================================================stack_blur_calc_rgba ++ template struct stack_blur_calc_rgba ++ { ++ typedef T value_type; ++ value_type r,g,b,a; ++ ++ AGG_INLINE void clear() ++ { ++ r = g = b = a = 0; ++ } ++ ++ template AGG_INLINE void add(const ArgT& v) ++ { ++ r += v.r; ++ g += v.g; ++ b += v.b; ++ a += v.a; ++ } ++ ++ template AGG_INLINE void add(const ArgT& v, unsigned k) ++ { ++ r += v.r * k; ++ g += v.g * k; ++ b += v.b * k; ++ a += v.a * k; ++ } ++ ++ template AGG_INLINE void sub(const ArgT& v) ++ { ++ r -= v.r; ++ g -= v.g; ++ b -= v.b; ++ a -= v.a; ++ } ++ ++ template AGG_INLINE void calc_pix(ArgT& v, unsigned div) ++ { ++ typedef typename ArgT::value_type value_type; ++ v.r = value_type(r / div); ++ v.g = value_type(g / div); ++ v.b = value_type(b / div); ++ v.a = value_type(a / div); ++ } ++ ++ template ++ AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr) ++ { ++ typedef typename ArgT::value_type value_type; ++ v.r = value_type((r * mul) >> shr); ++ v.g = value_type((g * mul) >> shr); ++ v.b = value_type((b * mul) >> shr); ++ v.a = value_type((a * mul) >> shr); ++ } ++ }; ++ ++ ++ //=====================================================stack_blur_calc_rgb ++ template struct stack_blur_calc_rgb ++ { ++ typedef T value_type; ++ value_type r,g,b; ++ ++ AGG_INLINE void clear() ++ { ++ r = g = b = 0; ++ } ++ ++ template AGG_INLINE void add(const ArgT& v) ++ { ++ r += v.r; ++ g += v.g; ++ b += v.b; ++ } ++ ++ template AGG_INLINE void add(const ArgT& v, unsigned k) ++ { ++ r += v.r * k; ++ g += v.g * k; ++ b += v.b * k; ++ } ++ ++ template AGG_INLINE void sub(const ArgT& v) ++ { ++ r -= v.r; ++ g -= v.g; ++ b -= v.b; ++ } ++ ++ template AGG_INLINE void calc_pix(ArgT& v, unsigned div) ++ { ++ typedef typename ArgT::value_type value_type; ++ v.r = value_type(r / div); ++ v.g = value_type(g / div); ++ v.b = value_type(b / div); ++ } ++ ++ template ++ AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr) ++ { ++ typedef typename ArgT::value_type value_type; ++ v.r = value_type((r * mul) >> shr); ++ v.g = value_type((g * mul) >> shr); ++ v.b = value_type((b * mul) >> shr); ++ } ++ }; ++ ++ ++ //====================================================stack_blur_calc_gray ++ template struct stack_blur_calc_gray ++ { ++ typedef T value_type; ++ value_type v; ++ ++ AGG_INLINE void clear() ++ { ++ v = 0; ++ } ++ ++ template AGG_INLINE void add(const ArgT& a) ++ { ++ v += a.v; ++ } ++ ++ template AGG_INLINE void add(const ArgT& a, unsigned k) ++ { ++ v += a.v * k; ++ } ++ ++ template AGG_INLINE void sub(const ArgT& a) ++ { ++ v -= a.v; ++ } ++ ++ template AGG_INLINE void calc_pix(ArgT& a, unsigned div) ++ { ++ typedef typename ArgT::value_type value_type; ++ a.v = value_type(v / div); ++ } ++ ++ template ++ AGG_INLINE void calc_pix(ArgT& a, unsigned mul, unsigned shr) ++ { ++ typedef typename ArgT::value_type value_type; ++ a.v = value_type((v * mul) >> shr); ++ } ++ }; ++ ++ ++ ++ //========================================================stack_blur_gray8 ++ template ++ void stack_blur_gray8(Img& img, unsigned rx, unsigned ry) ++ { ++ unsigned x, y, xp, yp, i; ++ unsigned stack_ptr; ++ unsigned stack_start; ++ ++ const int8u* src_pix_ptr; ++ int8u* dst_pix_ptr; ++ unsigned pix; ++ unsigned stack_pix; ++ unsigned sum; ++ unsigned sum_in; ++ unsigned sum_out; ++ ++ unsigned w = img.width(); ++ unsigned h = img.height(); ++ unsigned wm = w - 1; ++ unsigned hm = h - 1; ++ ++ unsigned div; ++ unsigned mul_sum; ++ unsigned shr_sum; ++ ++ pod_vector stack; ++ ++ if(rx > 0) ++ { ++ if(rx > 254) rx = 254; ++ div = rx * 2 + 1; ++ mul_sum = stack_blur_tables::g_stack_blur8_mul[rx]; ++ shr_sum = stack_blur_tables::g_stack_blur8_shr[rx]; ++ stack.allocate(div); ++ ++ for(y = 0; y < h; y++) ++ { ++ sum = sum_in = sum_out = 0; ++ ++ src_pix_ptr = img.pix_ptr(0, y); ++ pix = *src_pix_ptr; ++ for(i = 0; i <= rx; i++) ++ { ++ stack[i] = pix; ++ sum += pix * (i + 1); ++ sum_out += pix; ++ } ++ for(i = 1; i <= rx; i++) ++ { ++ if(i <= wm) src_pix_ptr += Img::pix_step; ++ pix = *src_pix_ptr; ++ stack[i + rx] = pix; ++ sum += pix * (rx + 1 - i); ++ sum_in += pix; ++ } ++ ++ stack_ptr = rx; ++ xp = rx; ++ if(xp > wm) xp = wm; ++ src_pix_ptr = img.pix_ptr(xp, y); ++ dst_pix_ptr = img.pix_ptr(0, y); ++ for(x = 0; x < w; x++) ++ { ++ *dst_pix_ptr = (sum * mul_sum) >> shr_sum; ++ dst_pix_ptr += Img::pix_step; ++ ++ sum -= sum_out; ++ ++ stack_start = stack_ptr + div - rx; ++ if(stack_start >= div) stack_start -= div; ++ sum_out -= stack[stack_start]; ++ ++ if(xp < wm) ++ { ++ src_pix_ptr += Img::pix_step; ++ pix = *src_pix_ptr; ++ ++xp; ++ } ++ ++ stack[stack_start] = pix; ++ ++ sum_in += pix; ++ sum += sum_in; ++ ++ ++stack_ptr; ++ if(stack_ptr >= div) stack_ptr = 0; ++ stack_pix = stack[stack_ptr]; ++ ++ sum_out += stack_pix; ++ sum_in -= stack_pix; ++ } ++ } ++ } ++ ++ if(ry > 0) ++ { ++ if(ry > 254) ry = 254; ++ div = ry * 2 + 1; ++ mul_sum = stack_blur_tables::g_stack_blur8_mul[ry]; ++ shr_sum = stack_blur_tables::g_stack_blur8_shr[ry]; ++ stack.allocate(div); ++ ++ int stride = img.stride(); ++ for(x = 0; x < w; x++) ++ { ++ sum = sum_in = sum_out = 0; ++ ++ src_pix_ptr = img.pix_ptr(x, 0); ++ pix = *src_pix_ptr; ++ for(i = 0; i <= ry; i++) ++ { ++ stack[i] = pix; ++ sum += pix * (i + 1); ++ sum_out += pix; ++ } ++ for(i = 1; i <= ry; i++) ++ { ++ if(i <= hm) src_pix_ptr += stride; ++ pix = *src_pix_ptr; ++ stack[i + ry] = pix; ++ sum += pix * (ry + 1 - i); ++ sum_in += pix; ++ } ++ ++ stack_ptr = ry; ++ yp = ry; ++ if(yp > hm) yp = hm; ++ src_pix_ptr = img.pix_ptr(x, yp); ++ dst_pix_ptr = img.pix_ptr(x, 0); ++ for(y = 0; y < h; y++) ++ { ++ *dst_pix_ptr = (sum * mul_sum) >> shr_sum; ++ dst_pix_ptr += stride; ++ ++ sum -= sum_out; ++ ++ stack_start = stack_ptr + div - ry; ++ if(stack_start >= div) stack_start -= div; ++ sum_out -= stack[stack_start]; ++ ++ if(yp < hm) ++ { ++ src_pix_ptr += stride; ++ pix = *src_pix_ptr; ++ ++yp; ++ } ++ ++ stack[stack_start] = pix; ++ ++ sum_in += pix; ++ sum += sum_in; ++ ++ ++stack_ptr; ++ if(stack_ptr >= div) stack_ptr = 0; ++ stack_pix = stack[stack_ptr]; ++ ++ sum_out += stack_pix; ++ sum_in -= stack_pix; ++ } ++ } ++ } ++ } ++ ++ ++ ++ //========================================================stack_blur_rgb24 ++ template ++ void stack_blur_rgb24(Img& img, unsigned rx, unsigned ry) ++ { ++ typedef typename Img::color_type color_type; ++ typedef typename Img::order_type order_type; ++ enum order_e ++ { ++ R = order_type::R, ++ G = order_type::G, ++ B = order_type::B ++ }; ++ ++ unsigned x, y, xp, yp, i; ++ unsigned stack_ptr; ++ unsigned stack_start; ++ ++ const int8u* src_pix_ptr; ++ int8u* dst_pix_ptr; ++ color_type* stack_pix_ptr; ++ ++ unsigned sum_r; ++ unsigned sum_g; ++ unsigned sum_b; ++ unsigned sum_in_r; ++ unsigned sum_in_g; ++ unsigned sum_in_b; ++ unsigned sum_out_r; ++ unsigned sum_out_g; ++ unsigned sum_out_b; ++ ++ unsigned w = img.width(); ++ unsigned h = img.height(); ++ unsigned wm = w - 1; ++ unsigned hm = h - 1; ++ ++ unsigned div; ++ unsigned mul_sum; ++ unsigned shr_sum; ++ ++ pod_vector stack; ++ ++ if(rx > 0) ++ { ++ if(rx > 254) rx = 254; ++ div = rx * 2 + 1; ++ mul_sum = stack_blur_tables::g_stack_blur8_mul[rx]; ++ shr_sum = stack_blur_tables::g_stack_blur8_shr[rx]; ++ stack.allocate(div); ++ ++ for(y = 0; y < h; y++) ++ { ++ sum_r = ++ sum_g = ++ sum_b = ++ sum_in_r = ++ sum_in_g = ++ sum_in_b = ++ sum_out_r = ++ sum_out_g = ++ sum_out_b = 0; ++ ++ src_pix_ptr = img.pix_ptr(0, y); ++ for(i = 0; i <= rx; i++) ++ { ++ stack_pix_ptr = &stack[i]; ++ stack_pix_ptr->r = src_pix_ptr[R]; ++ stack_pix_ptr->g = src_pix_ptr[G]; ++ stack_pix_ptr->b = src_pix_ptr[B]; ++ sum_r += src_pix_ptr[R] * (i + 1); ++ sum_g += src_pix_ptr[G] * (i + 1); ++ sum_b += src_pix_ptr[B] * (i + 1); ++ sum_out_r += src_pix_ptr[R]; ++ sum_out_g += src_pix_ptr[G]; ++ sum_out_b += src_pix_ptr[B]; ++ } ++ for(i = 1; i <= rx; i++) ++ { ++ if(i <= wm) src_pix_ptr += Img::pix_width; ++ stack_pix_ptr = &stack[i + rx]; ++ stack_pix_ptr->r = src_pix_ptr[R]; ++ stack_pix_ptr->g = src_pix_ptr[G]; ++ stack_pix_ptr->b = src_pix_ptr[B]; ++ sum_r += src_pix_ptr[R] * (rx + 1 - i); ++ sum_g += src_pix_ptr[G] * (rx + 1 - i); ++ sum_b += src_pix_ptr[B] * (rx + 1 - i); ++ sum_in_r += src_pix_ptr[R]; ++ sum_in_g += src_pix_ptr[G]; ++ sum_in_b += src_pix_ptr[B]; ++ } ++ ++ stack_ptr = rx; ++ xp = rx; ++ if(xp > wm) xp = wm; ++ src_pix_ptr = img.pix_ptr(xp, y); ++ dst_pix_ptr = img.pix_ptr(0, y); ++ for(x = 0; x < w; x++) ++ { ++ dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; ++ dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; ++ dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; ++ dst_pix_ptr += Img::pix_width; ++ ++ sum_r -= sum_out_r; ++ sum_g -= sum_out_g; ++ sum_b -= sum_out_b; ++ ++ stack_start = stack_ptr + div - rx; ++ if(stack_start >= div) stack_start -= div; ++ stack_pix_ptr = &stack[stack_start]; ++ ++ sum_out_r -= stack_pix_ptr->r; ++ sum_out_g -= stack_pix_ptr->g; ++ sum_out_b -= stack_pix_ptr->b; ++ ++ if(xp < wm) ++ { ++ src_pix_ptr += Img::pix_width; ++ ++xp; ++ } ++ ++ stack_pix_ptr->r = src_pix_ptr[R]; ++ stack_pix_ptr->g = src_pix_ptr[G]; ++ stack_pix_ptr->b = src_pix_ptr[B]; ++ ++ sum_in_r += src_pix_ptr[R]; ++ sum_in_g += src_pix_ptr[G]; ++ sum_in_b += src_pix_ptr[B]; ++ sum_r += sum_in_r; ++ sum_g += sum_in_g; ++ sum_b += sum_in_b; ++ ++ ++stack_ptr; ++ if(stack_ptr >= div) stack_ptr = 0; ++ stack_pix_ptr = &stack[stack_ptr]; ++ ++ sum_out_r += stack_pix_ptr->r; ++ sum_out_g += stack_pix_ptr->g; ++ sum_out_b += stack_pix_ptr->b; ++ sum_in_r -= stack_pix_ptr->r; ++ sum_in_g -= stack_pix_ptr->g; ++ sum_in_b -= stack_pix_ptr->b; ++ } ++ } ++ } ++ ++ if(ry > 0) ++ { ++ if(ry > 254) ry = 254; ++ div = ry * 2 + 1; ++ mul_sum = stack_blur_tables::g_stack_blur8_mul[ry]; ++ shr_sum = stack_blur_tables::g_stack_blur8_shr[ry]; ++ stack.allocate(div); ++ ++ int stride = img.stride(); ++ for(x = 0; x < w; x++) ++ { ++ sum_r = ++ sum_g = ++ sum_b = ++ sum_in_r = ++ sum_in_g = ++ sum_in_b = ++ sum_out_r = ++ sum_out_g = ++ sum_out_b = 0; ++ ++ src_pix_ptr = img.pix_ptr(x, 0); ++ for(i = 0; i <= ry; i++) ++ { ++ stack_pix_ptr = &stack[i]; ++ stack_pix_ptr->r = src_pix_ptr[R]; ++ stack_pix_ptr->g = src_pix_ptr[G]; ++ stack_pix_ptr->b = src_pix_ptr[B]; ++ sum_r += src_pix_ptr[R] * (i + 1); ++ sum_g += src_pix_ptr[G] * (i + 1); ++ sum_b += src_pix_ptr[B] * (i + 1); ++ sum_out_r += src_pix_ptr[R]; ++ sum_out_g += src_pix_ptr[G]; ++ sum_out_b += src_pix_ptr[B]; ++ } ++ for(i = 1; i <= ry; i++) ++ { ++ if(i <= hm) src_pix_ptr += stride; ++ stack_pix_ptr = &stack[i + ry]; ++ stack_pix_ptr->r = src_pix_ptr[R]; ++ stack_pix_ptr->g = src_pix_ptr[G]; ++ stack_pix_ptr->b = src_pix_ptr[B]; ++ sum_r += src_pix_ptr[R] * (ry + 1 - i); ++ sum_g += src_pix_ptr[G] * (ry + 1 - i); ++ sum_b += src_pix_ptr[B] * (ry + 1 - i); ++ sum_in_r += src_pix_ptr[R]; ++ sum_in_g += src_pix_ptr[G]; ++ sum_in_b += src_pix_ptr[B]; ++ } ++ ++ stack_ptr = ry; ++ yp = ry; ++ if(yp > hm) yp = hm; ++ src_pix_ptr = img.pix_ptr(x, yp); ++ dst_pix_ptr = img.pix_ptr(x, 0); ++ for(y = 0; y < h; y++) ++ { ++ dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; ++ dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; ++ dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; ++ dst_pix_ptr += stride; ++ ++ sum_r -= sum_out_r; ++ sum_g -= sum_out_g; ++ sum_b -= sum_out_b; ++ ++ stack_start = stack_ptr + div - ry; ++ if(stack_start >= div) stack_start -= div; ++ ++ stack_pix_ptr = &stack[stack_start]; ++ sum_out_r -= stack_pix_ptr->r; ++ sum_out_g -= stack_pix_ptr->g; ++ sum_out_b -= stack_pix_ptr->b; ++ ++ if(yp < hm) ++ { ++ src_pix_ptr += stride; ++ ++yp; ++ } ++ ++ stack_pix_ptr->r = src_pix_ptr[R]; ++ stack_pix_ptr->g = src_pix_ptr[G]; ++ stack_pix_ptr->b = src_pix_ptr[B]; ++ ++ sum_in_r += src_pix_ptr[R]; ++ sum_in_g += src_pix_ptr[G]; ++ sum_in_b += src_pix_ptr[B]; ++ sum_r += sum_in_r; ++ sum_g += sum_in_g; ++ sum_b += sum_in_b; ++ ++ ++stack_ptr; ++ if(stack_ptr >= div) stack_ptr = 0; ++ stack_pix_ptr = &stack[stack_ptr]; ++ ++ sum_out_r += stack_pix_ptr->r; ++ sum_out_g += stack_pix_ptr->g; ++ sum_out_b += stack_pix_ptr->b; ++ sum_in_r -= stack_pix_ptr->r; ++ sum_in_g -= stack_pix_ptr->g; ++ sum_in_b -= stack_pix_ptr->b; ++ } ++ } ++ } ++ } ++ ++ ++ ++ //=======================================================stack_blur_rgba32 ++ template ++ void stack_blur_rgba32(Img& img, unsigned rx, unsigned ry) ++ { ++ typedef typename Img::color_type color_type; ++ typedef typename Img::order_type order_type; ++ enum order_e ++ { ++ R = order_type::R, ++ G = order_type::G, ++ B = order_type::B, ++ A = order_type::A ++ }; ++ ++ unsigned x, y, xp, yp, i; ++ unsigned stack_ptr; ++ unsigned stack_start; ++ ++ const int8u* src_pix_ptr; ++ int8u* dst_pix_ptr; ++ color_type* stack_pix_ptr; ++ ++ unsigned sum_r; ++ unsigned sum_g; ++ unsigned sum_b; ++ unsigned sum_a; ++ unsigned sum_in_r; ++ unsigned sum_in_g; ++ unsigned sum_in_b; ++ unsigned sum_in_a; ++ unsigned sum_out_r; ++ unsigned sum_out_g; ++ unsigned sum_out_b; ++ unsigned sum_out_a; ++ ++ unsigned w = img.width(); ++ unsigned h = img.height(); ++ unsigned wm = w - 1; ++ unsigned hm = h - 1; ++ ++ unsigned div; ++ unsigned mul_sum; ++ unsigned shr_sum; ++ ++ pod_vector stack; ++ ++ if(rx > 0) ++ { ++ if(rx > 254) rx = 254; ++ div = rx * 2 + 1; ++ mul_sum = stack_blur_tables::g_stack_blur8_mul[rx]; ++ shr_sum = stack_blur_tables::g_stack_blur8_shr[rx]; ++ stack.allocate(div); ++ ++ for(y = 0; y < h; y++) ++ { ++ sum_r = ++ sum_g = ++ sum_b = ++ sum_a = ++ sum_in_r = ++ sum_in_g = ++ sum_in_b = ++ sum_in_a = ++ sum_out_r = ++ sum_out_g = ++ sum_out_b = ++ sum_out_a = 0; ++ ++ src_pix_ptr = img.pix_ptr(0, y); ++ for(i = 0; i <= rx; i++) ++ { ++ stack_pix_ptr = &stack[i]; ++ stack_pix_ptr->r = src_pix_ptr[R]; ++ stack_pix_ptr->g = src_pix_ptr[G]; ++ stack_pix_ptr->b = src_pix_ptr[B]; ++ stack_pix_ptr->a = src_pix_ptr[A]; ++ sum_r += src_pix_ptr[R] * (i + 1); ++ sum_g += src_pix_ptr[G] * (i + 1); ++ sum_b += src_pix_ptr[B] * (i + 1); ++ sum_a += src_pix_ptr[A] * (i + 1); ++ sum_out_r += src_pix_ptr[R]; ++ sum_out_g += src_pix_ptr[G]; ++ sum_out_b += src_pix_ptr[B]; ++ sum_out_a += src_pix_ptr[A]; ++ } ++ for(i = 1; i <= rx; i++) ++ { ++ if(i <= wm) src_pix_ptr += Img::pix_width; ++ stack_pix_ptr = &stack[i + rx]; ++ stack_pix_ptr->r = src_pix_ptr[R]; ++ stack_pix_ptr->g = src_pix_ptr[G]; ++ stack_pix_ptr->b = src_pix_ptr[B]; ++ stack_pix_ptr->a = src_pix_ptr[A]; ++ sum_r += src_pix_ptr[R] * (rx + 1 - i); ++ sum_g += src_pix_ptr[G] * (rx + 1 - i); ++ sum_b += src_pix_ptr[B] * (rx + 1 - i); ++ sum_a += src_pix_ptr[A] * (rx + 1 - i); ++ sum_in_r += src_pix_ptr[R]; ++ sum_in_g += src_pix_ptr[G]; ++ sum_in_b += src_pix_ptr[B]; ++ sum_in_a += src_pix_ptr[A]; ++ } ++ ++ stack_ptr = rx; ++ xp = rx; ++ if(xp > wm) xp = wm; ++ src_pix_ptr = img.pix_ptr(xp, y); ++ dst_pix_ptr = img.pix_ptr(0, y); ++ for(x = 0; x < w; x++) ++ { ++ dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; ++ dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; ++ dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; ++ dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum; ++ dst_pix_ptr += Img::pix_width; ++ ++ sum_r -= sum_out_r; ++ sum_g -= sum_out_g; ++ sum_b -= sum_out_b; ++ sum_a -= sum_out_a; ++ ++ stack_start = stack_ptr + div - rx; ++ if(stack_start >= div) stack_start -= div; ++ stack_pix_ptr = &stack[stack_start]; ++ ++ sum_out_r -= stack_pix_ptr->r; ++ sum_out_g -= stack_pix_ptr->g; ++ sum_out_b -= stack_pix_ptr->b; ++ sum_out_a -= stack_pix_ptr->a; ++ ++ if(xp < wm) ++ { ++ src_pix_ptr += Img::pix_width; ++ ++xp; ++ } ++ ++ stack_pix_ptr->r = src_pix_ptr[R]; ++ stack_pix_ptr->g = src_pix_ptr[G]; ++ stack_pix_ptr->b = src_pix_ptr[B]; ++ stack_pix_ptr->a = src_pix_ptr[A]; ++ ++ sum_in_r += src_pix_ptr[R]; ++ sum_in_g += src_pix_ptr[G]; ++ sum_in_b += src_pix_ptr[B]; ++ sum_in_a += src_pix_ptr[A]; ++ sum_r += sum_in_r; ++ sum_g += sum_in_g; ++ sum_b += sum_in_b; ++ sum_a += sum_in_a; ++ ++ ++stack_ptr; ++ if(stack_ptr >= div) stack_ptr = 0; ++ stack_pix_ptr = &stack[stack_ptr]; ++ ++ sum_out_r += stack_pix_ptr->r; ++ sum_out_g += stack_pix_ptr->g; ++ sum_out_b += stack_pix_ptr->b; ++ sum_out_a += stack_pix_ptr->a; ++ sum_in_r -= stack_pix_ptr->r; ++ sum_in_g -= stack_pix_ptr->g; ++ sum_in_b -= stack_pix_ptr->b; ++ sum_in_a -= stack_pix_ptr->a; ++ } ++ } ++ } ++ ++ if(ry > 0) ++ { ++ if(ry > 254) ry = 254; ++ div = ry * 2 + 1; ++ mul_sum = stack_blur_tables::g_stack_blur8_mul[ry]; ++ shr_sum = stack_blur_tables::g_stack_blur8_shr[ry]; ++ stack.allocate(div); ++ ++ int stride = img.stride(); ++ for(x = 0; x < w; x++) ++ { ++ sum_r = ++ sum_g = ++ sum_b = ++ sum_a = ++ sum_in_r = ++ sum_in_g = ++ sum_in_b = ++ sum_in_a = ++ sum_out_r = ++ sum_out_g = ++ sum_out_b = ++ sum_out_a = 0; ++ ++ src_pix_ptr = img.pix_ptr(x, 0); ++ for(i = 0; i <= ry; i++) ++ { ++ stack_pix_ptr = &stack[i]; ++ stack_pix_ptr->r = src_pix_ptr[R]; ++ stack_pix_ptr->g = src_pix_ptr[G]; ++ stack_pix_ptr->b = src_pix_ptr[B]; ++ stack_pix_ptr->a = src_pix_ptr[A]; ++ sum_r += src_pix_ptr[R] * (i + 1); ++ sum_g += src_pix_ptr[G] * (i + 1); ++ sum_b += src_pix_ptr[B] * (i + 1); ++ sum_a += src_pix_ptr[A] * (i + 1); ++ sum_out_r += src_pix_ptr[R]; ++ sum_out_g += src_pix_ptr[G]; ++ sum_out_b += src_pix_ptr[B]; ++ sum_out_a += src_pix_ptr[A]; ++ } ++ for(i = 1; i <= ry; i++) ++ { ++ if(i <= hm) src_pix_ptr += stride; ++ stack_pix_ptr = &stack[i + ry]; ++ stack_pix_ptr->r = src_pix_ptr[R]; ++ stack_pix_ptr->g = src_pix_ptr[G]; ++ stack_pix_ptr->b = src_pix_ptr[B]; ++ stack_pix_ptr->a = src_pix_ptr[A]; ++ sum_r += src_pix_ptr[R] * (ry + 1 - i); ++ sum_g += src_pix_ptr[G] * (ry + 1 - i); ++ sum_b += src_pix_ptr[B] * (ry + 1 - i); ++ sum_a += src_pix_ptr[A] * (ry + 1 - i); ++ sum_in_r += src_pix_ptr[R]; ++ sum_in_g += src_pix_ptr[G]; ++ sum_in_b += src_pix_ptr[B]; ++ sum_in_a += src_pix_ptr[A]; ++ } ++ ++ stack_ptr = ry; ++ yp = ry; ++ if(yp > hm) yp = hm; ++ src_pix_ptr = img.pix_ptr(x, yp); ++ dst_pix_ptr = img.pix_ptr(x, 0); ++ for(y = 0; y < h; y++) ++ { ++ dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; ++ dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; ++ dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; ++ dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum; ++ dst_pix_ptr += stride; ++ ++ sum_r -= sum_out_r; ++ sum_g -= sum_out_g; ++ sum_b -= sum_out_b; ++ sum_a -= sum_out_a; ++ ++ stack_start = stack_ptr + div - ry; ++ if(stack_start >= div) stack_start -= div; ++ ++ stack_pix_ptr = &stack[stack_start]; ++ sum_out_r -= stack_pix_ptr->r; ++ sum_out_g -= stack_pix_ptr->g; ++ sum_out_b -= stack_pix_ptr->b; ++ sum_out_a -= stack_pix_ptr->a; ++ ++ if(yp < hm) ++ { ++ src_pix_ptr += stride; ++ ++yp; ++ } ++ ++ stack_pix_ptr->r = src_pix_ptr[R]; ++ stack_pix_ptr->g = src_pix_ptr[G]; ++ stack_pix_ptr->b = src_pix_ptr[B]; ++ stack_pix_ptr->a = src_pix_ptr[A]; ++ ++ sum_in_r += src_pix_ptr[R]; ++ sum_in_g += src_pix_ptr[G]; ++ sum_in_b += src_pix_ptr[B]; ++ sum_in_a += src_pix_ptr[A]; ++ sum_r += sum_in_r; ++ sum_g += sum_in_g; ++ sum_b += sum_in_b; ++ sum_a += sum_in_a; ++ ++ ++stack_ptr; ++ if(stack_ptr >= div) stack_ptr = 0; ++ stack_pix_ptr = &stack[stack_ptr]; ++ ++ sum_out_r += stack_pix_ptr->r; ++ sum_out_g += stack_pix_ptr->g; ++ sum_out_b += stack_pix_ptr->b; ++ sum_out_a += stack_pix_ptr->a; ++ sum_in_r -= stack_pix_ptr->r; ++ sum_in_g -= stack_pix_ptr->g; ++ sum_in_b -= stack_pix_ptr->b; ++ sum_in_a -= stack_pix_ptr->a; ++ } ++ } ++ } ++ } ++ ++ ++ ++ //===========================================================recursive_blur ++ template class recursive_blur ++ { ++ public: ++ typedef ColorT color_type; ++ typedef CalculatorT calculator_type; ++ typedef typename color_type::value_type value_type; ++ typedef typename calculator_type::value_type calc_type; ++ ++ //-------------------------------------------------------------------- ++ template void blur_x(Img& img, double radius) ++ { ++ if(radius < 0.62) return; ++ if(img.width() < 3) return; ++ ++ calc_type s = calc_type(radius * 0.5); ++ calc_type q = calc_type((s < 2.5) ? ++ 3.97156 - 4.14554 * sqrt(1 - 0.26891 * s) : ++ 0.98711 * s - 0.96330); ++ ++ calc_type q2 = calc_type(q * q); ++ calc_type q3 = calc_type(q2 * q); ++ ++ calc_type b0 = calc_type(1.0 / (1.578250 + ++ 2.444130 * q + ++ 1.428100 * q2 + ++ 0.422205 * q3)); ++ ++ calc_type b1 = calc_type( 2.44413 * q + ++ 2.85619 * q2 + ++ 1.26661 * q3); ++ ++ calc_type b2 = calc_type(-1.42810 * q2 + ++ -1.26661 * q3); ++ ++ calc_type b3 = calc_type(0.422205 * q3); ++ ++ calc_type b = calc_type(1 - (b1 + b2 + b3) * b0); ++ ++ b1 *= b0; ++ b2 *= b0; ++ b3 *= b0; ++ ++ int w = img.width(); ++ int h = img.height(); ++ int wm = w-1; ++ int x, y; ++ ++ m_sum1.allocate(w); ++ m_sum2.allocate(w); ++ m_buf.allocate(w); ++ ++ for(y = 0; y < h; y++) ++ { ++ calculator_type c; ++ c.from_pix(img.pixel(0, y)); ++ m_sum1[0].calc(b, b1, b2, b3, c, c, c, c); ++ c.from_pix(img.pixel(1, y)); ++ m_sum1[1].calc(b, b1, b2, b3, c, m_sum1[0], m_sum1[0], m_sum1[0]); ++ c.from_pix(img.pixel(2, y)); ++ m_sum1[2].calc(b, b1, b2, b3, c, m_sum1[1], m_sum1[0], m_sum1[0]); ++ ++ for(x = 3; x < w; ++x) ++ { ++ c.from_pix(img.pixel(x, y)); ++ m_sum1[x].calc(b, b1, b2, b3, c, m_sum1[x-1], m_sum1[x-2], m_sum1[x-3]); ++ } ++ ++ m_sum2[wm ].calc(b, b1, b2, b3, m_sum1[wm ], m_sum1[wm ], m_sum1[wm], m_sum1[wm]); ++ m_sum2[wm-1].calc(b, b1, b2, b3, m_sum1[wm-1], m_sum2[wm ], m_sum2[wm], m_sum2[wm]); ++ m_sum2[wm-2].calc(b, b1, b2, b3, m_sum1[wm-2], m_sum2[wm-1], m_sum2[wm], m_sum2[wm]); ++ m_sum2[wm ].to_pix(m_buf[wm ]); ++ m_sum2[wm-1].to_pix(m_buf[wm-1]); ++ m_sum2[wm-2].to_pix(m_buf[wm-2]); ++ ++ for(x = wm-3; x >= 0; --x) ++ { ++ m_sum2[x].calc(b, b1, b2, b3, m_sum1[x], m_sum2[x+1], m_sum2[x+2], m_sum2[x+3]); ++ m_sum2[x].to_pix(m_buf[x]); ++ } ++ img.copy_color_hspan(0, y, w, &m_buf[0]); ++ } ++ } ++ ++ //-------------------------------------------------------------------- ++ template void blur_y(Img& img, double radius) ++ { ++ pixfmt_transposer img2(img); ++ blur_x(img2, radius); ++ } ++ ++ //-------------------------------------------------------------------- ++ template void blur(Img& img, double radius) ++ { ++ blur_x(img, radius); ++ pixfmt_transposer img2(img); ++ blur_x(img2, radius); ++ } ++ ++ private: ++ agg::pod_vector m_sum1; ++ agg::pod_vector m_sum2; ++ agg::pod_vector m_buf; ++ }; ++ ++ ++ //=================================================recursive_blur_calc_rgba ++ template struct recursive_blur_calc_rgba ++ { ++ typedef T value_type; ++ typedef recursive_blur_calc_rgba self_type; ++ ++ value_type r,g,b,a; ++ ++ template ++ AGG_INLINE void from_pix(const ColorT& c) ++ { ++ r = c.r; ++ g = c.g; ++ b = c.b; ++ a = c.a; ++ } ++ ++ AGG_INLINE void calc(value_type b1, ++ value_type b2, ++ value_type b3, ++ value_type b4, ++ const self_type& c1, ++ const self_type& c2, ++ const self_type& c3, ++ const self_type& c4) ++ { ++ r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r; ++ g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g; ++ b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b; ++ a = b1*c1.a + b2*c2.a + b3*c3.a + b4*c4.a; ++ } ++ ++ template ++ AGG_INLINE void to_pix(ColorT& c) const ++ { ++ typedef typename ColorT::value_type cv_type; ++ c.r = (cv_type)uround(r); ++ c.g = (cv_type)uround(g); ++ c.b = (cv_type)uround(b); ++ c.a = (cv_type)uround(a); ++ } ++ }; ++ ++ ++ //=================================================recursive_blur_calc_rgb ++ template struct recursive_blur_calc_rgb ++ { ++ typedef T value_type; ++ typedef recursive_blur_calc_rgb self_type; ++ ++ value_type r,g,b; ++ ++ template ++ AGG_INLINE void from_pix(const ColorT& c) ++ { ++ r = c.r; ++ g = c.g; ++ b = c.b; ++ } ++ ++ AGG_INLINE void calc(value_type b1, ++ value_type b2, ++ value_type b3, ++ value_type b4, ++ const self_type& c1, ++ const self_type& c2, ++ const self_type& c3, ++ const self_type& c4) ++ { ++ r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r; ++ g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g; ++ b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b; ++ } ++ ++ template ++ AGG_INLINE void to_pix(ColorT& c) const ++ { ++ typedef typename ColorT::value_type cv_type; ++ c.r = (cv_type)uround(r); ++ c.g = (cv_type)uround(g); ++ c.b = (cv_type)uround(b); ++ } ++ }; ++ ++ ++ //================================================recursive_blur_calc_gray ++ template struct recursive_blur_calc_gray ++ { ++ typedef T value_type; ++ typedef recursive_blur_calc_gray self_type; ++ ++ value_type v; ++ ++ template ++ AGG_INLINE void from_pix(const ColorT& c) ++ { ++ v = c.v; ++ } ++ ++ AGG_INLINE void calc(value_type b1, ++ value_type b2, ++ value_type b3, ++ value_type b4, ++ const self_type& c1, ++ const self_type& c2, ++ const self_type& c3, ++ const self_type& c4) ++ { ++ v = b1*c1.v + b2*c2.v + b3*c3.v + b4*c4.v; ++ } ++ ++ template ++ AGG_INLINE void to_pix(ColorT& c) const ++ { ++ typedef typename ColorT::value_type cv_type; ++ c.v = (cv_type)uround(v); ++ } ++ }; ++ ++} ++ ++ ++ ++ ++#endif +diff --git a/src/third_party/agg/include/agg_bspline.h b/src/third_party/agg/include/agg_bspline.h +index 19a153f..2c1ed9a 100644 +--- a/src/third_party/agg/include/agg_bspline.h ++++ b/src/third_party/agg/include/agg_bspline.h +@@ -20,7 +20,7 @@ + #ifndef AGG_BSPLINE_INCLUDED + #define AGG_BSPLINE_INCLUDED + +-#include "agg_basics.h" ++#include "agg_array.h" + + namespace agg + { +@@ -40,7 +40,6 @@ namespace agg + class bspline + { + public: +- ~bspline(); + bspline(); + bspline(int num); + bspline(int num, const double* x, const double* y); +@@ -63,12 +62,12 @@ namespace agg + double extrapolation_right(double x) const; + double interpolation(double x, int i) const; + +- int m_max; +- int m_num; +- double* m_x; +- double* m_y; +- double* m_am; +- mutable int m_last_idx; ++ int m_max; ++ int m_num; ++ double* m_x; ++ double* m_y; ++ pod_array m_am; ++ mutable int m_last_idx; + }; + + +diff --git a/src/third_party/agg/include/agg_color_gray.h b/src/third_party/agg/include/agg_color_gray.h +index 0fb11cc..5fa44ce 100644 +--- a/src/third_party/agg/include/agg_color_gray.h ++++ b/src/third_party/agg/include/agg_color_gray.h +@@ -55,7 +55,7 @@ namespace agg + gray8() {} + + //-------------------------------------------------------------------- +- gray8(unsigned v_, unsigned a_=base_mask) : ++ explicit gray8(unsigned v_, unsigned a_=base_mask) : + v(int8u(v_)), a(int8u(a_)) {} + + //-------------------------------------------------------------------- +@@ -162,6 +162,31 @@ namespace agg + return ret; + } + ++ //-------------------------------------------------------------------- ++ AGG_INLINE void add(const self_type& c, unsigned cover) ++ { ++ calc_type cv, ca; ++ if(cover == cover_mask) ++ { ++ if(c.a == base_mask) ++ { ++ *this = c; ++ } ++ else ++ { ++ cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; ++ ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; ++ } ++ } ++ else ++ { ++ cv = v + ((c.v * cover + cover_mask/2) >> cover_shift); ++ ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); ++ v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; ++ a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; ++ } ++ } ++ + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0); } + }; +@@ -217,7 +242,7 @@ namespace agg + gray16() {} + + //-------------------------------------------------------------------- +- gray16(unsigned v_, unsigned a_=base_mask) : ++ explicit gray16(unsigned v_, unsigned a_=base_mask) : + v(int16u(v_)), a(int16u(a_)) {} + + //-------------------------------------------------------------------- +@@ -324,6 +349,31 @@ namespace agg + return ret; + } + ++ //-------------------------------------------------------------------- ++ AGG_INLINE void add(const self_type& c, unsigned cover) ++ { ++ calc_type cv, ca; ++ if(cover == cover_mask) ++ { ++ if(c.a == base_mask) ++ { ++ *this = c; ++ } ++ else ++ { ++ cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; ++ ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; ++ } ++ } ++ else ++ { ++ cv = v + ((c.v * cover + cover_mask/2) >> cover_shift); ++ ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); ++ v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; ++ a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; ++ } ++ } ++ + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0); } + }; +diff --git a/src/third_party/agg/include/agg_conv_adaptor_vcgen.h b/src/third_party/agg/include/agg_conv_adaptor_vcgen.h +index 45811e6..cee24b2 100644 +--- a/src/third_party/agg/include/agg_conv_adaptor_vcgen.h ++++ b/src/third_party/agg/include/agg_conv_adaptor_vcgen.h +@@ -49,8 +49,7 @@ namespace agg + m_source(&source), + m_status(initial) + {} +- +- void set_source(VertexSource& source) { m_source = &source; } ++ void attach(VertexSource& source) { m_source = &source; } + + Generator& generator() { return m_generator; } + const Generator& generator() const { return m_generator; } +diff --git a/src/third_party/agg/include/agg_conv_adaptor_vpgen.h b/src/third_party/agg/include/agg_conv_adaptor_vpgen.h +index 37d9730..8fcedcb 100644 +--- a/src/third_party/agg/include/agg_conv_adaptor_vpgen.h ++++ b/src/third_party/agg/include/agg_conv_adaptor_vpgen.h +@@ -26,8 +26,7 @@ namespace agg + { + public: + conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {} +- +- void set_source(VertexSource& source) { m_source = &source; } ++ void attach(VertexSource& source) { m_source = &source; } + + VPGen& vpgen() { return m_vpgen; } + const VPGen& vpgen() const { return m_vpgen; } +diff --git a/src/third_party/agg/include/agg_conv_close_polygon.h b/src/third_party/agg/include/agg_conv_close_polygon.h +index d8f054c..7eecc9c 100644 +--- a/src/third_party/agg/include/agg_conv_close_polygon.h ++++ b/src/third_party/agg/include/agg_conv_close_polygon.h +@@ -26,8 +26,7 @@ namespace agg + { + public: + conv_close_polygon(VertexSource& vs) : m_source(&vs) {} +- +- void set_source(VertexSource& source) { m_source = &source; } ++ void attach(VertexSource& source) { m_source = &source; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); +diff --git a/src/third_party/agg/include/agg_conv_concat.h b/src/third_party/agg/include/agg_conv_concat.h +index fd243b4..745d349 100644 +--- a/src/third_party/agg/include/agg_conv_concat.h ++++ b/src/third_party/agg/include/agg_conv_concat.h +@@ -28,9 +28,8 @@ namespace agg + public: + conv_concat(VS1& source1, VS2& source2) : + m_source1(&source1), m_source2(&source2), m_status(2) {} +- +- void set_source1(VS1& source) { m_source1 = &source; } +- void set_source2(VS2& source) { m_source2 = &source; } ++ void attach1(VS1& source) { m_source1 = &source; } ++ void attach2(VS2& source) { m_source2 = &source; } + + + void rewind(unsigned path_id) +diff --git a/src/third_party/agg/include/agg_conv_curve.h b/src/third_party/agg/include/agg_conv_curve.h +index 5308b1a..bc28691 100644 +--- a/src/third_party/agg/include/agg_conv_curve.h ++++ b/src/third_party/agg/include/agg_conv_curve.h +@@ -23,6 +23,9 @@ + #include "agg_basics.h" + #include "agg_curves.h" + ++#include ++ ++ + namespace agg + { + +@@ -62,8 +65,7 @@ namespace agg + + conv_curve(VertexSource& source) : + m_source(&source), m_last_x(0.0), m_last_y(0.0) {} +- +- void set_source(VertexSource& source) { m_source = &source; } ++ void attach(VertexSource& source) { m_source = &source; } + + void approximation_method(curve_approximation_method_e v) + { +@@ -155,30 +157,26 @@ namespace agg + return path_cmd_line_to; + } + +- double ct2_x; +- double ct2_y; +- double end_x; +- double end_y; ++ 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); ++ if (!std::isnan(m_last_x) && !std::isnan(m_last_y) && !std::isnan(*x) ++ && !std::isnan(*y) && !std::isnan(end_x) && !std::isnan(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 ++ 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; + +@@ -186,16 +184,21 @@ namespace agg + 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); ++ if (!std::isnan(m_last_x) && !std::isnan(m_last_y) && !std::isnan(*x) ++ && !std::isnan(*y) && !std::isnan(end_x) && !std::isnan(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 ++ 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; + } ++ m_last_x = *x; ++ m_last_y = *y; + return cmd; + } + +diff --git a/src/third_party/agg/include/agg_conv_gpc.h b/src/third_party/agg/include/agg_conv_gpc.h +deleted file mode 100644 +index 7d4d65d..0000000 +--- a/src/third_party/agg/include/agg_conv_gpc.h ++++ /dev/null +@@ -1,437 +0,0 @@ +-//---------------------------------------------------------------------------- +-// Anti-Grain Geometry - Version 2.4 +-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +-// +-// Permission to copy, use, modify, sell and distribute this software +-// is granted provided this copyright notice appears in all copies. +-// This software is provided "as is" without express or implied +-// warranty, and with no claim as to its suitability for any purpose. +-// +-//---------------------------------------------------------------------------- +-// Contact: mcseem@antigrain.com +-// mcseemagg@yahoo.com +-// http://www.antigrain.com +-//---------------------------------------------------------------------------- +-// +-// 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 +-#include "agg_basics.h" +-#include "agg_array.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 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_bvector vertex_array_type; +- typedef pod_bvector contour_header_array_type; +- +- +- public: +- typedef VSA source_a_type; +- typedef VSB source_b_type; +- typedef conv_gpc 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 path_id); +- unsigned vertex(double* x, double* y); +- +- private: +- conv_gpc(const conv_gpc&); +- const conv_gpc& operator = (const conv_gpc&); +- +- //-------------------------------------------------------------------- +- 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 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 +- void conv_gpc::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 +- void conv_gpc::free_result() +- { +- if(m_result.contour) +- { +- gpc_free_polygon(&m_result); +- } +- memset(&m_result, 0, sizeof(m_result)); +- } +- +- +- //------------------------------------------------------------------------ +- template +- void conv_gpc::free_gpc_data() +- { +- free_polygon(m_poly_a); +- free_polygon(m_poly_b); +- free_result(); +- } +- +- +- //------------------------------------------------------------------------ +- template +- void conv_gpc::start_contour() +- { +- contour_header_type h; +- memset(&h, 0, sizeof(h)); +- m_contour_accumulator.add(h); +- m_vertex_accumulator.remove_all(); +- } +- +- +- //------------------------------------------------------------------------ +- template +- inline void conv_gpc::add_vertex(double x, double y) +- { +- gpc_vertex v; +- v.x = x; +- v.y = y; +- m_vertex_accumulator.add(v); +- } +- +- +- //------------------------------------------------------------------------ +- template +- void conv_gpc::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 +- void conv_gpc::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 +- void conv_gpc::start_extracting() +- { +- m_status = status_move_to; +- m_contour = -1; +- m_vertex = -1; +- } +- +- +- //------------------------------------------------------------------------ +- template +- bool conv_gpc::next_contour() +- { +- if(++m_contour < m_result.num_contours) +- { +- m_vertex = -1; +- return true; +- } +- return false; +- } +- +- +- //------------------------------------------------------------------------ +- template +- inline bool conv_gpc::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 +- void conv_gpc::rewind(unsigned path_id) +- { +- free_result(); +- m_src_a->rewind(path_id); +- m_src_b->rewind(path_id); +- add(*m_src_a, m_poly_a); +- add(*m_src_b, m_poly_b); +- switch(m_operation) +- { +- 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 +- unsigned conv_gpc::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/src/third_party/agg/include/agg_conv_transform.h b/src/third_party/agg/include/agg_conv_transform.h +index 1203e6c..1710877 100644 +--- a/src/third_party/agg/include/agg_conv_transform.h ++++ b/src/third_party/agg/include/agg_conv_transform.h +@@ -31,8 +31,7 @@ namespace agg + public: + conv_transform(VertexSource& source, const Transformer& tr) : + m_source(&source), m_trans(&tr) {} +- +- void set_source(VertexSource& source) { m_source = &source; } ++ void attach(VertexSource& source) { m_source = &source; } + + void rewind(unsigned path_id) + { +diff --git a/src/third_party/agg/include/agg_conv_unclose_polygon.h b/src/third_party/agg/include/agg_conv_unclose_polygon.h +index 5474ce2..66ea458 100644 +--- a/src/third_party/agg/include/agg_conv_unclose_polygon.h ++++ b/src/third_party/agg/include/agg_conv_unclose_polygon.h +@@ -25,8 +25,7 @@ namespace agg + { + public: + conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {} +- +- void set_source(VertexSource& source) { m_source = &source; } ++ void attach(VertexSource& source) { m_source = &source; } + + void rewind(unsigned path_id) + { +diff --git a/src/third_party/agg/include/agg_curves.h b/src/third_party/agg/include/agg_curves.h +index 1cb69c3..1ef02e8 100644 +--- a/src/third_party/agg/include/agg_curves.h ++++ b/src/third_party/agg/include/agg_curves.h +@@ -152,7 +152,6 @@ namespace agg + + double m_approximation_scale; + double m_distance_tolerance_square; +- double m_distance_tolerance_manhattan; + double m_angle_tolerance; + unsigned m_count; + pod_bvector m_points; +@@ -464,7 +463,6 @@ namespace agg + + double m_approximation_scale; + double m_distance_tolerance_square; +- double m_distance_tolerance_manhattan; + double m_angle_tolerance; + double m_cusp_limit; + unsigned m_count; +diff --git a/src/third_party/agg/include/agg_font_cache_manager.h b/src/third_party/agg/include/agg_font_cache_manager.h +index 4585465..e9cf5bf 100644 +--- a/src/third_party/agg/include/agg_font_cache_manager.h ++++ b/src/third_party/agg/include/agg_font_cache_manager.h +@@ -52,9 +52,13 @@ namespace agg + enum block_size_e { block_size = 16384-16 }; + + //-------------------------------------------------------------------- +- font_cache(const char* font_signature) : ++ font_cache() : + m_allocator(block_size), + m_font_signature(0) ++ {} ++ ++ //-------------------------------------------------------------------- ++ void signature(const char* font_signature) + { + m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1); + strcpy(m_font_signature, font_signature); +@@ -103,18 +107,18 @@ namespace agg + (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache), + sizeof(double)); + +- glyph->glyph_index = glyph_index; +- glyph->data = m_allocator.allocate(data_size); +- glyph->data_size = data_size; +- glyph->data_type = data_type; +- glyph->bounds = bounds; +- glyph->advance_x = advance_x; +- glyph->advance_y = advance_y; ++ glyph->glyph_index = glyph_index; ++ glyph->data = m_allocator.allocate(data_size); ++ glyph->data_size = data_size; ++ glyph->data_type = data_type; ++ glyph->bounds = bounds; ++ glyph->advance_x = advance_x; ++ glyph->advance_y = advance_y; + return m_glyphs[msb][lsb] = glyph; + } + + private: +- pod_allocator m_allocator; ++ block_allocator m_allocator; + glyph_cache** m_glyphs[256]; + char* m_font_signature; + }; +@@ -135,14 +139,14 @@ namespace agg + unsigned i; + for(i = 0; i < m_num_fonts; ++i) + { +- delete m_fonts[i]; ++ obj_allocator::deallocate(m_fonts[i]); + } +- delete [] m_fonts; ++ pod_allocator::deallocate(m_fonts, m_max_fonts); + } + + //-------------------------------------------------------------------- + font_cache_pool(unsigned max_fonts=32) : +- m_fonts(new font_cache* [max_fonts]), ++ m_fonts(pod_allocator::allocate(max_fonts)), + m_max_fonts(max_fonts), + m_num_fonts(0), + m_cur_font(0) +@@ -157,8 +161,9 @@ namespace agg + { + if(reset_cache) + { +- delete m_fonts[idx]; +- m_fonts[idx] = new font_cache(font_signature); ++ obj_allocator::deallocate(m_fonts[idx]); ++ m_fonts[idx] = obj_allocator::allocate(); ++ m_fonts[idx]->signature(font_signature); + } + m_cur_font = m_fonts[idx]; + } +@@ -166,13 +171,14 @@ namespace agg + { + if(m_num_fonts >= m_max_fonts) + { +- delete m_fonts[0]; ++ obj_allocator::deallocate(m_fonts[0]); + memcpy(m_fonts, + m_fonts + 1, + (m_max_fonts - 1) * sizeof(font_cache*)); + m_num_fonts = m_max_fonts - 1; + } +- m_fonts[m_num_fonts] = new font_cache(font_signature); ++ m_fonts[m_num_fonts] = obj_allocator::allocate(); ++ m_fonts[m_num_fonts]->signature(font_signature); + m_cur_font = m_fonts[m_num_fonts]; + ++m_num_fonts; + } +@@ -361,6 +367,12 @@ namespace agg + m_prev_glyph = m_last_glyph = 0; + } + ++ //-------------------------------------------------------------------- ++ void reset() ++ { ++ m_prev_glyph = m_last_glyph = 0; ++ } ++ + private: + //-------------------------------------------------------------------- + font_cache_manager(const self_type&); +diff --git a/src/third_party/agg/include/agg_gamma_lut.h b/src/third_party/agg/include/agg_gamma_lut.h +index cef8788..c3e8dfc 100644 +--- a/src/third_party/agg/include/agg_gamma_lut.h ++++ b/src/third_party/agg/include/agg_gamma_lut.h +@@ -45,14 +45,14 @@ namespace agg + + ~gamma_lut() + { +- delete [] m_inv_gamma; +- delete [] m_dir_gamma; ++ pod_allocator::deallocate(m_inv_gamma, hi_res_size); ++ pod_allocator::deallocate(m_dir_gamma, gamma_size); + } + + gamma_lut() : + m_gamma(1.0), +- m_dir_gamma(new HiResT[gamma_size]), +- m_inv_gamma(new LoResT[hi_res_size]) ++ m_dir_gamma(pod_allocator::allocate(gamma_size)), ++ m_inv_gamma(pod_allocator::allocate(hi_res_size)) + { + unsigned i; + for(i = 0; i < gamma_size; i++) +@@ -68,8 +68,8 @@ namespace agg + + gamma_lut(double g) : + m_gamma(1.0), +- m_dir_gamma(new HiResT[gamma_size]), +- m_inv_gamma(new LoResT[hi_res_size]) ++ m_dir_gamma(pod_allocator::allocate(gamma_size)), ++ m_inv_gamma(pod_allocator::allocate(hi_res_size)) + { + gamma(g); + } +diff --git a/src/third_party/agg/include/agg_gsv_text.h b/src/third_party/agg/include/agg_gsv_text.h +index cbfdc11..269c8a4 100644 +--- a/src/third_party/agg/include/agg_gsv_text.h ++++ b/src/third_party/agg/include/agg_gsv_text.h +@@ -20,7 +20,7 @@ + #ifndef AGG_GSV_TEXT_INCLUDED + #define AGG_GSV_TEXT_INCLUDED + +-#include "agg_basics.h" ++#include "agg_array.h" + #include "agg_conv_stroke.h" + #include "agg_conv_transform.h" + +@@ -43,7 +43,6 @@ namespace agg + }; + + public: +- ~gsv_text(); + gsv_text(); + + void font(const void* font); +@@ -80,30 +79,28 @@ namespace agg + } + + private: +- double m_x; +- double m_y; +- double m_start_x; +- double m_width; +- double m_height; +- double m_space; +- double m_line_space; +- char m_chr[2]; +- char* m_text; +- char* m_text_buf; +- unsigned m_buf_size; +- char* m_cur_chr; +- const void* m_font; +- char* m_loaded_font; +- status m_status; +- bool m_big_endian; +- bool m_flip; +- +- int8u* m_indices; +- int8* m_glyphs; +- int8* m_bglyph; +- int8* m_eglyph; +- double m_w; +- double m_h; ++ double m_x; ++ double m_y; ++ double m_start_x; ++ double m_width; ++ double m_height; ++ double m_space; ++ double m_line_space; ++ char m_chr[2]; ++ char* m_text; ++ pod_array m_text_buf; ++ char* m_cur_chr; ++ const void* m_font; ++ pod_array m_loaded_font; ++ status m_status; ++ bool m_big_endian; ++ bool m_flip; ++ int8u* m_indices; ++ int8* m_glyphs; ++ int8* m_bglyph; ++ int8* m_eglyph; ++ double m_w; ++ double m_h; + }; + + +diff --git a/src/third_party/agg/include/agg_image_accessors.h b/src/third_party/agg/include/agg_image_accessors.h +index fe5b7f4..d551dbc 100644 +--- a/src/third_party/agg/include/agg_image_accessors.h ++++ b/src/third_party/agg/include/agg_image_accessors.h +@@ -38,7 +38,7 @@ namespace agg + pixfmt_type::make_pix(m_bk_buf, bk); + } + +- void set_source(const pixfmt_type& pixf) ++ void attach(const pixfmt_type& pixf) + { + m_pixf = &pixf; + } +@@ -116,7 +116,7 @@ namespace agg + image_accessor_no_clip() {} + image_accessor_no_clip(const pixfmt_type& pixf) : m_pixf(&pixf) {} + +- void set_source(const pixfmt_type& pixf) ++ void attach(const pixfmt_type& pixf) + { + m_pixf = &pixf; + } +@@ -161,7 +161,7 @@ namespace agg + image_accessor_clone() {} + image_accessor_clone(const pixfmt_type& pixf) : m_pixf(&pixf) {} + +- void set_source(const pixfmt_type& pixf) ++ void attach(const pixfmt_type& pixf) + { + m_pixf = &pixf; + } +@@ -184,7 +184,7 @@ namespace agg + m_x = m_x0 = x; + m_y = y; + if(y >= 0 && y < (int)m_pixf->height() && +- x >= 0 && x+len <= (int)m_pixf->width()) ++ x >= 0 && (int)(x+len) <= (int)m_pixf->width()) + { + return m_pix_ptr = m_pixf->pix_ptr(x, y); + } +@@ -239,7 +239,7 @@ namespace agg + m_wrap_y(pixf.height()) + {} + +- void set_source(const pixfmt_type& pixf) ++ void attach(const pixfmt_type& pixf) + { + m_pixf = &pixf; + } +diff --git a/src/third_party/agg/include/agg_image_filters.h b/src/third_party/agg/include/agg_image_filters.h +index 2738cad..8e1bc8f 100644 +--- a/src/third_party/agg/include/agg_image_filters.h ++++ b/src/third_party/agg/include/agg_image_filters.h +@@ -20,6 +20,7 @@ + #ifndef AGG_IMAGE_FILTERS_INCLUDED + #define AGG_IMAGE_FILTERS_INCLUDED + ++#include "agg_array.h" + #include "agg_math.h" + + namespace agg +@@ -46,9 +47,6 @@ namespace agg + class image_filter_lut + { + public: +- ~image_filter_lut(); +- image_filter_lut(); +- + template void calculate(const FilterF& filter, + bool normalization=true) + { +@@ -71,18 +69,18 @@ namespace agg + } + } + ++ image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {} ++ + template image_filter_lut(const FilterF& filter, +- bool normalization=true) : +- m_weight_array(0), +- m_max_size(0) ++ bool normalization=true) + { + calculate(filter, normalization); + } + +- double radius() const { return m_radius; } +- unsigned diameter() const { return m_diameter; } +- int start() const { return m_start; } +- const int16* weight_array() const { return m_weight_array; } ++ double radius() const { return m_radius; } ++ unsigned diameter() const { return m_diameter; } ++ int start() const { return m_start; } ++ const int16* weight_array() const { return &m_weight_array[0]; } + void normalize(); + + private: +@@ -90,11 +88,10 @@ namespace agg + image_filter_lut(const image_filter_lut&); + const image_filter_lut& operator = (const image_filter_lut&); + +- double m_radius; +- unsigned m_diameter; +- int m_start; +- int16* m_weight_array; +- unsigned m_max_size; ++ double m_radius; ++ unsigned m_diameter; ++ int m_start; ++ pod_array m_weight_array; + }; + + +diff --git a/src/third_party/agg/include/agg_line_aa_basics.h b/src/third_party/agg/include/agg_line_aa_basics.h +index 1fafb98..c5acb18 100644 +--- a/src/third_party/agg/include/agg_line_aa_basics.h ++++ b/src/third_party/agg/include/agg_line_aa_basics.h +@@ -142,8 +142,8 @@ namespace agg + int octant; + + //--------------------------------------------------------------------- +- static int8u s_orthogonal_quadrant[8]; +- static int8u s_diagonal_quadrant[8]; ++ static const int8u s_orthogonal_quadrant[8]; ++ static const int8u s_diagonal_quadrant[8]; + }; + + +diff --git a/src/third_party/agg/include/agg_math.h b/src/third_party/agg/include/agg_math.h +index 3d6e22c..6d3ff11 100644 +--- a/src/third_party/agg/include/agg_math.h ++++ b/src/third_party/agg/include/agg_math.h +@@ -33,28 +33,26 @@ namespace agg + // See calc_intersection + const double intersection_epsilon = 1.0e-30; + +- //------------------------------------------------------calc_point_location +- AGG_INLINE double calc_point_location(double x1, double y1, +- double x2, double y2, +- double x, double y) ++ //------------------------------------------------------------cross_product ++ AGG_INLINE double cross_product(double x1, double y1, ++ double x2, double y2, ++ double x, double y) + { + return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1); + } + +- + //--------------------------------------------------------point_in_triangle + AGG_INLINE bool point_in_triangle(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x, double y) + { +- bool cp1 = calc_point_location(x1, y1, x2, y2, x, y) < 0.0; +- bool cp2 = calc_point_location(x2, y2, x3, y3, x, y) < 0.0; +- bool cp3 = calc_point_location(x3, y3, x1, y1, x, y) < 0.0; ++ bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0; ++ bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0; ++ bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0; + return cp1 == cp2 && cp2 == cp3 && cp3 == cp1; + } + +- + //-----------------------------------------------------------calc_distance + AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2) + { +@@ -63,6 +61,13 @@ namespace agg + return sqrt(dx * dx + dy * dy); + } + ++ //--------------------------------------------------------calc_sq_distance ++ AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2) ++ { ++ double dx = x2-x1; ++ double dy = y2-y1; ++ return dx * dx + dy * dy; ++ } + + //------------------------------------------------calc_line_point_distance + AGG_INLINE double calc_line_point_distance(double x1, double y1, +@@ -79,6 +84,53 @@ namespace agg + return ((x - x2) * dy - (y - y2) * dx) / d; + } + ++ //-------------------------------------------------------calc_line_point_u ++ AGG_INLINE double calc_segment_point_u(double x1, double y1, ++ double x2, double y2, ++ double x, double y) ++ { ++ double dx = x2 - x1; ++ double dy = y2 - y1; ++ ++ if(dx == 0 && dy == 0) ++ { ++ return 0; ++ } ++ ++ double pdx = x - x1; ++ double pdy = y - y1; ++ ++ return (pdx * dx + pdy * dy) / (dx * dx + dy * dy); ++ } ++ ++ //---------------------------------------------calc_line_point_sq_distance ++ AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, ++ double x2, double y2, ++ double x, double y, ++ double u) ++ { ++ if(u <= 0) ++ { ++ return calc_sq_distance(x, y, x1, y1); ++ } ++ else ++ if(u >= 1) ++ { ++ return calc_sq_distance(x, y, x2, y2); ++ } ++ return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1)); ++ } ++ ++ //---------------------------------------------calc_line_point_sq_distance ++ AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, ++ double x2, double y2, ++ double x, double y) ++ { ++ return ++ calc_segment_point_sq_distance( ++ x1, y1, x2, y2, x, y, ++ calc_segment_point_u(x1, y1, x2, y2, x, y)); ++ } + + //-------------------------------------------------------calc_intersection + AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by, +@@ -94,7 +146,6 @@ namespace agg + return true; + } + +- + //-----------------------------------------------------intersection_exists + AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2, + double x3, double y3, double x4, double y4) +@@ -122,7 +173,6 @@ namespace agg + //return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0; + } + +- + //--------------------------------------------------------calc_orthogonal + AGG_INLINE void calc_orthogonal(double thickness, + double x1, double y1, +@@ -132,11 +182,10 @@ namespace agg + double dx = x2 - x1; + double dy = y2 - y1; + double d = sqrt(dx*dx + dy*dy); +- *x = thickness * dy / d; +- *y = thickness * dx / d; ++ *x = thickness * dy / d; ++ *y = -thickness * dx / d; + } + +- + //--------------------------------------------------------dilate_triangle + AGG_INLINE void dilate_triangle(double x1, double y1, + double x2, double y2, +@@ -150,10 +199,10 @@ namespace agg + double dy2=0.0; + double dx3=0.0; + double dy3=0.0; +- double loc = calc_point_location(x1, y1, x2, y2, x3, y3); ++ double loc = cross_product(x1, y1, x2, y2, x3, y3); + if(fabs(loc) > intersection_epsilon) + { +- if(calc_point_location(x1, y1, x2, y2, x3, y3) > 0.0) ++ if(cross_product(x1, y1, x2, y2, x3, y3) > 0.0) + { + d = -d; + } +@@ -161,12 +210,12 @@ namespace agg + calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2); + calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3); + } +- *x++ = x1 + dx1; *y++ = y1 - dy1; +- *x++ = x2 + dx1; *y++ = y2 - dy1; +- *x++ = x2 + dx2; *y++ = y2 - dy2; +- *x++ = x3 + dx2; *y++ = y3 - dy2; +- *x++ = x3 + dx3; *y++ = y3 - dy3; +- *x++ = x1 + dx3; *y++ = y1 - dy3; ++ *x++ = x1 + dx1; *y++ = y1 + dy1; ++ *x++ = x2 + dx1; *y++ = y2 + dy1; ++ *x++ = x2 + dx2; *y++ = y2 + dy2; ++ *x++ = x3 + dx2; *y++ = y3 + dy2; ++ *x++ = x3 + dx3; *y++ = y3 + dy3; ++ *x++ = x1 + dx3; *y++ = y1 + dy3; + } + + //------------------------------------------------------calc_triangle_area +@@ -177,7 +226,6 @@ namespace agg + return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5; + } + +- + //-------------------------------------------------------calc_polygon_area + template double calc_polygon_area(const Storage& st) + { +diff --git a/src/third_party/agg/include/agg_math_stroke.h b/src/third_party/agg/include/agg_math_stroke.h +index 621f87a..c7f0dbd 100644 +--- a/src/third_party/agg/include/agg_math_stroke.h ++++ b/src/third_party/agg/include/agg_math_stroke.h +@@ -38,9 +38,9 @@ namespace agg + { + miter_join = 0, + miter_join_revert = 1, +- miter_join_round = 4, + round_join = 2, +- bevel_join = 3 ++ bevel_join = 3, ++ miter_join_round = 4 + }; + + +@@ -53,80 +53,162 @@ namespace agg + inner_round + }; + +- // Minimal angle to calculate round joins, less than 0.1 degree. +- const double stroke_theta = 0.001; //----stroke_theta +- +- //--------------------------------------------------------stroke_calc_arc +- template +- void stroke_calc_arc(VertexConsumer& out_vertices, +- double x, double y, +- double dx1, double dy1, +- double dx2, double dy2, +- double width, +- double approximation_scale) ++ //------------------------------------------------------------math_stroke ++ template class math_stroke + { ++ public: + typedef typename VertexConsumer::value_type coord_type; + +- double a1 = atan2(dy1, dx1); +- double a2 = atan2(dy2, dx2); +- double da = a1 - a2; ++ math_stroke(); ++ ++ void line_cap(line_cap_e lc) { m_line_cap = lc; } ++ void line_join(line_join_e lj) { m_line_join = lj; } ++ void inner_join(inner_join_e ij) { m_inner_join = ij; } ++ ++ line_cap_e line_cap() const { return m_line_cap; } ++ line_join_e line_join() const { return m_line_join; } ++ inner_join_e inner_join() const { return m_inner_join; } ++ ++ void width(double w); ++ void miter_limit(double ml) { m_miter_limit = ml; } ++ void miter_limit_theta(double t); ++ void inner_miter_limit(double ml) { m_inner_miter_limit = ml; } ++ void approximation_scale(double as) { m_approx_scale = as; } ++ ++ double width() const { return m_width * 2.0; } ++ double miter_limit() const { return m_miter_limit; } ++ double inner_miter_limit() const { return m_inner_miter_limit; } ++ double approximation_scale() const { return m_approx_scale; } ++ ++ void calc_cap(VertexConsumer& out_vertices, ++ const vertex_dist& v0, ++ const vertex_dist& v1, ++ double len); ++ ++ void calc_join(VertexConsumer& out_vertices, ++ const vertex_dist& v0, ++ const vertex_dist& v1, ++ const vertex_dist& v2, ++ double len1, ++ double len2); ++ ++ private: ++ void calc_arc(VertexConsumer& out_vertices, ++ double x, double y, ++ double dx1, double dy1, ++ double dx2, double dy2); ++ ++ void 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, ++ line_join_e lj, ++ double ml); ++ ++ double m_width; ++ double m_width_abs; ++ int m_width_sign; ++ double m_miter_limit; ++ double m_inner_miter_limit; ++ double m_approx_scale; ++ line_cap_e m_line_cap; ++ line_join_e m_line_join; ++ inner_join_e m_inner_join; ++ }; ++ ++ //----------------------------------------------------------------------- ++ template math_stroke::math_stroke() : ++ m_width(0.5), ++ m_width_abs(0.5), ++ m_width_sign(1), ++ m_miter_limit(4.0), ++ m_inner_miter_limit(1.01), ++ m_approx_scale(1.0), ++ m_line_cap(butt_cap), ++ m_line_join(miter_join), ++ m_inner_join(inner_miter) ++ { ++ } ++ ++ //----------------------------------------------------------------------- ++ template void math_stroke::width(double w) ++ { ++ m_width = w * 0.5; ++ if(m_width < 0) ++ { ++ m_width_abs = -m_width; ++ m_width_sign = -1; ++ } ++ else ++ { ++ m_width_abs = m_width; ++ m_width_sign = 1; ++ } ++ } + +- // Possible optimization. Not important at all; consumes time but happens rarely +- //if(fabs(da) < stroke_theta) +- //{ +- // out_vertices.add(coord_type((x + x + dx1 + dx2) * 0.5, +- // (y + y + dy1 + dy2) * 0.5)); +- // return; +- //} ++ //----------------------------------------------------------------------- ++ template void math_stroke::miter_limit_theta(double t) ++ { ++ m_miter_limit = 1.0 / sin(t * 0.5) ; ++ } + +- bool ccw = da > 0.0 && da < pi; ++ //----------------------------------------------------------------------- ++ template ++ void math_stroke::calc_arc(VC& out_vertices, ++ double x, double y, ++ double dx1, double dy1, ++ double dx2, double dy2) ++ { ++ double a1 = atan2(dy1 * m_width_sign, dx1 * m_width_sign); ++ double a2 = atan2(dy2 * m_width_sign, dx2 * m_width_sign); ++ double da = a1 - a2; ++ int i, n; + +- if(width < 0) width = -width; +- da = acos(width / (width + 0.125 / approximation_scale)) * 2; ++ da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2; + + out_vertices.add(coord_type(x + dx1, y + dy1)); +- if(!ccw) ++ if(m_width_sign > 0) + { + if(a1 > a2) a2 += 2 * pi; +- a2 -= da / 4; ++ n = int((a2 - a1) / da); ++ da = (a2 - a1) / (n + 1); + a1 += da; +- while(a1 < a2) ++ for(i = 0; i < n; i++) + { +- out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width)); ++ out_vertices.add(coord_type(x + cos(a1) * m_width, ++ y + sin(a1) * m_width)); + a1 += da; + } + } + else + { + if(a1 < a2) a2 -= 2 * pi; +- a2 += da / 4; ++ n = int((a1 - a2) / da); ++ da = (a1 - a2) / (n + 1); + a1 -= da; +- while(a1 > a2) ++ for(i = 0; i < n; i++) + { +- out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width)); ++ out_vertices.add(coord_type(x + cos(a1) * m_width, ++ y + sin(a1) * m_width)); + a1 -= da; + } + } + out_vertices.add(coord_type(x + dx2, y + dy2)); + } + +- +- +- //-------------------------------------------------------stroke_calc_miter +- template +- void stroke_calc_miter(VertexConsumer& out_vertices, +- const vertex_dist& v0, +- const vertex_dist& v1, +- const vertex_dist& v2, +- double dx1, double dy1, +- double dx2, double dy2, +- double width, +- line_join_e line_join, +- double miter_limit, +- double approximation_scale) ++ //----------------------------------------------------------------------- ++ template ++ void math_stroke::calc_miter(VC& out_vertices, ++ const vertex_dist& v0, ++ const vertex_dist& v1, ++ const vertex_dist& v2, ++ double dx1, double dy1, ++ double dx2, double dy2, ++ line_join_e lj, ++ double ml) + { +- typedef typename VertexConsumer::value_type coord_type; +- + double xi = v1.x; + double yi = v1.y; + bool miter_limit_exceeded = true; // Assume the worst +@@ -140,7 +222,7 @@ namespace agg + // Calculation of the intersection succeeded + //--------------------- + double d1 = calc_distance(v1.x, v1.y, xi, yi); +- double lim = width * miter_limit; ++ double lim = m_width_abs * ml; + if(d1 <= lim) + { + // Inside the miter limit +@@ -176,7 +258,7 @@ namespace agg + { + // Miter limit exceeded + //------------------------ +- switch(line_join) ++ switch(lj) + { + case miter_join_revert: + // For the compatibility with SVG, PDF, etc, +@@ -188,40 +270,29 @@ namespace agg + break; + + case miter_join_round: +- stroke_calc_arc(out_vertices, +- v1.x, v1.y, dx1, -dy1, dx2, -dy2, +- width, approximation_scale); ++ calc_arc(out_vertices, v1.x, v1.y, dx1, -dy1, dx2, -dy2); + break; + + default: + // If no miter-revert, calculate new dx1, dy1, dx2, dy2 + //---------------- +- out_vertices.add(coord_type(v1.x + dx1 + dy1 * miter_limit, +- v1.y - dy1 + dx1 * miter_limit)); +- out_vertices.add(coord_type(v1.x + dx2 - dy2 * miter_limit, +- v1.y - dy2 - dx2 * miter_limit)); ++ ml *= m_width_sign; ++ out_vertices.add(coord_type(v1.x + dx1 + dy1 * ml, ++ v1.y - dy1 + dx1 * ml)); ++ out_vertices.add(coord_type(v1.x + dx2 - dy2 * ml, ++ v1.y - dy2 - dx2 * ml)); + break; + } + } + } + +- +- +- +- +- + //--------------------------------------------------------stroke_calc_cap +- template +- void stroke_calc_cap(VertexConsumer& out_vertices, +- const vertex_dist& v0, +- const vertex_dist& v1, +- double len, +- line_cap_e line_cap, +- double width, +- double approximation_scale) ++ template ++ void math_stroke::calc_cap(VC& out_vertices, ++ const vertex_dist& v0, ++ const vertex_dist& v1, ++ double len) + { +- typedef typename VertexConsumer::value_type coord_type; +- + out_vertices.remove_all(); + + double dx1 = (v1.y - v0.y) / len; +@@ -229,71 +300,86 @@ namespace agg + double dx2 = 0; + double dy2 = 0; + +- dx1 *= width; +- dy1 *= width; ++ dx1 *= m_width; ++ dy1 *= m_width; + +- if(line_cap != round_cap) ++ if(m_line_cap != round_cap) + { +- if(line_cap == square_cap) ++ if(m_line_cap == square_cap) + { +- dx2 = dy1; +- dy2 = dx1; ++ dx2 = dy1 * m_width_sign; ++ dy2 = dx1 * m_width_sign; + } + out_vertices.add(coord_type(v0.x - dx1 - dx2, v0.y + dy1 - dy2)); + out_vertices.add(coord_type(v0.x + dx1 - dx2, v0.y - dy1 - dy2)); + } + else + { +- double a1 = atan2(dy1, -dx1); +- double a2 = a1 + pi; +- double da = acos(width / (width + 0.125 / approximation_scale)) * 2; ++ double da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2; ++ double a1; ++ int i; ++ int n = int(pi / da); ++ ++ da = pi / (n + 1); + out_vertices.add(coord_type(v0.x - dx1, v0.y + dy1)); +- a1 += da; +- a2 -= da/4; +- while(a1 < a2) ++ if(m_width_sign > 0) + { +- out_vertices.add(coord_type(v0.x + cos(a1) * width, +- v0.y + sin(a1) * width)); ++ a1 = atan2(dy1, -dx1); + a1 += da; ++ for(i = 0; i < n; i++) ++ { ++ out_vertices.add(coord_type(v0.x + cos(a1) * m_width, ++ v0.y + sin(a1) * m_width)); ++ a1 += da; ++ } ++ } ++ else ++ { ++ a1 = atan2(-dy1, dx1); ++ a1 -= da; ++ for(i = 0; i < n; i++) ++ { ++ out_vertices.add(coord_type(v0.x + cos(a1) * m_width, ++ v0.y + sin(a1) * m_width)); ++ a1 -= da; ++ } + } + out_vertices.add(coord_type(v0.x + dx1, v0.y - dy1)); + } + } + +- +- +- //-------------------------------------------------------stroke_calc_join +- template +- void stroke_calc_join(VertexConsumer& out_vertices, +- const vertex_dist& v0, +- const vertex_dist& v1, +- const vertex_dist& v2, +- double len1, +- double len2, +- double width, +- line_join_e line_join, +- inner_join_e inner_join, +- double miter_limit, +- double inner_miter_limit, +- double approximation_scale) ++ //----------------------------------------------------------------------- ++ template ++ void math_stroke::calc_join(VC& out_vertices, ++ const vertex_dist& v0, ++ const vertex_dist& v1, ++ const vertex_dist& v2, ++ double len1, ++ double len2) + { +- typedef typename VertexConsumer::value_type coord_type; +- + double dx1, dy1, dx2, dy2; ++ double d; + +- dx1 = width * (v1.y - v0.y) / len1; +- dy1 = width * (v1.x - v0.x) / len1; ++ dx1 = m_width * (v1.y - v0.y) / len1; ++ dy1 = m_width * (v1.x - v0.x) / len1; + +- dx2 = width * (v2.y - v1.y) / len2; +- dy2 = width * (v2.x - v1.x) / len2; ++ dx2 = m_width * (v2.y - v1.y) / len2; ++ dy2 = m_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) ++ double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y); ++ if(cp != 0 && (cp > 0) == (m_width > 0)) + { + // Inner join + //--------------- +- switch(inner_join) ++ double limit = ((len1 < len2) ? len1 : len2) / m_width_abs; ++ if(limit < m_inner_miter_limit) ++ { ++ limit = m_inner_miter_limit; ++ } ++ ++ switch(m_inner_join) + { + default: // inner_bevel + out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1)); +@@ -301,30 +387,26 @@ namespace agg + break; + + case inner_miter: +- stroke_calc_miter(out_vertices, +- v0, v1, v2, dx1, dy1, dx2, dy2, +- width, +- miter_join_revert, +- inner_miter_limit, +- 1.0); ++ calc_miter(out_vertices, ++ v0, v1, v2, dx1, dy1, dx2, dy2, ++ miter_join_revert, ++ limit); + break; + + case inner_jag: + case inner_round: + { +- double d = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2); ++ d = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2); + if(d < len1 * len1 && d < len2 * len2) + { +- stroke_calc_miter(out_vertices, +- v0, v1, v2, dx1, dy1, dx2, dy2, +- width, +- miter_join_revert, +- inner_miter_limit, +- 1.0); ++ calc_miter(out_vertices, ++ v0, v1, v2, dx1, dy1, dx2, dy2, ++ miter_join_revert, ++ limit); + } + else + { +- if(inner_join == inner_jag) ++ if(m_inner_join == inner_jag) + { + out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1)); + out_vertices.add(coord_type(v1.x, v1.y )); +@@ -334,9 +416,7 @@ namespace agg + { + out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1)); + out_vertices.add(coord_type(v1.x, v1.y )); +- stroke_calc_arc(out_vertices, +- v1.x, v1.y, dx2, -dy2, dx1, -dy1, +- width, approximation_scale); ++ calc_arc(out_vertices, v1.x, v1.y, dx2, -dy2, dx1, -dy1); + out_vertices.add(coord_type(v1.x, v1.y )); + out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2)); + } +@@ -349,23 +429,48 @@ namespace agg + { + // Outer join + //--------------- +- switch(line_join) ++ line_join_e lj = m_line_join; ++ if(m_line_join == round_join || m_line_join == bevel_join) ++ { ++ // This is an optimization that reduces the number of points ++ // in cases of almost collonear segments. If there's no ++ // visible difference between bevel and miter joins we'd rather ++ // use miter join because it adds only one point instead of two. ++ // ++ // Here we calculate the middle point between the bevel points ++ // and then, the distance between v1 and this middle point. ++ // At outer joins this distance always less than stroke width, ++ // because it's actually the height of an isosceles triangle of ++ // v1 and its two bevel points. If the difference between this ++ // width and this value is small (no visible bevel) we can switch ++ // to the miter join. ++ // ++ // The constant in the expression makes the result approximately ++ // the same as in round joins and caps. One can safely comment ++ // out this "if". ++ //------------------- ++ double dx = (dx1 + dx2) / 2; ++ double dy = (dy1 + dy2) / 2; ++ d = m_width_abs - sqrt(dx * dx + dy * dy); ++ if(d < 0.0625 / m_approx_scale) ++ { ++ lj = miter_join; ++ } ++ } ++ ++ switch(lj) + { + case miter_join: + case miter_join_revert: + case miter_join_round: +- stroke_calc_miter(out_vertices, +- v0, v1, v2, dx1, dy1, dx2, dy2, +- width, +- line_join, +- miter_limit, +- approximation_scale); ++ calc_miter(out_vertices, ++ v0, v1, v2, dx1, dy1, dx2, dy2, ++ lj, ++ m_miter_limit); + break; + + case round_join: +- stroke_calc_arc(out_vertices, +- v1.x, v1.y, dx1, -dy1, dx2, -dy2, +- width, approximation_scale); ++ calc_arc(out_vertices, v1.x, v1.y, dx1, -dy1, dx2, -dy2); + break; + + default: // Bevel join +diff --git a/src/third_party/agg/include/agg_path_storage.h b/src/third_party/agg/include/agg_path_storage.h +index 6a001af..141d704 100644 +--- a/src/third_party/agg/include/agg_path_storage.h ++++ b/src/third_party/agg/include/agg_path_storage.h +@@ -90,10 +90,13 @@ namespace agg + T** coord_blk = m_coord_blocks + m_total_blocks - 1; + while(m_total_blocks--) + { +- delete [] *coord_blk; ++ pod_allocator::deallocate( ++ *coord_blk, ++ block_size * 2 + ++ block_size / (sizeof(T) / sizeof(unsigned char))); + --coord_blk; + } +- delete [] m_coord_blocks; ++ pod_allocator::deallocate(m_coord_blocks, m_max_blocks * 2); + m_total_blocks = 0; + m_max_blocks = 0; + m_coord_blocks = 0; +@@ -145,7 +148,7 @@ namespace agg + unsigned cmd = v.vertex(i, &x, &y); + add_vertex(x, y, cmd); + } +- return *this; ++ return *this; + } + + //------------------------------------------------------------------------ +@@ -298,7 +301,7 @@ namespace agg + if(nb >= m_max_blocks) + { + T** new_coords = +- new T* [(m_max_blocks + block_pool) * 2]; ++ pod_allocator::allocate((m_max_blocks + block_pool) * 2); + + unsigned char** new_cmds = + (unsigned char**)(new_coords + m_max_blocks + block_pool); +@@ -313,15 +316,15 @@ namespace agg + m_cmd_blocks, + m_max_blocks * sizeof(unsigned char*)); + +- delete [] m_coord_blocks; ++ pod_allocator::deallocate(m_coord_blocks, m_max_blocks * 2); + } + m_coord_blocks = new_coords; +- m_cmd_blocks = new_cmds; +- m_max_blocks += block_pool; ++ m_cmd_blocks = new_cmds; ++ m_max_blocks += block_pool; + } + m_coord_blocks[nb] = +- new T [block_size * 2 + +- block_size / (sizeof(T) / sizeof(unsigned char))]; ++ pod_allocator::allocate(block_size * 2 + ++ block_size / (sizeof(T) / sizeof(unsigned char))); + + m_cmd_blocks[nb] = + (unsigned char*)(m_coord_blocks[nb] + block_size * 2); +@@ -1232,10 +1235,7 @@ namespace agg + while(end < m_vertices.total_vertices() && + !is_next_poly(m_vertices.command(end))) ++end; + +- if(end - start > 2) +- { +- invert_polygon(start, end); +- } ++ invert_polygon(start, end); + } + + //------------------------------------------------------------------------ +diff --git a/src/third_party/agg/include/agg_pixfmt_amask_adaptor.h b/src/third_party/agg/include/agg_pixfmt_amask_adaptor.h +index 0c7b0e3..1f2c12e 100644 +--- a/src/third_party/agg/include/agg_pixfmt_amask_adaptor.h ++++ b/src/third_party/agg/include/agg_pixfmt_amask_adaptor.h +@@ -18,6 +18,7 @@ + + + #include ++#include "agg_array.h" + #include "agg_rendering_buffer.h" + + +@@ -38,38 +39,40 @@ namespace agg + + void realloc_span(unsigned len) + { +- if(len > m_max_len) ++ if(len > m_span.size()) + { +- delete [] m_span; +- m_span = new cover_type[m_max_len = len + span_extra_tail]; ++ m_span.resize(len + span_extra_tail); + } + } + + void init_span(unsigned len) + { + realloc_span(len); +- +- // ATTN! May work incorrectly if cover_type is more that one byte +- memset(m_span, amask_type::cover_full, len * sizeof(cover_type)); ++ memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type)); + } + + void init_span(unsigned len, const cover_type* covers) + { + realloc_span(len); +- memcpy(m_span, covers, len * sizeof(cover_type)); ++ memcpy(&m_span[0], covers, len * sizeof(cover_type)); + } + + + public: +- ~pixfmt_amask_adaptor() { delete [] m_span; } +- + pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) : +- m_pixf(&pixf), m_mask(&mask), m_span(0), m_max_len(0) ++ m_pixf(&pixf), m_mask(&mask), m_span() + {} + + void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; } + void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; } + ++ //-------------------------------------------------------------------- ++ template ++ bool attach_pixfmt(PixFmt_& pixf, int x1, int y1, int x2, int y2) ++ { ++ return m_pixf->attach(pixf, x1, y1, x2, y2); ++ } ++ + //-------------------------------------------------------------------- + unsigned width() const { return m_pixf->width(); } + unsigned height() const { return m_pixf->height(); } +@@ -98,8 +101,8 @@ namespace agg + const color_type& c) + { + realloc_span(len); +- m_mask->fill_hspan(x, y, m_span, len); +- m_pixf->blend_solid_hspan(x, y, len, c, m_span); ++ m_mask->fill_hspan(x, y, &m_span[0], len); ++ m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); + } + + //-------------------------------------------------------------------- +@@ -109,8 +112,8 @@ namespace agg + cover_type cover) + { + init_span(len); +- m_mask->combine_hspan(x, y, m_span, len); +- m_pixf->blend_solid_hspan(x, y, len, c, m_span); ++ m_mask->combine_hspan(x, y, &m_span[0], len); ++ m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); + } + + //-------------------------------------------------------------------- +@@ -119,8 +122,8 @@ namespace agg + const color_type& c) + { + realloc_span(len); +- m_mask->fill_vspan(x, y, m_span, len); +- m_pixf->blend_solid_vspan(x, y, len, c, m_span); ++ m_mask->fill_vspan(x, y, &m_span[0], len); ++ m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); + } + + //-------------------------------------------------------------------- +@@ -130,8 +133,8 @@ namespace agg + cover_type cover) + { + init_span(len); +- m_mask->combine_vspan(x, y, m_span, len); +- m_pixf->blend_solid_vspan(x, y, len, c, m_span); ++ m_mask->combine_vspan(x, y, &m_span[0], len); ++ m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); + } + + //-------------------------------------------------------------------- +@@ -151,8 +154,8 @@ namespace agg + const cover_type* covers) + { + init_span(len, covers); +- m_mask->combine_hspan(x, y, m_span, len); +- m_pixf->blend_solid_hspan(x, y, len, c, m_span); ++ m_mask->combine_hspan(x, y, &m_span[0], len); ++ m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); + } + + +@@ -163,8 +166,8 @@ namespace agg + const cover_type* covers) + { + init_span(len, covers); +- m_mask->combine_vspan(x, y, m_span, len); +- m_pixf->blend_solid_vspan(x, y, len, c, m_span); ++ m_mask->combine_vspan(x, y, &m_span[0], len); ++ m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); + } + + +@@ -172,10 +175,17 @@ namespace agg + void copy_color_hspan(int x, int y, unsigned len, const color_type* colors) + { + realloc_span(len); +- m_mask->fill_hspan(x, y, m_span, len); +- m_pixf->blend_color_hspan(x, y, len, colors, m_span, cover_full); ++ m_mask->fill_hspan(x, y, &m_span[0], len); ++ m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full); + } + ++ //-------------------------------------------------------------------- ++ void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) ++ { ++ realloc_span(len); ++ m_mask->fill_vspan(x, y, &m_span[0], len); ++ m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full); ++ } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, +@@ -187,14 +197,14 @@ namespace agg + if(covers) + { + init_span(len, covers); +- m_mask->combine_hspan(x, y, m_span, len); ++ m_mask->combine_hspan(x, y, &m_span[0], len); + } + else + { + realloc_span(len); +- m_mask->fill_hspan(x, y, m_span, len); ++ m_mask->fill_hspan(x, y, &m_span[0], len); + } +- m_pixf->blend_color_hspan(x, y, len, colors, m_span, cover); ++ m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover); + } + + +@@ -208,22 +218,20 @@ namespace agg + if(covers) + { + init_span(len, covers); +- m_mask->combine_vspan(x, y, m_span, len); ++ m_mask->combine_vspan(x, y, &m_span[0], len); + } + else + { + realloc_span(len); +- m_mask->fill_vspan(x, y, m_span, len); ++ m_mask->fill_vspan(x, y, &m_span[0], len); + } +- m_pixf->blend_color_vspan(x, y, len, colors, m_span, cover); ++ m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover); + } + + private: +- pixfmt_type* m_pixf; +- const amask_type* m_mask; +- +- cover_type* m_span; +- unsigned m_max_len; ++ pixfmt_type* m_pixf; ++ const amask_type* m_mask; ++ pod_array m_span; + }; + + } +diff --git a/src/third_party/agg/include/agg_pixfmt_gray.h b/src/third_party/agg/include/agg_pixfmt_gray.h +index 64fc9a9..08b3d7d 100644 +--- a/src/third_party/agg/include/agg_pixfmt_gray.h ++++ b/src/third_party/agg/include/agg_pixfmt_gray.h +@@ -128,7 +128,9 @@ namespace agg + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, +- pix_width = sizeof(value_type) ++ pix_width = sizeof(value_type), ++ pix_step = Step, ++ pix_offset = Offset + }; + + private: +@@ -174,27 +176,43 @@ namespace agg + pixfmt_alpha_blend_gray(rbuf_type& rb) : + m_rbuf(&rb) + {} ++ void attach(rbuf_type& rb) { m_rbuf = &rb; } ++ //-------------------------------------------------------------------- ++ ++ template ++ bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) ++ { ++ rect_i r(x1, y1, x2, y2); ++ if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) ++ { ++ int stride = pixf.stride(); ++ m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), ++ (r.x2 - r.x1) + 1, ++ (r.y2 - r.y1) + 1, ++ stride); ++ return true; ++ } ++ return false; ++ } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } ++ AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- +- const int8u* row_ptr(int y) const +- { +- return m_rbuf->row_ptr(y); +- } ++ int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } ++ const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } ++ row_data row(int y) const { return m_rbuf->row(y); } + +- //-------------------------------------------------------------------- + const int8u* pix_ptr(int x, int y) const + { +- return m_rbuf->row_ptr(y) + x * pix_width; ++ return m_rbuf->row_ptr(y) + x * Step + Offset; + } + +- //-------------------------------------------------------------------- +- row_data row(int x, int y) const ++ int8u* pix_ptr(int x, int y) + { +- return m_rbuf->row(y); ++ return m_rbuf->row_ptr(y) + x * Step + Offset; + } + + //-------------------------------------------------------------------- +@@ -206,7 +224,7 @@ namespace agg + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { +- value_type* p = (value_type*)m_rbuf->row(y) + x * Step + Offset; ++ value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset; + return color_type(*p); + } + +@@ -399,13 +417,29 @@ namespace agg + + do + { +- *p++ = colors->v; ++ *p = colors->v; ++ p += Step; + ++colors; + } + while(--len); + } + + ++ //-------------------------------------------------------------------- ++ void copy_color_vspan(int x, int y, ++ unsigned len, ++ const color_type* colors) ++ { ++ do ++ { ++ value_type* p = (value_type*) ++ m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; ++ *p = colors->v; ++ ++colors; ++ } ++ while(--len); ++ } ++ + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, +diff --git a/src/third_party/agg/include/agg_pixfmt_rgb.h b/src/third_party/agg/include/agg_pixfmt_rgb.h +index 9a96851..51450cf 100644 +--- a/src/third_party/agg/include/agg_pixfmt_rgb.h ++++ b/src/third_party/agg/include/agg_pixfmt_rgb.h +@@ -173,8 +173,8 @@ namespace agg + { + public: + typedef RenBuf rbuf_type; +- typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; ++ typedef typename rbuf_type::row_data row_data; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; +@@ -234,6 +234,24 @@ namespace agg + pixfmt_alpha_blend_rgb(rbuf_type& rb) : + m_rbuf(&rb) + {} ++ void attach(rbuf_type& rb) { m_rbuf = &rb; } ++ ++ //-------------------------------------------------------------------- ++ template ++ bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) ++ { ++ rect_i r(x1, y1, x2, y2); ++ if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) ++ { ++ int stride = pixf.stride(); ++ m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), ++ (r.x2 - r.x1) + 1, ++ (r.y2 - r.y1) + 1, ++ stride); ++ return true; ++ } ++ return false; ++ } + + //-------------------------------------------------------------------- + Blender& blender() { return m_blender; } +@@ -241,23 +259,22 @@ namespace agg + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } ++ AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- +- const int8u* row_ptr(int y) const +- { +- return m_rbuf->row_ptr(y); +- } ++ AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } ++ AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } ++ AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- +- const int8u* pix_ptr(int x, int y) const +- { +- return m_rbuf->row_ptr(y) + x * pix_width; ++ AGG_INLINE int8u* pix_ptr(int x, int y) ++ { ++ return m_rbuf->row_ptr(y) + x * pix_width; + } + +- //-------------------------------------------------------------------- +- row_data row(int x, int y) const +- { +- return m_rbuf->row(y); ++ AGG_INLINE const int8u* pix_ptr(int x, int y) const ++ { ++ return m_rbuf->row_ptr(y) + x * pix_width; + } + + //-------------------------------------------------------------------- +@@ -484,6 +501,24 @@ namespace agg + } + + ++ //-------------------------------------------------------------------- ++ void copy_color_vspan(int x, int y, ++ unsigned len, ++ const color_type* colors) ++ { ++ do ++ { ++ value_type* p = (value_type*) ++ m_rbuf->row_ptr(x, y++, 1) + x + x + x; ++ p[order_type::R] = colors->r; ++ p[order_type::G] = colors->g; ++ p[order_type::B] = colors->b; ++ ++colors; ++ } ++ while(--len); ++ } ++ ++ + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, +diff --git a/src/third_party/agg/include/agg_pixfmt_rgb_packed.h b/src/third_party/agg/include/agg_pixfmt_rgb_packed.h +index ec2fbd4..7868085 100644 +--- a/src/third_party/agg/include/agg_pixfmt_rgb_packed.h ++++ b/src/third_party/agg/include/agg_pixfmt_rgb_packed.h +@@ -829,28 +829,46 @@ namespace agg + public: + //-------------------------------------------------------------------- + pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {} ++ void attach(rbuf_type& rb) { m_rbuf = &rb; } ++ ++ //-------------------------------------------------------------------- ++ template ++ bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) ++ { ++ rect_i r(x1, y1, x2, y2); ++ if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) ++ { ++ int stride = pixf.stride(); ++ m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), ++ (r.x2 - r.x1) + 1, ++ (r.y2 - r.y1) + 1, ++ stride); ++ return true; ++ } ++ return false; ++ } ++ + Blender& blender() { return m_blender; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } ++ AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- +- const int8u* row_ptr(int y) const +- { +- return m_rbuf->row_ptr(y); +- } ++ AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } ++ AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } ++ AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- +- const int8u* pix_ptr(int x, int y) const ++ AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + +- //-------------------------------------------------------------------- +- row_data row(int x, int y) const ++ AGG_INLINE const int8u* pix_ptr(int x, int y) const + { +- return m_rbuf->row(y); ++ return m_rbuf->row_ptr(y) + x * pix_width; + } + + //-------------------------------------------------------------------- +@@ -1012,6 +1030,20 @@ namespace agg + while(--len); + } + ++ //-------------------------------------------------------------------- ++ void copy_color_vspan(int x, int y, ++ unsigned len, ++ const color_type* colors) ++ { ++ do ++ { ++ pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; ++ *p = m_blender.make_pix(colors->r, colors->g, colors->b); ++ ++colors; ++ } ++ while(--len); ++ } ++ + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, +diff --git a/src/third_party/agg/include/agg_pixfmt_rgba.h b/src/third_party/agg/include/agg_pixfmt_rgba.h +index ab454cd..20ec129 100644 +--- a/src/third_party/agg/include/agg_pixfmt_rgba.h ++++ b/src/third_party/agg/include/agg_pixfmt_rgba.h +@@ -614,12 +614,15 @@ namespace agg + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } +- calc_type s1a = base_mask - sa; +- calc_type d1a = base_mask - p[Order::A]; +- p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift); +- p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift); +- p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift); +- p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1))); ++ if(sa) ++ { ++ calc_type s1a = base_mask - sa; ++ calc_type d1a = base_mask - p[Order::A]; ++ p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift); ++ p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift); ++ p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift); ++ p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1))); ++ } + } + }; + +@@ -649,14 +652,17 @@ namespace agg + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } +- calc_type dr = p[Order::R] + sr; +- calc_type dg = p[Order::G] + sg; +- calc_type db = p[Order::B] + sb; +- calc_type da = p[Order::A] + sa; +- p[Order::R] = (dr > base_mask) ? base_mask : dr; +- p[Order::G] = (dg > base_mask) ? base_mask : dg; +- p[Order::B] = (db > base_mask) ? base_mask : db; +- p[Order::A] = (da > base_mask) ? base_mask : da; ++ if(sa) ++ { ++ calc_type dr = p[Order::R] + sr; ++ calc_type dg = p[Order::G] + sg; ++ calc_type db = p[Order::B] + sb; ++ calc_type da = p[Order::A] + sa; ++ p[Order::R] = (dr > base_mask) ? base_mask : dr; ++ p[Order::G] = (dg > base_mask) ? base_mask : dg; ++ p[Order::B] = (db > base_mask) ? base_mask : db; ++ p[Order::A] = (da > base_mask) ? base_mask : da; ++ } + } + }; + +@@ -686,13 +692,17 @@ namespace agg + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } +- calc_type dr = p[Order::R] - sr; +- calc_type dg = p[Order::G] - sg; +- calc_type db = p[Order::B] - sb; +- p[Order::R] = (dr > base_mask) ? 0 : dr; +- p[Order::G] = (dg > base_mask) ? 0 : dg; +- p[Order::B] = (db > base_mask) ? 0 : db; +- p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift)); ++ if(sa) ++ { ++ calc_type dr = p[Order::R] - sr; ++ calc_type dg = p[Order::G] - sg; ++ calc_type db = p[Order::B] - sb; ++ p[Order::R] = (dr > base_mask) ? 0 : dr; ++ p[Order::G] = (dg > base_mask) ? 0 : dg; ++ p[Order::B] = (db > base_mask) ? 0 : db; ++ p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); ++ //p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift)); ++ } + } + }; + +@@ -722,15 +732,18 @@ namespace agg + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } +- calc_type s1a = base_mask - sa; +- calc_type d1a = base_mask - p[Order::A]; +- calc_type dr = p[Order::R]; +- calc_type dg = p[Order::G]; +- calc_type db = p[Order::B]; +- p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift); +- p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift); +- p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift); +- p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); ++ if(sa) ++ { ++ calc_type s1a = base_mask - sa; ++ calc_type d1a = base_mask - p[Order::A]; ++ calc_type dr = p[Order::R]; ++ calc_type dg = p[Order::G]; ++ calc_type db = p[Order::B]; ++ p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift); ++ p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift); ++ p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift); ++ p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); ++ } + } + }; + +@@ -760,14 +773,17 @@ namespace agg + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } +- calc_type dr = p[Order::R]; +- calc_type dg = p[Order::G]; +- calc_type db = p[Order::B]; +- calc_type da = p[Order::A]; +- p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift)); +- p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift)); +- p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift)); +- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ if(sa) ++ { ++ calc_type dr = p[Order::R]; ++ calc_type dg = p[Order::G]; ++ calc_type db = p[Order::B]; ++ calc_type da = p[Order::A]; ++ p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift)); ++ p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift)); ++ p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift)); ++ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ } + } + }; + +@@ -801,27 +817,30 @@ namespace agg + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } +- calc_type d1a = base_mask - p[Order::A]; +- calc_type s1a = base_mask - sa; +- calc_type dr = p[Order::R]; +- calc_type dg = p[Order::G]; +- calc_type db = p[Order::B]; +- calc_type da = p[Order::A]; +- calc_type sada = sa * p[Order::A]; +- +- p[Order::R] = (value_type)(((2*dr < da) ? +- 2*sr*dr + sr*d1a + dr*s1a : +- sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a) >> base_shift); +- +- p[Order::G] = (value_type)(((2*dg < da) ? +- 2*sg*dg + sg*d1a + dg*s1a : +- sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a) >> base_shift); +- +- p[Order::B] = (value_type)(((2*db < da) ? +- 2*sb*db + sb*d1a + db*s1a : +- sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a) >> base_shift); +- +- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ if(sa) ++ { ++ calc_type d1a = base_mask - p[Order::A]; ++ calc_type s1a = base_mask - sa; ++ calc_type dr = p[Order::R]; ++ calc_type dg = p[Order::G]; ++ calc_type db = p[Order::B]; ++ calc_type da = p[Order::A]; ++ calc_type sada = sa * p[Order::A]; ++ ++ p[Order::R] = (value_type)(((2*dr < da) ? ++ 2*sr*dr + sr*d1a + dr*s1a : ++ sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); ++ ++ p[Order::G] = (value_type)(((2*dg < da) ? ++ 2*sg*dg + sg*d1a + dg*s1a : ++ sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); ++ ++ p[Order::B] = (value_type)(((2*db < da) ? ++ 2*sb*db + sb*d1a + db*s1a : ++ sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); ++ ++ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ } + } + }; + +@@ -855,17 +874,20 @@ namespace agg + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } +- calc_type d1a = base_mask - p[Order::A]; +- calc_type s1a = base_mask - sa; +- calc_type dr = p[Order::R]; +- calc_type dg = p[Order::G]; +- calc_type db = p[Order::B]; +- calc_type da = p[Order::A]; +- +- p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a) >> base_shift); +- p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a) >> base_shift); +- p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a) >> base_shift); +- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ if(sa) ++ { ++ calc_type d1a = base_mask - p[Order::A]; ++ calc_type s1a = base_mask - sa; ++ calc_type dr = p[Order::R]; ++ calc_type dg = p[Order::G]; ++ calc_type db = p[Order::B]; ++ calc_type da = p[Order::A]; ++ ++ p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); ++ p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); ++ p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); ++ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ } + } + }; + +@@ -895,17 +917,20 @@ namespace agg + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } +- calc_type d1a = base_mask - p[Order::A]; +- calc_type s1a = base_mask - sa; +- calc_type dr = p[Order::R]; +- calc_type dg = p[Order::G]; +- calc_type db = p[Order::B]; +- calc_type da = p[Order::A]; +- +- p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a) >> base_shift); +- p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a) >> base_shift); +- p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a) >> base_shift); +- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ if(sa) ++ { ++ calc_type d1a = base_mask - p[Order::A]; ++ calc_type s1a = base_mask - sa; ++ calc_type dr = p[Order::R]; ++ calc_type dg = p[Order::G]; ++ calc_type db = p[Order::B]; ++ calc_type da = p[Order::A]; ++ ++ p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); ++ p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); ++ p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); ++ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ } + } + }; + +@@ -940,33 +965,36 @@ namespace agg + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } +- calc_type d1a = base_mask - p[Order::A]; +- calc_type s1a = base_mask - sa; +- calc_type dr = p[Order::R]; +- calc_type dg = p[Order::G]; +- calc_type db = p[Order::B]; +- calc_type da = p[Order::A]; +- long_type drsa = dr * sa; +- long_type dgsa = dg * sa; +- long_type dbsa = db * sa; +- long_type srda = sr * da; +- long_type sgda = sg * da; +- long_type sbda = sb * da; +- long_type sada = sa * da; +- +- p[Order::R] = (value_type)((srda + drsa >= sada) ? +- (sada + sr * d1a + dr * s1a) >> base_shift : +- drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a) >> base_shift)); +- +- p[Order::G] = (value_type)((sgda + dgsa >= sada) ? +- (sada + sg * d1a + dg * s1a) >> base_shift : +- dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a) >> base_shift)); +- +- p[Order::B] = (value_type)((sbda + dbsa >= sada) ? +- (sada + sb * d1a + db * s1a) >> base_shift : +- dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a) >> base_shift)); +- +- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ if(sa) ++ { ++ calc_type d1a = base_mask - p[Order::A]; ++ calc_type s1a = base_mask - sa; ++ calc_type dr = p[Order::R]; ++ calc_type dg = p[Order::G]; ++ calc_type db = p[Order::B]; ++ calc_type da = p[Order::A]; ++ long_type drsa = dr * sa; ++ long_type dgsa = dg * sa; ++ long_type dbsa = db * sa; ++ long_type srda = sr * da; ++ long_type sgda = sg * da; ++ long_type sbda = sb * da; ++ long_type sada = sa * da; ++ ++ p[Order::R] = (value_type)((srda + drsa >= sada) ? ++ (sada + sr * d1a + dr * s1a + base_mask) >> base_shift : ++ drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift)); ++ ++ p[Order::G] = (value_type)((sgda + dgsa >= sada) ? ++ (sada + sg * d1a + dg * s1a + base_mask) >> base_shift : ++ dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift)); ++ ++ p[Order::B] = (value_type)((sbda + dbsa >= sada) ? ++ (sada + sb * d1a + db * s1a + base_mask) >> base_shift : ++ dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift)); ++ ++ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ } + } + }; + +@@ -1001,33 +1029,36 @@ namespace agg + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } +- calc_type d1a = base_mask - p[Order::A]; +- calc_type s1a = base_mask - sa; +- calc_type dr = p[Order::R]; +- calc_type dg = p[Order::G]; +- calc_type db = p[Order::B]; +- calc_type da = p[Order::A]; +- long_type drsa = dr * sa; +- long_type dgsa = dg * sa; +- long_type dbsa = db * sa; +- long_type srda = sr * da; +- long_type sgda = sg * da; +- long_type sbda = sb * da; +- long_type sada = sa * da; +- +- p[Order::R] = (value_type)(((srda + drsa <= sada) ? +- sr * d1a + dr * s1a : +- sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a) >> base_shift); +- +- p[Order::G] = (value_type)(((sgda + dgsa <= sada) ? +- sg * d1a + dg * s1a : +- sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a) >> base_shift); +- +- p[Order::B] = (value_type)(((sbda + dbsa <= sada) ? +- sb * d1a + db * s1a : +- sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a) >> base_shift); +- +- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ if(sa) ++ { ++ calc_type d1a = base_mask - p[Order::A]; ++ calc_type s1a = base_mask - sa; ++ calc_type dr = p[Order::R]; ++ calc_type dg = p[Order::G]; ++ calc_type db = p[Order::B]; ++ calc_type da = p[Order::A]; ++ long_type drsa = dr * sa; ++ long_type dgsa = dg * sa; ++ long_type dbsa = db * sa; ++ long_type srda = sr * da; ++ long_type sgda = sg * da; ++ long_type sbda = sb * da; ++ long_type sada = sa * da; ++ ++ p[Order::R] = (value_type)(((srda + drsa <= sada) ? ++ sr * d1a + dr * s1a : ++ sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask) >> base_shift); ++ ++ p[Order::G] = (value_type)(((sgda + dgsa <= sada) ? ++ sg * d1a + dg * s1a : ++ sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask) >> base_shift); ++ ++ p[Order::B] = (value_type)(((sbda + dbsa <= sada) ? ++ sb * d1a + db * s1a : ++ sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask) >> base_shift); ++ ++ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ } + } + }; + +@@ -1062,27 +1093,30 @@ namespace agg + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } +- calc_type d1a = base_mask - p[Order::A]; +- calc_type s1a = base_mask - sa; +- calc_type dr = p[Order::R]; +- calc_type dg = p[Order::G]; +- calc_type db = p[Order::B]; +- calc_type da = p[Order::A]; +- calc_type sada = sa * da; +- +- p[Order::R] = (value_type)(((2*sr < sa) ? +- 2*sr*dr + sr*d1a + dr*s1a : +- sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a) >> base_shift); +- +- p[Order::G] = (value_type)(((2*sg < sa) ? +- 2*sg*dg + sg*d1a + dg*s1a : +- sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a) >> base_shift); +- +- p[Order::B] = (value_type)(((2*sb < sa) ? +- 2*sb*db + sb*d1a + db*s1a : +- sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a) >> base_shift); +- +- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ if(sa) ++ { ++ calc_type d1a = base_mask - p[Order::A]; ++ calc_type s1a = base_mask - sa; ++ calc_type dr = p[Order::R]; ++ calc_type dg = p[Order::G]; ++ calc_type db = p[Order::B]; ++ calc_type da = p[Order::A]; ++ calc_type sada = sa * da; ++ ++ p[Order::R] = (value_type)(((2*sr < sa) ? ++ 2*sr*dr + sr*d1a + dr*s1a : ++ sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); ++ ++ p[Order::G] = (value_type)(((2*sg < sa) ? ++ 2*sg*dg + sg*d1a + dg*s1a : ++ sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); ++ ++ p[Order::B] = (value_type)(((2*sb < sa) ? ++ 2*sb*db + sb*d1a + db*s1a : ++ sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); ++ ++ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ } + } + }; + +@@ -1117,31 +1151,34 @@ namespace agg + double sg = double(g * cover) / (base_mask * 255); + double sb = double(b * cover) / (base_mask * 255); + double sa = double(a * cover) / (base_mask * 255); +- double dr = double(p[Order::R]) / base_mask; +- double dg = double(p[Order::G]) / base_mask; +- double db = double(p[Order::B]) / base_mask; +- double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask; +- if(cover < 255) ++ if(sa > 0) + { +- a = (a * cover + 255) >> 8; +- } ++ double dr = double(p[Order::R]) / base_mask; ++ double dg = double(p[Order::G]) / base_mask; ++ double db = double(p[Order::B]) / base_mask; ++ double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask; ++ if(cover < 255) ++ { ++ a = (a * cover + 255) >> 8; ++ } + +- if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); +- else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa); +- else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); ++ if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); ++ else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa); ++ else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); + +- if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); +- else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa); +- else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); ++ if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); ++ else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa); ++ else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); + +- if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); +- else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa); +- else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); ++ if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); ++ else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa); ++ else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); + +- p[Order::R] = (value_type)uround(dr * base_mask); +- p[Order::G] = (value_type)uround(dg * base_mask); +- p[Order::B] = (value_type)uround(db * base_mask); +- p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift)); ++ p[Order::R] = (value_type)uround(dr * base_mask); ++ p[Order::G] = (value_type)uround(dg * base_mask); ++ p[Order::B] = (value_type)uround(db * base_mask); ++ p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift)); ++ } + } + }; + +@@ -1156,6 +1193,7 @@ namespace agg + enum base_scale_e + { + base_shift = color_type::base_shift, ++ base_scale = color_type::base_scale, + base_mask = color_type::base_mask + }; + +@@ -1172,14 +1210,17 @@ namespace agg + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } +- calc_type dr = p[Order::R]; +- calc_type dg = p[Order::G]; +- calc_type db = p[Order::B]; +- calc_type da = p[Order::A]; +- p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa)) >> base_shift)); +- p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa)) >> base_shift)); +- p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa)) >> base_shift)); +- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ if(sa) ++ { ++ calc_type dr = p[Order::R]; ++ calc_type dg = p[Order::G]; ++ calc_type db = p[Order::B]; ++ calc_type da = p[Order::A]; ++ p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift)); ++ p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift)); ++ p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift)); ++ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ } + } + }; + +@@ -1210,16 +1251,19 @@ namespace agg + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } +- calc_type d1a = base_mask - p[Order::A]; +- calc_type s1a = base_mask - sa; +- calc_type dr = p[Order::R]; +- calc_type dg = p[Order::G]; +- calc_type db = p[Order::B]; +- calc_type da = p[Order::A]; +- p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a) >> base_shift); +- p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a) >> base_shift); +- p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a) >> base_shift); +- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ if(sa) ++ { ++ calc_type d1a = base_mask - p[Order::A]; ++ calc_type s1a = base_mask - sa; ++ calc_type dr = p[Order::R]; ++ calc_type dg = p[Order::G]; ++ calc_type db = p[Order::B]; ++ calc_type da = p[Order::A]; ++ p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift); ++ p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift); ++ p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift); ++ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ } + } + }; + +@@ -1270,11 +1314,83 @@ namespace agg + } + }; + ++ //=====================================================comp_op_rgba_invert ++ template struct comp_op_rgba_invert ++ { ++ typedef ColorT color_type; ++ typedef Order order_type; ++ typedef typename color_type::value_type value_type; ++ typedef typename color_type::calc_type calc_type; ++ typedef typename color_type::long_type long_type; ++ enum base_scale_e ++ { ++ base_shift = color_type::base_shift, ++ base_mask = color_type::base_mask ++ }; + ++ // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa) ++ // Da' = Sa + Da - Sa.Da ++ static AGG_INLINE void blend_pix(value_type* p, ++ unsigned sr, unsigned sg, unsigned sb, ++ unsigned sa, unsigned cover) ++ { ++ sa = (sa * cover + 255) >> 8; ++ if(sa) ++ { ++ calc_type da = p[Order::A]; ++ calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift; ++ calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift; ++ calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift; ++ calc_type s1a = base_mask - sa; ++ p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); ++ p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); ++ p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); ++ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ } ++ } ++ }; + ++ //=================================================comp_op_rgba_invert_rgb ++ template struct comp_op_rgba_invert_rgb ++ { ++ typedef ColorT color_type; ++ typedef Order order_type; ++ typedef typename color_type::value_type value_type; ++ typedef typename color_type::calc_type calc_type; ++ typedef typename color_type::long_type long_type; ++ enum base_scale_e ++ { ++ base_shift = color_type::base_shift, ++ base_mask = color_type::base_mask ++ }; + +- +- ++ // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa) ++ // Da' = Sa + Da - Sa.Da ++ static AGG_INLINE void blend_pix(value_type* p, ++ unsigned sr, unsigned sg, unsigned sb, ++ unsigned sa, unsigned cover) ++ { ++ if(cover < 255) ++ { ++ sr = (sr * cover + 255) >> 8; ++ sg = (sg * cover + 255) >> 8; ++ sb = (sb * cover + 255) >> 8; ++ sa = (sa * cover + 255) >> 8; ++ } ++ if(sa) ++ { ++ calc_type da = p[Order::A]; ++ calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift; ++ calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift; ++ calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift; ++ calc_type s1a = base_mask - sa; ++ p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); ++ p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); ++ p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); ++ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ } ++ } ++ }; + + + +@@ -1324,6 +1440,8 @@ namespace agg + comp_op_rgba_difference ::blend_pix, + comp_op_rgba_exclusion ::blend_pix, + comp_op_rgba_contrast ::blend_pix, ++ comp_op_rgba_invert ::blend_pix, ++ comp_op_rgba_invert_rgb ::blend_pix, + 0 + }; + +@@ -1357,6 +1475,8 @@ namespace agg + comp_op_difference, //----comp_op_difference + comp_op_exclusion, //----comp_op_exclusion + comp_op_contrast, //----comp_op_contrast ++ comp_op_invert, //----comp_op_invert ++ comp_op_invert_rgb, //----comp_op_invert_rgb + + end_of_comp_op_e + }; +@@ -1655,28 +1775,45 @@ namespace agg + pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + ++ //-------------------------------------------------------------------- ++ template ++ bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) ++ { ++ rect_i r(x1, y1, x2, y2); ++ if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) ++ { ++ int stride = pixf.stride(); ++ m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), ++ (r.x2 - r.x1) + 1, ++ (r.y2 - r.y1) + 1, ++ stride); ++ return true; ++ } ++ return false; ++ } ++ + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } ++ AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- +- const int8u* row_ptr(int y) const +- { +- return m_rbuf->row_ptr(y); +- } ++ AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } ++ AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } ++ AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- +- const int8u* pix_ptr(int x, int y) const ++ AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + +- //-------------------------------------------------------------------- +- row_data row(int y) const ++ AGG_INLINE const int8u* pix_ptr(int x, int y) const + { +- return m_rbuf->row(y); ++ return m_rbuf->row_ptr(y) + x * pix_width; + } + ++ + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { +@@ -1828,8 +1965,8 @@ namespace agg + ((value_type*)&v)[order_type::A] = c.a; + do + { ++ p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + *(pixel_type*)p = v; +- p = (value_type*)m_rbuf->next_row(p); + } + while(--len); + } +@@ -1938,6 +2075,24 @@ namespace agg + } + + ++ //-------------------------------------------------------------------- ++ void copy_color_vspan(int x, int y, ++ unsigned len, ++ const color_type* colors) ++ { ++ do ++ { ++ value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); ++ p[order_type::R] = colors->r; ++ p[order_type::G] = colors->g; ++ p[order_type::B] = colors->b; ++ p[order_type::A] = colors->a; ++ ++colors; ++ } ++ while(--len); ++ } ++ ++ + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, +@@ -2206,31 +2361,47 @@ namespace agg + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- +- unsigned width() const { return m_rbuf->width(); } +- unsigned height() const { return m_rbuf->height(); } ++ template ++ bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) ++ { ++ rect_i r(x1, y1, x2, y2); ++ if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) ++ { ++ int stride = pixf.stride(); ++ m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), ++ (r.x2 - r.x1) + 1, ++ (r.y2 - r.y1) + 1, ++ stride); ++ return true; ++ } ++ return false; ++ } + + //-------------------------------------------------------------------- +- void comp_op(unsigned op) { m_comp_op = op; } +- unsigned comp_op() const { return m_comp_op; } ++ AGG_INLINE unsigned width() const { return m_rbuf->width(); } ++ AGG_INLINE unsigned height() const { return m_rbuf->height(); } ++ AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- +- const int8u* row_ptr(int y) const +- { +- return m_rbuf->row_ptr(y); +- } ++ AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } ++ AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } ++ AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- +- const int8u* pix_ptr(int x, int y) const ++ AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + +- //-------------------------------------------------------------------- +- row_data row(int x, int y) const ++ AGG_INLINE const int8u* pix_ptr(int x, int y) const + { +- return m_rbuf->row(y); ++ return m_rbuf->row_ptr(y) + x * pix_width; + } + ++ //-------------------------------------------------------------------- ++ void comp_op(unsigned op) { m_comp_op = op; } ++ unsigned comp_op() const { return m_comp_op; } ++ + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { +@@ -2373,6 +2544,23 @@ namespace agg + while(--len); + } + ++ //-------------------------------------------------------------------- ++ void copy_color_vspan(int x, int y, ++ unsigned len, ++ const color_type* colors) ++ { ++ do ++ { ++ value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); ++ p[order_type::R] = colors->r; ++ p[order_type::G] = colors->g; ++ p[order_type::B] = colors->b; ++ p[order_type::A] = colors->a; ++ ++colors; ++ } ++ while(--len); ++ } ++ + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, unsigned len, + const color_type* colors, +diff --git a/src/third_party/agg/include/agg_pixfmt_transposer.h b/src/third_party/agg/include/agg_pixfmt_transposer.h +new file mode 100644 +index 0000000..723da7b +--- /dev/null ++++ b/src/third_party/agg/include/agg_pixfmt_transposer.h +@@ -0,0 +1,157 @@ ++//---------------------------------------------------------------------------- ++// Anti-Grain Geometry - Version 2.4 ++// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) ++// ++// Permission to copy, use, modify, sell and distribute this software ++// is granted provided this copyright notice appears in all copies. ++// This software is provided "as is" without express or implied ++// warranty, and with no claim as to its suitability for any purpose. ++// ++//---------------------------------------------------------------------------- ++// Contact: mcseem@antigrain.com ++// mcseemagg@yahoo.com ++// http://www.antigrain.com ++//---------------------------------------------------------------------------- ++ ++#ifndef AGG_PIXFMT_TRANSPOSER_INCLUDED ++#define AGG_PIXFMT_TRANSPOSER_INCLUDED ++ ++#include "agg_basics.h" ++ ++namespace agg ++{ ++ //=======================================================pixfmt_transposer ++ template class pixfmt_transposer ++ { ++ public: ++ typedef PixFmt pixfmt_type; ++ typedef typename pixfmt_type::color_type color_type; ++ typedef typename pixfmt_type::row_data row_data; ++ typedef typename color_type::value_type value_type; ++ typedef typename color_type::calc_type calc_type; ++ ++ //-------------------------------------------------------------------- ++ pixfmt_transposer() : m_pixf(0) {} ++ pixfmt_transposer(pixfmt_type& pixf) : m_pixf(&pixf) {} ++ void attach(pixfmt_type& pixf) { m_pixf = &pixf; } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE unsigned width() const { return m_pixf->height(); } ++ AGG_INLINE unsigned height() const { return m_pixf->width(); } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE color_type pixel(int x, int y) const ++ { ++ return m_pixf->pixel(y, x); ++ } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE void copy_pixel(int x, int y, const color_type& c) ++ { ++ m_pixf->copy_pixel(y, x, c); ++ } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE void blend_pixel(int x, int y, ++ const color_type& c, ++ int8u cover) ++ { ++ m_pixf->blend_pixel(y, x, c, cover); ++ } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE void copy_hline(int x, int y, ++ unsigned len, ++ const color_type& c) ++ { ++ m_pixf->copy_vline(y, x, len, c); ++ } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE void copy_vline(int x, int y, ++ unsigned len, ++ const color_type& c) ++ { ++ m_pixf->copy_hline(y, x, len, c); ++ } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE void blend_hline(int x, int y, ++ unsigned len, ++ const color_type& c, ++ int8u cover) ++ { ++ m_pixf->blend_vline(y, x, len, c, cover); ++ } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE void blend_vline(int x, int y, ++ unsigned len, ++ const color_type& c, ++ int8u cover) ++ { ++ m_pixf->blend_hline(y, x, len, c, cover); ++ } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE void blend_solid_hspan(int x, int y, ++ unsigned len, ++ const color_type& c, ++ const int8u* covers) ++ { ++ m_pixf->blend_solid_vspan(y, x, len, c, covers); ++ } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE void blend_solid_vspan(int x, int y, ++ unsigned len, ++ const color_type& c, ++ const int8u* covers) ++ { ++ m_pixf->blend_solid_hspan(y, x, len, c, covers); ++ } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE void copy_color_hspan(int x, int y, ++ unsigned len, ++ const color_type* colors) ++ { ++ m_pixf->copy_color_vspan(y, x, len, colors); ++ } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE void copy_color_vspan(int x, int y, ++ unsigned len, ++ const color_type* colors) ++ { ++ m_pixf->copy_color_hspan(y, x, len, colors); ++ } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE void blend_color_hspan(int x, int y, ++ unsigned len, ++ const color_type* colors, ++ const int8u* covers, ++ int8u cover) ++ { ++ m_pixf->blend_color_vspan(y, x, len, colors, covers, cover); ++ } ++ ++ //-------------------------------------------------------------------- ++ AGG_INLINE void blend_color_vspan(int x, int y, ++ unsigned len, ++ const color_type* colors, ++ const int8u* covers, ++ int8u cover) ++ { ++ m_pixf->blend_color_hspan(y, x, len, colors, covers, cover); ++ } ++ ++ private: ++ pixfmt_type* m_pixf; ++ }; ++} ++ ++#endif ++ ++ +diff --git a/src/third_party/agg/include/agg_rasterizer_cells_aa.h b/src/third_party/agg/include/agg_rasterizer_cells_aa.h +old mode 100755 +new mode 100644 +index 5455e55..59ffd77 +--- a/src/third_party/agg/include/agg_rasterizer_cells_aa.h ++++ b/src/third_party/agg/include/agg_rasterizer_cells_aa.h +@@ -103,21 +103,21 @@ namespace agg + void allocate_block(); + + private: +- unsigned m_num_blocks; +- unsigned m_max_blocks; +- unsigned m_curr_block; +- unsigned m_num_cells; +- cell_type** m_cells; +- cell_type* m_curr_cell_ptr; +- pod_vector m_sorted_cells; +- pod_vector m_sorted_y; +- cell_type m_curr_cell; +- cell_type m_style_cell; +- int m_min_x; +- int m_min_y; +- int m_max_x; +- int m_max_y; +- bool m_sorted; ++ unsigned m_num_blocks; ++ unsigned m_max_blocks; ++ unsigned m_curr_block; ++ unsigned m_num_cells; ++ cell_type** m_cells; ++ cell_type* m_curr_cell_ptr; ++ pod_vector m_sorted_cells; ++ pod_vector m_sorted_y; ++ cell_type m_curr_cell; ++ cell_type m_style_cell; ++ int m_min_x; ++ int m_min_y; ++ int m_max_x; ++ int m_max_y; ++ bool m_sorted; + }; + + +@@ -132,10 +132,10 @@ namespace agg + cell_type** ptr = m_cells + m_num_blocks - 1; + while(m_num_blocks--) + { +- delete [] *ptr; ++ pod_allocator::deallocate(*ptr, cell_block_size); + ptr--; + } +- delete [] m_cells; ++ pod_allocator::deallocate(m_cells, m_max_blocks); + } + } + +@@ -188,10 +188,6 @@ namespace agg + } + *m_curr_cell_ptr++ = m_curr_cell; + ++m_num_cells; +- //if(m_curr_cell.x < m_min_x) m_min_x = m_curr_cell.x; +- //if(m_curr_cell.x > m_max_x) m_max_x = m_curr_cell.x; +- //if(m_curr_cell.y < m_min_y) m_min_y = m_curr_cell.y; +- //if(m_curr_cell.y > m_max_y) m_max_y = m_curr_cell.y; + } + } + +@@ -474,16 +470,22 @@ namespace agg + { + if(m_num_blocks >= m_max_blocks) + { +- cell_type** new_cells = new cell_type* [m_max_blocks + cell_block_pool]; ++ cell_type** new_cells = ++ pod_allocator::allocate(m_max_blocks + ++ cell_block_pool); ++ + if(m_cells) + { + memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*)); +- delete [] m_cells; ++ pod_allocator::deallocate(m_cells, m_max_blocks); + } + m_cells = new_cells; + m_max_blocks += cell_block_pool; + } +- m_cells[m_num_blocks++] = new cell_type [unsigned(cell_block_size)]; ++ ++ m_cells[m_num_blocks++] = ++ pod_allocator::allocate(cell_block_size); ++ + } + m_curr_cell_ptr = m_cells[m_curr_block++]; + } +@@ -721,6 +723,33 @@ namespace agg + m_sorted = true; + } + ++ ++ ++ //------------------------------------------------------scanline_hit_test ++ class scanline_hit_test ++ { ++ public: ++ scanline_hit_test(int x) : m_x(x), m_hit(false) {} ++ ++ void reset_spans() {} ++ void finalize(int) {} ++ void add_cell(int x, int) ++ { ++ if(m_x == x) m_hit = true; ++ } ++ void add_span(int x, int len, int) ++ { ++ if(m_x >= x && m_x < x+len) m_hit = true; ++ } ++ unsigned num_spans() const { return 1; } ++ bool hit() const { return m_hit; } ++ ++ private: ++ int m_x; ++ bool m_hit; ++ }; ++ ++ + } + + #endif +diff --git a/src/third_party/agg/include/agg_rasterizer_compound_aa.h b/src/third_party/agg/include/agg_rasterizer_compound_aa.h +old mode 100755 +new mode 100644 +index c6c69e2..8547747 +--- a/src/third_party/agg/include/agg_rasterizer_compound_aa.h ++++ b/src/third_party/agg/include/agg_rasterizer_compound_aa.h +@@ -86,33 +86,45 @@ namespace agg + }; + + public: +- typedef Clip clip_type; +- typedef typename Clip::conv_type conv_type; ++ typedef Clip clip_type; ++ typedef typename Clip::conv_type conv_type; ++ typedef typename Clip::coord_type coord_type; + + enum aa_scale_e + { + aa_shift = 8, + aa_scale = 1 << aa_shift, +- aa_mask = aa_scale - 1 ++ aa_mask = aa_scale - 1, ++ aa_scale2 = aa_scale * 2, ++ aa_mask2 = aa_scale2 - 1 + }; + + //-------------------------------------------------------------------- + rasterizer_compound_aa() : + m_outline(), + m_clipper(), ++ m_filling_rule(fill_non_zero), + m_styles(), // Active Styles + m_ast(), // Active Style Table (unique values) + m_asm(), // Active Style Mask + m_cells(), ++ m_cover_buf(), ++ m_master_alpha(), + m_min_style(0x7FFFFFFF), + m_max_style(-0x7FFFFFFF), +- m_scan_y(0x7FFFFFFF) ++ m_start_x(0), ++ m_start_y(0), ++ m_scan_y(0x7FFFFFFF), ++ m_sl_start(0), ++ m_sl_len(0) + {} + + //-------------------------------------------------------------------- + void reset(); + void reset_clipping(); + void clip_box(double x1, double y1, double x2, double y2); ++ void filling_rule(filling_rule_e filling_rule); ++ void master_alpha(int style, double alpha); + + //-------------------------------------------------------------------- + void styles(int left, int right); +@@ -154,15 +166,31 @@ namespace agg + void sort(); + bool rewind_scanlines(); + unsigned sweep_styles(); ++ int scanline_start() const { return m_sl_start; } ++ unsigned scanline_length() const { return m_sl_len; } + unsigned style(unsigned style_idx) const; + ++ cover_type* allocate_cover_buffer(unsigned len); ++ ++ //-------------------------------------------------------------------- ++ bool navigate_scanline(int y); ++ bool hit_test(int tx, int ty); ++ + //-------------------------------------------------------------------- +- AGG_INLINE unsigned calculate_alpha(int area) const ++ AGG_INLINE unsigned calculate_alpha(int area, unsigned master_alpha) const + { + int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); + if(cover < 0) cover = -cover; ++ if(m_filling_rule == fill_even_odd) ++ { ++ cover &= aa_mask2; ++ if(cover > aa_scale) ++ { ++ cover = aa_scale2 - cover; ++ } ++ } + if(cover > aa_mask) cover = aa_mask; +- return cover; ++ return (cover * master_alpha + aa_mask) >> aa_shift; + } + + //-------------------------------------------------------------------- +@@ -175,8 +203,17 @@ namespace agg + + sl.reset_spans(); + +- if(style_idx < 0) style_idx = 0; +- else style_idx++; ++ unsigned master_alpha = aa_mask; ++ ++ if(style_idx < 0) ++ { ++ style_idx = 0; ++ } ++ else ++ { ++ style_idx++; ++ master_alpha = m_master_alpha[m_ast[style_idx] + m_min_style - 1]; ++ } + + const style_info& st = m_styles[m_ast[style_idx]]; + +@@ -196,14 +233,16 @@ namespace agg + + if(area) + { +- alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area); ++ alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area, ++ master_alpha); + sl.add_cell(x, alpha); + x++; + } + + if(num_cells && cell->x > x) + { +- alpha = calculate_alpha(cover << (poly_subpixel_shift + 1)); ++ alpha = calculate_alpha(cover << (poly_subpixel_shift + 1), ++ master_alpha); + if(alpha) + { + sl.add_span(x, cell->x - x, alpha); +@@ -214,11 +253,11 @@ namespace agg + if(sl.num_spans() == 0) return false; + sl.finalize(scan_y); + return true; +- + } + + private: + void add_style(int style_id); ++ void allocate_master_alpha(); + + //-------------------------------------------------------------------- + // Disable copying +@@ -229,14 +268,21 @@ namespace agg + private: + rasterizer_cells_aa m_outline; + clip_type m_clipper; ++ filling_rule_e m_filling_rule; + pod_vector m_styles; // Active Styles + pod_vector m_ast; // Active Style Table (unique values) + pod_vector m_asm; // Active Style Mask + pod_vector m_cells; +- +- int m_min_style; +- int m_max_style; +- int m_scan_y; ++ pod_vector m_cover_buf; ++ pod_bvector m_master_alpha; ++ ++ int m_min_style; ++ int m_max_style; ++ coord_type m_start_x; ++ coord_type m_start_y; ++ int m_scan_y; ++ int m_sl_start; ++ unsigned m_sl_len; + }; + + +@@ -256,6 +302,15 @@ namespace agg + m_min_style = 0x7FFFFFFF; + m_max_style = -0x7FFFFFFF; + m_scan_y = 0x7FFFFFFF; ++ m_sl_start = 0; ++ m_sl_len = 0; ++ } ++ ++ //------------------------------------------------------------------------ ++ template ++ void rasterizer_compound_aa::filling_rule(filling_rule_e filling_rule) ++ { ++ m_filling_rule = filling_rule; + } + + //------------------------------------------------------------------------ +@@ -296,7 +351,8 @@ namespace agg + void rasterizer_compound_aa::move_to(int x, int y) + { + if(m_outline.sorted()) reset(); +- m_clipper.move_to(conv_type::downscale(x), conv_type::downscale(y)); ++ m_clipper.move_to(m_start_x = conv_type::downscale(x), ++ m_start_y = conv_type::downscale(y)); + } + + //------------------------------------------------------------------------ +@@ -313,7 +369,8 @@ namespace agg + void rasterizer_compound_aa::move_to_d(double x, double y) + { + if(m_outline.sorted()) reset(); +- m_clipper.move_to(conv_type::upscale(x), conv_type::upscale(y)); ++ m_clipper.move_to(m_start_x = conv_type::upscale(x), ++ m_start_y = conv_type::upscale(y)); + } + + //------------------------------------------------------------------------ +@@ -334,11 +391,14 @@ namespace agg + move_to_d(x, y); + } + else ++ if(is_vertex(cmd)) + { +- if(is_vertex(cmd)) +- { +- line_to_d(x, y); +- } ++ line_to_d(x, y); ++ } ++ else ++ if(is_close(cmd)) ++ { ++ m_clipper.line_to(m_outline, m_start_x, m_start_y); + } + } + +@@ -387,6 +447,7 @@ namespace agg + } + m_scan_y = m_outline.min_y(); + m_styles.allocate(m_max_style - m_min_style + 2, 128); ++ allocate_master_alpha(); + return true; + } + +@@ -433,83 +494,92 @@ namespace agg + m_asm.allocate((num_styles + 7) >> 3, 8); + m_asm.zero(); + +- // Pre-add zero (for no-fill style, that is, -1). +- // We need that to ensure that the "-1 style" would go first. +- m_asm[0] |= 1; +- m_ast.add(0); +- style = &m_styles[0]; +- style->start_cell = 0; +- style->num_cells = 0; +- style->last_x = -0x7FFFFFFF; +- +- while(num_cells--) ++ if(num_cells) + { +- curr_cell = *cells++; +- add_style(curr_cell->left); +- add_style(curr_cell->right); +- } +- +- // Convert the Y-histogram into the array of starting indexes +- unsigned i; +- unsigned start_cell = 0; +- for(i = 0; i < m_ast.size(); i++) +- { +- style_info& st = m_styles[m_ast[i]]; +- unsigned v = st.start_cell; +- st.start_cell = start_cell; +- start_cell += v; +- } +- +- cells = m_outline.scanline_cells(m_scan_y); +- num_cells = m_outline.scanline_num_cells(m_scan_y); +- +- while(num_cells--) +- { +- curr_cell = *cells++; +- style_id = (curr_cell->left < 0) ? 0 : +- curr_cell->left - m_min_style + 1; +- +- style = &m_styles[style_id]; +- if(curr_cell->x == style->last_x) ++ // Pre-add zero (for no-fill style, that is, -1). ++ // We need that to ensure that the "-1 style" would go first. ++ m_asm[0] |= 1; ++ m_ast.add(0); ++ style = &m_styles[0]; ++ style->start_cell = 0; ++ style->num_cells = 0; ++ style->last_x = -0x7FFFFFFF; ++ ++ m_sl_start = cells[0]->x; ++ m_sl_len = cells[num_cells-1]->x - m_sl_start + 1; ++ while(num_cells--) + { +- cell = &m_cells[style->start_cell + style->num_cells - 1]; +- cell->area += curr_cell->area; +- cell->cover += curr_cell->cover; ++ curr_cell = *cells++; ++ add_style(curr_cell->left); ++ add_style(curr_cell->right); + } +- else ++ ++ // Convert the Y-histogram into the array of starting indexes ++ unsigned i; ++ unsigned start_cell = 0; ++ for(i = 0; i < m_ast.size(); i++) + { +- cell = &m_cells[style->start_cell + style->num_cells]; +- cell->x = curr_cell->x; +- cell->area = curr_cell->area; +- cell->cover = curr_cell->cover; +- style->last_x = curr_cell->x; +- style->num_cells++; ++ style_info& st = m_styles[m_ast[i]]; ++ unsigned v = st.start_cell; ++ st.start_cell = start_cell; ++ start_cell += v; + } + +- style_id = (curr_cell->right < 0) ? 0 : +- curr_cell->right - m_min_style + 1; ++ cells = m_outline.scanline_cells(m_scan_y); ++ num_cells = m_outline.scanline_num_cells(m_scan_y); + +- style = &m_styles[style_id]; +- if(curr_cell->x == style->last_x) ++ while(num_cells--) + { +- cell = &m_cells[style->start_cell + style->num_cells - 1]; +- cell->area -= curr_cell->area; +- cell->cover -= curr_cell->cover; +- } +- else +- { +- cell = &m_cells[style->start_cell + style->num_cells]; +- cell->x = curr_cell->x; +- cell->area = -curr_cell->area; +- cell->cover = -curr_cell->cover; +- style->last_x = curr_cell->x; +- style->num_cells++; ++ curr_cell = *cells++; ++ style_id = (curr_cell->left < 0) ? 0 : ++ curr_cell->left - m_min_style + 1; ++ ++ style = &m_styles[style_id]; ++ if(curr_cell->x == style->last_x) ++ { ++ cell = &m_cells[style->start_cell + style->num_cells - 1]; ++ cell->area += curr_cell->area; ++ cell->cover += curr_cell->cover; ++ } ++ else ++ { ++ cell = &m_cells[style->start_cell + style->num_cells]; ++ cell->x = curr_cell->x; ++ cell->area = curr_cell->area; ++ cell->cover = curr_cell->cover; ++ style->last_x = curr_cell->x; ++ style->num_cells++; ++ } ++ ++ style_id = (curr_cell->right < 0) ? 0 : ++ curr_cell->right - m_min_style + 1; ++ ++ style = &m_styles[style_id]; ++ if(curr_cell->x == style->last_x) ++ { ++ cell = &m_cells[style->start_cell + style->num_cells - 1]; ++ cell->area -= curr_cell->area; ++ cell->cover -= curr_cell->cover; ++ } ++ else ++ { ++ cell = &m_cells[style->start_cell + style->num_cells]; ++ cell->x = curr_cell->x; ++ cell->area = -curr_cell->area; ++ cell->cover = -curr_cell->cover; ++ style->last_x = curr_cell->x; ++ style->num_cells++; ++ } + } + } + if(m_ast.size() > 1) break; + ++m_scan_y; + } + ++m_scan_y; ++ ++ range_adaptor > ra(m_ast, 1, m_ast.size() - 1); ++ quick_sort(ra, unsigned_greater); ++ + return m_ast.size() - 1; + } + +@@ -522,6 +592,80 @@ namespace agg + return m_ast[style_idx + 1] + m_min_style - 1; + } + ++ //------------------------------------------------------------------------ ++ template ++ AGG_INLINE bool rasterizer_compound_aa::navigate_scanline(int y) ++ { ++ m_outline.sort_cells(); ++ if(m_outline.total_cells() == 0) ++ { ++ return false; ++ } ++ if(m_max_style < m_min_style) ++ { ++ return false; ++ } ++ if(y < m_outline.min_y() || y > m_outline.max_y()) ++ { ++ return false; ++ } ++ m_scan_y = y; ++ m_styles.allocate(m_max_style - m_min_style + 2, 128); ++ allocate_master_alpha(); ++ return true; ++ } ++ ++ //------------------------------------------------------------------------ ++ template ++ bool rasterizer_compound_aa::hit_test(int tx, int ty) ++ { ++ if(!navigate_scanline(ty)) ++ { ++ return false; ++ } ++ ++ unsigned num_styles = sweep_styles(); ++ if(num_styles <= 0) ++ { ++ return false; ++ } ++ ++ scanline_hit_test sl(tx); ++ sweep_scanline(sl, -1); ++ return sl.hit(); ++ } ++ ++ //------------------------------------------------------------------------ ++ template ++ cover_type* rasterizer_compound_aa::allocate_cover_buffer(unsigned len) ++ { ++ m_cover_buf.allocate(len, 256); ++ return &m_cover_buf[0]; ++ } ++ ++ //------------------------------------------------------------------------ ++ template ++ void rasterizer_compound_aa::allocate_master_alpha() ++ { ++ while((int)m_master_alpha.size() <= m_max_style) ++ { ++ m_master_alpha.add(aa_mask); ++ } ++ } ++ ++ //------------------------------------------------------------------------ ++ template ++ void rasterizer_compound_aa::master_alpha(int style, double alpha) ++ { ++ if(style >= 0) ++ { ++ while((int)m_master_alpha.size() <= style) ++ { ++ m_master_alpha.add(aa_mask); ++ } ++ m_master_alpha[style] = uround(alpha * aa_mask); ++ } ++ } + + } + +diff --git a/src/third_party/agg/include/agg_rasterizer_outline.h b/src/third_party/agg/include/agg_rasterizer_outline.h +index e2dea2a..cc2bd2f 100644 +--- a/src/third_party/agg/include/agg_rasterizer_outline.h ++++ b/src/third_party/agg/include/agg_rasterizer_outline.h +@@ -28,8 +28,9 @@ namespace agg + m_start_x(0), + m_start_y(0), + m_vertices(0) +- { +- } ++ {} ++ void attach(Renderer& ren) { m_ren = &ren; } ++ + + //-------------------------------------------------------------------- + void move_to(int x, int y) +diff --git a/src/third_party/agg/include/agg_rasterizer_outline_aa.h b/src/third_party/agg/include/agg_rasterizer_outline_aa.h +index d06a80f..6ce3c31 100644 +--- a/src/third_party/agg/include/agg_rasterizer_outline_aa.h ++++ b/src/third_party/agg/include/agg_rasterizer_outline_aa.h +@@ -86,20 +86,20 @@ namespace agg + typedef vertex_sequence vertex_storage_type; + + rasterizer_outline_aa(Renderer& ren) : +- m_ren(ren), ++ m_ren(&ren), + m_line_join(ren.accurate_join_only() ? + outline_miter_accurate_join : + outline_round_join), + m_round_cap(false), + m_start_x(0), + m_start_y(0) +- { +- } ++ {} ++ void attach(Renderer& ren) { m_ren = &ren; } + + //------------------------------------------------------------------------ + void line_join(outline_aa_join_e join) + { +- m_line_join = m_ren.accurate_join_only() ? ++ m_line_join = m_ren->accurate_join_only() ? + outline_miter_accurate_join : + join; + } +@@ -187,7 +187,7 @@ namespace agg + { + for(unsigned i = 0; i < num_paths; i++) + { +- m_ren.color(colors[i]); ++ m_ren->color(colors[i]); + add_path(vs, path_id[i]); + } + } +@@ -199,7 +199,7 @@ namespace agg + unsigned i; + for(i = 0; i < c.num_paths(); i++) + { +- m_ren.color(c.color(i)); ++ m_ren->color(c.color(i)); + add_path(c, i); + } + } +@@ -209,7 +209,7 @@ namespace agg + const rasterizer_outline_aa& operator = + (const rasterizer_outline_aa&); + +- Renderer& m_ren; ++ Renderer* m_ren; + vertex_storage_type m_src_vertices; + outline_aa_join_e m_line_join; + bool m_round_cap; +@@ -245,19 +245,19 @@ namespace agg + + switch(dv.flags) + { +- case 0: m_ren.line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break; +- case 1: m_ren.line2(dv.curr, dv.xb2, dv.yb2); break; +- case 2: m_ren.line1(dv.curr, dv.xb1, dv.yb1); break; +- case 3: m_ren.line0(dv.curr); break; ++ case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break; ++ case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break; ++ case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break; ++ case 3: m_ren->line0(dv.curr); break; + } + + if(m_line_join == outline_round_join && (dv.flags & 2) == 0) + { +- m_ren.pie(dv.curr.x2, dv.curr.y2, +- dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), +- dv.curr.y2 - (dv.curr.x2 - dv.curr.x1), +- dv.curr.x2 + (dv.next.y2 - dv.next.y1), +- dv.curr.y2 - (dv.next.x2 - dv.next.x1)); ++ m_ren->pie(dv.curr.x2, dv.curr.y2, ++ dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), ++ dv.curr.y2 - (dv.curr.x2 - dv.curr.x1), ++ dv.curr.x2 + (dv.next.y2 - dv.next.y1), ++ dv.curr.y2 - (dv.next.x2 - dv.next.x1)); + } + + dv.x1 = dv.x2; +@@ -406,16 +406,16 @@ namespace agg + line_parameters lp(x1, y1, x2, y2, lprev); + if(m_round_cap) + { +- m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); ++ m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + } +- m_ren.line3(lp, +- x1 + (y2 - y1), +- y1 - (x2 - x1), +- x2 + (y2 - y1), +- y2 - (x2 - x1)); ++ m_ren->line3(lp, ++ x1 + (y2 - y1), ++ y1 - (x2 - x1), ++ x2 + (y2 - y1), ++ y2 - (x2 - x1)); + if(m_round_cap) + { +- m_ren.semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1)); ++ m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1)); + } + } + break; +@@ -440,32 +440,32 @@ namespace agg + + if(m_round_cap) + { +- m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); ++ m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + } + + if(m_line_join == outline_round_join) + { +- m_ren.line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), +- x2 + (y2 - y1), y2 - (x2 - x1)); ++ m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), ++ x2 + (y2 - y1), y2 - (x2 - x1)); + +- m_ren.pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1), +- x2 + (y3 - y2), y2 - (x3 - x2)); ++ m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1), ++ x2 + (y3 - y2), y2 - (x3 - x2)); + +- m_ren.line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2), +- x3 + (y3 - y2), y3 - (x3 - x2)); ++ m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2), ++ x3 + (y3 - y2), y3 - (x3 - x2)); + } + else + { + bisectrix(lp1, lp2, &dv.xb1, &dv.yb1); +- m_ren.line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), +- dv.xb1, dv.yb1); ++ m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), ++ dv.xb1, dv.yb1); + +- m_ren.line3(lp2, dv.xb1, dv.yb1, +- x3 + (y3 - y2), y3 - (x3 - x2)); ++ m_ren->line3(lp2, dv.xb1, dv.yb1, ++ x3 + (y3 - y2), y3 - (x3 - x2)); + } + if(m_round_cap) + { +- m_ren.semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2)); ++ m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2)); + } + } + break; +@@ -521,31 +521,31 @@ namespace agg + + if(m_round_cap) + { +- m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); ++ m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + } + if((dv.flags & 1) == 0) + { + if(m_line_join == outline_round_join) + { +- m_ren.line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), +- x2 + (y2 - y1), y2 - (x2 - x1)); +- m_ren.pie(prev.x2, prev.y2, +- x2 + (y2 - y1), y2 - (x2 - x1), +- dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), +- dv.curr.y1 - (dv.curr.x2 - dv.curr.x1)); ++ m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), ++ x2 + (y2 - y1), y2 - (x2 - x1)); ++ m_ren->pie(prev.x2, prev.y2, ++ x2 + (y2 - y1), y2 - (x2 - x1), ++ dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), ++ dv.curr.y1 - (dv.curr.x2 - dv.curr.x1)); + } + else + { + bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); +- m_ren.line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), +- dv.xb1, dv.yb1); ++ m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), ++ dv.xb1, dv.yb1); + } + } + else + { +- m_ren.line1(prev, +- x1 + (y2 - y1), +- y1 - (x2 - x1)); ++ m_ren->line1(prev, ++ x1 + (y2 - y1), ++ y1 - (x2 - x1)); + } + if((dv.flags & 2) == 0 && m_line_join != outline_round_join) + { +@@ -558,30 +558,30 @@ namespace agg + { + if(m_line_join == outline_round_join) + { +- m_ren.line3(dv.curr, +- dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), +- dv.curr.y1 - (dv.curr.x2 - dv.curr.x1), +- dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), +- dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); ++ m_ren->line3(dv.curr, ++ dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), ++ dv.curr.y1 - (dv.curr.x2 - dv.curr.x1), ++ dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), ++ dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } + else + { +- m_ren.line3(dv.curr, dv.xb1, dv.yb1, +- dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), +- dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); ++ m_ren->line3(dv.curr, dv.xb1, dv.yb1, ++ dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), ++ dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } + } + else + { +- m_ren.line2(dv.curr, +- dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), +- dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); ++ m_ren->line2(dv.curr, ++ dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), ++ dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } + if(m_round_cap) + { +- m_ren.semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2, +- dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), +- dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); ++ m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2, ++ dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), ++ dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } + + } +diff --git a/src/third_party/agg/include/agg_rasterizer_scanline_aa.h b/src/third_party/agg/include/agg_rasterizer_scanline_aa.h +index 20f4c97..39286d7 100644 +--- a/src/third_party/agg/include/agg_rasterizer_scanline_aa.h ++++ b/src/third_party/agg/include/agg_rasterizer_scanline_aa.h +@@ -65,13 +65,6 @@ namespace agg + } + }; + +- //----------------------------------------------------------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 +@@ -194,8 +187,8 @@ namespace agg + template + void add_path(VertexSource& vs, unsigned path_id=0) + { +- double x; +- double y; ++ double x = 0; ++ double y = 0; + + unsigned cmd; + vs.rewind(path_id); +@@ -364,7 +357,7 @@ namespace agg + template + void rasterizer_scanline_aa::close_polygon() + { +- if(m_auto_close && m_status == status_line_to) ++ if(m_status == status_line_to) + { + m_clipper.line_to(m_outline, m_start_x, m_start_y); + m_status = status_closed; +@@ -376,7 +369,7 @@ namespace agg + void rasterizer_scanline_aa::move_to(int x, int y) + { + if(m_outline.sorted()) reset(); +- if(m_status == status_line_to) close_polygon(); ++ if(m_auto_close) close_polygon(); + m_clipper.move_to(m_start_x = conv_type::downscale(x), + m_start_y = conv_type::downscale(y)); + m_status = status_move_to; +@@ -397,7 +390,7 @@ namespace agg + void rasterizer_scanline_aa::move_to_d(double x, double y) + { + if(m_outline.sorted()) reset(); +- if(m_status == status_line_to) close_polygon(); ++ if(m_auto_close) close_polygon(); + m_clipper.move_to(m_start_x = conv_type::upscale(x), + m_start_y = conv_type::upscale(y)); + m_status = status_move_to; +@@ -422,11 +415,14 @@ namespace agg + move_to_d(x, y); + } + else ++ if(is_vertex(cmd)) + { +- if(is_vertex(cmd)) +- { +- line_to_d(x, y); +- } ++ line_to_d(x, y); ++ } ++ else ++ if(is_close(cmd)) ++ { ++ close_polygon(); + } + } + +@@ -466,7 +462,7 @@ namespace agg + template + AGG_INLINE bool rasterizer_scanline_aa::rewind_scanlines() + { +- close_polygon(); ++ if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) + { +@@ -481,7 +477,7 @@ namespace agg + template + AGG_INLINE bool rasterizer_scanline_aa::navigate_scanline(int y) + { +- close_polygon(); ++ if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + if(m_outline.total_cells() == 0 || + y < m_outline.min_y() || +@@ -493,31 +489,6 @@ namespace agg + return true; + } + +- //------------------------------------------------------scanline_hit_test +- class scanline_hit_test +- { +- public: +- scanline_hit_test(int x) : m_x(x), m_hit(false) {} +- +- void reset_spans() {} +- void finalize(int) {} +- void add_cell(int x, int) +- { +- if(m_x == x) m_hit = true; +- } +- void add_span(int x, int len, int) +- { +- if(m_x >= x && m_x < x+len) m_hit = true; +- } +- unsigned num_spans() const { return 1; } +- bool hit() const { return m_hit; } +- +- private: +- int m_x; +- bool m_hit; +- }; +- +- + //------------------------------------------------------------------------ + template + bool rasterizer_scanline_aa::hit_test(int tx, int ty) +diff --git a/src/third_party/agg/include/agg_renderer_base.h b/src/third_party/agg/include/agg_renderer_base.h +index 19fd6de..2dc3aa1 100644 +--- a/src/third_party/agg/include/agg_renderer_base.h ++++ b/src/third_party/agg/include/agg_renderer_base.h +@@ -132,7 +132,19 @@ namespace agg + } + } + } +- ++ ++ //-------------------------------------------------------------------- ++ void fill(const color_type& c) ++ { ++ unsigned y; ++ if(width()) ++ { ++ for(y = 0; y < height(); y++) ++ { ++ m_ren->blend_hline(0, y, width(), c, cover_mask); ++ } ++ } ++ } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) +@@ -205,6 +217,7 @@ namespace agg + + m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover); + } ++ + + //-------------------------------------------------------------------- + void blend_vline(int x, int y1, int y2, +@@ -280,6 +293,29 @@ namespace agg + } + m_ren->blend_solid_hspan(x, y, len, c, covers); + } ++ ++ //-------------------------------------------------------------------- ++ void blend_solid_hspan_subpix(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 -= 3 * (xmin() - x); ++ if(len <= 0) return; ++ covers += 3 * (xmin() - x); ++ x = xmin(); ++ } ++ if(x + len / 3 > xmax()) ++ { ++ len = 3 * (xmax() - x + 1); ++ if(len <= 0) return; ++ } ++ m_ren->blend_solid_hspan_subpix(x, y, len, c, covers); ++ } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, int len, +@@ -327,6 +363,30 @@ namespace agg + m_ren->copy_color_hspan(x, y, len, colors); + } + ++ ++ //-------------------------------------------------------------------- ++ void copy_color_vspan(int x, int y, int len, const color_type* colors) ++ { ++ if(x > xmax()) return; ++ if(x < xmin()) return; ++ ++ if(y < ymin()) ++ { ++ int d = ymin() - y; ++ len -= d; ++ if(len <= 0) return; ++ colors += d; ++ y = ymin(); ++ } ++ if(y + len > ymax()) ++ { ++ len = ymax() - y + 1; ++ if(len <= 0) return; ++ } ++ m_ren->copy_color_vspan(x, y, len, colors); ++ } ++ ++ + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, int len, + const color_type* colors, +diff --git a/src/third_party/agg/include/agg_renderer_markers.h b/src/third_party/agg/include/agg_renderer_markers.h +index 6673e18..820f753 100644 +--- a/src/third_party/agg/include/agg_renderer_markers.h ++++ b/src/third_party/agg/include/agg_renderer_markers.h +@@ -65,8 +65,7 @@ namespace agg + //-------------------------------------------------------------------- + renderer_markers(base_ren_type& rbuf) : + base_type(rbuf) +- { +- } ++ {} + + //-------------------------------------------------------------------- + bool visible(int x, int y, int r) const +diff --git a/src/third_party/agg/include/agg_renderer_mclip.h b/src/third_party/agg/include/agg_renderer_mclip.h +index 2c8eb0f..31da0ed 100644 +--- a/src/third_party/agg/include/agg_renderer_mclip.h ++++ b/src/third_party/agg/include/agg_renderer_mclip.h +@@ -37,11 +37,15 @@ namespace agg + typedef renderer_base base_ren_type; + + //-------------------------------------------------------------------- +- renderer_mclip(pixfmt_type& ren) : +- m_ren(ren), ++ renderer_mclip(pixfmt_type& pixf) : ++ m_ren(pixf), + m_curr_cb(0), + m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax()) ++ {} ++ void attach(pixfmt_type& pixf) + { ++ m_ren.attach(pixf); ++ reset_clipping(true); + } + + //-------------------------------------------------------------------- +diff --git a/src/third_party/agg/include/agg_renderer_outline_aa.h b/src/third_party/agg/include/agg_renderer_outline_aa.h +index b02277a..f9c7674 100644 +--- a/src/third_party/agg/include/agg_renderer_outline_aa.h ++++ b/src/third_party/agg/include/agg_renderer_outline_aa.h +@@ -15,7 +15,7 @@ + #ifndef AGG_RENDERER_OUTLINE_AA_INCLUDED + #define AGG_RENDERER_OUTLINE_AA_INCLUDED + +-#include "agg_basics.h" ++#include "agg_array.h" + #include "agg_math.h" + #include "agg_line_aa_basics.h" + #include "agg_dda_line.h" +@@ -1273,13 +1273,8 @@ namespace agg + aa_mask = aa_scale - 1 + }; + +- //--------------------------------------------------------------------- +- ~line_profile_aa() { delete [] m_profile; } +- + //--------------------------------------------------------------------- + line_profile_aa() : +- m_size(0), +- m_profile(0), + m_subpixel_width(0), + m_min_width(1.0), + m_smoother_width(1.0) +@@ -1291,8 +1286,6 @@ namespace agg + //--------------------------------------------------------------------- + template + line_profile_aa(double w, const GammaF& gamma_function) : +- m_size(0), +- m_profile(0), + m_subpixel_width(0), + m_min_width(1.0), + m_smoother_width(1.0) +@@ -1318,7 +1311,7 @@ namespace agg + + void width(double w); + +- unsigned profile_size() const { return m_size; } ++ unsigned profile_size() const { return m_profile.size(); } + int subpixel_width() const { return m_subpixel_width; } + + //--------------------------------------------------------------------- +@@ -1339,12 +1332,11 @@ namespace agg + void set(double center_width, double smoother_width); + + //--------------------------------------------------------------------- +- unsigned m_size; +- value_type* m_profile; +- value_type m_gamma[aa_scale]; +- int m_subpixel_width; +- double m_min_width; +- double m_smoother_width; ++ pod_array m_profile; ++ value_type m_gamma[aa_scale]; ++ int m_subpixel_width; ++ double m_min_width; ++ double m_smoother_width; + }; + + +@@ -1363,8 +1355,8 @@ namespace agg + m_profile(&prof), + m_clip_box(0,0,0,0), + m_clipping(false) +- { +- } ++ {} ++ void attach(base_ren_type& ren) { m_ren = &ren; } + + //--------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } +@@ -1373,7 +1365,7 @@ namespace agg + //--------------------------------------------------------------------- + void profile(const line_profile_aa& prof) { m_profile = &prof; } + const line_profile_aa& profile() const { return *m_profile; } +- line_profile_aa& profile() { return *m_profile; } ++ line_profile_aa& profile() { return *(line_profile_aa*)m_profile; } + + //--------------------------------------------------------------------- + int subpixel_width() const { return m_profile->subpixel_width(); } +diff --git a/src/third_party/agg/include/agg_renderer_outline_image.h b/src/third_party/agg/include/agg_renderer_outline_image.h +index 8376979..dd48450 100644 +--- a/src/third_party/agg/include/agg_renderer_outline_image.h ++++ b/src/third_party/agg/include/agg_renderer_outline_image.h +@@ -15,6 +15,7 @@ + #ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED + #define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED + ++#include "agg_array.h" + #include "agg_math.h" + #include "agg_line_aa_basics.h" + #include "agg_dda_line.h" +@@ -69,18 +70,12 @@ namespace agg + typedef Filter filter_type; + typedef typename filter_type::color_type color_type; + +- //-------------------------------------------------------------------- +- ~line_image_pattern() +- { +- delete [] m_data; +- } +- + //-------------------------------------------------------------------- + line_image_pattern(const Filter& filter) : + m_filter(&filter), + m_dilation(filter.dilation() + 1), + m_dilation_hr(m_dilation << line_subpixel_shift), +- m_data(0), ++ m_data(), + m_width(0), + m_height(0), + m_width_hr(0), +@@ -96,7 +91,7 @@ namespace agg + m_filter(&filter), + m_dilation(filter.dilation() + 1), + m_dilation_hr(m_dilation << line_subpixel_shift), +- m_data(0), ++ m_data(), + m_width(0), + m_height(0), + m_width_hr(0), +@@ -117,12 +112,11 @@ namespace agg + m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_scale/2; + m_half_height_hr += line_subpixel_scale/2; + +- delete [] m_data; +- m_data = new color_type [(m_width + m_dilation * 2) * (m_height + m_dilation * 2)]; ++ m_data.resize((m_width + m_dilation * 2) * (m_height + m_dilation * 2)); + +- m_buf.attach(m_data, m_width + m_dilation * 2, +- m_height + m_dilation * 2, +- m_width + m_dilation * 2); ++ m_buf.attach(&m_data[0], m_width + m_dilation * 2, ++ m_height + m_dilation * 2, ++ m_width + m_dilation * 2); + unsigned x, y; + color_type* d1; + color_type* d2; +@@ -195,7 +189,7 @@ namespace agg + const filter_type* m_filter; + unsigned m_dilation; + int m_dilation_hr; +- color_type* m_data; ++ pod_array m_data; + unsigned m_width; + unsigned m_height; + int m_width_hr; +@@ -829,8 +823,8 @@ namespace agg + m_scale_x(1.0), + m_clip_box(0,0,0,0), + m_clipping(false) +- { +- } ++ {} ++ void attach(base_ren_type& ren) { m_ren = &ren; } + + //--------------------------------------------------------------------- + void pattern(const pattern_type& p) { m_pattern = &p; } +@@ -924,10 +918,6 @@ namespace agg + + fix_degenerate_bisectrix_start(lp, &sx, &sy); + fix_degenerate_bisectrix_end(lp, &ex, &ey); +-//sx = lp.x1 + (lp.y2 - lp.y1); +-//sy = lp.y1 - (lp.x2 - lp.x1); +-//ex = lp.x2 + (lp.y2 - lp.y1); +-//ey = lp.y2 - (lp.x2 - lp.x1); + line_interpolator_image li(*this, lp, + sx, sy, + ex, ey, +diff --git a/src/third_party/agg/include/agg_renderer_primitives.h b/src/third_party/agg/include/agg_renderer_primitives.h +index a9d8410..fe4780d 100644 +--- a/src/third_party/agg/include/agg_renderer_primitives.h ++++ b/src/third_party/agg/include/agg_renderer_primitives.h +@@ -41,8 +41,8 @@ namespace agg + m_line_color(), + m_curr_x(0), + m_curr_y(0) +- { +- } ++ {} ++ void attach(base_ren_type& ren) { m_ren = &ren; } + + //-------------------------------------------------------------------- + static int coord(double c) +diff --git a/src/third_party/agg/include/agg_renderer_raster_text.h b/src/third_party/agg/include/agg_renderer_raster_text.h +index d1de298..87b43f9 100644 +--- a/src/third_party/agg/include/agg_renderer_raster_text.h ++++ b/src/third_party/agg/include/agg_renderer_raster_text.h +@@ -34,8 +34,8 @@ namespace agg + renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph) : + m_ren(&ren), + m_glyph(&glyph) +- { +- } ++ {} ++ void attach(ren_type& ren) { m_ren = &ren; } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } +diff --git a/src/third_party/agg/include/agg_renderer_scanline.h b/src/third_party/agg/include/agg_renderer_scanline.h +index 506c635..615fffb 100644 +--- a/src/third_party/agg/include/agg_renderer_scanline.h ++++ b/src/third_party/agg/include/agg_renderer_scanline.h +@@ -52,7 +52,6 @@ namespace agg + } + } + +- + //===============================================render_scanlines_aa_solid + template +@@ -103,7 +102,6 @@ namespace agg + } + } + +- + //==============================================renderer_scanline_aa_solid + template class renderer_scanline_aa_solid + { +@@ -176,8 +174,6 @@ namespace agg + } + } + +- +- + //=====================================================render_scanlines_aa + template +@@ -195,8 +191,6 @@ namespace agg + } + } + +- +- + //====================================================renderer_scanline_aa + template + class renderer_scanline_aa +@@ -244,318 +238,6 @@ namespace agg + + + +- +- +- +- +- +- +- +- +- +-/* +- //===================================================renderer_scanline_bin +- template class renderer_scanline_bin +- { +- public: +- typedef BaseRenderer base_ren_type; +- typedef SpanGenerator span_gen_type; +- +- //-------------------------------------------------------------------- +- renderer_scanline_bin() : m_ren(0), m_span_gen(0) {} +- renderer_scanline_bin(base_ren_type& ren, span_gen_type& span_gen) : +- m_ren(&ren), +- m_span_gen(&span_gen) +- {} +- void attach(base_ren_type& ren, span_gen_type& span_gen) +- { +- m_ren = &ren; +- m_span_gen = &span_gen; +- } +- +- //-------------------------------------------------------------------- +- void prepare(unsigned max_span_len) +- { +- m_span_gen->prepare(max_span_len); +- } +- +- //-------------------------------------------------------------------- +- template void render(const Scanline& sl) +- { +- int y = sl.y(); +- m_ren->first_clip_box(); +- do +- { +- int xmin = m_ren->xmin(); +- int xmax = m_ren->xmax(); +- +- if(y >= m_ren->ymin() && y <= m_ren->ymax()) +- { +- unsigned num_spans = sl.num_spans(); +- typename Scanline::const_iterator span = sl.begin(); +- for(;;) +- { +- int x = span->x; +- int len = span->len; +- +- if(len < 0) len = -len; +- if(x < xmin) +- { +- len -= xmin - x; +- x = xmin; +- } +- if(len > 0) +- { +- if(x + len > xmax) +- { +- len = xmax - x + 1; +- } +- if(len > 0) +- { +- m_ren->blend_color_hspan_no_clip( +- x, y, len, +- m_span_gen->generate(x, y, len), +- 0); +- } +- } +- if(--num_spans == 0) break; +- ++span; +- } +- } +- } +- while(m_ren->next_clip_box()); +- } +- +- private: +- base_ren_type* m_ren; +- SpanGenerator* m_span_gen; +- }; +- +- +- +- +- +- //================================================renderer_scanline_direct +- template class renderer_scanline_direct +- { +- public: +- typedef BaseRenderer base_ren_type; +- typedef SpanGenerator span_gen_type; +- +- //-------------------------------------------------------------------- +- renderer_scanline_direct() : m_ren(0), m_span_gen(0) {} +- renderer_scanline_direct(base_ren_type& ren, span_gen_type& span_gen) : +- m_ren(&ren), +- m_span_gen(&span_gen) +- {} +- void attach(base_ren_type& ren, span_gen_type& span_gen) +- { +- m_ren = &ren; +- m_span_gen = &span_gen; +- } +- +- //-------------------------------------------------------------------- +- void prepare(unsigned max_span_len) +- { +- m_span_gen->prepare(max_span_len); +- } +- +- //-------------------------------------------------------------------- +- template void render(const Scanline& sl) +- { +- int y = sl.y(); +- m_ren->first_clip_box(); +- do +- { +- int xmin = m_ren->xmin(); +- int xmax = m_ren->xmax(); +- +- if(y >= m_ren->ymin() && y <= m_ren->ymax()) +- { +- unsigned num_spans = sl.num_spans(); +- typename Scanline::const_iterator span = sl.begin(); +- for(;;) +- { +- int x = span->x; +- int len = span->len; +- +- if(len < 0) len = -len; +- if(x < xmin) +- { +- len -= xmin - x; +- x = xmin; +- } +- if(len > 0) +- { +- if(x + len > xmax) +- { +- len = xmax - x + 1; +- } +- if(len > 0) +- { +- span_data span = m_ren->span(x, y, len); +- if(span.ptr) +- { +- m_span_gen->generate(span.x, y, span.len, span.ptr); +- } +- } +- } +- if(--num_spans == 0) break; +- ++span; +- } +- } +- } +- while(m_ren->next_clip_box()); +- } +- +- private: +- base_ren_type* m_ren; +- SpanGenerator* m_span_gen; +- }; +- +- +- +- +- +- +- //===============================================renderer_scanline_bin_copy +- template class renderer_scanline_bin_copy +- { +- public: +- typedef BaseRenderer base_ren_type; +- typedef SpanGenerator span_gen_type; +- +- //-------------------------------------------------------------------- +- renderer_scanline_bin_copy() : m_ren(0), m_span_gen(0) {} +- renderer_scanline_bin_copy(base_ren_type& ren, span_gen_type& span_gen) : +- m_ren(&ren), +- m_span_gen(&span_gen) +- {} +- void attach(base_ren_type& ren, span_gen_type& span_gen) +- { +- m_ren = &ren; +- m_span_gen = &span_gen; +- } +- +- //-------------------------------------------------------------------- +- void prepare(unsigned max_span_len) +- { +- m_span_gen->prepare(max_span_len); +- } +- +- //-------------------------------------------------------------------- +- template void render(const Scanline& sl) +- { +- int y = sl.y(); +- m_ren->first_clip_box(); +- do +- { +- int xmin = m_ren->xmin(); +- int xmax = m_ren->xmax(); +- +- if(y >= m_ren->ymin() && y <= m_ren->ymax()) +- { +- unsigned num_spans = sl.num_spans(); +- typename Scanline::const_iterator span = sl.begin(); +- for(;;) +- { +- int x = span->x; +- int len = span->len; +- +- if(len < 0) len = -len; +- if(x < xmin) +- { +- len -= xmin - x; +- x = xmin; +- } +- if(len > 0) +- { +- if(x + len > xmax) +- { +- len = xmax - x + 1; +- } +- if(len > 0) +- { +- m_ren->copy_color_hspan_no_clip( +- x, y, len, +- m_span_gen->generate(x, y, len)); +- } +- } +- if(--num_spans == 0) break; +- ++span; +- } +- } +- } +- while(m_ren->next_clip_box()); +- } +- +- private: +- base_ren_type* m_ren; +- SpanGenerator* m_span_gen; +- }; +- +- +- +- //=============================================renderer_scanline_bin_solid +- template class renderer_scanline_bin_solid +- { +- public: +- typedef BaseRenderer base_ren_type; +- typedef typename base_ren_type::color_type color_type; +- +- //-------------------------------------------------------------------- +- renderer_scanline_bin_solid() : m_ren(0) {} +- renderer_scanline_bin_solid(base_ren_type& ren) : +- m_ren(&ren) +- {} +- void attach(base_ren_type& ren) +- { +- m_ren = &ren; +- } +- +- //-------------------------------------------------------------------- +- void color(const color_type& c) { m_color = c; } +- const color_type& color() const { return m_color; } +- +- //-------------------------------------------------------------------- +- void prepare(unsigned) {} +- +- //-------------------------------------------------------------------- +- template void render(const Scanline& sl) +- { +- unsigned num_spans = sl.num_spans(); +- typename Scanline::const_iterator span = sl.begin(); +- for(;;) +- { +- m_ren->blend_hline(span->x, +- sl.y(), +- span->x - 1 + ((span->len < 0) ? +- -span->len : +- span->len), +- m_color, +- cover_full); +- if(--num_spans == 0) break; +- ++span; +- } +- } +- +- private: +- base_ren_type* m_ren; +- color_type m_color; +- }; +-*/ +- +- +- +- +- +- +- +- +- +- +- +- + //===============================================render_scanline_bin_solid + template + void render_scanline_bin_solid(const Scanline& sl, +@@ -578,7 +260,6 @@ namespace agg + } + } + +- + //==============================================render_scanlines_bin_solid + template +@@ -621,7 +302,6 @@ namespace agg + } + } + +- + //=============================================renderer_scanline_bin_solid + template class renderer_scanline_bin_solid + { +@@ -662,6 +342,92 @@ namespace agg + + + ++ //======================================================render_scanline_bin ++ template ++ void render_scanline_bin(const Scanline& sl, BaseRenderer& ren, ++ SpanAllocator& alloc, SpanGenerator& span_gen) ++ { ++ int y = sl.y(); ++ ++ unsigned num_spans = sl.num_spans(); ++ typename Scanline::const_iterator span = sl.begin(); ++ for(;;) ++ { ++ int x = span->x; ++ int len = span->len; ++ if(len < 0) len = -len; ++ typename BaseRenderer::color_type* colors = alloc.allocate(len); ++ span_gen.generate(colors, x, y, len); ++ ren.blend_color_hspan(x, y, len, colors, 0, cover_full); ++ if(--num_spans == 0) break; ++ ++span; ++ } ++ } ++ ++ //=====================================================render_scanlines_bin ++ template ++ void render_scanlines_bin(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, ++ SpanAllocator& alloc, SpanGenerator& span_gen) ++ { ++ if(ras.rewind_scanlines()) ++ { ++ sl.reset(ras.min_x(), ras.max_x()); ++ span_gen.prepare(); ++ while(ras.sweep_scanline(sl)) ++ { ++ render_scanline_bin(sl, ren, alloc, span_gen); ++ } ++ } ++ } ++ ++ //====================================================renderer_scanline_bin ++ template ++ class renderer_scanline_bin ++ { ++ public: ++ typedef BaseRenderer base_ren_type; ++ typedef SpanAllocator alloc_type; ++ typedef SpanGenerator span_gen_type; ++ ++ //-------------------------------------------------------------------- ++ renderer_scanline_bin() : m_ren(0), m_alloc(0), m_span_gen(0) {} ++ renderer_scanline_bin(base_ren_type& ren, ++ alloc_type& alloc, ++ span_gen_type& span_gen) : ++ m_ren(&ren), ++ m_alloc(&alloc), ++ m_span_gen(&span_gen) ++ {} ++ void attach(base_ren_type& ren, ++ alloc_type& alloc, ++ span_gen_type& span_gen) ++ { ++ m_ren = &ren; ++ m_alloc = &alloc; ++ m_span_gen = &span_gen; ++ } ++ ++ //-------------------------------------------------------------------- ++ void prepare() { m_span_gen->prepare(); } ++ ++ //-------------------------------------------------------------------- ++ template void render(const Scanline& sl) ++ { ++ render_scanline_bin(sl, *m_ren, *m_alloc, *m_span_gen); ++ } ++ ++ private: ++ base_ren_type* m_ren; ++ alloc_type* m_alloc; ++ span_gen_type* m_span_gen; ++ }; ++ ++ ++ ++ ++ + + + +@@ -682,7 +448,6 @@ namespace agg + } + } + +- + //========================================================render_all_paths + template +@@ -707,6 +472,10 @@ namespace agg + + + ++ ++ ++ ++ + //=============================================render_scanlines_compound + templatex - min_x, +- 0, +- span_bin->len * sizeof(color_type)); ++ memset(mix_buffer + sl_start - min_x, ++ 0, ++ sl_len * sizeof(color_type)); + +- if(--num_spans == 0) break; +- ++span_bin; +- } ++ memset(cover_buffer + sl_start - min_x, ++ 0, ++ sl_len * sizeof(cover_type)); + ++ int sl_y = 0x7FFFFFFF; + unsigned i; + for(i = 0; i < num_styles; i++) + { +@@ -804,11 +571,14 @@ namespace agg + + if(ras.sweep_scanline(sl_aa, i)) + { ++ unsigned cover; + color_type* colors; + color_type* cspan; +- typename ScanlineAA::cover_type* covers; ++ cover_type* src_covers; ++ cover_type* dst_covers; + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); ++ sl_y = sl_aa.y(); + if(solid) + { + // Just solid fill +@@ -818,12 +588,23 @@ namespace agg + color_type c = sh.color(style); + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; +- covers = span_aa->covers; ++ src_covers = span_aa->covers; ++ dst_covers = cover_buffer + span_aa->x - min_x; + do + { +- colors->add(c, *covers); ++ cover = *src_covers; ++ if(*dst_covers + cover > cover_full) ++ { ++ cover = cover_full - *dst_covers; ++ } ++ if(cover) ++ { ++ colors->add(c, cover); ++ *dst_covers += cover; ++ } + ++colors; +- ++covers; ++ ++src_covers; ++ ++dst_covers; + } + while(--len); + if(--num_spans == 0) break; +@@ -844,13 +625,24 @@ namespace agg + sl_aa.y(), + len, + style); +- covers = span_aa->covers; ++ src_covers = span_aa->covers; ++ dst_covers = cover_buffer + span_aa->x - min_x; + do + { +- colors->add(*cspan, *covers); ++ cover = *src_covers; ++ if(*dst_covers + cover > cover_full) ++ { ++ cover = cover_full - *dst_covers; ++ } ++ if(cover) ++ { ++ colors->add(*cspan, cover); ++ *dst_covers += cover; ++ } + ++cspan; + ++colors; +- ++covers; ++ ++src_covers; ++ ++dst_covers; + } + while(--len); + if(--num_spans == 0) break; +@@ -859,33 +651,19 @@ namespace agg + } + } + } +- +- // Emit the blended result as a color hspan +- //------------------------- +- span_bin = sl_bin.begin(); +- num_spans = sl_bin.num_spans(); +- for(;;) +- { +- ren.blend_color_hspan(span_bin->x, +- sl_bin.y(), +- span_bin->len, +- mix_buffer + span_bin->x - min_x, +- 0, +- cover_full); +- if(--num_spans == 0) break; +- ++span_bin; +- } +- +- } +- } +- } +- } ++ ren.blend_color_hspan(sl_start, ++ sl_y, ++ sl_len, ++ mix_buffer + sl_start - min_x, ++ 0, ++ cover_full); ++ } //if(sl_len) ++ } //if(num_styles == 1) ... else ++ } //while((num_styles = ras.sweep_styles()) > 0) ++ } //if(ras.rewind_scanlines()) + } + + +- +- +- + } + + #endif +diff --git a/src/third_party/agg/include/agg_rendering_buffer.h b/src/third_party/agg/include/agg_rendering_buffer.h +index 399c554..54268bd 100644 +--- a/src/third_party/agg/include/agg_rendering_buffer.h ++++ b/src/third_party/agg/include/agg_rendering_buffer.h +@@ -20,7 +20,7 @@ + #ifndef AGG_RENDERING_BUFFER_INCLUDED + #define AGG_RENDERING_BUFFER_INCLUDED + +-#include "agg_basics.h" ++#include "agg_array.h" + + namespace agg + { +@@ -39,31 +39,23 @@ namespace agg + x1(x1_), x2(x2_), ptr(ptr_) {} + }; + +- //------------------------------------------------------------------- +- ~row_ptr_cache() +- { +- delete [] m_rows; +- } +- + //------------------------------------------------------------------- + row_ptr_cache() : + m_buf(0), +- m_rows(0), ++ m_rows(), + m_width(0), + m_height(0), +- m_stride(0), +- m_max_height(0) ++ m_stride(0) + { + } + + //-------------------------------------------------------------------- + row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) : + m_buf(0), +- m_rows(0), ++ m_rows(), + m_width(0), + m_height(0), +- m_stride(0), +- m_max_height(0) ++ m_stride(0) + { + attach(buf, width, height, stride); + } +@@ -75,20 +67,19 @@ namespace agg + m_width = width; + m_height = height; + m_stride = stride; +- if(height > m_max_height) ++ if(height > m_rows.size()) + { +- delete [] m_rows; +- m_rows = new T* [m_max_height = height]; ++ m_rows.resize(height); + } + + T* row_ptr = m_buf; + + if(stride < 0) + { +- row_ptr = m_buf - (height - 1) * stride; ++ row_ptr = m_buf - int(height - 1) * stride; + } + +- T** rows = m_rows; ++ T** rows = &m_rows[0]; + + while(height--) + { +@@ -115,7 +106,7 @@ namespace agg + row_data row (int y) const { return row_data(0, m_width-1, m_rows[y]); } + + //-------------------------------------------------------------------- +- T const* const* rows() const { return m_rows; } ++ T const* const* rows() const { return &m_rows[0]; } + + //-------------------------------------------------------------------- + template +@@ -154,21 +145,13 @@ namespace agg + } + } + +- +- private: +- //-------------------------------------------------------------------- +- // Prohibit copying +- row_ptr_cache(const row_ptr_cache&); +- const row_ptr_cache& operator = (const row_ptr_cache&); +- + private: + //-------------------------------------------------------------------- +- T* m_buf; // Pointer to renrdering buffer +- T** m_rows; // Pointers to each row of the buffer +- unsigned m_width; // Width in pixels +- unsigned m_height; // Height in pixels +- int m_stride; // Number of bytes per row. Can be < 0 +- unsigned m_max_height; // The maximal height (currently allocated) ++ T* m_buf; // Pointer to renrdering buffer ++ pod_array m_rows; // Pointers to each row of the buffer ++ unsigned m_width; // Width in pixels ++ unsigned m_height; // Height in pixels ++ int m_stride; // Number of bytes per row. Can be < 0 + }; + + +diff --git a/src/third_party/agg/include/agg_rendering_buffer_dynarow.h b/src/third_party/agg/include/agg_rendering_buffer_dynarow.h +index f7a9134..7ae61c3 100644 +--- a/src/third_party/agg/include/agg_rendering_buffer_dynarow.h ++++ b/src/third_party/agg/include/agg_rendering_buffer_dynarow.h +@@ -20,8 +20,7 @@ + #ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED + #define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED + +-#include +-#include "agg_basics.h" ++#include "agg_array.h" + + namespace agg + { +@@ -51,9 +50,10 @@ namespace agg + + //------------------------------------------------------------------- + rendering_buffer_dynarow() : +- m_rows(0), ++ m_rows(), + m_width(0), +- m_height(0) ++ m_height(0), ++ m_byte_width(0) + { + } + +@@ -61,12 +61,12 @@ namespace agg + //-------------------------------------------------------------------- + rendering_buffer_dynarow(unsigned width, unsigned height, + unsigned byte_width) : +- m_rows(new row_data[height]), ++ m_rows(height), + m_width(width), + m_height(height), + m_byte_width(byte_width) + { +- memset(m_rows, 0, sizeof(row_data) * height); ++ memset(&m_rows[0], 0, sizeof(row_data) * height); + } + + // Allocate and clear the buffer +@@ -74,16 +74,17 @@ namespace agg + void init(unsigned width, unsigned height, unsigned byte_width) + { + unsigned i; +- for(i = 0; i < m_height; ++i) delete [] (int8u*)m_rows[i].ptr; +- delete [] m_rows; +- m_rows = 0; ++ for(i = 0; i < m_height; ++i) ++ { ++ pod_allocator::deallocate((int8u*)m_rows[i].ptr, m_byte_width); ++ } + if(width && height) + { + m_width = width; + m_height = height; + m_byte_width = byte_width; +- m_rows = new row_data[height]; +- memset(m_rows, 0, sizeof(row_data) * height); ++ m_rows.resize(height); ++ memset(&m_rows[0], 0, sizeof(row_data) * height); + } + } + +@@ -97,7 +98,7 @@ namespace agg + //-------------------------------------------------------------------- + int8u* row_ptr(int x, int y, unsigned len) + { +- row_data* r = m_rows + y; ++ row_data* r = &m_rows[y]; + int x2 = x + len - 1; + if(r->ptr) + { +@@ -106,7 +107,7 @@ namespace agg + } + else + { +- int8u* p = new int8u [m_byte_width]; ++ int8u* p = pod_allocator::allocate(m_byte_width); + r->ptr = p; + r->x1 = x; + r->x2 = x2; +@@ -128,10 +129,10 @@ namespace agg + + private: + //-------------------------------------------------------------------- +- row_data* m_rows; // Pointers to each row of the buffer +- unsigned m_width; // Width in pixels +- unsigned m_height; // Height in pixels +- unsigned m_byte_width; // Width in bytes ++ pod_array m_rows; // Pointers to each row of the buffer ++ unsigned m_width; // Width in pixels ++ unsigned m_height; // Height in pixels ++ unsigned m_byte_width; // Width in bytes + }; + + +diff --git a/src/third_party/agg/include/agg_scanline_bin.h b/src/third_party/agg/include/agg_scanline_bin.h +index e0584d0..660292b 100644 +--- a/src/third_party/agg/include/agg_scanline_bin.h ++++ b/src/third_party/agg/include/agg_scanline_bin.h +@@ -54,15 +54,9 @@ namespace agg + typedef const span* const_iterator; + + //-------------------------------------------------------------------- +- ~scanline_bin() +- { +- delete [] m_spans; +- } +- + scanline_bin() : +- m_max_len(0), + m_last_x(0x7FFFFFF0), +- m_spans(0), ++ m_spans(), + m_cur_span(0) + { + } +@@ -71,14 +65,12 @@ namespace agg + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; +- if(max_len > m_max_len) ++ if(max_len > m_spans.size()) + { +- delete [] m_spans; +- m_spans = new span [max_len]; +- m_max_len = max_len; ++ m_spans.resize(max_len); + } + m_last_x = 0x7FFFFFF0; +- m_cur_span = m_spans; ++ m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- +@@ -129,23 +121,22 @@ namespace agg + void reset_spans() + { + m_last_x = 0x7FFFFFF0; +- m_cur_span = m_spans; ++ m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } +- unsigned num_spans() const { return unsigned(m_cur_span - m_spans); } +- const_iterator begin() const { return m_spans + 1; } ++ unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } ++ const_iterator begin() const { return &m_spans[1]; } + + private: + scanline_bin(const scanline_bin&); + const scanline_bin operator = (const scanline_bin&); + +- unsigned m_max_len; +- int m_last_x; +- int m_y; +- span* m_spans; +- span* m_cur_span; ++ int m_last_x; ++ int m_y; ++ pod_array m_spans; ++ span* m_cur_span; + }; + + +diff --git a/src/third_party/agg/include/agg_scanline_boolean_algebra.h b/src/third_party/agg/include/agg_scanline_boolean_algebra.h +index ad359e6..bc2e9c9 100644 +--- a/src/third_party/agg/include/agg_scanline_boolean_algebra.h ++++ b/src/third_party/agg/include/agg_scanline_boolean_algebra.h +@@ -850,8 +850,8 @@ namespace agg + unsigned num1 = sl1.num_spans(); + unsigned num2 = sl2.num_spans(); + +- typename Scanline1::const_iterator span1; +- typename Scanline2::const_iterator span2; ++ typename Scanline1::const_iterator span1;// = sl1.begin(); ++ typename Scanline2::const_iterator span2;// = sl2.begin(); + + enum invalidation_e + { +@@ -1046,7 +1046,11 @@ namespace agg + + // Calculate the union of the bounding boxes + //----------------- +- rect_i ur = unite_rectangles(r1, r2); ++ rect_i ur(1,1,0,0); ++ if(flag1 && flag2) ur = unite_rectangles(r1, r2); ++ else if(flag1) ur = r1; ++ else if(flag2) ur = r2; ++ + if(!ur.is_valid()) return; + + ren.prepare(); +@@ -1176,7 +1180,7 @@ namespace agg + ren.prepare(); + + // A fake span2 processor +- sbool_add_span_empty add_span2; ++ sbool_add_span_empty add_span2; + + // The main loop + // Here we synchronize the scanlines with +diff --git a/src/third_party/agg/include/agg_scanline_p.h b/src/third_party/agg/include/agg_scanline_p.h +index e93bbd5..1d1cbe7 100644 +--- a/src/third_party/agg/include/agg_scanline_p.h ++++ b/src/third_party/agg/include/agg_scanline_p.h +@@ -57,19 +57,11 @@ namespace agg + typedef span* iterator; + typedef const span* const_iterator; + +- //-------------------------------------------------------------------- +- ~scanline_p8() +- { +- delete [] m_spans; +- delete [] m_covers; +- } +- + scanline_p8() : +- m_max_len(0), + m_last_x(0x7FFFFFF0), +- m_covers(0), ++ m_covers(), + m_cover_ptr(0), +- m_spans(0), ++ m_spans(), + m_cur_span(0) + { + } +@@ -78,17 +70,14 @@ namespace agg + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; +- if(max_len > m_max_len) ++ if(max_len > m_spans.size()) + { +- delete [] m_spans; +- delete [] m_covers; +- m_covers = new cover_type [max_len]; +- m_spans = new span [max_len]; +- m_max_len = max_len; ++ m_spans.resize(max_len); ++ m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; +- m_cover_ptr = m_covers; +- m_cur_span = m_spans; ++ m_cover_ptr = &m_covers[0]; ++ m_cur_span = &m_spans[0]; + m_cur_span->len = 0; + } + +@@ -160,27 +149,26 @@ namespace agg + void reset_spans() + { + m_last_x = 0x7FFFFFF0; +- m_cover_ptr = m_covers; +- m_cur_span = m_spans; ++ m_cover_ptr = &m_covers[0]; ++ m_cur_span = &m_spans[0]; + m_cur_span->len = 0; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } +- unsigned num_spans() const { return unsigned(m_cur_span - m_spans); } +- const_iterator begin() const { return m_spans + 1; } ++ unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } ++ const_iterator begin() const { return &m_spans[1]; } + + private: + scanline_p8(const self_type&); + const self_type& operator = (const self_type&); + +- unsigned m_max_len; +- int m_last_x; +- int m_y; +- cover_type* m_covers; +- cover_type* m_cover_ptr; +- span* m_spans; +- span* m_cur_span; ++ int m_last_x; ++ int m_y; ++ pod_array m_covers; ++ cover_type* m_cover_ptr; ++ pod_array m_spans; ++ span* m_cur_span; + }; + + +@@ -231,15 +219,10 @@ namespace agg + }; + + //-------------------------------------------------------------------- +- ~scanline32_p8() +- { +- delete [] m_covers; +- } +- + scanline32_p8() : + m_max_len(0), + m_last_x(0x7FFFFFF0), +- m_covers(0), ++ m_covers(), + m_cover_ptr(0) + { + } +@@ -248,14 +231,12 @@ namespace agg + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; +- if(max_len > m_max_len) ++ if(max_len > m_covers.size()) + { +- delete [] m_covers; +- m_covers = new cover_type[max_len]; +- m_max_len = max_len; ++ m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; +- m_cover_ptr = m_covers; ++ m_cover_ptr = &m_covers[0]; + m_spans.remove_all(); + } + +@@ -319,7 +300,7 @@ namespace agg + void reset_spans() + { + m_last_x = 0x7FFFFFF0; +- m_cover_ptr = m_covers; ++ m_cover_ptr = &m_covers[0]; + m_spans.remove_all(); + } + +@@ -332,12 +313,12 @@ namespace agg + scanline32_p8(const self_type&); + const self_type& operator = (const self_type&); + +- unsigned m_max_len; +- int m_last_x; +- int m_y; +- cover_type* m_covers; +- cover_type* m_cover_ptr; +- span_array_type m_spans; ++ unsigned m_max_len; ++ int m_last_x; ++ int m_y; ++ pod_array m_covers; ++ cover_type* m_cover_ptr; ++ span_array_type m_spans; + }; + + +diff --git a/src/third_party/agg/include/agg_scanline_storage_aa.h b/src/third_party/agg/include/agg_scanline_storage_aa.h +index 4ea187e..be452a8 100644 +--- a/src/third_party/agg/include/agg_scanline_storage_aa.h ++++ b/src/third_party/agg/include/agg_scanline_storage_aa.h +@@ -83,7 +83,8 @@ namespace agg + int i; + for(i = m_extra_storage.size()-1; i >= 0; --i) + { +- delete [] m_extra_storage[(unsigned)i].ptr; ++ pod_allocator::deallocate(m_extra_storage[i].ptr, ++ m_extra_storage[i].len); + } + m_extra_storage.remove_all(); + m_cells.remove_all(); +@@ -101,7 +102,7 @@ namespace agg + } + extra_span s; + s.len = num_cells; +- s.ptr = new T [num_cells]; ++ s.ptr = pod_allocator::allocate(num_cells); + memcpy(s.ptr, cells, sizeof(T) * num_cells); + m_extra_storage.add(s); + return -int(m_extra_storage.size()); +@@ -142,7 +143,7 @@ namespace agg + const extra_span& src = v.m_extra_storage[i]; + extra_span dst; + dst.len = src.len; +- dst.ptr = new T [dst.len]; ++ dst.ptr = pod_allocator::allocate(dst.len); + memcpy(dst.ptr, src.ptr, dst.len * sizeof(T)); + m_extra_storage.add(dst); + } +@@ -196,6 +197,7 @@ namespace agg + const T* covers; + }; + ++ const_iterator() : m_storage(0) {} + const_iterator(const embedded_scanline& sl) : + m_storage(sl.m_storage), + m_span_idx(sl.m_scanline.start_span) +@@ -554,6 +556,7 @@ namespace agg + const T* covers; + }; + ++ const_iterator() : m_ptr(0) {} + const_iterator(const embedded_scanline& sl) : + m_ptr(sl.m_ptr), + m_dx(sl.m_dx) +@@ -721,9 +724,8 @@ namespace agg + m_min_y = read_int32() + m_dy; + m_max_x = read_int32() + m_dx; + m_max_y = read_int32() + m_dy; +- return true; + } +- return false; ++ return m_ptr < m_end; + } + + //-------------------------------------------------------------------- +diff --git a/src/third_party/agg/include/agg_scanline_storage_bin.h b/src/third_party/agg/include/agg_scanline_storage_bin.h +index 07ea2ee..d760016 100644 +--- a/src/third_party/agg/include/agg_scanline_storage_bin.h ++++ b/src/third_party/agg/include/agg_scanline_storage_bin.h +@@ -63,6 +63,7 @@ namespace agg + class const_iterator + { + public: ++ const_iterator() : m_storage(0) {} + const_iterator(const embedded_scanline& sl) : + m_storage(sl.m_storage), + m_span_idx(sl.m_scanline.start_span) +@@ -360,6 +361,7 @@ namespace agg + int32 len; + }; + ++ const_iterator() : m_ptr(0) {} + const_iterator(const embedded_scanline& sl) : + m_ptr(sl.m_ptr), + m_dx(sl.m_dx) +@@ -503,9 +505,8 @@ namespace agg + m_min_y = read_int32() + m_dy; + m_max_x = read_int32() + m_dx; + m_max_y = read_int32() + m_dy; +- return true; + } +- return false; ++ return m_ptr < m_end; + } + + //-------------------------------------------------------------------- +diff --git a/src/third_party/agg/include/agg_scanline_u.h b/src/third_party/agg/include/agg_scanline_u.h +index 1151306..630eb9d 100644 +--- a/src/third_party/agg/include/agg_scanline_u.h ++++ b/src/third_party/agg/include/agg_scanline_u.h +@@ -125,18 +125,9 @@ namespace agg + typedef const span* const_iterator; + + //-------------------------------------------------------------------- +- ~scanline_u8() +- { +- delete [] m_spans; +- delete [] m_covers; +- } +- + scanline_u8() : + m_min_x(0), +- m_max_len(0), + m_last_x(0x7FFFFFF0), +- m_covers(0), +- m_spans(0), + m_cur_span(0) + {} + +@@ -144,17 +135,14 @@ namespace agg + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 2; +- if(max_len > m_max_len) ++ if(max_len > m_spans.size()) + { +- delete [] m_spans; +- delete [] m_covers; +- m_covers = new cover_type [max_len]; +- m_spans = new span [max_len]; +- m_max_len = max_len; ++ m_spans.resize(max_len); ++ m_covers.resize(max_len); + } +- m_last_x = 0x7FFFFFF0; +- m_min_x = min_x; +- m_cur_span = m_spans; ++ m_last_x = 0x7FFFFFF0; ++ m_min_x = min_x; ++ m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- +@@ -171,7 +159,7 @@ namespace agg + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = 1; +- m_cur_span->covers = m_covers + x; ++ m_cur_span->covers = &m_covers[x]; + } + m_last_x = x; + } +@@ -180,7 +168,7 @@ namespace agg + void add_cells(int x, unsigned len, const cover_type* covers) + { + x -= m_min_x; +- memcpy(m_covers + x, covers, len * sizeof(cover_type)); ++ memcpy(&m_covers[x], covers, len * sizeof(cover_type)); + if(x == m_last_x+1) + { + m_cur_span->len += (coord_type)len; +@@ -190,7 +178,7 @@ namespace agg + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = (coord_type)len; +- m_cur_span->covers = m_covers + x; ++ m_cur_span->covers = &m_covers[x]; + } + m_last_x = x + len - 1; + } +@@ -199,7 +187,7 @@ namespace agg + void add_span(int x, unsigned len, unsigned cover) + { + x -= m_min_x; +- memset(m_covers + x, cover, len); ++ memset(&m_covers[x], cover, len); + if(x == m_last_x+1) + { + m_cur_span->len += (coord_type)len; +@@ -209,7 +197,7 @@ namespace agg + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = (coord_type)len; +- m_cur_span->covers = m_covers + x; ++ m_cur_span->covers = &m_covers[x]; + } + m_last_x = x + len - 1; + } +@@ -224,27 +212,26 @@ namespace agg + void reset_spans() + { + m_last_x = 0x7FFFFFF0; +- m_cur_span = m_spans; ++ m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } +- unsigned num_spans() const { return unsigned(m_cur_span - m_spans); } +- const_iterator begin() const { return m_spans + 1; } +- iterator begin() { return m_spans + 1; } ++ unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } ++ const_iterator begin() const { return &m_spans[1]; } ++ iterator begin() { return &m_spans[1]; } + + private: + scanline_u8(const self_type&); + const self_type& operator = (const self_type&); + + private: +- int m_min_x; +- unsigned m_max_len; +- int m_last_x; +- int m_y; +- cover_type* m_covers; +- span* m_spans; +- span* m_cur_span; ++ int m_min_x; ++ int m_last_x; ++ int m_y; ++ pod_array m_covers; ++ pod_array m_spans; ++ span* m_cur_span; + }; + + +@@ -265,7 +252,7 @@ namespace agg + typedef base_type::coord_type coord_type; + + scanline_u8_am() : base_type(), m_alpha_mask(0) {} +- scanline_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {} ++ scanline_u8_am(AlphaMask& am) : base_type(), m_alpha_mask(&am) {} + + //-------------------------------------------------------------------- + void finalize(int span_y) +@@ -288,7 +275,7 @@ namespace agg + } + + private: +- const AlphaMask* m_alpha_mask; ++ AlphaMask* m_alpha_mask; + }; + + +@@ -357,27 +344,19 @@ namespace agg + + + //-------------------------------------------------------------------- +- ~scanline32_u8() +- { +- delete [] m_covers; +- } +- + scanline32_u8() : + m_min_x(0), +- m_max_len(0), + m_last_x(0x7FFFFFF0), +- m_covers(0) ++ m_covers() + {} + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 2; +- if(max_len > m_max_len) ++ if(max_len > m_covers.size()) + { +- delete [] m_covers; +- m_covers = new cover_type [max_len]; +- m_max_len = max_len; ++ m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_min_x = min_x; +@@ -395,7 +374,7 @@ namespace agg + } + else + { +- m_spans.add(span(coord_type(x + m_min_x), 1, m_covers + x)); ++ m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x])); + } + m_last_x = x; + } +@@ -404,14 +383,16 @@ namespace agg + void add_cells(int x, unsigned len, const cover_type* covers) + { + x -= m_min_x; +- memcpy(m_covers + x, covers, len * sizeof(cover_type)); ++ memcpy(&m_covers[x], covers, len * sizeof(cover_type)); + if(x == m_last_x+1) + { + m_spans.last().len += coord_type(len); + } + else + { +- m_spans.add(span(coord_type(x + m_min_x), coord_type(len), m_covers + x)); ++ m_spans.add(span(coord_type(x + m_min_x), ++ coord_type(len), ++ &m_covers[x])); + } + m_last_x = x + len - 1; + } +@@ -420,14 +401,16 @@ namespace agg + void add_span(int x, unsigned len, unsigned cover) + { + x -= m_min_x; +- memset(m_covers + x, cover, len); ++ memset(&m_covers[x], cover, len); + if(x == m_last_x+1) + { + m_spans.last().len += coord_type(len); + } + else + { +- m_spans.add(span(coord_type(x + m_min_x), coord_type(len), m_covers + x)); ++ m_spans.add(span(coord_type(x + m_min_x), ++ coord_type(len), ++ &m_covers[x])); + } + m_last_x = x + len - 1; + } +@@ -456,12 +439,11 @@ namespace agg + const self_type& operator = (const self_type&); + + private: +- int m_min_x; +- unsigned m_max_len; +- int m_last_x; +- int m_y; +- cover_type* m_covers; +- span_array_type m_spans; ++ int m_min_x; ++ int m_last_x; ++ int m_y; ++ pod_array m_covers; ++ span_array_type m_spans; + }; + + +@@ -476,14 +458,14 @@ namespace agg + class scanline32_u8_am : public scanline32_u8 + { + public: +- typedef scanline_u8 base_type; ++ typedef scanline32_u8 base_type; + typedef AlphaMask alpha_mask_type; + typedef base_type::cover_type cover_type; + typedef base_type::coord_type coord_type; + + + scanline32_u8_am() : base_type(), m_alpha_mask(0) {} +- scanline32_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {} ++ scanline32_u8_am(AlphaMask& am) : base_type(), m_alpha_mask(&am) {} + + //-------------------------------------------------------------------- + void finalize(int span_y) +@@ -506,7 +488,7 @@ namespace agg + } + + private: +- const AlphaMask* m_alpha_mask; ++ AlphaMask* m_alpha_mask; + }; + + +diff --git a/src/third_party/agg/include/agg_span_allocator.h b/src/third_party/agg/include/agg_span_allocator.h +index 4cbc3cc..201b69b 100644 +--- a/src/third_party/agg/include/agg_span_allocator.h ++++ b/src/third_party/agg/include/agg_span_allocator.h +@@ -16,7 +16,7 @@ + #ifndef AGG_SPAN_ALLOCATOR_INCLUDED + #define AGG_SPAN_ALLOCATOR_INCLUDED + +-#include "agg_basics.h" ++#include "agg_array.h" + + namespace agg + { +@@ -26,45 +26,25 @@ namespace agg + public: + typedef ColorT color_type; + +- //-------------------------------------------------------------------- +- ~span_allocator() +- { +- delete [] m_span; +- } +- +- //-------------------------------------------------------------------- +- span_allocator() : +- m_max_span_len(0), +- m_span(0) +- { +- } +- + //-------------------------------------------------------------------- + AGG_INLINE color_type* allocate(unsigned span_len) + { +- if(span_len > m_max_span_len) ++ if(span_len > m_span.size()) + { + // To reduce the number of reallocs we align the + // span_len to 256 color elements. + // Well, I just like this number and it looks reasonable. + //----------------------- +- delete [] m_span; +- span_len = ((span_len + 255) >> 8) << 8; +- m_span = new color_type[m_max_span_len = span_len]; ++ m_span.resize(((span_len + 255) >> 8) << 8); + } +- return m_span; ++ return &m_span[0]; + } + +- AGG_INLINE color_type* span() { return m_span; } +- AGG_INLINE unsigned max_span_len() const { return m_max_span_len; } ++ AGG_INLINE color_type* span() { return &m_span[0]; } ++ AGG_INLINE unsigned max_span_len() const { return m_span.size(); } + + private: +- //-------------------------------------------------------------------- +- span_allocator(const span_allocator&); +- const span_allocator& operator = (const span_allocator&); +- +- unsigned m_max_span_len; +- color_type* m_span; ++ pod_array m_span; + }; + } + +diff --git a/src/third_party/agg/include/agg_span_converter.h b/src/third_party/agg/include/agg_span_converter.h +index 27b78e1..91d0f87 100644 +--- a/src/third_party/agg/include/agg_span_converter.h ++++ b/src/third_party/agg/include/agg_span_converter.h +@@ -29,6 +29,9 @@ namespace agg + span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv) : + m_span_gen(&span_gen), m_span_cnv(&span_cnv) {} + ++ void attach_generator(SpanGenerator& span_gen) { m_span_gen = &span_gen; } ++ void attach_converter(SpanConverter& span_cnv) { m_span_cnv = &span_cnv; } ++ + //-------------------------------------------------------------------- + void prepare() + { +diff --git a/src/third_party/agg/include/agg_span_gouraud_gray.h b/src/third_party/agg/include/agg_span_gouraud_gray.h +index 347b5c8..d5fc39d 100644 +--- a/src/third_party/agg/include/agg_span_gouraud_gray.h ++++ b/src/third_party/agg/include/agg_span_gouraud_gray.h +@@ -108,9 +108,9 @@ namespace agg + + m_y2 = int(coord[1].y); + +- m_swap = calc_point_location(coord[0].x, coord[0].y, +- coord[2].x, coord[2].y, +- coord[1].x, coord[1].y) < 0.0; ++ m_swap = cross_product(coord[0].x, coord[0].y, ++ coord[2].x, coord[2].y, ++ coord[1].x, coord[1].y) < 0.0; + + m_c1.init(coord[0], coord[2]); + m_c2.init(coord[0], coord[1]); +diff --git a/src/third_party/agg/include/agg_span_gouraud_rgba.h b/src/third_party/agg/include/agg_span_gouraud_rgba.h +index 7c54833..89192d2 100644 +--- a/src/third_party/agg/include/agg_span_gouraud_rgba.h ++++ b/src/third_party/agg/include/agg_span_gouraud_rgba.h +@@ -120,9 +120,9 @@ namespace agg + + m_y2 = int(coord[1].y); + +- m_swap = calc_point_location(coord[0].x, coord[0].y, +- coord[2].x, coord[2].y, +- coord[1].x, coord[1].y) < 0.0; ++ m_swap = cross_product(coord[0].x, coord[0].y, ++ coord[2].x, coord[2].y, ++ coord[1].x, coord[1].y) < 0.0; + + m_rgba1.init(coord[0], coord[2]); + m_rgba2.init(coord[0], coord[1]); +diff --git a/src/third_party/agg/include/agg_span_image_filter.h b/src/third_party/agg/include/agg_span_image_filter.h +index 4832917..47e2f44 100644 +--- a/src/third_party/agg/include/agg_span_image_filter.h ++++ b/src/third_party/agg/include/agg_span_image_filter.h +@@ -46,6 +46,7 @@ namespace agg + m_dx_int(image_subpixel_scale / 2), + m_dy_int(image_subpixel_scale / 2) + {} ++ void attach(source_type& v) { m_src = &v; } + + //-------------------------------------------------------------------- + source_type& source() { return *m_src; } +@@ -57,7 +58,6 @@ namespace agg + double filter_dy_dbl() const { return m_dy_dbl; } + + //-------------------------------------------------------------------- +- void set_source(source_type& v) { m_src = &v; } + void interpolator(interpolator_type& v) { m_interpolator = &v; } + void filter(const image_filter_lut& v) { m_filter = &v; } + void filter_offset(double dx, double dy) +@@ -136,33 +136,29 @@ namespace agg + + base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y); + +- m_rx = image_subpixel_scale; +- m_ry = image_subpixel_scale; +- m_rx_inv = image_subpixel_scale; +- m_ry_inv = image_subpixel_scale; +- +- scale_x *= m_blur_x; +- scale_y *= m_blur_y; +- + if(scale_x * scale_y > m_scale_limit) + { + scale_x = scale_x * m_scale_limit / (scale_x * scale_y); + scale_y = scale_y * m_scale_limit / (scale_x * scale_y); + } + +- if(scale_x > 1.0001) +- { +- if(scale_x > m_scale_limit) scale_x = m_scale_limit; +- m_rx = uround( scale_x * double(image_subpixel_scale)); +- m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale)); +- } ++ if(scale_x < 1) scale_x = 1; ++ if(scale_y < 1) scale_y = 1; + +- if(scale_y > 1.0001) +- { +- if(scale_y > m_scale_limit) scale_y = m_scale_limit; +- m_ry = uround( scale_y * double(image_subpixel_scale)); +- m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale)); +- } ++ if(scale_x > m_scale_limit) scale_x = m_scale_limit; ++ if(scale_y > m_scale_limit) scale_y = m_scale_limit; ++ ++ scale_x *= m_blur_x; ++ scale_y *= m_blur_y; ++ ++ if(scale_x < 1) scale_x = 1; ++ if(scale_y < 1) scale_y = 1; ++ ++ m_rx = uround( scale_x * double(image_subpixel_scale)); ++ m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale)); ++ ++ m_ry = uround( scale_y * double(image_subpixel_scale)); ++ m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale)); + } + + protected: +@@ -219,6 +215,24 @@ namespace agg + m_blur_y = uround(v * double(image_subpixel_scale)); } + + protected: ++ AGG_INLINE void adjust_scale(int* rx, int* ry) ++ { ++ if(*rx < image_subpixel_scale) *rx = image_subpixel_scale; ++ if(*ry < image_subpixel_scale) *ry = image_subpixel_scale; ++ if(*rx > image_subpixel_scale * m_scale_limit) ++ { ++ *rx = image_subpixel_scale * m_scale_limit; ++ } ++ if(*ry > image_subpixel_scale * m_scale_limit) ++ { ++ *ry = image_subpixel_scale * m_scale_limit; ++ } ++ *rx = (*rx * m_blur_x) >> image_subpixel_shift; ++ *ry = (*ry * m_blur_y) >> image_subpixel_shift; ++ if(*rx < image_subpixel_scale) *rx = image_subpixel_scale; ++ if(*ry < image_subpixel_scale) *ry = image_subpixel_scale; ++ } ++ + int m_scale_limit; + int m_blur_x; + int m_blur_y; +diff --git a/src/third_party/agg/include/agg_span_image_filter_gray.h b/src/third_party/agg/include/agg_span_image_filter_gray.h +index bdc30e3..9f3ede7 100644 +--- a/src/third_party/agg/include/agg_span_image_filter_gray.h ++++ b/src/third_party/agg/include/agg_span_image_filter_gray.h +@@ -123,7 +123,6 @@ namespace agg + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + +- unsigned weight; + fg = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; +@@ -139,7 +138,7 @@ namespace agg + fg += *fg_ptr * (image_subpixel_scale - x_hr) * y_hr; + + fg_ptr = (const value_type*)base_type::source().next_x(); +- fg += fg_ptr * x_hr * y_hr; ++ fg += *fg_ptr * x_hr * y_hr; + + span->v = value_type(fg >> (image_subpixel_shift * 2)); + span->a = base_mask; +@@ -677,35 +676,10 @@ namespace agg + int ry_inv = image_subpixel_scale; + base_type::interpolator().coordinates(&x, &y); + base_type::interpolator().local_scale(&rx, &ry); ++ base_type::adjust_scale(&rx, &ry); + +- rx = (rx * base_type::m_blur_x) >> image_subpixel_shift; +- ry = (ry * base_type::m_blur_y) >> image_subpixel_shift; +- +- if(rx < image_subpixel_scale) +- { +- rx = image_subpixel_scale; +- } +- else +- { +- if(rx > image_subpixel_scale * base_type::m_scale_limit) +- { +- rx = image_subpixel_scale * base_type::m_scale_limit; +- } +- rx_inv = image_subpixel_scale * image_subpixel_scale / rx; +- } +- +- if(ry < image_subpixel_scale) +- { +- ry = image_subpixel_scale; +- } +- else +- { +- if(ry > image_subpixel_scale * base_type::m_scale_limit) +- { +- ry = image_subpixel_scale * base_type::m_scale_limit; +- } +- ry_inv = image_subpixel_scale * image_subpixel_scale / ry; +- } ++ rx_inv = image_subpixel_scale * image_subpixel_scale / rx; ++ ry_inv = image_subpixel_scale * image_subpixel_scale / ry; + + int radius_x = (diameter * rx) >> 1; + int radius_y = (diameter * ry) >> 1; +diff --git a/src/third_party/agg/include/agg_span_image_filter_rgb.h b/src/third_party/agg/include/agg_span_image_filter_rgb.h +index bd61436..a72ffd2 100644 +--- a/src/third_party/agg/include/agg_span_image_filter_rgb.h ++++ b/src/third_party/agg/include/agg_span_image_filter_rgb.h +@@ -808,35 +808,10 @@ namespace agg + int ry_inv = image_subpixel_scale; + base_type::interpolator().coordinates(&x, &y); + base_type::interpolator().local_scale(&rx, &ry); ++ base_type::adjust_scale(&rx, &ry); + +- rx = (rx * base_type::m_blur_x) >> image_subpixel_shift; +- ry = (ry * base_type::m_blur_y) >> image_subpixel_shift; +- +- if(rx < image_subpixel_scale) +- { +- rx = image_subpixel_scale; +- } +- else +- { +- if(rx > image_subpixel_scale * base_type::m_scale_limit) +- { +- rx = image_subpixel_scale * base_type::m_scale_limit; +- } +- rx_inv = image_subpixel_scale * image_subpixel_scale / rx; +- } +- +- if(ry < image_subpixel_scale) +- { +- ry = image_subpixel_scale; +- } +- else +- { +- if(ry > image_subpixel_scale * base_type::m_scale_limit) +- { +- ry = image_subpixel_scale * base_type::m_scale_limit; +- } +- ry_inv = image_subpixel_scale * image_subpixel_scale / ry; +- } ++ rx_inv = image_subpixel_scale * image_subpixel_scale / rx; ++ ry_inv = image_subpixel_scale * image_subpixel_scale / ry; + + int radius_x = (diameter * rx) >> 1; + int radius_y = (diameter * ry) >> 1; +diff --git a/src/third_party/agg/include/agg_span_image_filter_rgba.h b/src/third_party/agg/include/agg_span_image_filter_rgba.h +index 6d86fcb..d47085c 100644 +--- a/src/third_party/agg/include/agg_span_image_filter_rgba.h ++++ b/src/third_party/agg/include/agg_span_image_filter_rgba.h +@@ -226,7 +226,7 @@ namespace agg + value_type back_b = m_back_color.b; + value_type back_a = m_back_color.a; + +- const value_type *fg_ptr; ++ const value_type *fg_ptr = NULL; + int maxx = base_type::source().width() - 1; + int maxy = base_type::source().height() - 1; + +@@ -832,35 +832,10 @@ namespace agg + int ry_inv = image_subpixel_scale; + base_type::interpolator().coordinates(&x, &y); + base_type::interpolator().local_scale(&rx, &ry); ++ base_type::adjust_scale(&rx, &ry); + +- rx = (rx * base_type::m_blur_x) >> image_subpixel_shift; +- ry = (ry * base_type::m_blur_y) >> image_subpixel_shift; +- +- if(rx < image_subpixel_scale) +- { +- rx = image_subpixel_scale; +- } +- else +- { +- if(rx > image_subpixel_scale * base_type::m_scale_limit) +- { +- rx = image_subpixel_scale * base_type::m_scale_limit; +- } +- rx_inv = image_subpixel_scale * image_subpixel_scale / rx; +- } +- +- if(ry < image_subpixel_scale) +- { +- ry = image_subpixel_scale; +- } +- else +- { +- if(ry > image_subpixel_scale * base_type::m_scale_limit) +- { +- ry = image_subpixel_scale * base_type::m_scale_limit; +- } +- ry_inv = image_subpixel_scale * image_subpixel_scale / ry; +- } ++ rx_inv = image_subpixel_scale * image_subpixel_scale / rx; ++ ry_inv = image_subpixel_scale * image_subpixel_scale / ry; + + int radius_x = (diameter * rx) >> 1; + int radius_y = (diameter * ry) >> 1; +diff --git a/src/third_party/agg/include/agg_span_pattern_gray.h b/src/third_party/agg/include/agg_span_pattern_gray.h +index 83ae9c4..ae1a49f 100644 +--- a/src/third_party/agg/include/agg_span_pattern_gray.h ++++ b/src/third_party/agg/include/agg_span_pattern_gray.h +@@ -50,9 +50,9 @@ namespace agg + {} + + //-------------------------------------------------------------------- ++ void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } +- void set_source(source_type& v) { m_src = &v; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } +diff --git a/src/third_party/agg/include/agg_span_pattern_rgb.h b/src/third_party/agg/include/agg_span_pattern_rgb.h +index d401cb6..4850508 100644 +--- a/src/third_party/agg/include/agg_span_pattern_rgb.h ++++ b/src/third_party/agg/include/agg_span_pattern_rgb.h +@@ -51,9 +51,9 @@ namespace agg + {} + + //-------------------------------------------------------------------- ++ void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } +- void set_source(source_type& v) { m_src = &v; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } +diff --git a/src/third_party/agg/include/agg_span_pattern_rgba.h b/src/third_party/agg/include/agg_span_pattern_rgba.h +index 2725f83..d47d2a6 100644 +--- a/src/third_party/agg/include/agg_span_pattern_rgba.h ++++ b/src/third_party/agg/include/agg_span_pattern_rgba.h +@@ -50,9 +50,9 @@ namespace agg + {} + + //-------------------------------------------------------------------- ++ void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } +- void set_source(source_type& v) { m_src = &v; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } +@@ -75,7 +75,7 @@ namespace agg + span->g = p[order_type::G]; + span->b = p[order_type::B]; + span->a = p[order_type::A]; +- p = m_src->next_x(); ++ p = (const value_type*)m_src->next_x(); + ++span; + } + while(--len); +diff --git a/src/third_party/agg/include/agg_trans_affine.h b/src/third_party/agg/include/agg_trans_affine.h +index edf7ea7..ea5d9cf 100644 +--- a/src/third_party/agg/include/agg_trans_affine.h ++++ b/src/third_party/agg/include/agg_trans_affine.h +@@ -137,12 +137,6 @@ namespace agg + double x1, double y1, + double x2, double y2); + +- const trans_affine& rect_to_rect(double x1, double y1, +- double x2, double y2, +- double x3, double y3, +- double x4, double y4); +- +- + + //------------------------------------------ Operations + // Reset - actually load an identity matrix +@@ -201,14 +195,14 @@ namespace agg + + // Multiply current matrix to another one and return + // the result in a separete matrix. +- trans_affine operator * (const trans_affine& m) ++ trans_affine operator * (const trans_affine& m) const + { + return trans_affine(*this).multiply(m); + } + + // Multiply current matrix to inverse of another one + // and return the result in a separete matrix. +- trans_affine operator / (const trans_affine& m) ++ trans_affine operator / (const trans_affine& m) const + { + return trans_affine(*this).multiply_inv(m); + } +diff --git a/src/third_party/agg/include/agg_vcgen_contour.h b/src/third_party/agg/include/agg_vcgen_contour.h +index c56f026..8c25da1 100644 +--- a/src/third_party/agg/include/agg_vcgen_contour.h ++++ b/src/third_party/agg/include/agg_vcgen_contour.h +@@ -43,22 +43,27 @@ namespace agg + + vcgen_contour(); + +- void line_join(line_join_e lj) { m_line_join = lj; } +- void inner_join(inner_join_e ij) { m_inner_join = ij; } +- void width(double w) { m_width = w * 0.5; } +- void miter_limit(double ml) { m_miter_limit = ml; } +- void miter_limit_theta(double t); +- void inner_miter_limit(double ml) { m_inner_miter_limit = ml; } +- void approximation_scale(double as) { m_approx_scale = as; } +- void auto_detect_orientation(bool v) { m_auto_detect = v; } ++ void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); } ++ void line_join(line_join_e lj) { m_stroker.line_join(lj); } ++ void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); } ++ ++ line_cap_e line_cap() const { return m_stroker.line_cap(); } ++ line_join_e line_join() const { return m_stroker.line_join(); } ++ inner_join_e inner_join() const { return m_stroker.inner_join(); } ++ ++ void width(double w) { m_stroker.width(m_width = w); } ++ void miter_limit(double ml) { m_stroker.miter_limit(ml); } ++ void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); } ++ void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); } ++ void approximation_scale(double as) { m_stroker.approximation_scale(as); } + +- line_join_e line_join() const { return m_line_join; } +- inner_join_e inner_join() const { return m_inner_join; } +- double width() const { return m_width * 2.0; } +- double miter_limit() const { return m_miter_limit; } +- double inner_miter_limit() const { return m_inner_miter_limit; } +- double approximation_scale() const { return m_approx_scale; } +- bool auto_detect_orientation() const { return m_auto_detect; } ++ double width() const { return m_width; } ++ double miter_limit() const { return m_stroker.miter_limit(); } ++ double inner_miter_limit() const { return m_stroker.inner_miter_limit(); } ++ double approximation_scale() const { return m_stroker.approximation_scale(); } ++ ++ void auto_detect_orientation(bool v) { m_auto_detect = v; } ++ bool auto_detect_orientation() const { return m_auto_detect; } + + // Generator interface + void remove_all(); +@@ -72,22 +77,16 @@ namespace agg + vcgen_contour(const vcgen_contour&); + const vcgen_contour& operator = (const vcgen_contour&); + +- vertex_storage m_src_vertices; +- coord_storage m_out_vertices; +- double m_width; +- line_join_e m_line_join; +- inner_join_e m_inner_join; +- double m_approx_scale; +- double m_abs_width; +- double m_signed_width; +- double m_miter_limit; +- double m_inner_miter_limit; +- status_e m_status; +- unsigned m_src_vertex; +- unsigned m_out_vertex; +- unsigned m_closed; +- unsigned m_orientation; +- bool m_auto_detect; ++ math_stroke m_stroker; ++ double m_width; ++ vertex_storage m_src_vertices; ++ coord_storage m_out_vertices; ++ status_e m_status; ++ unsigned m_src_vertex; ++ unsigned m_out_vertex; ++ unsigned m_closed; ++ unsigned m_orientation; ++ bool m_auto_detect; + }; + + } +diff --git a/src/third_party/agg/include/agg_vcgen_stroke.h b/src/third_party/agg/include/agg_vcgen_stroke.h +index e0d9dc5..778223f 100644 +--- a/src/third_party/agg/include/agg_vcgen_stroke.h ++++ b/src/third_party/agg/include/agg_vcgen_stroke.h +@@ -51,24 +51,24 @@ namespace agg + + vcgen_stroke(); + +- void line_cap(line_cap_e lc) { m_line_cap = lc; } +- void line_join(line_join_e lj) { m_line_join = lj; } +- void inner_join(inner_join_e ij) { m_inner_join = ij; } ++ void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); } ++ void line_join(line_join_e lj) { m_stroker.line_join(lj); } ++ void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); } + +- line_cap_e line_cap() const { return m_line_cap; } +- line_join_e line_join() const { return m_line_join; } +- inner_join_e inner_join() const { return m_inner_join; } ++ line_cap_e line_cap() const { return m_stroker.line_cap(); } ++ line_join_e line_join() const { return m_stroker.line_join(); } ++ inner_join_e inner_join() const { return m_stroker.inner_join(); } + +- void width(double w) { m_width = w * 0.5; } +- void miter_limit(double ml) { m_miter_limit = ml; } +- void miter_limit_theta(double t); +- void inner_miter_limit(double ml) { m_inner_miter_limit = ml; } +- void approximation_scale(double as) { m_approx_scale = as; } ++ void width(double w) { m_stroker.width(w); } ++ void miter_limit(double ml) { m_stroker.miter_limit(ml); } ++ void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); } ++ void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); } ++ void approximation_scale(double as) { m_stroker.approximation_scale(as); } + +- double width() const { return m_width * 2.0; } +- double miter_limit() const { return m_miter_limit; } +- double inner_miter_limit() const { return m_inner_miter_limit; } +- double approximation_scale() const { return m_approx_scale; } ++ double width() const { return m_stroker.width(); } ++ double miter_limit() const { return m_stroker.miter_limit(); } ++ double inner_miter_limit() const { return m_stroker.inner_miter_limit(); } ++ double approximation_scale() const { return m_stroker.approximation_scale(); } + + void shorten(double s) { m_shorten = s; } + double shorten() const { return m_shorten; } +@@ -85,21 +85,15 @@ namespace agg + vcgen_stroke(const vcgen_stroke&); + const vcgen_stroke& operator = (const vcgen_stroke&); + +- vertex_storage m_src_vertices; +- coord_storage m_out_vertices; +- double m_width; +- double m_miter_limit; +- double m_inner_miter_limit; +- double m_approx_scale; +- double m_shorten; +- line_cap_e m_line_cap; +- line_join_e m_line_join; +- inner_join_e m_inner_join; +- unsigned m_closed; +- status_e m_status; +- status_e m_prev_status; +- unsigned m_src_vertex; +- unsigned m_out_vertex; ++ math_stroke m_stroker; ++ vertex_storage m_src_vertices; ++ coord_storage m_out_vertices; ++ double m_shorten; ++ unsigned m_closed; ++ status_e m_status; ++ status_e m_prev_status; ++ unsigned m_src_vertex; ++ unsigned m_out_vertex; + }; + + +diff --git a/src/third_party/agg/include/agg_vertex_sequence.h b/src/third_party/agg/include/agg_vertex_sequence.h +index f9bc915..2ad0701 100644 +--- a/src/third_party/agg/include/agg_vertex_sequence.h ++++ b/src/third_party/agg/include/agg_vertex_sequence.h +@@ -30,7 +30,7 @@ namespace agg + // Modified agg::pod_bvector. The data is interpreted as a sequence + // of vertices. It means that the type T must expose: + // +- // bool operator() (const T& val) ++ // bool T::operator() (const T& val) + // + // that is called every time new vertex is being added. The main purpose + // of this operator is the possibility to calculate some values during +diff --git a/src/third_party/agg/include/agg_vpgen_clip_polyline.h b/src/third_party/agg/include/agg_vpgen_clip_polyline.h +index 6f09856..b070a77 100644 +--- a/src/third_party/agg/include/agg_vpgen_clip_polyline.h ++++ b/src/third_party/agg/include/agg_vpgen_clip_polyline.h +@@ -32,12 +32,9 @@ namespace agg + m_clip_box(0, 0, 1, 1), + m_x1(0), + m_y1(0), +- m_f1(0), +- m_x2(0), +- m_y2(0), +- m_f2(0), + m_num_vertices(0), +- m_vertex(0) ++ m_vertex(0), ++ m_move_to(false) + { + } + +@@ -50,7 +47,6 @@ namespace agg + 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; } +@@ -64,55 +60,16 @@ namespace agg + 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; ++ bool m_move_to; + }; + + } +diff --git a/src/third_party/agg/include/dbg_new/agg_dbg_new.h b/src/third_party/agg/include/dbg_new/agg_dbg_new.h +new file mode 100644 +index 0000000..687358d +--- /dev/null ++++ b/src/third_party/agg/include/dbg_new/agg_dbg_new.h +@@ -0,0 +1,79 @@ ++//---------------------------------------------------------------------------- ++// Anti-Grain Geometry - Version 2.2 ++// Copyright (C) 2002-2004 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 ++//---------------------------------------------------------------------------- ++// ++// Debuging stuff for catching memory leaks and corruptions ++// ++//---------------------------------------------------------------------------- ++#ifndef AGG_DBG_NEW_INCLUDED ++#define AGG_DBG_NEW_INCLUDED ++ ++#ifdef _WIN32 ++#include ++#include ++#endif ++ ++//#define AGG_DBG_NEW_CHECK_ADDR ++ ++void* operator new (unsigned size, const char* file, int line); ++void* operator new [] (unsigned size, const char* file, int line); ++#define AGG_DBG_NEW_OPERATOR new(__FILE__, __LINE__) ++ ++void operator delete(void *ptr) throw(); ++void operator delete [] (void *ptr) throw(); ++ ++namespace agg ++{ ++ #ifdef _WIN32 ++ inline void printf(char* fmt, ...) ++ { ++ FILE* fd = fopen("stdout.txt", "at"); ++ static char msg[1024]; ++ va_list arg; ++ va_start(arg, fmt); ++ vsprintf(msg, fmt, arg); ++ va_end(arg); ++ fputs(msg, fd); ++ fclose(fd); ++ } ++ #endif ++ ++ enum { max_dbg_new_level = 32 }; ++ ++#ifdef AGG_DBG_NEW_CHECK_ADDR ++ enum { max_allocations = 4096 }; ++#endif ++ ++ // All you need to watch for memory in heap is to declare an object ++ // of this class in your main() or whatever function you need. ++ // It will report you about all bad things happend to new/delete. ++ // Try not to exceed the maximal nested level of declared watchdoggies ++ // (max_dbg_new_level) ++ class watchdoggy ++ { ++ public: ++ watchdoggy(const char* file=0, int line=0, bool report_all=false); ++ ~watchdoggy(); ++ }; ++} ++ ++#define AGG_WATCHDOGGY(name, report_all) \ ++ agg::watchdoggy name(__FILE__, __LINE__, report_all); ++#endif ++ ++#ifdef new ++#undef new ++#endif ++#define new AGG_DBG_NEW_OPERATOR ++ +diff --git a/src/third_party/agg/include/util/agg_color_conv.h b/src/third_party/agg/include/util/agg_color_conv.h +index 6e27690..fd7aeea 100644 +--- a/src/third_party/agg/include/util/agg_color_conv.h ++++ b/src/third_party/agg/include/util/agg_color_conv.h +@@ -1,6 +1,6 @@ + //---------------------------------------------------------------------------- +-// Anti-Grain Geometry - Version 2.4 +-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) ++// Anti-Grain Geometry - Version 2.2 ++// Copyright (C) 2002-2004 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. +@@ -31,8 +31,10 @@ namespace agg + { + + //--------------------------------------------------------------color_conv +- template +- void color_conv(RenBuf* dst, const RenBuf* src, CopyRow copy_row_functor) ++ template ++ void color_conv(rendering_buffer* dst, ++ const rendering_buffer* src, ++ CopyRow copy_row_functor) + { + unsigned width = src->width(); + unsigned height = src->height(); +@@ -45,9 +47,7 @@ namespace agg + unsigned y; + for(y = 0; y < height; y++) + { +- copy_row_functor(dst->row_ptr(0, y, width), +- src->row_ptr(y), +- width); ++ copy_row_functor(dst->row(y), src->row(y), width); + } + } + } +@@ -55,8 +55,8 @@ namespace agg + + //---------------------------------------------------------color_conv_row + template +- void color_conv_row(int8u* dst, +- const int8u* src, ++ void color_conv_row(unsigned char* dst, ++ const unsigned char* src, + unsigned width, + CopyRow copy_row_functor) + { +@@ -68,8 +68,8 @@ namespace agg + template class color_conv_same + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + memmove(dst, src, width*BPP); +diff --git a/src/third_party/agg/include/util/agg_color_conv_rgb16.h b/src/third_party/agg/include/util/agg_color_conv_rgb16.h +deleted file mode 100644 +index aaa4132..0000000 +--- a/src/third_party/agg/include/util/agg_color_conv_rgb16.h ++++ /dev/null +@@ -1,285 +0,0 @@ +-//---------------------------------------------------------------------------- +-// Anti-Grain Geometry - Version 2.4 +-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +-// +-// Permission to copy, use, modify, sell and distribute this software +-// is granted provided this copyright notice appears in all copies. +-// This software is provided "as is" without express or implied +-// warranty, and with no claim as to its suitability for any purpose. +-// +-//---------------------------------------------------------------------------- +-// Contact: mcseem@antigrain.com +-// mcseemagg@yahoo.com +-// http://www.antigrain.com +-//---------------------------------------------------------------------------- +-// +-// This part of the library 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. +-// +-//---------------------------------------------------------------------------- +-// +-// A set of functors used with color_conv(). See file agg_color_conv.h +-// These functors can convert images with up to 8 bits per component. +-// Use convertors in the following way: +-// +-// agg::color_conv(dst, src, agg::color_conv_XXXX_to_YYYY()); +-//---------------------------------------------------------------------------- +- +-#ifndef AGG_COLOR_CONV_RGB16_INCLUDED +-#define AGG_COLOR_CONV_RGB16_INCLUDED +- +-#include "agg_basics.h" +-#include "agg_color_conv.h" +- +-namespace agg +-{ +- +- //-------------------------------------------------color_conv_gray16_to_gray8 +- class color_conv_gray16_to_gray8 +- { +- public: +- void operator () (int8u* dst, +- const int8u* src, +- unsigned width) const +- { +- int16u* s = (int16u*)src; +- do +- { +- *dst++ = *s++ >> 8; +- } +- while(--width); +- } +- }; +- +- +- //-----------------------------------------------------color_conv_rgb24_rgb48 +- template class color_conv_rgb24_rgb48 +- { +- public: +- void operator () (int8u* dst, +- const int8u* src, +- unsigned width) const +- { +- int16u* d = (int16u*)dst; +- do +- { +- *d++ = (src[I1] << 8) | src[I1]; +- *d++ = (src[1] << 8) | src[1] ; +- *d++ = (src[I3] << 8) | src[I3]; +- src += 3; +- } +- while(--width); +- } +- }; +- +- typedef color_conv_rgb24_rgb48<0,2> color_conv_rgb24_to_rgb48; +- typedef color_conv_rgb24_rgb48<0,2> color_conv_bgr24_to_bgr48; +- typedef color_conv_rgb24_rgb48<2,0> color_conv_rgb24_to_bgr48; +- typedef color_conv_rgb24_rgb48<2,0> color_conv_bgr24_to_rgb48; +- +- +- //-----------------------------------------------------color_conv_rgb24_rgb48 +- template class color_conv_rgb48_rgb24 +- { +- public: +- void operator () (int8u* dst, +- const int8u* src, +- unsigned width) const +- { +- const int16u* s = (const int16u*)src; +- do +- { +- *dst++ = s[I1] >> 8; +- *dst++ = s[1] >> 8; +- *dst++ = s[I3] >> 8; +- s += 3; +- } +- while(--width); +- } +- }; +- +- typedef color_conv_rgb48_rgb24<0,2> color_conv_rgb48_to_rgb24; +- typedef color_conv_rgb48_rgb24<0,2> color_conv_bgr48_to_bgr24; +- typedef color_conv_rgb48_rgb24<2,0> color_conv_rgb48_to_bgr24; +- typedef color_conv_rgb48_rgb24<2,0> color_conv_bgr48_to_rgb24; +- +- +- //----------------------------------------------color_conv_rgbAAA_rgb24 +- template class color_conv_rgbAAA_rgb24 +- { +- public: +- void operator () (int8u* dst, +- const int8u* src, +- unsigned width) const +- { +- do +- { +- int32u rgb = *(int32u*)src; +- dst[R] = int8u(rgb >> 22); +- dst[1] = int8u(rgb >> 12); +- dst[B] = int8u(rgb >> 2); +- src += 4; +- dst += 3; +- } +- while(--width); +- } +- }; +- +- typedef color_conv_rgbAAA_rgb24<0,2> color_conv_rgbAAA_to_rgb24; +- typedef color_conv_rgbAAA_rgb24<2,0> color_conv_rgbAAA_to_bgr24; +- typedef color_conv_rgbAAA_rgb24<2,0> color_conv_bgrAAA_to_rgb24; +- typedef color_conv_rgbAAA_rgb24<0,2> color_conv_bgrAAA_to_bgr24; +- +- +- //----------------------------------------------color_conv_rgbBBA_rgb24 +- template class color_conv_rgbBBA_rgb24 +- { +- public: +- void operator () (int8u* dst, +- const int8u* src, +- unsigned width) const +- { +- do +- { +- int32u rgb = *(int32u*)src; +- dst[R] = int8u(rgb >> 24); +- dst[1] = int8u(rgb >> 13); +- dst[B] = int8u(rgb >> 2); +- src += 4; +- dst += 3; +- } +- while(--width); +- } +- }; +- +- typedef color_conv_rgbBBA_rgb24<0,2> color_conv_rgbBBA_to_rgb24; +- typedef color_conv_rgbBBA_rgb24<2,0> color_conv_rgbBBA_to_bgr24; +- +- +- //----------------------------------------------color_conv_bgrABB_rgb24 +- template class color_conv_bgrABB_rgb24 +- { +- public: +- void operator () (int8u* dst, +- const int8u* src, +- unsigned width) const +- { +- do +- { +- int32u bgr = *(int32u*)src; +- dst[R] = int8u(bgr >> 3); +- dst[1] = int8u(bgr >> 14); +- dst[B] = int8u(bgr >> 24); +- src += 4; +- dst += 3; +- } +- while(--width); +- } +- }; +- +- typedef color_conv_bgrABB_rgb24<2,0> color_conv_bgrABB_to_rgb24; +- typedef color_conv_bgrABB_rgb24<0,2> color_conv_bgrABB_to_bgr24; +- +- +- //-------------------------------------------------color_conv_rgba64_rgba32 +- template class color_conv_rgba64_rgba32 +- { +- public: +- void operator () (int8u* dst, +- const int8u* src, +- unsigned width) const +- { +- do +- { +- *dst++ = int8u(((int16u*)src)[I1] >> 8); +- *dst++ = int8u(((int16u*)src)[I2] >> 8); +- *dst++ = int8u(((int16u*)src)[I3] >> 8); +- *dst++ = int8u(((int16u*)src)[I4] >> 8); +- src += 8; +- } +- while(--width); +- } +- }; +- +- //------------------------------------------------------------------------ +- typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_rgba64_to_rgba32; //----color_conv_rgba64_to_rgba32 +- typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_argb64_to_argb32; //----color_conv_argb64_to_argb32 +- typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_bgra64_to_bgra32; //----color_conv_bgra64_to_bgra32 +- typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_abgr64_to_abgr32; //----color_conv_abgr64_to_abgr32 +- typedef color_conv_rgba64_rgba32<0,3,2,1> color_conv_argb64_to_abgr32; //----color_conv_argb64_to_abgr32 +- typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_argb64_to_bgra32; //----color_conv_argb64_to_bgra32 +- typedef color_conv_rgba64_rgba32<1,2,3,0> color_conv_argb64_to_rgba32; //----color_conv_argb64_to_rgba32 +- typedef color_conv_rgba64_rgba32<3,0,1,2> color_conv_bgra64_to_abgr32; //----color_conv_bgra64_to_abgr32 +- typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_bgra64_to_argb32; //----color_conv_bgra64_to_argb32 +- typedef color_conv_rgba64_rgba32<2,1,0,3> color_conv_bgra64_to_rgba32; //----color_conv_bgra64_to_rgba32 +- typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_rgba64_to_abgr32; //----color_conv_rgba64_to_abgr32 +- typedef color_conv_rgba64_rgba32<3,0,1,2> color_conv_rgba64_to_argb32; //----color_conv_rgba64_to_argb32 +- typedef color_conv_rgba64_rgba32<2,1,0,3> color_conv_rgba64_to_bgra32; //----color_conv_rgba64_to_bgra32 +- typedef color_conv_rgba64_rgba32<0,3,2,1> color_conv_abgr64_to_argb32; //----color_conv_abgr64_to_argb32 +- typedef color_conv_rgba64_rgba32<1,2,3,0> color_conv_abgr64_to_bgra32; //----color_conv_abgr64_to_bgra32 +- typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_abgr64_to_rgba32; //----color_conv_abgr64_to_rgba32 +- +- +- +- //--------------------------------------------color_conv_rgb24_rgba64 +- template class color_conv_rgb24_rgba64 +- { +- public: +- void operator () (int8u* dst, +- const int8u* src, +- unsigned width) const +- { +- int16u* d = (int16u*)dst; +- do +- { +- d[I1] = (src[0] << 8) | src[0]; +- d[I2] = (src[1] << 8) | src[1]; +- d[I3] = (src[2] << 8) | src[2]; +- d[A] = 65535; +- d += 4; +- src += 3; +- } +- while(--width); +- } +- }; +- +- +- //------------------------------------------------------------------------ +- typedef color_conv_rgb24_rgba64<1,2,3,0> color_conv_rgb24_to_argb64; //----color_conv_rgb24_to_argb64 +- typedef color_conv_rgb24_rgba64<3,2,1,0> color_conv_rgb24_to_abgr64; //----color_conv_rgb24_to_abgr64 +- typedef color_conv_rgb24_rgba64<2,1,0,3> color_conv_rgb24_to_bgra64; //----color_conv_rgb24_to_bgra64 +- typedef color_conv_rgb24_rgba64<0,1,2,3> color_conv_rgb24_to_rgba64; //----color_conv_rgb24_to_rgba64 +- typedef color_conv_rgb24_rgba64<3,2,1,0> color_conv_bgr24_to_argb64; //----color_conv_bgr24_to_argb64 +- typedef color_conv_rgb24_rgba64<1,2,3,0> color_conv_bgr24_to_abgr64; //----color_conv_bgr24_to_abgr64 +- typedef color_conv_rgb24_rgba64<0,1,2,3> color_conv_bgr24_to_bgra64; //----color_conv_bgr24_to_bgra64 +- typedef color_conv_rgb24_rgba64<2,1,0,3> color_conv_bgr24_to_rgba64; //----color_conv_bgr24_to_rgba64 +- +- +- template class color_conv_rgb24_gray16 +- { +- public: +- void operator () (int8u* dst, +- const int8u* src, +- unsigned width) const +- { +- int16u* d = (int16u*)dst; +- do +- { +- *d++ = src[R]*77 + src[1]*150 + src[B]*29; +- src += 3; +- } +- while(--width); +- } +- }; +- +- typedef color_conv_rgb24_gray16<0,2> color_conv_rgb24_to_gray16; +- typedef color_conv_rgb24_gray16<2,0> color_conv_bgr24_to_gray16; +- +- +-} +- +- +-#endif +diff --git a/src/third_party/agg/include/util/agg_color_conv_rgb8.h b/src/third_party/agg/include/util/agg_color_conv_rgb8.h +index 4268b5a..fdf9cf4 100644 +--- a/src/third_party/agg/include/util/agg_color_conv_rgb8.h ++++ b/src/third_party/agg/include/util/agg_color_conv_rgb8.h +@@ -1,6 +1,6 @@ + //---------------------------------------------------------------------------- +-// Anti-Grain Geometry - Version 2.4 +-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) ++// Anti-Grain Geometry - Version 2.2 ++// Copyright (C) 2002-2004 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. +@@ -42,8 +42,8 @@ namespace agg + class color_conv_rgb24 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do +@@ -69,8 +69,8 @@ namespace agg + template class color_conv_rgba32 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do +@@ -111,8 +111,8 @@ namespace agg + template class color_conv_rgb24_rgba32 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do +@@ -144,8 +144,8 @@ namespace agg + template class color_conv_rgba32_rgb24 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do +@@ -176,16 +176,16 @@ namespace agg + template class color_conv_rgb555_rgb24 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do + { + unsigned rgb = *(int16u*)src; +- dst[R] = (int8u)((rgb >> 7) & 0xF8); +- dst[1] = (int8u)((rgb >> 2) & 0xF8); +- dst[B] = (int8u)((rgb << 3) & 0xF8); ++ dst[R] = (unsigned char)((rgb >> 7) & 0xF8); ++ dst[1] = (unsigned char)((rgb >> 2) & 0xF8); ++ dst[B] = (unsigned char)((rgb << 3) & 0xF8); + src += 2; + dst += 3; + } +@@ -203,8 +203,8 @@ namespace agg + template class color_conv_rgb24_rgb555 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do +@@ -229,8 +229,8 @@ namespace agg + template class color_conv_rgb565_rgb24 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do +@@ -256,8 +256,8 @@ namespace agg + template class color_conv_rgb24_rgb565 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do +@@ -283,8 +283,8 @@ namespace agg + template class color_conv_rgb555_rgba32 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do +@@ -313,8 +313,8 @@ namespace agg + template class color_conv_rgba32_rgb555 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do +@@ -343,8 +343,8 @@ namespace agg + template class color_conv_rgb565_rgba32 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do +@@ -373,8 +373,8 @@ namespace agg + template class color_conv_rgba32_rgb565 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do +@@ -401,8 +401,8 @@ namespace agg + class color_conv_rgb555_to_rgb565 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do +@@ -421,8 +421,8 @@ namespace agg + class color_conv_rgb565_to_rgb555 + { + public: +- void operator () (int8u* dst, +- const int8u* src, ++ void operator () (unsigned char* dst, ++ const unsigned char* src, + unsigned width) const + { + do +@@ -440,27 +440,7 @@ namespace agg + //------------------------------------------------------------------------ + typedef color_conv_same<2> color_conv_rgb555_to_rgb555; //----color_conv_rgb555_to_rgb555 + typedef color_conv_same<2> color_conv_rgb565_to_rgb565; //----color_conv_rgb565_to_rgb565 +- + +- template class color_conv_rgb24_gray8 +- { +- public: +- void operator () (int8u* dst, +- const int8u* src, +- unsigned width) const +- { +- do +- { +- *dst++ = (src[R]*77 + src[1]*150 + src[B]*29) >> 8; +- src += 3; +- } +- while(--width); +- } +- }; +- +- typedef color_conv_rgb24_gray8<0,2> color_conv_rgb24_to_gray8; //----color_conv_rgb24_to_gray8 +- typedef color_conv_rgb24_gray8<2,0> color_conv_bgr24_to_gray8; //----color_conv_bgr24_to_gray8 +- + + } + +diff --git a/src/third_party/agg/src/agg_bspline.cpp b/src/third_party/agg/src/agg_bspline.cpp +index 2dc4e1b..e1fda9f 100644 +--- a/src/third_party/agg/src/agg_bspline.cpp ++++ b/src/third_party/agg/src/agg_bspline.cpp +@@ -17,26 +17,16 @@ + // + //---------------------------------------------------------------------------- + +- + #include "agg_bspline.h" + + namespace agg + { +- +- //------------------------------------------------------------------------ +- bspline::~bspline() +- { +- delete [] m_am; +- } +- +- + //------------------------------------------------------------------------ + bspline::bspline() : + m_max(0), + m_num(0), + m_x(0), + m_y(0), +- m_am(0), + m_last_idx(-1) + { + } +@@ -47,7 +37,6 @@ namespace agg + m_num(0), + m_x(0), + m_y(0), +- m_am(0), + m_last_idx(-1) + { + init(num); +@@ -59,7 +48,6 @@ namespace agg + m_num(0), + m_x(0), + m_y(0), +- m_am(0), + m_last_idx(-1) + { + init(num, x, y); +@@ -71,11 +59,10 @@ namespace agg + { + if(max > 2 && max > m_max) + { +- delete [] m_am; +- m_am = new double[max * 3]; ++ m_am.resize(max * 3); + m_max = max; +- m_x = m_am + m_max; +- m_y = m_am + m_max * 2; ++ m_x = &m_am[m_max]; ++ m_y = &m_am[m_max * 2]; + } + m_num = 0; + m_last_idx = -1; +@@ -103,7 +90,6 @@ namespace agg + double* temp; + double* r; + double* s; +- double* al; + double h, p, d, f, e; + + for(k = 0; k < m_num; k++) +@@ -113,8 +99,8 @@ namespace agg + + n1 = 3 * m_num; + +- al = new double[n1]; +- temp = al; ++ pod_array al(n1); ++ temp = &al[0]; + + for(k = 0; k < n1; k++) + { +@@ -155,7 +141,6 @@ namespace agg + al[k] = al[k] * al[k + 1] + s[k]; + m_am[k] = al[k]; + } +- delete [] al; + } + m_last_idx = -1; + } +diff --git a/src/third_party/agg/src/agg_curves.cpp b/src/third_party/agg/src/agg_curves.cpp +index 5cdf65e..4701734 100644 +--- a/src/third_party/agg/src/agg_curves.cpp ++++ b/src/third_party/agg/src/agg_curves.cpp +@@ -82,9 +82,6 @@ namespace agg + m_step = m_num_steps; + } + +- +- +- + //------------------------------------------------------------------------ + void curve3_inc::rewind(unsigned) + { +@@ -100,9 +97,6 @@ namespace agg + m_dfy = m_saved_dfy; + } + +- +- +- + //------------------------------------------------------------------------ + unsigned curve3_inc::vertex(double* x, double* y) + { +@@ -131,7 +125,6 @@ namespace agg + return path_cmd_line_to; + } + +- + //------------------------------------------------------------------------ + void curve3_div::init(double x1, double y1, + double x2, double y2, +@@ -140,12 +133,10 @@ namespace agg + m_points.remove_all(); + m_distance_tolerance_square = 0.5 / m_approximation_scale; + m_distance_tolerance_square *= m_distance_tolerance_square; +- m_distance_tolerance_manhattan = 4.0 / m_approximation_scale; + bezier(x1, y1, x2, y2, x3, y3); + m_count = 0; + } + +- + //------------------------------------------------------------------------ + void curve3_div::recursive_bezier(double x1, double y1, + double x2, double y2, +@@ -169,10 +160,11 @@ namespace agg + double dx = x3-x1; + double dy = y3-y1; + double d = fabs(((x2 - x3) * dy - (y2 - y3) * dx)); ++ double da; + + if(d > curve_collinearity_epsilon) + { +- // Regular care ++ // Regular case + //----------------- + if(d * d <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { +@@ -187,7 +179,7 @@ namespace agg + + // Angle & Cusp Condition + //---------------------- +- double da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); ++ da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); + if(da >= pi) da = 2*pi - da; + + if(da < m_angle_tolerance) +@@ -201,12 +193,31 @@ namespace agg + } + else + { +- if(fabs(x1 + x3 - x2 - x2) + +- fabs(y1 + y3 - y2 - y2) <= m_distance_tolerance_manhattan) ++ // Collinear case ++ //------------------ ++ da = dx*dx + dy*dy; ++ if(da == 0) ++ { ++ d = calc_sq_distance(x1, y1, x2, y2); ++ } ++ else ++ { ++ d = ((x2 - x1)*dx + (y2 - y1)*dy) / da; ++ if(d > 0 && d < 1) ++ { ++ // Simple collinear case, 1---2---3 ++ // We can leave just two endpoints ++ return; ++ } ++ if(d <= 0) d = calc_sq_distance(x2, y2, x1, y1); ++ else if(d >= 1) d = calc_sq_distance(x2, y2, x3, y3); ++ else d = calc_sq_distance(x2, y2, x1 + d*dx, y1 + d*dy); ++ } ++ if(d < m_distance_tolerance_square) + { +- m_points.add(point_d(x123, y123)); ++ m_points.add(point_d(x2, y2)); + return; +- } ++ } + } + + // Continue subdivision +@@ -241,8 +252,10 @@ namespace agg + return m_scale; + } + ++#if defined(_MSC_VER) && _MSC_VER <= 1200 + //------------------------------------------------------------------------ + static double MSC60_fix_ICE(double v) { return v; } ++#endif + + //------------------------------------------------------------------------ + void curve4_inc::init(double x1, double y1, +@@ -262,9 +275,9 @@ namespace agg + double dx3 = x4 - x3; + double dy3 = y4 - y3; + +- double len = sqrt(dx1 * dx1 + dy1 * dy1) + +- sqrt(dx2 * dx2 + dy2 * dy2) + +- sqrt(dx3 * dx3 + dy3 * dy3) * 0.25 * m_scale; ++ double len = (sqrt(dx1 * dx1 + dy1 * dy1) + ++ sqrt(dx2 * dx2 + dy2 * dy2) + ++ sqrt(dx3 * dx3 + dy3 * dy3)) * 0.25 * m_scale; + + #if defined(_MSC_VER) && _MSC_VER <= 1200 + m_num_steps = uround(MSC60_fix_ICE(len)); +@@ -307,9 +320,6 @@ namespace agg + m_step = m_num_steps; + } + +- +- +- + //------------------------------------------------------------------------ + void curve4_inc::rewind(unsigned) + { +@@ -327,10 +337,6 @@ namespace agg + m_ddfy = m_saved_ddfy; + } + +- +- +- +- + //------------------------------------------------------------------------ + unsigned curve4_inc::vertex(double* x, double* y) + { +@@ -376,12 +382,10 @@ namespace agg + m_points.remove_all(); + m_distance_tolerance_square = 0.5 / m_approximation_scale; + m_distance_tolerance_square *= m_distance_tolerance_square; +- m_distance_tolerance_manhattan = 4.0 / m_approximation_scale; + bezier(x1, y1, x2, y2, x3, y3, x4, y4); + m_count = 0; + } + +- + //------------------------------------------------------------------------ + void curve4_div::recursive_bezier(double x1, double y1, + double x2, double y2, +@@ -409,6 +413,7 @@ namespace agg + double x1234 = (x123 + x234) / 2; + double y1234 = (y123 + y234) / 2; + ++ + // Try to approximate the full cubic curve by a single straight line + //------------------ + double dx = x4-x1; +@@ -416,7 +421,7 @@ namespace agg + + double d2 = fabs(((x2 - x4) * dy - (y2 - y4) * dx)); + double d3 = fabs(((x3 - x4) * dy - (y3 - y4) * dx)); +- double da1, da2; ++ double da1, da2, k; + + switch((int(d2 > curve_collinearity_epsilon) << 1) + + int(d3 > curve_collinearity_epsilon)) +@@ -424,18 +429,55 @@ namespace agg + case 0: + // All collinear OR p1==p4 + //---------------------- +- if(fabs(x1 + x3 - x2 - x2) + +- fabs(y1 + y3 - y2 - y2) + +- fabs(x2 + x4 - x3 - x3) + +- fabs(y2 + y4 - y3 - y3) <= m_distance_tolerance_manhattan) ++ k = dx*dx + dy*dy; ++ if(k == 0) + { +- m_points.add(point_d(x1234, y1234)); +- return; +- } ++ d2 = calc_sq_distance(x1, y1, x2, y2); ++ d3 = calc_sq_distance(x4, y4, x3, y3); ++ } ++ else ++ { ++ k = 1 / k; ++ da1 = x2 - x1; ++ da2 = y2 - y1; ++ d2 = k * (da1*dx + da2*dy); ++ da1 = x3 - x1; ++ da2 = y3 - y1; ++ d3 = k * (da1*dx + da2*dy); ++ if(d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1) ++ { ++ // Simple collinear case, 1---2---3---4 ++ // We can leave just two endpoints ++ return; ++ } ++ if(d2 <= 0) d2 = calc_sq_distance(x2, y2, x1, y1); ++ else if(d2 >= 1) d2 = calc_sq_distance(x2, y2, x4, y4); ++ else d2 = calc_sq_distance(x2, y2, x1 + d2*dx, y1 + d2*dy); ++ ++ if(d3 <= 0) d3 = calc_sq_distance(x3, y3, x1, y1); ++ else if(d3 >= 1) d3 = calc_sq_distance(x3, y3, x4, y4); ++ else d3 = calc_sq_distance(x3, y3, x1 + d3*dx, y1 + d3*dy); ++ } ++ if(d2 > d3) ++ { ++ if(d2 < m_distance_tolerance_square) ++ { ++ m_points.add(point_d(x2, y2)); ++ return; ++ } ++ } ++ else ++ { ++ if(d3 < m_distance_tolerance_square) ++ { ++ m_points.add(point_d(x3, y3)); ++ return; ++ } ++ } + break; + + case 1: +- // p1,p2,p4 are collinear, p3 is considerable ++ // p1,p2,p4 are collinear, p3 is significant + //---------------------- + if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { +@@ -469,7 +511,7 @@ namespace agg + break; + + case 2: +- // p1,p3,p4 are collinear, p2 is considerable ++ // p1,p3,p4 are collinear, p2 is significant + //---------------------- + if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { +@@ -503,7 +545,7 @@ namespace agg + break; + + case 3: +- // Regular care ++ // Regular case + //----------------- + if((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { +@@ -518,9 +560,9 @@ namespace agg + + // Angle & Cusp Condition + //---------------------- +- double a23 = atan2(y3 - y2, x3 - x2); +- da1 = fabs(a23 - atan2(y2 - y1, x2 - x1)); +- da2 = fabs(atan2(y4 - y3, x4 - x3) - a23); ++ k = atan2(y3 - y2, x3 - x2); ++ da1 = fabs(k - atan2(y2 - y1, x2 - x1)); ++ da2 = fabs(atan2(y4 - y3, x4 - x3) - k); + if(da1 >= pi) da1 = 2*pi - da1; + if(da2 >= pi) da2 = 2*pi - da2; + +diff --git a/src/third_party/agg/src/agg_gsv_text.cpp b/src/third_party/agg/src/agg_gsv_text.cpp +index 0ccc64b..901e2c5 100644 +--- a/src/third_party/agg/src/agg_gsv_text.cpp ++++ b/src/third_party/agg/src/agg_gsv_text.cpp +@@ -480,16 +480,6 @@ namespace agg + 0xf6,0xfa,0x04,0x06,0x08,0xfa + }; + +- +- +- //------------------------------------------------------------------------- +- gsv_text::~gsv_text() +- { +- if(m_loaded_font) delete [] m_loaded_font; +- if(m_text_buf) delete [] m_text_buf; +- } +- +- + //------------------------------------------------------------------------- + gsv_text::gsv_text() : + m_x(0.0), +@@ -500,11 +490,10 @@ namespace agg + m_space(0.0), + m_line_space(0.0), + m_text(m_chr), +- m_text_buf(0), +- m_buf_size(0), ++ m_text_buf(), + m_cur_chr(m_chr), + m_font(gsv_default_font), +- m_loaded_font(0), ++ m_loaded_font(), + m_status(initial), + m_big_endian(false), + m_flip(false) +@@ -521,7 +510,7 @@ namespace agg + void gsv_text::font(const void* font) + { + m_font = font; +- if(m_font == 0) m_font = m_loaded_font; ++ if(m_font == 0) m_font = &m_loaded_font[0]; + } + + //------------------------------------------------------------------------- +@@ -555,9 +544,7 @@ namespace agg + //------------------------------------------------------------------------- + void gsv_text::load_font(const char* file) + { +- if(m_loaded_font) delete [] m_loaded_font; +- m_loaded_font = 0; +- ++ m_loaded_font.resize(0); + FILE* fd = fopen(file, "rb"); + if(fd) + { +@@ -568,9 +555,9 @@ namespace agg + fseek(fd, 0l, SEEK_SET); + if(len > 0) + { +- m_loaded_font = new char [len]; +- fread(m_loaded_font, 1, len, fd); +- m_font = m_loaded_font; ++ m_loaded_font.resize(len); ++ fread(&m_loaded_font[0], 1, len, fd); ++ m_font = &m_loaded_font[0]; + } + fclose(fd); + } +@@ -587,13 +574,12 @@ namespace agg + return; + } + unsigned new_size = strlen(text) + 1; +- if(new_size > m_buf_size) ++ if(new_size > m_text_buf.size()) + { +- if(m_text_buf) delete [] m_text_buf; +- m_text_buf = new char [m_buf_size = new_size]; ++ m_text_buf.resize(new_size); + } +- memcpy(m_text_buf, text, new_size); +- m_text = m_text_buf; ++ memcpy(&m_text_buf[0], text, new_size); ++ m_text = &m_text_buf[0]; + } + + +diff --git a/src/third_party/agg/src/agg_image_filters.cpp b/src/third_party/agg/src/agg_image_filters.cpp +index 531a056..549d9ad 100644 +--- a/src/third_party/agg/src/agg_image_filters.cpp ++++ b/src/third_party/agg/src/agg_image_filters.cpp +@@ -23,20 +23,6 @@ + + namespace agg + { +- +- //-------------------------------------------------------------------- +- image_filter_lut::~image_filter_lut() +- { +- delete [] m_weight_array; +- } +- +- +- //-------------------------------------------------------------------- +- image_filter_lut::image_filter_lut() : +- m_weight_array(0), +- m_max_size(0) +- {} +- + //-------------------------------------------------------------------- + void image_filter_lut::realloc_lut(double radius) + { +@@ -44,11 +30,9 @@ namespace agg + m_diameter = uceil(radius) * 2; + m_start = -int(m_diameter / 2 - 1); + unsigned size = m_diameter << image_subpixel_shift; +- if(size > m_max_size) ++ if(size > m_weight_array.size()) + { +- delete [] m_weight_array; +- m_weight_array = new int16 [size]; +- m_max_size = size; ++ m_weight_array.resize(size); + } + } + +diff --git a/src/third_party/agg/src/agg_line_aa_basics.cpp b/src/third_party/agg/src/agg_line_aa_basics.cpp +index ec6e854..018d653 100644 +--- a/src/third_party/agg/src/agg_line_aa_basics.cpp ++++ b/src/third_party/agg/src/agg_line_aa_basics.cpp +@@ -41,9 +41,9 @@ namespace agg + // (7)111 | 101(5) + // [2] | [3] + // <3> +- // 0,1,2,3,4,5,6,7 +- int8u line_parameters::s_orthogonal_quadrant[8] = { 0,0,1,1,3,3,2,2 }; +- int8u line_parameters::s_diagonal_quadrant[8] = { 0,1,2,1,0,3,2,3 }; ++ // 0,1,2,3,4,5,6,7 ++ const int8u line_parameters::s_orthogonal_quadrant[8] = { 0,0,1,1,3,3,2,2 }; ++ const int8u line_parameters::s_diagonal_quadrant[8] = { 0,1,2,1,0,3,2,3 }; + + + +diff --git a/src/third_party/agg/src/agg_line_profile_aa.cpp b/src/third_party/agg/src/agg_line_profile_aa.cpp +index 6646ded..6066662 100644 +--- a/src/third_party/agg/src/agg_line_profile_aa.cpp ++++ b/src/third_party/agg/src/agg_line_profile_aa.cpp +@@ -44,12 +44,11 @@ namespace agg + { + m_subpixel_width = uround(w * subpixel_scale); + unsigned size = m_subpixel_width + subpixel_scale * 6; +- if(size > m_size) ++ if(size > m_profile.size()) + { +- delete [] m_profile; +- m_profile = new value_type[m_size = size]; ++ m_profile.resize(size); + } +- return m_profile; ++ return &m_profile[0]; + } + + +diff --git a/src/third_party/agg/src/agg_trans_affine.cpp b/src/third_party/agg/src/agg_trans_affine.cpp +index 568f9f9..b8a1851 100644 +--- a/src/third_party/agg/src/agg_trans_affine.cpp ++++ b/src/third_party/agg/src/agg_trans_affine.cpp +@@ -66,26 +66,6 @@ namespace agg + return *this; + } + +- //------------------------------------------------------------------------ +- const trans_affine& trans_affine::rect_to_rect(double x1, double y1, +- double x2, double y2, +- double x3, double y3, +- double x4, double y4) +- { +- double src[6]; +- src[0] = x1; src[1] = y1; +- src[2] = x2; src[3] = y1; +- src[4] = x2; src[5] = y2; +- +- double dst[6]; +- dst[0] = x3; dst[1] = y3; +- dst[2] = x4; dst[3] = y3; +- dst[4] = x4; dst[5] = y4; +- +- parl_to_parl(src, dst); +- return *this; +- } +- + //------------------------------------------------------------------------ + const trans_affine& trans_affine::multiply(const trans_affine& m) + { +diff --git a/src/third_party/agg/src/agg_vcgen_contour.cpp b/src/third_party/agg/src/agg_vcgen_contour.cpp +index ae8f14a..a6a9940 100644 +--- a/src/third_party/agg/src/agg_vcgen_contour.cpp ++++ b/src/third_party/agg/src/agg_vcgen_contour.cpp +@@ -25,16 +25,10 @@ namespace agg + + //------------------------------------------------------------------------ + vcgen_contour::vcgen_contour() : ++ m_stroker(), ++ m_width(1), + m_src_vertices(), + m_out_vertices(), +- m_width(1.0), +- m_line_join(bevel_join), +- m_inner_join(inner_miter), +- m_approx_scale(1.0), +- m_abs_width(1.0), +- m_signed_width(1.0), +- m_miter_limit(4.0), +- m_inner_miter_limit(1.0 + 1.0/64.0), + m_status(initial), + m_src_vertex(0), + m_closed(0), +@@ -43,26 +37,15 @@ namespace agg + { + } + +- + //------------------------------------------------------------------------ + void vcgen_contour::remove_all() + { + m_src_vertices.remove_all(); + m_closed = 0; + m_orientation = 0; +- m_abs_width = fabs(m_width); +- m_signed_width = m_width; + m_status = initial; + } + +- +- //------------------------------------------------------------------------ +- void vcgen_contour::miter_limit_theta(double t) +- { +- m_miter_limit = 1.0 / sin(t * 0.5) ; +- } +- +- + //------------------------------------------------------------------------ + void vcgen_contour::add_vertex(double x, double y, unsigned cmd) + { +@@ -91,14 +74,12 @@ namespace agg + } + } + +- + //------------------------------------------------------------------------ + void vcgen_contour::rewind(unsigned) + { + if(m_status == initial) + { + m_src_vertices.close(true); +- m_signed_width = m_width; + if(m_auto_detect) + { + if(!is_oriented(m_orientation)) +@@ -110,14 +91,13 @@ namespace agg + } + if(is_oriented(m_orientation)) + { +- m_signed_width = is_ccw(m_orientation) ? m_width : -m_width; ++ m_stroker.width(is_ccw(m_orientation) ? m_width : -m_width); + } + } + m_status = ready; + m_src_vertex = 0; + } + +- + //------------------------------------------------------------------------ + unsigned vcgen_contour::vertex(double* x, double* y) + { +@@ -146,18 +126,12 @@ namespace agg + m_status = end_poly; + break; + } +- stroke_calc_join(m_out_vertices, +- m_src_vertices.prev(m_src_vertex), +- m_src_vertices.curr(m_src_vertex), +- m_src_vertices.next(m_src_vertex), +- m_src_vertices.prev(m_src_vertex).dist, +- m_src_vertices.curr(m_src_vertex).dist, +- m_signed_width, +- m_line_join, +- m_inner_join, +- m_miter_limit, +- m_inner_miter_limit, +- m_approx_scale); ++ m_stroker.calc_join(m_out_vertices, ++ m_src_vertices.prev(m_src_vertex), ++ m_src_vertices.curr(m_src_vertex), ++ m_src_vertices.next(m_src_vertex), ++ m_src_vertices.prev(m_src_vertex).dist, ++ m_src_vertices.curr(m_src_vertex).dist); + ++m_src_vertex; + m_status = out_vertices; + m_out_vertex = 0; +diff --git a/src/third_party/agg/src/agg_vcgen_dash.cpp b/src/third_party/agg/src/agg_vcgen_dash.cpp +index 1295057..582b53f 100644 +--- a/src/third_party/agg/src/agg_vcgen_dash.cpp ++++ b/src/third_party/agg/src/agg_vcgen_dash.cpp +@@ -54,7 +54,7 @@ namespace agg + //------------------------------------------------------------------------ + void vcgen_dash::add_dash(double dash_len, double gap_len) + { +- if(m_num_dashes < max_dashes) ++ if(m_num_dashes < max_dashes - 1) + { + m_total_dash_len += dash_len + gap_len; + m_dashes[m_num_dashes++] = dash_len; +diff --git a/src/third_party/agg/src/agg_vcgen_stroke.cpp b/src/third_party/agg/src/agg_vcgen_stroke.cpp +index c505f0f..2dae3e1 100644 +--- a/src/third_party/agg/src/agg_vcgen_stroke.cpp ++++ b/src/third_party/agg/src/agg_vcgen_stroke.cpp +@@ -25,16 +25,10 @@ namespace agg + + //------------------------------------------------------------------------ + vcgen_stroke::vcgen_stroke() : ++ m_stroker(), + m_src_vertices(), + m_out_vertices(), +- m_width(0.5), +- m_miter_limit(4.0), +- m_inner_miter_limit(1.01), +- m_approx_scale(1.0), + m_shorten(0.0), +- m_line_cap(butt_cap), +- m_line_join(miter_join), +- m_inner_join(inner_miter), + m_closed(0), + m_status(initial), + m_src_vertex(0), +@@ -42,14 +36,6 @@ namespace agg + { + } + +- +- //------------------------------------------------------------------------ +- void vcgen_stroke::miter_limit_theta(double t) +- { +- m_miter_limit = 1.0 / sin(t * 0.5) ; +- } +- +- + //------------------------------------------------------------------------ + void vcgen_stroke::remove_all() + { +@@ -80,22 +66,6 @@ namespace agg + } + } + +- +- //------------------------------------------------------------------------ +- static inline void calc_butt_cap(double* cap, +- const vertex_dist& v0, +- const vertex_dist& v1, +- double len, +- double width) +- { +- double dx = (v1.y - v0.y) * width / len; +- double dy = (v1.x - v0.x) * width / len; +- cap[0] = v0.x - dx; +- cap[1] = v0.y + dy; +- cap[2] = v0.x + dx; +- cap[3] = v0.y - dy; +- } +- + //------------------------------------------------------------------------ + void vcgen_stroke::rewind(unsigned) + { +@@ -135,13 +105,10 @@ namespace agg + break; + + case cap1: +- stroke_calc_cap(m_out_vertices, +- m_src_vertices[0], +- m_src_vertices[1], +- m_src_vertices[0].dist, +- m_line_cap, +- m_width, +- m_approx_scale); ++ m_stroker.calc_cap(m_out_vertices, ++ m_src_vertices[0], ++ m_src_vertices[1], ++ m_src_vertices[0].dist); + m_src_vertex = 1; + m_prev_status = outline1; + m_status = out_vertices; +@@ -149,13 +116,10 @@ namespace agg + break; + + case cap2: +- stroke_calc_cap(m_out_vertices, +- m_src_vertices[m_src_vertices.size() - 1], +- m_src_vertices[m_src_vertices.size() - 2], +- m_src_vertices[m_src_vertices.size() - 2].dist, +- m_line_cap, +- m_width, +- m_approx_scale); ++ m_stroker.calc_cap(m_out_vertices, ++ m_src_vertices[m_src_vertices.size() - 1], ++ m_src_vertices[m_src_vertices.size() - 2], ++ m_src_vertices[m_src_vertices.size() - 2].dist); + m_prev_status = outline2; + m_status = out_vertices; + m_out_vertex = 0; +@@ -179,18 +143,12 @@ namespace agg + break; + } + } +- stroke_calc_join(m_out_vertices, +- m_src_vertices.prev(m_src_vertex), +- m_src_vertices.curr(m_src_vertex), +- m_src_vertices.next(m_src_vertex), +- m_src_vertices.prev(m_src_vertex).dist, +- m_src_vertices.curr(m_src_vertex).dist, +- m_width, +- m_line_join, +- m_inner_join, +- m_miter_limit, +- m_inner_miter_limit, +- m_approx_scale); ++ m_stroker.calc_join(m_out_vertices, ++ m_src_vertices.prev(m_src_vertex), ++ m_src_vertices.curr(m_src_vertex), ++ m_src_vertices.next(m_src_vertex), ++ m_src_vertices.prev(m_src_vertex).dist, ++ m_src_vertices.curr(m_src_vertex).dist); + ++m_src_vertex; + m_prev_status = m_status; + m_status = out_vertices; +@@ -210,18 +168,12 @@ namespace agg + } + + --m_src_vertex; +- stroke_calc_join(m_out_vertices, +- m_src_vertices.next(m_src_vertex), +- m_src_vertices.curr(m_src_vertex), +- m_src_vertices.prev(m_src_vertex), +- m_src_vertices.curr(m_src_vertex).dist, +- m_src_vertices.prev(m_src_vertex).dist, +- m_width, +- m_line_join, +- m_inner_join, +- m_miter_limit, +- m_inner_miter_limit, +- m_approx_scale); ++ m_stroker.calc_join(m_out_vertices, ++ m_src_vertices.next(m_src_vertex), ++ m_src_vertices.curr(m_src_vertex), ++ m_src_vertices.prev(m_src_vertex), ++ m_src_vertices.curr(m_src_vertex).dist, ++ m_src_vertices.prev(m_src_vertex).dist); + + m_prev_status = m_status; + m_status = out_vertices; +diff --git a/src/third_party/agg/src/agg_vpgen_clip_polyline.cpp b/src/third_party/agg/src/agg_vpgen_clip_polyline.cpp +index 36d1247..6840803 100644 +--- a/src/third_party/agg/src/agg_vpgen_clip_polyline.cpp ++++ b/src/third_party/agg/src/agg_vpgen_clip_polyline.cpp +@@ -13,19 +13,17 @@ + // http://www.antigrain.com + //---------------------------------------------------------------------------- + +-#include + #include "agg_vpgen_clip_polyline.h" ++#include "agg_clip_liang_barsky.h" + + namespace agg + { +- static double clip_epsilon = 1e-10; +- +- + //---------------------------------------------------------------------------- + void vpgen_clip_polyline::reset() + { + m_vertex = 0; + m_num_vertices = 0; ++ m_move_to = false; + } + + //---------------------------------------------------------------------------- +@@ -33,99 +31,38 @@ namespace agg + { + m_vertex = 0; + m_num_vertices = 0; +- m_f1 = clipping_flags(x, y); +- if(m_f1 == 0) +- { +- m_x[0] = x; +- m_y[0] = y; +- m_cmd[0] = path_cmd_move_to; +- m_num_vertices = 1; +- } + m_x1 = x; + m_y1 = y; ++ m_move_to = true; + } + +- + //---------------------------------------------------------------------------- +- bool vpgen_clip_polyline::move_point(double& x, double& y, unsigned& flags) ++ void vpgen_clip_polyline::line_to(double x, double y) + { +- double bound; +- +- if(flags & (clip_x1 | clip_x2)) +- { +- bound = (flags & clip_x1) ? m_clip_box.x1 : m_clip_box.x2; +- y = (bound - m_x1) * (m_y2 - m_y1) / (m_x2 - m_x1) + m_y1; +- x = bound; +- flags = clipping_flags_y(y); +- } +- if(fabs(m_y2 - m_y1) < clip_epsilon && fabs(m_x2 - m_x1) < clip_epsilon) +- { +- return false; +- } +- if(flags & (clip_y1 | clip_y2)) +- { +- bound = (flags & clip_y1) ? m_clip_box.y1 : m_clip_box.y2; +- x = (bound - m_y1) * (m_x2 - m_x1) / (m_y2 - m_y1) + m_x1; +- y = bound; +- } +- flags = 0; +- return true; +- } ++ double x2 = x; ++ double y2 = y; ++ unsigned flags = clip_line_segment(&m_x1, &m_y1, &x2, &y2, m_clip_box); + +- //---------------------------------------------------------------------------- +- void vpgen_clip_polyline::clip_line_segment() +- { +- if((m_f1 & m_f2) == 0) ++ m_vertex = 0; ++ m_num_vertices = 0; ++ if((flags & 4) == 0) + { +- if(m_f1) +- { +- if(!move_point(m_x1, m_y1, m_f1)) return; +- if(m_f1) return; ++ if((flags & 1) != 0 || m_move_to) ++ { + m_x[0] = m_x1; + m_y[0] = m_y1; + m_cmd[0] = path_cmd_move_to; + m_num_vertices = 1; + } +- if(m_f2) +- { // Move Point 2 +- if(!move_point(m_x2, m_y2, m_f2)) return; +- } +- m_x[m_num_vertices] = m_x2; +- m_y[m_num_vertices] = m_y2; ++ m_x[m_num_vertices] = x2; ++ m_y[m_num_vertices] = y2; + m_cmd[m_num_vertices++] = path_cmd_line_to; ++ m_move_to = (flags & 2) != 0; + } +- } +- +- +- +- //---------------------------------------------------------------------------- +- void vpgen_clip_polyline::line_to(double x, double y) +- { +- m_vertex = 0; +- m_num_vertices = 0; +- unsigned f = m_f2 = clipping_flags(m_x2 = x, m_y2 = y); +- +- if(m_f2 == m_f1) +- { +- if(m_f2 == 0) +- { +- m_x[0] = x; +- m_y[0] = y; +- m_cmd[0] = path_cmd_line_to; +- m_num_vertices = 1; +- } +- } +- else +- { +- clip_line_segment(); +- } +- +- m_f1 = f; + m_x1 = x; + m_y1 = y; + } + +- + //---------------------------------------------------------------------------- + unsigned vpgen_clip_polyline::vertex(double* x, double* y) + { +@@ -137,6 +74,4 @@ namespace agg + } + return path_cmd_stop; + } +- +- + } +-- +2.19.0 +