Initial checkin

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9933 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
DarkWyrm
2004-11-12 02:02:58 +00:00
parent 5344cdf47b
commit 39241fe228
157 changed files with 50650 additions and 0 deletions
+499
View File
@@ -0,0 +1,499 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// scanline_u8 class
//
//----------------------------------------------------------------------------
#ifndef AGG_ALPHA_MASK_U8_INCLUDED
#define AGG_ALPHA_MASK_U8_INCLUDED
#include <string.h>
#include "agg_basics.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//===================================================one_component_mask_u8
struct one_component_mask_u8
{
static unsigned calculate(const int8u* p) { return *p; }
};
//=====================================================rgb_to_gray_mask_u8
template<unsigned R, unsigned G, unsigned B>
struct rgb_to_gray_mask_u8
{
static unsigned calculate(const int8u* p)
{
return (p[R]*77 + p[G]*150 + p[B]*29) >> 8;
}
};
//==========================================================alpha_mask_u8
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
class alpha_mask_u8
{
public:
typedef int8u cover_type;
typedef alpha_mask_u8<Step, Offset, MaskF> self_type;
enum
{
cover_shift = 8,
cover_none = 0,
cover_full = 255
};
alpha_mask_u8() : m_rbuf(0) {}
alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
MaskF& mask_function() { return m_mask_function; }
const MaskF& mask_function() const { return m_mask_function; }
//--------------------------------------------------------------------
cover_type pixel(int x, int y) const
{
if(x >= 0 && y >= 0 &&
x < (int)m_rbuf->width() &&
y <= (int)m_rbuf->height())
{
return (cover_type)m_mask_function.calculate(
m_rbuf->row(y) + x * Step + Offset);
}
return 0;
}
//--------------------------------------------------------------------
cover_type combine_pixel(int x, int y, cover_type val) const
{
if(x >= 0 && y >= 0 &&
x < (int)m_rbuf->width() &&
y <= (int)m_rbuf->height())
{
return (cover_type)((val *
m_mask_function.calculate(
m_rbuf->row(y) + x * Step + Offset)) >>
cover_shift);
}
return 0;
}
//--------------------------------------------------------------------
void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
{
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int count = num_pix;
cover_type* covers = dst;
if(y < 0 || y > ymax)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
if(x < 0)
{
count += x;
if(count <= 0)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
memset(covers, 0, -x * sizeof(cover_type));
covers -= x;
x = 0;
}
if(x + count > xmax)
{
int rest = x + count - xmax - 1;
count -= rest;
if(count <= 0)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
memset(covers + count, 0, rest * sizeof(cover_type));
}
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
do
{
*covers++ = (cover_type)m_mask_function.calculate(mask);
mask += Step;
}
while(--count);
}
//--------------------------------------------------------------------
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
{
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int count = num_pix;
cover_type* covers = dst;
if(y < 0 || y > ymax)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
if(x < 0)
{
count += x;
if(count <= 0)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
memset(covers, 0, -x * sizeof(cover_type));
covers -= x;
x = 0;
}
if(x + count > xmax)
{
int rest = x + count - xmax - 1;
count -= rest;
if(count <= 0)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
memset(covers + count, 0, rest * sizeof(cover_type));
}
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
do
{
*covers = (cover_type)(((*covers) *
m_mask_function.calculate(mask)) >>
cover_shift);
++covers;
mask += Step;
}
while(--count);
}
//--------------------------------------------------------------------
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
{
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int count = num_pix;
cover_type* covers = dst;
if(x < 0 || x > xmax)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
if(y < 0)
{
count += y;
if(count <= 0)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
memset(covers, 0, -y * sizeof(cover_type));
covers -= y;
y = 0;
}
if(y + count > ymax)
{
int rest = y + count - ymax - 1;
count -= rest;
if(count <= 0)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
memset(covers + count, 0, rest * sizeof(cover_type));
}
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
do
{
*covers++ = (cover_type)m_mask_function.calculate(mask);
mask += m_rbuf->stride();
}
while(--count);
}
//--------------------------------------------------------------------
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
{
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int count = num_pix;
cover_type* covers = dst;
if(x < 0 || x > xmax)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
if(y < 0)
{
count += y;
if(count <= 0)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
memset(covers, 0, -y * sizeof(cover_type));
covers -= y;
y = 0;
}
if(y + count > ymax)
{
int rest = y + count - ymax - 1;
count -= rest;
if(count <= 0)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
memset(covers + count, 0, rest * sizeof(cover_type));
}
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
do
{
*covers = (cover_type)(((*covers) *
m_mask_function.calculate(mask)) >>
cover_shift);
++covers;
mask += m_rbuf->stride();
}
while(--count);
}
private:
alpha_mask_u8(const self_type&);
const self_type& operator = (const self_type&);
rendering_buffer* m_rbuf;
MaskF m_mask_function;
};
typedef alpha_mask_u8<1, 0> alpha_mask_gray8; //----alpha_mask_gray8
typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r; //----alpha_mask_rgb24r
typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g; //----alpha_mask_rgb24g
typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b; //----alpha_mask_rgb24b
typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r; //----alpha_mask_bgr24r
typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g; //----alpha_mask_bgr24g
typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b; //----alpha_mask_bgr24b
typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r
typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g
typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b
typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a
typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r
typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g
typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b
typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a
typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r
typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g
typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b
typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a
typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r
typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g
typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b
typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray; //----alpha_mask_rgb24gray
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray; //----alpha_mask_bgr24gray
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray
//==========================================================amask_no_clip_u8
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
class amask_no_clip_u8
{
public:
typedef int8u cover_type;
typedef amask_no_clip_u8<Step, Offset, MaskF> self_type;
enum
{
cover_shift = 8,
cover_none = 0,
cover_full = 255
};
amask_no_clip_u8() : m_rbuf(0) {}
amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
MaskF& mask_function() { return m_mask_function; }
const MaskF& mask_function() const { return m_mask_function; }
//--------------------------------------------------------------------
cover_type pixel(int x, int y) const
{
return (cover_type)m_mask_function.calculate(
m_rbuf->row(y) + x * Step + Offset);
}
//--------------------------------------------------------------------
cover_type combine_pixel(int x, int y, cover_type val) const
{
return (cover_type)((val *
m_mask_function.calculate(
m_rbuf->row(y) + x * Step + Offset)) >>
cover_shift);
}
//--------------------------------------------------------------------
void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
{
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
do
{
*dst++ = (cover_type)m_mask_function.calculate(mask);
mask += Step;
}
while(--num_pix);
}
//--------------------------------------------------------------------
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
{
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
do
{
*dst = (cover_type)(((*dst) *
m_mask_function.calculate(mask)) >>
cover_shift);
++dst;
mask += Step;
}
while(--num_pix);
}
//--------------------------------------------------------------------
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
{
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
do
{
*dst++ = (cover_type)m_mask_function.calculate(mask);
mask += m_rbuf->stride();
}
while(--num_pix);
}
//--------------------------------------------------------------------
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
{
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
do
{
*dst = (cover_type)(((*dst) *
m_mask_function.calculate(mask)) >>
cover_shift);
++dst;
mask += m_rbuf->stride();
}
while(--num_pix);
}
private:
amask_no_clip_u8(const self_type&);
const self_type& operator = (const self_type&);
rendering_buffer* m_rbuf;
MaskF m_mask_function;
};
typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8
typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r
typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g; //----amask_no_clip_rgb24g
typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b; //----amask_no_clip_rgb24b
typedef amask_no_clip_u8<3, 2> amask_no_clip_bgr24r; //----amask_no_clip_bgr24r
typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g; //----amask_no_clip_bgr24g
typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b; //----amask_no_clip_bgr24b
typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r
typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g
typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b
typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a
typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r
typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g
typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b
typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a
typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r
typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g
typedef amask_no_clip_u8<4, 0> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b
typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a
typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r
typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g
typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b
typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a
typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgb24gray; //----amask_no_clip_rgb24gray
typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray; //----amask_no_clip_bgr24gray
typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgba32gray; //----amask_no_clip_rgba32gray
typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_argb32gray; //----amask_no_clip_argb32gray
typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgra32gray; //----amask_no_clip_bgra32gray
typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_abgr32gray; //----amask_no_clip_abgr32gray
}
#endif
+74
View File
@@ -0,0 +1,74 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Arc vertex generator
//
//----------------------------------------------------------------------------
#ifndef AGG_ARC_INCLUDED
#define AGG_ARC_INCLUDED
#include <math.h>
#include "agg_basics.h"
namespace agg
{
//=====================================================================arc
//
// See Implementation agg_arc.cpp
//
class arc
{
public:
arc() : m_scale(1.0), m_initialized(false) {}
arc(double x, double y,
double rx, double ry,
double a1, double a2,
bool ccw=true);
void init(double x, double y,
double rx, double ry,
double a1, double a2,
bool ccw=true);
void approximation_scale(double s);
double approximation_scale() const { return m_scale; }
void rewind(unsigned);
unsigned vertex(double* x, double* y);
private:
void normalize(double a1, double a2, bool ccw);
double m_x;
double m_y;
double m_rx;
double m_ry;
double m_angle;
double m_start;
double m_end;
double m_scale;
double m_da;
bool m_ccw;
bool m_initialized;
unsigned m_path_cmd;
};
}
#endif
+734
View File
@@ -0,0 +1,734 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_ARRAY_INCLUDED
#define AGG_ARRAY_INCLUDED
#include <string.h>
#include "agg_basics.h"
namespace agg
{
//---------------------------------------------------------------pod_array
// A simple class template to store Plain Old Data, a vector
// of a fixed size. The data is continous in memory
//------------------------------------------------------------------------
template<class T> class pod_array
{
public:
typedef T value_type;
~pod_array() { delete [] m_array; }
pod_array() : m_size(0), m_capacity(0), m_array(0) {}
pod_array(unsigned cap, unsigned extra_tail=0);
// Copying
pod_array(const pod_array<T>&);
const pod_array<T>& operator = (const pod_array<T>&);
unsigned capacity() const { return m_capacity; }
void capacity(unsigned cap, unsigned extra_tail=0);
void resize(unsigned new_size);
void add(const T& v) { m_array[m_size++] = v; }
void inc_size(unsigned size) { m_size += size; }
unsigned size() const { return m_size; }
const T& operator [] (unsigned idx) const { return m_array[idx]; }
T& operator [] (unsigned idx) { return m_array[idx]; }
void remove_all() { m_size = 0; }
void cut_at(unsigned num) { if(num < m_size) m_size = num; }
private:
unsigned m_size;
unsigned m_capacity;
T* m_array;
};
//------------------------------------------------------------------------
template<class T>
void pod_array<T>::capacity(unsigned cap, unsigned extra_tail)
{
m_size = 0;
if(cap > m_capacity)
{
delete [] m_array;
m_capacity = cap + extra_tail;
m_array = m_capacity ? new T [m_capacity] : 0;
}
}
//------------------------------------------------------------------------
template<class T>
void pod_array<T>::resize(unsigned new_size)
{
if(new_size > m_size)
{
if(new_size > m_capacity)
{
T* data = new T[new_size];
memcpy(data, m_array, m_size * sizeof(T));
delete [] m_array;
m_array = data;
}
}
else
{
m_size = new_size;
}
}
//------------------------------------------------------------------------
template<class T> pod_array<T>::pod_array(unsigned cap, unsigned extra_tail) :
m_size(0), m_capacity(0), m_array(0)
{
capacity(cap, extra_tail);
}
//------------------------------------------------------------------------
template<class T> pod_array<T>::pod_array(const pod_array<T>& v) :
m_size(v.m_size),
m_capacity(v.m_capacity),
m_array(v.m_capacity ? new T [v.m_capacity] : 0)
{
memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
}
//------------------------------------------------------------------------
template<class T> const pod_array<T>&
pod_array<T>::operator = (const pod_array<T>&v)
{
capacity(v.m_capacity);
if(v.m_size) memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
return *this;
}
//------------------------------------------------------------------------
template<class T> class pod_array_adaptor
{
public:
typedef T value_type;
pod_array_adaptor(T* array, unsigned size) :
m_array(array), m_size(size) {}
unsigned size() const { return m_size; }
const T& operator [] (unsigned idx) const { return m_array[idx]; }
T& operator [] (unsigned idx) { return m_array[idx]; }
private:
T* m_array;
unsigned m_size;
};
//---------------------------------------------------------------pod_deque
// A simple class template to store Plain Old Data, similar to std::deque
// It doesn't reallocate memory but instead, uses blocks of data of size
// of (1 << S), that is, power of two. The data is NOT continuous in memory,
// so the only valid access method is operator [] or curr(), prev(), next()
//
// There reallocs occure only when the pool of pointers to blocks needs
// to be extended (it happens very rear). You can control the value
// of increment to reallocate the pointer buffer. See the second constructor.
// By default, the incremeent value equals (1 << S), i.e., the block size.
//------------------------------------------------------------------------
template<class T, unsigned S=6> class pod_deque
{
enum
{
block_shift = S,
block_size = 1 << block_shift,
block_mask = block_size - 1
};
public:
typedef T value_type;
~pod_deque();
pod_deque();
pod_deque(unsigned block_ptr_inc);
// Copying
pod_deque(const pod_deque<T, S>& v);
const pod_deque<T, S>& operator = (const pod_deque<T, S>& v);
void remove_all() { m_size = 0; }
void free_all() { free_tail(0); }
void free_tail(unsigned size);
void add(const T& val);
void modify_last(const T& val);
void remove_last();
int allocate_continuous_block(unsigned num_elements);
void cut_at(unsigned size)
{
if(size < m_size) m_size = size;
}
unsigned size() const { return m_size; }
const T& operator [] (unsigned idx) const
{
return m_blocks[idx >> block_shift][idx & block_mask];
}
T& operator [] (unsigned idx)
{
return m_blocks[idx >> block_shift][idx & block_mask];
}
const T& curr(unsigned idx) const
{
return (*this)[idx];
}
T& curr(unsigned idx)
{
return (*this)[idx];
}
const T& prev(unsigned idx) const
{
return (*this)[(idx + m_size - 1) % m_size];
}
T& prev(unsigned idx)
{
return (*this)[(idx + m_size - 1) % m_size];
}
const T& next(unsigned idx) const
{
return (*this)[(idx + 1) % m_size];
}
T& next(unsigned idx)
{
return (*this)[(idx + 1) % m_size];
}
const T& last() const
{
return (*this)[m_size - 1];
}
T& last()
{
return (*this)[m_size - 1];
}
unsigned byte_size() const;
void serialize(int8u* ptr) const;
private:
void allocate_block(unsigned nb);
T* data_ptr();
unsigned m_size;
unsigned m_num_blocks;
unsigned m_max_blocks;
T** m_blocks;
unsigned m_block_ptr_inc;
};
//------------------------------------------------------------------------
template<class T, unsigned S> pod_deque<T, S>::~pod_deque()
{
if(m_num_blocks)
{
T** blk = m_blocks + m_num_blocks - 1;
while(m_num_blocks--)
{
delete [] *blk;
--blk;
}
delete [] m_blocks;
}
}
//------------------------------------------------------------------------
template<class T, unsigned S>
void pod_deque<T, S>::free_tail(unsigned size)
{
if(size < m_size)
{
unsigned nb = (size + block_mask) >> block_shift;
while(m_num_blocks > nb)
{
delete [] m_blocks[--m_num_blocks];
}
m_size = size;
}
}
//------------------------------------------------------------------------
template<class T, unsigned S> pod_deque<T, S>::pod_deque() :
m_size(0),
m_num_blocks(0),
m_max_blocks(0),
m_blocks(0),
m_block_ptr_inc(block_size)
{
}
//------------------------------------------------------------------------
template<class T, unsigned S>
pod_deque<T, S>::pod_deque(unsigned block_ptr_inc) :
m_size(0),
m_num_blocks(0),
m_max_blocks(0),
m_blocks(0),
m_block_ptr_inc(block_ptr_inc)
{
}
//------------------------------------------------------------------------
template<class T, unsigned S>
pod_deque<T, S>::pod_deque(const pod_deque<T, S>& v) :
m_size(v.m_size),
m_num_blocks(v.m_num_blocks),
m_max_blocks(v.m_max_blocks),
m_blocks(v.m_max_blocks ? new T* [v.m_max_blocks] : 0),
m_block_ptr_inc(v.m_block_ptr_inc)
{
unsigned i;
for(i = 0; i < v.m_num_blocks; ++i)
{
m_blocks[i] = new T [block_size];
memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
}
}
//------------------------------------------------------------------------
template<class T, unsigned S>
const pod_deque<T, S>& pod_deque<T, S>::operator = (const pod_deque<T, S>& v)
{
unsigned i;
for(i = m_num_blocks; i < v.m_num_blocks; ++i)
{
allocate_block(i);
}
for(i = 0; i < v.m_num_blocks; ++i)
{
memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
}
m_size = v.m_size;
return *this;
}
//------------------------------------------------------------------------
template<class T, unsigned S>
void pod_deque<T, S>::allocate_block(unsigned nb)
{
if(nb >= m_max_blocks)
{
T** new_blocks = new T* [m_max_blocks + m_block_ptr_inc];
if(m_blocks)
{
memcpy(new_blocks,
m_blocks,
m_num_blocks * sizeof(T*));
delete [] m_blocks;
}
m_blocks = new_blocks;
m_max_blocks += m_block_ptr_inc;
}
m_blocks[nb] = new T [block_size];
m_num_blocks++;
}
//------------------------------------------------------------------------
template<class T, unsigned S>
inline T* pod_deque<T, S>::data_ptr()
{
unsigned nb = m_size >> block_shift;
if(nb >= m_num_blocks)
{
allocate_block(nb);
}
return m_blocks[nb] + (m_size & block_mask);
}
//------------------------------------------------------------------------
template<class T, unsigned S>
inline void pod_deque<T, S>::add(const T& val)
{
*data_ptr() = val;
++m_size;
}
//------------------------------------------------------------------------
template<class T, unsigned S>
inline void pod_deque<T, S>::remove_last()
{
if(m_size) --m_size;
}
//------------------------------------------------------------------------
template<class T, unsigned S>
void pod_deque<T, S>::modify_last(const T& val)
{
remove_last();
add(val);
}
//------------------------------------------------------------------------
template<class T, unsigned S>
int pod_deque<T, S>::allocate_continuous_block(unsigned num_elements)
{
if(num_elements < block_size)
{
data_ptr(); // Allocate initial block if necessary
unsigned rest = block_size - (m_size & block_mask);
unsigned index;
if(num_elements <= rest)
{
// The rest of the block is good, we can use it
//-----------------
index = m_size;
m_size += num_elements;
return index;
}
// New block
//---------------
m_size += rest;
data_ptr();
index = m_size;
m_size += num_elements;
return index;
}
return -1; // Impossible to allocate
}
//------------------------------------------------------------------------
template<class T, unsigned S>
unsigned pod_deque<T, S>::byte_size() const
{
return m_size * sizeof(T);
}
//------------------------------------------------------------------------
template<class T, unsigned S>
void pod_deque<T, S>::serialize(int8u* ptr) const
{
unsigned i;
for(i = 0; i < m_size; i++)
{
memcpy(ptr, &(*this)[i], sizeof(T));
ptr += sizeof(T);
}
}
//-----------------------------------------------------------pod_allocator
// Allocator for arbitrary POD data. Most usable in different cache
// systems for efficient memory allocations.
// Memory is allocated with blocks of fixed size ("block_size" in
// the constructor). If required size exceeds the block size the allocator
// creates a new block of the required size. However, the most efficient
// use is when the average reqired size is much less than the block size.
//------------------------------------------------------------------------
class pod_allocator
{
public:
void remove_all()
{
if(m_num_blocks)
{
int8u** blk = m_blocks + m_num_blocks - 1;
while(m_num_blocks--)
{
delete [] *blk;
--blk;
}
delete [] m_blocks;
}
m_num_blocks = 0;
m_max_blocks = 0;
m_blocks = 0;
m_buf_ptr = 0;
m_rest = 0;
}
~pod_allocator()
{
remove_all();
}
pod_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) :
m_block_size(block_size),
m_block_ptr_inc(block_ptr_inc),
m_num_blocks(0),
m_max_blocks(0),
m_blocks(0),
m_buf_ptr(0),
m_rest(0)
{
}
int8u* allocate(unsigned size, unsigned alignment=1)
{
if(size == 0) return 0;
if(size <= m_rest)
{
int8u* ptr = m_buf_ptr;
if(alignment > 1)
{
unsigned align = (alignment - unsigned(ptr) % alignment) % alignment;
size += align;
ptr += align;
if(size <= m_rest)
{
m_rest -= size;
m_buf_ptr += size;
return ptr;
}
allocate_block(size);
return allocate(size - align, alignment);
}
m_rest -= size;
m_buf_ptr += size;
return ptr;
}
allocate_block(size + alignment - 1);
return allocate(size, alignment);
}
private:
void allocate_block(unsigned size)
{
if(size < m_block_size) size = m_block_size;
if(m_num_blocks >= m_max_blocks)
{
int8u** new_blocks = new int8u* [m_max_blocks + m_block_ptr_inc];
if(m_blocks)
{
memcpy(new_blocks,
m_blocks,
m_num_blocks * sizeof(int8u*));
delete [] m_blocks;
}
m_blocks = new_blocks;
m_max_blocks += m_block_ptr_inc;
}
m_blocks[m_num_blocks] = m_buf_ptr = new int8u [size];
m_num_blocks++;
m_rest = size;
}
unsigned m_block_size;
unsigned m_block_ptr_inc;
unsigned m_num_blocks;
unsigned m_max_blocks;
int8u** m_blocks;
int8u* m_buf_ptr;
unsigned m_rest;
};
//------------------------------------------------------------------------
enum
{
quick_sort_threshold = 9
};
//-----------------------------------------------------------swap_elements
template<class T> inline void swap_elements(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
//--------------------------------------------------------------quick_sort
template<class Array, class Less>
void quick_sort(Array& arr, Less less)
{
if(arr.size() < 2) return;
typename Array::value_type* e1;
typename Array::value_type* e2;
int stack[80];
int* top = stack;
int limit = arr.size();
int base = 0;
for(;;)
{
int len = limit - base;
int i;
int j;
int pivot;
if(len > quick_sort_threshold)
{
// we use base + len/2 as the pivot
pivot = base + len / 2;
swap_elements(arr[base], arr[pivot]);
i = base + 1;
j = limit - 1;
// now ensure that *i <= *base <= *j
e1 = &(arr[j]);
e2 = &(arr[i]);
if(less(*e1, *e2)) swap_elements(*e1, *e2);
e1 = &(arr[base]);
e2 = &(arr[i]);
if(less(*e1, *e2)) swap_elements(*e1, *e2);
e1 = &(arr[j]);
e2 = &(arr[base]);
if(less(*e1, *e2)) swap_elements(*e1, *e2);
for(;;)
{
do i++; while( less(arr[i], arr[base]) );
do j--; while( less(arr[base], arr[j]) );
if( i > j )
{
break;
}
swap_elements(arr[i], arr[j]);
}
swap_elements(arr[base], arr[j]);
// now, push the largest sub-array
if(j - base > limit - i)
{
top[0] = base;
top[1] = j;
base = i;
}
else
{
top[0] = i;
top[1] = limit;
limit = j;
}
top += 2;
}
else
{
// the sub-array is small, perform insertion sort
j = base;
i = j + 1;
for(; i < limit; j = i, i++)
{
for(; less(*(e1 = &(arr[j + 1])), *(e2 = &(arr[j]))); j--)
{
swap_elements(*e1, *e2);
if(j == base)
{
break;
}
}
}
if(top > stack)
{
top -= 2;
base = top[0];
limit = top[1];
}
else
{
break;
}
}
}
}
//------------------------------------------------------remove_duplicates
// Remove duplicates from a sorted array. It doesn't cut the the
// tail of the array, it just returns the number of remaining elements.
//-----------------------------------------------------------------------
template<class Array, class Equal>
unsigned remove_duplicates(Array& arr, Equal equal)
{
if(arr.size() < 2) return arr.size();
unsigned i, j;
for(i = 1, j = 1; i < arr.size(); i++)
{
typename Array::value_type& e = arr[i];
if(!equal(e, arr[i - 1]))
{
arr[j++] = e;
}
}
return j;
}
}
#endif
+82
View File
@@ -0,0 +1,82 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Simple arrowhead/arrowtail generator
//
//----------------------------------------------------------------------------
#ifndef AGG_ARROWHEAD_INCLUDED
#define AGG_ARROWHEAD_INCLUDED
#include "agg_basics.h"
namespace agg
{
//===============================================================arrowhead
//
// See implementation agg_arrowhead.cpp
//
class arrowhead
{
public:
arrowhead();
void head(double d1, double d2, double d3, double d4)
{
m_head_d1 = d1;
m_head_d2 = d2;
m_head_d3 = d3;
m_head_d4 = d4;
m_head_flag = true;
}
void head() { m_head_flag = true; }
void no_head() { m_head_flag = false; }
void tail(double d1, double d2, double d3, double d4)
{
m_tail_d1 = d1;
m_tail_d2 = d2;
m_tail_d3 = d3;
m_tail_d4 = d4;
m_tail_flag = true;
}
void tail() { m_tail_flag = true; }
void no_tail() { m_tail_flag = false; }
void rewind(unsigned id);
unsigned vertex(double* x, double* y);
private:
double m_head_d1;
double m_head_d2;
double m_head_d3;
double m_head_d4;
double m_tail_d1;
double m_tail_d2;
double m_tail_d3;
double m_tail_d4;
bool m_head_flag;
bool m_tail_flag;
double m_coord[16];
unsigned m_cmd[8];
unsigned m_curr_id;
unsigned m_curr_coord;
};
}
#endif
+283
View File
@@ -0,0 +1,283 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_BASICS_INCLUDED
#define AGG_BASICS_INCLUDED
namespace agg
{
//-------------------------------------------------------------------------
typedef signed char int8; //----int8
typedef unsigned char int8u; //----int8u
typedef signed short int16; //----int16
typedef unsigned short int16u; //----int16u
typedef signed int int32; //----int32
typedef unsigned int int32u; //----int32u
//-------------------------------------------------------------------------
typedef unsigned char cover_type; //----cover_type
enum
{
cover_shift = 8, //----cover_shift
cover_size = 1 << cover_shift, //----cover_size
cover_mask = cover_size - 1, //----cover_mask
cover_none = 0, //----cover_none
cover_full = cover_mask //----cover_full
};
//-----------------------------------------------------------------------pi
const double pi = 3.14159265358979323846;
//------------------------------------------------------------------deg2rad
inline double deg2rad(double deg)
{
return deg * pi / 180.0;
}
//------------------------------------------------------------------rad2deg
inline double rad2deg(double rad)
{
return rad * 180.0 / pi;
}
//----------------------------------------------------------------rect_base
template<class T> struct rect_base
{
typedef rect_base<T> self_type;
T x1;
T y1;
T x2;
T y2;
rect_base() {}
rect_base(T x1_, T y1_, T x2_, T y2_) :
x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
const self_type& normalize()
{
T t;
if(x1 > x2) { t = x1; x1 = x2; x2 = t; }
if(y1 > y2) { t = y1; y1 = y2; y2 = t; }
return *this;
}
bool clip(const self_type& r)
{
if(x2 > r.x2) x2 = r.x2;
if(y2 > r.y2) y2 = r.y2;
if(x1 < r.x1) x1 = r.x1;
if(y1 < r.y1) y1 = r.y1;
return x1 <= x2 && y1 <= y2;
}
bool is_valid() const
{
return x1 <= x2 && y1 <= y2;
}
};
//-----------------------------------------------------intersect_rectangles
template<class Rect>
inline Rect intersect_rectangles(const Rect& r1, const Rect& r2)
{
Rect r = r1;
// First process x2,y2 because the other order
// results in Internal Compiler Error under
// Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in
// case of "Maximize Speed" optimization option.
//-----------------
if(r.x2 > r2.x2) r.x2 = r2.x2;
if(r.y2 > r2.y2) r.y2 = r2.y2;
if(r.x1 < r2.x1) r.x1 = r2.x1;
if(r.y1 < r2.y1) r.y1 = r2.y1;
return r;
}
//---------------------------------------------------------unite_rectangles
template<class Rect>
inline Rect unite_rectangles(const Rect& r1, const Rect& r2)
{
Rect r = r1;
if(r.x2 < r2.x2) r.x2 = r2.x2;
if(r.y2 < r2.y2) r.y2 = r2.y2;
if(r.x1 > r2.x1) r.x1 = r2.x1;
if(r.y1 > r2.y1) r.y1 = r2.y1;
return r;
}
typedef rect_base<int> rect; //----rect
typedef rect_base<double> rect_d; //----rect_d
//---------------------------------------------------------path_commands_e
enum path_commands_e
{
path_cmd_stop = 0, //----path_cmd_stop
path_cmd_move_to = 1, //----path_cmd_move_to
path_cmd_line_to = 2, //----path_cmd_line_to
path_cmd_curve3 = 3, //----path_cmd_curve3
path_cmd_curve4 = 4, //----path_cmd_curve4
path_cmd_end_poly = 6, //----path_cmd_end_poly
path_cmd_mask = 0x0F //----path_cmd_mask
};
//------------------------------------------------------------path_flags_e
enum path_flags_e
{
path_flags_none = 0, //----path_flags_none
path_flags_ccw = 0x10, //----path_flags_ccw
path_flags_cw = 0x20, //----path_flags_cw
path_flags_close = 0x40, //----path_flags_close
path_flags_mask = 0xF0 //----path_flags_mask
};
//---------------------------------------------------------------is_vertex
inline bool is_vertex(unsigned c)
{
return c >= path_cmd_move_to && c < path_cmd_end_poly;
}
//-----------------------------------------------------------------is_stop
inline bool is_stop(unsigned c)
{
return c == path_cmd_stop;
}
//--------------------------------------------------------------is_move_to
inline bool is_move_to(unsigned c)
{
return c == path_cmd_move_to;
}
//--------------------------------------------------------------is_line_to
inline bool is_line_to(unsigned c)
{
return c == path_cmd_line_to;
}
//----------------------------------------------------------------is_curve
inline bool is_curve(unsigned c)
{
return c == path_cmd_curve3 || c == path_cmd_curve4;
}
//---------------------------------------------------------------is_curve3
inline bool is_curve3(unsigned c)
{
return c == path_cmd_curve3;
}
//---------------------------------------------------------------is_curve4
inline bool is_curve4(unsigned c)
{
return c == path_cmd_curve4;
}
//-------------------------------------------------------------is_end_poly
inline bool is_end_poly(unsigned c)
{
return (c & path_cmd_mask) == path_cmd_end_poly;
}
//----------------------------------------------------------------is_close
inline bool is_close(unsigned c)
{
return (c & ~(path_flags_cw | path_flags_ccw)) ==
(path_cmd_end_poly | path_flags_close);
}
//------------------------------------------------------------is_next_poly
inline bool is_next_poly(unsigned c)
{
return is_stop(c) || is_move_to(c) || is_end_poly(c);
}
//-------------------------------------------------------------------is_cw
inline bool is_cw(unsigned c)
{
return (c & path_flags_cw) != 0;
}
//------------------------------------------------------------------is_ccw
inline bool is_ccw(unsigned c)
{
return (c & path_flags_ccw) != 0;
}
//-------------------------------------------------------------is_oriented
inline bool is_oriented(unsigned c)
{
return (c & (path_flags_cw | path_flags_ccw)) != 0;
}
//---------------------------------------------------------------is_closed
inline bool is_closed(unsigned c)
{
return (c & path_flags_close) != 0;
}
//----------------------------------------------------------get_close_flag
inline unsigned get_close_flag(unsigned c)
{
return c & path_flags_close;
}
//-------------------------------------------------------clear_orientation
inline unsigned clear_orientation(unsigned c)
{
return c & ~(path_flags_cw | path_flags_ccw);
}
//---------------------------------------------------------get_orientation
inline unsigned get_orientation(unsigned c)
{
return c & (path_flags_cw | path_flags_ccw);
}
//---------------------------------------------------------set_orientation
inline unsigned set_orientation(unsigned c, unsigned o)
{
return clear_orientation(c) | o;
}
//--------------------------------------------------------------point_type
struct point_type
{
double x, y;
point_type() {}
point_type(double x_, double y_) : x(x_), y(y_) {}
};
//-------------------------------------------------------------vertex_type
struct vertex_type
{
double x, y;
unsigned cmd;
vertex_type() {}
vertex_type(double x_, double y_, unsigned cmd_) :
x(x_), y(y_), cmd(cmd_) {}
};
}
#endif
+156
View File
@@ -0,0 +1,156 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e.,
// 4, 7, 10, or 13 vertices.
//
//----------------------------------------------------------------------------
#ifndef AGG_BEZIER_ARC_INCLUDED
#define AGG_BEZIER_ARC_INCLUDED
#include "agg_conv_transform.h"
namespace agg
{
//-----------------------------------------------------------------------
void arc_to_bezier(double cx, double cy, double rx, double ry,
double start_angle, double sweep_angle,
double* curve);
//==============================================================bezier_arc
//
// See implemantaion agg_bezier_arc.cpp
//
class bezier_arc
{
public:
bezier_arc() : m_vertex(26) {}
bezier_arc(double x, double y,
double rx, double ry,
double start_angle,
double sweep_angle)
{
init(x, y, rx, ry, start_angle, sweep_angle);
}
void init(double x, double y,
double rx, double ry,
double start_angle,
double sweep_angle);
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_vertex = 0;
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
if(m_vertex >= m_num_vertices) return path_cmd_stop;
*x = m_vertices[m_vertex];
*y = m_vertices[m_vertex + 1];
m_vertex += 2;
return (m_vertex == 2) ? path_cmd_move_to : path_cmd_curve4;
}
// Supplemantary functions. num_vertices() actually returns doubled
// number of vertices. That is, for 1 vertex it returns 2.
//--------------------------------------------------------------------
unsigned num_vertices() const { return m_num_vertices; }
const double* vertices() const { return m_vertices; }
double* vertices() { return m_vertices; }
private:
unsigned m_vertex;
unsigned m_num_vertices;
double m_vertices[26];
};
//==========================================================bezier_arc_svg
// Compute an SVG-style bezier arc.
//
// Computes an elliptical arc from (x1, y1) to (x2, y2). The size and
// orientation of the ellipse are defined by two radii (rx, ry)
// and an x-axis-rotation, which indicates how the ellipse as a whole
// is rotated relative to the current coordinate system. The center
// (cx, cy) of the ellipse is calculated automatically to satisfy the
// constraints imposed by the other parameters.
// large-arc-flag and sweep-flag contribute to the automatic calculations
// and help determine how the arc is drawn.
class bezier_arc_svg
{
public:
//--------------------------------------------------------------------
bezier_arc_svg() : m_arc(), m_radii_ok(false) {}
bezier_arc_svg(double x1, double y1,
double rx, double ry,
double angle,
bool large_arc_flag,
bool sweep_flag,
double x2, double y2) :
m_arc(), m_radii_ok(false)
{
init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2);
}
//--------------------------------------------------------------------
void init(double x1, double y1,
double rx, double ry,
double angle,
bool large_arc_flag,
bool sweep_flag,
double x2, double y2);
//--------------------------------------------------------------------
bool radii_ok() const { return m_radii_ok; }
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_arc.rewind(0);
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
return m_arc.vertex(x, y);
}
// Supplemantary functions. num_vertices() actually returns doubled
// number of vertices. That is, for 1 vertex it returns 2.
//--------------------------------------------------------------------
unsigned num_vertices() const { return m_arc.num_vertices(); }
const double* vertices() const { return m_arc.vertices(); }
double* vertices() { return m_arc.vertices(); }
private:
bezier_arc m_arc;
bool m_radii_ok;
};
}
#endif
+54
View File
@@ -0,0 +1,54 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_BITSET_ITERATOR_INCLUDED
#define AGG_BITSET_ITERATOR_INCLUDED
#include "agg_basics.h"
namespace agg
{
class bitset_iterator
{
public:
bitset_iterator(const int8u* bits, unsigned offset = 0) :
m_bits(bits + (offset >> 3)),
m_mask(0x80 >> (offset & 7))
{}
void operator ++ ()
{
m_mask >>= 1;
if(m_mask == 0)
{
++m_bits;
m_mask = 0x80;
}
}
unsigned bit() const
{
return (*m_bits) & m_mask;
}
private:
const int8u* m_bits;
int8u m_mask;
};
}
#endif
+106
View File
@@ -0,0 +1,106 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// bounding_rect function template
//
//----------------------------------------------------------------------------
#ifndef AGG_BOUNDING_RECT_INCLUDED
#define AGG_BOUNDING_RECT_INCLUDED
#include "agg_basics.h"
namespace agg
{
//-----------------------------------------------------------bounding_rect
template<class VertexSource, class GetId, class CoordT>
bool bounding_rect(VertexSource& vs, GetId& gi,
unsigned start, unsigned num,
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
{
unsigned i;
double x;
double y;
bool first = true;
for(i = 0; i < num; i++)
{
vs.rewind(gi[start + i]);
unsigned cmd;
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
if(is_vertex(cmd))
{
if(first)
{
*x1 = CoordT(x);
*y1 = CoordT(y);
*x2 = CoordT(x);
*y2 = CoordT(y);
first = false;
}
else
{
if(CoordT(x) < *x1) *x1 = CoordT(x);
if(CoordT(y) < *y1) *y1 = CoordT(y);
if(CoordT(x) > *x2) *x2 = CoordT(x);
if(CoordT(y) > *y2) *y2 = CoordT(y);
}
}
}
}
return *x1 <= *x2 && *y1 <= *y2;
}
//-----------------------------------------------------bounding_rect_single
template<class VertexSource, class CoordT>
bool bounding_rect_single(VertexSource& vs, unsigned path_id,
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
{
double x;
double y;
bool first = true;
vs.rewind(path_id);
unsigned cmd;
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
if(is_vertex(cmd))
{
if(first)
{
*x1 = CoordT(x);
*y1 = CoordT(y);
*x2 = CoordT(x);
*y2 = CoordT(y);
first = false;
}
else
{
if(CoordT(x) < *x1) *x1 = CoordT(x);
if(CoordT(y) < *y1) *y1 = CoordT(y);
if(CoordT(x) > *x2) *x2 = CoordT(x);
if(CoordT(y) > *y2) *y2 = CoordT(y);
}
}
}
return *x1 <= *x2 && *y1 <= *y2;
}
}
#endif
+77
View File
@@ -0,0 +1,77 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// class bspline
//
//----------------------------------------------------------------------------
#ifndef AGG_BSPLINE_INCLUDED
#define AGG_BSPLINE_INCLUDED
#include "agg_basics.h"
namespace agg
{
//----------------------------------------------------------------bspline
// A very simple class of Bi-cubic Spline interpolation.
// First call init(num, x[], y[]) where num - number of source points,
// x, y - arrays of X and Y values respectively. Here Y must be a function
// of X. It means that all the X-coordinates must be arranged in the ascending
// order.
// Then call get(x) that calculates a value Y for the respective X.
// The class supports extrapolation, i.e. you can call get(x) where x is
// outside the given with init() X-range. Extrapolation is a simple linear
// function.
//
// See Implementation agg_bspline.cpp
//------------------------------------------------------------------------
class bspline
{
public:
~bspline();
bspline();
bspline(int num);
bspline(int num, const double* x, const double* y);
void init(int num);
void add_point(double x, double y);
void prepare();
void init(int num, const double* x, const double* y);
double get(double x) const;
double get_stateful(double x) const;
private:
bspline(const bspline&);
const bspline& operator = (const bspline&);
static void bsearch(int n, const double *x, double x0, int *i);
double extrapolation_left(double x) const;
double extrapolation_right(double x) const;
double interpolation(double x, int i) const;
int m_max;
int m_num;
double* m_x;
double* m_y;
double* m_am;
mutable int m_last_idx;
};
}
#endif
+180
View File
@@ -0,0 +1,180 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Liang-Barsky clipping
//
//----------------------------------------------------------------------------
#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED
#define AGG_CLIP_LIANG_BARSKY_INCLUDED
#include "agg_basics.h"
namespace agg
{
//-------------------------------------------------------clip_liang_barsky
template<class T>
inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2,
const rect_base<T>& clip_box,
T* x, T* y)
{
const double nearzero = 1e-30;
double deltax = x2 - x1;
double deltay = y2 - y1;
double xin;
double xout;
double yin;
double yout;
double tinx;
double tiny;
double toutx;
double touty;
double tin1;
double tin2;
double tout1;
unsigned np = 0;
if(deltax == 0.0)
{
// bump off of the vertical
deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
}
if(deltay == 0.0)
{
// bump off of the horizontal
deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
}
if(deltax > 0.0)
{
// points to right
xin = clip_box.x1;
xout = clip_box.x2;
}
else
{
xin = clip_box.x2;
xout = clip_box.x1;
}
if(deltay > 0.0)
{
// points up
yin = clip_box.y1;
yout = clip_box.y2;
}
else
{
yin = clip_box.y2;
yout = clip_box.y1;
}
tinx = (xin - x1) / deltax;
tiny = (yin - y1) / deltay;
if (tinx < tiny)
{
// hits x first
tin1 = tinx;
tin2 = tiny;
}
else
{
// hits y first
tin1 = tiny;
tin2 = tinx;
}
if(tin1 <= 1.0)
{
if(0.0 < tin1)
{
*x++ = (T)xin;
*y++ = (T)yin;
++np;
}
if(tin2 <= 1.0)
{
toutx = (xout - x1) / deltax;
touty = (yout - y1) / deltay;
tout1 = (toutx < touty) ? toutx : touty;
if(tin2 > 0.0 || tout1 > 0.0)
{
if(tin2 <= tout1)
{
if(tin2 > 0.0)
{
if(tinx > tiny)
{
*x++ = (T)xin;
*y++ = (T)(y1 + tinx * deltay);
}
else
{
*x++ = (T)(x1 + tiny * deltax);
*y++ = (T)yin;
}
++np;
}
if(tout1 < 1.0)
{
if(toutx < touty)
{
*x++ = (T)xout;
*y++ = (T)(y1 + toutx * deltay);
}
else
{
*x++ = (T)(x1 + touty * deltax);
*y++ = (T)yout;
}
}
else
{
*x++ = x2;
*y++ = y2;
}
++np;
}
else
{
if(tinx > tiny)
{
*x++ = (T)xin;
*y++ = (T)yout;
}
else
{
*x++ = (T)xout;
*y++ = (T)yin;
}
++np;
}
}
}
}
return np;
}
}
#endif
+252
View File
@@ -0,0 +1,252 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// color type rgba
//
//----------------------------------------------------------------------------
#ifndef AGG_COLOR_RGBA_INCLUDED
#define AGG_COLOR_RGBA_INCLUDED
#include <math.h>
#include "agg_basics.h"
namespace agg
{
//====================================================================rgba
struct rgba
{
enum premul { pre };
double r;
double g;
double b;
double a;
//--------------------------------------------------------------------
rgba() {}
//--------------------------------------------------------------------
rgba(double r_, double g_, double b_, double a_=1.0) :
r(r_), g(g_), b(b_), a(a_) {}
//--------------------------------------------------------------------
rgba(premul, double r_, double g_, double b_, double a_=1.0) :
r(r_), g(g_), b(b_), a(a_)
{
premultiply();
}
//--------------------------------------------------------------------
rgba(premul, const rgba& c) : r(c.r), g(c.g), b(c.b), a(c.a)
{
premultiply();
}
//--------------------------------------------------------------------
rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {}
//--------------------------------------------------------------------
rgba(premul, const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_)
{
premultiply();
}
//--------------------------------------------------------------------
void clear()
{
r = g = b = a = 0;
}
//--------------------------------------------------------------------
const rgba& transparent()
{
a = 0.0;
return *this;
}
//--------------------------------------------------------------------
const rgba& transparent(premul)
{
clear();
return *this;
}
//--------------------------------------------------------------------
const rgba& opacity(double a_)
{
if(a_ < 0.0) a_ = 0.0;
if(a_ > 1.0) a_ = 1.0;
a = a_;
return *this;
}
//--------------------------------------------------------------------
const rgba& opacity(premul, double a_)
{
if(a_ < 0.0) a_ = 0.0;
if(a_ > 1.0) a_ = 1.0;
premultiply(a_);
return *this;
}
//--------------------------------------------------------------------
double opacity() const
{
return a;
}
//--------------------------------------------------------------------
const rgba& premultiply()
{
r *= a;
g *= a;
b *= a;
return *this;
}
//--------------------------------------------------------------------
const rgba& premultiply(double a_)
{
if(a == 0.0 || a_ == 0.0)
{
r = g = b = a = 0.0;
return *this;
}
a_ /= a;
r *= a_;
g *= a_;
b *= a_;
a = a_;
return *this;
}
//--------------------------------------------------------------------
const rgba& demultiply()
{
if(a == 0)
{
r = g = b = 0;
return *this;
}
double a_ = 1.0 / a;
r *= a_;
g *= a_;
b *= a_;
return *this;
}
//--------------------------------------------------------------------
rgba gradient(rgba c, double k) const
{
rgba ret;
ret.r = r + (c.r - r) * k;
ret.g = g + (c.g - g) * k;
ret.b = b + (c.b - b) * k;
ret.a = a + (c.a - a) * k;
return ret;
}
//--------------------------------------------------------------------
static rgba no_color() { return rgba(0,0,0,0); }
//--------------------------------------------------------------------
static rgba from_wavelength(double wl, double gamma = 1.0);
//--------------------------------------------------------------------
rgba(double wavelen, double gamma=1.0)
{
*this = from_wavelength(wavelen, gamma);
}
};
//------------------------------------------------------------------------
inline rgba rgba_pre(double r, double g, double b, double a=1.0)
{
return rgba(rgba::pre, r, g, b, a);
}
//--------------------------------------------------------------------
inline rgba rgba_pre(const rgba& c)
{
return rgba(rgba::pre, c);
}
//--------------------------------------------------------------------
inline rgba rgba_pre(const rgba& c, double a)
{
return rgba(rgba::pre, c, a);
}
//------------------------------------------------------------------------
inline rgba rgba::from_wavelength(double wl, double gamma)
{
rgba t(0.0, 0.0, 0.0);
if(wl >= 380.0 && wl <= 440.0)
{
t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0);
t.b = 1.0;
}
else
if(wl >= 440.0 && wl <= 490.0)
{
t.g = (wl - 440.0) / (490.0 - 440.0);
t.b = 1.0;
}
else
if(wl >= 490.0 && wl <= 510.0)
{
t.g = 1.0;
t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0);
}
else
if(wl >= 510.0 && wl <= 580.0)
{
t.r = (wl - 510.0) / (580.0 - 510.0);
t.g = 1.0;
}
else
if(wl >= 580.0 && wl <= 645.0)
{
t.r = 1.0;
t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0);
}
else
if(wl >= 645.0 && wl <= 780.0)
{
t.r = 1.0;
}
double s = 1.0;
if(wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0);
else if(wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0);
t.r = pow(t.r * s, gamma);
t.g = pow(t.g * s, gamma);
t.b = pow(t.b * s, gamma);
return t;
}
}
#endif
+256
View File
@@ -0,0 +1,256 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// color type rgba8
//
//----------------------------------------------------------------------------
#ifndef AGG_COLOR_RGBA8_INCLUDED
#define AGG_COLOR_RGBA8_INCLUDED
#include "agg_basics.h"
#include "agg_color_rgba.h"
namespace agg
{
// Supported byte orders for RGB and RGBA pixel formats
//=======================================================================
struct order_rgb24 { enum { R=0, G=1, B=2, rgb24_tag }; }; //----order_rgb24
struct order_bgr24 { enum { B=0, G=1, R=2, rgb24_tag }; }; //----order_bgr24
struct order_rgba32 { enum { R=0, G=1, B=2, A=3, rgba32_tag }; }; //----order_rgba32
struct order_argb32 { enum { A=0, R=1, G=2, B=3, rgba32_tag }; }; //----order_argb32
struct order_abgr32 { enum { A=0, B=1, G=2, R=3, rgba32_tag }; }; //----order_abgr32
struct order_bgra32 { enum { B=0, G=1, R=2, A=3, rgba32_tag }; }; //----order_bgra32
//==================================================================rgba8
struct rgba8
{
enum order { rgb, bgr };
enum premul { pre };
int8u r;
int8u g;
int8u b;
int8u a;
//--------------------------------------------------------------------
rgba8() {}
//--------------------------------------------------------------------
rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=255) :
r(int8u(r_)), g(int8u(g_)), b(int8u(b_)), a(int8u(a_)) {}
//--------------------------------------------------------------------
rgba8(premul, unsigned r_, unsigned g_, unsigned b_, unsigned a_=255) :
r(int8u(r_)), g(int8u(g_)), b(int8u(b_)), a(int8u(a_))
{
premultiply();
}
//--------------------------------------------------------------------
rgba8(const rgba& c) :
r(int8u(c.r * 255.0 + 0.5)),
g(int8u(c.g * 255.0 + 0.5)),
b(int8u(c.b * 255.0 + 0.5)),
a(int8u(c.a * 255.0 + 0.5)) {}
//--------------------------------------------------------------------
rgba8(premul, const rgba8& c) :
r(int8u(c.r)), g(int8u(c.g)), b(int8u(c.b)), a(int8u(c.a))
{
premultiply();
}
//--------------------------------------------------------------------
rgba8(const rgba8& c, unsigned a_) :
r(int8u(c.r)), g(int8u(c.g)), b(int8u(c.b)), a(int8u(a_)) {}
//--------------------------------------------------------------------
rgba8(premul, const rgba8& c, unsigned a_) :
r(int8u(c.r)), g(int8u(c.g)), b(int8u(c.b)), a(int8u(a_))
{
premultiply();
}
//--------------------------------------------------------------------
rgba8(unsigned packed, order o) :
r(int8u((o == rgb) ? ((packed >> 16) & 0xFF) : (packed & 0xFF))),
g(int8u((packed >> 8) & 0xFF)),
b(int8u((o == rgb) ? (packed & 0xFF) : ((packed >> 16) & 0xFF))),
a(255) {}
//--------------------------------------------------------------------
rgba8(premul, unsigned packed, order o) :
r(int8u((o == rgb) ? ((packed >> 16) & 0xFF) : (packed & 0xFF))),
g(int8u((packed >> 8) & 0xFF)),
b(int8u((o == rgb) ? (packed & 0xFF) : ((packed >> 16) & 0xFF))),
a(255)
{
premultiply();
}
//--------------------------------------------------------------------
void clear()
{
r = g = b = a = 0;
}
//--------------------------------------------------------------------
const rgba8& transparent()
{
a = 0;
return *this;
}
//--------------------------------------------------------------------
const rgba8& transparent(premul)
{
clear();
return *this;
}
//--------------------------------------------------------------------
const rgba8& opacity(double a_)
{
if(a_ < 0.0) a_ = 0.0;
if(a_ > 1.0) a_ = 1.0;
a = int8u(a_ * 255.0 + 0.5);
return *this;
}
//--------------------------------------------------------------------
const rgba8& opacity(premul, double a_)
{
if(a_ < 0.0) a_ = 0.0;
if(a_ > 1.0) a_ = 1.0;
a = int8u(a_ * 255.0 + 0.5);
premultiply(int8u(a_ * 255.0));
return *this;
}
//--------------------------------------------------------------------
double opacity() const
{
return double(a) / 255.0;
}
//--------------------------------------------------------------------
const rgba8& premultiply()
{
if(a == 255) return *this;
if(a == 0)
{
r = g = b = 0;
return *this;
}
r = (r * a) >> 8;
g = (g * a) >> 8;
b = (b * a) >> 8;
return *this;
}
//--------------------------------------------------------------------
const rgba8& premultiply(unsigned a_)
{
if(a == 255 && a_ >= 255) return *this;
if(a == 0 || a_ == 0)
{
r = g = b = a = 0;
return *this;
}
unsigned r_ = (r * a_) / a;
unsigned g_ = (g * a_) / a;
unsigned b_ = (b * a_) / a;
r = int8u((r_ > a_) ? a_ : r_);
g = int8u((g_ > a_) ? a_ : g_);
b = int8u((b_ > a_) ? a_ : b_);
a = int8u(a_);
return *this;
}
//--------------------------------------------------------------------
const rgba8& demultiply()
{
if(a == 255) return *this;
if(a == 0)
{
r = g = b = 0;
return *this;
}
unsigned r_ = (r * 255) / a;
unsigned g_ = (g * 255) / a;
unsigned b_ = (b * 255) / a;
r = (r_ > 255) ? 255 : r_;
g = (g_ > 255) ? 255 : g_;
b = (b_ > 255) ? 255 : b_;
return *this;
}
//--------------------------------------------------------------------
rgba8 gradient(rgba8 c, double k) const
{
rgba8 ret;
int ik = int(k * 256);
ret.r = int8u(int(r) + (((int(c.r) - int(r)) * ik) >> 8));
ret.g = int8u(int(g) + (((int(c.g) - int(g)) * ik) >> 8));
ret.b = int8u(int(b) + (((int(c.b) - int(b)) * ik) >> 8));
ret.a = int8u(int(a) + (((int(c.a) - int(a)) * ik) >> 8));
return ret;
}
//--------------------------------------------------------------------
static rgba8 no_color() { return rgba8(0,0,0,0); }
//--------------------------------------------------------------------
static rgba8 from_wavelength(double wl, double gamma = 1.0)
{
return rgba8(rgba::from_wavelength(wl, gamma));
}
//--------------------------------------------------------------------
rgba8(double wavelen, double gamma=1.0)
{
*this = from_wavelength(wavelen, gamma);
}
};
//------------------------------------------------------------------------
inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, unsigned a=1.0)
{
return rgba8(rgba8::pre, r, g, b, a);
}
//--------------------------------------------------------------------
inline rgba8 rgba8_pre(const rgba& c)
{
return rgba8(rgba8::pre, c);
}
//--------------------------------------------------------------------
inline rgba8 rgba8_pre(const rgba8& c, unsigned a)
{
return rgba8(rgba8::pre, c, a);
}
}
#endif
+169
View File
@@ -0,0 +1,169 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_ADAPTOR_VCGEN_INCLUDED
#define AGG_CONV_ADAPTOR_VCGEN_INCLUDED
#include "agg_basics.h"
#include "agg_vertex_iterator.h"
namespace agg
{
//------------------------------------------------------------null_markers
struct null_markers
{
void remove_all() {}
void add_vertex(double, double, unsigned) {}
void prepare_src() {}
void rewind(unsigned) {}
unsigned vertex(double*, double*) { return path_cmd_stop; }
typedef null_markers source_type;
typedef vertex_iterator<source_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
};
//------------------------------------------------------conv_adaptor_vcgen
template<class VertexSource,
class Generator,
class Markers=null_markers> class conv_adaptor_vcgen
{
enum status
{
initial,
accumulate,
generate
};
public:
conv_adaptor_vcgen(VertexSource& source) :
m_source(&source),
m_status(initial)
{}
void set_source(VertexSource& source) { m_source = &source; }
Generator& generator() { return m_generator; }
const Generator& generator() const { return m_generator; }
Markers& markers() { return m_markers; }
const Markers& markers() const { return m_markers; }
void rewind(unsigned id)
{
m_source->rewind(id);
m_status = initial;
}
unsigned vertex(double* x, double* y);
typedef conv_adaptor_vcgen<VertexSource, Generator, Markers> source_type;
typedef vertex_iterator<source_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
private:
// Prohibit copying
conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
const conv_adaptor_vcgen<VertexSource, Generator, Markers>&
operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
VertexSource* m_source;
Generator m_generator;
Markers m_markers;
status m_status;
unsigned m_last_cmd;
double m_start_x;
double m_start_y;
};
//------------------------------------------------------------------------
template<class VertexSource, class Generator, class Markers>
unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_stop;
bool done = false;
while(!done)
{
switch(m_status)
{
case initial:
m_markers.remove_all();
m_last_cmd = m_source->vertex(&m_start_x, &m_start_y);
m_status = accumulate;
case accumulate:
if(is_stop(m_last_cmd)) return path_cmd_stop;
m_generator.remove_all();
m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
for(;;)
{
cmd = m_source->vertex(x, y);
if(is_vertex(cmd))
{
m_last_cmd = cmd;
if(is_move_to(cmd))
{
m_start_x = *x;
m_start_y = *y;
break;
}
m_generator.add_vertex(*x, *y, cmd);
m_markers.add_vertex(*x, *y, path_cmd_line_to);
}
else
{
if(is_stop(cmd))
{
m_last_cmd = path_cmd_stop;
break;
}
if(is_end_poly(cmd))
{
m_generator.add_vertex(*x, *y, cmd);
break;
}
}
}
m_generator.rewind(0);
m_status = generate;
case generate:
cmd = m_generator.vertex(x, y);
if(is_stop(cmd))
{
m_status = accumulate;
break;
}
done = true;
break;
}
}
return cmd;
}
}
#endif
+127
View File
@@ -0,0 +1,127 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_ADAPTOR_VPGEN_INCLUDED
#define AGG_CONV_ADAPTOR_VPGEN_INCLUDED
#include "agg_basics.h"
#include "agg_vertex_iterator.h"
namespace agg
{
//======================================================conv_adaptor_vpgen
template<class VertexSource, class VPGen> class conv_adaptor_vpgen
{
public:
conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
void set_source(VertexSource& source) { m_source = &source; }
VPGen& vpgen() { return m_vpgen; }
const VPGen& vpgen() const { return m_vpgen; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
typedef conv_adaptor_vpgen<VertexSource, VPGen> source_type;
typedef vertex_iterator<source_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
private:
conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);
const conv_adaptor_vpgen<VertexSource, VPGen>&
operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&);
VertexSource* m_source;
VPGen m_vpgen;
double m_start_x;
double m_start_y;
unsigned m_poly_flags;
};
//------------------------------------------------------------------------
template<class VertexSource, class VPGen>
void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id)
{
m_source->rewind(path_id);
m_vpgen.reset();
m_start_x = 0;
m_start_y = 0;
m_poly_flags = 0;
}
//------------------------------------------------------------------------
template<class VertexSource, class VPGen>
unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_stop;
for(;;)
{
cmd = m_vpgen.vertex(x, y);
if(!is_stop(cmd)) break;
if(m_poly_flags)
{
cmd = m_poly_flags;
m_poly_flags = 0;
break;
}
double tx, ty;
cmd = m_source->vertex(&tx, &ty);
if(is_vertex(cmd))
{
if(is_move_to(cmd))
{
m_vpgen.move_to(tx, ty);
m_start_x = tx;
m_start_y = ty;
}
else
{
m_vpgen.line_to(tx, ty);
}
}
else
{
if(is_end_poly(cmd))
{
m_poly_flags = cmd;
if(is_closed(cmd))
{
m_vpgen.line_to(m_start_x, m_start_y);
}
}
else
{
// The adaptor should be transparent to all unknown commands
break;
}
}
}
return cmd;
}
}
#endif
+48
View File
@@ -0,0 +1,48 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_BSPLINE_INCLUDED
#define AGG_CONV_BSPLINE_INCLUDED
#include "agg_basics.h"
#include "agg_vcgen_bspline.h"
#include "agg_conv_adaptor_vcgen.h"
namespace agg
{
//---------------------------------------------------------conv_bspline
template<class VertexSource>
struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline>
{
typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type;
conv_bspline(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) {}
void interpolation_step(double v) { base_type::generator().interpolation_step(v); }
double interpolation_step() const { return base_type::generator().interpolation_step(); }
private:
conv_bspline(const conv_bspline<VertexSource>&);
const conv_bspline<VertexSource>&
operator = (const conv_bspline<VertexSource>&);
};
}
#endif
+69
View File
@@ -0,0 +1,69 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Polygon clipping converter
// There an optimized Liang-Basky algorithm is used.
// The algorithm doesn't optimize the degenerate edges, i.e. it will never
// break a closed polygon into two or more ones, instead, there will be
// degenerate edges coinciding with the respective clipping boundaries.
// This is a sub-optimal solution, because that optimization would require
// extra, rather expensive math while the rasterizer tolerates it quite well,
// without any considerable overhead.
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_CLIP_POLYGON_INCLUDED
#define AGG_CONV_CLIP_POLYGON_INCLUDED
#include "agg_basics.h"
#include "agg_conv_adaptor_vpgen.h"
#include "agg_vpgen_clip_polygon.h"
#include "agg_vertex_iterator.h"
namespace agg
{
//=======================================================conv_clip_polygon
template<class VertexSource>
struct conv_clip_polygon : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>
{
typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> base_type;
conv_clip_polygon(VertexSource& vs) :
conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) {}
void clip_box(double x1, double y1, double x2, double y2)
{
base_type::vpgen().clip_box(x1, y1, x2, y2);
}
double x1() const { return base_type::vpgen().x1(); }
double y1() const { return base_type::vpgen().y1(); }
double x2() const { return base_type::vpgen().x2(); }
double y2() const { return base_type::vpgen().y2(); }
typedef conv_clip_polygon<VertexSource> source_type;
typedef vertex_iterator<source_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
private:
conv_clip_polygon(const conv_clip_polygon<VertexSource>&);
const conv_clip_polygon<VertexSource>&
operator = (const conv_clip_polygon<VertexSource>&);
};
}
#endif
+132
View File
@@ -0,0 +1,132 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_CLOSE_POLYGON_INCLUDED
#define AGG_CONV_CLOSE_POLYGON_INCLUDED
#include "agg_basics.h"
#include "agg_vertex_iterator.h"
namespace agg
{
//======================================================conv_close_polygon
template<class VertexSource> class conv_close_polygon
{
public:
conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
void set_source(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
typedef conv_close_polygon<VertexSource> source_type;
typedef vertex_iterator<source_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
private:
conv_close_polygon(const conv_close_polygon<VertexSource>&);
const conv_close_polygon<VertexSource>&
operator = (const conv_close_polygon<VertexSource>&);
VertexSource* m_source;
unsigned m_cmd[2];
double m_x[2];
double m_y[2];
unsigned m_vertex;
bool m_line_to;
};
//------------------------------------------------------------------------
template<class VertexSource>
void conv_close_polygon<VertexSource>::rewind(unsigned path_id)
{
m_source->rewind(path_id);
m_vertex = 2;
m_line_to = false;
}
//------------------------------------------------------------------------
template<class VertexSource>
unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_stop;
for(;;)
{
if(m_vertex < 2)
{
*x = m_x[m_vertex];
*y = m_y[m_vertex];
cmd = m_cmd[m_vertex];
++m_vertex;
break;
}
cmd = m_source->vertex(x, y);
if(is_end_poly(cmd))
{
cmd |= path_flags_close;
break;
}
if(is_stop(cmd))
{
if(m_line_to)
{
m_cmd[0] = path_cmd_end_poly | path_flags_close;
m_cmd[1] = path_cmd_stop;
m_vertex = 0;
m_line_to = false;
continue;
}
break;
}
if(is_move_to(cmd))
{
if(m_line_to)
{
m_x[0] = 0.0;
m_y[0] = 0.0;
m_cmd[0] = path_cmd_end_poly | path_flags_close;
m_x[1] = *x;
m_y[1] = *y;
m_cmd[1] = cmd;
m_vertex = 0;
m_line_to = false;
continue;
}
break;
}
if(is_vertex(cmd))
{
m_line_to = true;
break;
}
}
return cmd;
}
}
#endif
+80
View File
@@ -0,0 +1,80 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_CONCAT_INCLUDED
#define AGG_CONV_CONCAT_INCLUDED
#include "agg_basics.h"
#include "agg_vertex_iterator.h"
namespace agg
{
//=============================================================conv_concat
// Concatenation of two paths. Usually used to combine lines or curves
// with markers such as arrowheads
template<class VS1, class VS2> class conv_concat
{
public:
conv_concat(VS1& source1, VS2& source2) :
m_source1(&source1), m_source2(&source2), m_status(2) {}
void set_source1(VS1& source) { m_source1 = &source; }
void set_source2(VS2& source) { m_source2 = &source; }
void rewind(unsigned id)
{
m_source1->rewind(id);
m_source2->rewind(0);
m_status = 0;
}
unsigned vertex(double* x, double* y)
{
unsigned cmd;
if(m_status == 0)
{
cmd = m_source1->vertex(x, y);
if(!is_stop(cmd)) return cmd;
m_status = 1;
}
if(m_status == 1)
{
cmd = m_source2->vertex(x, y);
if(!is_stop(cmd)) return cmd;
m_status = 2;
}
return path_cmd_stop;
}
typedef conv_concat<VS1, VS2> source_type;
typedef vertex_iterator<source_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
private:
conv_concat(const conv_concat<VS1, VS2>&);
const conv_concat<VS1, VS2>&
operator = (const conv_concat<VS1, VS2>&);
VS1* m_source1;
VS2* m_source2;
int m_status;
};
}
#endif
+57
View File
@@ -0,0 +1,57 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// conv_stroke
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_CONTOUR_INCLUDED
#define AGG_CONV_CONTOUR_INCLUDED
#include "agg_basics.h"
#include "agg_vcgen_contour.h"
#include "agg_conv_adaptor_vcgen.h"
namespace agg
{
//-----------------------------------------------------------conv_contour
template<class VertexSource>
struct conv_contour : public conv_adaptor_vcgen<VertexSource, vcgen_contour>
{
typedef conv_adaptor_vcgen<VertexSource, vcgen_contour> base_type;
conv_contour(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs)
{
}
void width(double w) { base_type::generator().width(w); }
void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); }
double width() const { return base_type::generator().width(); }
double miter_limit() const { return base_type::generator().miter_limit(); }
bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); }
private:
conv_contour(const conv_contour<VertexSource>&);
const conv_contour<VertexSource>&
operator = (const conv_contour<VertexSource>&);
};
}
#endif
+174
View File
@@ -0,0 +1,174 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// classes conv_curve
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_CURVE_INCLUDED
#define AGG_CONV_CURVE_INCLUDED
#include "agg_basics.h"
#include "agg_curves.h"
namespace agg
{
//---------------------------------------------------------------conv_curve
// Curve converter class. Any path storage can have Bezier curves defined
// by their control points. There're two types of curves supported: curve3
// and curve4. Curve3 is a conic Bezier curve with 2 endpoints and 1 control
// point. Curve4 has 2 control points (4 points in total) and can be used
// to interpolate more complicated curves. Curve4, unlike curve3 can be used
// to approximate arcs, both curcular and elliptical. Curves are approximated
// with straight lines and one of the approaches is just to store the whole
// sequence of vertices that approximate our curve. It takes additional
// memory, and at the same time the consecutive vertices can be calculated
// on demand.
//
// Initially, path storages are not suppose to keep all the vertices of the
// curves (although, nothig prevents us from doing so). Instead, path_storage
// keeps only vertices, needed to calculate a curve on demand. Those vertices
// are marked with special commands. So, if the path_storage contains curves
// (which are not real curves yet), and we render this storage directly,
// all we will see is only 2 or 3 straight line segments (for curve3 and
// curve4 respectively). If we need to see real curves drawn we need to
// include this class into the conversion pipeline.
//
// Class conv_curve recognizes commands path_cmd_curve3 and path_cmd_curve4
// and converts these vertices into a move_to/line_to sequence.
//-----------------------------------------------------------------------
template<class VertexSource> class conv_curve
{
public:
conv_curve(VertexSource& source) :
m_source(&source), m_last_x(0.0), m_last_y(0.0) {}
void set_source(VertexSource& source) { m_source = &source; }
void approximation_scale(double s)
{
m_curve3.approximation_scale(s);
m_curve4.approximation_scale(s);
}
double approximation_scale() const
{
return m_curve3.approximation_scale();
}
void rewind(unsigned id);
unsigned vertex(double* x, double* y);
typedef conv_curve<VertexSource> source_type;
typedef vertex_iterator<source_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
private:
conv_curve(const conv_curve<VertexSource>&);
const conv_curve<VertexSource>&
operator = (const conv_curve<VertexSource>&);
VertexSource* m_source;
double m_last_x;
double m_last_y;
curve3 m_curve3;
curve4 m_curve4;
};
//------------------------------------------------------------------------
template<class VertexSource>
void conv_curve<VertexSource>::rewind(unsigned id)
{
m_source->rewind(id);
m_last_x = 0.0;
m_last_y = 0.0;
m_curve3.reset();
m_curve4.reset();
}
//------------------------------------------------------------------------
template<class VertexSource>
unsigned conv_curve<VertexSource>::vertex(double* x, double* y)
{
if(!is_stop(m_curve3.vertex(x, y)))
{
m_last_x = *x;
m_last_y = *y;
return path_cmd_line_to;
}
if(!is_stop(m_curve4.vertex(x, y)))
{
m_last_x = *x;
m_last_y = *y;
return path_cmd_line_to;
}
double ct2_x;
double ct2_y;
double end_x;
double end_y;
unsigned cmd = m_source->vertex(x, y);
switch(cmd)
{
case path_cmd_move_to:
case path_cmd_line_to:
m_last_x = *x;
m_last_y = *y;
default:
break;
case path_cmd_curve3:
m_source->vertex(&end_x, &end_y);
m_curve3.init(m_last_x, m_last_y,
*x, *y,
end_x, end_y);
m_curve3.vertex(x, y); // First call returns path_cmd_move_to
m_curve3.vertex(x, y); // This is the first vertex of the curve
cmd = path_cmd_line_to;
break;
case path_cmd_curve4:
m_source->vertex(&ct2_x, &ct2_y);
m_source->vertex(&end_x, &end_y);
m_curve4.init(m_last_x, m_last_y,
*x, *y,
ct2_x, ct2_y,
end_x, end_y);
m_curve4.vertex(x, y); // First call returns path_cmd_move_to
m_curve4.vertex(x, y); // This is the first vertex of the curve
cmd = path_cmd_line_to;
break;
}
return cmd;
}
}
#endif
+68
View File
@@ -0,0 +1,68 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// conv_dash
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_DASH_INCLUDED
#define AGG_CONV_DASH_INCLUDED
#include "agg_basics.h"
#include "agg_vcgen_dash.h"
#include "agg_conv_adaptor_vcgen.h"
namespace agg
{
//---------------------------------------------------------------conv_dash
template<class VertexSource, class Markers=null_markers>
struct conv_dash : public conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>
{
typedef Markers marker_type;
typedef conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers> base_type;
conv_dash(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs)
{
}
void remove_all_dashes()
{
base_type::generator().remove_all_dashes();
}
void add_dash(double dash_len, double gap_len)
{
base_type::generator().add_dash(dash_len, gap_len);
}
void dash_start(double ds)
{
base_type::generator().dash_start(ds);
}
void shorten(double s) { base_type::generator().shorten(s); }
double shorten() const { return base_type::generator().shorten(); }
private:
conv_dash(const conv_dash<VertexSource, Markers>&);
const conv_dash<VertexSource, Markers>&
operator = (const conv_dash<VertexSource, Markers>&);
};
}
#endif
+443
View File
@@ -0,0 +1,443 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// 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: [email protected])
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_GPC_INCLUDED
#define AGG_CONV_GPC_INCLUDED
#include <math.h>
#include "agg_basics.h"
#include "agg_array.h"
#include "agg_vertex_iterator.h"
extern "C"
{
#include "gpc.h"
}
namespace agg
{
enum gpc_op_e
{
gpc_or,
gpc_and,
gpc_xor,
gpc_a_minus_b,
gpc_b_minus_a
};
//================================================================conv_gpc
template<class VSA, class VSB> class conv_gpc
{
enum status
{
status_move_to,
status_line_to,
status_stop
};
struct contour_header_type
{
int num_vertices;
int hole_flag;
gpc_vertex* vertices;
};
typedef pod_deque<gpc_vertex, 8> vertex_array_type;
typedef pod_deque<contour_header_type, 6> contour_header_array_type;
public:
typedef VSA source_a_type;
typedef VSB source_b_type;
typedef conv_gpc<source_a_type, source_b_type> self_type;
~conv_gpc()
{
free_gpc_data();
}
conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) :
m_src_a(&a),
m_src_b(&b),
m_status(status_move_to),
m_vertex(-1),
m_contour(-1),
m_operation(op)
{
memset(&m_poly_a, 0, sizeof(m_poly_a));
memset(&m_poly_b, 0, sizeof(m_poly_b));
memset(&m_result, 0, sizeof(m_result));
}
void set_source1(VSA& source) { m_src_a = &source; }
void set_source2(VSB& source) { m_src_b = &source; }
void operation(gpc_op_e v) { m_operation = v; }
// Vertex Source Interface
void rewind(unsigned id);
unsigned vertex(double* x, double* y);
// Iterator
typedef vertex_iterator<self_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
private:
conv_gpc(const conv_gpc<VSA, VSB>&);
const conv_gpc<VSA, VSB>& operator = (const conv_gpc<VSA, VSB>&);
//--------------------------------------------------------------------
void free_polygon(gpc_polygon& p);
void free_result();
void free_gpc_data();
void start_contour();
void add_vertex(double x, double y);
void end_contour(unsigned orientation);
void make_polygon(gpc_polygon& p);
void start_extracting();
bool next_contour();
bool next_vertex(double* x, double* y);
//--------------------------------------------------------------------
template<class VS> void add(VS& src, gpc_polygon& p)
{
unsigned cmd;
double x, y;
double start_x = 0.0;
double start_y = 0.0;
bool line_to = false;
unsigned orientation = 0;
m_contour_accumulator.remove_all();
while(!is_stop(cmd = src.vertex(&x, &y)))
{
if(is_vertex(cmd))
{
if(is_move_to(cmd))
{
if(line_to)
{
end_contour(orientation);
orientation = 0;
}
start_contour();
start_x = x;
start_y = y;
}
add_vertex(x, y);
line_to = true;
}
else
{
if(is_end_poly(cmd))
{
orientation = get_orientation(cmd);
if(line_to && is_closed(cmd))
{
add_vertex(start_x, start_y);
}
}
}
}
if(line_to)
{
end_contour(orientation);
}
make_polygon(p);
}
private:
//--------------------------------------------------------------------
source_a_type* m_src_a;
source_b_type* m_src_b;
status m_status;
int m_vertex;
int m_contour;
gpc_op_e m_operation;
vertex_array_type m_vertex_accumulator;
contour_header_array_type m_contour_accumulator;
gpc_polygon m_poly_a;
gpc_polygon m_poly_b;
gpc_polygon m_result;
};
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::free_polygon(gpc_polygon& p)
{
int i;
for(i = 0; i < p.num_contours; i++)
{
delete [] p.contour[i].vertex;
}
delete [] p.hole;
delete [] p.contour;
memset(&p, 0, sizeof(gpc_polygon));
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::free_result()
{
if(m_result.contour)
{
gpc_free_polygon(&m_result);
}
memset(&m_result, 0, sizeof(m_result));
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::free_gpc_data()
{
free_polygon(m_poly_a);
free_polygon(m_poly_b);
free_result();
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::start_contour()
{
contour_header_type h;
memset(&h, 0, sizeof(h));
m_contour_accumulator.add(h);
m_vertex_accumulator.remove_all();
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
inline void conv_gpc<VSA, VSB>::add_vertex(double x, double y)
{
gpc_vertex v;
v.x = x;
v.y = y;
m_vertex_accumulator.add(v);
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::end_contour(unsigned orientation)
{
if(m_contour_accumulator.size())
{
if(m_vertex_accumulator.size() > 2)
{
contour_header_type& h =
m_contour_accumulator[m_contour_accumulator.size() - 1];
h.num_vertices = m_vertex_accumulator.size();
h.hole_flag = 0;
// TO DO: Clarify the "holes"
//if(is_cw(orientation)) h.hole_flag = 1;
h.vertices = new gpc_vertex [h.num_vertices];
gpc_vertex* d = h.vertices;
int i;
for(i = 0; i < h.num_vertices; i++)
{
const gpc_vertex& s = m_vertex_accumulator[i];
d->x = s.x;
d->y = s.y;
++d;
}
}
else
{
m_vertex_accumulator.remove_last();
}
}
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p)
{
free_polygon(p);
if(m_contour_accumulator.size())
{
p.num_contours = m_contour_accumulator.size();
// TO DO: Clarify the "holes"
//p.hole = new int[p.num_contours];
p.hole = 0;
p.contour = new gpc_vertex_list[p.num_contours];
int i;
//int* ph = p.hole;
gpc_vertex_list* pv = p.contour;
for(i = 0; i < p.num_contours; i++)
{
const contour_header_type& h = m_contour_accumulator[i];
// *ph++ = h.hole_flag;
pv->num_vertices = h.num_vertices;
pv->vertex = h.vertices;
++pv;
}
}
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::start_extracting()
{
m_status = status_move_to;
m_contour = -1;
m_vertex = -1;
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
bool conv_gpc<VSA, VSB>::next_contour()
{
if(++m_contour < m_result.num_contours)
{
m_vertex = -1;
return true;
}
return false;
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
inline bool conv_gpc<VSA, VSB>::next_vertex(double* x, double* y)
{
const gpc_vertex_list& vlist = m_result.contour[m_contour];
if(++m_vertex < vlist.num_vertices)
{
const gpc_vertex& v = vlist.vertex[m_vertex];
*x = v.x;
*y = v.y;
return true;
}
return false;
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::rewind(unsigned id)
{
free_result();
m_src_a->rewind(id);
m_src_b->rewind(id);
add(*m_src_a, m_poly_a);
add(*m_src_b, m_poly_b);
switch(m_operation)
{
case gpc_or:
gpc_polygon_clip(GPC_UNION,
&m_poly_a,
&m_poly_b,
&m_result);
break;
case gpc_and:
gpc_polygon_clip(GPC_INT,
&m_poly_a,
&m_poly_b,
&m_result);
break;
case gpc_xor:
gpc_polygon_clip(GPC_XOR,
&m_poly_a,
&m_poly_b,
&m_result);
break;
case gpc_a_minus_b:
gpc_polygon_clip(GPC_DIFF,
&m_poly_a,
&m_poly_b,
&m_result);
break;
case gpc_b_minus_a:
gpc_polygon_clip(GPC_DIFF,
&m_poly_b,
&m_poly_a,
&m_result);
break;
}
start_extracting();
}
//------------------------------------------------------------------------
template<class VSA, class VSB>
unsigned conv_gpc<VSA, VSB>::vertex(double* x, double* y)
{
if(m_status == status_move_to)
{
if(next_contour())
{
if(next_vertex(x, y))
{
m_status = status_line_to;
return path_cmd_move_to;
}
m_status = status_stop;
return path_cmd_end_poly | path_flags_close;
}
}
else
{
if(next_vertex(x, y))
{
return path_cmd_line_to;
}
else
{
m_status = status_move_to;
}
return path_cmd_end_poly | path_flags_close;
}
return path_cmd_stop;
}
}
#endif
+154
View File
@@ -0,0 +1,154 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// conv_marker
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_MARKER_INCLUDED
#define AGG_CONV_MARKER_INCLUDED
#include "agg_basics.h"
#include "agg_trans_affine.h"
#include "agg_vertex_iterator.h"
namespace agg
{
//-------------------------------------------------------------conv_marker
template<class MarkerLocator, class MarkerShapes>
class conv_marker
{
public:
conv_marker(MarkerLocator& ml, MarkerShapes& ms);
trans_affine& transform() { return m_transform; }
const trans_affine& transform() const { return m_transform; }
void rewind(unsigned id);
unsigned vertex(double* x, double* y);
typedef conv_marker<MarkerLocator, MarkerShapes> source_type;
typedef vertex_iterator<source_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
private:
conv_marker(const conv_marker<MarkerLocator, MarkerShapes>&);
const conv_marker<MarkerLocator, MarkerShapes>&
operator = (const conv_marker<MarkerLocator, MarkerShapes>&);
enum status_e
{
initial,
markers,
polygon,
stop
};
MarkerLocator* m_marker_locator;
MarkerShapes* m_marker_shapes;
trans_affine m_transform;
trans_affine m_mtx;
status_e m_status;
unsigned m_marker;
unsigned m_num_markers;
};
//------------------------------------------------------------------------
template<class MarkerLocator, class MarkerShapes>
conv_marker<MarkerLocator, MarkerShapes>::conv_marker(MarkerLocator& ml, MarkerShapes& ms) :
m_marker_locator(&ml),
m_marker_shapes(&ms),
m_status(initial),
m_marker(0),
m_num_markers(1)
{
}
//------------------------------------------------------------------------
template<class MarkerLocator, class MarkerShapes>
void conv_marker<MarkerLocator, MarkerShapes>::rewind(unsigned)
{
m_status = initial;
m_marker = 0;
m_num_markers = 1;
}
//------------------------------------------------------------------------
template<class MarkerLocator, class MarkerShapes>
unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_move_to;
double x1, y1, x2, y2;
while(!is_stop(cmd))
{
switch(m_status)
{
case initial:
if(m_num_markers == 0)
{
cmd = path_cmd_stop;
break;
}
m_marker_locator->rewind(m_marker);
++m_marker;
m_num_markers = 0;
m_status = markers;
case markers:
if(is_stop(m_marker_locator->vertex(&x1, &y1)))
{
m_status = initial;
break;
}
if(is_stop(m_marker_locator->vertex(&x2, &y2)))
{
m_status = initial;
break;
}
++m_num_markers;
m_mtx = m_transform;
m_mtx *= trans_affine_rotation(atan2(y2 - y1, x2 - x1));
m_mtx *= trans_affine_translation(x1, y1);
m_marker_shapes->rewind(m_marker - 1);
m_status = polygon;
case polygon:
cmd = m_marker_shapes->vertex(x, y);
if(is_stop(cmd))
{
cmd = path_cmd_move_to;
m_status = markers;
break;
}
m_mtx.transform(x, y);
return cmd;
case stop:
cmd = path_cmd_stop;
break;
}
}
return cmd;
}
}
#endif
@@ -0,0 +1,51 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_MARKER_ADAPTOR_INCLUDED
#define AGG_CONV_MARKER_ADAPTOR_INCLUDED
#include "agg_basics.h"
#include "agg_conv_adaptor_vcgen.h"
#include "agg_vcgen_vertex_sequence.h"
namespace agg
{
//=====================================================conv_marker_adaptor
template<class VertexSource, class Markers=null_markers>
struct conv_marker_adaptor :
public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>
{
typedef Markers marker_type;
typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers> base_type;
conv_marker_adaptor(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>(vs)
{
}
void shorten(double s) { base_type::generator().shorten(s); }
double shorten() const { return base_type::generator().shorten(); }
private:
conv_marker_adaptor(const conv_marker_adaptor<VertexSource, Markers>&);
const conv_marker_adaptor<VertexSource, Markers>&
operator = (const conv_marker_adaptor<VertexSource, Markers>&);
};
}
#endif
+48
View File
@@ -0,0 +1,48 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_SEGMENTATOR_INCLUDED
#define AGG_CONV_SEGMENTATOR_INCLUDED
#include "agg_basics.h"
#include "agg_conv_adaptor_vpgen.h"
#include "agg_vpgen_segmentator.h"
namespace agg
{
//========================================================conv_segmentator
template<class VertexSource>
struct conv_segmentator : public conv_adaptor_vpgen<VertexSource, vpgen_segmentator>
{
typedef conv_adaptor_vpgen<VertexSource, vpgen_segmentator> base_type;
conv_segmentator(VertexSource& vs) :
conv_adaptor_vpgen<VertexSource, vpgen_segmentator>(vs) {}
void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); }
double approximation_scale() const { return base_type::vpgen().approximation_scale(); }
private:
conv_segmentator(const conv_segmentator<VertexSource>&);
const conv_segmentator<VertexSource>&
operator = (const conv_segmentator<VertexSource>&);
};
}
#endif
+50
View File
@@ -0,0 +1,50 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_SHORTEN_PATH_INCLUDED
#define AGG_CONV_SHORTEN_PATH_INCLUDED
#include "agg_basics.h"
#include "agg_conv_adaptor_vcgen.h"
#include "agg_vcgen_vertex_sequence.h"
namespace agg
{
//=======================================================conv_shorten_path
template<class VertexSource> class conv_shorten_path :
public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>
{
public:
typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> base_type;
conv_shorten_path(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>(vs)
{
}
void shorten(double s) { base_type::generator().shorten(s); }
double shorten() const { return base_type::generator().shorten(); }
private:
conv_shorten_path(const conv_shorten_path<VertexSource>&);
const conv_shorten_path<VertexSource>&
operator = (const conv_shorten_path<VertexSource>&);
};
}
#endif
+80
View File
@@ -0,0 +1,80 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Smooth polygon generator
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_SMOOTH_POLY1_INCLUDED
#define AGG_CONV_SMOOTH_POLY1_INCLUDED
#include "agg_basics.h"
#include "agg_vcgen_smooth_poly1.h"
#include "agg_conv_adaptor_vcgen.h"
#include "agg_conv_curve.h"
namespace agg
{
//-------------------------------------------------------conv_smooth_poly1
template<class VertexSource>
struct conv_smooth_poly1 :
public conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>
{
typedef conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1> base_type;
conv_smooth_poly1(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>(vs)
{
}
void smooth_value(double v) { base_type::generator().smooth_value(v); }
double smooth_value() const { return base_type::generator().smooth_value(); }
private:
conv_smooth_poly1(const conv_smooth_poly1<VertexSource>&);
const conv_smooth_poly1<VertexSource>&
operator = (const conv_smooth_poly1<VertexSource>&);
};
//-------------------------------------------------conv_smooth_poly1_curve
template<class VertexSource>
struct conv_smooth_poly1_curve :
public conv_curve<conv_smooth_poly1<VertexSource> >
{
conv_smooth_poly1_curve(VertexSource& vs) :
conv_curve<conv_smooth_poly1<VertexSource> >(m_smooth),
m_smooth(vs)
{
}
void smooth_value(double v) { m_smooth.generator().smooth_value(v); }
double smooth_value() const { return m_smooth.generator().smooth_value(); }
private:
conv_smooth_poly1_curve(const conv_smooth_poly1_curve<VertexSource>&);
const conv_smooth_poly1_curve<VertexSource>&
operator = (const conv_smooth_poly1_curve<VertexSource>&);
conv_smooth_poly1<VertexSource> m_smooth;
};
}
#endif
+69
View File
@@ -0,0 +1,69 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// conv_stroke
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_STROKE_INCLUDED
#define AGG_CONV_STROKE_INCLUDED
#include "agg_basics.h"
#include "agg_vcgen_stroke.h"
#include "agg_conv_adaptor_vcgen.h"
namespace agg
{
//-------------------------------------------------------------conv_stroke
template<class VertexSource, class Markers=null_markers>
struct conv_stroke :
public conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>
{
typedef Markers marker_type;
typedef conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers> base_type;
conv_stroke(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs)
{
}
void line_cap(vcgen_stroke::line_cap_e lc) { base_type::generator().line_cap(lc); }
void line_join(vcgen_stroke::line_join_e lj) { base_type::generator().line_join(lj); }
vcgen_stroke::line_cap_e line_cap() const { return base_type::generator().line_cap(); }
vcgen_stroke::line_join_e line_join() const { return base_type::generator().line_join(); }
void width(double w) { base_type::generator().width(w); }
void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
double width() const { return base_type::generator().width(); }
double miter_limit() const { return base_type::generator().miter_limit(); }
double approximation_scale() const { return base_type::generator().approximation_scale(); }
void shorten(double s) { base_type::generator().shorten(s); }
double shorten() const { return base_type::generator().shorten(); }
private:
conv_stroke(const conv_stroke<VertexSource, Markers>&);
const conv_stroke<VertexSource, Markers>&
operator = (const conv_stroke<VertexSource, Markers>&);
};
}
#endif
+75
View File
@@ -0,0 +1,75 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// class conv_transform
//
//----------------------------------------------------------------------------
#ifndef AGG_CONV_TRANSFORM_INCLUDED
#define AGG_CONV_TRANSFORM_INCLUDED
#include "agg_basics.h"
#include "agg_trans_affine.h"
#include "agg_vertex_iterator.h"
namespace agg
{
//----------------------------------------------------------conv_transform
template<class VertexSource, class Transformer=trans_affine> class conv_transform
{
public:
conv_transform(VertexSource& source, const Transformer& tr) :
m_source(&source), m_trans(&tr) {}
void set_source(VertexSource& source) { m_source = &source; }
void rewind(unsigned id)
{
m_source->rewind(id);
}
unsigned vertex(double* x, double* y)
{
unsigned cmd = m_source->vertex(x, y);
if(is_vertex(cmd))
{
m_trans->transform(x, y);
}
return cmd;
}
void transformer(const Transformer& tr)
{
m_trans = &tr;
}
typedef conv_transform<VertexSource, Transformer> source_type;
typedef vertex_iterator<source_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
private:
conv_transform(const conv_transform<VertexSource>&);
const conv_transform<VertexSource>&
operator = (const conv_transform<VertexSource>&);
VertexSource* m_source;
const Transformer* m_trans;
};
}
#endif
@@ -0,0 +1,59 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_CONV_UNCLOSE_POLYGON_INCLUDED
#define AGG_CONV_UNCLOSE_POLYGON_INCLUDED
#include "agg_basics.h"
#include "agg_vertex_iterator.h"
namespace agg
{
//====================================================conv_unclose_polygon
template<class VertexSource> class conv_unclose_polygon
{
public:
conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {}
void set_source(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id)
{
m_source->rewind(path_id);
}
unsigned vertex(double* x, double* y)
{
unsigned cmd = m_source->vertex(x, y);
if(is_end_poly(cmd)) cmd &= ~path_flags_close;
return cmd;
}
typedef conv_unclose_polygon<VertexSource> source_type;
typedef vertex_iterator<source_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
private:
conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&);
const conv_unclose_polygon<VertexSource>&
operator = (const conv_unclose_polygon<VertexSource>&);
VertexSource* m_source;
};
}
#endif
+150
View File
@@ -0,0 +1,150 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// classes curve3 and curve4
//
//----------------------------------------------------------------------------
#ifndef AGG_CURVES_INCLUDED
#define AGG_CURVES_INCLUDED
#include "agg_basics.h"
#include "agg_vertex_iterator.h"
namespace agg
{
// See Implemantation agg_curves.cpp
//------------------------------------------------------------------curve3
class curve3
{
public:
curve3() :
m_num_steps(0), m_step(0), m_scale(1.0) { }
curve3(double x1, double y1,
double x2, double y2,
double x3, double y3) :
m_num_steps(0), m_step(0), m_scale(1.0)
{
init(x1, y1, x2, y2, x3, y3);
}
void reset() { m_num_steps = 0; m_step = -1; }
void init(double x1, double y1,
double x2, double y2,
double x3, double y3);
void approximation_scale(double s) { m_scale = s; }
double approximation_scale() const { return m_scale; }
void rewind(unsigned id);
unsigned vertex(double* x, double* y);
typedef curve3 source_type;
typedef vertex_iterator<source_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
private:
int m_num_steps;
int m_step;
double m_scale;
double m_start_x;
double m_start_y;
double m_end_x;
double m_end_y;
double m_fx;
double m_fy;
double m_dfx;
double m_dfy;
double m_ddfx;
double m_ddfy;
double m_saved_fx;
double m_saved_fy;
double m_saved_dfx;
double m_saved_dfy;
};
//-----------------------------------------------------------------curve4
class curve4
{
public:
curve4() :
m_num_steps(0), m_step(0), m_scale(1.0) { }
curve4(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4) :
m_num_steps(0), m_step(0), m_scale(1.0)
{
init(x1, y1, x2, y2, x3, y3, x4, y4);
}
void reset() { m_num_steps = 0; m_step = -1; }
void init(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4);
void approximation_scale(double s) { m_scale = s; }
double approximation_scale() const { return m_scale; }
void rewind(unsigned id);
unsigned vertex(double* x, double* y);
typedef curve4 source_type;
typedef vertex_iterator<source_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
private:
int m_num_steps;
int m_step;
double m_scale;
double m_start_x;
double m_start_y;
double m_end_x;
double m_end_y;
double m_fx;
double m_fy;
double m_dfx;
double m_dfy;
double m_ddfx;
double m_ddfy;
double m_dddfx;
double m_dddfy;
double m_saved_fx;
double m_saved_fy;
double m_saved_dfx;
double m_saved_dfy;
double m_saved_ddfx;
double m_saved_ddfy;
};
}
#endif
+290
View File
@@ -0,0 +1,290 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// classes dda_line_interpolator, dda2_line_interpolator
//
//----------------------------------------------------------------------------
#ifndef AGG_DDA_LINE_INCLUDED
#define AGG_DDA_LINE_INCLUDED
#include <stdlib.h>
#include "agg_basics.h"
namespace agg
{
//===================================================dda_line_interpolator
template<int FractionShift, int YShift=0> class dda_line_interpolator
{
public:
//--------------------------------------------------------------------
dda_line_interpolator() {}
//--------------------------------------------------------------------
dda_line_interpolator(int y1, int y2, unsigned count) :
m_y(y1),
m_inc(((y2 - y1) << FractionShift) / int(count)),
m_dy(0)
{
}
//--------------------------------------------------------------------
void operator ++ ()
{
m_dy += m_inc;
}
//--------------------------------------------------------------------
void operator -- ()
{
m_dy -= m_inc;
}
//--------------------------------------------------------------------
void operator += (unsigned n)
{
m_dy += m_inc * n;
}
//--------------------------------------------------------------------
void operator -= (unsigned n)
{
m_dy -= m_inc * n;
}
//--------------------------------------------------------------------
int y() const { return m_y + (m_dy >> (FractionShift-YShift)); }
int dy() const { return m_dy; }
private:
int m_y;
int m_inc;
int m_dy;
};
//=================================================dda2_line_interpolator
class dda2_line_interpolator
{
public:
typedef int save_data_type;
enum { save_size = 2 };
//--------------------------------------------------------------------
dda2_line_interpolator() {}
//-------------------------------------------- Forward-adjusted line
dda2_line_interpolator(int y1, int y2, int count) :
m_cnt(count <= 0 ? 1 : count),
m_lft((y2 - y1) / m_cnt),
m_rem((y2 - y1) % m_cnt),
m_mod(m_rem),
m_y(y1)
{
if(m_mod <= 0)
{
m_mod += count;
m_rem += count;
m_lft--;
}
m_mod -= count;
}
//-------------------------------------------- Backward-adjusted line
dda2_line_interpolator(int y1, int y2, int count, int) :
m_cnt(count <= 0 ? 1 : count),
m_lft((y2 - y1) / m_cnt),
m_rem((y2 - y1) % m_cnt),
m_mod(m_rem),
m_y(y1)
{
if(m_mod <= 0)
{
m_mod += count;
m_rem += count;
m_lft--;
}
}
//-------------------------------------------- Backward-adjusted line
dda2_line_interpolator(int y, int count) :
m_cnt(count <= 0 ? 1 : count),
m_lft(y / m_cnt),
m_rem(y % m_cnt),
m_mod(m_rem),
m_y(0)
{
if(m_mod <= 0)
{
m_mod += count;
m_rem += count;
m_lft--;
}
}
//--------------------------------------------------------------------
void save(save_data_type* data) const
{
data[0] = m_mod;
data[1] = m_y;
}
//--------------------------------------------------------------------
void load(const save_data_type* data)
{
m_mod = data[0];
m_y = data[1];
}
//--------------------------------------------------------------------
void operator++()
{
m_mod += m_rem;
m_y += m_lft;
if(m_mod > 0)
{
m_mod -= m_cnt;
m_y++;
}
}
//--------------------------------------------------------------------
void operator--()
{
if(m_mod <= m_rem)
{
m_mod += m_cnt;
m_y--;
}
m_mod -= m_rem;
m_y -= m_lft;
}
//--------------------------------------------------------------------
void adjust_forward()
{
m_mod -= m_cnt;
}
//--------------------------------------------------------------------
void adjust_backward()
{
m_mod += m_cnt;
}
//--------------------------------------------------------------------
int mod() const { return m_mod; }
int rem() const { return m_rem; }
int lft() const { return m_lft; }
//--------------------------------------------------------------------
int y() const { return m_y; }
private:
int m_cnt;
int m_lft;
int m_rem;
int m_mod;
int m_y;
};
//---------------------------------------------line_bresenham_interpolator
class line_bresenham_interpolator
{
public:
enum
{
subpixel_shift = 8,
subpixel_size = 1 << subpixel_shift,
subpixel_mask = subpixel_size - 1
};
//--------------------------------------------------------------------
static int line_lr(int v) { return v >> subpixel_shift; }
//--------------------------------------------------------------------
line_bresenham_interpolator(int x1, int y1, int x2, int y2) :
m_x1_lr(line_lr(x1)),
m_y1_lr(line_lr(y1)),
m_x2_lr(line_lr(x2)),
m_y2_lr(line_lr(y2)),
m_ver(abs(m_x2_lr - m_x1_lr) < abs(m_y2_lr - m_y1_lr)),
m_len(m_ver ? abs(m_y2_lr - m_y1_lr) :
abs(m_x2_lr - m_x1_lr)),
m_inc(m_ver ? ((y2 > y1) ? 1 : -1) : ((x2 > x1) ? 1 : -1)),
m_interpolator(m_ver ? x1 : y1,
m_ver ? x2 : y2,
m_len)
{
}
//--------------------------------------------------------------------
bool is_ver() const { return m_ver; }
unsigned len() const { return m_len; }
int inc() const { return m_inc; }
//--------------------------------------------------------------------
void hstep()
{
++m_interpolator;
m_x1_lr += m_inc;
}
//--------------------------------------------------------------------
void vstep()
{
++m_interpolator;
m_y1_lr += m_inc;
}
//--------------------------------------------------------------------
int x1() const { return m_x1_lr; }
int y1() const { return m_y1_lr; }
int x2() const { return line_lr(m_interpolator.y()); }
int y2() const { return line_lr(m_interpolator.y()); }
int x2_hr() const { return m_interpolator.y(); }
int y2_hr() const { return m_interpolator.y(); }
private:
int m_x1_lr;
int m_y1_lr;
int m_x2_lr;
int m_y2_lr;
bool m_ver;
unsigned m_len;
int m_inc;
dda2_line_interpolator m_interpolator;
};
}
#endif
+98
View File
@@ -0,0 +1,98 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// class ellipse
//
//----------------------------------------------------------------------------
#ifndef AGG_ELLIPSE_INCLUDED
#define AGG_ELLIPSE_INCLUDED
#include "agg_basics.h"
#include <math.h>
namespace agg
{
//----------------------------------------------------------------ellipse
class ellipse
{
public:
ellipse() : m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_num(4), m_step(0) {}
ellipse(double x, double y, double rx, double ry, unsigned num_steps)
: m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_num(num_steps), m_step(0) {}
void init(double x, double y, double rx, double ry, unsigned num_steps);
void approximation_scale(double scale);
void rewind(unsigned id);
unsigned vertex(double* x, double* y);
private:
double m_x;
double m_y;
double m_rx;
double m_ry;
unsigned m_num;
unsigned m_step;
};
//------------------------------------------------------------------------
inline void ellipse::init(double x, double y, double rx, double ry, unsigned num_steps)
{
m_x = x;
m_y = y;
m_rx = rx;
m_ry = ry;
m_num = num_steps;
m_step = 0;
}
//------------------------------------------------------------------------
inline void ellipse::approximation_scale(double scale)
{
m_num = unsigned((fabs(m_rx) + fabs(m_ry) + 6.0) * scale);
if(m_num < 6) m_num = 6;
}
//------------------------------------------------------------------------
inline void ellipse::rewind(unsigned)
{
m_step = 0;
}
//------------------------------------------------------------------------
inline unsigned ellipse::vertex(double* x, double* y)
{
if(m_step == m_num)
{
++m_step;
return path_cmd_end_poly | path_flags_close | path_flags_ccw;
}
if(m_step > m_num) return path_cmd_stop;
double angle = double(m_step) / double(m_num) * 2.0 * pi;
*x = m_x + cos(angle) * m_rx;
*y = m_y + sin(angle) * m_ry;
m_step++;
return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to);
}
}
#endif
+113
View File
@@ -0,0 +1,113 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Simple Bresenham interpolator for ellipsees
//
//----------------------------------------------------------------------------
#ifndef AGG_ELLIPSE_BRESENHAM_INCLUDED
#define AGG_ELLIPSE_BRESENHAM_INCLUDED
#include "agg_basics.h"
namespace agg
{
//------------------------------------------ellipse_bresenham_interpolator
class ellipse_bresenham_interpolator
{
public:
ellipse_bresenham_interpolator(int rx, int ry) :
m_rx2(rx * rx),
m_ry2(ry * ry),
m_two_rx2(m_rx2 << 1),
m_two_ry2(m_ry2 << 1),
m_dx(0),
m_dy(0),
m_inc_x(0),
m_inc_y(-ry * m_two_rx2),
m_cur_f(0)
{}
int dx() const { return m_dx; }
int dy() const { return m_dy; }
void operator++ ()
{
int mx, my, mxy, min_m;
int fx, fy, fxy;
mx = fx = m_cur_f + m_inc_x + m_ry2;
if(mx < 0) mx = -mx;
my = fy = m_cur_f + m_inc_y + m_rx2;
if(my < 0) my = -my;
mxy = fxy = m_cur_f + m_inc_x + m_ry2 + m_inc_y + m_rx2;
if(mxy < 0) mxy = -mxy;
min_m = mx;
bool flag = true;
if(min_m > my)
{
min_m = my;
flag = false;
}
m_dx = m_dy = 0;
if(min_m > mxy)
{
m_inc_x += m_two_ry2;
m_inc_y += m_two_rx2;
m_cur_f = fxy;
m_dx = 1;
m_dy = 1;
return;
}
if(flag)
{
m_inc_x += m_two_ry2;
m_cur_f = fx;
m_dx = 1;
return;
}
m_inc_y += m_two_rx2;
m_cur_f = fy;
m_dy = 1;
}
private:
int m_rx2;
int m_ry2;
int m_two_rx2;
int m_two_ry2;
int m_dx;
int m_dy;
int m_inc_x;
int m_inc_y;
int m_cur_f;
};
}
#endif
@@ -0,0 +1,59 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_EMBEDDED_RASTER_FONTS_INCLUDED
#define AGG_EMBEDDED_RASTER_FONTS_INCLUDED
#include "agg_basics.h"
namespace agg
{
extern const int8u gse4x6[];
extern const int8u gse4x8[];
extern const int8u gse5x7[];
extern const int8u gse5x9[];
extern const int8u gse6x12[];
extern const int8u gse6x9[];
extern const int8u gse7x11[];
extern const int8u gse7x11_bold[];
extern const int8u gse7x15[];
extern const int8u gse7x15_bold[];
extern const int8u gse8x16[];
extern const int8u gse8x16_bold[];
extern const int8u mcs11_prop[];
extern const int8u mcs11_prop_condensed[];
extern const int8u mcs12_prop[];
extern const int8u mcs13_prop[];
extern const int8u mcs5x10_mono[];
extern const int8u mcs5x11_mono[];
extern const int8u mcs6x10_mono[];
extern const int8u mcs6x11_mono[];
extern const int8u mcs7x12_mono_high[];
extern const int8u mcs7x12_mono_low[];
extern const int8u verdana12[];
extern const int8u verdana12_bold[];
extern const int8u verdana13[];
extern const int8u verdana13_bold[];
extern const int8u verdana14[];
extern const int8u verdana14_bold[];
extern const int8u verdana16[];
extern const int8u verdana16_bold[];
extern const int8u verdana17[];
extern const int8u verdana17_bold[];
extern const int8u verdana18[];
extern const int8u verdana18_bold[];
}
#endif
+394
View File
@@ -0,0 +1,394 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_FONT_CACHE_MANAGER_INCLUDED
#define AGG_FONT_CACHE_MANAGER_INCLUDED
#include <string.h>
#include "agg_array.h"
namespace agg
{
//---------------------------------------------------------glyph_data_type
enum glyph_data_type
{
glyph_data_invalid = 0,
glyph_data_mono = 1,
glyph_data_gray8 = 2,
glyph_data_outline = 3
};
//-------------------------------------------------------------glyph_cache
struct glyph_cache
{
unsigned glyph_index;
int8u* data;
unsigned data_size;
glyph_data_type data_type;
rect bounds;
double advance_x;
double advance_y;
};
//--------------------------------------------------------------font_cache
class font_cache
{
public:
enum { block_size = 16384-16 };
//--------------------------------------------------------------------
font_cache(const char* font_signature) :
m_allocator(block_size),
m_font_signature(0)
{
m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1);
strcpy(m_font_signature, font_signature);
memset(m_glyphs, 0, sizeof(m_glyphs));
}
//--------------------------------------------------------------------
bool font_is(const char* font_signature) const
{
return strcmp(font_signature, m_font_signature) == 0;
}
//--------------------------------------------------------------------
const glyph_cache* find_glyph(unsigned glyph_code) const
{
unsigned msb = (glyph_code >> 8) & 0xFF;
if(m_glyphs[msb])
{
return m_glyphs[msb][glyph_code & 0xFF];
}
return 0;
}
//--------------------------------------------------------------------
glyph_cache* cache_glyph(unsigned glyph_code,
unsigned glyph_index,
unsigned data_size,
glyph_data_type data_type,
const rect& bounds,
double advance_x,
double advance_y)
{
unsigned msb = (glyph_code >> 8) & 0xFF;
if(m_glyphs[msb] == 0)
{
m_glyphs[msb] =
(glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256,
sizeof(glyph_cache*));
memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
}
unsigned lsb = glyph_code & 0xFF;
if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
glyph_cache* glyph =
(glyph_cache*)m_allocator.allocate(sizeof(glyph_cache),
sizeof(int8u*));
glyph->glyph_index = glyph_index;
glyph->data = m_allocator.allocate(data_size);
glyph->data_size = data_size;
glyph->data_type = data_type;
glyph->bounds = bounds;
glyph->advance_x = advance_x;
glyph->advance_y = advance_y;
return m_glyphs[msb][lsb] = glyph;
}
private:
pod_allocator m_allocator;
glyph_cache** m_glyphs[256];
char* m_font_signature;
};
//---------------------------------------------------------font_cache_pool
class font_cache_pool
{
public:
//--------------------------------------------------------------------
~font_cache_pool()
{
unsigned i;
for(i = 0; i < m_num_fonts; ++i)
{
delete m_fonts[i];
}
delete [] m_fonts;
}
//--------------------------------------------------------------------
font_cache_pool(unsigned max_fonts=32) :
m_fonts(new font_cache* [max_fonts]),
m_max_fonts(max_fonts),
m_num_fonts(0),
m_cur_font(0)
{}
//--------------------------------------------------------------------
void font(const char* font_signature, bool reset_cache = false)
{
int idx = find_font(font_signature);
if(idx >= 0)
{
if(reset_cache)
{
delete m_fonts[idx];
m_fonts[idx] = new font_cache(font_signature);
}
m_cur_font = m_fonts[idx];
}
else
{
if(m_num_fonts >= m_max_fonts)
{
delete m_fonts[0];
memcpy(m_fonts,
m_fonts + 1,
(m_max_fonts - 1) * sizeof(font_cache*));
m_num_fonts = m_max_fonts - 1;
}
m_fonts[m_num_fonts] = new font_cache(font_signature);
m_cur_font = m_fonts[m_num_fonts];
++m_num_fonts;
}
}
//--------------------------------------------------------------------
const font_cache* font() const
{
return m_cur_font;
}
//--------------------------------------------------------------------
const glyph_cache* find_glyph(unsigned glyph_code) const
{
if(m_cur_font) return m_cur_font->find_glyph(glyph_code);
return 0;
}
//--------------------------------------------------------------------
glyph_cache* cache_glyph(unsigned glyph_code,
unsigned glyph_index,
unsigned data_size,
glyph_data_type data_type,
const rect& bounds,
double advance_x,
double advance_y)
{
if(m_cur_font)
{
return m_cur_font->cache_glyph(glyph_code,
glyph_index,
data_size,
data_type,
bounds,
advance_x,
advance_y);
}
return 0;
}
//--------------------------------------------------------------------
int find_font(const char* font_signature)
{
unsigned i;
for(i = 0; i < m_num_fonts; i++)
{
if(m_fonts[i]->font_is(font_signature)) return int(i);
}
return -1;
}
private:
font_cache** m_fonts;
unsigned m_max_fonts;
unsigned m_num_fonts;
font_cache* m_cur_font;
};
//------------------------------------------------------------------------
enum glyph_rendering
{
glyph_ren_native_mono,
glyph_ren_native_gray8,
glyph_ren_outline,
glyph_ren_agg_mono,
glyph_ren_agg_gray8
};
//------------------------------------------------------font_cache_manager
template<class FontEngine> class font_cache_manager
{
public:
typedef FontEngine font_engine_type;
typedef font_cache_manager<FontEngine> self_type;
typedef typename font_engine_type::path_adaptor_type path_adaptor_type;
typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type;
typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type;
typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type;
typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type;
//--------------------------------------------------------------------
font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) :
m_fonts(max_fonts),
m_engine(engine),
m_change_stamp(-1),
m_prev_glyph(0),
m_last_glyph(0)
{}
//--------------------------------------------------------------------
const glyph_cache* glyph(unsigned glyph_code)
{
synchronize();
const glyph_cache* gl = m_fonts.find_glyph(glyph_code);
if(gl)
{
m_prev_glyph = m_last_glyph;
return m_last_glyph = gl;
}
else
{
if(m_engine.prepare_glyph(glyph_code))
{
m_prev_glyph = m_last_glyph;
m_last_glyph = m_fonts.cache_glyph(glyph_code,
m_engine.glyph_index(),
m_engine.data_size(),
m_engine.data_type(),
m_engine.bounds(),
m_engine.advance_x(),
m_engine.advance_y());
m_engine.write_glyph_to(m_last_glyph->data);
return m_last_glyph;
}
}
return 0;
}
//--------------------------------------------------------------------
void init_embedded_adaptors(const glyph_cache* gl, double x, double y)
{
if(gl)
{
switch(gl->data_type)
{
case glyph_data_mono:
m_mono_adaptor.init(gl->data, gl->data_size, x, y);
break;
case glyph_data_gray8:
m_gray8_adaptor.init(gl->data, gl->data_size, x, y);
break;
case glyph_data_outline:
m_path_adaptor.init(gl->data, gl->data_size, x, y);
break;
}
}
}
//--------------------------------------------------------------------
path_adaptor_type& path_adaptor() { return m_path_adaptor; }
gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; }
gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }
mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; }
mono_scanline_type& mono_scanline() { return m_mono_scanline; }
//--------------------------------------------------------------------
const glyph_cache* perv_glyph() const { return m_prev_glyph; }
const glyph_cache* last_glyph() const { return m_last_glyph; }
//--------------------------------------------------------------------
bool add_kerning(double* x, double* y)
{
if(m_prev_glyph && m_last_glyph)
{
return m_engine.add_kerning(m_prev_glyph->glyph_index,
m_last_glyph->glyph_index,
x, y);
}
return false;
}
//--------------------------------------------------------------------
void precache(unsigned from, unsigned to)
{
for(; from <= to; ++from) glyph(from);
}
//--------------------------------------------------------------------
void reset_cache()
{
m_fonts.font(m_engine.font_signature(), true);
m_change_stamp = m_engine.change_stamp();
m_prev_glyph = m_last_glyph = 0;
}
private:
//--------------------------------------------------------------------
font_cache_manager(const self_type&);
const self_type& operator = (const self_type&);
//--------------------------------------------------------------------
void synchronize()
{
if(m_change_stamp != m_engine.change_stamp())
{
m_fonts.font(m_engine.font_signature());
m_change_stamp = m_engine.change_stamp();
m_prev_glyph = m_last_glyph = 0;
}
}
font_cache_pool m_fonts;
font_engine_type& m_engine;
int m_change_stamp;
double m_dx;
double m_dy;
const glyph_cache* m_prev_glyph;
const glyph_cache* m_last_glyph;
path_adaptor_type m_path_adaptor;
gray8_adaptor_type m_gray8_adaptor;
gray8_scanline_type m_gray8_scanline;
mono_adaptor_type m_mono_adaptor;
mono_scanline_type m_mono_scanline;
};
}
#endif
+123
View File
@@ -0,0 +1,123 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_GAMMA_FUNCTIONS_INCLUDED
#define AGG_GAMMA_FUNCTIONS_INCLUDED
#include <math.h>
#include "agg_basics.h"
namespace agg
{
//===============================================================gamma_none
struct gamma_none
{
double operator()(double x) const { return x; }
};
//==============================================================gamma_power
class gamma_power
{
public:
gamma_power() : m_gamma(1.0) {}
gamma_power(double g) : m_gamma(g) {}
void gamma(double g) { m_gamma = g; }
double gamma() const { return m_gamma; }
double operator() (double x) const
{
return pow(x, m_gamma);
}
private:
double m_gamma;
};
//==========================================================gamma_threshold
class gamma_threshold
{
public:
gamma_threshold() : m_threshold(0.5) {}
gamma_threshold(double t) : m_threshold(t) {}
void threshold(double t) { m_threshold = t; }
double threshold() const { return m_threshold; }
double operator() (double x) const
{
return (x < m_threshold) ? 0.0 : 1.0;
}
private:
double m_threshold;
};
//============================================================gamma_linear
class gamma_linear
{
public:
gamma_linear() : m_start(0.0), m_end(1.0) {}
gamma_linear(double s, double e) : m_start(s), m_end(e) {}
void set(double s, double e) { m_start = s; m_end = e; }
void start(double s) { m_start = s; }
void end(double e) { m_end = e; }
double start() const { return m_start; }
double end() const { return m_end; }
double operator() (double x) const
{
if(x < m_start) return 0.0;
if(x > m_end) return 1.0;
return (x - m_start) / (m_end - m_start);
}
private:
double m_start;
double m_end;
};
//==========================================================gamma_multiply
class gamma_multiply
{
public:
gamma_multiply() : m_mul(1.0) {}
gamma_multiply(double v) : m_mul(v) {}
void value(double v) { m_mul = v; }
double value() const { return m_mul; }
double operator() (double x) const
{
double y = x * m_mul;
if(y > 1.0) y = 1.0;
return y;
}
private:
double m_mul;
};
}
#endif
+114
View File
@@ -0,0 +1,114 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_GAMMA_LUT_INCLUDED
#define AGG_GAMMA_LUT_INCLUDED
#include <math.h>
#include "agg_basics.h"
namespace agg
{
template<class LoResT=int8u,
class HiResT=int8u,
unsigned GammaShift=8,
unsigned HiResShift=8> class gamma_lut
{
public:
enum
{
gamma_shift = GammaShift,
gamma_size = 1 << gamma_shift,
gamma_mask = gamma_size - 1
};
enum
{
hi_res_shift = HiResShift,
hi_res_size = 1 << hi_res_shift,
hi_res_mask = hi_res_size - 1
};
~gamma_lut()
{
delete [] m_inv_gamma;
delete [] m_dir_gamma;
}
gamma_lut() :
m_gamma(1.0),
m_dir_gamma(new HiResT[gamma_size]),
m_inv_gamma(new LoResT[hi_res_size])
{
unsigned i;
for(i = 0; i < gamma_size; i++)
{
m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift));
}
for(i = 0; i < hi_res_size; i++)
{
m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift));
}
}
gamma_lut(double g) :
m_gamma(1.0),
m_dir_gamma(new HiResT[gamma_size]),
m_inv_gamma(new LoResT[hi_res_size])
{
gamma(g);
}
void gamma(double g)
{
m_gamma = g;
unsigned i;
for(i = 0; i < gamma_size; i++)
{
m_dir_gamma[i] = (HiResT)(pow(double(i) / double(gamma_mask), m_gamma) * double(hi_res_mask) + 0.5);
}
double inv_g = 1.0 / g;
for(i = 0; i < hi_res_size; i++)
{
m_inv_gamma[i] = (LoResT)(pow(double(i) / double(hi_res_mask), inv_g) * double(gamma_mask) + 0.5);
}
}
double gamma() const
{
return m_gamma;
}
HiResT dir(LoResT v) const
{
return m_dir_gamma[unsigned(v)];
}
LoResT inv(HiResT v) const
{
return m_inv_gamma[unsigned(v)];
}
private:
double m_gamma;
HiResT* m_dir_gamma;
LoResT* m_inv_gamma;
};
}
#endif
+155
View File
@@ -0,0 +1,155 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_GLYPH_RASTER_BIN_INCLUDED
#define AGG_GLYPH_RASTER_BIN_INCLUDED
#include <string.h>
#include "agg_basics.h"
namespace agg
{
//========================================================glyph_raster_bin
template<class ColorT> class glyph_raster_bin
{
public:
typedef ColorT color_type;
//--------------------------------------------------------------------
struct glyph_rect
{
int x1,y1,x2,y2;
double dx, dy;
};
//--------------------------------------------------------------------
glyph_raster_bin(const int8u* font) :
m_font(font),
m_big_endian(false)
{
int t = 1;
if(*(char*)&t == 0) m_big_endian = true;
memset(m_span, 0, sizeof(m_span));
}
//--------------------------------------------------------------------
const int8u* font() const { return m_font; }
void font(const int8u* f) { m_font = f; }
//--------------------------------------------------------------------
double height() const { return m_font[0]; }
double base_line() const { return m_font[1]; }
//--------------------------------------------------------------------
template<class CharT>
double width(const CharT* str) const
{
unsigned start_char = m_font[2];
unsigned num_chars = m_font[3];
unsigned w = 0;
while(*str)
{
unsigned glyph = *str;
const int8u* bits = m_font + 4 + num_chars * 2 +
value(m_font + 4 + (glyph - start_char) * 2);
w += *bits;
++str;
}
return w;
}
//--------------------------------------------------------------------
void prepare(glyph_rect* r, double x, double y, unsigned glyph, bool flip)
{
unsigned start_char = m_font[2];
unsigned num_chars = m_font[3];
m_bits = m_font + 4 + num_chars * 2 +
value(m_font + 4 + (glyph - start_char) * 2);
m_glyph_width = *m_bits++;
m_glyph_byte_width = (m_glyph_width + 7) >> 3;
r->x1 = int(x);
r->x2 = r->x1 + m_glyph_width - 1;
if(flip)
{
r->y1 = int(y) - m_font[0] + m_font[1];
r->y2 = r->y1 + m_font[0] - 1;
}
else
{
r->y1 = int(y) - m_font[1] + 1;
r->y2 = r->y1 + m_font[0] - 1;
}
r->dx = m_glyph_width;
r->dy = 0;
}
//--------------------------------------------------------------------
const cover_type* span(unsigned i)
{
i = m_font[0] - i - 1;
const int8u* bits = m_bits + i * m_glyph_byte_width;
unsigned j;
unsigned val = *bits;
unsigned nb = 0;
for(j = 0; j < m_glyph_width; ++j)
{
m_span[j] = (cover_type)((val & 0x80) ? cover_full : cover_none);
val <<= 1;
if(++nb >= 8)
{
val = *++bits;
nb = 0;
}
}
return m_span;
}
private:
//--------------------------------------------------------------------
int16u value(const int8u* p) const
{
int16u v;
if(m_big_endian)
{
*(int8u*)&v = p[1];
*((int8u*)&v + 1) = p[0];
}
else
{
*(int8u*)&v = p[0];
*((int8u*)&v + 1) = p[1];
}
return v;
}
//--------------------------------------------------------------------
const int8u* m_font;
bool m_big_endian;
cover_type m_span[32];
const int8u* m_bits;
unsigned m_glyph_width;
unsigned m_glyph_byte_width;
};
}
#endif
+107
View File
@@ -0,0 +1,107 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// color type gray8
//
//----------------------------------------------------------------------------
#ifndef AGG_GRAY8_INCLUDED
#define AGG_GRAY8_INCLUDED
#include "agg_basics.h"
#include "agg_color_rgba.h"
#include "agg_color_rgba8.h"
namespace agg
{
//===================================================================gray8
struct gray8
{
int8u v;
int8u a;
//--------------------------------------------------------------------
gray8() {}
//--------------------------------------------------------------------
gray8(unsigned v_, unsigned a_=255) :
v(int8u(v_)), a(int8u(a_)) {}
//--------------------------------------------------------------------
gray8(const rgba& c) :
v(int8u((0.299*c.r + 0.587*c.g + 0.114*c.b) * 255.0 + 0.5)),
a(int8u(c.a*255.0)) {}
//--------------------------------------------------------------------
gray8(const rgba8& c) :
v((c.r*77 + c.g*150 + c.b*29) >> 8),
a(c.a) {}
//--------------------------------------------------------------------
void clear()
{
v = a = 0;
}
//--------------------------------------------------------------------
const gray8& transparent()
{
a = 0;
return *this;
}
//--------------------------------------------------------------------
void opacity(double a_)
{
if(a_ < 0.0) a_ = 0.0;
if(a_ > 1.0) a_ = 1.0;
a = int8u(a_ * 255.0);
}
//--------------------------------------------------------------------
double opacity() const
{
return double(a) / 255.0;
}
//--------------------------------------------------------------------
gray8 gradient(gray8 c, double k) const
{
gray8 ret;
int ik = int(k * 256);
ret.v = int8u(int(v) + (((int(c.v) - int(v)) * ik) >> 8));
ret.a = int8u(int(a) + (((int(c.a) - int(a)) * ik) >> 8));
return ret;
}
//--------------------------------------------------------------------
gray8 pre() const
{
return gray8((v*a) >> 8, a);
}
//--------------------------------------------------------------------
static gray8 no_color() { return gray8(0,0); }
};
}
#endif
+154
View File
@@ -0,0 +1,154 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Class gsv_text
//
//----------------------------------------------------------------------------
#ifndef AGG_GSV_TEXT_INCLUDED
#define AGG_GSV_TEXT_INCLUDED
#include "agg_basics.h"
#include "agg_conv_stroke.h"
#include "agg_conv_transform.h"
namespace agg
{
//---------------------------------------------------------------gsv_text
//
// See Implementation agg_gsv_text.cpp
//
class gsv_text
{
enum status
{
initial,
next_char,
start_glyph,
glyph
};
public:
~gsv_text();
gsv_text();
void font(const void* font);
void flip(bool flip_y) { m_flip = flip_y; }
void load_font(const char* file);
void size(double height, double width=0.0);
void space(double space);
void line_space(double line_space);
void start_point(double x, double y);
void text(const char* text);
void rewind(unsigned id);
unsigned vertex(double* x, double* y);
private:
// not supposed to be copied
gsv_text(const gsv_text&);
const gsv_text& operator = (const gsv_text&);
int16u value(const int8u* p) const
{
int16u v;
if(m_big_endian)
{
*(int8u*)&v = p[1];
*((int8u*)&v + 1) = p[0];
}
else
{
*(int8u*)&v = p[0];
*((int8u*)&v + 1) = p[1];
}
return v;
}
private:
double m_x;
double m_y;
double m_start_x;
double m_width;
double m_height;
double m_space;
double m_line_space;
char m_chr[2];
char* m_text;
char* m_text_buf;
unsigned m_buf_size;
char* m_cur_chr;
const void* m_font;
char* m_loaded_font;
status m_status;
bool m_big_endian;
bool m_flip;
int8u* m_indices;
int8* m_glyphs;
int8* m_bglyph;
int8* m_eglyph;
double m_w;
double m_h;
};
//--------------------------------------------------------gsv_text_outline
template<class Transformer = trans_affine> class gsv_text_outline
{
public:
gsv_text_outline(gsv_text& text, const Transformer& trans) :
m_polyline(text),
m_trans(m_polyline, trans)
{
}
void width(double w)
{
m_polyline.width(w);
}
void transformer(const Transformer* trans)
{
m_trans->transformer(trans);
}
void rewind(unsigned id)
{
m_trans.rewind(id);
m_polyline.line_join(vcgen_stroke::round_join);
m_polyline.line_cap(vcgen_stroke::round_cap);
}
unsigned vertex(double* x, double* y)
{
return m_trans.vertex(x, y);
}
private:
conv_stroke<gsv_text> m_polyline;
conv_transform<conv_stroke<gsv_text>, Transformer> m_trans;
};
}
#endif
+367
View File
@@ -0,0 +1,367 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Image transformation filters,
// Filtering classes (image_filter_base, image_filter),
// Basic filter shape classes:
// image_filter_bilinear,
// image_filter_bicubic,
// image_filter_spline16,
// image_filter_spline36,
// image_filter_sinc64,
// image_filter_sinc144,
// image_filter_sinc196,
// image_filter_sinc256
//
//----------------------------------------------------------------------------
#ifndef AGG_IMAGE_FILTERS_INCLUDED
#define AGG_IMAGE_FILTERS_INCLUDED
#include <math.h>
#include "agg_basics.h"
namespace agg
{
// See Implementation agg_image_filters.cpp
enum
{
image_filter_shift = 14, //----image_filter_shift
image_filter_size = 1 << image_filter_shift, //----image_filter_size
image_filter_mask = image_filter_size - 1, //----image_filter_mask
image_subpixel_shift = 8, //----image_subpixel_shift
image_subpixel_size = 1 << image_subpixel_shift, //----image_subpixel_size
image_subpixel_mask = image_subpixel_size - 1 //----image_subpixel_mask
};
//-----------------------------------------------------image_filter_base
class image_filter_base
{
public:
~image_filter_base();
image_filter_base(unsigned dimension);
unsigned dimension() const { return m_dimension; }
int start() const { return m_start; }
const double* weight_array_dbl() const { return m_weight_array_dbl; }
const int* weight_array_int() const { return m_weight_array_int; }
protected:
void weight(unsigned idx, double val);
double calc_x(unsigned idx) const;
void normalize();
private:
image_filter_base(const image_filter_base&);
const image_filter_base& operator = (const image_filter_base&);
unsigned m_dimension;
int m_start;
double* m_weight_array_dbl;
int* m_weight_array_int;
};
//--------------------------------------------------------image_filter
template<class FilterF> class image_filter : public image_filter_base
{
public:
image_filter() :
image_filter_base(FilterF::dimension()),
m_filter_function()
{
unsigned i;
unsigned dim = dimension() << image_subpixel_shift;
for(i = 0; i < dim; i++)
{
weight(i, m_filter_function.calc_weight(calc_x(i)));
}
normalize();
}
private:
FilterF m_filter_function;
};
//-----------------------------------------------image_filter_bilinear
class image_filter_bilinear
{
public:
static unsigned dimension() { return 2; }
static double calc_weight(double x)
{
return (x <= 0.0) ? x + 1.0 : 1.0 - x;
}
};
//------------------------------------------------image_filter_bicubic
class image_filter_bicubic
{
static double pow3(double x)
{
return (x <= 0.0) ? 0.0 : x * x * x;
}
public:
static unsigned dimension() { return 4; }
static double calc_weight(double x)
{
return
(1.0/6.0) *
(pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1));
}
};
//----------------------------------------------image_filter_spline16
class image_filter_spline16
{
public:
static unsigned dimension() { return 4; }
static double calc_weight(double x)
{
if(x < 0.0) x = -x;
if(x < 1.0)
{
return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0;
}
return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1);
}
};
//---------------------------------------------image_filter_spline36
class image_filter_spline36
{
public:
static unsigned dimension() { return 6; }
static double calc_weight(double x)
{
if(x < 0.0) x = -x;
if(x < 1.0)
{
return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0;
}
if(x < 2.0)
{
return ((-6.0/11.0 * (x-1) + 270.0/209.0) * (x-1) - 156.0/ 209.0) * (x-1);
}
return ((1.0/11.0 * (x-2) - 45.0/209.0) * (x-2) + 26.0/209.0) * (x-2);
}
};
//-----------------------------------------------image_filter_sinc36
class image_filter_sinc36
{
public:
static unsigned dimension() { return 6; }
static double calc_weight(double x)
{
if(x == 0.0) return 1.0;
x *= pi;
double x3 = x * (1.0/3.0);
return (sin(x) / x) * (sin(x3) / x3);
}
};
//------------------------------------------------image_filter_sinc64
class image_filter_sinc64
{
public:
static unsigned dimension() { return 8; }
static double calc_weight(double x)
{
if(x == 0.0) return 1.0;
x *= pi;
double x4 = x * 0.25;
return (sin(x) / x) * (sin(x4) / x4);
}
};
//-----------------------------------------------image_filter_sinc100
class image_filter_sinc100
{
public:
static unsigned dimension() { return 10; }
static double calc_weight(double x)
{
if(x == 0.0) return 1.0;
x *= pi;
double x5 = x * 0.2;
return (sin(x) / x) * (sin(x5) / x5);
}
};
//-----------------------------------------------image_filter_sinc144
class image_filter_sinc144
{
public:
static unsigned dimension() { return 12; }
static double calc_weight(double x)
{
if(x == 0.0) return 1.0;
x *= pi;
double x6 = x * (1.0/6.0);
return (sin(x) / x) * (sin(x6) / x6);
}
};
//-----------------------------------------------image_filter_sinc196
class image_filter_sinc196
{
public:
static unsigned dimension() { return 14; }
static double calc_weight(double x)
{
if(x == 0.0) return 1.0;
x *= pi;
double x7 = x * (1.0/7.0);
return (sin(x) / x) * (sin(x7) / x7);
}
};
//-----------------------------------------------image_filter_sinc256
class image_filter_sinc256
{
public:
static unsigned dimension() { return 16; }
static double calc_weight(double x)
{
if(x == 0.0) return 1.0;
x *= pi;
double x8 = x * 0.125;
return (sin(x) / x) * (sin(x8) / x8);
}
};
//--------------------------------------------image_filter_blackman36
class image_filter_blackman36
{
public:
static unsigned dimension() { return 6; }
static double calc_weight(double x)
{
if(x == 0.0) return 1.0;
x *= pi;
double x3 = x * (1.0/3.0);
return (sin(x) / x) * (0.42 + 0.5*cos(x3) + 0.08*cos(2*x3));
}
};
//--------------------------------------------image_filter_blackman64
class image_filter_blackman64
{
public:
static unsigned dimension() { return 8; }
static double calc_weight(double x)
{
if(x == 0.0) return 1.0;
x *= pi;
double x4 = x * 0.25;
return (sin(x) / x) * (0.42 + 0.5*cos(x4) + 0.08*cos(2*x4));
}
};
//-------------------------------------------image_filter_blackman100
class image_filter_blackman100
{
public:
static unsigned dimension() { return 10; }
static double calc_weight(double x)
{
if(x == 0.0) return 1.0;
x *= pi;
double x5 = x * 0.2;
return (sin(x) / x) * (0.42 + 0.5*cos(x5) + 0.08*cos(2*x5));
}
};
//-------------------------------------------image_filter_blackman144
class image_filter_blackman144
{
public:
static unsigned dimension() { return 12; }
static double calc_weight(double x)
{
if(x == 0.0) return 1.0;
x *= pi;
double x6 = x * (1.0/6.0);
return (sin(x) / x) * (0.42 + 0.5*cos(x6) + 0.08*cos(2*x6));
}
};
//-------------------------------------------image_filter_blackman196
class image_filter_blackman196
{
public:
static unsigned dimension() { return 14; }
static double calc_weight(double x)
{
if(x == 0.0) return 1.0;
x *= pi;
double x7 = x * (1.0/7.0);
return (sin(x) / x) * (0.42 + 0.5*cos(x7) + 0.08*cos(2*x7));
}
};
//-------------------------------------------image_filter_blackman256
class image_filter_blackman256
{
public:
static unsigned dimension() { return 16; }
static double calc_weight(double x)
{
if(x == 0.0) return 1.0;
x *= pi;
double x8 = x * 0.125;
return (sin(x) / x) * (0.42 + 0.5*cos(x8) + 0.08*cos(2*x8));
}
};
}
#endif
+123
View File
@@ -0,0 +1,123 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_LINE_AA_BASICS_INCLUDED
#define AGG_LINE_AA_BASICS_INCLUDED
#include <stdlib.h>
#include "agg_basics.h"
namespace agg
{
// See Implementation agg_line_aa_basics.cpp
//-------------------------------------------------------------------------
enum
{
line_subpixel_shift = 8, //----line_subpixel_shift
line_subpixel_size = 1 << line_subpixel_shift, //----line_subpixel_size
line_subpixel_mask = line_subpixel_size - 1 //----line_subpixel_mask
};
//-------------------------------------------------------------------------
enum
{
line_mr_subpixel_shift = 4, //----line_mr_subpixel_shift
line_mr_subpixel_size = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_size
line_mr_subpixel_mask = line_mr_subpixel_size - 1 //----line_mr_subpixel_mask
};
//------------------------------------------------------------------line_mr
inline int line_mr(int x)
{
return x >> (line_subpixel_shift - line_mr_subpixel_shift);
}
//-------------------------------------------------------------------line_hr
inline int line_hr(int x)
{
return x << (line_subpixel_shift - line_mr_subpixel_shift);
}
//---------------------------------------------------------------line_dbl_hr
inline int line_dbl_hr(int x)
{
return x << line_subpixel_shift;
}
//---------------------------------------------------------------line_coord
inline int line_coord(double x)
{
return int(x * line_subpixel_size);
}
//==========================================================line_parameters
struct line_parameters
{
//---------------------------------------------------------------------
line_parameters() {}
line_parameters(int x1_, int y1_, int x2_, int y2_, int len_) :
x1(x1_), y1(y1_), x2(x2_), y2(y2_),
dx(abs(x2_ - x1_)),
dy(abs(y2_ - y1_)),
sx((x2_ > x1_) ? 1 : -1),
sy((y2_ > y1_) ? 1 : -1),
vertical(dy >= dx),
inc(vertical ? sy : sx),
len(len_),
octant((sy & 4) | (sx & 2) | int(vertical))
{
}
//---------------------------------------------------------------------
unsigned orthogonal_quadrant() const { return s_orthogonal_quadrant[octant]; }
unsigned diagonal_quadrant() const { return s_diagonal_quadrant[octant]; }
//---------------------------------------------------------------------
bool same_orthogonal_quadrant(const line_parameters& lp) const
{
return s_orthogonal_quadrant[octant] == s_orthogonal_quadrant[lp.octant];
}
//---------------------------------------------------------------------
bool same_diagonal_quadrant(const line_parameters& lp) const
{
return s_diagonal_quadrant[octant] == s_diagonal_quadrant[lp.octant];
}
//---------------------------------------------------------------------
int x1, y1, x2, y2, dx, dy, sx, sy;
bool vertical;
int inc;
int len;
int octant;
//---------------------------------------------------------------------
static int8u s_orthogonal_quadrant[8];
static int8u s_diagonal_quadrant[8];
};
// See Implementation agg_line_aa_basics.cpp
//----------------------------------------------------------------bisectrix
void bisectrix(const line_parameters& l1,
const line_parameters& l2,
int* x, int* y);
}
#endif
+247
View File
@@ -0,0 +1,247 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_MATH_INCLUDED
#define AGG_MATH_INCLUDED
#include <math.h>
#include "agg_basics.h"
namespace agg
{
const double intersection_epsilon = 1.0e-8;
//------------------------------------------------------calc_point_location
inline double calc_point_location(double x1, double y1,
double x2, double y2,
double x, double y)
{
return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
}
//--------------------------------------------------------point_in_triangle
inline bool point_in_triangle(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x, double y)
{
bool cp1 = calc_point_location(x1, y1, x2, y2, x, y) < 0.0;
bool cp2 = calc_point_location(x2, y2, x3, y3, x, y) < 0.0;
bool cp3 = calc_point_location(x3, y3, x1, y1, x, y) < 0.0;
return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
}
//-----------------------------------------------------------calc_distance
inline double calc_distance(double x1, double y1, double x2, double y2)
{
double dx = x2-x1;
double dy = y2-y1;
return sqrt(dx * dx + dy * dy);
}
//------------------------------------------------calc_point_line_distance
inline double calc_point_line_distance(double x1, double y1,
double x2, double y2,
double x, double y)
{
double dx = x2-x1;
double dy = y2-y1;
return ((x - x2) * dy - (y - y2) * dx) / sqrt(dx * dx + dy * dy);
}
//-------------------------------------------------------calc_intersection
inline bool calc_intersection(double ax, double ay, double bx, double by,
double cx, double cy, double dx, double dy,
double* x, double* y)
{
double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy);
double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx);
if(fabs(den) < intersection_epsilon) return false;
double r = num / den;
*x = ax + r * (bx-ax);
*y = ay + r * (by-ay);
return true;
}
//--------------------------------------------------------calc_orthogonal
inline void calc_orthogonal(double thickness,
double x1, double y1,
double x2, double y2,
double* x, double* y)
{
double dx = x2 - x1;
double dy = y2 - y1;
double d = sqrt(dx*dx + dy*dy);
*x = thickness * dy / d;
*y = thickness * dx / d;
}
//--------------------------------------------------------dilate_triangle
inline void dilate_triangle(double x1, double y1,
double x2, double y2,
double x3, double y3,
double *x, double* y,
double d)
{
double dx1=0.0;
double dy1=0.0;
double dx2=0.0;
double dy2=0.0;
double dx3=0.0;
double dy3=0.0;
double loc = calc_point_location(x1, y1, x2, y2, x3, y3);
if(fabs(loc) > intersection_epsilon)
{
if(calc_point_location(x1, y1, x2, y2, x3, y3) > 0.0)
{
d = -d;
}
calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1);
calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2);
calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3);
}
*x++ = x1 + dx1; *y++ = y1 - dy1;
*x++ = x2 + dx1; *y++ = y2 - dy1;
*x++ = x2 + dx2; *y++ = y2 - dy2;
*x++ = x3 + dx2; *y++ = y3 - dy2;
*x++ = x3 + dx3; *y++ = y3 - dy3;
*x++ = x1 + dx3; *y++ = y1 - dy3;
}
//-------------------------------------------------------calc_polygon_area
template<class Storage> double calc_polygon_area(const Storage& st)
{
unsigned i;
double sum = 0.0;
double x = st[0].x;
double y = st[0].y;
double xs = x;
double ys = y;
for(i = 1; i < st.size(); i++)
{
const typename Storage::value_type& v = st[i];
sum += x * v.y - y * v.x;
x = v.x;
y = v.y;
}
return (sum + x * ys - y * xs) * 0.5;
}
//------------------------------------------------------------------------
// Tables for fast sqrt
extern int16u g_sqrt_table[1024];
extern int8 g_elder_bit_table[256];
//---------------------------------------------------------------fast_sqrt
//Fast integer Sqrt - really fast: no cycles, divisions or multiplications
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4035) //Disable warning "no return value"
#endif
inline unsigned fast_sqrt(unsigned val)
{
#if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM)
//For Ix86 family processors this assembler code is used.
//The key command here is bsr - determination the number of the most
//significant bit of the value. For other processors
//(and maybe compilers) the pure C "#else" section is used.
__asm
{
mov ebx, val
mov edx, 11
bsr ecx, ebx
sub ecx, 9
jle less_than_9_bits
shr ecx, 1
adc ecx, 0
sub edx, ecx
shl ecx, 1
shr ebx, cl
less_than_9_bits:
xor eax, eax
mov ax, g_sqrt_table[ebx*2]
mov ecx, edx
shr eax, cl
}
#else
//This code is actually pure C and portable to most
//arcitectures including 64bit ones.
unsigned t = val;
int bit=0;
unsigned shift = 11;
//The following piece of code is just an emulation of the
//Ix86 assembler command "bsr" (see above). However on old
//Intels (like Intel MMX 233MHz) this code is about twice
//faster (sic!) then just one "bsr". On PIII and PIV the
//bsr is optimized quite well.
bit = t >> 24;
if(bit)
{
bit = g_elder_bit_table[bit] + 24;
}
else
{
bit = (t >> 16) & 0xFF;
if(bit)
{
bit = g_elder_bit_table[bit] + 16;
}
else
{
bit = (t >> 8) & 0xFF;
if(bit)
{
bit = g_elder_bit_table[bit] + 8;
}
else
{
bit = g_elder_bit_table[t];
}
}
}
//This is calculation sqrt itself.
bit -= 9;
if(bit > 0)
{
bit = (bit >> 1) + (bit & 1);
shift -= bit;
val >>= (bit << 1);
}
return g_sqrt_table[val] >> shift;
#endif
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
}
#endif
+369
View File
@@ -0,0 +1,369 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PATH_STORAGE_INCLUDED
#define AGG_PATH_STORAGE_INCLUDED
#include "agg_basics.h"
namespace agg
{
//------------------------------------------------------------path_storage
// A container to store vertices with their flags.
// A path consists of a number of contours separated with "move_to"
// commands. The path storage can keep and maintain more than one
// path.
// To navigate to the beginning of a particular path, use rewind(path_id);
// Where path_id is what start_new_path() returns. So, when you call
// start_new_path() you need to store its return value somewhere else
// to navigate to the path afterwards.
//
// See Implementation: agg_path_storage.cpp
// See also: vertex_source concept
//------------------------------------------------------------------------
class path_storage
{
// Allocation parameters
enum
{
block_shift = 8,
block_size = 1 << block_shift,
block_mask = block_size - 1,
block_pool = 256
};
public:
//--------------------------------------------------------------------
class const_iterator
{
void vertex()
{
if(m_vertex_idx < m_path->total_vertices())
{
m_vertex.cmd = m_path->vertex(m_vertex_idx, &m_vertex.x, &m_vertex.y);
}
else
{
m_vertex.cmd = path_cmd_stop;
m_vertex.x = m_vertex.y = 0.0;
}
}
public:
const_iterator() {}
const_iterator(unsigned cmd) { m_vertex.cmd = cmd; }
const_iterator(const const_iterator& i) :
m_path(i.m_path),
m_vertex_idx(i.m_vertex_idx),
m_vertex(i.m_vertex)
{
}
const_iterator(const path_storage& p, unsigned id) :
m_path(&p),
m_vertex_idx(id)
{
vertex();
}
const_iterator& operator++()
{
++m_vertex_idx;
vertex();
return *this;
}
const vertex_type& operator*() const { return m_vertex; }
const vertex_type* operator->() const { return &m_vertex; }
bool operator != (const const_iterator& i)
{
return m_vertex.cmd != i.m_vertex.cmd;
}
private:
const path_storage* m_path;
unsigned m_vertex_idx;
vertex_type m_vertex;
};
~path_storage();
path_storage();
path_storage(const path_storage& ps);
void remove_all();
unsigned last_vertex(double* x, double* y) const;
unsigned prev_vertex(double* x, double* y) const;
void rel_to_abs(double* x, double* y) const;
void move_to(double x, double y);
void move_rel(double dx, double dy);
void line_to(double x, double y);
void line_rel(double dx, double dy);
void arc_to(double rx, double ry,
double angle,
bool large_arc_flag,
bool sweep_flag,
double x, double y);
void arc_rel(double rx, double ry,
double angle,
bool large_arc_flag,
bool sweep_flag,
double dx, double dy);
void curve3(double x_ctrl, double y_ctrl,
double x_to, double y_to);
void curve3_rel(double dx_ctrl, double dy_ctrl,
double dx_to, double dy_to);
void curve3(double x_to, double y_to);
void curve3_rel(double dx_to, double dy_to);
void curve4(double x_ctrl1, double y_ctrl1,
double x_ctrl2, double y_ctrl2,
double x_to, double y_to);
void curve4_rel(double dx_ctrl1, double dy_ctrl1,
double dx_ctrl2, double dy_ctrl2,
double dx_to, double dy_to);
void curve4(double x_ctrl2, double y_ctrl2,
double x_to, double y_to);
void curve4_rel(double x_ctrl2, double y_ctrl2,
double x_to, double y_to);
void end_poly(unsigned flags = path_flags_close);
void close_polygon(unsigned flags = path_flags_none)
{
end_poly(path_flags_close | flags);
}
void add_poly(const double* vertices, unsigned num,
bool solid_path = false,
unsigned end_flags = path_flags_none);
void add_vertices(const double* vertices, unsigned num)
{
add_poly(vertices, num, path_flags_none);
}
template<class VertexSource>
void add_path(VertexSource& vs,
unsigned path_id = 0,
bool solid_path = true)
{
double x, y;
unsigned cmd;
vs.rewind(path_id);
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
if(is_move_to(cmd) && solid_path && m_total_vertices)
{
cmd = path_cmd_line_to;
}
add_vertex(x, y, cmd);
}
}
unsigned start_new_path();
void copy_from(const path_storage& ps);
const path_storage& operator = (const path_storage& ps)
{
copy_from(ps);
return *this;
}
unsigned total_vertices() const { return m_total_vertices; }
unsigned vertex(unsigned idx, double* x, double* y) const
{
unsigned nb = idx >> block_shift;
const double* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1);
*x = *pv++;
*y = *pv;
return m_cmd_blocks[nb][idx & block_mask];
}
unsigned command(unsigned idx) const
{
return m_cmd_blocks[idx >> block_shift][idx & block_mask];
}
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
const_iterator begin(unsigned id) const { return const_iterator(*this, id); }
const_iterator begin() const { return const_iterator(*this, 0); }
const_iterator end() const { return const_iterator(path_cmd_stop); }
// Arrange the orientation of all the polygons. After calling this
// method all the polygons will have the same orientation
// determined by the new_orientation flag, i.e.,
// path_flags_cw or path_flags_ccw
unsigned arrange_orientations(unsigned path_id, path_flags_e new_orientation);
void arrange_orientations_all_paths(path_flags_e new_orientation);
// Flip all the vertices horizontally or vertically
void flip_x(double x1, double x2);
void flip_y(double y1, double y2);
// This function adds a vertex with its flags directly. Since there's no
// checking for errors, keeping proper path integrity is the responsibility
// of the caller. It can be said the function is "not very public".
void add_vertex(double x, double y, unsigned cmd);
// Allows you to modify vertex coordinates. The caller must know
// the index of the vertex.
void modify_vertex(unsigned idx, double x, double y)
{
double* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1);
*pv++ = x;
*pv = y;
}
// Allows you to modify vertex command. The caller must know
// the index of the vertex.
void modify_command(unsigned idx, unsigned cmd)
{
m_cmd_blocks[idx >> block_shift][idx & block_mask] = (unsigned char)cmd;
}
private:
void allocate_block(unsigned nb);
unsigned char* storage_ptrs(double** xy_ptr);
unsigned perceive_polygon_orientation(unsigned idx,
double xs, double ys,
unsigned* orientation);
void reverse_polygon(unsigned start, unsigned end);
private:
unsigned m_total_vertices;
unsigned m_total_blocks;
unsigned m_max_blocks;
double** m_coord_blocks;
unsigned char** m_cmd_blocks;
unsigned m_iterator;
};
//------------------------------------------------------------------------
inline unsigned path_storage::vertex(double* x, double* y)
{
if(m_iterator >= m_total_vertices) return path_cmd_stop;
return vertex(m_iterator++, x, y);
}
//------------------------------------------------------------------------
inline unsigned path_storage::prev_vertex(double* x, double* y) const
{
if(m_total_vertices > 1)
{
return vertex(m_total_vertices - 2, x, y);
}
return path_cmd_stop;
}
//------------------------------------------------------------------------
inline unsigned path_storage::last_vertex(double* x, double* y) const
{
if(m_total_vertices)
{
return vertex(m_total_vertices - 1, x, y);
}
return path_cmd_stop;
}
//------------------------------------------------------------------------
inline void path_storage::rel_to_abs(double* x, double* y) const
{
if(m_total_vertices)
{
double x2;
double y2;
if(is_vertex(vertex(m_total_vertices - 1, &x2, &y2)))
{
*x += x2;
*y += y2;
}
}
}
//------------------------------------------------------------------------
inline unsigned char* path_storage::storage_ptrs(double** xy_ptr)
{
unsigned nb = m_total_vertices >> block_shift;
if(nb >= m_total_blocks)
{
allocate_block(nb);
}
*xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1);
return m_cmd_blocks[nb] + (m_total_vertices & block_mask);
}
//------------------------------------------------------------------------
inline void path_storage::add_vertex(double x, double y, unsigned cmd)
{
double* coord_ptr = 0;
unsigned char* cmd_ptr = storage_ptrs(&coord_ptr);
*cmd_ptr = (unsigned char)cmd;
*coord_ptr++ = x;
*coord_ptr = y;
m_total_vertices++;
}
//------------------------------------------------------------------------
inline void path_storage::move_to(double x, double y)
{
add_vertex(x, y, path_cmd_move_to);
}
//------------------------------------------------------------------------
inline void path_storage::move_rel(double dx, double dy)
{
rel_to_abs(&dx, &dy);
add_vertex(dx, dy, path_cmd_move_to);
}
//------------------------------------------------------------------------
inline void path_storage::line_to(double x, double y)
{
add_vertex(x, y, path_cmd_line_to);
}
//------------------------------------------------------------------------
inline void path_storage::line_rel(double dx, double dy)
{
rel_to_abs(&dx, &dy);
add_vertex(dx, dy, path_cmd_line_to);
}
}
#endif
+293
View File
@@ -0,0 +1,293 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PATH_STORAGE_INTEGER_INCLUDED
#define AGG_PATH_STORAGE_INTEGER_INCLUDED
#include <string.h>
#include "agg_array.h"
namespace agg
{
//---------------------------------------------------------vertex_integer
template<class T, unsigned CoordShift=6> struct vertex_integer
{
enum path_cmd
{
cmd_move_to = 0,
cmd_line_to = 1,
cmd_curve3 = 2,
cmd_curve4 = 3
};
enum
{
coord_shift = CoordShift,
coord_mult = 1 << coord_shift
};
T x,y;
vertex_integer() {}
vertex_integer(T x_, T y_, unsigned flag) :
x(((x_ << 1) & ~1) | (flag & 1)),
y(((y_ << 1) & ~1) | (flag >> 1)) {}
unsigned vertex(double* x_, double* y_, double dx=0, double dy=0) const
{
*x_ = dx + (double(x >> 1) / coord_mult);
*y_ = dy + (double(y >> 1) / coord_mult);
switch(((y & 1) << 1) | (x & 1))
{
case cmd_move_to: return path_cmd_move_to;
case cmd_line_to: return path_cmd_line_to;
case cmd_curve3: return path_cmd_curve3;
case cmd_curve4: return path_cmd_curve4;
}
return path_cmd_stop;
}
};
//---------------------------------------------------path_storage_integer
template<class T, unsigned CoordShift=6> class path_storage_integer
{
public:
typedef vertex_integer<T, CoordShift> vertex_integer_type;
//--------------------------------------------------------------------
path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {}
//--------------------------------------------------------------------
void remove_all() { m_storage.remove_all(); }
//--------------------------------------------------------------------
void move_to(T x, T y)
{
m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to));
}
//--------------------------------------------------------------------
void line_to(T x, T y)
{
m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_line_to));
}
//--------------------------------------------------------------------
void curve3(T x_ctrl, T y_ctrl,
T x_to, T y_to)
{
m_storage.add(vertex_integer_type(x_ctrl, y_ctrl, vertex_integer_type::cmd_curve3));
m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve3));
}
//--------------------------------------------------------------------
void curve4(T x_ctrl1, T y_ctrl1,
T x_ctrl2, T y_ctrl2,
T x_to, T y_to)
{
m_storage.add(vertex_integer_type(x_ctrl1, y_ctrl1, vertex_integer_type::cmd_curve4));
m_storage.add(vertex_integer_type(x_ctrl2, y_ctrl2, vertex_integer_type::cmd_curve4));
m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve4));
}
//--------------------------------------------------------------------
void close_polygon() {}
//--------------------------------------------------------------------
unsigned size() const { return m_storage.size(); }
unsigned vertex(unsigned idx, T* x, T* y) const
{
const vertex_integer_type& v = m_storage[idx];
*x = v.x >> 1;
*y = v.y >> 1;
return ((v.y & 1) << 1) | (v.x & 1);
}
//--------------------------------------------------------------------
unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); }
void serialize(int8u* ptr) const
{
unsigned i;
for(i = 0; i < m_storage.size(); i++)
{
memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type));
ptr += sizeof(vertex_integer_type);
}
}
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_vertex_idx = 0;
m_closed = true;
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
if(m_storage.size() < 2 || m_vertex_idx > m_storage.size())
{
*x = 0;
*y = 0;
return path_cmd_stop;
}
if(m_vertex_idx == m_storage.size())
{
*x = 0;
*y = 0;
++m_vertex_idx;
return path_cmd_end_poly | path_flags_close;
}
unsigned cmd = m_storage[m_vertex_idx].vertex(x, y);
if(is_move_to(cmd) && !m_closed)
{
*x = 0;
*y = 0;
m_closed = true;
return path_cmd_end_poly | path_flags_close;
}
m_closed = false;
++m_vertex_idx;
return cmd;
}
//--------------------------------------------------------------------
rect_d bounding_rect() const
{
rect_d bounds(1e100, 1e100, -1e100, -1e100);
if(m_storage.size() == 0)
{
bounds.x1 = bounds.x1 = bounds.x2 = bounds.y2 = 0.0;
}
else
{
unsigned i;
for(i = 0; i < m_storage.size(); i++)
{
double x, y;
m_storage[i].vertex(&x, &y);
if(x < bounds.x1) bounds.x1 = x;
if(y < bounds.y1) bounds.y1 = y;
if(x > bounds.x2) bounds.x2 = x;
if(y > bounds.y2) bounds.y2 = y;
}
}
return bounds;
}
private:
pod_deque<vertex_integer_type, 6> m_storage;
unsigned m_vertex_idx;
bool m_closed;
};
//-----------------------------------------serialized_integer_path_adaptor
template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor
{
public:
typedef vertex_integer<T, CoordShift> vertex_integer_type;
//--------------------------------------------------------------------
serialized_integer_path_adaptor() :
m_data(0),
m_end(0),
m_ptr(0),
m_dx(0.0),
m_dy(0.0),
m_closed(true)
{}
//--------------------------------------------------------------------
serialized_integer_path_adaptor(const int8u* data, unsigned size,
double dx, double dy) :
m_data(data),
m_end(data + size),
m_ptr(data),
m_dx(dx),
m_dy(dy),
m_closed(true)
{}
//--------------------------------------------------------------------
void init(const int8u* data, unsigned size, double dx, double dy)
{
m_data = data;
m_end = data + size;
m_ptr = data;
m_dx = dx;
m_dy = dy;
m_closed = true;
}
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_ptr = m_data;
m_closed = true;
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
if(m_data == 0 || m_ptr > m_end)
{
*x = 0;
*y = 0;
return path_cmd_stop;
}
if(m_ptr == m_end)
{
*x = 0;
*y = 0;
m_ptr += sizeof(vertex_integer_type);
return path_cmd_end_poly | path_flags_close;
}
vertex_integer_type v;
memcpy(&v, m_ptr, sizeof(vertex_integer_type));
unsigned cmd = v.vertex(x, y, m_dx, m_dy);
if(is_move_to(cmd) && !m_closed)
{
*x = 0;
*y = 0;
m_closed = true;
return path_cmd_end_poly | path_flags_close;
}
m_closed = false;
m_ptr += sizeof(vertex_integer_type);
return cmd;
}
private:
const int8u* m_data;
const int8u* m_end;
const int8u* m_ptr;
double m_dx;
double m_dy;
bool m_closed;
};
}
#endif
@@ -0,0 +1,117 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PATTERN_FILTERS_RGBA8_INCLUDED
#define AGG_PATTERN_FILTERS_RGBA8_INCLUDED
#include "agg_basics.h"
#include "agg_line_aa_basics.h"
#include "agg_color_rgba8.h"
namespace agg
{
//=======================================================pattern_filter_nn
template<class ColorT> struct pattern_filter_nn
{
typedef ColorT color_type;
static unsigned dilation() { return 0; }
static void pixel_low_res(color_type const* const* buf,
color_type* p, int x, int y)
{
*p = buf[y][x];
}
static void pixel_high_res(color_type const* const* buf,
color_type* p, int x, int y)
{
*p = buf[y >> line_subpixel_shift]
[x >> line_subpixel_shift];
}
};
typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8;
//===========================================pattern_filter_bilinear_rgba8
struct pattern_filter_bilinear_rgba8
{
typedef rgba8 color_type;
static unsigned dilation() { return 1; }
static void pixel_low_res(color_type const* const* buf,
color_type* p, int x, int y)
{
*p = buf[y][x];
}
static void pixel_high_res(color_type const* const* buf,
color_type* p, int x, int y)
{
int r, g, b, a;
r = g = b = a = line_subpixel_size * line_subpixel_size / 2;
int weight;
int x_lr = x >> line_subpixel_shift;
int y_lr = y >> line_subpixel_shift;
x &= line_subpixel_mask;
y &= line_subpixel_mask;
const color_type* ptr = buf[y_lr] + x_lr;
weight = (line_subpixel_size - x) *
(line_subpixel_size - y);
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
++ptr;
weight = x * (line_subpixel_size - y);
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
ptr = buf[y_lr + 1] + x_lr;
weight = (line_subpixel_size - x) * y;
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
++ptr;
weight = x * y;
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
p->r = (int8u)(r >> line_subpixel_shift * 2);
p->g = (int8u)(g >> line_subpixel_shift * 2);
p->b = (int8u)(b >> line_subpixel_shift * 2);
p->a = (int8u)(a >> line_subpixel_shift * 2);
}
};
}
#endif
+222
View File
@@ -0,0 +1,222 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
#define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
#include <string.h>
#include "agg_rendering_buffer.h"
namespace agg
{
//==================================================pixfmt_amask_adaptor
template<class PixFmt, class AlphaMask> class pixfmt_amask_adaptor
{
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef AlphaMask amask_type;
typedef typename amask_type::cover_type cover_type;
private:
enum { span_extra_tail = 256 };
void realloc_span(unsigned len)
{
if(len > m_max_len)
{
delete [] m_span;
m_span = new cover_type[m_max_len = len + span_extra_tail];
}
}
void init_span(unsigned len)
{
realloc_span(len);
// ATTN! May work incorrectly if cover_type is more that one byte
memset(m_span, amask_type::cover_full, len * sizeof(cover_type));
}
void init_span(unsigned len, const cover_type* covers)
{
realloc_span(len);
memcpy(m_span, covers, len * sizeof(cover_type));
}
public:
~pixfmt_amask_adaptor() { delete [] m_span; }
pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) :
m_pixf(&pixf), m_mask(&mask), m_span(0), m_max_len(0)
{}
void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; }
void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; }
//--------------------------------------------------------------------
unsigned width() const { return m_pixf->width(); }
unsigned height() const { return m_pixf->height(); }
//--------------------------------------------------------------------
color_type pixel(int x, int y)
{
return m_pixf->pixel(x, y);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y));
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
{
m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover));
}
//--------------------------------------------------------------------
void copy_hline(int x, int y,
unsigned len,
const color_type& c)
{
realloc_span(len);
m_mask->fill_hspan(x, y, m_span, len);
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y,
unsigned len,
const color_type& c,
cover_type cover)
{
init_span(len);
m_mask->combine_hspan(x, y, m_span, len);
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
}
//--------------------------------------------------------------------
void copy_vline(int x, int y,
unsigned len,
const color_type& c)
{
realloc_span(len);
m_mask->fill_vspan(x, y, m_span, len);
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
}
//--------------------------------------------------------------------
void blend_vline(int x, int y,
unsigned len,
const color_type& c,
cover_type cover)
{
init_span(len);
m_mask->combine_vspan(x, y, m_span, len);
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
}
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len);
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y,
unsigned len,
const color_type& c,
const cover_type* covers)
{
init_span(len, covers);
m_mask->combine_hspan(x, y, m_span, len);
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y,
unsigned len,
const color_type& c,
const cover_type* covers)
{
init_span(len, covers);
m_mask->combine_vspan(x, y, m_span, len);
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y,
unsigned len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
if(covers)
{
init_span(len, covers);
m_mask->combine_hspan(x, y, m_span, len);
}
else
{
realloc_span(len);
m_mask->fill_hspan(x, y, m_span, len);
}
m_pixf->blend_color_hspan(x, y, len, colors, m_span, cover);
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y,
unsigned len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
if(covers)
{
init_span(len, covers);
m_mask->combine_vspan(x, y, m_span, len);
}
else
{
realloc_span(len);
m_mask->fill_vspan(x, y, m_span, len);
}
m_pixf->blend_color_vspan(x, y, len, colors, m_span, cover);
}
private:
pixfmt_type* m_pixf;
const amask_type* m_mask;
cover_type* m_span;
unsigned m_max_len;
};
}
#endif
+312
View File
@@ -0,0 +1,312 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_GRAY8_INCLUDED
#define AGG_PIXFMT_GRAY8_INCLUDED
#include <string.h>
#include "agg_basics.h"
#include "agg_gray8.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//======================================================pixfmt_gray8_base
template<unsigned Step=1, unsigned Offset=0>
class pixfmt_gray8_base
{
public:
typedef gray8 color_type;
//--------------------------------------------------------------------
pixfmt_gray8_base(rendering_buffer& rb)
: m_rbuf(&rb)
{
}
//--------------------------------------------------------------------
unsigned width() const { return m_rbuf->width(); }
unsigned height() const { return m_rbuf->height(); }
//--------------------------------------------------------------------
color_type pixel(int x, int y)
{
return color_type(m_rbuf->row(y)[x * Step + Offset]);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
m_rbuf->row(y)[x * Step + Offset] = (int8u)c.v;
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, int8u cover)
{
int8u* p = m_rbuf->row(y) + x * Step + Offset;
int v = *p;
int alpha = int(cover) * c.a;
*p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16);
}
//--------------------------------------------------------------------
void copy_hline(int x, int y, unsigned len, const color_type& c)
{
int8u* p = m_rbuf->row(y) + x * Step + Offset;
do
{
*p = (int8u)c.v;
p += Step;
}
while(--len);
}
//--------------------------------------------------------------------
void copy_vline(int x, int y, unsigned len, const color_type& c)
{
int8u* p = m_rbuf->row(y) + x * Step + Offset;
do
{
*p = (int8u)c.v;
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
int8u* p = m_rbuf->row(y) + x * Step + Offset;
int alpha = int(cover) * c.a;
if(alpha == 255*255)
{
do
{
*p = (int8u)c.v;
p += Step;
}
while(--len);
}
else
{
do
{
int v = *p;
*p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16);
p += Step;
}
while(--len);
}
}
//--------------------------------------------------------------------
void blend_vline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
int8u* p = m_rbuf->row(y) + x * Step + Offset;
int alpha = int(cover) * c.a;
if(alpha == 255*255)
{
do
{
*p = (int8u)c.v;
p += m_rbuf->stride();
}
while(--len);
}
else
{
do
{
int v = *p;
*p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16);
p += m_rbuf->stride();
}
while(--len);
}
}
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
memmove(m_rbuf->row(ydst) + xdst * Step + Offset,
(const void*)(from.row(ysrc) + xsrc * Step + Offset),
len * Step);
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int8u* p = m_rbuf->row(y) + x * Step + Offset;
do
{
int alpha = int(*covers++) * c.a;
if(alpha)
{
if(alpha == 255*255)
{
*p = (int8u)c.v;
}
else
{
int v = *p;
*p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16);
}
}
p += Step;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int8u* p = m_rbuf->row(y) + x * Step + Offset;
do
{
int alpha = int(*covers++) * c.a;
if(alpha)
{
if(alpha == 255*255)
{
*p = (int8u)c.v;
}
else
{
int v = *p;
*p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16);
}
}
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + x * Step + Offset;
do
{
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
if(alpha)
{
if(alpha == 255*255)
{
*p = (int8u)colors->v;
}
else
{
int v = *p;
*p = (int8u)((((colors->v - v) * alpha) + (v << 16)) >> 16);
}
}
p += Step;
++colors;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + x * Step + Offset;
do
{
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
if(alpha)
{
if(alpha == 255*255)
{
*p = (int8u)colors->v;
}
else
{
int v = *p;
*p = (int8u)((((colors->v - v) * alpha) + (v << 16)) >> 16);
}
}
p += m_rbuf->stride();
++colors;
}
while(--len);
}
private:
rendering_buffer* m_rbuf;
};
typedef pixfmt_gray8_base<1, 0> pixfmt_gray8; //----pixfmt_gray8
typedef pixfmt_gray8_base<3, 0> pixfmt_gray8_rgb24r; //----pixfmt_gray8_rgb24r
typedef pixfmt_gray8_base<3, 1> pixfmt_gray8_rgb24g; //----pixfmt_gray8_rgb24g
typedef pixfmt_gray8_base<3, 2> pixfmt_gray8_rgb24b; //----pixfmt_gray8_rgb24b
typedef pixfmt_gray8_base<3, 2> pixfmt_gray8_bgr24r; //----pixfmt_gray8_bgr24r
typedef pixfmt_gray8_base<3, 1> pixfmt_gray8_bgr24g; //----pixfmt_gray8_bgr24g
typedef pixfmt_gray8_base<3, 0> pixfmt_gray8_bgr24b; //----pixfmt_gray8_bgr24b
typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_rgba32r; //----pixfmt_gray8_rgba32r
typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_rgba32g; //----pixfmt_gray8_rgba32g
typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_rgba32b; //----pixfmt_gray8_rgba32b
typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_rgba32a; //----pixfmt_gray8_rgba32a
typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_argb32r; //----pixfmt_gray8_argb32r
typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_argb32g; //----pixfmt_gray8_argb32g
typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_argb32b; //----pixfmt_gray8_argb32b
typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_argb32a; //----pixfmt_gray8_argb32a
typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_bgra32r; //----pixfmt_gray8_bgra32r
typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_bgra32g; //----pixfmt_gray8_bgra32g
typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_bgra32b; //----pixfmt_gray8_bgra32b
typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_bgra32a; //----pixfmt_gray8_bgra32a
typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_abgr32r; //----pixfmt_gray8_abgr32r
typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_abgr32g; //----pixfmt_gray8_abgr32g
typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_abgr32b; //----pixfmt_gray8_abgr32b
typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_abgr32a; //----pixfmt_gray8_abgr32a
}
#endif
+355
View File
@@ -0,0 +1,355 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_RGB24_INCLUDED
#define AGG_PIXFMT_RGB24_INCLUDED
#include <string.h>
#include "agg_basics.h"
#include "agg_color_rgba8.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//=====================================================pixel_formats_rgb24
template<class Order> class pixel_formats_rgb24
{
public:
typedef rgba8 color_type;
//--------------------------------------------------------------------
pixel_formats_rgb24(rendering_buffer& rb)
: m_rbuf(&rb)
{
}
//--------------------------------------------------------------------
unsigned width() const { return m_rbuf->width(); }
unsigned height() const { return m_rbuf->height(); }
//--------------------------------------------------------------------
color_type pixel(int x, int y)
{
int8u* p = m_rbuf->row(y) + x + x + x;
return color_type(p[Order::R], p[Order::G], p[Order::B]);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
int8u* p = m_rbuf->row(y) + x + x + x;
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, int8u cover)
{
int8u* p = m_rbuf->row(y) + x + x + x;
int alpha = int(cover) * c.a;
if(alpha == 255*255)
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
}
else
{
int r = p[Order::R];
int g = p[Order::G];
int b = p[Order::B];
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
}
}
//--------------------------------------------------------------------
void copy_hline(int x, int y,
unsigned len,
const color_type& c)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p += 3;
}
while(--len);
}
//--------------------------------------------------------------------
void copy_vline(int x, int y,
unsigned len,
const color_type& c)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y,
unsigned len,
const color_type& c,
int8u cover)
{
int8u* p = m_rbuf->row(y) + x + x + x;
int alpha = int(cover) * c.a;
if(alpha == 255*255)
{
do
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p += 3;
}
while(--len);
}
else
{
do
{
int r = p[Order::R];
int g = p[Order::G];
int b = p[Order::B];
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
p += 3;
}
while(--len);
}
}
//--------------------------------------------------------------------
void blend_vline(int x, int y,
unsigned len,
const color_type& c,
int8u cover)
{
int8u* p = m_rbuf->row(y) + x + x + x;
int alpha = int(cover) * c.a;
if(alpha == 255*255)
{
do
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p += m_rbuf->stride();
}
while(--len);
}
else
{
do
{
int r = p[Order::R];
int g = p[Order::G];
int b = p[Order::B];
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
p += m_rbuf->stride();
}
while(--len);
}
}
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
memmove(m_rbuf->row(ydst) + xdst * 3,
(const void*)(from.row(ysrc) + xsrc * 3), len * 3);
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
int alpha = int(*covers++) * c.a;
if(alpha)
{
if(alpha == 255*255)
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
}
else
{
int r = (int8u)p[Order::R];
int g = (int8u)p[Order::G];
int b = (int8u)p[Order::B];
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
}
}
p += 3;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
int alpha = int(*covers++) * c.a;
if(alpha)
{
if(alpha == 255*255)
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
}
else
{
int r = p[Order::R];
int g = p[Order::G];
int b = p[Order::B];
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
}
}
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
const int8u cover)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
if(alpha)
{
if(alpha == 255*255)
{
p[Order::R] = (int8u)colors->r;
p[Order::G] = (int8u)colors->g;
p[Order::B] = (int8u)colors->b;
}
else
{
int r = p[Order::R];
int g = p[Order::G];
int b = p[Order::B];
p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16);
}
}
p += 3;
++colors;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
const int8u cover)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
if(alpha)
{
if(alpha == 255*255)
{
p[Order::R] = (int8u)colors->r;
p[Order::G] = (int8u)colors->g;
p[Order::B] = (int8u)colors->b;
}
else
{
int r = p[Order::R];
int g = p[Order::G];
int b = p[Order::B];
p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16);
}
}
p += m_rbuf->stride();
++colors;
}
while(--len);
}
private:
rendering_buffer* m_rbuf;
};
typedef pixel_formats_rgb24<order_rgb24> pixfmt_rgb24; //----pixfmt_rgb24
typedef pixel_formats_rgb24<order_bgr24> pixfmt_bgr24; //----pixfmt_bgr24
}
#endif
+331
View File
@@ -0,0 +1,331 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_RGB24_GAMMA_INCLUDED
#define AGG_PIXFMT_RGB24_GAMMA_INCLUDED
#include <string.h>
#include "agg_basics.h"
#include "agg_color_rgba8.h"
#include "agg_rendering_buffer.h"
#include "agg_gamma_lut.h"
namespace agg
{
//================================================pixel_formats_rgb24_gamma
template<class Order, class Gamma> class pixel_formats_rgb24_gamma
{
public:
typedef rgba8 color_type;
typedef Gamma gamma_type;
private:
//--------------------------------------------------------------------
inline void blend_pix(int8u* p, const color_type& c, int alpha)
{
int r = m_gamma->dir(p[Order::R]);
int g = m_gamma->dir(p[Order::G]);
int b = m_gamma->dir(p[Order::B]);
p[Order::R] = m_gamma->inv((((m_gamma->dir(c.r) - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = m_gamma->inv((((m_gamma->dir(c.g) - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = m_gamma->inv((((m_gamma->dir(c.b) - b) * alpha) + (b << 16)) >> 16);
}
//--------------------------------------------------------------------
inline void copy_or_blend_pix(int8u* p, const color_type& c, int cover)
{
int alpha = int(c.a) * cover;
if(alpha)
{
if(alpha == 255*255)
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
}
else
{
blend_pix(p, c, alpha);
}
}
}
//--------------------------------------------------------------------
inline void copy_or_blend_pix(int8u* p, const color_type& c)
{
if(c.a)
{
if(c.a == 255)
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
}
else
{
int r = m_gamma->dir(p[Order::R]);
int g = m_gamma->dir(p[Order::G]);
int b = m_gamma->dir(p[Order::B]);
p[Order::R] = m_gamma->inv((((m_gamma->dir(c.r) - r) * c.a) + (r << 8)) >> 8);
p[Order::G] = m_gamma->inv((((m_gamma->dir(c.g) - g) * c.a) + (g << 8)) >> 8);
p[Order::B] = m_gamma->inv((((m_gamma->dir(c.b) - b) * c.a) + (b << 8)) >> 8);
}
}
}
public:
//--------------------------------------------------------------------
pixel_formats_rgb24_gamma(rendering_buffer& rb, const gamma_type& g) :
m_rbuf(&rb),
m_gamma(&g)
{}
//--------------------------------------------------------------------
void gamma(const gamma_type& g) { m_gamma = &g; }
const gamma_type& gamma() const { return *m_gamma; }
//--------------------------------------------------------------------
unsigned width() const { return m_rbuf->width(); }
unsigned height() const { return m_rbuf->height(); }
//--------------------------------------------------------------------
color_type pixel(int x, int y)
{
int8u* p = m_rbuf->row(y) + x + x + x;
return color_type(p[Order::R], p[Order::G], p[Order::B]);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
int8u* p = m_rbuf->row(y) + x + x + x;
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, int8u cover)
{
copy_or_blend_pix(m_rbuf->row(y) + x + x + x, c, cover);
}
//--------------------------------------------------------------------
void copy_hline(int x, int y,
unsigned len,
const color_type& c)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p += 3;
}
while(--len);
}
//--------------------------------------------------------------------
void copy_vline(int x, int y,
unsigned len,
const color_type& c)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y,
unsigned len,
const color_type& c,
int8u cover)
{
int8u* p = m_rbuf->row(y) + x + x + x;
int alpha = int(cover) * c.a;
if(alpha == 255*255)
{
do
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p += 3;
}
while(--len);
}
else
{
do
{
blend_pix(p, c, alpha);
p += 3;
}
while(--len);
}
}
//--------------------------------------------------------------------
void blend_vline(int x, int y,
unsigned len,
const color_type& c,
int8u cover)
{
int8u* p = m_rbuf->row(y) + x + x + x;
int alpha = int(cover) * c.a;
if(alpha == 255*255)
{
do
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p += m_rbuf->stride();
}
while(--len);
}
else
{
do
{
blend_pix(p, c, alpha);
p += m_rbuf->stride();
}
while(--len);
}
}
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
memmove(m_rbuf->row(ydst) + xdst * 3,
(const void*)(from.row(ysrc) + xsrc * 3), len * 3);
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
copy_or_blend_pix(p, c, *covers++);
p += 3;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
copy_or_blend_pix(p, c, *covers++);
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
p += 3;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
p += m_rbuf->stride();
}
while(--len);
}
private:
rendering_buffer* m_rbuf;
const gamma_type* m_gamma;
};
//-----------------------------------------------------pixfmt_rgb24_gamma
template<class Gamma> class pixfmt_rgb24_gamma :
public pixel_formats_rgb24_gamma<order_rgb24, Gamma>
{
public:
pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) :
pixel_formats_rgb24_gamma<order_rgb24, Gamma>(rb, g) {}
};
//-----------------------------------------------------pixfmt_bgr24_gamma
template<class Gamma> class pixfmt_bgr24_gamma :
public pixel_formats_rgb24_gamma<order_bgr24, Gamma>
{
public:
pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) :
pixel_formats_rgb24_gamma<order_bgr24, Gamma>(rb, g) {}
};
}
#endif
+292
View File
@@ -0,0 +1,292 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_RGB24_PRE_INCLUDED
#define AGG_PIXFMT_RGB24_PRE_INCLUDED
#include <string.h>
#include "agg_basics.h"
#include "agg_color_rgba8.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//==================================================pixel_formats_rgb24_pre
template<class Order> class pixel_formats_rgb24_pre
{
public:
typedef rgba8 color_type;
private:
//--------------------------------------------------------------------
static inline void copy_pix(int8u* p, const color_type& c)
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
}
//--------------------------------------------------------------------
static inline void blend_pix(int8u* p, const color_type& c,
unsigned cover, unsigned alpha)
{
p[Order::R] = (int8u)((p[Order::R] * alpha + ((c.r * cover) << 8)) >> 16);
p[Order::G] = (int8u)((p[Order::G] * alpha + ((c.g * cover) << 8)) >> 16);
p[Order::B] = (int8u)((p[Order::B] * alpha + ((c.b * cover) << 8)) >> 16);
}
//--------------------------------------------------------------------
static inline void copy_or_blend_pix(int8u* p, const color_type& c, unsigned cover)
{
unsigned alpha = 65535 - cover * c.a;
if(alpha < 65535)
{
if(alpha <= 65535-255*255)
{
copy_pix(p, c);
}
else
{
blend_pix(p, c, cover, alpha);
}
}
}
//--------------------------------------------------------------------
static inline void copy_or_blend_pix(int8u* p, const color_type& c)
{
unsigned alpha = 255 - c.a;
if(alpha < 255)
{
if(alpha == 0)
{
copy_pix(p, c);
}
else
{
p[Order::R] = (int8u)((p[Order::R] * alpha + (c.r << 8)) >> 8);
p[Order::G] = (int8u)((p[Order::G] * alpha + (c.g << 8)) >> 8);
p[Order::B] = (int8u)((p[Order::B] * alpha + (c.b << 8)) >> 8);
}
}
}
public:
//--------------------------------------------------------------------
pixel_formats_rgb24_pre(rendering_buffer& rb)
: m_rbuf(&rb)
{
}
//--------------------------------------------------------------------
unsigned width() const { return m_rbuf->width(); }
unsigned height() const { return m_rbuf->height(); }
//--------------------------------------------------------------------
color_type pixel(int x, int y)
{
int8u* p = m_rbuf->row(y) + x + x + x;
return color_type(p[Order::R], p[Order::G], p[Order::B]);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
int8u* p = m_rbuf->row(y) + x + x + x;
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, int8u cover)
{
copy_or_blend_pix(m_rbuf->row(y) + x + x + x, c, cover);
}
//--------------------------------------------------------------------
void copy_hline(int x, int y, unsigned len, const color_type& c)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p += 3;
}
while(--len);
}
//--------------------------------------------------------------------
void copy_vline(int x, int y, unsigned len, const color_type& c)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
int8u* p = m_rbuf->row(y) + x + x + x;
unsigned alpha = unsigned(cover) * c.a;
if(alpha == 255*255)
{
do
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p += 3;
}
while(--len);
}
else
{
alpha = 65535 - alpha;
do
{
blend_pix(p, c, cover, alpha);
p += 3;
}
while(--len);
}
}
//--------------------------------------------------------------------
void blend_vline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
int8u* p = m_rbuf->row(y) + x + x + x;
unsigned alpha = unsigned(cover) * c.a;
if(alpha == 255*255)
{
do
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p += m_rbuf->stride();
}
while(--len);
}
else
{
alpha = 65535 - alpha;
do
{
blend_pix(p, c, cover, alpha);
p += m_rbuf->stride();
}
while(--len);
}
}
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
memmove(m_rbuf->row(ydst) + xdst * 3,
(const void*)(from.row(ysrc) + xsrc * 3), len * 3);
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
copy_or_blend_pix(p, c, *covers++);
p += 3;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
copy_or_blend_pix(p, c, *covers++);
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
p += 3;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + x + x + x;
do
{
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
p += m_rbuf->stride();
}
while(--len);
}
private:
rendering_buffer* m_rbuf;
};
typedef pixel_formats_rgb24_pre<order_rgb24> pixfmt_rgb24_pre; //----pixfmt_rgb24_pre
typedef pixel_formats_rgb24_pre<order_bgr24> pixfmt_bgr24_pre; //----pixfmt_bgr24_pre
}
#endif
+326
View File
@@ -0,0 +1,326 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_RGB555_INCLUDED
#define AGG_PIXFMT_RGB555_INCLUDED
#include <string.h>
#include "agg_basics.h"
#include "agg_color_rgba8.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//------------------------------------------------------------------rgb555
inline int16u rgb555(unsigned r, unsigned g, unsigned b)
{
return (int16u)(((r & 0xF8) << 7) | ((g & 0xF8) << 2) | (b >> 3));
}
//===========================================================pixfmt_rgb555
class pixfmt_rgb555
{
public:
typedef rgba8 color_type;
//--------------------------------------------------------------------
pixfmt_rgb555(rendering_buffer& rb)
: m_rbuf(&rb)
{
}
//--------------------------------------------------------------------
unsigned width() const { return m_rbuf->width(); }
unsigned height() const { return m_rbuf->height(); }
//--------------------------------------------------------------------
color_type pixel(int x, int y)
{
unsigned rgb = ((int16u*)(m_rbuf->row(y)))[x];
return color_type((rgb >> 7) & 0xF8,
(rgb >> 2) & 0xF8,
(rgb << 3) & 0xF8);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
((int16u*)(m_rbuf->row(y)))[x] = rgb555(c.r, c.g, c.b);
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, int8u cover)
{
int alpha = int(cover) * c.a;
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
if(alpha == 255*255)
{
*p = rgb555(c.r, c.g, c.b);
}
else
{
int16u rgb = *p;
int r = (rgb >> 7) & 0xF8;
int g = (rgb >> 2) & 0xF8;
int b = (rgb << 3) & 0xF8;
*p = (int16u)
((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
(((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
((((c.b - b) * alpha) + (b << 16)) >> 19));
}
}
//--------------------------------------------------------------------
void copy_hline(int x, int y, unsigned len, const color_type& c)
{
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
int16u v = rgb555(c.r, c.g, c.b);
do
{
*p++ = v;
}
while(--len);
}
//--------------------------------------------------------------------
void copy_vline(int x, int y, unsigned len, const color_type& c)
{
int8u* p = m_rbuf->row(y) + (x << 1);
int16u v = rgb555(c.r, c.g, c.b);
do
{
*(int16u*)p = v;
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
int alpha = int(cover) * c.a;
if(alpha == 255*255)
{
int16u v = rgb555(c.r, c.g, c.b);
do
{
*p++ = v;
}
while(--len);
}
else
{
do
{
int16u rgb = *p;
int r = (rgb >> 7) & 0xF8;
int g = (rgb >> 2) & 0xF8;
int b = (rgb << 3) & 0xF8;
*p++ = (int16u)
((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
(((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
((((c.b - b) * alpha) + (b << 16)) >> 19));
}
while(--len);
}
}
//--------------------------------------------------------------------
void blend_vline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 1);
int alpha = int(cover) * c.a;
if(alpha == 255*255)
{
int16u v = rgb555(c.r, c.g, c.b);
do
{
*(int16u*)p = v;
p += m_rbuf->stride();
}
while(--len);
}
else
{
do
{
int16u rgb = *(int16u*)p;
int r = (rgb >> 7) & 0xF8;
int g = (rgb >> 2) & 0xF8;
int b = (rgb << 3) & 0xF8;
*(int16u*)p = (int16u)
((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
(((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
((((c.b - b) * alpha) + (b << 16)) >> 19));
p += m_rbuf->stride();
}
while(--len);
}
}
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
memmove(m_rbuf->row(ydst) + xdst * 2,
(const void*)(from.row(ysrc) + xsrc * 2), len * 2);
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
do
{
int alpha = int(*covers++) * c.a;
if(alpha)
{
if(alpha == 255*255)
{
*p = rgb555(c.r, c.g, c.b);
}
else
{
int16u rgb = *p;
int r = (rgb >> 7) & 0xF8;
int g = (rgb >> 2) & 0xF8;
int b = (rgb << 3) & 0xF8;
*p = (int16u)
((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
(((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
((((c.b - b) * alpha) + (b << 16)) >> 19));
}
}
++p;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int8u* p = m_rbuf->row(y) + (x << 1);
do
{
int alpha = int(*covers++) * c.a;
if(alpha)
{
if(alpha == 255*255)
{
*(int16u*)p = rgb555(c.r, c.g, c.b);
}
else
{
int16u rgb = *(int16u*)p;
int r = (rgb >> 7) & 0xF8;
int g = (rgb >> 2) & 0xF8;
int b = (rgb << 3) & 0xF8;
*(int16u*)p = (int16u)
((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
(((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
((((c.b - b) * alpha) + (b << 16)) >> 19));
}
}
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
do
{
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
if(alpha)
{
if(alpha == 255*255)
{
*(int16u*)p = rgb555(colors->r, colors->g, colors->b);
}
else
{
int16u rgb = *p;
int r = (rgb >> 7) & 0xF8;
int g = (rgb >> 2) & 0xF8;
int b = (rgb << 3) & 0xF8;
*(int16u*)p = (int16u)
((((((colors->r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
(((((colors->g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
((((colors->b - b) * alpha) + (b << 16)) >> 19));
}
}
++p;
++colors;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 1);
do
{
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
if(alpha)
{
if(alpha == 255*255)
{
*(int16u*)p = rgb555(colors->r, colors->g, colors->b);
}
else
{
int16u rgb = *(int16u*)p;
int r = (rgb >> 7) & 0xF8;
int g = (rgb >> 2) & 0xF8;
int b = (rgb << 3) & 0xF8;
*(int16u*)p = (int16u)
((((((colors->r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
(((((colors->g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
((((colors->b - b) * alpha) + (b << 16)) >> 19));
}
}
p += m_rbuf->stride();
++colors;
}
while(--len);
}
private:
rendering_buffer* m_rbuf;
};
}
#endif
+326
View File
@@ -0,0 +1,326 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_RGB565_INCLUDED
#define AGG_PIXFMT_RGB565_INCLUDED
#include <string.h>
#include "agg_basics.h"
#include "agg_color_rgba8.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//------------------------------------------------------------------rgb565
inline int16u rgb565(unsigned r, unsigned g, unsigned b)
{
return (int16u)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3));
}
//===========================================================pixfmt_rgb565
class pixfmt_rgb565
{
public:
typedef rgba8 color_type;
//--------------------------------------------------------------------
pixfmt_rgb565(rendering_buffer& rb)
: m_rbuf(&rb)
{
}
//--------------------------------------------------------------------
unsigned width() const { return m_rbuf->width(); }
unsigned height() const { return m_rbuf->height(); }
//--------------------------------------------------------------------
color_type pixel(int x, int y)
{
unsigned rgb = ((int16u*)(m_rbuf->row(y)))[x];
return color_type((rgb >> 8) & 0xF8,
(rgb >> 3) & 0xFC,
(rgb << 3) & 0xF8);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
((int16u*)(m_rbuf->row(y)))[x] = rgb565(c.r, c.g, c.b);
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, int8u cover)
{
int alpha = int(cover) * c.a;
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
if(alpha == 255*255)
{
*p = rgb565(c.r, c.g, c.b);
}
else
{
int16u rgb = *p;
int r = (rgb >> 8) & 0xF8;
int g = (rgb >> 3) & 0xFC;
int b = (rgb << 3) & 0xF8;
*p = (int16u)
((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
(((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
((((c.b - b) * alpha) + (b << 16)) >> 19));
}
}
//--------------------------------------------------------------------
void copy_hline(int x, int y, unsigned len, const color_type& c)
{
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
int16u v = rgb565(c.r, c.g, c.b);
do
{
*p++ = v;
}
while(--len);
}
//--------------------------------------------------------------------
void copy_vline(int x, int y, unsigned len, const color_type& c)
{
int8u* p = m_rbuf->row(y) + (x << 1);
int16u v = rgb565(c.r, c.g, c.b);
do
{
*(int16u*)p = v;
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
int alpha = int(cover) * c.a;
if(alpha == 255*255)
{
int16u v = rgb565(c.r, c.g, c.b);
do
{
*p++ = v;
}
while(--len);
}
else
{
do
{
int16u rgb = *p;
int r = (rgb >> 8) & 0xF8;
int g = (rgb >> 3) & 0xFC;
int b = (rgb << 3) & 0xF8;
*p++ = (int16u)
((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
(((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
((((c.b - b) * alpha) + (b << 16)) >> 19));
}
while(--len);
}
}
//--------------------------------------------------------------------
void blend_vline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 1);
int alpha = int(cover) * c.a;
if(alpha == 255*255)
{
int16u v = rgb565(c.r, c.g, c.b);
do
{
*(int16u*)p = v;
p += m_rbuf->stride();
}
while(--len);
}
else
{
do
{
int16u rgb = *(int16u*)p;
int r = (rgb >> 8) & 0xF8;
int g = (rgb >> 3) & 0xFC;
int b = (rgb << 3) & 0xF8;
*(int16u*)p = (int16u)
((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
(((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
((((c.b - b) * alpha) + (b << 16)) >> 19));
p += m_rbuf->stride();
}
while(--len);
}
}
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
memmove(m_rbuf->row(ydst) + xdst * 2,
(const void*)(from.row(ysrc) + xsrc * 2), len * 2);
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
do
{
int alpha = int(*covers++) * c.a;
if(alpha)
{
if(alpha == 255*255)
{
*p = rgb565(c.r, c.g, c.b);
}
else
{
int16u rgb = *p;
int r = (rgb >> 8) & 0xF8;
int g = (rgb >> 3) & 0xFC;
int b = (rgb << 3) & 0xF8;
*p = (int16u)
((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
(((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
((((c.b - b) * alpha) + (b << 16)) >> 19));
}
}
++p;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int8u* p = m_rbuf->row(y) + (x << 1);
do
{
int alpha = int(*covers++) * c.a;
if(alpha)
{
if(alpha == 255*255)
{
*(int16u*)p = rgb565(c.r, c.g, c.b);
}
else
{
int16u rgb = *(int16u*)p;
int r = (rgb >> 8) & 0xF8;
int g = (rgb >> 3) & 0xFC;
int b = (rgb << 3) & 0xF8;
*(int16u*)p = (int16u)
((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
(((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
((((c.b - b) * alpha) + (b << 16)) >> 19));
}
}
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
do
{
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
if(alpha)
{
if(alpha == 255*255)
{
*(int16u*)p = rgb565(colors->r, colors->g, colors->b);
}
else
{
int16u rgb = *p;
int r = (rgb >> 8) & 0xF8;
int g = (rgb >> 3) & 0xFC;
int b = (rgb << 3) & 0xF8;
*p = (int16u)
((((((colors->r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
(((((colors->g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
((((colors->b - b) * alpha) + (b << 16)) >> 19));
}
}
++p;
++colors;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 1);
do
{
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
if(alpha)
{
if(alpha == 255*255)
{
*(int16u*)p = rgb565(colors->r, colors->g, colors->b);
}
else
{
int16u rgb = *(int16u*)p;
int r = (rgb >> 8) & 0xF8;
int g = (rgb >> 3) & 0xFC;
int b = (rgb << 3) & 0xF8;
*(int16u*)p = (int16u)
((((((colors->r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
(((((colors->g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
((((colors->b - b) * alpha) + (b << 16)) >> 19));
}
}
p += m_rbuf->stride();
++colors;
}
while(--len);
}
private:
rendering_buffer* m_rbuf;
};
}
#endif
+371
View File
@@ -0,0 +1,371 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_RGBA32_INCLUDED
#define AGG_PIXFMT_RGBA32_INCLUDED
#include <string.h>
#include "agg_basics.h"
#include "agg_color_rgba8.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//====================================================pixel_formats_rgba32
template<class Order> class pixel_formats_rgba32
{
public:
typedef rgba8 color_type;
//--------------------------------------------------------------------
pixel_formats_rgba32(rendering_buffer& rb)
: m_rbuf(&rb)
{
}
//--------------------------------------------------------------------
unsigned width() const { return m_rbuf->width(); }
unsigned height() const { return m_rbuf->height(); }
//--------------------------------------------------------------------
color_type pixel(int x, int y)
{
int8u* p = m_rbuf->row(y) + (x << 2);
return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
int8u* p = m_rbuf->row(y) + (x << 2);
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p[Order::A] = (int8u)c.a;
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 2);
int alpha = int(cover) * int(c.a);
if(alpha == 255*255)
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p[Order::A] = (int8u)c.a;
}
else
{
int r = p[Order::R];
int g = p[Order::G];
int b = p[Order::B];
int a = p[Order::A];
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
}
}
//--------------------------------------------------------------------
void copy_hline(int x, int y, unsigned len, const color_type& c)
{
int32u v;
int8u* p8 = (int8u*)&v;
p8[Order::R] = (int8u)c.r;
p8[Order::G] = (int8u)c.g;
p8[Order::B] = (int8u)c.b;
p8[Order::A] = (int8u)c.a;
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
do
{
*p32++ = v;
}
while(--len);
}
//--------------------------------------------------------------------
void copy_vline(int x, int y, unsigned len, const color_type& c)
{
int32u v;
int8u* p8 = (int8u*)&v;
p8[Order::R] = (int8u)c.r;
p8[Order::G] = (int8u)c.g;
p8[Order::B] = (int8u)c.b;
p8[Order::A] = (int8u)c.a;
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
*(int32u*)p = v;
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
int alpha = int(cover) * int(c.a);
if(alpha == 255*255)
{
int32u v;
int8u* p8 = (int8u*)&v;
p8[Order::R] = (int8u)c.r;
p8[Order::G] = (int8u)c.g;
p8[Order::B] = (int8u)c.b;
p8[Order::A] = (int8u)c.a;
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
do
{
*p32++ = v;
}
while(--len);
}
else
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
int r = p[Order::R];
int g = p[Order::G];
int b = p[Order::B];
int a = p[Order::A];
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
p += 4;
}
while(--len);
}
}
//--------------------------------------------------------------------
void blend_vline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 2);
int alpha = int(cover) * c.a;
if(alpha == 255*255)
{
int32u v;
int8u* p8 = (int8u*)&v;
p8[Order::R] = (int8u)c.r;
p8[Order::G] = (int8u)c.g;
p8[Order::B] = (int8u)c.b;
p8[Order::A] = (int8u)c.a;
do
{
*(int32u*)p = v;
p += m_rbuf->stride();
}
while(--len);
}
else
{
do
{
int r = p[Order::R];
int g = p[Order::G];
int b = p[Order::B];
int a = p[Order::A];
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
p += m_rbuf->stride();
}
while(--len);
}
}
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
memmove(m_rbuf->row(ydst) + xdst * 4,
(const void*)(from.row(ysrc) + xsrc * 4), len * 4);
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
int alpha = int(*covers++) * c.a;
if(alpha)
{
if(alpha == 255*255)
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p[Order::A] = (int8u)c.a;
}
else
{
int r = p[Order::R];
int g = p[Order::G];
int b = p[Order::B];
int a = p[Order::A];
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
}
}
p += 4;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
int alpha = int(*covers++) * c.a;
if(alpha)
{
if(alpha == 255*255)
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p[Order::A] = (int8u)c.a;
}
else
{
int r = p[Order::R];
int g = p[Order::G];
int b = p[Order::B];
int a = p[Order::A];
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
}
}
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
if(alpha)
{
if(alpha == 255*255)
{
p[Order::R] = (int8u)colors->r;
p[Order::G] = (int8u)colors->g;
p[Order::B] = (int8u)colors->b;
p[Order::A] = (int8u)colors->a;
}
else
{
int r = p[Order::R];
int g = p[Order::G];
int b = p[Order::B];
int a = p[Order::A];
p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16);
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
}
}
p += 4;
++colors;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
if(alpha)
{
if(alpha == 255*255)
{
p[Order::R] = (int8u)colors->r;
p[Order::G] = (int8u)colors->g;
p[Order::B] = (int8u)colors->b;
p[Order::A] = (int8u)colors->a;
}
else
{
int r = p[Order::R];
int g = p[Order::G];
int b = p[Order::B];
int a = p[Order::A];
p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16);
p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16);
p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16);
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
}
}
p += m_rbuf->stride();
++colors;
}
while(--len);
}
private:
rendering_buffer* m_rbuf;
};
typedef pixel_formats_rgba32<order_rgba32> pixfmt_rgba32; //----pixfmt_rgba32
typedef pixel_formats_rgba32<order_argb32> pixfmt_argb32; //----pixfmt_argb32
typedef pixel_formats_rgba32<order_abgr32> pixfmt_abgr32; //----pixfmt_abgr32
typedef pixel_formats_rgba32<order_bgra32> pixfmt_bgra32; //----pixfmt_bgra32
}
#endif
+315
View File
@@ -0,0 +1,315 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_RGBA32_PLAIN_INCLUDED
#define AGG_PIXFMT_RGBA32_PLAIN_INCLUDED
#include <string.h>
#include "agg_basics.h"
#include "agg_color_rgba8.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//===============================================pixel_formats_rgba32_plain
template<class Order> class pixel_formats_rgba32_plain
{
public:
typedef rgba8 color_type;
private:
//--------------------------------------------------------------------
static inline void copy_pix(int8u* p, const color_type& c)
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p[Order::A] = (int8u)c.a;
}
//--------------------------------------------------------------------
static inline void blend_pix(int8u* p, const color_type& c, unsigned alpha)
{
int a = p[Order::A];
int r = p[Order::R] * a;
int g = p[Order::G] * a;
int b = p[Order::B] * a;
a = ((alpha << 8) + (a << 16)) - alpha * a;
p[Order::A] = (int8u)(a >> 16);
p[Order::R] = (int8u)((((((c.r << 8) - r) * alpha) + (r << 16)) / a));
p[Order::G] = (int8u)((((((c.g << 8) - g) * alpha) + (g << 16)) / a));
p[Order::B] = (int8u)((((((c.b << 8) - b) * alpha) + (b << 16)) / a));
}
//--------------------------------------------------------------------
static inline void copy_or_blend_pix(int8u* p, const color_type& c, unsigned cover)
{
unsigned alpha = cover * c.a;
// For testing
//color_type c2 = c;
//c2.a = alpha >> 8;
//copy_or_blend_pix(p, c2);
if(alpha)
{
if(alpha == 255*255)
{
copy_pix(p, c);
}
else
{
blend_pix(p, c, alpha);
}
}
}
//--------------------------------------------------------------------
static inline void copy_or_blend_pix(int8u* p, const color_type& c)
{
unsigned alpha = c.a;
if(alpha)
{
if(alpha == 255)
{
copy_pix(p, c);
}
else
{
int a = p[Order::A];
int r = p[Order::R] * a;
int g = p[Order::G] * a;
int b = p[Order::B] * a;
a = ((alpha + a) << 8) - alpha * a;
p[Order::A] = (int8u)(a >> 8);
p[Order::R] = (int8u)((((((c.r << 8) - r) * alpha) + (r << 8)) / a));
p[Order::G] = (int8u)((((((c.g << 8) - g) * alpha) + (g << 8)) / a));
p[Order::B] = (int8u)((((((c.b << 8) - b) * alpha) + (b << 8)) / a));
}
}
}
public:
//--------------------------------------------------------------------
pixel_formats_rgba32_plain(rendering_buffer& rb)
: m_rbuf(&rb)
{
}
//--------------------------------------------------------------------
unsigned width() const { return m_rbuf->width(); }
unsigned height() const { return m_rbuf->height(); }
//--------------------------------------------------------------------
color_type pixel(int x, int y)
{
int8u* p = m_rbuf->row(y) + (x << 2);
return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
int8u* p = m_rbuf->row(y) + (x << 2);
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p[Order::A] = (int8u)c.a;
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, int8u cover)
{
copy_or_blend_pix(m_rbuf->row(y) + (x << 2), c, cover);
}
//--------------------------------------------------------------------
void copy_hline(int x, int y, unsigned len, const color_type& c)
{
int32u v;
copy_pix((int8u*)&v, c);
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
do
{
*p32++ = v;
}
while(--len);
}
//--------------------------------------------------------------------
void copy_vline(int x, int y, unsigned len, const color_type& c)
{
int32u v;
copy_pix((int8u*)&v, c);
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
*(int32u*)p = v;
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
unsigned alpha = unsigned(cover) * c.a;
if(alpha)
{
if(alpha == 255*255)
{
int32u v;
copy_pix((int8u*)&v, c);
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
do
{
*p32++ = v;
}
while(--len);
}
else
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
blend_pix(p, c, alpha);
p += 4;
}
while(--len);
}
}
}
//--------------------------------------------------------------------
void blend_vline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 2);
unsigned alpha = unsigned(cover) * c.a;
if(alpha)
{
unsigned alpha = unsigned(cover) * c.a;
if(alpha == 255*255)
{
int32u v;
copy_pix((int8u*)&v, c);
do
{
*(int32u*)p = v;
p += m_rbuf->stride();
}
while(--len);
}
else
{
do
{
blend_pix(p, c, alpha);
p += m_rbuf->stride();
}
while(--len);
}
}
}
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
memmove(m_rbuf->row(ydst) + xdst * 4,
(const void*)(from.row(ysrc) + xsrc * 4), len * 4);
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
copy_or_blend_pix(p, c, *covers++);
p += 4;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
copy_or_blend_pix(p, c, *covers++);
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
p += 4;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
p += m_rbuf->stride();
}
while(--len);
}
private:
rendering_buffer* m_rbuf;
};
typedef pixel_formats_rgba32_plain<order_rgba32> pixfmt_rgba32_plain; //----pixfmt_rgba32_plain
typedef pixel_formats_rgba32_plain<order_argb32> pixfmt_argb32_plain; //----pixfmt_argb32_plain
typedef pixel_formats_rgba32_plain<order_abgr32> pixfmt_abgr32_plain; //----pixfmt_abgr32_plain
typedef pixel_formats_rgba32_plain<order_bgra32> pixfmt_bgra32_plain; //----pixfmt_bgra32_plain
}
#endif
+297
View File
@@ -0,0 +1,297 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PIXFMT_RGBA32_PRE_INCLUDED
#define AGG_PIXFMT_RGBA32_PRE_INCLUDED
#include <string.h>
#include "agg_basics.h"
#include "agg_color_rgba8.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//=================================================pixel_formats_rgba32_pre
template<class Order> class pixel_formats_rgba32_pre
{
public:
typedef rgba8 color_type;
private:
//--------------------------------------------------------------------
static inline void copy_pix(int8u* p, const color_type& c)
{
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p[Order::A] = (int8u)c.a;
}
//--------------------------------------------------------------------
static inline void blend_pix(int8u* p, const color_type& c,
unsigned cover, unsigned alpha)
{
p[Order::R] = (int8u)((p[Order::R] * alpha + ((c.r * cover) << 8)) >> 16);
p[Order::G] = (int8u)((p[Order::G] * alpha + ((c.g * cover) << 8)) >> 16);
p[Order::B] = (int8u)((p[Order::B] * alpha + ((c.b * cover) << 8)) >> 16);
p[Order::A] = (int8u)(255 - ((alpha * (255 - p[Order::A])) >> 16));
}
//--------------------------------------------------------------------
static inline void copy_or_blend_pix(int8u* p, const color_type& c, unsigned cover)
{
unsigned alpha = 65535 - cover * c.a;
if(alpha < 65535)
{
if(alpha <= 65535-255*255)
{
copy_pix(p, c);
}
else
{
blend_pix(p, c, cover, alpha);
}
}
}
//--------------------------------------------------------------------
static inline void copy_or_blend_pix(int8u* p, const color_type& c)
{
unsigned alpha = 255 - c.a;
if(alpha < 255)
{
if(alpha == 0)
{
copy_pix(p, c);
}
else
{
p[Order::R] = (int8u)((p[Order::R] * alpha + (c.r << 8)) >> 8);
p[Order::G] = (int8u)((p[Order::G] * alpha + (c.g << 8)) >> 8);
p[Order::B] = (int8u)((p[Order::B] * alpha + (c.b << 8)) >> 8);
p[Order::A] = (int8u)(255 - ((alpha * (255 - p[Order::A])) >> 8));
}
}
}
public:
//--------------------------------------------------------------------
pixel_formats_rgba32_pre(rendering_buffer& rb)
: m_rbuf(&rb)
{
}
//--------------------------------------------------------------------
unsigned width() const { return m_rbuf->width(); }
unsigned height() const { return m_rbuf->height(); }
//--------------------------------------------------------------------
color_type pixel(int x, int y)
{
int8u* p = m_rbuf->row(y) + (x << 2);
return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
int8u* p = m_rbuf->row(y) + (x << 2);
p[Order::R] = (int8u)c.r;
p[Order::G] = (int8u)c.g;
p[Order::B] = (int8u)c.b;
p[Order::A] = (int8u)c.a;
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, int8u cover)
{
copy_or_blend_pix(m_rbuf->row(y) + (x << 2), c, cover);
}
//--------------------------------------------------------------------
void copy_hline(int x, int y, unsigned len, const color_type& c)
{
int32u v;
copy_pix((int8u*)&v, c);
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
do
{
*p32++ = v;
}
while(--len);
}
//--------------------------------------------------------------------
void copy_vline(int x, int y, unsigned len, const color_type& c)
{
int32u v;
copy_pix((int8u*)&v, c);
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
*(int32u*)p = v;
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
unsigned alpha = unsigned(cover) * c.a;
if(alpha == 255*255)
{
int32u v;
copy_pix((int8u*)&v, c);
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
do
{
*p32++ = v;
}
while(--len);
}
else
{
int8u* p = m_rbuf->row(y) + (x << 2);
alpha = 65535 - alpha;
do
{
blend_pix(p, c, cover, alpha);
p += 4;
}
while(--len);
}
}
//--------------------------------------------------------------------
void blend_vline(int x, int y, unsigned len,
const color_type& c, int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 2);
unsigned alpha = unsigned(cover) * c.a;
if(alpha == 255*255)
{
int32u v;
copy_pix((int8u*)&v, c);
do
{
*(int32u*)p = v;
p += m_rbuf->stride();
}
while(--len);
}
else
{
alpha = 65535 - alpha;
do
{
blend_pix(p, c, cover, alpha);
p += m_rbuf->stride();
}
while(--len);
}
}
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
memmove(m_rbuf->row(ydst) + xdst * 4,
(const void*)(from.row(ysrc) + xsrc * 4), len * 4);
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
copy_or_blend_pix(p, c, *covers++);
p += 4;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y, unsigned len,
const color_type& c, const int8u* covers)
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
copy_or_blend_pix(p, c, *covers++);
p += m_rbuf->stride();
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
p += 4;
}
while(--len);
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y, unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
int8u* p = m_rbuf->row(y) + (x << 2);
do
{
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
p += m_rbuf->stride();
}
while(--len);
}
private:
rendering_buffer* m_rbuf;
};
typedef pixel_formats_rgba32_pre<order_rgba32> pixfmt_rgba32_pre; //----pixfmt_rgba32_pre
typedef pixel_formats_rgba32_pre<order_argb32> pixfmt_argb32_pre; //----pixfmt_argb32_pre
typedef pixel_formats_rgba32_pre<order_abgr32> pixfmt_abgr32_pre; //----pixfmt_abgr32_pre
typedef pixel_formats_rgba32_pre<order_bgra32> pixfmt_bgra32_pre; //----pixfmt_bgra32_pre
}
#endif
+135
View File
@@ -0,0 +1,135 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_RASTERIZER_OUTLINE_INCLUDED
#define AGG_RASTERIZER_OUTLINE_INCLUDED
#include "agg_basics.h"
namespace agg
{
//======================================================rasterizer_outline
template<class Renderer> class rasterizer_outline
{
public:
rasterizer_outline(Renderer& ren) : m_ren(&ren), m_start_x(0), m_start_y(0)
{
}
//--------------------------------------------------------------------
void move_to(int x, int y)
{
m_ren->move_to(m_start_x = x, m_start_y = y);
}
//--------------------------------------------------------------------
void line_to(int x, int y)
{
m_ren->line_to(x, y);
}
//--------------------------------------------------------------------
void move_to_d(double x, double y)
{
move_to(m_ren->coord(x), m_ren->coord(y));
}
//--------------------------------------------------------------------
void line_to_d(double x, double y)
{
line_to(m_ren->coord(x), m_ren->coord(y));
}
//--------------------------------------------------------------------
void close()
{
line_to(m_start_x, m_start_y);
}
//--------------------------------------------------------------------
void add_vertex(double x, double y, unsigned cmd)
{
if(is_move_to(cmd))
{
move_to_d(x, y);
}
else
{
if(is_end_poly(cmd))
{
if(is_closed(cmd)) close();
}
else
{
line_to_d(x, y);
}
}
}
//--------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned id=0)
{
double x;
double y;
unsigned cmd;
vs.rewind(id);
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
add_vertex(x, y, cmd);
}
}
//--------------------------------------------------------------------
template<class VertexSource, class ColorStorage, class PathId>
void render_all_paths(VertexSource& vs,
const ColorStorage& colors,
const PathId& id,
unsigned num_paths)
{
for(unsigned i = 0; i < num_paths; i++)
{
m_ren->line_color(colors[i]);
add_path(vs, id[i]);
}
}
//--------------------------------------------------------------------
template<class Ctrl> void render_ctrl(Ctrl& c)
{
unsigned i;
for(i = 0; i < c.num_paths(); i++)
{
m_ren->line_color(c.color(i));
add_path(c, i);
}
}
private:
Renderer* m_ren;
int m_start_x;
int m_start_y;
};
}
#endif
@@ -0,0 +1,513 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_RASTERIZER_OUTLINE_AA_INCLUDED
#define AGG_RASTERIZER_OUTLINE_AA_INCLUDED
#include "agg_basics.h"
#include "agg_line_aa_basics.h"
#include "agg_vertex_sequence.h"
namespace agg
{
//-------------------------------------------------------------------------
inline bool cmp_dist_start(int d) { return d > 0; }
inline bool cmp_dist_end(int d) { return d <= 0; }
//-----------------------------------------------------------line_aa_vertex
// Vertex (x, y) with the distance to the next one. The last vertex has
// the distance between the last and the first points
struct line_aa_vertex
{
int x;
int y;
int len;
line_aa_vertex() {}
line_aa_vertex(int x_, int y_) :
x(x_),
y(y_),
len(0)
{
}
bool operator () (const line_aa_vertex& val)
{
double dx = val.x - x;
double dy = val.y - y;
return (len = int(sqrt(dx * dx + dy * dy))) >
(line_subpixel_size + line_subpixel_size / 2);
}
};
//=======================================================rasterizer_outline_aa
template<class Renderer> class rasterizer_outline_aa
{
private:
//------------------------------------------------------------------------
struct draw_vars
{
unsigned idx;
int x1, y1, x2, y2;
line_parameters curr, next;
int lcurr, lnext;
int xb1, yb1, xb2, yb2;
unsigned flags;
};
void draw(draw_vars& dv, unsigned start, unsigned end);
public:
typedef line_aa_vertex vertex_type;
typedef vertex_sequence<vertex_type, 6> vertex_storage_type;
rasterizer_outline_aa(Renderer& ren) :
m_ren(ren),
m_accurate_join(m_ren.accurate_join_only()),
m_round_cap(false),
m_start_x(0),
m_start_y(0)
{
}
//------------------------------------------------------------------------
void accurate_join(bool v)
{
m_accurate_join = m_ren.accurate_join_only() ? true : v;
}
bool accurate_join() const { return m_accurate_join; }
//------------------------------------------------------------------------
void round_cap(bool v) { m_round_cap = v; }
bool round_cap() const { return m_round_cap; }
//------------------------------------------------------------------------
void move_to(int x, int y)
{
m_src_vertices.modify_last(vertex_type(m_start_x = x, m_start_y = y));
}
//------------------------------------------------------------------------
void line_to(int x, int y)
{
m_src_vertices.add(vertex_type(x, y));
}
//------------------------------------------------------------------------
void move_to_d(double x, double y)
{
move_to(line_coord(x), line_coord(y));
}
//------------------------------------------------------------------------
void line_to_d(double x, double y)
{
line_to(line_coord(x), line_coord(y));
}
//------------------------------------------------------------------------
void render(bool close_polygon);
//------------------------------------------------------------------------
void add_vertex(double x, double y, unsigned cmd)
{
if(is_move_to(cmd))
{
render(false);
move_to_d(x, y);
}
else
{
if(is_end_poly(cmd))
{
render(is_closed(cmd));
if(is_closed(cmd)) move_to(m_start_x, m_start_y);
}
else
{
line_to_d(x, y);
}
}
}
//------------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned id=0)
{
double x;
double y;
unsigned cmd;
vs.rewind(id);
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
add_vertex(x, y, cmd);
}
render(false);
}
//------------------------------------------------------------------------
template<class VertexSource, class ColorStorage, class PathId>
void render_all_paths(VertexSource& vs,
const ColorStorage& colors,
const PathId& id,
unsigned num_paths)
{
for(unsigned i = 0; i < num_paths; i++)
{
m_ren.color(colors[i]);
add_path(vs, id[i]);
}
}
//------------------------------------------------------------------------
template<class Ctrl> void render_ctrl(Ctrl& c)
{
unsigned i;
for(i = 0; i < c.num_paths(); i++)
{
m_ren.color(c.color(i));
add_path(c, i);
}
}
private:
rasterizer_outline_aa(const rasterizer_outline_aa<Renderer>&);
const rasterizer_outline_aa<Renderer>& operator =
(const rasterizer_outline_aa<Renderer>&);
Renderer& m_ren;
vertex_storage_type m_src_vertices;
bool m_accurate_join;
bool m_round_cap;
int m_start_x;
int m_start_y;
};
//----------------------------------------------------------------------------
template<class Renderer>
void rasterizer_outline_aa<Renderer>::draw(draw_vars& dv, unsigned start, unsigned end)
{
unsigned i;
const vertex_storage_type::value_type* v;
for(i = start; i < end; i++)
{
switch(dv.flags)
{
case 0: m_ren.line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break;
case 1: m_ren.line2(dv.curr, dv.xb2, dv.yb2); break;
case 2: m_ren.line1(dv.curr, dv.xb1, dv.yb1); break;
case 3: m_ren.line0(dv.curr); break;
}
dv.x1 = dv.x2;
dv.y1 = dv.y2;
dv.lcurr = dv.lnext;
dv.lnext = m_src_vertices[dv.idx].len;
++dv.idx;
if(dv.idx >= m_src_vertices.size()) dv.idx = 0;
v = &m_src_vertices[dv.idx];
dv.x2 = v->x;
dv.y2 = v->y;
dv.curr = dv.next;
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
dv.xb1 = dv.xb2;
dv.yb1 = dv.yb2;
if(m_accurate_join)
{
dv.flags = 0;
}
else
{
dv.flags >>= 1;
dv.flags |= ((dv.curr.diagonal_quadrant() ==
dv.next.diagonal_quadrant()) << 1);
}
if((dv.flags & 2) == 0)
{
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
}
}
}
//----------------------------------------------------------------------------
template<class Renderer>
void rasterizer_outline_aa<Renderer>::render(bool close_polygon)
{
m_src_vertices.close(close_polygon);
draw_vars dv;
const vertex_storage_type::value_type* v;
int x1;
int y1;
int x2;
int y2;
int lprev;
if(close_polygon)
{
if(m_src_vertices.size() >= 3)
{
dv.idx = 2;
v = &m_src_vertices[m_src_vertices.size() - 1];
x1 = v->x;
y1 = v->y;
lprev = v->len;
v = &m_src_vertices[0];
x2 = v->x;
y2 = v->y;
dv.lcurr = v->len;
line_parameters prev(x1, y1, x2, y2, lprev);
v = &m_src_vertices[1];
dv.x1 = v->x;
dv.y1 = v->y;
dv.lnext = v->len;
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
v = &m_src_vertices[dv.idx];
dv.x2 = v->x;
dv.y2 = v->y;
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
dv.xb1 = 0;
dv.yb1 = 0;
dv.xb2 = 0;
dv.yb2 = 0;
if(m_accurate_join)
{
dv.flags = 0;
}
else
{
dv.flags =
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
}
if((dv.flags & 1) == 0)
{
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
}
if((dv.flags & 2) == 0)
{
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
}
draw(dv, 0, m_src_vertices.size());
}
}
else
{
switch(m_src_vertices.size())
{
case 0:
case 1:
break;
case 2:
{
v = &m_src_vertices[0];
x1 = v->x;
y1 = v->y;
lprev = v->len;
v = &m_src_vertices[1];
x2 = v->x;
y2 = v->y;
line_parameters lp(x1, y1, x2, y2, lprev);
if(m_round_cap)
{
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
}
m_ren.line3(lp,
x1 + (y2 - y1),
y1 - (x2 - x1),
x2 + (y2 - y1),
y2 - (x2 - x1));
if(m_round_cap)
{
m_ren.semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
}
}
break;
case 3:
{
int x3, y3;
int lnext;
v = &m_src_vertices[0];
x1 = v->x;
y1 = v->y;
lprev = v->len;
v = &m_src_vertices[1];
x2 = v->x;
y2 = v->y;
lnext = v->len;
v = &m_src_vertices[2];
x3 = v->x;
y3 = v->y;
line_parameters lp1(x1, y1, x2, y2, lprev);
line_parameters lp2(x2, y2, x3, y3, lnext);
bisectrix(lp1, lp2, &dv.xb1, &dv.yb1);
if(m_round_cap)
{
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
}
m_ren.line3(lp1,
x1 + (y2 - y1),
y1 - (x2 - x1),
dv.xb1,
dv.yb1);
m_ren.line3(lp2,
dv.xb1,
dv.yb1,
x3 + (y3 - y2),
y3 - (x3 - x2));
if(m_round_cap)
{
m_ren.semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2));
}
}
break;
default:
{
dv.idx = 3;
v = &m_src_vertices[0];
x1 = v->x;
y1 = v->y;
lprev = v->len;
v = &m_src_vertices[1];
x2 = v->x;
y2 = v->y;
dv.lcurr = v->len;
line_parameters prev(x1, y1, x2, y2, lprev);
v = &m_src_vertices[2];
dv.x1 = v->x;
dv.y1 = v->y;
dv.lnext = v->len;
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
v = &m_src_vertices[dv.idx];
dv.x2 = v->x;
dv.y2 = v->y;
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
dv.xb1 = 0;
dv.yb1 = 0;
dv.xb2 = 0;
dv.yb2 = 0;
if(m_accurate_join)
{
dv.flags = 0;
}
else
{
dv.flags =
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
}
if((dv.flags & 1) == 0)
{
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
m_ren.line3(prev,
x1 + (y2 - y1),
y1 - (x2 - x1),
dv.xb1,
dv.yb1);
}
else
{
m_ren.line1(prev,
x1 + (y2 - y1),
y1 - (x2 - x1));
}
if(m_round_cap)
{
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
}
if((dv.flags & 2) == 0)
{
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
}
draw(dv, 1, m_src_vertices.size() - 2);
if((dv.flags & 1) == 0)
{
m_ren.line3(dv.curr,
dv.xb1,
dv.yb1,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}
else
{
m_ren.line2(dv.curr,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}
if(m_round_cap)
{
m_ren.semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}
}
break;
}
}
m_src_vertices.remove_all();
}
}
#endif
@@ -0,0 +1,771 @@
//----------------------------------------------------------------------------
// 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.
//
// The author gratefully acknowleges the support of David Turner,
// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
// libray - in producing this work. See http://www.freetype.org for details.
//
//----------------------------------------------------------------------------
// Contact: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Class rasterizer_scanline_aa
//
//
//----------------------------------------------------------------------------
#ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED
#define AGG_RASTERIZER_SCANLINE_AA_INCLUDED
#include <string.h>
#include <math.h>
#include "agg_basics.h"
#include "agg_math.h"
#include "agg_gamma_functions.h"
#include "agg_clip_liang_barsky.h"
#include "agg_render_scanlines.h"
namespace agg
{
//------------------------------------------------------------------------
// These constants determine the subpixel accuracy, to be more precise,
// the number of bits of the fractional part of the coordinates.
// The possible coordinate capacity in bits can be calculated by formula:
// sizeof(int) * 8 - poly_base_shift * 2, i.e, for 32-bit integers and
// 8-bits fractional part the capacity is 16 bits or [-32768...32767].
enum
{
poly_base_shift = 8, //----poly_base_shift
poly_base_size = 1 << poly_base_shift, //----poly_base_size
poly_base_mask = poly_base_size - 1 //----poly_base_mask
};
//--------------------------------------------------------------poly_coord
inline int poly_coord(double c)
{
return int(c * poly_base_size);
}
//-----------------------------------------------------------------cell_aa
// A pixel cell. There're no constructors defined and it was done
// intentionally in order to avoid extra overhead when allocating an
// array of cells.
struct cell_aa
{
int16 x;
int16 y;
int packed_coord;
int cover;
int area;
void set(int x, int y, int c, int a);
void set_coord(int x, int y);
void set_cover(int c, int a);
void add_cover(int c, int a);
};
//--------------------------------------------------------------outline_aa
// An internal class that implements the main rasterization algorithm.
// Used in the rasterizer. Should not be used direcly.
class outline_aa
{
enum
{
cell_block_shift = 12,
cell_block_size = 1 << cell_block_shift,
cell_block_mask = cell_block_size - 1,
cell_block_pool = 256,
cell_block_limit = 1024
};
public:
~outline_aa();
outline_aa();
void reset();
void move_to(int x, int y);
void line_to(int x, int y);
int min_x() const { return m_min_x; }
int min_y() const { return m_min_y; }
int max_x() const { return m_max_x; }
int max_y() const { return m_max_y; }
const cell_aa* const* cells();
unsigned num_cells() { cells(); return m_num_cells; }
bool sorted() const { return m_sorted; }
private:
outline_aa(const outline_aa&);
const outline_aa& operator = (const outline_aa&);
void set_cur_cell(int x, int y);
void add_cur_cell();
void sort_cells();
void render_hline(int ey, int x1, int y1, int x2, int y2);
void render_line(int x1, int y1, int x2, int y2);
void allocate_block();
static void qsort_cells(cell_aa** start, unsigned num);
private:
unsigned m_num_blocks;
unsigned m_max_blocks;
unsigned m_cur_block;
unsigned m_num_cells;
cell_aa** m_cells;
cell_aa* m_cur_cell_ptr;
cell_aa** m_sorted_cells;
unsigned m_sorted_size;
cell_aa m_cur_cell;
int m_cur_x;
int m_cur_y;
int m_min_x;
int m_min_y;
int m_max_x;
int m_max_y;
bool m_sorted;
};
//----------------------------------------------------------filling_rule_e
enum filling_rule_e
{
fill_non_zero,
fill_even_odd
};
//----------------------------------------------------------clipping_flags
// Determine the clipping code of the vertex according to the
// Cyrus-Beck line clipping algorithm
//
// | |
// 0110 | 0010 | 0011
// | |
// -------+--------+-------- clip_box.y2
// | |
// 0100 | 0000 | 0001
// | |
// -------+--------+-------- clip_box.y1
// | |
// 1100 | 1000 | 1001
// | |
// clip_box.x1 clip_box.x2
//
//
inline unsigned clipping_flags(int x, int y, const rect& clip_box)
{
return (x > clip_box.x2) |
((y > clip_box.y2) << 1) |
((x < clip_box.x1) << 2) |
((y < clip_box.y1) << 3);
}
//==================================================rasterizer_scanline_aa
// Polygon rasterizer that is used to render filled polygons with
// high-quality Anti-Aliasing. Internally, by default, the class uses
// integer coordinates in format 24.8, i.e. 24 bits for integer part
// and 8 bits for fractional - see poly_base_shift. This class can be
// used in the following way:
//
// 1. filling_rule(filling_rule_e ft) - optional.
//
// 2. gamma() - optional.
//
// 3. reset()
//
// 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create
// more than one contour, but each contour must consist of at least 3
// vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3);
// is the absolute minimum of vertices that define a triangle.
// The algorithm does not check either the number of vertices nor
// coincidence of their coordinates, but in the worst case it just
// won't draw anything.
// The orger of the vertices (clockwise or counterclockwise)
// is important when using the non-zero filling rule (fill_non_zero).
// In this case the vertex order of all the contours must be the same
// if you want your intersecting polygons to be without "holes".
// You actually can use different vertices order. If the contours do not
// intersect each other the order is not important anyway. If they do,
// contours with the same vertex order will be rendered without "holes"
// while the intersecting contours with different orders will have "holes".
//
// filling_rule() and gamma() can be called anytime before "sweeping".
//------------------------------------------------------------------------
template<unsigned AA_Shift=8> class rasterizer_scanline_aa
{
enum status
{
status_initial,
status_line_to,
status_closed
};
struct iterator
{
const cell_aa* const* cells;
int cover;
int last_y;
};
public:
enum
{
aa_shift = AA_Shift,
aa_num = 1 << aa_shift,
aa_mask = aa_num - 1,
aa_2num = aa_num * 2,
aa_2mask = aa_2num - 1
};
//--------------------------------------------------------------------
rasterizer_scanline_aa() :
m_filling_rule(fill_non_zero),
m_clipped_start_x(0),
m_clipped_start_y(0),
m_start_x(0),
m_start_y(0),
m_prev_x(0),
m_prev_y(0),
m_prev_flags(0),
m_status(status_initial),
m_clipping(false)
{
int i;
for(i = 0; i < aa_num; i++) m_gamma[i] = i;
}
//--------------------------------------------------------------------
template<class GammaF>
rasterizer_scanline_aa(const GammaF& gamma_function) :
m_filling_rule(fill_non_zero),
m_clipped_start_x(0),
m_clipped_start_y(0),
m_start_x(0),
m_start_y(0),
m_prev_x(0),
m_prev_y(0),
m_prev_flags(0),
m_status(status_initial),
m_clipping(false)
{
gamma(gamma_function);
}
//--------------------------------------------------------------------
void reset();
void filling_rule(filling_rule_e filling_rule);
void clip_box(double x1, double y1, double x2, double y2);
void reset_clipping();
//--------------------------------------------------------------------
template<class GammaF> void gamma(const GammaF& gamma_function)
{
int i;
for(i = 0; i < aa_num; i++)
{
m_gamma[i] = int(floor(gamma_function(double(i) / aa_mask) * aa_mask + 0.5));
}
}
//--------------------------------------------------------------------
unsigned apply_gamma(unsigned cover) const
{
return m_gamma[cover];
}
//--------------------------------------------------------------------
void add_vertex(double x, double y, unsigned cmd);
void move_to(int x, int y);
void line_to(int x, int y);
void close_polygon();
void move_to_d(double x, double y);
void line_to_d(double x, double y);
//--------------------------------------------------------------------
int min_x() const { return m_outline.min_x(); }
int min_y() const { return m_outline.min_y(); }
int max_x() const { return m_outline.max_x(); }
int max_y() const { return m_outline.max_y(); }
//--------------------------------------------------------------------
unsigned calculate_alpha(int area) const
{
int cover = area >> (poly_base_shift*2 + 1 - aa_shift);
if(cover < 0) cover = -cover;
if(m_filling_rule == fill_even_odd)
{
cover &= aa_2mask;
if(cover > aa_num)
{
cover = aa_2num - cover;
}
}
if(cover > aa_mask) cover = aa_mask;
return m_gamma[cover];
}
//--------------------------------------------------------------------
void sort()
{
m_outline.cells();
}
//--------------------------------------------------------------------
bool rewind_scanlines()
{
close_polygon();
m_iterator.cells = m_outline.cells();
if(m_outline.num_cells() == 0)
{
return false;
}
m_iterator.cover = 0;
m_iterator.last_y = (*m_iterator.cells)->y;
return true;
}
//--------------------------------------------------------------------
template<class Scanline> bool sweep_scanline(Scanline& sl)
{
sl.reset_spans();
for(;;)
{
const cell_aa* cur_cell = *m_iterator.cells;
if(cur_cell == 0) return false;
++m_iterator.cells;
m_iterator.last_y = cur_cell->y;
for(;;)
{
int coord = cur_cell->packed_coord;
int area = cur_cell->area;
int last_x = cur_cell->x;
m_iterator.cover += cur_cell->cover;
//accumulate all cells with the same coordinates
for(; (cur_cell = *m_iterator.cells) != 0; ++m_iterator.cells)
{
if(cur_cell->packed_coord != coord) break;
area += cur_cell->area;
m_iterator.cover += cur_cell->cover;
}
int alpha;
if(cur_cell == 0 || cur_cell->y != m_iterator.last_y)
{
if(area)
{
alpha = calculate_alpha((m_iterator.cover << (poly_base_shift + 1)) - area);
if(alpha)
{
sl.add_cell(last_x, alpha);
}
++last_x;
}
break;
}
++m_iterator.cells;
if(area)
{
alpha = calculate_alpha((m_iterator.cover << (poly_base_shift + 1)) - area);
if(alpha)
{
sl.add_cell(last_x, alpha);
}
++last_x;
}
if(cur_cell->x > last_x)
{
alpha = calculate_alpha(m_iterator.cover << (poly_base_shift + 1));
if(alpha)
{
sl.add_span(last_x, cur_cell->x - last_x, alpha);
}
}
}
if(sl.num_spans())
{
sl.finalize(m_iterator.last_y);
break;
}
}
return true;
}
//--------------------------------------------------------------------
bool hit_test(int tx, int ty);
//--------------------------------------------------------------------
void add_xy(const double* x, const double* y, unsigned n)
{
if(n > 2)
{
move_to_d(*x++, *y++);
--n;
do
{
line_to_d(*x++, *y++);
}
while(--n);
}
}
//-------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned id=0)
{
double x;
double y;
unsigned cmd;
vs.rewind(id);
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
add_vertex(x, y, cmd);
}
}
private:
//--------------------------------------------------------------------
// Disable copying
rasterizer_scanline_aa(const rasterizer_scanline_aa<AA_Shift>&);
const rasterizer_scanline_aa<AA_Shift>&
operator = (const rasterizer_scanline_aa<AA_Shift>&);
//--------------------------------------------------------------------
void move_to_no_clip(int x, int y);
void line_to_no_clip(int x, int y);
void close_polygon_no_clip();
void clip_segment(int x, int y);
private:
outline_aa m_outline;
int m_gamma[aa_num];
filling_rule_e m_filling_rule;
int m_clipped_start_x;
int m_clipped_start_y;
int m_start_x;
int m_start_y;
int m_prev_x;
int m_prev_y;
unsigned m_prev_flags;
unsigned m_status;
rect m_clip_box;
bool m_clipping;
iterator m_iterator;
};
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::reset()
{
m_outline.reset();
m_status = status_initial;
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::filling_rule(filling_rule_e filling_rule)
{
m_filling_rule = filling_rule;
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::clip_box(double x1, double y1, double x2, double y2)
{
reset();
m_clip_box = rect(poly_coord(x1), poly_coord(y1),
poly_coord(x2), poly_coord(y2));
m_clip_box.normalize();
m_clipping = true;
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::reset_clipping()
{
reset();
m_clipping = false;
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::move_to_no_clip(int x, int y)
{
if(m_status == status_line_to)
{
close_polygon_no_clip();
}
m_outline.move_to(x, y);
m_clipped_start_x = x;
m_clipped_start_y = y;
m_status = status_line_to;
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::line_to_no_clip(int x, int y)
{
if(m_status != status_initial)
{
m_outline.line_to(x, y);
m_status = status_line_to;
}
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::close_polygon_no_clip()
{
if(m_status == status_line_to)
{
m_outline.line_to(m_clipped_start_x, m_clipped_start_y);
m_status = status_closed;
}
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::clip_segment(int x, int y)
{
unsigned flags = clipping_flags(x, y, m_clip_box);
if(m_prev_flags == flags)
{
if(flags == 0)
{
if(m_status == status_initial)
{
move_to_no_clip(x, y);
}
else
{
line_to_no_clip(x, y);
}
}
}
else
{
int cx[4];
int cy[4];
unsigned n = clip_liang_barsky(m_prev_x, m_prev_y,
x, y,
m_clip_box,
cx, cy);
const int* px = cx;
const int* py = cy;
while(n--)
{
if(m_status == status_initial)
{
move_to_no_clip(*px++, *py++);
}
else
{
line_to_no_clip(*px++, *py++);
}
}
}
m_prev_flags = flags;
m_prev_x = x;
m_prev_y = y;
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::add_vertex(double x, double y, unsigned cmd)
{
if(is_close(cmd))
{
close_polygon();
}
else
{
if(is_move_to(cmd))
{
move_to(poly_coord(x), poly_coord(y));
}
else
{
if(is_vertex(cmd))
{
line_to(poly_coord(x), poly_coord(y));
}
}
}
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::move_to(int x, int y)
{
if(m_clipping)
{
if(m_outline.sorted())
{
reset();
}
if(m_status == status_line_to)
{
close_polygon();
}
m_prev_x = m_start_x = x;
m_prev_y = m_start_y = y;
m_status = status_initial;
m_prev_flags = clipping_flags(x, y, m_clip_box);
if(m_prev_flags == 0)
{
move_to_no_clip(x, y);
}
}
else
{
move_to_no_clip(x, y);
}
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::line_to(int x, int y)
{
if(m_clipping)
{
clip_segment(x, y);
}
else
{
line_to_no_clip(x, y);
}
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::close_polygon()
{
if(m_clipping)
{
clip_segment(m_start_x, m_start_y);
}
close_polygon_no_clip();
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::move_to_d(double x, double y)
{
move_to(poly_coord(x), poly_coord(y));
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
void rasterizer_scanline_aa<AA_Shift>::line_to_d(double x, double y)
{
line_to(poly_coord(x), poly_coord(y));
}
//------------------------------------------------------------------------
template<unsigned AA_Shift>
bool rasterizer_scanline_aa<AA_Shift>::hit_test(int tx, int ty)
{
close_polygon();
const cell_aa* const* cells = m_outline.cells();
if(m_outline.num_cells() == 0) return false;
int cover = 0;
const cell_aa* cur_cell = *cells++;
for(;;)
{
int alpha;
int coord = cur_cell->packed_coord;
int x = cur_cell->x;
int y = cur_cell->y;
if(y > ty) return false;
int area = cur_cell->area;
cover += cur_cell->cover;
while((cur_cell = *cells++) != 0)
{
if(cur_cell->packed_coord != coord) break;
area += cur_cell->area;
cover += cur_cell->cover;
}
if(area)
{
alpha = calculate_alpha((cover << (poly_base_shift + 1)) - area);
if(alpha)
{
if(tx == x && ty == y) return true;
}
x++;
}
if(!cur_cell) break;
if(cur_cell->x > x)
{
alpha = calculate_alpha(cover << (poly_base_shift + 1));
if(alpha)
{
if(ty == y && tx >= x && tx <= cur_cell->x) return true;
}
}
}
return false;
}
}
#endif
+66
View File
@@ -0,0 +1,66 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_RENDER_SCANLINES_INCLUDED
#define AGG_RENDER_SCANLINES_INCLUDED
#include "agg_basics.h"
namespace agg
{
//========================================================render_scanlines
template<class Rasterizer, class Scanline, class Renderer>
void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren)
{
if(ras.rewind_scanlines())
{
sl.reset(ras.min_x(), ras.max_x());
ren.prepare(unsigned(ras.max_x() - ras.min_x() + 2));
while(ras.sweep_scanline(sl))
{
ren.render(sl);
}
}
}
//========================================================render_all_paths
template<class Rasterizer, class Scanline, class Renderer,
class VertexSource, class ColorStorage, class PathId>
void render_all_paths(Rasterizer& ras,
Scanline& sl,
Renderer& r,
VertexSource& vs,
const ColorStorage& as,
const PathId& id,
unsigned num_paths)
{
for(unsigned i = 0; i < num_paths; i++)
{
ras.reset();
ras.add_path(vs, id[i]);
r.color(as[i]);
render_scanlines(ras, sl, r);
}
}
}
#endif
+420
View File
@@ -0,0 +1,420 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// class renderer_base
//
//----------------------------------------------------------------------------
#ifndef AGG_RENDERER_BASE_INCLUDED
#define AGG_RENDERER_BASE_INCLUDED
#include "agg_basics.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//-----------------------------------------------------------renderer_base
template<class PixelFormat> class renderer_base
{
public:
typedef PixelFormat pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
//--------------------------------------------------------------------
renderer_base(pixfmt_type& ren) :
m_ren(&ren),
m_clip_box(0, 0, ren.width() - 1, ren.height() - 1)
{
}
//--------------------------------------------------------------------
const pixfmt_type& ren() const { return *m_ren; }
pixfmt_type& ren() { return *m_ren; }
//--------------------------------------------------------------------
unsigned width() const { return m_ren->width(); }
unsigned height() const { return m_ren->height(); }
//--------------------------------------------------------------------
bool clip_box(int x1, int y1, int x2, int y2)
{
rect cb(x1, y1, x2, y2);
cb.normalize();
if(cb.clip(rect(0, 0, width() - 1, height() - 1)))
{
m_clip_box = cb;
return true;
}
m_clip_box.x1 = 1;
m_clip_box.y1 = 1;
m_clip_box.x2 = 0;
m_clip_box.y2 = 0;
return false;
}
//--------------------------------------------------------------------
void reset_clipping(bool visibility)
{
if(visibility)
{
m_clip_box.x1 = 0;
m_clip_box.y1 = 0;
m_clip_box.x2 = width() - 1;
m_clip_box.y2 = height() - 1;
}
else
{
m_clip_box.x1 = 1;
m_clip_box.y1 = 1;
m_clip_box.x2 = 0;
m_clip_box.y2 = 0;
}
}
//--------------------------------------------------------------------
void clip_box_naked(int x1, int y1, int x2, int y2)
{
m_clip_box.x1 = x1;
m_clip_box.y1 = y1;
m_clip_box.x2 = x2;
m_clip_box.y2 = y2;
}
//--------------------------------------------------------------------
bool inbox(int x, int y) const
{
return x >= m_clip_box.x1 && y >= m_clip_box.y1 &&
x <= m_clip_box.x2 && y <= m_clip_box.y2;
}
//--------------------------------------------------------------------
void first_clip_box() {}
bool next_clip_box() { return false; }
//--------------------------------------------------------------------
const rect& clip_box() const { return m_clip_box; }
int xmin() const { return m_clip_box.x1; }
int ymin() const { return m_clip_box.y1; }
int xmax() const { return m_clip_box.x2; }
int ymax() const { return m_clip_box.y2; }
//--------------------------------------------------------------------
const rect& bounding_clip_box() const { return m_clip_box; }
int bounding_xmin() const { return m_clip_box.x1; }
int bounding_ymin() const { return m_clip_box.y1; }
int bounding_xmax() const { return m_clip_box.x2; }
int bounding_ymax() const { return m_clip_box.y2; }
//--------------------------------------------------------------------
void clear(const color_type& c)
{
unsigned y;
if(width())
{
for(y = 0; y < height(); y++)
{
m_ren->copy_hline(0, y, width(), c);
}
}
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
if(inbox(x, y))
{
m_ren->copy_pixel(x, y, c);
}
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
{
if(inbox(x, y))
{
m_ren->blend_pixel(x, y, c, cover);
}
}
//--------------------------------------------------------------------
color_type pixel(int x, int y) const
{
return inbox(x, y) ?
m_ren->pixel(x, y) :
color_type::no_color();
}
//--------------------------------------------------------------------
void copy_hline(int x1, int y, int x2, const color_type& c)
{
if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
if(y > ymax()) return;
if(y < ymin()) return;
if(x1 > xmax()) return;
if(x2 < xmin()) return;
if(x1 < xmin()) x1 = xmin();
if(x2 > xmax()) x2 = xmax();
m_ren->copy_hline(x1, y, x2 - x1 + 1, c);
}
//--------------------------------------------------------------------
void copy_vline(int x, int y1, int y2, const color_type& c)
{
if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
if(x > xmax()) return;
if(x < xmin()) return;
if(y1 > ymax()) return;
if(y2 < ymin()) return;
if(y1 < ymin()) y1 = ymin();
if(y2 > ymax()) y2 = ymax();
m_ren->copy_vline(x, y1, y2 - y1 + 1, c);
}
//--------------------------------------------------------------------
void blend_hline(int x1, int y, int x2,
const color_type& c, cover_type cover)
{
if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
if(y > ymax()) return;
if(y < ymin()) return;
if(x1 > xmax()) return;
if(x2 < xmin()) return;
if(x1 < xmin()) x1 = xmin();
if(x2 > xmax()) x2 = xmax();
m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover);
}
//--------------------------------------------------------------------
void blend_vline(int x, int y1, int y2,
const color_type& c, cover_type cover)
{
if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
if(x > xmax()) return;
if(x < xmin()) return;
if(y1 > ymax()) return;
if(y2 < ymin()) return;
if(y1 < ymin()) y1 = ymin();
if(y2 > ymax()) y2 = ymax();
m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover);
}
//--------------------------------------------------------------------
void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
{
rect rc(x1, y1, x2, y2);
rc.normalize();
if(rc.clip(clip_box()))
{
int y;
for(y = rc.y1; y <= rc.y2; y++)
{
m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c);
}
}
}
//--------------------------------------------------------------------
void blend_bar(int x1, int y1, int x2, int y2,
const color_type& c, cover_type cover)
{
rect rc(x1, y1, x2, y2);
rc.normalize();
if(rc.clip(clip_box()))
{
int y;
for(y = rc.y1; y <= rc.y2; y++)
{
m_ren->blend_hline(rc.x1,
y,
unsigned(rc.x2 - rc.x1 + 1),
c,
cover);
}
}
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, int len,
const color_type& c,
const cover_type* covers)
{
if(y > ymax()) return;
if(y < ymin()) return;
if(x < xmin())
{
len -= xmin() - x;
if(len <= 0) return;
covers += xmin() - x;
x = xmin();
}
if(x + len > xmax())
{
len = xmax() - x + 1;
if(len <= 0) return;
}
m_ren->blend_solid_hspan(x, y, len, c, covers);
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y, int len,
const color_type& c,
const cover_type* covers)
{
if(x > xmax()) return;
if(x < xmin()) return;
if(y < ymin())
{
len -= ymin() - y;
if(len <= 0) return;
covers += ymin() - y;
y = ymin();
}
if(y + len > ymax())
{
len = ymax() - y + 1;
if(len <= 0) return;
}
m_ren->blend_solid_vspan(x, y, len, c, covers);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y, int len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
if(y > ymax()) return;
if(y < ymin()) return;
if(x < xmin())
{
int d = xmin() - x;
len -= d;
if(len <= 0) return;
if(covers) covers += d;
colors += d;
x = xmin();
}
if(x + len > xmax())
{
len = xmax() - x + 1;
if(len <= 0) return;
}
m_ren->blend_color_hspan(x, y, len, colors, covers, cover);
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y, int len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
if(x > xmax()) return;
if(x < xmin()) return;
if(y < ymin())
{
int d = ymin() - y;
len -= d;
if(len <= 0) return;
if(covers) covers += d;
colors += d;
y = ymin();
}
if(y + len > ymax())
{
len = ymax() - y + 1;
if(len <= 0) return;
}
m_ren->blend_color_vspan(x, y, len, colors, covers, cover);
}
//--------------------------------------------------------------------
void blend_color_hspan_no_clip(int x, int y, int len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
m_ren->blend_color_hspan(x, y, len, colors, covers, cover);
}
//--------------------------------------------------------------------
void blend_color_vspan_no_clip(int x, int y, int len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
m_ren->blend_color_vspan(x, y, len, colors, covers, cover);
}
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
const rect* rc=0,
int x_to=0,
int y_to=0)
{
rect tmp_rect(0, 0, from.width(), from.height());
if(rc == 0)
{
rc = &tmp_rect;
}
rect rc2(*rc);
rc2.normalize();
if(rc2.clip(rect(0, 0, from.width() - 1, from.height() - 1)))
{
rect rc3(x_to + rc2.x1 - rc->x1,
y_to + rc2.y1 - rc->y1,
x_to + rc2.x2 - rc->x1,
y_to + rc2.y2 - rc->y1);
rc3.normalize();
if(rc3.clip(clip_box()))
{
while(rc3.y1 <= rc3.y2)
{
m_ren->copy_from(from,
rc3.x1, rc3.y1,
rc2.x1, rc2.y1,
rc3.x2 - rc3.x1 + 1);
++rc2.y1;
++rc3.y1;
}
}
}
}
private:
pixfmt_type* m_ren;
rect m_clip_box;
};
}
#endif
+707
View File
@@ -0,0 +1,707 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// class renderer_markers
//
//----------------------------------------------------------------------------
#ifndef AGG_RENDERER_MARKERS_INCLUDED
#define AGG_RENDERER_MARKERS_INCLUDED
#include "agg_basics.h"
#include "agg_renderer_primitives.h"
namespace agg
{
//---------------------------------------------------------------marker_e
enum marker_e
{
marker_square,
marker_diamond,
marker_circle,
marker_crossed_circle,
marker_semiellipse_left,
marker_semiellipse_right,
marker_semiellipse_up,
marker_semiellipse_down,
marker_triangle_left,
marker_triangle_right,
marker_triangle_up,
marker_triangle_down,
marker_four_rays,
marker_cross,
marker_x,
marker_dash,
marker_dot,
marker_pixel,
end_of_markers
};
//--------------------------------------------------------renderer_markers
template<class BaseRenderer> class renderer_markers :
public renderer_primitives<BaseRenderer>
{
public:
typedef renderer_primitives<BaseRenderer> base_type;
typedef BaseRenderer base_ren_type;
typedef typename base_ren_type::color_type color_type;
//--------------------------------------------------------------------
renderer_markers(base_ren_type& rbuf) :
base_type(rbuf)
{
}
//--------------------------------------------------------------------
bool visible(int x, int y, int r) const
{
rect rc(x-r, y-r, x+y, y+r);
return rc.clip(base_type::ren().bounding_clip_box());
}
//--------------------------------------------------------------------
void square(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r) base_type::outlined_rectangle(x-r, y-r, x+r, y+r);
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
//--------------------------------------------------------------------
void diamond(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r)
{
int dy = -r;
int dx = 0;
do
{
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
if(dx)
{
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
}
++dy;
++dx;
}
while(dy <= 0);
}
else
{
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
}
//--------------------------------------------------------------------
void circle(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r) base_type::outlined_ellipse(x, y, r, r);
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
//--------------------------------------------------------------------
void crossed_circle(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r)
{
base_type::outlined_ellipse(x, y, r, r);
int r6 = r + (r >> 1);
if(r <= 2) r6++;
r >>= 1;
base_type::ren().blend_hline(x-r6, y, x-r, base_type::line_color(), cover_full);
base_type::ren().blend_hline(x+r, y, x+r6, base_type::line_color(), cover_full);
base_type::ren().blend_vline(x, y-r6, y-r, base_type::line_color(), cover_full);
base_type::ren().blend_vline(x, y+r, y+r6, base_type::line_color(), cover_full);
}
else
{
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
}
//------------------------------------------------------------------------
void semiellipse_left(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r)
{
int r8 = r * 4 / 5;
int dy = -r;
int dx = 0;
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
do
{
dx += ei.dx();
dy += ei.dy();
base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
if(ei.dy() && dx)
{
base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
}
++ei;
}
while(dy < r8);
base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full);
}
else
{
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
}
//--------------------------------------------------------------------
void semiellipse_right(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r)
{
int r8 = r * 4 / 5;
int dy = -r;
int dx = 0;
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
do
{
dx += ei.dx();
dy += ei.dy();
base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
if(ei.dy() && dx)
{
base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
}
++ei;
}
while(dy < r8);
base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full);
}
else
{
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
}
//--------------------------------------------------------------------
void semiellipse_up(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r)
{
int r8 = r * 4 / 5;
int dy = -r;
int dx = 0;
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
do
{
dx += ei.dx();
dy += ei.dy();
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
if(ei.dy() && dx)
{
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
}
++ei;
}
while(dy < r8);
base_type::ren().blend_hline(x-dx, y-dy-1, x+dx, base_type::line_color(), cover_full);
}
else
{
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
}
//--------------------------------------------------------------------
void semiellipse_down(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r)
{
int r8 = r * 4 / 5;
int dy = -r;
int dx = 0;
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
do
{
dx += ei.dx();
dy += ei.dy();
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
if(ei.dy() && dx)
{
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
}
++ei;
}
while(dy < r8);
base_type::ren().blend_hline(x-dx, y+dy+1, x+dx, base_type::line_color(), cover_full);
}
else
{
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
}
//--------------------------------------------------------------------
void triangle_left(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r)
{
int dy = -r;
int dx = 0;
int flip = 0;
int r6 = r * 3 / 5;
do
{
base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
if(dx)
{
base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
}
++dy;
dx += flip;
flip ^= 1;
}
while(dy < r6);
base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full);
}
else
{
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
}
//--------------------------------------------------------------------
void triangle_right(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r)
{
int dy = -r;
int dx = 0;
int flip = 0;
int r6 = r * 3 / 5;
do
{
base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
if(dx)
{
base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
}
++dy;
dx += flip;
flip ^= 1;
}
while(dy < r6);
base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full);
}
else
{
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
}
//--------------------------------------------------------------------
void triangle_up(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r)
{
int dy = -r;
int dx = 0;
int flip = 0;
int r6 = r * 3 / 5;
do
{
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
if(dx)
{
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
}
++dy;
dx += flip;
flip ^= 1;
}
while(dy < r6);
base_type::ren().blend_hline(x-dx, y-dy, x+dx, base_type::line_color(), cover_full);
}
else
{
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
}
//--------------------------------------------------------------------
void triangle_down(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r)
{
int dy = -r;
int dx = 0;
int flip = 0;
int r6 = r * 3 / 5;
do
{
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
if(dx)
{
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
}
++dy;
dx += flip;
flip ^= 1;
}
while(dy < r6);
base_type::ren().blend_hline(x-dx, y+dy, x+dx, base_type::line_color(), cover_full);
}
else
{
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
}
//--------------------------------------------------------------------
void four_rays(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r)
{
int dy = -r;
int dx = 0;
int flip = 0;
int r3 = -(r / 3);
do
{
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
if(dx)
{
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
}
++dy;
dx += flip;
flip ^= 1;
}
while(dy <= r3);
base_type::solid_rectangle(x+r3+1, y+r3+1, x-r3-1, y-r3-1);
}
else
{
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
}
//--------------------------------------------------------------------
void cross(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r)
{
base_type::ren().blend_vline(x, y-r, y+r, base_type::line_color(), cover_full);
base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full);
}
else
{
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
}
//--------------------------------------------------------------------
void xing(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r)
{
int dy = -r * 7 / 10;
do
{
base_type::ren().blend_pixel(x + dy, y + dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x - dy, y + dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x + dy, y - dy, base_type::line_color(), cover_full);
base_type::ren().blend_pixel(x - dy, y - dy, base_type::line_color(), cover_full);
++dy;
}
while(dy < 0);
}
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
//--------------------------------------------------------------------
void dash(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r) base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full);
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
//--------------------------------------------------------------------
void dot(int x, int y, int r)
{
if(visible(x, y, r))
{
if(r) base_type::solid_ellipse(x, y, r, r);
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
}
//--------------------------------------------------------------------
void pixel(int x, int y, int)
{
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
}
//--------------------------------------------------------------------
void marker(int x, int y, int r, marker_e type)
{
switch(type)
{
case marker_square: square(x, y, r); break;
case marker_diamond: diamond(x, y, r); break;
case marker_circle: circle(x, y, r); break;
case marker_crossed_circle: crossed_circle(x, y, r); break;
case marker_semiellipse_left: semiellipse_left(x, y, r); break;
case marker_semiellipse_right: semiellipse_right(x, y, r); break;
case marker_semiellipse_up: semiellipse_up(x, y, r); break;
case marker_semiellipse_down: semiellipse_down(x, y, r); break;
case marker_triangle_left: triangle_left(x, y, r); break;
case marker_triangle_right: triangle_right(x, y, r); break;
case marker_triangle_up: triangle_up(x, y, r); break;
case marker_triangle_down: triangle_down(x, y, r); break;
case marker_four_rays: four_rays(x, y, r); break;
case marker_cross: cross(x, y, r); break;
case marker_x: xing(x, y, r); break;
case marker_dash: dash(x, y, r); break;
case marker_dot: dot(x, y, r); break;
case marker_pixel: pixel(x, y, r); break;
}
}
//--------------------------------------------------------------------
template<class T>
void markers(int n, const T* x, const T* y, T r, marker_e type)
{
if(n <= 0) return;
if(r == 0)
{
do
{
base_type::ren().blend_pixel(int(*x), int(*y), base_type::fill_color(), cover_full);
++x;
++y;
}
while(--n);
return;
}
switch(type)
{
case marker_square: do { square (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_diamond: do { diamond (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_circle: do { circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_four_rays: do { four_rays (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_cross: do { cross (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_x: do { xing (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_dash: do { dash (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_dot: do { dot (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
case marker_pixel: do { pixel (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
}
}
//--------------------------------------------------------------------
template<class T>
void markers(int n, const T* x, const T* y, const T* r, marker_e type)
{
if(n <= 0) return;
switch(type)
{
case marker_square: do { square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_diamond: do { diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_circle: do { circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_four_rays: do { four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_cross: do { cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_x: do { xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_dash: do { dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_dot: do { dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
case marker_pixel: do { pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
}
}
//--------------------------------------------------------------------
template<class T>
void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, marker_e type)
{
if(n <= 0) return;
switch(type)
{
case marker_square: do { base_type::fill_color(*fc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_diamond: do { base_type::fill_color(*fc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_circle: do { base_type::fill_color(*fc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_crossed_circle: do { base_type::fill_color(*fc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_semiellipse_left: do { base_type::fill_color(*fc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_semiellipse_right: do { base_type::fill_color(*fc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_semiellipse_up: do { base_type::fill_color(*fc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_semiellipse_down: do { base_type::fill_color(*fc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_triangle_left: do { base_type::fill_color(*fc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_triangle_right: do { base_type::fill_color(*fc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_triangle_up: do { base_type::fill_color(*fc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_triangle_down: do { base_type::fill_color(*fc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_four_rays: do { base_type::fill_color(*fc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_cross: do { base_type::fill_color(*fc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_x: do { base_type::fill_color(*fc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_dash: do { base_type::fill_color(*fc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_dot: do { base_type::fill_color(*fc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
case marker_pixel: do { base_type::fill_color(*fc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
}
}
//--------------------------------------------------------------------
template<class T>
void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, const color_type* lc, marker_e type)
{
if(n <= 0) return;
switch(type)
{
case marker_square: do { base_type::fill_color(*fc); base_type::line_color(*lc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_diamond: do { base_type::fill_color(*fc); base_type::line_color(*lc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_crossed_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_semiellipse_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_semiellipse_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_semiellipse_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_semiellipse_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_triangle_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_triangle_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_triangle_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_triangle_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_four_rays: do { base_type::fill_color(*fc); base_type::line_color(*lc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_cross: do { base_type::fill_color(*fc); base_type::line_color(*lc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_x: do { base_type::fill_color(*fc); base_type::line_color(*lc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_dash: do { base_type::fill_color(*fc); base_type::line_color(*lc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_dot: do { base_type::fill_color(*fc); base_type::line_color(*lc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
case marker_pixel: do { base_type::fill_color(*fc); base_type::line_color(*lc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
}
}
};
}
#endif
+334
View File
@@ -0,0 +1,334 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// class renderer_mclip
//
//----------------------------------------------------------------------------
#ifndef AGG_RENDERER_MCLIP_INCLUDED
#define AGG_RENDERER_MCLIP_INCLUDED
#include "agg_basics.h"
#include "agg_array.h"
#include "agg_renderer_base.h"
namespace agg
{
//----------------------------------------------------------renderer_mclip
template<class PixelFormat> class renderer_mclip
{
public:
typedef PixelFormat pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef renderer_base<pixfmt_type> base_ren_type;
//--------------------------------------------------------------------
renderer_mclip(pixfmt_type& ren) :
m_ren(ren),
m_curr_cb(0),
m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax())
{
}
//--------------------------------------------------------------------
const pixfmt_type& ren() const { return m_ren.ren(); }
pixfmt_type& ren() { return m_ren.ren(); }
//--------------------------------------------------------------------
unsigned width() const { return m_ren.width(); }
unsigned height() const { return m_ren.height(); }
//--------------------------------------------------------------------
const rect& clip_box() const { return m_ren.clip_box(); }
int xmin() const { return m_ren.xmin(); }
int ymin() const { return m_ren.ymin(); }
int xmax() const { return m_ren.xmax(); }
int ymax() const { return m_ren.ymax(); }
//--------------------------------------------------------------------
const rect& bounding_clip_box() const { return m_bounds; }
int bounding_xmin() const { return m_bounds.x1; }
int bounding_ymin() const { return m_bounds.y1; }
int bounding_xmax() const { return m_bounds.x2; }
int bounding_ymax() const { return m_bounds.y2; }
//--------------------------------------------------------------------
void first_clip_box()
{
m_curr_cb = 0;
if(m_clip.size())
{
const rect& cb = m_clip[0];
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
}
}
//--------------------------------------------------------------------
bool next_clip_box()
{
if(++m_curr_cb < m_clip.size())
{
const rect& cb = m_clip[m_curr_cb];
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
return true;
}
return false;
}
//--------------------------------------------------------------------
void reset_clipping(bool visibility)
{
m_ren.reset_clipping(visibility);
m_clip.remove_all();
m_curr_cb = 0;
m_bounds = m_ren.clip_box();
}
//--------------------------------------------------------------------
void add_clip_box(int x1, int y1, int x2, int y2)
{
rect cb(x1, y1, x2, y2);
cb.normalize();
if(cb.clip(rect(0, 0, width() - 1, height() - 1)))
{
m_clip.add(cb);
if(cb.x1 < m_bounds.x1) m_bounds.x1 = cb.x1;
if(cb.y1 < m_bounds.y1) m_bounds.y1 = cb.y1;
if(cb.x2 > m_bounds.x2) m_bounds.x2 = cb.x2;
if(cb.y2 > m_bounds.y2) m_bounds.y2 = cb.y2;
}
}
//--------------------------------------------------------------------
void clear(const color_type& c)
{
m_ren.clear(c);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
first_clip_box();
do
{
if(m_ren.inbox(x, y))
{
m_ren.ren().copy_pixel(x, y, c);
break;
}
}
while(next_clip_box());
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
{
first_clip_box();
do
{
if(m_ren.inbox(x, y))
{
m_ren.ren().blend_pixel(x, y, c, cover);
break;
}
}
while(next_clip_box());
}
//--------------------------------------------------------------------
color_type pixel(int x, int y) const
{
first_clip_box();
do
{
if(m_ren.inbox(x, y))
{
return m_ren.ren().pixel(x, y);
}
}
while(next_clip_box());
return color_type::no_color();
}
//--------------------------------------------------------------------
void copy_hline(int x1, int y, int x2, const color_type& c)
{
first_clip_box();
do
{
m_ren.copy_hline(x1, y, x2, c);
}
while(next_clip_box());
}
//--------------------------------------------------------------------
void copy_vline(int x, int y1, int y2, const color_type& c)
{
first_clip_box();
do
{
m_ren.copy_vline(x, y1, y2, c);
}
while(next_clip_box());
}
//--------------------------------------------------------------------
void blend_hline(int x1, int y, int x2,
const color_type& c, cover_type cover)
{
first_clip_box();
do
{
m_ren.blend_hline(x1, y, x2, c, cover);
}
while(next_clip_box());
}
//--------------------------------------------------------------------
void blend_vline(int x, int y1, int y2,
const color_type& c, cover_type cover)
{
first_clip_box();
do
{
m_ren.blend_vline(x, y1, y2, c, cover);
}
while(next_clip_box());
}
//--------------------------------------------------------------------
void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
{
first_clip_box();
do
{
m_ren.copy_bar(x1, y1, x2, y2, c);
}
while(next_clip_box());
}
//--------------------------------------------------------------------
void blend_bar(int x1, int y1, int x2, int y2,
const color_type& c, cover_type cover)
{
first_clip_box();
do
{
m_ren.blend_bar(x1, y1, x2, y2, c, cover);
}
while(next_clip_box());
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, int len,
const color_type& c, const cover_type* covers)
{
first_clip_box();
do
{
m_ren.blend_solid_hspan(x, y, len, c, covers);
}
while(next_clip_box());
}
//--------------------------------------------------------------------
void blend_solid_vspan(int x, int y, int len,
const color_type& c, const cover_type* covers)
{
first_clip_box();
do
{
m_ren.blend_solid_vspan(x, y, len, c, covers);
}
while(next_clip_box());
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y, int len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
first_clip_box();
do
{
m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
}
while(next_clip_box());
}
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y, int len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
first_clip_box();
do
{
m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
}
while(next_clip_box());
}
//--------------------------------------------------------------------
void blend_color_hspan_no_clip(int x, int y, int len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
m_ren.blend_color_hspan_no_clip(x, y, len, colors, covers, cover);
}
//--------------------------------------------------------------------
void blend_color_vspan_no_clip(int x, int y, int len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
m_ren.blend_color_vspan_no_clip(x, y, len, colors, covers, cover);
}
//--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
const rect* rc=0,
int x_to=0,
int y_to=0)
{
first_clip_box();
do
{
m_ren.copy_from(from, rc, x_to, y_to);
}
while(next_clip_box());
}
private:
renderer_mclip(const renderer_mclip<PixelFormat>&);
const renderer_mclip<PixelFormat>&
operator = (const renderer_mclip<PixelFormat>&);
base_ren_type m_ren;
pod_deque<rect, 4> m_clip;
unsigned m_curr_cb;
rect m_bounds;
};
}
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,916 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED
#define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED
#include <math.h>
#include "agg_line_aa_basics.h"
#include "agg_dda_line.h"
#include "agg_rendering_buffer.h"
namespace agg
{
//========================================================line_image_scale
template<class Source> class line_image_scale
{
public:
typedef typename Source::color_type color_type;
line_image_scale(const Source& src, double height) :
m_source(src),
m_height(height),
m_scale(src.height() / height)
{
}
double width() const { return m_source.width(); }
double height() const { return m_height; }
color_type pixel(int x, int y) const
{
double src_y = y * m_scale;
int h = int(m_source.height()) - 1;
int y1 = int(floor(src_y));
int y2 = y1 + 1;
color_type pix1 = (y1 < 0) ? m_source.pixel(x, 0).transparent() : m_source.pixel(x, y1);
color_type pix2 = (y2 > h) ? m_source.pixel(x, h).transparent() : m_source.pixel(x, y2);
return pix1.gradient(pix2, src_y - y1);
}
private:
line_image_scale(const line_image_scale<Source>&);
const line_image_scale<Source>& operator = (const line_image_scale<Source>&);
const Source& m_source;
double m_height;
double m_scale;
};
//======================================================line_image_pattern
template<class Filter> class line_image_pattern
{
public:
typedef Filter filter_type;
typedef typename filter_type::color_type color_type;
//--------------------------------------------------------------------
~line_image_pattern()
{
delete [] m_data;
}
//--------------------------------------------------------------------
line_image_pattern(const Filter& filter) :
m_filter(&filter),
m_dilation(filter.dilation() + 1),
m_dilation_hr(m_dilation << line_subpixel_shift),
m_data(0),
m_width(0),
m_height(0),
m_width_hr(0),
m_half_height_hr(0),
m_offset_y_hr(0)
{
}
// Create
//--------------------------------------------------------------------
template<class Source>
line_image_pattern(const Filter& filter, const Source& src) :
m_filter(&filter),
m_dilation(filter.dilation() + 1),
m_dilation_hr(m_dilation << line_subpixel_shift),
m_data(0),
m_width(0),
m_height(0),
m_width_hr(0),
m_half_height_hr(0),
m_offset_y_hr(0)
{
create(src);
}
// Create
//--------------------------------------------------------------------
template<class Source> void create(const Source& src)
{
m_height = unsigned(ceil((double)src.height()));
m_width = unsigned(ceil((double)src.width()));
m_width_hr = int(src.width() * line_subpixel_size);
m_half_height_hr = int(src.height() * line_subpixel_size/2);
m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_size/2;
m_half_height_hr += line_subpixel_size/2;
delete [] m_data;
m_data = new color_type [(m_width + m_dilation * 2) * (m_height + m_dilation * 2)];
m_buf.attach(m_data, m_width + m_dilation * 2,
m_height + m_dilation * 2,
m_width + m_dilation * 2);
unsigned x, y;
color_type* d1;
color_type* d2;
for(y = 0; y < m_height; y++)
{
d1 = m_buf.row(y + m_dilation) + m_dilation;
for(x = 0; x < m_width; x++)
{
*d1++ = src.pixel(x, y);
}
}
const color_type* s1;
const color_type* s2;
for(y = 0; y < m_dilation; y++)
{
s1 = m_buf.row(m_height + m_dilation - 1) + m_dilation;
s2 = m_buf.row(m_dilation) + m_dilation;
d1 = m_buf.row(m_dilation + m_height + y) + m_dilation;
d2 = m_buf.row(m_dilation - y - 1) + m_dilation;
for(x = 0; x < m_width; x++)
{
*d1++ = color_type(*s1++, 0);
*d2++ = color_type(*s2++, 0);
}
}
unsigned h = m_height + m_dilation * 2;
for(y = 0; y < h; y++)
{
s1 = m_buf.row(y) + m_dilation;
s2 = m_buf.row(y) + m_dilation + m_width;
d1 = m_buf.row(y) + m_dilation + m_width;
d2 = m_buf.row(y) + m_dilation;
for(x = 0; x < m_dilation; x++)
{
*d1++ = *s1++;
*--d2 = *--s2;
}
}
}
//--------------------------------------------------------------------
int pattern_width() const { return m_width_hr; }
int line_width() const { return m_half_height_hr; }
//--------------------------------------------------------------------
color_type pixel(int x, int y) const
{
return m_filter->pixel_high_res(m_buf.rows(),
x % m_width_hr + m_dilation_hr,
y + m_offset_y_hr);
}
//--------------------------------------------------------------------
const filter_type& filter() const { return m_filter; }
filter_type& filter() { return m_filter; }
private:
line_image_pattern(const line_image_pattern<filter_type>&);
const line_image_pattern<filter_type>&
operator = (const line_image_pattern<filter_type>&);
protected:
row_ptr_cache<color_type> m_buf;
const filter_type* m_filter;
unsigned m_dilation;
int m_dilation_hr;
color_type* m_data;
unsigned m_width;
unsigned m_height;
int m_width_hr;
int m_half_height_hr;
int m_offset_y_hr;
};
//=================================================line_image_pattern_pow2
template<class Filter> class line_image_pattern_pow2 :
public line_image_pattern<Filter>
{
public:
typedef Filter filter_type;
typedef typename filter_type::color_type color_type;
typedef line_image_pattern<Filter> base_type;
//--------------------------------------------------------------------
line_image_pattern_pow2(const Filter& filter) :
line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) {}
//--------------------------------------------------------------------
template<class Source>
line_image_pattern_pow2(const Filter& filter, const Source& src) :
line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask)
{
create(src);
}
//--------------------------------------------------------------------
template<class Source> void create(const Source& src)
{
line_image_pattern<Filter>::create(src);
m_mask = 1;
while(m_mask < base_type::m_width)
{
m_mask <<= 1;
m_mask |= 1;
}
m_mask <<= line_subpixel_shift - 1;
m_mask |= line_subpixel_mask;
base_type::m_width_hr = m_mask + 1;
}
//--------------------------------------------------------------------
void pixel(color_type* p, int x, int y) const
{
base_type::m_filter->pixel_high_res(
base_type::m_buf.rows(),
p,
(x & m_mask) + base_type::m_dilation_hr,
y + base_type::m_offset_y_hr);
}
private:
unsigned m_mask;
};
//===================================================distance_interpolator4
class distance_interpolator4
{
public:
//---------------------------------------------------------------------
distance_interpolator4() {}
distance_interpolator4(int x1, int y1, int x2, int y2,
int sx, int sy, int ex, int ey,
int len, double scale, int x, int y) :
m_dx(x2 - x1),
m_dy(y2 - y1),
m_dx_start(line_mr(sx) - line_mr(x1)),
m_dy_start(line_mr(sy) - line_mr(y1)),
m_dx_end(line_mr(ex) - line_mr(x2)),
m_dy_end(line_mr(ey) - line_mr(y2)),
m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) -
double(y + line_subpixel_size/2 - y2) * double(m_dx))),
m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(sx)) * m_dy_start -
(line_mr(y + line_subpixel_size/2) - line_mr(sy)) * m_dx_start),
m_dist_end((line_mr(x + line_subpixel_size/2) - line_mr(ex)) * m_dy_end -
(line_mr(y + line_subpixel_size/2) - line_mr(ey)) * m_dx_end),
m_len(int(len / scale))
{
double d = len * scale;
int dx = int(((x2 - x1) << line_subpixel_shift) / d);
int dy = int(((y2 - y1) << line_subpixel_shift) / d);
m_dx_pict = -dy;
m_dy_pict = dx;
m_dist_pict = ((x + line_subpixel_size/2 - (x1 - dy)) * m_dy_pict -
(y + line_subpixel_size/2 - (y1 + dx)) * m_dx_pict) >>
line_subpixel_shift;
m_dx <<= line_subpixel_shift;
m_dy <<= line_subpixel_shift;
m_dx_start <<= line_mr_subpixel_shift;
m_dy_start <<= line_mr_subpixel_shift;
m_dx_end <<= line_mr_subpixel_shift;
m_dy_end <<= line_mr_subpixel_shift;
}
//---------------------------------------------------------------------
void inc_x()
{
m_dist += m_dy;
m_dist_start += m_dy_start;
m_dist_pict += m_dy_pict;
m_dist_end += m_dy_end;
}
//---------------------------------------------------------------------
void dec_x()
{
m_dist -= m_dy;
m_dist_start -= m_dy_start;
m_dist_pict -= m_dy_pict;
m_dist_end -= m_dy_end;
}
//---------------------------------------------------------------------
void inc_y()
{
m_dist -= m_dx;
m_dist_start -= m_dx_start;
m_dist_pict -= m_dx_pict;
m_dist_end -= m_dx_end;
}
//---------------------------------------------------------------------
void dec_y()
{
m_dist += m_dx;
m_dist_start += m_dx_start;
m_dist_pict += m_dx_pict;
m_dist_end += m_dx_end;
}
//---------------------------------------------------------------------
void inc_x(int dy)
{
m_dist += m_dy;
m_dist_start += m_dy_start;
m_dist_pict += m_dy_pict;
m_dist_end += m_dy_end;
if(dy > 0)
{
m_dist -= m_dx;
m_dist_start -= m_dx_start;
m_dist_pict -= m_dx_pict;
m_dist_end -= m_dx_end;
}
if(dy < 0)
{
m_dist += m_dx;
m_dist_start += m_dx_start;
m_dist_pict += m_dx_pict;
m_dist_end += m_dx_end;
}
}
//---------------------------------------------------------------------
void dec_x(int dy)
{
m_dist -= m_dy;
m_dist_start -= m_dy_start;
m_dist_pict -= m_dy_pict;
m_dist_end -= m_dy_end;
if(dy > 0)
{
m_dist -= m_dx;
m_dist_start -= m_dx_start;
m_dist_pict -= m_dx_pict;
m_dist_end -= m_dx_end;
}
if(dy < 0)
{
m_dist += m_dx;
m_dist_start += m_dx_start;
m_dist_pict += m_dx_pict;
m_dist_end += m_dx_end;
}
}
//---------------------------------------------------------------------
void inc_y(int dx)
{
m_dist -= m_dx;
m_dist_start -= m_dx_start;
m_dist_pict -= m_dx_pict;
m_dist_end -= m_dx_end;
if(dx > 0)
{
m_dist += m_dy;
m_dist_start += m_dy_start;
m_dist_pict += m_dy_pict;
m_dist_end += m_dy_end;
}
if(dx < 0)
{
m_dist -= m_dy;
m_dist_start -= m_dy_start;
m_dist_pict -= m_dy_pict;
m_dist_end -= m_dy_end;
}
}
//---------------------------------------------------------------------
void dec_y(int dx)
{
m_dist += m_dx;
m_dist_start += m_dx_start;
m_dist_pict += m_dx_pict;
m_dist_end += m_dx_end;
if(dx > 0)
{
m_dist += m_dy;
m_dist_start += m_dy_start;
m_dist_pict += m_dy_pict;
m_dist_end += m_dy_end;
}
if(dx < 0)
{
m_dist -= m_dy;
m_dist_start -= m_dy_start;
m_dist_pict -= m_dy_pict;
m_dist_end -= m_dy_end;
}
}
//---------------------------------------------------------------------
int dist() const { return m_dist; }
int dist_start() const { return m_dist_start; }
int dist_pict() const { return m_dist_pict; }
int dist_end() const { return m_dist_end; }
//---------------------------------------------------------------------
int dx() const { return m_dx; }
int dy() const { return m_dy; }
int dx_start() const { return m_dx_start; }
int dy_start() const { return m_dy_start; }
int dx_pict() const { return m_dx_pict; }
int dy_pict() const { return m_dy_pict; }
int dx_end() const { return m_dx_end; }
int dy_end() const { return m_dy_end; }
int len() const { return m_len; }
private:
//---------------------------------------------------------------------
int m_dx;
int m_dy;
int m_dx_start;
int m_dy_start;
int m_dx_pict;
int m_dy_pict;
int m_dx_end;
int m_dy_end;
int m_dist;
int m_dist_start;
int m_dist_pict;
int m_dist_end;
int m_len;
};
//==================================================line_interpolator_image
template<class Renderer> class line_interpolator_image
{
public:
typedef Renderer renderer_type;
typedef typename Renderer::color_type color_type;
//---------------------------------------------------------------------
enum
{
max_half_width = 64
};
//---------------------------------------------------------------------
line_interpolator_image(renderer_type& ren, const line_parameters& lp,
int sx, int sy, int ex, int ey,
int pattern_start,
double scale_x) :
m_lp(lp),
m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) :
line_dbl_hr(lp.y2 - lp.y1),
lp.vertical ? abs(lp.y2 - lp.y1) :
abs(lp.x2 - lp.x1) + 1),
m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x,
lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask),
m_ren(ren),
m_x(lp.x1 >> line_subpixel_shift),
m_y(lp.y1 >> line_subpixel_shift),
m_old_x(m_x),
m_old_y(m_y),
m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) :
abs((lp.x2 >> line_subpixel_shift) - m_x))),
m_width(ren.subpixel_width()),
m_max_extent(m_width >> (line_subpixel_shift - 2)),
m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()),
m_step(0)
{
agg::dda2_line_interpolator li(0, lp.vertical ?
(lp.dy << agg::line_subpixel_shift) :
(lp.dx << agg::line_subpixel_shift),
lp.len);
unsigned i;
int stop = m_width + line_subpixel_size * 2;
for(i = 0; i < max_half_width; ++i)
{
m_dist_pos[i] = li.y();
if(m_dist_pos[i] >= stop) break;
++li;
}
m_dist_pos[i] = 0x7FFF0000;
int dist1_start;
int dist2_start;
int npix = 1;
if(lp.vertical)
{
do
{
--m_li;
m_y -= lp.inc;
m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
if(lp.inc > 0) m_di.dec_y(m_x - m_old_x);
else m_di.inc_y(m_x - m_old_x);
m_old_x = m_x;
dist1_start = dist2_start = m_di.dist_start();
int dx = 0;
if(dist1_start < 0) ++npix;
do
{
dist1_start += m_di.dy_start();
dist2_start -= m_di.dy_start();
if(dist1_start < 0) ++npix;
if(dist2_start < 0) ++npix;
++dx;
}
while(m_dist_pos[dx] <= m_width);
if(npix == 0) break;
npix = 0;
}
while(--m_step >= -m_max_extent);
}
else
{
do
{
--m_li;
m_x -= lp.inc;
m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
if(lp.inc > 0) m_di.dec_x(m_y - m_old_y);
else m_di.inc_x(m_y - m_old_y);
m_old_y = m_y;
dist1_start = dist2_start = m_di.dist_start();
int dy = 0;
if(dist1_start < 0) ++npix;
do
{
dist1_start -= m_di.dx_start();
dist2_start += m_di.dx_start();
if(dist1_start < 0) ++npix;
if(dist2_start < 0) ++npix;
++dy;
}
while(m_dist_pos[dy] <= m_width);
if(npix == 0) break;
npix = 0;
}
while(--m_step >= -m_max_extent);
}
m_li.adjust_forward();
m_step -= m_max_extent;
}
//---------------------------------------------------------------------
bool step_hor()
{
++m_li;
m_x += m_lp.inc;
m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
if(m_lp.inc > 0) m_di.inc_x(m_y - m_old_y);
else m_di.dec_x(m_y - m_old_y);
m_old_y = m_y;
int s1 = m_di.dist() / m_lp.len;
int s2 = -s1;
if(m_lp.inc < 0) s1 = -s1;
int dist_start;
int dist_pict;
int dist_end;
int dy;
int dist;
dist_start = m_di.dist_start();
dist_pict = m_di.dist_pict() + m_start;
dist_end = m_di.dist_end();
color_type* p0 = m_colors + max_half_width + 2;
color_type* p1 = p0;
int npix = 0;
p1->clear();
if(dist_end > 0)
{
if(dist_start <= 0)
{
m_ren.pixel(p1, dist_pict, s2);
}
++npix;
}
++p1;
dy = 1;
while((dist = m_dist_pos[dy]) - s1 <= m_width)
{
dist_start -= m_di.dx_start();
dist_pict -= m_di.dx_pict();
dist_end -= m_di.dx_end();
p1->clear();
if(dist_end > 0 && dist_start <= 0)
{
if(m_lp.inc > 0) dist = -dist;
m_ren.pixel(p1, dist_pict, s2 - dist);
++npix;
}
++p1;
++dy;
}
dy = 1;
dist_start = m_di.dist_start();
dist_pict = m_di.dist_pict() + m_start;
dist_end = m_di.dist_end();
while((dist = m_dist_pos[dy]) + s1 <= m_width)
{
dist_start += m_di.dx_start();
dist_pict += m_di.dx_pict();
dist_end += m_di.dx_end();
--p0;
p0->clear();
if(dist_end > 0 && dist_start <= 0)
{
if(m_lp.inc > 0) dist = -dist;
m_ren.pixel(p0, dist_pict, s2 + dist);
++npix;
}
++dy;
}
m_ren.blend_color_vspan(m_x,
m_y - dy + 1,
unsigned(p1 - p0),
p0);
return npix && ++m_step < m_count;
}
//---------------------------------------------------------------------
bool step_ver()
{
++m_li;
m_y += m_lp.inc;
m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
if(m_lp.inc > 0) m_di.inc_y(m_x - m_old_x);
else m_di.dec_y(m_x - m_old_x);
m_old_x = m_x;
int s1 = m_di.dist() / m_lp.len;
int s2 = -s1;
if(m_lp.inc > 0) s1 = -s1;
int dist_start;
int dist_pict;
int dist_end;
int dist;
int dx;
dist_start = m_di.dist_start();
dist_pict = m_di.dist_pict() + m_start;
dist_end = m_di.dist_end();
color_type* p0 = m_colors + max_half_width + 2;
color_type* p1 = p0;
int npix = 0;
p1->clear();
if(dist_end > 0)
{
if(dist_start <= 0)
{
m_ren.pixel(p1, dist_pict, s2);
}
++npix;
}
++p1;
dx = 1;
while((dist = m_dist_pos[dx]) - s1 <= m_width)
{
dist_start += m_di.dy_start();
dist_pict += m_di.dy_pict();
dist_end += m_di.dy_end();
p1->clear();
if(dist_end > 0 && dist_start <= 0)
{
if(m_lp.inc > 0) dist = -dist;
m_ren.pixel(p1, dist_pict, s2 + dist);
++npix;
}
++p1;
++dx;
}
dx = 1;
dist_start = m_di.dist_start();
dist_pict = m_di.dist_pict() + m_start;
dist_end = m_di.dist_end();
while((dist = m_dist_pos[dx]) + s1 <= m_width)
{
dist_start -= m_di.dy_start();
dist_pict -= m_di.dy_pict();
dist_end -= m_di.dy_end();
--p0;
p0->clear();
if(dist_end > 0 && dist_start <= 0)
{
if(m_lp.inc > 0) dist = -dist;
m_ren.pixel(p0, dist_pict, s2 - dist);
++npix;
}
++dx;
}
m_ren.blend_color_hspan(m_x - dx + 1,
m_y,
unsigned(p1 - p0),
p0);
return npix && ++m_step < m_count;
}
//---------------------------------------------------------------------
int pattern_end() const { return m_start + m_di.len(); }
//---------------------------------------------------------------------
bool vertical() const { return m_lp.vertical; }
int width() const { return m_width; }
int count() const { return m_count; }
private:
line_interpolator_image(const line_interpolator_image<Renderer>&);
const line_interpolator_image<Renderer>&
operator = (const line_interpolator_image<Renderer>&);
protected:
const line_parameters& m_lp;
dda2_line_interpolator m_li;
distance_interpolator4 m_di;
renderer_type& m_ren;
int m_plen;
int m_x;
int m_y;
int m_old_x;
int m_old_y;
int m_count;
int m_width;
int m_max_extent;
int m_start;
int m_step;
int m_dist_pos[max_half_width + 1];
color_type m_colors[max_half_width * 2 + 4];
};
//===================================================renderer_outline_image
template<class BaseRenderer, class ImagePattern>
class renderer_outline_image
{
public:
//---------------------------------------------------------------------
typedef BaseRenderer base_ren_type;
typedef renderer_outline_image<BaseRenderer, ImagePattern> self_type;
typedef typename base_ren_type::color_type color_type;
typedef ImagePattern pattern_type;
//---------------------------------------------------------------------
renderer_outline_image(base_ren_type& ren, const pattern_type& patt) :
m_ren(&ren),
m_pattern(&patt),
m_start(0),
m_scale_x(1.0)
{
}
//---------------------------------------------------------------------
void pattern(const pattern_type& p) { m_pattern = &p; }
const pattern_type& pattern() const { return *m_pattern; }
//---------------------------------------------------------------------
void scale_x(double s) { m_scale_x = s; }
double scale_x() const { return m_scale_x; }
//---------------------------------------------------------------------
int subpixel_width() const { return m_pattern->line_width(); }
int pattern_width() const { return m_pattern->pattern_width(); }
//-------------------------------------------------------------------------
void pixel(color_type* p, int x, int y) const
{
m_pattern->pixel(p, x, y);
}
//-------------------------------------------------------------------------
void blend_color_hspan(int x, int y, unsigned len, const color_type* colors)
{
m_ren->blend_color_hspan(x, y, len, colors, 0);
}
//-------------------------------------------------------------------------
void blend_color_vspan(int x, int y, unsigned len, const color_type* colors)
{
m_ren->blend_color_vspan(x, y, len, colors, 0);
}
//-------------------------------------------------------------------------
static bool accurate_join_only() { return true; }
//-------------------------------------------------------------------------
template<class Cmp>
void semidot(Cmp, int, int, int, int)
{
}
//-------------------------------------------------------------------------
void line0(const line_parameters&)
{
}
//-------------------------------------------------------------------------
void line1(const line_parameters&, int, int)
{
}
//-------------------------------------------------------------------------
void line2(const line_parameters&, int, int)
{
}
//-------------------------------------------------------------------------
void line3(const line_parameters& lp,
int sx, int sy, int ex, int ey)
{
line_interpolator_image<self_type> li(*this, lp,
sx, sy,
ex, ey,
m_start, m_scale_x);
if(li.vertical())
{
while(li.step_ver());
}
else
{
while(li.step_hor());
}
m_start = li.pattern_end();
}
private:
base_ren_type* m_ren;
const pattern_type* m_pattern;
int m_start;
double m_scale_x;
};
}
#endif
+224
View File
@@ -0,0 +1,224 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// class renderer_primitives
//
//----------------------------------------------------------------------------
#ifndef AGG_RENDERER_PRIMITIVES_INCLUDED
#define AGG_RENDERER_PRIMITIVES_INCLUDED
#include "agg_basics.h"
#include "agg_renderer_base.h"
#include "agg_dda_line.h"
#include "agg_ellipse_bresenham.h"
namespace agg
{
//-----------------------------------------------------renderer_primitives
template<class BaseRenderer> class renderer_primitives
{
public:
typedef BaseRenderer base_ren_type;
typedef typename base_ren_type::color_type color_type;
//--------------------------------------------------------------------
renderer_primitives(base_ren_type& ren) :
m_ren(&ren),
m_fill_color(),
m_line_color(),
m_curr_x(0),
m_curr_y(0)
{
}
//--------------------------------------------------------------------
static int coord(double c)
{
return int(c * line_bresenham_interpolator::subpixel_size);
}
//--------------------------------------------------------------------
void fill_color(const color_type& c) { m_fill_color = c; }
void line_color(const color_type& c) { m_line_color = c; }
const color_type& fill_color() const { return m_fill_color; }
const color_type& line_color() const { return m_line_color; }
//--------------------------------------------------------------------
void rectangle(int x1, int y1, int x2, int y2)
{
m_ren->blend_hline(x1, y1, x2-1, m_line_color, cover_full);
m_ren->blend_vline(x2, y1, y2-1, m_line_color, cover_full);
m_ren->blend_hline(x1+1, y2, x2, m_line_color, cover_full);
m_ren->blend_vline(x1, y1+1, y2, m_line_color, cover_full);
}
//--------------------------------------------------------------------
void solid_rectangle(int x1, int y1, int x2, int y2)
{
m_ren->blend_bar(x1, y1, x2, y2, m_fill_color, cover_full);
}
//--------------------------------------------------------------------
void outlined_rectangle(int x1, int y1, int x2, int y2)
{
rectangle(x1, y1, x2, y2);
m_ren->blend_bar(x1+1, y1+1, x2-1, y2-1, m_fill_color, cover_full);
}
//--------------------------------------------------------------------
void ellipse(int x, int y, int rx, int ry)
{
ellipse_bresenham_interpolator ei(rx, ry);
int dx = 0;
int dy = -ry;
do
{
dx += ei.dx();
dy += ei.dy();
m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
++ei;
}
while(dy < 0);
}
//--------------------------------------------------------------------
void solid_ellipse(int x, int y, int rx, int ry)
{
ellipse_bresenham_interpolator ei(rx, ry);
int dx = 0;
int dy = -ry;
int dy0 = dy;
int dx0 = dx;
do
{
dx += ei.dx();
dy += ei.dy();
if(dy != dy0)
{
m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full);
m_ren->blend_hline(x-dx0, y-dy0, x+dx0, m_fill_color, cover_full);
}
dx0 = dx;
dy0 = dy;
++ei;
}
while(dy < 0);
m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full);
}
//--------------------------------------------------------------------
void outlined_ellipse(int x, int y, int rx, int ry)
{
ellipse_bresenham_interpolator ei(rx, ry);
int dx = 0;
int dy = -ry;
do
{
dx += ei.dx();
dy += ei.dy();
m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
if(ei.dy() && dx)
{
m_ren->blend_hline(x-dx+1, y+dy, x+dx-1, m_fill_color, cover_full);
m_ren->blend_hline(x-dx+1, y-dy, x+dx-1, m_fill_color, cover_full);
}
++ei;
}
while(dy < 0);
}
//--------------------------------------------------------------------
void line(int x1, int y1, int x2, int y2, bool last=false)
{
line_bresenham_interpolator li(x1, y1, x2, y2);
unsigned len = li.len();
if(len == 0)
{
if(last)
{
m_ren->blend_pixel(li.line_lr(x1), li.line_lr(y1), m_line_color, cover_full);
}
return;
}
if(last) ++len;
if(li.is_ver())
{
do
{
m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full);
li.vstep();
}
while(--len);
}
else
{
do
{
m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full);
li.hstep();
}
while(--len);
}
}
//--------------------------------------------------------------------
void move_to(int x, int y)
{
m_curr_x = x;
m_curr_y = y;
}
//--------------------------------------------------------------------
void line_to(int x, int y, bool last=false)
{
line(m_curr_x, m_curr_y, x, y, last);
m_curr_x = x;
m_curr_y = y;
}
//--------------------------------------------------------------------
const base_ren_type& ren() const { return *m_ren; }
base_ren_type& ren() { return *m_ren; }
//--------------------------------------------------------------------
const rendering_buffer& rbuf() const { return m_ren->rbuf(); }
rendering_buffer& rbuf() { return m_ren->rbuf(); }
private:
base_ren_type* m_ren;
color_type m_fill_color;
color_type m_line_color;
int m_curr_x;
int m_curr_y;
};
}
#endif
+264
View File
@@ -0,0 +1,264 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_RENDERER_RASTER_TEXT_INCLUDED
#define AGG_RENDERER_RASTER_TEXT_INCLUDED
#include "agg_basics.h"
namespace agg
{
//==============================================renderer_raster_htext_solid
template<class BaseRenderer, class GlyphGenerator>
class renderer_raster_htext_solid
{
public:
typedef BaseRenderer ren_type;
typedef GlyphGenerator glyph_gen_type;
typedef typename glyph_gen_type::glyph_rect glyph_rect;
typedef typename ren_type::color_type color_type;
renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph) :
m_ren(&ren),
m_glyph(&glyph)
{
}
//--------------------------------------------------------------------
void color(const color_type& c) { m_color = c; }
const color_type& color() const { return m_color; }
//--------------------------------------------------------------------
template<class CharT>
void render_text(double x, double y, const CharT* str, bool flip=false)
{
glyph_rect r;
while(*str)
{
m_glyph->prepare(&r, x, y, *str, flip);
if(r.x2 >= r.x1)
{
int i;
if(flip)
{
for(i = r.y1; i <= r.y2; i++)
{
m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1),
m_color,
m_glyph->span(r.y2 - i));
}
}
else
{
for(i = r.y1; i <= r.y2; i++)
{
m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1),
m_color,
m_glyph->span(i - r.y1));
}
}
}
x += r.dx;
y += r.dy;
++str;
}
}
private:
ren_type* m_ren;
glyph_gen_type* m_glyph;
color_type m_color;
};
//=============================================renderer_raster_vtext_solid
template<class BaseRenderer, class GlyphGenerator>
class renderer_raster_vtext_solid
{
public:
typedef BaseRenderer ren_type;
typedef GlyphGenerator glyph_gen_type;
typedef typename glyph_gen_type::glyph_rect glyph_rect;
typedef typename ren_type::color_type color_type;
renderer_raster_vtext_solid(ren_type& ren, glyph_gen_type& glyph) :
m_ren(&ren),
m_glyph(&glyph)
{
}
//--------------------------------------------------------------------
void color(const color_type& c) { m_color = c; }
const color_type& color() const { return m_color; }
//--------------------------------------------------------------------
template<class CharT>
void render_text(double x, double y, const CharT* str, bool flip=false)
{
glyph_rect r;
while(*str)
{
m_glyph->prepare(&r, x, y, *str, !flip);
if(r.x2 >= r.x1)
{
int i;
if(flip)
{
for(i = r.y1; i <= r.y2; i++)
{
m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1),
m_color,
m_glyph->span(i - r.y1));
}
}
else
{
for(i = r.y1; i <= r.y2; i++)
{
m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1),
m_color,
m_glyph->span(r.y2 - i));
}
}
}
x += r.dx;
y += r.dy;
++str;
}
}
private:
ren_type* m_ren;
glyph_gen_type* m_glyph;
color_type m_color;
};
//===================================================renderer_raster_htext
template<class ScanlineRenderer, class GlyphGenerator>
class renderer_raster_htext
{
public:
typedef ScanlineRenderer ren_type;
typedef GlyphGenerator glyph_gen_type;
typedef typename glyph_gen_type::glyph_rect glyph_rect;
class scanline_single_span
{
public:
typedef agg::cover_type cover_type;
//----------------------------------------------------------------
struct const_span
{
int x;
unsigned len;
const cover_type* covers;
const_span() {}
const_span(int x_, unsigned len_, const cover_type* covers_) :
x(x_), len(len_), covers(covers_)
{}
};
typedef const const_span* const_iterator;
//----------------------------------------------------------------
scanline_single_span(int x, int y, unsigned len,
const cover_type* covers) :
m_y(y),
m_span(x, len, covers)
{}
//----------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return 1; }
const_iterator begin() const { return &m_span; }
private:
//----------------------------------------------------------------
int m_y;
const_span m_span;
};
//--------------------------------------------------------------------
renderer_raster_htext(ren_type& ren, glyph_gen_type& glyph) :
m_ren(&ren),
m_glyph(&glyph)
{
}
//--------------------------------------------------------------------
template<class CharT>
void render_text(double x, double y, const CharT* str, bool flip=false)
{
glyph_rect r;
while(*str)
{
m_glyph->prepare(&r, x, y, *str, flip);
if(r.x2 >= r.x1)
{
m_ren->prepare(r.x2 - r.x1 + 1);
int i;
if(flip)
{
for(i = r.y1; i <= r.y2; i++)
{
m_ren->render(
scanline_single_span(r.x1,
i,
(r.x2 - r.x1 + 1),
m_glyph->span(r.y2 - i)));
}
}
else
{
for(i = r.y1; i <= r.y2; i++)
{
m_ren->render(
scanline_single_span(r.x1,
i,
(r.x2 - r.x1 + 1),
m_glyph->span(i - r.y1)));
}
}
}
x += r.dx;
y += r.dy;
++str;
}
}
private:
ren_type* m_ren;
glyph_gen_type* m_glyph;
};
}
#endif
+285
View File
@@ -0,0 +1,285 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_RENDERER_SCANLINE_INCLUDED
#define AGG_RENDERER_SCANLINE_INCLUDED
#include "agg_basics.h"
#include "agg_renderer_base.h"
#include "agg_render_scanlines.h"
namespace agg
{
//====================================================renderer_scanline_aa
template<class BaseRenderer, class SpanGenerator> class renderer_scanline_aa
{
public:
typedef BaseRenderer base_ren_type;
//--------------------------------------------------------------------
renderer_scanline_aa(base_ren_type& ren, SpanGenerator& span_gen) :
m_ren(&ren),
m_span_gen(&span_gen)
{
}
//--------------------------------------------------------------------
void prepare(unsigned max_span_len)
{
m_span_gen->prepare(max_span_len);
}
//--------------------------------------------------------------------
template<class Scanline> void render(const Scanline& sl)
{
int y = sl.y();
m_ren->first_clip_box();
do
{
int xmin = m_ren->xmin();
int xmax = m_ren->xmax();
if(y >= m_ren->ymin() && y <= m_ren->ymax())
{
unsigned num_spans = sl.num_spans();
typename Scanline::const_iterator span = sl.begin();
do
{
int x = span->x;
int len = span->len;
bool solid = false;
const typename Scanline::cover_type* covers = span->covers;
if(len < 0)
{
solid = true;
len = -len;
}
if(x < xmin)
{
len -= xmin - x;
covers += xmin - x;
x = xmin;
}
if(len > 0)
{
if(x + len > xmax)
{
len = xmax - x + 1;
}
if(len > 0)
{
m_ren->blend_color_hspan_no_clip(
x, y, len,
m_span_gen->generate(x, y, len),
solid ? 0 : covers,
*covers);
}
}
++span;
}
while(--num_spans);
}
}
while(m_ren->next_clip_box());
}
private:
base_ren_type* m_ren;
SpanGenerator* m_span_gen;
};
//==============================================renderer_scanline_aa_solid
template<class BaseRenderer> class renderer_scanline_aa_solid
{
public:
typedef BaseRenderer base_ren_type;
typedef typename base_ren_type::color_type color_type;
//--------------------------------------------------------------------
renderer_scanline_aa_solid(base_ren_type& ren) :
m_ren(&ren)
{
}
//--------------------------------------------------------------------
void color(const color_type& c) { m_color = c; }
const color_type& color() const { return m_color; }
//--------------------------------------------------------------------
void prepare(unsigned) {}
//--------------------------------------------------------------------
template<class Scanline> void render(const Scanline& sl)
{
int y = sl.y();
unsigned num_spans = sl.num_spans();
typename Scanline::const_iterator span = sl.begin();
do
{
int x = span->x;
if(span->len > 0)
{
m_ren->blend_solid_hspan(x, y, (unsigned)span->len,
m_color,
span->covers);
}
else
{
m_ren->blend_hline(x, y, (unsigned)(x - span->len - 1),
m_color,
*(span->covers));
}
++span;
}
while(--num_spans);
}
private:
base_ren_type* m_ren;
color_type m_color;
};
//===================================================renderer_scanline_bin
template<class BaseRenderer, class SpanGenerator> class renderer_scanline_bin
{
public:
typedef BaseRenderer base_ren_type;
//--------------------------------------------------------------------
renderer_scanline_bin(base_ren_type& ren, SpanGenerator& span_gen) :
m_ren(&ren),
m_span_gen(&span_gen)
{
}
//--------------------------------------------------------------------
void prepare(unsigned max_span_len)
{
m_span_gen->prepare(max_span_len);
}
//--------------------------------------------------------------------
template<class Scanline> void render(const Scanline& sl)
{
int y = sl.y();
m_ren->first_clip_box();
do
{
int xmin = m_ren->xmin();
int xmax = m_ren->xmax();
if(y >= m_ren->ymin() && y <= m_ren->ymax())
{
unsigned num_spans = sl.num_spans();
typename Scanline::const_iterator span = sl.begin();
do
{
int x = span->x;
int len = span->len;
if(len < 0) len = -len;
if(x < xmin)
{
len -= xmin - x;
x = xmin;
}
if(len > 0)
{
if(x + len > xmax)
{
len = xmax - x + 1;
}
if(len > 0)
{
m_ren->blend_color_hspan_no_clip(
x, y, len,
m_span_gen->generate(x, y, len),
0);
}
}
++span;
}
while(--num_spans);
}
}
while(m_ren->next_clip_box());
}
private:
base_ren_type* m_ren;
SpanGenerator* m_span_gen;
};
//=============================================renderer_scanline_bin_solid
template<class BaseRenderer> class renderer_scanline_bin_solid
{
public:
typedef BaseRenderer base_ren_type;
typedef typename base_ren_type::color_type color_type;
//--------------------------------------------------------------------
renderer_scanline_bin_solid(base_ren_type& ren) :
m_ren(&ren)
{
}
//--------------------------------------------------------------------
void color(const color_type& c) { m_color = c; }
const color_type& color() const { return m_color; }
//--------------------------------------------------------------------
void prepare(unsigned) {}
//--------------------------------------------------------------------
template<class Scanline> void render(const Scanline& sl)
{
unsigned num_spans = sl.num_spans();
typename Scanline::const_iterator span = sl.begin();
do
{
m_ren->blend_hline(span->x,
sl.y(),
span->x - 1 + ((span->len < 0) ?
-span->len :
span->len),
m_color,
cover_full);
++span;
}
while(--num_spans);
}
private:
base_ren_type* m_ren;
color_type m_color;
};
}
#endif
+149
View File
@@ -0,0 +1,149 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// class rendering_buffer
//
//----------------------------------------------------------------------------
#ifndef AGG_RENDERING_BUFFER_INCLUDED
#define AGG_RENDERING_BUFFER_INCLUDED
#include "agg_basics.h"
namespace agg
{
//==========================================================row_ptr_cache
template<class T> class row_ptr_cache
{
public:
//-------------------------------------------------------------------
~row_ptr_cache()
{
delete [] m_rows;
}
//-------------------------------------------------------------------
row_ptr_cache() :
m_buf(0),
m_rows(0),
m_width(0),
m_height(0),
m_stride(0),
m_max_height(0)
{
}
//--------------------------------------------------------------------
row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) :
m_buf(0),
m_rows(0),
m_width(0),
m_height(0),
m_stride(0),
m_max_height(0)
{
attach(buf, width, height, stride);
}
//--------------------------------------------------------------------
void attach(T* buf, unsigned width, unsigned height, int stride)
{
m_buf = buf;
m_width = width;
m_height = height;
m_stride = stride;
if(height > m_max_height)
{
delete [] m_rows;
m_rows = new T* [m_max_height = height];
}
T* row_ptr = m_buf;
if(stride < 0)
{
row_ptr = m_buf - int(height - 1) * stride;
}
T** rows = m_rows;
while(height--)
{
*rows++ = row_ptr;
row_ptr += stride;
}
}
//--------------------------------------------------------------------
const T* buf() const { return m_buf; }
unsigned width() const { return m_width; }
unsigned height() const { return m_height; }
int stride() const { return m_stride; }
unsigned stride_abs() const
{
return (m_stride < 0) ?
unsigned(-m_stride) :
unsigned(m_stride);
}
//--------------------------------------------------------------------
T* row(unsigned y) { return m_rows[y]; }
const T* row(unsigned y) const { return m_rows[y]; }
T const* const* rows() const { return m_rows; }
//--------------------------------------------------------------------
void copy_from(const row_ptr_cache<T>& mtx)
{
unsigned h = height();
if(mtx.height() < h) h = mtx.height();
unsigned l = stride_abs();
if(mtx.stride_abs() < l) l = mtx.stride_abs();
l *= sizeof(T);
unsigned y;
for (y = 0; y < h; y++)
{
memcpy(row(y), mtx.row(y), l);
}
}
private:
//--------------------------------------------------------------------
// Prohibit copying
row_ptr_cache(const row_ptr_cache<T>&);
const row_ptr_cache<T>& operator = (const row_ptr_cache<T>&);
private:
//--------------------------------------------------------------------
T* m_buf; // Pointer to renrdering buffer
T** m_rows; // Pointers to each row of the buffer
unsigned m_width; // Width in pixels
unsigned m_height; // Height in pixels
int m_stride; // Number of bytes per row. Can be < 0
unsigned m_max_height; // The maximal height (currently allocated)
};
//========================================================rendering_buffer
typedef row_ptr_cache<int8u> rendering_buffer;
}
#endif
+79
View File
@@ -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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Rounded rectangle vertex generator
//
//----------------------------------------------------------------------------
#ifndef AGG_ROUNDED_RECT_INCLUDED
#define AGG_ROUNDED_RECT_INCLUDED
#include "agg_basics.h"
#include "agg_arc.h"
#include "agg_vertex_iterator.h"
namespace agg
{
//------------------------------------------------------------rounded_rect
//
// See Implemantation agg_rounded_rect.cpp
//
class rounded_rect
{
public:
rounded_rect() {}
rounded_rect(double x1, double y1, double x2, double y2, double r);
void rect(double x1, double y1, double x2, double y2);
void radius(double r);
void radius(double rx, double ry);
void radius(double rx_bottom, double ry_bottom, double rx_top, double ry_top);
void radius(double rx1, double ry1, double rx2, double ry2,
double rx3, double ry3, double rx4, double ry4);
void normalize_radius();
void approximation_scale(double s) { m_arc.approximation_scale(s); }
double approximation_scale() const { return m_arc.approximation_scale(); }
void rewind(unsigned);
unsigned vertex(double* x, double* y);
typedef rounded_rect source_type;
typedef vertex_iterator<source_type> iterator;
iterator begin(unsigned id) { return iterator(*this, id); }
iterator end() { return iterator(path_cmd_stop); }
private:
double m_x1;
double m_y1;
double m_x2;
double m_y2;
double m_rx1;
double m_ry1;
double m_rx2;
double m_ry2;
double m_rx3;
double m_ry3;
double m_rx4;
double m_ry4;
unsigned m_status;
arc m_arc;
};
}
#endif
+171
View File
@@ -0,0 +1,171 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Class scanline_bin - binary scanline.
//
//----------------------------------------------------------------------------
#ifndef AGG_SCANLINE_BIN_INCLUDED
#define AGG_SCANLINE_BIN_INCLUDED
#include "agg_basics.h"
namespace agg
{
//=============================================================scanline_bin
//
// This is binary scaline container which supports the interface
// used in the rasterizer::render(). See description of agg_scanline_u8
// for details.
//
// Rendering:
//-------------------------------------------------------------------------
//
// int y = sl.y();
//
// ************************************
// ...Perform vertical clipping here...
// ************************************
//
// unsigned num_spans = sl.num_spans();
// const agg::scanline_bin::span* cur_span = sl.spans();
//
// do
// {
// x = cur_span->x;
// len = cur_span->len;
//
// **************************************
// ...Perform horizontal clipping here...
// **************************************
//
// hor_line(x, y, len)
// ++cur_span;
// }
// while(--num_spans);
//
//------------------------------------------------------------------------
class scanline_bin
{
public:
struct span
{
int16 x;
int16 len;
};
typedef const span* const_iterator;
~scanline_bin()
{
delete [] m_spans;
}
scanline_bin() :
m_max_len(0),
m_last_x(0x7FFF),
m_spans(0),
m_cur_span(0)
{
}
void reset(int min_x, int max_x);
void add_cell(int x, unsigned);
void add_cells(int x, unsigned len, const void*);
void add_span(int x, unsigned len, unsigned);
void finalize(int y) { m_y = y; }
void reset_spans();
int y() const { return m_y; }
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
const_iterator begin() const { return m_spans + 1; }
private:
scanline_bin(const scanline_bin&);
const scanline_bin operator = (const scanline_bin&);
unsigned m_max_len;
int m_last_x;
int m_y;
span* m_spans;
span* m_cur_span;
};
//------------------------------------------------------------------------
inline void scanline_bin::reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 3;
if(max_len > m_max_len)
{
delete [] m_spans;
m_spans = new span [max_len];
m_max_len = max_len;
}
m_last_x = 0x7FFF;
m_cur_span = m_spans;
}
//------------------------------------------------------------------------
inline void scanline_bin::reset_spans()
{
m_last_x = 0x7FFF;
m_cur_span = m_spans;
}
//------------------------------------------------------------------------
inline void scanline_bin::add_cell(int x, unsigned)
{
if(x == m_last_x+1)
{
m_cur_span->len++;
}
else
{
++m_cur_span;
m_cur_span->x = (int16)x;
m_cur_span->len = 1;
}
m_last_x = x;
}
//------------------------------------------------------------------------
inline void scanline_bin::add_span(int x, unsigned len, unsigned)
{
if(x == m_last_x+1)
{
m_cur_span->len = (int16)(m_cur_span->len + len);
}
else
{
++m_cur_span;
m_cur_span->x = (int16)x;
m_cur_span->len = (int16)len;
}
m_last_x = x + len - 1;
}
//------------------------------------------------------------------------
inline void scanline_bin::add_cells(int x, unsigned len, const void*)
{
add_span(x, len, 0);
}
}
#endif
File diff suppressed because it is too large Load Diff
+197
View File
@@ -0,0 +1,197 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Class scanline_p - a general purpose scanline container with packed spans.
//
//----------------------------------------------------------------------------
#ifndef AGG_SCANLINE_P_INCLUDED
#define AGG_SCANLINE_P_INCLUDED
#include "agg_basics.h"
namespace agg
{
//==============================================================scanline_p
//
// This is a general purpose scaline container which supports the interface
// used in the rasterizer::render(). See description of agg_scanline_u
// for details.
//
//------------------------------------------------------------------------
template<class T> class scanline_p
{
public:
typedef T cover_type;
struct span
{
int16 x;
int16 len; // If negative, it's a solid span, covers is valid
const T* covers;
};
typedef span* iterator;
typedef const span* const_iterator;
~scanline_p()
{
delete [] m_spans;
delete [] m_covers;
}
scanline_p() :
m_max_len(0),
m_last_x(0x7FFFFFF0),
m_covers(0),
m_cover_ptr(0),
m_spans(0),
m_cur_span(0)
{
}
void reset(int min_x, int max_x);
void add_cell(int x, unsigned cover);
void add_cells(int x, unsigned len, const T* covers);
void add_span(int x, unsigned len, unsigned cover);
void finalize(int y) { m_y = y; }
void reset_spans();
int y() const { return m_y; }
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
const_iterator begin() const { return m_spans + 1; }
private:
scanline_p(const scanline_p<T>&);
const scanline_p<T>& operator = (const scanline_p<T>&);
unsigned m_max_len;
int m_last_x;
int m_y;
T* m_covers;
T* m_cover_ptr;
span* m_spans;
span* m_cur_span;
};
//------------------------------------------------------------------------
template<class T>
void scanline_p<T>::reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 3;
if(max_len > m_max_len)
{
delete [] m_spans;
delete [] m_covers;
m_covers = new T [max_len];
m_spans = new span [max_len];
m_max_len = max_len;
}
m_last_x = 0x7FFFFFF0;
m_cover_ptr = m_covers;
m_cur_span = m_spans;
m_cur_span->len = 0;
}
//------------------------------------------------------------------------
template<class T>
void scanline_p<T>::reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cover_ptr = m_covers;
m_cur_span = m_spans;
m_cur_span->len = 0;
}
//------------------------------------------------------------------------
template<class T>
void scanline_p<T>::add_cell(int x, unsigned cover)
{
*m_cover_ptr = (T)cover;
if(x == m_last_x+1 && m_cur_span->len > 0)
{
m_cur_span->len++;
}
else
{
m_cur_span++;
m_cur_span->covers = m_cover_ptr;
m_cur_span->x = (int16)x;
m_cur_span->len = 1;
}
m_last_x = x;
m_cover_ptr++;
}
//------------------------------------------------------------------------
template<class T>
void scanline_p<T>::add_cells(int x, unsigned len, const T* covers)
{
memcpy(m_cover_ptr, covers, len * sizeof(T));
if(x == m_last_x+1 && m_cur_span->len > 0)
{
m_cur_span->len += (int16)len;
}
else
{
m_cur_span++;
m_cur_span->covers = m_cover_ptr;
m_cur_span->x = (int16)x;
m_cur_span->len = (int16)len;
}
m_cover_ptr += len;
m_last_x = x + len - 1;
}
//------------------------------------------------------------------------
template<class T>
void scanline_p<T>::add_span(int x, unsigned len, unsigned cover)
{
if(x == m_last_x+1 &&
m_cur_span->len < 0 &&
cover == *m_cur_span->covers)
{
m_cur_span->len -= (int16)len;
}
else
{
*m_cover_ptr = (T)cover;
m_cur_span++;
m_cur_span->covers = m_cover_ptr++;
m_cur_span->x = (int16)x;
m_cur_span->len = -((int16)len);
}
m_last_x = x + len - 1;
}
//=============================================================scanline_p8
typedef scanline_p<int8u> scanline_p8;
//============================================================scanline_p16
typedef scanline_p<int16u> scanline_p16;
//============================================================scanline_p32
typedef scanline_p<int32u> scanline_p32;
}
#endif
+795
View File
@@ -0,0 +1,795 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SCANLINE_STORAGE_AA_INCLUDED
#define AGG_SCANLINE_STORAGE_AA_INCLUDED
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "agg_array.h"
#include "agg_render_scanlines.h"
namespace agg
{
//----------------------------------------------scanline_cell_storage
template<class T> class scanline_cell_storage
{
struct extra_span
{
unsigned len;
T* ptr;
};
public:
typedef T value_type;
//---------------------------------------------------------------
~scanline_cell_storage()
{
remove_all();
}
//---------------------------------------------------------------
scanline_cell_storage() :
m_cells(128-2),
m_extra_storage()
{}
// Copying
//---------------------------------------------------------------
scanline_cell_storage(const scanline_cell_storage<T>& v) :
m_cells(v.m_cells),
m_extra_storage()
{
copy_extra_storage(v);
}
//---------------------------------------------------------------
const scanline_cell_storage<T>&
operator = (const scanline_cell_storage<T>& v)
{
remove_all();
m_cells = v.m_cells;
copy_extra_storage(v);
return *this;
}
//---------------------------------------------------------------
void remove_all()
{
int i;
for(i = m_extra_storage.size()-1; i >= 0; --i)
{
delete [] m_extra_storage[(unsigned)i].ptr;
}
m_extra_storage.remove_all();
m_cells.remove_all();
}
//---------------------------------------------------------------
int add_cells(const T* cells, unsigned num_cells)
{
int idx = m_cells.allocate_continuous_block(num_cells);
if(idx >= 0)
{
T* ptr = &m_cells[idx];
memcpy(ptr, cells, sizeof(T) * num_cells);
return idx;
}
extra_span s;
s.len = num_cells;
s.ptr = new T [num_cells];
memcpy(s.ptr, cells, sizeof(T) * num_cells);
m_extra_storage.add(s);
return -int(m_extra_storage.size());
}
//---------------------------------------------------------------
const T* operator [] (int idx) const
{
if(idx >= 0)
{
if((unsigned)idx >= m_cells.size()) return 0;
return &m_cells[(unsigned)idx];
}
unsigned i = unsigned(-idx - 1);
if(i >= m_extra_storage.size()) return 0;
return m_extra_storage[i].ptr;
}
//---------------------------------------------------------------
T* operator [] (int idx)
{
if(idx >= 0)
{
if((unsigned)idx >= m_cells.size()) return 0;
return &m_cells[(unsigned)idx];
}
unsigned i = unsigned(-idx - 1);
if(i >= m_extra_storage.size()) return 0;
return m_extra_storage[i].ptr;
}
private:
void copy_extra_storage(const scanline_cell_storage<T>& v)
{
unsigned i;
for(i = 0; i < v.m_extra_storage.size(); ++i)
{
const extra_span& src = v.m_extra_storage[i];
extra_span dst;
dst.len = src.len;
dst.ptr = new T [dst.len];
memcpy(dst.ptr, src.ptr, dst.len * sizeof(T));
m_extra_storage.add(dst);
}
}
pod_deque<T, 12> m_cells;
pod_deque<extra_span, 6> m_extra_storage;
};
//-----------------------------------------------scanline_storage_aa
template<class T> class scanline_storage_aa
{
public:
typedef T cover_type;
//---------------------------------------------------------------
struct span_data
{
int16 x;
int16 len; // If negative, it's a solid span, covers is valid
int covers_id; // The index of the cells in the scanline_cell_storage
};
//---------------------------------------------------------------
struct scanline_data
{
int y;
unsigned num_spans;
unsigned start_span;
};
//---------------------------------------------------------------
class embedded_scanline
{
public:
//-----------------------------------------------------------
class const_iterator
{
public:
struct span
{
int16 x;
int16 len; // If negative, it's a solid span, covers is valid
const T* covers;
};
const_iterator(const embedded_scanline& sl) :
m_storage(sl.m_storage),
m_span_idx(sl.m_scanline.start_span)
{
init_span();
}
const span& operator*() const { return m_span; }
const span* operator->() const { return &m_span; }
void operator ++ ()
{
++m_span_idx;
init_span();
}
private:
void init_span()
{
const span_data& s = m_storage->span_by_index(m_span_idx);
m_span.x = s.x;
m_span.len = s.len;
m_span.covers = m_storage->covers_by_index(s.covers_id);
}
const scanline_storage_aa* m_storage;
unsigned m_span_idx;
span m_span;
};
friend class const_iterator;
//-----------------------------------------------------------
embedded_scanline(const scanline_storage_aa& storage) :
m_storage(&storage)
{
init(0);
}
//-----------------------------------------------------------
void reset(int, int) {}
unsigned num_spans() const { return m_scanline.num_spans; }
int y() const { return m_scanline.y; }
const_iterator begin() const { return const_iterator(*this); }
//-----------------------------------------------------------
void init(unsigned scanline_idx)
{
m_scanline_idx = scanline_idx;
m_scanline = m_storage->scanline_by_index(m_scanline_idx);
}
private:
const scanline_storage_aa* m_storage;
scanline_data m_scanline;
unsigned m_scanline_idx;
};
//---------------------------------------------------------------
scanline_storage_aa() :
m_covers(),
m_spans(256-2), // Block increment size
m_scanlines(),
m_min_x( 0x7FFFFFFF),
m_min_y( 0x7FFFFFFF),
m_max_x(-0x7FFFFFFF),
m_max_y(-0x7FFFFFFF),
m_cur_scanline(0)
{
m_fake_scanline.y = 0;
m_fake_scanline.num_spans = 0;
m_fake_scanline.start_span = 0;
m_fake_span.x = 0;
m_fake_span.len = 0;
m_fake_span.covers_id = 0;
}
// Renderer Interface
//---------------------------------------------------------------
void prepare(unsigned)
{
m_covers.remove_all();
m_scanlines.remove_all();
m_spans.remove_all();
m_min_x = 0x7FFFFFFF;
m_min_y = 0x7FFFFFFF;
m_max_x = -0x7FFFFFFF;
m_max_y = -0x7FFFFFFF;
m_cur_scanline = 0;
}
//---------------------------------------------------------------
template<class Scanline> void render(const Scanline& sl)
{
scanline_data sl_this;
int y = sl.y();
if(y < m_min_y) m_min_y = y;
if(y > m_max_y) m_max_y = y;
sl_this.y = y;
sl_this.num_spans = sl.num_spans();
sl_this.start_span = m_spans.size();
typename Scanline::const_iterator span_iterator = sl.begin();
unsigned num_spans = sl_this.num_spans;
do
{
span_data sp;
sp.x = span_iterator->x;
sp.len = span_iterator->len;
sp.covers_id =
m_covers.add_cells(span_iterator->covers,
unsigned(abs(int(sp.len))));
m_spans.add(sp);
int x1 = sp.x;
int x2 = sp.x + sp.len - 1;
if(x1 < m_min_x) m_min_x = x1;
if(x2 > m_max_x) m_max_x = x2;
++span_iterator;
}
while(--num_spans);
m_scanlines.add(sl_this);
}
//---------------------------------------------------------------
// Iterate scanlines interface
int min_x() const { return m_min_x; }
int min_y() const { return m_min_y; }
int max_x() const { return m_max_x; }
int max_y() const { return m_max_y; }
//---------------------------------------------------------------
bool rewind_scanlines()
{
m_cur_scanline = 0;
return m_scanlines.size() > 0;
}
//---------------------------------------------------------------
template<class Scanline> bool sweep_scanline(Scanline& sl)
{
sl.reset_spans();
for(;;)
{
if(m_cur_scanline >= m_scanlines.size()) return false;
const scanline_data& sl_this = m_scanlines[m_cur_scanline];
unsigned num_spans = sl_this.num_spans;
unsigned span_idx = sl_this.start_span;
do
{
const span_data& sp = m_spans[span_idx++];
const T* covers = covers_by_index(sp.covers_id);
if(sp.len < 0)
{
sl.add_span(sp.x, unsigned(-sp.len), *covers);
}
else
{
sl.add_cells(sp.x, sp.len, covers);
}
}
while(--num_spans);
++m_cur_scanline;
if(sl.num_spans())
{
sl.finalize(sl_this.y);
break;
}
}
return true;
}
//---------------------------------------------------------------
// Specialization for embedded_scanline
bool sweep_scanline(embedded_scanline& sl)
{
do
{
if(m_cur_scanline >= m_scanlines.size()) return false;
sl.init(m_cur_scanline);
++m_cur_scanline;
}
while(sl.num_spans() == 0);
return true;
}
//---------------------------------------------------------------
unsigned byte_size() const
{
unsigned i;
unsigned size = sizeof(int16) * 4; // min_x, min_y, max_x, max_y
for(i = 0; i < m_scanlines.size(); ++i)
{
size += sizeof(int16) * 3; // scanline size in bytes, Y, num_spans
const scanline_data& sl_this = m_scanlines[i];
unsigned num_spans = sl_this.num_spans;
unsigned span_idx = sl_this.start_span;
do
{
const span_data& sp = m_spans[span_idx++];
size += sizeof(int16) * 2; // X, span_len
if(sp.len < 0)
{
size += sizeof(T); // cover
}
else
{
size += sizeof(T) * unsigned(sp.len); // covers
}
}
while(--num_spans);
}
return size;
}
//---------------------------------------------------------------
static void write_int16(int8u* dst, int16 val)
{
dst[0] = ((const int8u*)&val)[0];
dst[1] = ((const int8u*)&val)[1];
}
//---------------------------------------------------------------
void serialize(int8u* data) const
{
unsigned i;
write_int16(data, int16u(min_x())); // min_x
data += sizeof(int16u);
write_int16(data, int16u(min_y())); // min_y
data += sizeof(int16u);
write_int16(data, int16u(max_x())); // max_x
data += sizeof(int16u);
write_int16(data, int16u(max_y())); // max_y
data += sizeof(int16u);
for(i = 0; i < m_scanlines.size(); ++i)
{
const scanline_data& sl_this = m_scanlines[i];
int8u* size_ptr = data;
data += sizeof(int16); // Reserve space for scanline size in bytes
write_int16(data, int16(sl_this.y)); // Y
data += sizeof(int16);
write_int16(data, int16(sl_this.num_spans)); // num_spans
data += sizeof(int16);
unsigned num_spans = sl_this.num_spans;
unsigned span_idx = sl_this.start_span;
do
{
const span_data& sp = m_spans[span_idx++];
const T* covers = covers_by_index(sp.covers_id);
write_int16(data, int16(sp.x)); // X
data += sizeof(int16);
write_int16(data, int16(sp.len)); // span_len
data += sizeof(int16);
if(sp.len < 0)
{
memcpy(data, covers, sizeof(T));
data += sizeof(T);
}
else
{
memcpy(data, covers, unsigned(sp.len) * sizeof(T));
data += sizeof(T) * unsigned(sp.len);
}
}
while(--num_spans);
write_int16(size_ptr, int16(unsigned(data - size_ptr)));
}
}
//---------------------------------------------------------------
const scanline_data& scanline_by_index(unsigned i) const
{
return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline;
}
//---------------------------------------------------------------
const span_data& span_by_index(unsigned i) const
{
return (i < m_spans.size()) ? m_spans[i] : m_fake_span;
}
//---------------------------------------------------------------
const T* covers_by_index(int i) const
{
return m_covers[i];
}
private:
scanline_cell_storage<T> m_covers;
pod_deque<span_data, 10> m_spans;
pod_deque<scanline_data, 8> m_scanlines;
span_data m_fake_span;
scanline_data m_fake_scanline;
int m_min_x;
int m_min_y;
int m_max_x;
int m_max_y;
unsigned m_cur_scanline;
};
typedef scanline_storage_aa<int8u> scanline_storage_aa8; //--------scanline_storage_aa8
typedef scanline_storage_aa<int16u> scanline_storage_aa16; //--------scanline_storage_aa16
typedef scanline_storage_aa<int32u> scanline_storage_aa32; //--------scanline_storage_aa32
//------------------------------------------serialized_scanlines_adaptor_aa
template<class T> class serialized_scanlines_adaptor_aa
{
public:
typedef T cover_type;
//---------------------------------------------------------------------
class embedded_scanline
{
public:
typedef T cover_type;
//-----------------------------------------------------------------
class const_iterator
{
public:
struct span
{
int16 x;
int16 len; // If negative, it's a solid span, "covers" is valid
const T* covers;
};
const_iterator(const embedded_scanline& sl) :
m_ptr(sl.m_ptr),
m_dx(sl.m_dx)
{
init_span();
}
const span& operator*() const { return m_span; }
const span* operator->() const { return &m_span; }
void operator ++ ()
{
if(m_span.len < 0)
{
m_ptr += sizeof(T);
}
else
{
m_ptr += m_span.len * sizeof(T);
}
init_span();
}
private:
int read_int16()
{
int16 val;
((int8u*)&val)[0] = *m_ptr++;
((int8u*)&val)[1] = *m_ptr++;
return val;
}
void init_span()
{
m_span.x = read_int16() + m_dx;
m_span.len = read_int16();
m_span.covers = m_ptr;
}
const int8u* m_ptr;
span m_span;
int m_dx;
};
friend class const_iterator;
//-----------------------------------------------------------------
embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
//-----------------------------------------------------------------
void reset(int, int) {}
unsigned num_spans() const { return m_num_spans; }
int y() const { return m_y; }
const_iterator begin() const { return const_iterator(*this); }
private:
//-----------------------------------------------------------------
int read_int16()
{
int16 val;
((int8u*)&val)[0] = *m_ptr++;
((int8u*)&val)[1] = *m_ptr++;
return val;
}
public:
//-----------------------------------------------------------------
void init(const int8u* ptr, int dx, int dy)
{
m_ptr = ptr;
m_y = read_int16() + dy;
m_num_spans = unsigned(read_int16());
m_dx = dx;
}
private:
const int8u* m_ptr;
int m_y;
unsigned m_num_spans;
int m_dx;
};
public:
//--------------------------------------------------------------------
serialized_scanlines_adaptor_aa() :
m_data(0),
m_end(0),
m_ptr(0),
m_dx(0),
m_dy(0),
m_min_x(0x7FFFFFFF),
m_min_y(0x7FFFFFFF),
m_max_x(-0x7FFFFFFF),
m_max_y(-0x7FFFFFFF)
{}
//--------------------------------------------------------------------
serialized_scanlines_adaptor_aa(const int8u* data, unsigned size,
double dx, double dy) :
m_data(data),
m_end(data + size),
m_ptr(data),
m_dx(int(floor(dx + 0.5))),
m_dy(int(floor(dy + 0.5))),
m_min_x(0x7FFFFFFF),
m_min_y(0x7FFFFFFF),
m_max_x(-0x7FFFFFFF),
m_max_y(-0x7FFFFFFF)
{}
//--------------------------------------------------------------------
void init(const int8u* data, unsigned size, double dx, double dy)
{
m_data = data;
m_end = data + size;
m_ptr = data;
m_dx = int(floor(dx + 0.5));
m_dy = int(floor(dy + 0.5));
m_min_x = 0x7FFFFFFF;
m_min_y = 0x7FFFFFFF;
m_max_x = -0x7FFFFFFF;
m_max_y = -0x7FFFFFFF;
}
private:
//--------------------------------------------------------------------
int read_int16()
{
int16 val;
((int8u*)&val)[0] = *m_ptr++;
((int8u*)&val)[1] = *m_ptr++;
return val;
}
//--------------------------------------------------------------------
unsigned read_int16u()
{
int16u val;
((int8u*)&val)[0] = *m_ptr++;
((int8u*)&val)[1] = *m_ptr++;
return val;
}
public:
// Iterate scanlines interface
//--------------------------------------------------------------------
bool rewind_scanlines()
{
m_ptr = m_data;
if(m_ptr < m_end)
{
m_min_x = read_int16() + m_dx;
m_min_y = read_int16() + m_dy;
m_max_x = read_int16() + m_dx;
m_max_y = read_int16() + m_dy;
return true;
}
return false;
}
//--------------------------------------------------------------------
int min_x() const { return m_min_x; }
int min_y() const { return m_min_y; }
int max_x() const { return m_max_x; }
int max_y() const { return m_max_y; }
//--------------------------------------------------------------------
template<class Scanline> bool sweep_scanline(Scanline& sl)
{
sl.reset_spans();
for(;;)
{
if(m_ptr >= m_end) return false;
read_int16(); // Skip scanline size in bytes
int y = read_int16() + m_dy;
unsigned num_spans = read_int16();
do
{
int x = read_int16() + m_dx;
int len = read_int16();
if(len < 0)
{
sl.add_span(x, unsigned(-len), *m_ptr);
m_ptr += sizeof(T);
}
else
{
sl.add_cells(x, len, m_ptr);
m_ptr += len * sizeof(T);
}
}
while(--num_spans);
if(sl.num_spans())
{
sl.finalize(y);
break;
}
}
return true;
}
//--------------------------------------------------------------------
// Specialization for embedded_scanline
bool sweep_scanline(embedded_scanline& sl)
{
do
{
if(m_ptr >= m_end) return false;
unsigned byte_size = read_int16u();
sl.init(m_ptr, m_dx, m_dy);
m_ptr += byte_size - sizeof(int16);
}
while(sl.num_spans() == 0);
return true;
}
private:
const int8u* m_data;
const int8u* m_end;
const int8u* m_ptr;
int m_dx;
int m_dy;
int m_min_x;
int m_min_y;
int m_max_x;
int m_max_y;
};
typedef serialized_scanlines_adaptor_aa<int8u> serialized_scanlines_adaptor_aa8; //----serialized_scanlines_adaptor_aa8
typedef serialized_scanlines_adaptor_aa<int16u> serialized_scanlines_adaptor_aa16; //----serialized_scanlines_adaptor_aa16
typedef serialized_scanlines_adaptor_aa<int32u> serialized_scanlines_adaptor_aa32; //----serialized_scanlines_adaptor_aa32
}
#endif
+579
View File
@@ -0,0 +1,579 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SCANLINE_STORAGE_BIN_INCLUDED
#define AGG_SCANLINE_STORAGE_BIN_INCLUDED
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "agg_array.h"
#include "agg_render_scanlines.h"
namespace agg
{
//-----------------------------------------------scanline_storage_bin
class scanline_storage_bin
{
public:
//---------------------------------------------------------------
struct span_data
{
int16 x;
int16 len;
};
//---------------------------------------------------------------
struct scanline_data
{
int y;
unsigned num_spans;
unsigned start_span;
};
//---------------------------------------------------------------
class embedded_scanline
{
public:
//-----------------------------------------------------------
class const_iterator
{
public:
const_iterator(const embedded_scanline& sl) :
m_storage(sl.m_storage),
m_span_idx(sl.m_scanline.start_span)
{
m_span = m_storage->span_by_index(m_span_idx);
}
const span_data& operator*() const { return m_span; }
const span_data* operator->() const { return &m_span; }
void operator ++ ()
{
++m_span_idx;
m_span = m_storage->span_by_index(m_span_idx);
}
private:
const scanline_storage_bin* m_storage;
unsigned m_span_idx;
span_data m_span;
};
friend class const_iterator;
//-----------------------------------------------------------
embedded_scanline(const scanline_storage_bin& storage) :
m_storage(&storage)
{
setup(0);
}
//-----------------------------------------------------------
void reset(int, int) {}
unsigned num_spans() const { return m_scanline.num_spans; }
int y() const { return m_scanline.y; }
const_iterator begin() const { return const_iterator(*this); }
//-----------------------------------------------------------
void setup(unsigned scanline_idx)
{
m_scanline_idx = scanline_idx;
m_scanline = m_storage->scanline_by_index(m_scanline_idx);
}
private:
const scanline_storage_bin* m_storage;
scanline_data m_scanline;
unsigned m_scanline_idx;
};
//---------------------------------------------------------------
scanline_storage_bin() :
m_spans(256-2), // Block increment size
m_scanlines(),
m_min_x( 0x7FFFFFFF),
m_min_y( 0x7FFFFFFF),
m_max_x(-0x7FFFFFFF),
m_max_y(-0x7FFFFFFF),
m_cur_scanline(0)
{
m_fake_scanline.y = 0;
m_fake_scanline.num_spans = 0;
m_fake_scanline.start_span = 0;
m_fake_span.x = 0;
m_fake_span.len = 0;
}
// Renderer Interface
//---------------------------------------------------------------
void prepare(unsigned)
{
m_scanlines.remove_all();
m_spans.remove_all();
m_min_x = 0x7FFFFFFF;
m_min_y = 0x7FFFFFFF;
m_max_x = -0x7FFFFFFF;
m_max_y = -0x7FFFFFFF;
m_cur_scanline = 0;
}
//---------------------------------------------------------------
template<class Scanline> void render(const Scanline& sl)
{
scanline_data sl_this;
int y = sl.y();
if(y < m_min_y) m_min_y = y;
if(y > m_max_y) m_max_y = y;
sl_this.y = y;
sl_this.num_spans = sl.num_spans();
sl_this.start_span = m_spans.size();
typename Scanline::const_iterator span_iterator = sl.begin();
unsigned num_spans = sl_this.num_spans;
do
{
span_data sp;
sp.x = span_iterator->x;
sp.len = (int16)abs((int)(span_iterator->len));
m_spans.add(sp);
int x1 = sp.x;
int x2 = sp.x + sp.len - 1;
if(x1 < m_min_x) m_min_x = x1;
if(x2 > m_max_x) m_max_x = x2;
++span_iterator;
}
while(--num_spans);
m_scanlines.add(sl_this);
}
//---------------------------------------------------------------
// Iterate scanlines interface
int min_x() const { return m_min_x; }
int min_y() const { return m_min_y; }
int max_x() const { return m_max_x; }
int max_y() const { return m_max_y; }
//---------------------------------------------------------------
bool rewind_scanlines()
{
m_cur_scanline = 0;
return m_scanlines.size() > 0;
}
//---------------------------------------------------------------
template<class Scanline> bool sweep_scanline(Scanline& sl)
{
sl.reset_spans();
for(;;)
{
if(m_cur_scanline >= m_scanlines.size()) return false;
const scanline_data& sl_this = m_scanlines[m_cur_scanline];
unsigned num_spans = sl_this.num_spans;
unsigned span_idx = sl_this.start_span;
do
{
const span_data& sp = m_spans[span_idx++];
sl.add_span(sp.x, sp.len, cover_full);
}
while(--num_spans);
++m_cur_scanline;
if(sl.num_spans())
{
sl.finalize(sl_this.y);
break;
}
}
return true;
}
//---------------------------------------------------------------
// Specialization for embedded_scanline
bool sweep_scanline(embedded_scanline& sl)
{
do
{
if(m_cur_scanline >= m_scanlines.size()) return false;
sl.setup(m_cur_scanline);
++m_cur_scanline;
}
while(sl.num_spans() == 0);
return true;
}
//---------------------------------------------------------------
unsigned byte_size() const
{
unsigned i;
unsigned size = sizeof(int16) * 4; // min_x, min_y, max_x, max_y
for(i = 0; i < m_scanlines.size(); ++i)
{
size += sizeof(int16) * 2; // Y, num_spans
const scanline_data& sl_this = m_scanlines[i];
unsigned num_spans = sl_this.num_spans;
unsigned span_idx = sl_this.start_span;
do
{
const span_data& sp = m_spans[span_idx++];
size += sizeof(int16) * 2; // X, span_len
}
while(--num_spans);
}
return size;
}
//---------------------------------------------------------------
static void write_int16(int8u* dst, int16 val)
{
dst[0] = ((const int8u*)&val)[0];
dst[1] = ((const int8u*)&val)[1];
}
//---------------------------------------------------------------
void serialize(int8u* data) const
{
unsigned i;
write_int16(data, int16u(min_x())); // min_x
data += sizeof(int16u);
write_int16(data, int16u(min_y())); // min_y
data += sizeof(int16u);
write_int16(data, int16u(max_x())); // max_x
data += sizeof(int16u);
write_int16(data, int16u(max_y())); // max_y
data += sizeof(int16u);
for(i = 0; i < m_scanlines.size(); ++i)
{
const scanline_data& sl_this = m_scanlines[i];
write_int16(data, int16(sl_this.y)); // Y
data += sizeof(int16);
write_int16(data, int16(sl_this.num_spans)); // num_spans
data += sizeof(int16);
unsigned num_spans = sl_this.num_spans;
unsigned span_idx = sl_this.start_span;
do
{
const span_data& sp = m_spans[span_idx++];
write_int16(data, int16(sp.x)); // X
data += sizeof(int16);
write_int16(data, int16(sp.len)); // len
data += sizeof(int16);
}
while(--num_spans);
}
}
//---------------------------------------------------------------
const scanline_data& scanline_by_index(unsigned i) const
{
return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline;
}
//---------------------------------------------------------------
const span_data& span_by_index(unsigned i) const
{
return (i < m_spans.size()) ? m_spans[i] : m_fake_span;
}
private:
pod_deque<span_data, 10> m_spans;
pod_deque<scanline_data, 8> m_scanlines;
span_data m_fake_span;
scanline_data m_fake_scanline;
int m_min_x;
int m_min_y;
int m_max_x;
int m_max_y;
unsigned m_cur_scanline;
};
//---------------------------------------serialized_scanlines_adaptor_bin
class serialized_scanlines_adaptor_bin
{
public:
typedef bool cover_type;
//--------------------------------------------------------------------
class embedded_scanline
{
public:
//----------------------------------------------------------------
class const_iterator
{
public:
struct span
{
int16 x;
int16 len;
};
const_iterator(const embedded_scanline& sl) :
m_ptr(sl.m_ptr),
m_dx(sl.m_dx)
{
m_span.x = read_int16() + m_dx;
m_span.len = read_int16();
}
const span& operator*() const { return m_span; }
const span* operator->() const { return &m_span; }
void operator ++ ()
{
m_span.x = read_int16() + m_dx;
m_span.len = read_int16();
}
private:
int read_int16()
{
int16 val;
((int8u*)&val)[0] = *m_ptr++;
((int8u*)&val)[1] = *m_ptr++;
return val;
}
const int8u* m_ptr;
span m_span;
int m_dx;
};
friend class const_iterator;
//----------------------------------------------------------------
embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
//----------------------------------------------------------------
void reset(int, int) {}
unsigned num_spans() const { return m_num_spans; }
int y() const { return m_y; }
const_iterator begin() const { return const_iterator(*this); }
private:
//----------------------------------------------------------------
int read_int16()
{
int16 val;
((int8u*)&val)[0] = *m_ptr++;
((int8u*)&val)[1] = *m_ptr++;
return val;
}
public:
//----------------------------------------------------------------
void init(const int8u* ptr, int dx, int dy)
{
m_ptr = ptr;
m_y = read_int16() + dy;
m_num_spans = unsigned(read_int16());
m_dx = dx;
}
private:
const int8u* m_ptr;
int m_y;
unsigned m_num_spans;
int m_dx;
};
public:
//--------------------------------------------------------------------
serialized_scanlines_adaptor_bin() :
m_data(0),
m_end(0),
m_ptr(0),
m_dx(0),
m_dy(0),
m_min_x(0x7FFFFFFF),
m_min_y(0x7FFFFFFF),
m_max_x(-0x7FFFFFFF),
m_max_y(-0x7FFFFFFF)
{}
//--------------------------------------------------------------------
serialized_scanlines_adaptor_bin(const int8u* data, unsigned size,
double dx, double dy) :
m_data(data),
m_end(data + size),
m_ptr(data),
m_dx(int(floor(dx + 0.5))),
m_dy(int(floor(dy + 0.5))),
m_min_x(0x7FFFFFFF),
m_min_y(0x7FFFFFFF),
m_max_x(-0x7FFFFFFF),
m_max_y(-0x7FFFFFFF)
{}
//--------------------------------------------------------------------
void init(const int8u* data, unsigned size, double dx, double dy)
{
m_data = data;
m_end = data + size;
m_ptr = data;
m_dx = int(floor(dx + 0.5));
m_dy = int(floor(dy + 0.5));
m_min_x = 0x7FFFFFFF;
m_min_y = 0x7FFFFFFF;
m_max_x = -0x7FFFFFFF;
m_max_y = -0x7FFFFFFF;
}
private:
//--------------------------------------------------------------------
int read_int16()
{
int16 val;
((int8u*)&val)[0] = *m_ptr++;
((int8u*)&val)[1] = *m_ptr++;
return val;
}
public:
// Iterate scanlines interface
//--------------------------------------------------------------------
bool rewind_scanlines()
{
m_ptr = m_data;
if(m_ptr < m_end)
{
m_min_x = read_int16() + m_dx;
m_min_y = read_int16() + m_dy;
m_max_x = read_int16() + m_dx;
m_max_y = read_int16() + m_dy;
return true;
}
return false;
}
//--------------------------------------------------------------------
int min_x() const { return m_min_x; }
int min_y() const { return m_min_y; }
int max_x() const { return m_max_x; }
int max_y() const { return m_max_y; }
//--------------------------------------------------------------------
template<class Scanline> bool sweep_scanline(Scanline& sl)
{
sl.reset_spans();
for(;;)
{
if(m_ptr >= m_end) return false;
int y = read_int16() + m_dy;
unsigned num_spans = read_int16();
do
{
int x = read_int16() + m_dx;
int len = read_int16();
if(len < 0) len = -len;
sl.add_span(x, unsigned(len), cover_full);
}
while(--num_spans);
if(sl.num_spans())
{
sl.finalize(y);
break;
}
}
return true;
}
//--------------------------------------------------------------------
// Specialization for embedded_scanline
bool sweep_scanline(embedded_scanline& sl)
{
do
{
if(m_ptr >= m_end) return false;
sl.init(m_ptr, m_dx, m_dy);
// Jump to the next scanline
//--------------------------
read_int16(); // Y
int num_spans = read_int16(); // num_spans
m_ptr += num_spans * sizeof(int16) * 2;
}
while(sl.num_spans() == 0);
return true;
}
private:
const int8u* m_data;
const int8u* m_end;
const int8u* m_ptr;
int m_dx;
int m_dy;
int m_min_x;
int m_min_y;
int m_max_x;
int m_max_y;
};
}
#endif
+323
View File
@@ -0,0 +1,323 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SCANLINE_U_INCLUDED
#define AGG_SCANLINE_U_INCLUDED
#include <string.h>
#include "agg_basics.h"
namespace agg
{
//==============================================================scanline_u
//
// Unpacked scanline container class
//
// This class is used to transfer data from a scanline rastyerizer
// to the rendering buffer. It's organized very simple. The class stores
// information of horizontal spans to render it into a pixel-map buffer.
// Each span has staring X, length, and an array of bytes that determine the
// cover-values for each pixel.
// Before using this class you should know the minimal and maximal pixel
// coordinates of your scanline. The protocol of using is:
// 1. reset(min_x, max_x)
// 2. add_cell() / add_span() - accumulate scanline.
// When forming one scanline the next X coordinate must be always greater
// than the last stored one, i.e. it works only with ordered coordinates.
// 3. Call finalize(y) and render the scanline.
// 3. Call reset_spans() to prepare for the new scanline.
//
// 4. Rendering:
//
// Scanline provides an iterator class that allows you to extract
// the spans and the cover values for each pixel. Be aware that clipping
// has not been done yet, so you should perform it yourself.
// Use scanline_u8::iterator to render spans:
//-------------------------------------------------------------------------
//
// int y = sl.y(); // Y-coordinate of the scanline
//
// ************************************
// ...Perform vertical clipping here...
// ************************************
//
// scanline_u8::const_iterator span = sl.begin();
//
// unsigned char* row = m_rbuf->row(y); // The the address of the beginning
// // of the current row
//
// unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
// // num_spans is always greater than 0.
//
// do
// {
// const scanline_u8::cover_type* covers =
// span->covers; // The array of the cover values
//
// int num_pix = span->len; // Number of pixels of the span.
// // Always greater than 0, still it's
// // better to use "int" instead of
// // "unsigned" because it's more
// // convenient for clipping
// int x = span->x;
//
// **************************************
// ...Perform horizontal clipping here...
// ...you have x, covers, and pix_count..
// **************************************
//
// unsigned char* dst = row + x; // Calculate the start address of the row.
// // In this case we assume a simple
// // grayscale image 1-byte per pixel.
// do
// {
// *dst++ = *covers++; // Hypotetical rendering.
// }
// while(--num_pix);
//
// ++span;
// }
// while(--num_spans); // num_spans cannot be 0, so this loop is quite safe
//------------------------------------------------------------------------
//
// The question is: why should we accumulate the whole scanline when we
// could render just separate spans when they're ready?
// That's because using the scaline is generally faster. When is consists
// of more than one span the conditions for the processor cash system
// are better, because switching between two different areas of memory
// (that can be very large) occures less frequently.
//------------------------------------------------------------------------
template<class T> class scanline_u
{
public:
typedef T cover_type;
//--------------------------------------------------------------------
struct span
{
int16 x;
int16 len;
cover_type* covers;
};
typedef span* iterator;
typedef const span* const_iterator;
//--------------------------------------------------------------------
~scanline_u();
scanline_u();
void reset(int min_x, int max_x);
void add_cell(int x, unsigned cover);
void add_cells(int x, unsigned len, const T* covers);
void add_span(int x, unsigned len, unsigned cover);
void finalize(int y) { m_y = y; }
void reset_spans();
int y() const { return m_y; }
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
const_iterator begin() const { return m_spans + 1; }
iterator begin() { return m_spans + 1; }
private:
scanline_u<T>(const scanline_u<T>&);
const scanline_u<T>& operator = (const scanline_u<T>&);
private:
int m_min_x;
unsigned m_max_len;
int m_last_x;
int m_y;
cover_type* m_covers;
span* m_spans;
span* m_cur_span;
};
//------------------------------------------------------------------------
template<class T> scanline_u<T>::~scanline_u()
{
delete [] m_spans;
delete [] m_covers;
}
//------------------------------------------------------------------------
template<class T> scanline_u<T>::scanline_u() :
m_min_x(0),
m_max_len(0),
m_last_x(0x7FFFFFF0),
m_covers(0),
m_spans(0),
m_cur_span(0)
{
}
//------------------------------------------------------------------------
template<class T> void scanline_u<T>::reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 2;
if(max_len > m_max_len)
{
delete [] m_spans;
delete [] m_covers;
m_covers = new cover_type [max_len];
m_spans = new span [max_len];
m_max_len = max_len;
}
m_last_x = 0x7FFFFFF0;
m_min_x = min_x;
m_cur_span = m_spans;
}
//------------------------------------------------------------------------
template<class T> inline void scanline_u<T>::reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cur_span = m_spans;
}
//------------------------------------------------------------------------
template<class T> inline void scanline_u<T>::add_cell(int x, unsigned cover)
{
x -= m_min_x;
m_covers[x] = (unsigned char)cover;
if(x == m_last_x+1)
{
m_cur_span->len++;
}
else
{
m_cur_span++;
m_cur_span->x = (int16)(x + m_min_x);
m_cur_span->len = 1;
m_cur_span->covers = m_covers + x;
}
m_last_x = x;
}
//------------------------------------------------------------------------
template<class T> void scanline_u<T>::add_cells(int x, unsigned len, const T* covers)
{
x -= m_min_x;
memcpy(m_covers + x, covers, len * sizeof(T));
if(x == m_last_x+1)
{
m_cur_span->len += (int16)len;
}
else
{
m_cur_span++;
m_cur_span->x = (int16)(x + m_min_x);
m_cur_span->len = (int16)len;
m_cur_span->covers = m_covers + x;
}
m_last_x = x + len - 1;
}
//------------------------------------------------------------------------
template<class T> void scanline_u<T>::add_span(int x, unsigned len, unsigned cover)
{
x -= m_min_x;
memset(m_covers + x, cover, len);
if(x == m_last_x+1)
{
m_cur_span->len += (int16)len;
}
else
{
m_cur_span++;
m_cur_span->x = (int16)(x + m_min_x);
m_cur_span->len = (int16)len;
m_cur_span->covers = m_covers + x;
}
m_last_x = x + len - 1;
}
//=============================================================scanline_u8
typedef scanline_u<int8u> scanline_u8;
//============================================================scanline_u16
typedef scanline_u<int16u> scanline_u16;
//============================================================scanline_u32
typedef scanline_u<int32u> scanline_u32;
//=============================================================scanline_am
//
// The scanline container with alpha-masking
//
//------------------------------------------------------------------------
template<class AlphaMask, class CoverT>
class scanline_am : public scanline_u<CoverT>
{
public:
typedef AlphaMask alpha_mask_type;
typedef CoverT cover_type;
typedef scanline_u<CoverT> scanline_type;
scanline_am() : scanline_type(), m_alpha_mask(0) {}
scanline_am(const AlphaMask& am) : scanline_type(), m_alpha_mask(&am) {}
//--------------------------------------------------------------------
void finalize(int span_y)
{
scanline_u<CoverT>::finalize(span_y);
if(m_alpha_mask)
{
typename scanline_type::iterator span = scanline_type::begin();
unsigned count = scanline_type::num_spans();
do
{
m_alpha_mask->combine_hspan(span->x,
scanline_type::y(),
span->covers,
span->len);
++span;
}
while(--count);
}
}
private:
const AlphaMask* m_alpha_mask;
};
//==========================================================scanline_u8_am
template<class AlphaMask>
class scanline_u8_am : public scanline_am<AlphaMask, int8u>
{
public:
typedef AlphaMask alpha_mask_type;
typedef int8u cover_type;
typedef scanline_am<alpha_mask_type, cover_type> self_type;
scanline_u8_am() : self_type() {}
scanline_u8_am(const AlphaMask& am) : self_type(am) {}
};
}
#endif
+66
View File
@@ -0,0 +1,66 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SHORTEN_PATH_INCLUDED
#define AGG_SHORTEN_PATH_INCLUDED
#include "agg_basics.h"
#include "agg_vertex_sequence.h"
namespace agg
{
//===========================================================shorten_path
template<class VertexSequence>
void shorten_path(VertexSequence& vs, double s, unsigned closed = 0)
{
typedef typename VertexSequence::value_type vertex_type;
if(s > 0.0 && vs.size() > 1)
{
double d;
int n = int(vs.size() - 2);
while(n)
{
d = vs[n].dist;
if(d > s) break;
vs.remove_last();
s -= d;
--n;
}
if(vs.size() < 2)
{
vs.remove_all();
}
else
{
n = vs.size() - 1;
vertex_type& prev = vs[n-1];
vertex_type& last = vs[n];
d = (prev.dist - s) / prev.dist;
double x = prev.x + (last.x - prev.x) * d;
double y = prev.y + (last.y - prev.y) * d;
last.x = x;
last.y = y;
if(!prev(last)) vs.remove_last();
vs.close(closed != 0);
}
}
}
}
#endif
+147
View File
@@ -0,0 +1,147 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Solving simultaneous equations
//
//----------------------------------------------------------------------------
#ifndef AGG_SIMUL_EQ_INCLUDED
#define AGG_SIMUL_EQ_INCLUDED
#include <math.h>
#include "agg_basics.h"
namespace agg
{
//=============================================================swap_arrays
template<class T> void swap_arrays(T* a1, T* a2, unsigned n)
{
unsigned i;
for(i = 0; i < n; i++)
{
T tmp = *a1;
*a1++ = *a2;
*a2++ = tmp;
}
}
//============================================================matrix_pivot
template<unsigned Rows, unsigned Cols>
struct matrix_pivot
{
static int pivot(double m[Rows][Cols], unsigned row)
{
int k = int(row);
double max_val, tmp;
max_val = -1.0;
unsigned i;
for(i = row; i < Rows; i++)
{
if((tmp = fabs(m[i][row])) > max_val && tmp != 0.0)
{
max_val = tmp;
k = i;
}
}
if(m[k][row] == 0.0)
{
return -1;
}
if(k != int(row))
{
swap_arrays(m[k], m[row], Cols);
return k;
}
return 0;
}
};
//===============================================================simul_eq
template<unsigned Size, unsigned RightCols>
struct simul_eq
{
static bool solve(const double left[Size][Size],
const double right[Size][RightCols],
double result[Size][RightCols])
{
unsigned i, j, k;
double a1;
double tmp[Size][Size + RightCols];
for(i = 0; i < Size; i++)
{
for(j = 0; j < Size; j++)
{
tmp[i][j] = left[i][j];
}
for(j = 0; j < RightCols; j++)
{
tmp[i][Size + j] = right[i][j];
}
}
for(k = 0; k < Size; k++)
{
if(matrix_pivot<Size, Size + RightCols>::pivot(tmp, k) < 0)
{
return false; // Singularity....
}
a1 = tmp[k][k];
for(j = k; j < Size + RightCols; j++)
{
tmp[k][j] /= a1;
}
for(i = k + 1; i < Size; i++)
{
a1 = tmp[i][k];
for (j = k; j < Size + RightCols; j++)
{
tmp[i][j] -= a1 * tmp[k][j];
}
}
}
for(k = 0; k < RightCols; k++)
{
int m;
for(m = int(Size - 1); m >= 0; m--)
{
result[m][k] = tmp[m][Size + k];
for(j = m + 1; j < Size; j++)
{
result[m][k] -= tmp[m][j] * result[j][k];
}
}
}
return true;
}
};
}
#endif
+72
View File
@@ -0,0 +1,72 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_ALLOCATOR_INCLUDED
#define AGG_SPAN_ALLOCATOR_INCLUDED
#include "agg_basics.h"
namespace agg
{
//----------------------------------------------------------span_allocator
template<class ColorT> class span_allocator
{
public:
typedef ColorT color_type;
//--------------------------------------------------------------------
~span_allocator()
{
delete [] m_span;
}
//--------------------------------------------------------------------
span_allocator() :
m_max_span_len(0),
m_span(0)
{
}
//--------------------------------------------------------------------
color_type* allocate(unsigned max_span_len)
{
if(max_span_len > m_max_span_len)
{
delete [] m_span;
m_span = new color_type[m_max_span_len = max_span_len];
}
return m_span;
}
//--------------------------------------------------------------------
color_type* span()
{
return m_span;
}
private:
//--------------------------------------------------------------------
span_allocator(const span_allocator<ColorT>&);
const span_allocator<ColorT>& operator = (const span_allocator<ColorT>&);
unsigned m_max_span_len;
color_type* m_span;
};
}
#endif
+53
View File
@@ -0,0 +1,53 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_CONVERTER_INCLUDED
#define AGG_SPAN_CONVERTER_INCLUDED
#include "agg_basics.h"
namespace agg
{
//----------------------------------------------------------span_converter
template<class SpanGenerator, class Conv> class span_converter
{
public:
typedef typename SpanGenerator::color_type color_type;
span_converter(SpanGenerator& span_gen, Conv& conv) :
m_span_gen(&span_gen), m_conv(&conv) {}
//--------------------------------------------------------------------
void prepare(unsigned max_span_len)
{
m_span_gen->prepare(max_span_len);
}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
color_type* span = m_span_gen->generate(x, y, len);
m_conv->convert(span, len);
return span;
}
private:
SpanGenerator* m_span_gen;
Conv* m_conv;
};
}
#endif
+50
View File
@@ -0,0 +1,50 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_GENERATOR_INCLUDED
#define AGG_SPAN_GENERATOR_INCLUDED
#include "agg_basics.h"
#include "agg_span_allocator.h"
namespace agg
{
//==========================================================span_generator
template<class ColorT, class Allocator> class span_generator
{
public:
typedef ColorT color_type;
typedef Allocator alloc_type;
//--------------------------------------------------------------------
span_generator(alloc_type& alloc) : m_alloc(&alloc) {}
//--------------------------------------------------------------------
void allocator(alloc_type& alloc) { m_alloc = &alloc; }
alloc_type& allocator() { return *m_alloc; }
//--------------------------------------------------------------------
void prepare(unsigned max_span_len)
{
m_alloc->allocate(max_span_len);
}
private:
alloc_type* m_alloc;
};
}
#endif
+180
View File
@@ -0,0 +1,180 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_GOURAUD_INCLUDED
#define AGG_SPAN_GOURAUD_INCLUDED
#include "agg_basics.h"
#include "agg_math.h"
#include "agg_span_generator.h"
namespace agg
{
//============================================================span_gouraud
template<class ColorT, class Allocator>
class span_gouraud : public span_generator<ColorT, Allocator>
{
public:
typedef ColorT color_type;
typedef Allocator alloc_type;
struct coord_type
{
double x;
double y;
color_type color;
};
//--------------------------------------------------------------------
span_gouraud(alloc_type& alloc) :
span_generator<color_type, alloc_type>(alloc),
m_vertex(0)
{
m_cmd[0] = path_cmd_stop;
}
//--------------------------------------------------------------------
span_gouraud(alloc_type& alloc,
const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1, double y1,
double x2, double y2,
double x3, double y3,
double d) :
span_generator<color_type, alloc_type>(alloc)
{
colors(c1, c2, c3);
triangle(x1, y1, x2, y2, x3, y3, d);
}
//--------------------------------------------------------------------
void colors(ColorT c1, ColorT c2, ColorT c3)
{
m_coord[0].color = c1;
m_coord[1].color = c2;
m_coord[2].color = c3;
}
//--------------------------------------------------------------------
// Sets the triangle and dilates it if needed.
// The trick here is to calculate beveled joins in the vertices of the
// triangle and render it as a 6-vertex polygon.
// It's necessary to achieve numerical stability.
// However, the coordinates to interpolate colors are calculated
// as miter joins (calc_intersection).
void triangle(double x1, double y1,
double x2, double y2,
double x3, double y3,
double d)
{
m_coord[0].x = m_x[0] = x1;
m_coord[0].y = m_y[0] = y1;
m_coord[1].x = m_x[1] = x2;
m_coord[1].y = m_y[1] = y2;
m_coord[2].x = m_x[2] = x3;
m_coord[2].y = m_y[2] = y3;
m_cmd[0] = path_cmd_move_to;
m_cmd[1] = path_cmd_line_to;
m_cmd[2] = path_cmd_line_to;
m_cmd[3] = path_cmd_stop;
if(d != 0.0)
{
dilate_triangle(m_coord[0].x, m_coord[0].y,
m_coord[1].x, m_coord[1].y,
m_coord[2].x, m_coord[2].y,
m_x, m_y, d);
calc_intersection(m_x[4], m_y[4], m_x[5], m_y[5],
m_x[0], m_y[0], m_x[1], m_y[1],
&m_coord[0].x, &m_coord[0].y);
calc_intersection(m_x[0], m_y[0], m_x[1], m_y[1],
m_x[2], m_y[2], m_x[3], m_y[3],
&m_coord[1].x, &m_coord[1].y);
calc_intersection(m_x[2], m_y[2], m_x[3], m_y[3],
m_x[4], m_y[4], m_x[5], m_y[5],
&m_coord[2].x, &m_coord[2].y);
m_cmd[3] = path_cmd_line_to;
m_cmd[4] = path_cmd_line_to;
m_cmd[5] = path_cmd_line_to;
m_cmd[6] = path_cmd_stop;
}
}
//--------------------------------------------------------------------
// Vertex Source Interface to feed the coordinates to the rasterizer
void rewind(unsigned)
{
m_vertex = 0;
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
*x = m_x[m_vertex];
*y = m_y[m_vertex];
return m_cmd[m_vertex++];
}
protected:
//--------------------------------------------------------------------
void arrange_vertices(coord_type* coord) const
{
coord[0] = m_coord[0];
coord[1] = m_coord[1];
coord[2] = m_coord[2];
if(m_coord[0].y > m_coord[2].y)
{
coord[0] = m_coord[2];
coord[2] = m_coord[0];
}
coord_type tmp;
if(coord[0].y > coord[1].y)
{
tmp = coord[1];
coord[1] = coord[0];
coord[0] = tmp;
}
if(coord[1].y > coord[2].y)
{
tmp = coord[2];
coord[2] = coord[1];
coord[1] = tmp;
}
}
private:
//--------------------------------------------------------------------
coord_type m_coord[3];
double m_x[8];
double m_y[8];
unsigned m_cmd[8];
unsigned m_vertex;
};
}
#endif
+176
View File
@@ -0,0 +1,176 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_GOURAUD_GRAY8_INCLUDED
#define AGG_SPAN_GOURAUD_GRAY8_INCLUDED
#include "agg_basics.h"
#include "agg_gray8.h"
#include "agg_dda_line.h"
#include "agg_span_gouraud.h"
namespace agg
{
//======================================================span_gouraud_gray8
template<class Allocator = span_allocator<gray8> >
class span_gouraud_gray8 : public span_gouraud<gray8, Allocator>
{
public:
typedef Allocator alloc_type;
typedef gray8 color_type;
typedef span_gouraud<color_type, alloc_type> base_type;
typedef typename base_type::coord_type coord_type;
private:
//--------------------------------------------------------------------
struct gray_calc
{
void init(const coord_type& c1, const coord_type& c2)
{
m_x1 = c1.x;
m_y1 = c1.y;
m_dx = c2.x - c1.x;
m_dy = 1.0 / (c2.y - c1.y);
m_v1 = c1.color.v;
m_a1 = c1.color.a;
m_dv = c2.color.v - m_v1;
m_da = c2.color.a - m_a1;
}
void calc(int y)
{
double k = 0.0;
if(y > m_y1) k = (y - m_y1) * m_dy;
gray8 c;
m_v = m_v1 + int(m_dv * k);
m_a = m_a1 + int(m_da * k);
m_x = int(m_x1 + m_dx * k);
}
double m_x1;
double m_y1;
double m_dx;
double m_dy;
int m_v1;
int m_a1;
int m_dv;
int m_da;
int m_v;
int m_a;
int m_x;
};
public:
//--------------------------------------------------------------------
span_gouraud_gray8(alloc_type& alloc) : base_type(alloc) {}
//--------------------------------------------------------------------
span_gouraud_gray8(alloc_type& alloc,
const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1, double y1,
double x2, double y2,
double x3, double y3,
double d = 0) :
base_type(alloc, c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
{}
//--------------------------------------------------------------------
void prepare(unsigned max_span_len)
{
base_type::prepare(max_span_len);
coord_type coord[3];
arrange_vertices(coord);
m_y2 = int(coord[1].y);
m_swap = calc_point_location(coord[0].x, coord[0].y,
coord[2].x, coord[2].y,
coord[1].x, coord[1].y) < 0.0;
m_c1.init(coord[0], coord[2]);
m_c2.init(coord[0], coord[1]);
m_c3.init(coord[1], coord[2]);
}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
m_c1.calc(y);
const gray_calc* pc1 = &m_c1;
const gray_calc* pc2 = &m_c2;
if(y < m_y2)
{
m_c2.calc(y+1);
}
else
{
m_c3.calc(y);
pc2 = &m_c3;
}
if(m_swap)
{
const gray_calc* t = pc2;
pc2 = pc1;
pc1 = t;
}
int nx = pc1->m_x;
unsigned nlen = pc2->m_x - pc1->m_x + 1;
if(nlen < len) nlen = len;
dda_line_interpolator<16> v(pc1->m_v, pc2->m_v, nlen);
dda_line_interpolator<16> a(pc1->m_a, pc2->m_a, nlen);
if(nx < x)
{
unsigned d = unsigned(x - nx);
v += d;
a += d;
}
color_type* span = base_type::allocator().span();
do
{
span->v = v.y();
span->a = a.y();
++v;
++a;
++span;
}
while(--len);
return base_type::allocator().span();
}
private:
bool m_swap;
int m_y2;
gray_calc m_c1;
gray_calc m_c2;
gray_calc m_c3;
};
}
#endif
+197
View File
@@ -0,0 +1,197 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_GOURAUD_RGBA8_INCLUDED
#define AGG_SPAN_GOURAUD_RGBA8_INCLUDED
#include "agg_basics.h"
#include "agg_color_rgba8.h"
#include "agg_dda_line.h"
#include "agg_span_gouraud.h"
namespace agg
{
//======================================================span_gouraud_rgba8
template<class Allocator = span_allocator<rgba8> >
class span_gouraud_rgba8 : public span_gouraud<rgba8, Allocator>
{
public:
typedef Allocator alloc_type;
typedef rgba8 color_type;
typedef span_gouraud<color_type, alloc_type> base_type;
typedef typename base_type::coord_type coord_type;
private:
//--------------------------------------------------------------------
struct rgba_calc
{
void init(const coord_type& c1, const coord_type& c2)
{
m_x1 = c1.x;
m_y1 = c1.y;
m_dx = c2.x - c1.x;
m_dy = 1.0 / (c2.y - c1.y);
m_r1 = c1.color.r;
m_g1 = c1.color.g;
m_b1 = c1.color.b;
m_a1 = c1.color.a;
m_dr = c2.color.r - m_r1;
m_dg = c2.color.g - m_g1;
m_db = c2.color.b - m_b1;
m_da = c2.color.a - m_a1;
}
void calc(int y)
{
double k = 0.0;
if(y > m_y1) k = (y - m_y1) * m_dy;
rgba8 rgba;
m_r = m_r1 + int(m_dr * k);
m_g = m_g1 + int(m_dg * k);
m_b = m_b1 + int(m_db * k);
m_a = m_a1 + int(m_da * k);
m_x = int(m_x1 + m_dx * k);
}
double m_x1;
double m_y1;
double m_dx;
double m_dy;
int m_r1;
int m_g1;
int m_b1;
int m_a1;
int m_dr;
int m_dg;
int m_db;
int m_da;
int m_r;
int m_g;
int m_b;
int m_a;
int m_x;
};
public:
//--------------------------------------------------------------------
span_gouraud_rgba8(alloc_type& alloc) : base_type(alloc) {}
//--------------------------------------------------------------------
span_gouraud_rgba8(alloc_type& alloc,
const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1, double y1,
double x2, double y2,
double x3, double y3,
double d = 0) :
base_type(alloc, c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
{}
//--------------------------------------------------------------------
void prepare(unsigned max_span_len)
{
base_type::prepare(max_span_len);
coord_type coord[3];
arrange_vertices(coord);
m_y2 = int(coord[1].y);
m_swap = calc_point_location(coord[0].x, coord[0].y,
coord[2].x, coord[2].y,
coord[1].x, coord[1].y) < 0.0;
m_rgba1.init(coord[0], coord[2]);
m_rgba2.init(coord[0], coord[1]);
m_rgba3.init(coord[1], coord[2]);
}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
m_rgba1.calc(y);
const rgba_calc* pc1 = &m_rgba1;
const rgba_calc* pc2 = &m_rgba2;
if(y < m_y2)
{
m_rgba2.calc(y+1);
}
else
{
m_rgba3.calc(y);
pc2 = &m_rgba3;
}
if(m_swap)
{
const rgba_calc* t = pc2;
pc2 = pc1;
pc1 = t;
}
int nx = pc1->m_x;
unsigned nlen = pc2->m_x - pc1->m_x + 1;
if(nlen < len) nlen = len;
dda_line_interpolator<16> r(pc1->m_r, pc2->m_r, nlen);
dda_line_interpolator<16> g(pc1->m_g, pc2->m_g, nlen);
dda_line_interpolator<16> b(pc1->m_b, pc2->m_b, nlen);
dda_line_interpolator<16> a(pc1->m_a, pc2->m_a, nlen);
if(nx < x)
{
unsigned d = unsigned(x - nx);
r += d;
g += d;
b += d;
a += d;
}
color_type* span = base_type::allocator().span();
do
{
span->r = (int8u)r.y();
span->g = (int8u)g.y();
span->b = (int8u)b.y();
span->a = (int8u)a.y();
++r;
++g;
++b;
++a;
++span;
}
while(--len);
return base_type::allocator().span();
}
private:
bool m_swap;
int m_y2;
rgba_calc m_rgba1;
rgba_calc m_rgba2;
rgba_calc m_rgba3;
};
}
#endif
@@ -0,0 +1,207 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_GOURAUD_RGBA8_GAMMA_INCLUDED
#define AGG_SPAN_GOURAUD_RGBA8_GAMMA_INCLUDED
#include "agg_basics.h"
#include "agg_color_rgba8.h"
#include "agg_dda_line.h"
#include "agg_span_gouraud.h"
#include "agg_gamma_lut.h"
namespace agg
{
//======================================================span_gouraud_rgba8
template<class Allocator = span_allocator<rgba8>,
class Gamma = gamma_lut<int8u, int16u, 8, 16> >
class span_gouraud_rgba8_gamma : public span_gouraud<rgba8, Allocator>
{
public:
typedef Allocator alloc_type;
typedef rgba8 color_type;
typedef span_gouraud<color_type, alloc_type> base_type;
typedef typename base_type::coord_type coord_type;
typedef Gamma gamma_type;
private:
//--------------------------------------------------------------------
struct rgba_calc
{
void init(const coord_type& c1, const coord_type& c2, const gamma_type& gamma)
{
m_x1 = c1.x;
m_y1 = c1.y;
m_dx = c2.x - c1.x;
m_dy = 1.0 / (c2.y - c1.y);
m_r1 = gamma.dir(c1.color.r);
m_g1 = gamma.dir(c1.color.g);
m_b1 = gamma.dir(c1.color.b);
m_a1 = c1.color.a;
m_dr = gamma.dir(c2.color.r) - m_r1;
m_dg = gamma.dir(c2.color.g) - m_g1;
m_db = gamma.dir(c2.color.b) - m_b1;
m_da = c2.color.a - m_a1;
}
void calc(int y)
{
double k = 0.0;
if(y > m_y1) k = (y - m_y1) * m_dy;
m_r = m_r1 + int(m_dr * k);
m_g = m_g1 + int(m_dg * k);
m_b = m_b1 + int(m_db * k);
m_a = m_a1 + int(m_da * k);
m_x = int(m_x1 + m_dx * k);
}
double m_x1;
double m_y1;
double m_dx;
double m_dy;
int m_r1;
int m_g1;
int m_b1;
int m_a1;
int m_dr;
int m_dg;
int m_db;
int m_da;
int m_r;
int m_g;
int m_b;
int m_a;
int m_x;
};
public:
//--------------------------------------------------------------------
span_gouraud_rgba8_gamma(alloc_type& alloc, const gamma_type& g) :
base_type(alloc), m_gamma(&g) {}
//--------------------------------------------------------------------
span_gouraud_rgba8_gamma(alloc_type& alloc,
const gamma_type& g,
const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1, double y1,
double x2, double y2,
double x3, double y3,
double d = 0) :
base_type(alloc, c1, c2, c3, x1, y1, x2, y2, x3, y3, d),
m_gamma(&g)
{}
//--------------------------------------------------------------------
void gamma(const gamma_type& g) { m_gamma = &g; }
const gamma_type& gamma() const { return *m_gamma; }
//--------------------------------------------------------------------
void prepare(unsigned max_span_len)
{
base_type::prepare(max_span_len);
coord_type coord[3];
arrange_vertices(coord);
m_y2 = int(coord[1].y);
m_swap = calc_point_location(coord[0].x, coord[0].y,
coord[2].x, coord[2].y,
coord[1].x, coord[1].y) < 0.0;
m_rgba1.init(coord[0], coord[2], *m_gamma);
m_rgba2.init(coord[0], coord[1], *m_gamma);
m_rgba3.init(coord[1], coord[2], *m_gamma);
}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
m_rgba1.calc(y);
const rgba_calc* pc1 = &m_rgba1;
const rgba_calc* pc2 = &m_rgba2;
if(y < m_y2)
{
m_rgba2.calc(y+1);
}
else
{
m_rgba3.calc(y);
pc2 = &m_rgba3;
}
if(m_swap)
{
const rgba_calc* t = pc2;
pc2 = pc1;
pc1 = t;
}
int nx = pc1->m_x;
unsigned nlen = pc2->m_x - pc1->m_x + 1;
if(nlen < len) nlen = len;
dda_line_interpolator<8> r(pc1->m_r, pc2->m_r, nlen);
dda_line_interpolator<8> g(pc1->m_g, pc2->m_g, nlen);
dda_line_interpolator<8> b(pc1->m_b, pc2->m_b, nlen);
dda_line_interpolator<16> a(pc1->m_a, pc2->m_a, nlen);
if(nx < x)
{
unsigned d = unsigned(x - nx);
r += d;
g += d;
b += d;
a += d;
}
color_type* span = base_type::allocator().span();
do
{
span->r = m_gamma->inv(r.y());
span->g = m_gamma->inv(g.y());
span->b = m_gamma->inv(b.y());
span->a = a.y();
++r;
++g;
++b;
++a;
++span;
}
while(--len);
return base_type::allocator().span();
}
private:
const gamma_type* m_gamma;
bool m_swap;
int m_y2;
rgba_calc m_rgba1;
rgba_calc m_rgba2;
rgba_calc m_rgba3;
};
}
#endif
+231
View File
@@ -0,0 +1,231 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_GRADIENT_INCLUDED
#define AGG_SPAN_GRADIENT_INCLUDED
#include <math.h>
#include <stdlib.h>
#include "agg_basics.h"
#include "agg_span_generator.h"
#include "agg_math.h"
namespace agg
{
//==========================================================span_gradient
template<class ColorT,
class Interpolator,
class GradientF,
class ColorF,
class Allocator = span_allocator<ColorT> >
class span_gradient : public span_generator<ColorT, Allocator>
{
public:
typedef Interpolator interpolator_type;
typedef Allocator alloc_type;
typedef ColorT color_type;
typedef span_generator<color_type, alloc_type> base_type;
enum
{
base_shift = 8,
base_size = 1 << base_shift,
base_mask = base_size - 1,
gradient_shift = 4,
gradient_size = 1 << gradient_shift,
gradient_mask = gradient_size - 1,
downscale_shift = interpolator_type::subpixel_shift - gradient_shift
};
//--------------------------------------------------------------------
span_gradient(alloc_type& alloc) : base_type(alloc) {}
//--------------------------------------------------------------------
span_gradient(alloc_type& alloc,
interpolator_type& inter,
const GradientF& gradient_function,
ColorF color_function,
double d1, double d2) :
base_type(alloc),
m_interpolator(&inter),
m_gradient_function(&gradient_function),
m_color_function(color_function),
m_d1(int(d1 * gradient_size)),
m_d2(int(d2 * gradient_size))
{}
//--------------------------------------------------------------------
interpolator_type& interpolator() { return *m_interpolator; }
const GradientF& gradient_function() const { return *m_gradient_function; }
const ColorF color_function() const { return m_color_function; }
double d1() const { return double(m_d1) / gradient_size; }
double d2() const { return double(m_d2) / gradient_size; }
//--------------------------------------------------------------------
void interpolator(interpolator_type& i) { m_interpolator = &i; }
void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
void color_function(ColorF cf) { m_color_function = cf; }
void d1(double v) { m_d1 = int(v * gradient_size); }
void d2(double v) { m_d2 = int(v * gradient_size); }
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
color_type* span = base_type::allocator().span();
int dd = m_d2 - m_d1;
if(dd < 1) dd = 1;
m_interpolator->begin(x+0.5, y+0.5, len);
do
{
m_interpolator->coordinates(&x, &y);
int d = m_gradient_function->calculate(x >> downscale_shift,
y >> downscale_shift, dd);
d = ((d - m_d1) << base_shift) / dd;
if(d < 0) d = 0;
if(d > base_mask) d = base_mask;
*span++ = m_color_function[d];
++(*m_interpolator);
}
while(--len);
return base_type::allocator().span();
}
private:
interpolator_type* m_interpolator;
const GradientF* m_gradient_function;
ColorF m_color_function;
int m_d1;
int m_d2;
};
//=====================================================gradient_linear_color
template<class ColorT, unsigned BaseShift=8>
struct gradient_linear_color
{
typedef ColorT color_type;
enum
{
base_shift = BaseShift,
base_size = 1 << base_shift,
base_mask = base_size - 1
};
gradient_linear_color() {}
gradient_linear_color(const color_type& c1, const color_type& c2) :
m_c1(c1), m_c2(c2) {}
color_type operator [] (unsigned v) const
{
return m_c1.gradient(m_c2, double(v) / double(base_mask));
}
void colors(const color_type& c1, const color_type& c2)
{
m_c1 = c1;
m_c2 = c2;
}
color_type m_c1;
color_type m_c2;
};
//---------------------------------------------------------gradient_circle
class gradient_circle
{
public:
static int calculate(int x, int y, int)
{
return int(fast_sqrt(x*x + y*y));
}
};
//--------------------------------------------------------------gradient_x
class gradient_x
{
public:
static int calculate(int x, int, int) { return x; }
};
//--------------------------------------------------------------gradient_y
class gradient_y
{
public:
static int calculate(int, int y, int) { return y; }
};
//--------------------------------------------------------gradient_diamond
class gradient_diamond
{
public:
static int calculate(int x, int y, int)
{
int ax = abs(x);
int ay = abs(y);
return ax > ay ? ax : ay;
}
};
//-------------------------------------------------------------gradient_xy
class gradient_xy
{
public:
static int calculate(int x, int y, int d)
{
return abs(x) * abs(y) / d;
}
};
//--------------------------------------------------------gradient_sqrt_xy
class gradient_sqrt_xy
{
public:
static int calculate(int x, int y, int)
{
return fast_sqrt(abs(x) * abs(y));
}
};
//----------------------------------------------------------gradient_conic
class gradient_conic
{
public:
static int calculate(int x, int y, int d)
{
return int(fabs(atan2(double(y), double(x))) * double(d) / pi);
}
};
}
#endif
+83
View File
@@ -0,0 +1,83 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Image transformations with filtering. Span generator base class
//
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_IMAGE_FILTER_INCLUDED
#define AGG_SPAN_IMAGE_FILTER_INCLUDED
#include "agg_basics.h"
#include "agg_image_filters.h"
#include "agg_rendering_buffer.h"
#include "agg_span_generator.h"
namespace agg
{
//--------------------------------------------------span_image_filter
template<class ColorT, class Interpolator, class Allocator>
class span_image_filter : public span_generator<ColorT, Allocator>
{
public:
typedef ColorT color_type;
typedef Allocator alloc_type;
typedef Interpolator interpolator_type;
//----------------------------------------------------------------
span_image_filter(alloc_type& alloc) :
span_generator<color_type, alloc_type>(alloc)
{}
//----------------------------------------------------------------
span_image_filter(alloc_type& alloc,
const rendering_buffer& src,
const color_type& back_color,
interpolator_type& interpolator,
const image_filter_base* filter) :
span_generator<color_type, alloc_type>(alloc),
m_src(&src),
m_back_color(back_color),
m_interpolator(&interpolator),
m_filter(filter)
{}
//----------------------------------------------------------------
const rendering_buffer& source_image() const { return *m_src; }
const color_type& background_color() const { return m_back_color; }
const image_filter_base& filter() const { return *m_filter; }
//----------------------------------------------------------------
void source_image(const rendering_buffer& v) { m_src = &v; }
void background_color(const color_type& v) { m_back_color = v; }
void interpolator(interpolator_type& v) { m_interpolator = &v; }
void filter(const image_filter_base& v) { m_filter = &v; }
//----------------------------------------------------------------
interpolator_type& interpolator() { return *m_interpolator; }
//----------------------------------------------------------------
private:
const rendering_buffer* m_src;
color_type m_back_color;
interpolator_type* m_interpolator;
const image_filter_base* m_filter;
};
}
#endif
@@ -0,0 +1,531 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_IMAGE_FILTER_RGB24_INCLUDED
#define AGG_SPAN_IMAGE_FILTER_RGB24_INCLUDED
#include "agg_basics.h"
#include "agg_color_rgba8.h"
#include "agg_span_image_filter.h"
namespace agg
{
//==============================================span_image_filter_rgb24_nn
template<class Order,
class Interpolator,
class Allocator = span_allocator<rgba8> >
class span_image_filter_rgb24_nn :
public span_image_filter<rgba8, Interpolator, Allocator>
{
public:
typedef Interpolator interpolator_type;
typedef Allocator alloc_type;
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
typedef rgba8 color_type;
//--------------------------------------------------------------------
span_image_filter_rgb24_nn(alloc_type& alloc) : base_type(alloc) {}
//--------------------------------------------------------------------
span_image_filter_rgb24_nn(alloc_type& alloc,
const rendering_buffer& src,
const color_type& back_color,
interpolator_type& inter) :
base_type(alloc, src, back_color, inter, 0)
{}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
base_type::interpolator().begin(x, y, len);
int fg[3];
int src_alpha;
const unsigned char *fg_ptr;
color_type* span = base_type::allocator().span();
int maxx = base_type::source_image().width() - 1;
int maxy = base_type::source_image().height() - 1;
do
{
base_type::interpolator().coordinates(&x, &y);
x >>= image_subpixel_shift;
y >>= image_subpixel_shift;
if(x >= 0 && y >= 0 &&
x <= maxx && y <= maxy)
{
fg_ptr = base_type::source_image().row(y) + x + x + x;
fg[0] = *fg_ptr++;
fg[1] = *fg_ptr++;
fg[2] = *fg_ptr++;
src_alpha = 255;
}
else
{
fg[Order::R] = base_type::background_color().r;
fg[Order::G] = base_type::background_color().g;
fg[Order::B] = base_type::background_color().b;
src_alpha = base_type::background_color().a;
}
span->r = (int8u)fg[Order::R];
span->g = (int8u)fg[Order::G];
span->b = (int8u)fg[Order::B];
span->a = (int8u)src_alpha;
++span;
++base_type::interpolator();
} while(--len);
return base_type::allocator().span();
}
};
//=========================================span_image_filter_rgb24_bilinear
template<class Order,
class Interpolator,
class Allocator = span_allocator<rgba8> >
class span_image_filter_rgb24_bilinear :
public span_image_filter<rgba8, Interpolator, Allocator>
{
public:
typedef Interpolator interpolator_type;
typedef Allocator alloc_type;
typedef span_image_filter<rgba8, Interpolator, Allocator> base_type;
typedef rgba8 color_type;
//--------------------------------------------------------------------
span_image_filter_rgb24_bilinear(alloc_type& alloc) : base_type(alloc) {}
//--------------------------------------------------------------------
span_image_filter_rgb24_bilinear(alloc_type& alloc,
const rendering_buffer& src,
const color_type& back_color,
interpolator_type& inter) :
base_type(alloc, src, back_color, inter, 0)
{}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
base_type::interpolator().begin(x, y, len);
int fg[3];
int src_alpha;
int back_r = base_type::background_color().r;
int back_g = base_type::background_color().g;
int back_b = base_type::background_color().b;
int back_a = base_type::background_color().a;
const unsigned char *fg_ptr;
int stride = base_type::source_image().stride() - 2 * 3;
color_type* span = base_type::allocator().span();
int maxx = base_type::source_image().width() - 1;
int maxy = base_type::source_image().height() - 1;
do
{
int x_hr;
int y_hr;
base_type::interpolator().coordinates(&x_hr, &y_hr);
int x_lr = x_hr >> image_subpixel_shift;
int y_lr = y_hr >> image_subpixel_shift;
int weight;
if(x_lr >= 0 && y_lr >= 0 &&
x_lr < maxx && y_lr < maxy)
{
fg[0] =
fg[1] =
fg[2] = image_subpixel_size * image_subpixel_size / 2;
x_hr &= image_subpixel_mask;
y_hr &= image_subpixel_mask;
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
weight = (image_subpixel_size - x_hr) *
(image_subpixel_size - y_hr);
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
weight = x_hr * (image_subpixel_size - y_hr);
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
fg_ptr += stride;
weight = (image_subpixel_size - x_hr) * y_hr;
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
weight = x_hr * y_hr;
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
fg[0] >>= image_subpixel_shift * 2;
fg[1] >>= image_subpixel_shift * 2;
fg[2] >>= image_subpixel_shift * 2;
src_alpha = 255;
}
else
{
if(x_lr < -1 || y_lr < -1 ||
x_lr > maxx || y_lr > maxy)
{
fg[Order::R] = back_r;
fg[Order::G] = back_g;
fg[Order::B] = back_b;
src_alpha = back_a;
}
else
{
fg[0] =
fg[1] =
fg[2] =
src_alpha = image_subpixel_size * image_subpixel_size / 2;
x_hr &= image_subpixel_mask;
y_hr &= image_subpixel_mask;
weight = (image_subpixel_size - x_hr) *
(image_subpixel_size - y_hr);
if(x_lr >= 0 && y_lr >= 0 &&
x_lr <= maxx && y_lr <= maxy)
{
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
src_alpha += weight * 255;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
src_alpha += back_a * weight;
}
x_lr++;
weight = x_hr * (image_subpixel_size - y_hr);
if(x_lr >= 0 && y_lr >= 0 &&
x_lr <= maxx && y_lr <= maxy)
{
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
src_alpha += weight * 255;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
src_alpha += back_a * weight;
}
x_lr--;
y_lr++;
weight = (image_subpixel_size - x_hr) * y_hr;
if(x_lr >= 0 && y_lr >= 0 &&
x_lr <= maxx && y_lr <= maxy)
{
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
src_alpha += weight * 255;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
src_alpha += back_a * weight;
}
x_lr++;
weight = x_hr * y_hr;
if(x_lr >= 0 && y_lr >= 0 &&
x_lr <= maxx && y_lr <= maxy)
{
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
src_alpha += weight * 255;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
src_alpha += back_a * weight;
}
fg[0] >>= image_subpixel_shift * 2;
fg[1] >>= image_subpixel_shift * 2;
fg[2] >>= image_subpixel_shift * 2;
src_alpha >>= image_subpixel_shift * 2;
}
}
span->r = (int8u)fg[Order::R];
span->g = (int8u)fg[Order::G];
span->b = (int8u)fg[Order::B];
span->a = (int8u)src_alpha;
++span;
++base_type::interpolator();
} while(--len);
return base_type::allocator().span();
}
};
//=================================================span_image_filter_rgb24
template<class Order,
class Interpolator,
class Allocator = span_allocator<rgba8> >
class span_image_filter_rgb24 :
public span_image_filter<rgba8, Interpolator, Allocator>
{
public:
typedef Interpolator interpolator_type;
typedef Allocator alloc_type;
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
typedef rgba8 color_type;
//--------------------------------------------------------------------
span_image_filter_rgb24(alloc_type& alloc) : base_type(alloc) {}
//--------------------------------------------------------------------
span_image_filter_rgb24(alloc_type& alloc,
const rendering_buffer& src,
const color_type& back_color,
interpolator_type& inter,
const image_filter_base& filter) :
base_type(alloc, src, back_color, inter, &filter)
{}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
base_type::interpolator().begin(x, y, len);
int fg[3];
int src_alpha;
int back_r = base_type::background_color().r;
int back_g = base_type::background_color().g;
int back_b = base_type::background_color().b;
int back_a = base_type::background_color().a;
const unsigned char *fg_ptr;
unsigned dimension = base_type::filter().dimension();
int start = base_type::filter().start();
int start1 = start - 1;
const int* weight_array = base_type::filter().weight_array_int();
int stride = base_type::source_image().stride() - dimension * 3;
color_type* span = base_type::allocator().span();
int maxx = base_type::source_image().width() + start - 2;
int maxy = base_type::source_image().height() + start - 2;
int maxx2 = base_type::source_image().width() - start - 1;
int maxy2 = base_type::source_image().height() - start - 1;
int x_count;
int weight_y;
do
{
base_type::interpolator().coordinates(&x, &y);
int x_hr = x;
int y_hr = y;
int x_lr = x_hr >> image_subpixel_shift;
int y_lr = y_hr >> image_subpixel_shift;
fg[0] = fg[1] = fg[2] = image_filter_size / 2;
int x_fract = x_hr & image_subpixel_mask;
unsigned y_count = dimension;
if(x_lr >= -start && y_lr >= -start &&
x_lr <= maxx && y_lr <= maxy)
{
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
fg_ptr = base_type::source_image().row(y_lr + start) + (x_lr + start) * 3;
do
{
x_count = dimension;
weight_y = weight_array[y_hr];
x_hr = image_subpixel_mask - x_fract;
do
{
int weight = (weight_y * weight_array[x_hr] +
image_filter_size / 2) >>
image_filter_shift;
fg[0] += *fg_ptr++ * weight;
fg[1] += *fg_ptr++ * weight;
fg[2] += *fg_ptr++ * weight;
x_hr += image_subpixel_size;
} while(--x_count);
y_hr += image_subpixel_size;
fg_ptr += stride;
} while(--y_count);
fg[0] >>= image_filter_shift;
fg[1] >>= image_filter_shift;
fg[2] >>= image_filter_shift;
if(fg[0] < 0) fg[0] = 0;
if(fg[1] < 0) fg[1] = 0;
if(fg[2] < 0) fg[2] = 0;
if(fg[0] > 255) fg[0] = 255;
if(fg[1] > 255) fg[1] = 255;
if(fg[2] > 255) fg[2] = 255;
src_alpha = 255;
}
else
{
if(x_lr < start1 || y_lr < start1 ||
x_lr > maxx2 || y_lr > maxy2)
{
fg[Order::R] = back_r;
fg[Order::G] = back_g;
fg[Order::B] = back_b;
src_alpha = back_a;
}
else
{
src_alpha = image_filter_size / 2;
y_lr = (y >> image_subpixel_shift) + start;
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
do
{
x_count = dimension;
weight_y = weight_array[y_hr];
x_lr = (x >> image_subpixel_shift) + start;
x_hr = image_subpixel_mask - x_fract;
do
{
int weight = (weight_y * weight_array[x_hr] +
image_filter_size / 2) >>
image_filter_shift;
if(x_lr >= 0 && y_lr >= 0 &&
x_lr < int(base_type::source_image().width()) &&
y_lr < int(base_type::source_image().height()))
{
fg_ptr = base_type::source_image().row(y_lr) + x_lr * 3;
fg[0] += *fg_ptr++ * weight;
fg[1] += *fg_ptr++ * weight;
fg[2] += *fg_ptr++ * weight;
src_alpha += 255 * weight;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
src_alpha += back_a * weight;
}
x_hr += image_subpixel_size;
x_lr++;
} while(--x_count);
y_hr += image_subpixel_size;
y_lr++;
} while(--y_count);
fg[0] >>= image_filter_shift;
fg[1] >>= image_filter_shift;
fg[2] >>= image_filter_shift;
src_alpha >>= image_filter_shift;
if(fg[0] < 0) fg[0] = 0;
if(fg[1] < 0) fg[1] = 0;
if(fg[2] < 0) fg[2] = 0;
if(src_alpha < 0) src_alpha = 0;
if(fg[0] > 255) fg[0] = 255;
if(fg[1] > 255) fg[1] = 255;
if(fg[2] > 255) fg[2] = 255;
if(src_alpha > 255) src_alpha = 255;
}
}
span->r = (int8u)fg[Order::R];
span->g = (int8u)fg[Order::G];
span->b = (int8u)fg[Order::B];
span->a = (int8u)src_alpha;
++span;
++base_type::interpolator();
} while(--len);
return base_type::allocator().span();
}
};
}
#endif
@@ -0,0 +1,475 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_IMAGE_FILTER_RGB24_GAMMA_INCLUDED
#define AGG_SPAN_IMAGE_FILTER_RGB24_GAMMA_INCLUDED
#include "agg_basics.h"
#include "agg_color_rgba8.h"
#include "agg_span_image_filter.h"
#include "agg_gamma_lut.h"
namespace agg
{
//===================================span_image_filter_rgb24_gamma_bilinear
template<class Order,
class Interpolator,
class Allocator = span_allocator<rgba8>,
class Gamma = gamma_lut<int8u, int8u, 8, 8> >
class span_image_filter_rgb24_gamma_bilinear :
public span_image_filter<rgba8, Interpolator, Allocator>
{
public:
typedef Interpolator interpolator_type;
typedef Allocator alloc_type;
typedef span_image_filter<rgba8, Interpolator, Allocator> base_type;
typedef rgba8 color_type;
typedef Gamma gamma_type;
//--------------------------------------------------------------------
span_image_filter_rgb24_gamma_bilinear(alloc_type& alloc,
const gamma_type& g) :
base_type(alloc),
m_gamma(&g)
{}
//--------------------------------------------------------------------
span_image_filter_rgb24_gamma_bilinear(alloc_type& alloc,
const rendering_buffer& src,
const color_type& back_color,
interpolator_type& inter,
const gamma_type& g) :
base_type(alloc, src, back_color, inter, 0),
m_gamma(&g)
{}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
base_type::interpolator().begin(x, y, len);
int fg[3];
int src_alpha;
int back_r = m_gamma->dir(base_type::background_color().r);
int back_g = m_gamma->dir(base_type::background_color().g);
int back_b = m_gamma->dir(base_type::background_color().b);
int back_a = base_type::background_color().a;
const unsigned char *fg_ptr;
int stride = base_type::source_image().stride() - 2 * 3;
color_type* span = base_type::allocator().span();
int maxx = base_type::source_image().width() - 1;
int maxy = base_type::source_image().height() - 1;
do
{
int x_hr;
int y_hr;
base_type::interpolator().coordinates(&x_hr, &y_hr);
int x_lr = x_hr >> image_subpixel_shift;
int y_lr = y_hr >> image_subpixel_shift;
int weight;
if(x_lr >= 0 && y_lr >= 0 &&
x_lr < maxx && y_lr < maxy)
{
fg[0] =
fg[1] =
fg[2] = image_subpixel_size * image_subpixel_size / 2;
x_hr &= image_subpixel_mask;
y_hr &= image_subpixel_mask;
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
weight = (image_subpixel_size - x_hr) *
(image_subpixel_size - y_hr);
fg[0] += weight * m_gamma->dir(*fg_ptr++);
fg[1] += weight * m_gamma->dir(*fg_ptr++);
fg[2] += weight * m_gamma->dir(*fg_ptr++);
weight = x_hr * (image_subpixel_size - y_hr);
fg[0] += weight * m_gamma->dir(*fg_ptr++);
fg[1] += weight * m_gamma->dir(*fg_ptr++);
fg[2] += weight * m_gamma->dir(*fg_ptr++);
fg_ptr += stride;
weight = (image_subpixel_size - x_hr) * y_hr;
fg[0] += weight * m_gamma->dir(*fg_ptr++);
fg[1] += weight * m_gamma->dir(*fg_ptr++);
fg[2] += weight * m_gamma->dir(*fg_ptr++);
weight = x_hr * y_hr;
fg[0] += weight * m_gamma->dir(*fg_ptr++);
fg[1] += weight * m_gamma->dir(*fg_ptr++);
fg[2] += weight * m_gamma->dir(*fg_ptr++);
fg[0] >>= image_subpixel_shift * 2;
fg[1] >>= image_subpixel_shift * 2;
fg[2] >>= image_subpixel_shift * 2;
src_alpha = 255;
}
else
{
if(x_lr < -1 || y_lr < -1 ||
x_lr > maxx || y_lr > maxy)
{
fg[Order::R] = back_r;
fg[Order::G] = back_g;
fg[Order::B] = back_b;
src_alpha = back_a;
}
else
{
fg[0] =
fg[1] =
fg[2] =
src_alpha = image_subpixel_size * image_subpixel_size / 2;
x_hr &= image_subpixel_mask;
y_hr &= image_subpixel_mask;
weight = (image_subpixel_size - x_hr) *
(image_subpixel_size - y_hr);
if(x_lr >= 0 && y_lr >= 0 &&
x_lr <= maxx && y_lr <= maxy)
{
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
fg[0] += weight * m_gamma->dir(*fg_ptr++);
fg[1] += weight * m_gamma->dir(*fg_ptr++);
fg[2] += weight * m_gamma->dir(*fg_ptr++);
src_alpha += weight * 255;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
src_alpha += back_a * weight;
}
x_lr++;
weight = x_hr * (image_subpixel_size - y_hr);
if(x_lr >= 0 && y_lr >= 0 &&
x_lr <= maxx && y_lr <= maxy)
{
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
fg[0] += weight * m_gamma->dir(*fg_ptr++);
fg[1] += weight * m_gamma->dir(*fg_ptr++);
fg[2] += weight * m_gamma->dir(*fg_ptr++);
src_alpha += weight * 255;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
src_alpha += back_a * weight;
}
x_lr--;
y_lr++;
weight = (image_subpixel_size - x_hr) * y_hr;
if(x_lr >= 0 && y_lr >= 0 &&
x_lr <= maxx && y_lr <= maxy)
{
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
fg[0] += weight * m_gamma->dir(*fg_ptr++);
fg[1] += weight * m_gamma->dir(*fg_ptr++);
fg[2] += weight * m_gamma->dir(*fg_ptr++);
src_alpha += weight * 255;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
src_alpha += back_a * weight;
}
x_lr++;
weight = x_hr * y_hr;
if(x_lr >= 0 && y_lr >= 0 &&
x_lr <= maxx && y_lr <= maxy)
{
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
fg[0] += weight * m_gamma->dir(*fg_ptr++);
fg[1] += weight * m_gamma->dir(*fg_ptr++);
fg[2] += weight * m_gamma->dir(*fg_ptr++);
src_alpha += weight * 255;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
src_alpha += back_a * weight;
}
fg[0] >>= image_subpixel_shift * 2;
fg[1] >>= image_subpixel_shift * 2;
fg[2] >>= image_subpixel_shift * 2;
src_alpha >>= image_subpixel_shift * 2;
}
}
span->r = (int8u)m_gamma->inv(fg[Order::R]);
span->g = (int8u)m_gamma->inv(fg[Order::G]);
span->b = (int8u)m_gamma->inv(fg[Order::B]);
span->a = (int8u)src_alpha;
++span;
++base_type::interpolator();
} while(--len);
return base_type::allocator().span();
}
private:
const gamma_type* m_gamma;
};
//============================================span_image_filter_rgb24_gamma
template<class Order,
class Interpolator,
class Allocator = span_allocator<rgba8>,
class Gamma = gamma_lut<int8u, int8u, 8, 8> >
class span_image_filter_rgb24_gamma :
public span_image_filter<rgba8, Interpolator, Allocator>
{
public:
typedef Interpolator interpolator_type;
typedef Allocator alloc_type;
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
typedef rgba8 color_type;
typedef Gamma gamma_type;
//--------------------------------------------------------------------
span_image_filter_rgb24_gamma(alloc_type& alloc, const gamma_type& g) :
base_type(alloc),
m_gamma(&g)
{}
//--------------------------------------------------------------------
span_image_filter_rgb24_gamma(alloc_type& alloc,
const rendering_buffer& src,
const color_type& back_color,
interpolator_type& inter,
const image_filter_base& filter,
const gamma_type& g) :
base_type(alloc, src, back_color, inter, &filter),
m_gamma(&g)
{}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
base_type::interpolator().begin(x, y, len);
int fg[3];
int src_alpha;
int back_r = m_gamma->dir(base_type::background_color().r);
int back_g = m_gamma->dir(base_type::background_color().g);
int back_b = m_gamma->dir(base_type::background_color().b);
int back_a = base_type::background_color().a;
const unsigned char *fg_ptr;
unsigned dimension = base_type::filter().dimension();
int start = base_type::filter().start();
int start1 = start - 1;
const int* weight_array = base_type::filter().weight_array_int();
int stride = base_type::source_image().stride() - dimension * 3;
color_type* span = base_type::allocator().span();
int maxx = base_type::source_image().width() + start - 2;
int maxy = base_type::source_image().height() + start - 2;
int maxx2 = base_type::source_image().width() - start - 1;
int maxy2 = base_type::source_image().height() - start - 1;
int x_count;
int weight_y;
do
{
base_type::interpolator().coordinates(&x, &y);
int x_hr = x;
int y_hr = y;
int x_lr = x_hr >> image_subpixel_shift;
int y_lr = y_hr >> image_subpixel_shift;
fg[0] = fg[1] = fg[2] = image_filter_size / 2;
int x_fract = x_hr & image_subpixel_mask;
unsigned y_count = dimension;
if(x_lr >= -start && y_lr >= -start &&
x_lr <= maxx && y_lr <= maxy)
{
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
fg_ptr = base_type::source_image().row(y_lr + start) + (x_lr + start) * 3;
do
{
x_count = dimension;
weight_y = weight_array[y_hr];
x_hr = image_subpixel_mask - x_fract;
do
{
int weight = (weight_y * weight_array[x_hr] +
image_filter_size / 2) >>
image_filter_shift;
fg[0] += m_gamma->dir(*fg_ptr++) * weight;
fg[1] += m_gamma->dir(*fg_ptr++) * weight;
fg[2] += m_gamma->dir(*fg_ptr++) * weight;
x_hr += image_subpixel_size;
} while(--x_count);
y_hr += image_subpixel_size;
fg_ptr += stride;
} while(--y_count);
fg[0] >>= image_filter_shift;
fg[1] >>= image_filter_shift;
fg[2] >>= image_filter_shift;
if(fg[0] < 0) fg[0] = 0;
if(fg[1] < 0) fg[1] = 0;
if(fg[2] < 0) fg[2] = 0;
if(fg[0] > 255) fg[0] = 255;
if(fg[1] > 255) fg[1] = 255;
if(fg[2] > 255) fg[2] = 255;
src_alpha = 255;
}
else
{
if(x_lr < start1 || y_lr < start1 ||
x_lr > maxx2 || y_lr > maxy2)
{
fg[Order::R] = back_r;
fg[Order::G] = back_g;
fg[Order::B] = back_b;
src_alpha = back_a;
}
else
{
src_alpha = image_filter_size / 2;
y_lr = (y >> image_subpixel_shift) + start;
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
do
{
x_count = dimension;
weight_y = weight_array[y_hr];
x_lr = (x >> image_subpixel_shift) + start;
x_hr = image_subpixel_mask - x_fract;
do
{
int weight = (weight_y * weight_array[x_hr] +
image_filter_size / 2) >>
image_filter_shift;
if(x_lr >= 0 && y_lr >= 0 &&
x_lr < int(base_type::source_image().width()) &&
y_lr < int(base_type::source_image().height()))
{
fg_ptr = base_type::source_image().row(y_lr) + x_lr * 3;
fg[0] += m_gamma->dir(*fg_ptr++) * weight;
fg[1] += m_gamma->dir(*fg_ptr++) * weight;
fg[2] += m_gamma->dir(*fg_ptr++) * weight;
src_alpha += 255 * weight;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
src_alpha += back_a * weight;
}
x_hr += image_subpixel_size;
x_lr++;
} while(--x_count);
y_hr += image_subpixel_size;
y_lr++;
} while(--y_count);
fg[0] >>= image_filter_shift;
fg[1] >>= image_filter_shift;
fg[2] >>= image_filter_shift;
src_alpha >>= image_filter_shift;
if(fg[0] < 0) fg[0] = 0;
if(fg[1] < 0) fg[1] = 0;
if(fg[2] < 0) fg[2] = 0;
if(src_alpha < 0) src_alpha = 0;
if(fg[0] > 255) fg[0] = 255;
if(fg[1] > 255) fg[1] = 255;
if(fg[2] > 255) fg[2] = 255;
if(src_alpha > 255) src_alpha = 255;
}
}
span->r = (int8u)m_gamma->inv(fg[Order::R]);
span->g = (int8u)m_gamma->inv(fg[Order::G]);
span->b = (int8u)m_gamma->inv(fg[Order::B]);
span->a = (int8u)src_alpha;
++span;
++base_type::interpolator();
} while(--len);
return base_type::allocator().span();
}
private:
const gamma_type* m_gamma;
};
}
#endif
@@ -0,0 +1,548 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// classes span_image_filter_rgba32*
//
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_IMAGE_FILTER_RGBA32_INCLUDED
#define AGG_SPAN_IMAGE_FILTER_RGBA32_INCLUDED
#include "agg_basics.h"
#include "agg_color_rgba8.h"
#include "agg_span_image_filter.h"
namespace agg
{
//=============================================span_image_filter_rgba32_nn
template<class Order,
class Interpolator,
class Allocator = span_allocator<rgba8> >
class span_image_filter_rgba32_nn :
public span_image_filter<rgba8, Interpolator, Allocator>
{
public:
typedef Interpolator interpolator_type;
typedef Allocator alloc_type;
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
typedef rgba8 color_type;
//--------------------------------------------------------------------
span_image_filter_rgba32_nn(alloc_type& alloc) : base_type(alloc) {}
//--------------------------------------------------------------------
span_image_filter_rgba32_nn(alloc_type& alloc,
const rendering_buffer& src,
const color_type& back_color,
interpolator_type& inter) :
base_type(alloc, src, back_color, inter, 0)
{}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
base_type::interpolator().begin(x, y, len);
int fg[4];
const unsigned char *fg_ptr;
color_type* span = base_type::allocator().span();
int maxx = base_type::source_image().width() - 1;
int maxy = base_type::source_image().height() - 1;
do
{
base_type::interpolator().coordinates(&x, &y);
x >>= image_subpixel_shift;
y >>= image_subpixel_shift;
if(x >= 0 && y >= 0 &&
x <= maxx && y <= maxy)
{
fg_ptr = base_type::source_image().row(y) + (x << 2);
fg[0] = *fg_ptr++;
fg[1] = *fg_ptr++;
fg[2] = *fg_ptr++;
fg[3] = *fg_ptr++;
}
else
{
fg[Order::R] = base_type::background_color().r;
fg[Order::G] = base_type::background_color().g;
fg[Order::B] = base_type::background_color().b;
fg[Order::A] = base_type::background_color().a;
}
span->r = fg[Order::R];
span->g = fg[Order::G];
span->b = fg[Order::B];
span->a = fg[Order::A];
++span;
++base_type::interpolator();
} while(--len);
return base_type::allocator().span();
}
};
//=======================================span_image_filter_rgba32_bilinear
template<class Order,
class Interpolator,
class Allocator = span_allocator<rgba8> >
class span_image_filter_rgba32_bilinear :
public span_image_filter<rgba8, Interpolator, Allocator>
{
public:
typedef Interpolator interpolator_type;
typedef Allocator alloc_type;
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
typedef rgba8 color_type;
//--------------------------------------------------------------------
span_image_filter_rgba32_bilinear(alloc_type& alloc) : base_type(alloc) {}
//--------------------------------------------------------------------
span_image_filter_rgba32_bilinear(alloc_type& alloc,
const rendering_buffer& src,
const color_type& back_color,
interpolator_type& inter) :
base_type(alloc, src, back_color, inter, 0)
{}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
base_type::interpolator().begin(x, y, len);
int fg[4];
int back_r = base_type::background_color().r;
int back_g = base_type::background_color().g;
int back_b = base_type::background_color().b;
int back_a = base_type::background_color().a;
const unsigned char *fg_ptr;
int stride = base_type::source_image().stride() - 2 * 4;
color_type* span = base_type::allocator().span();
int maxx = base_type::source_image().width() - 1;
int maxy = base_type::source_image().height() - 1;
do
{
int x_hr;
int y_hr;
base_type::interpolator().coordinates(&x_hr, &y_hr);
int x_lr = x_hr >> image_subpixel_shift;
int y_lr = y_hr >> image_subpixel_shift;
int weight;
if(x_lr >= 0 && y_lr >= 0 &&
x_lr < maxx && y_lr < maxy)
{
fg[0] =
fg[1] =
fg[2] =
fg[3] = image_subpixel_size * image_subpixel_size / 2;
x_hr &= image_subpixel_mask;
y_hr &= image_subpixel_mask;
fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2);
weight = (image_subpixel_size - x_hr) *
(image_subpixel_size - y_hr);
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
fg[3] += weight * *fg_ptr++;
weight = x_hr * (image_subpixel_size - y_hr);
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
fg[3] += weight * *fg_ptr++;
fg_ptr += stride;
weight = (image_subpixel_size - x_hr) * y_hr;
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
fg[3] += weight * *fg_ptr++;
weight = x_hr * y_hr;
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
fg[3] += weight * *fg_ptr++;
fg[0] >>= image_subpixel_shift * 2;
fg[1] >>= image_subpixel_shift * 2;
fg[2] >>= image_subpixel_shift * 2;
fg[3] >>= image_subpixel_shift * 2;
}
else
{
if(x_lr < -1 || y_lr < -1 ||
x_lr > maxx || y_lr > maxy)
{
fg[Order::R] = back_r;
fg[Order::G] = back_g;
fg[Order::B] = back_b;
fg[Order::A] = back_a;
}
else
{
fg[0] =
fg[1] =
fg[2] =
fg[3] = image_subpixel_size * image_subpixel_size / 2;
x_hr &= image_subpixel_mask;
y_hr &= image_subpixel_mask;
weight = (image_subpixel_size - x_hr) *
(image_subpixel_size - y_hr);
if(x_lr >= 0 && y_lr >= 0 &&
x_lr <= maxx && y_lr <= maxy)
{
fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2);
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
fg[3] += weight * *fg_ptr++;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
fg[Order::A] += back_a * weight;
}
x_lr++;
weight = x_hr * (image_subpixel_size - y_hr);
if(x_lr >= 0 && y_lr >= 0 &&
x_lr <= maxx && y_lr <= maxy)
{
fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2);
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
fg[3] += weight * *fg_ptr++;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
fg[Order::A] += back_a * weight;
}
x_lr--;
y_lr++;
weight = (image_subpixel_size - x_hr) * y_hr;
if(x_lr >= 0 && y_lr >= 0 &&
x_lr <= maxx && y_lr <= maxy)
{
fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2);
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
fg[3] += weight * *fg_ptr++;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
fg[Order::A] += back_a * weight;
}
x_lr++;
weight = x_hr * y_hr;
if(x_lr >= 0 && y_lr >= 0 &&
x_lr <= maxx && y_lr <= maxy)
{
fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2);
fg[0] += weight * *fg_ptr++;
fg[1] += weight * *fg_ptr++;
fg[2] += weight * *fg_ptr++;
fg[3] += weight * *fg_ptr++;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
fg[Order::A] += back_a * weight;
}
fg[0] >>= image_subpixel_shift * 2;
fg[1] >>= image_subpixel_shift * 2;
fg[2] >>= image_subpixel_shift * 2;
fg[3] >>= image_subpixel_shift * 2;
}
}
span->r = (int8u)fg[Order::R];
span->g = (int8u)fg[Order::G];
span->b = (int8u)fg[Order::B];
span->a = (int8u)fg[Order::A];
++span;
++base_type::interpolator();
} while(--len);
return base_type::allocator().span();
}
};
//================================================span_image_filter_rgba32
template<class Order,
class Interpolator,
class Allocator = span_allocator<rgba8> >
class span_image_filter_rgba32 :
public span_image_filter<rgba8, Interpolator, Allocator>
{
public:
typedef Interpolator interpolator_type;
typedef Allocator alloc_type;
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
typedef rgba8 color_type;
//--------------------------------------------------------------------
span_image_filter_rgba32(alloc_type& alloc) : base_type(alloc) {}
//--------------------------------------------------------------------
span_image_filter_rgba32(alloc_type& alloc,
const rendering_buffer& src,
const color_type& back_color,
interpolator_type& inter,
const image_filter_base& filter) :
base_type(alloc, src, back_color, inter, &filter)
{}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
base_type::interpolator().begin(x, y, len);
int fg[4];
int back_r = base_type::background_color().r;
int back_g = base_type::background_color().g;
int back_b = base_type::background_color().b;
int back_a = base_type::background_color().a;
const unsigned char *fg_ptr;
unsigned dimension = base_type::filter().dimension();
int start = base_type::filter().start();
int start1 = start - 1;
const int* weight_array = base_type::filter().weight_array_int();
int stride = base_type::source_image().stride() - (dimension << 2);
color_type* span = base_type::allocator().span();
int maxx = base_type::source_image().width() + start - 2;
int maxy = base_type::source_image().height() + start - 2;
int maxx2 = base_type::source_image().width() - start - 1;
int maxy2 = base_type::source_image().height() - start - 1;
int x_count;
int weight_y;
do
{
base_type::interpolator().coordinates(&x, &y);
int x_hr = x;
int y_hr = y;
int x_lr = x_hr >> image_subpixel_shift;
int y_lr = y_hr >> image_subpixel_shift;
fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2;
int x_fract = x_hr & image_subpixel_mask;
unsigned y_count = dimension;
if(x_lr >= -start && y_lr >= -start &&
x_lr <= maxx && y_lr <= maxy)
{
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
fg_ptr = base_type::source_image().row(y_lr + start) + ((x_lr + start) << 2);
do
{
x_count = dimension;
weight_y = weight_array[y_hr];
x_hr = image_subpixel_mask - x_fract;
do
{
int weight = (weight_y * weight_array[x_hr] +
image_filter_size / 2) >>
image_filter_shift;
fg[0] += *fg_ptr++ * weight;
fg[1] += *fg_ptr++ * weight;
fg[2] += *fg_ptr++ * weight;
fg[3] += *fg_ptr++ * weight;
x_hr += image_subpixel_size;
} while(--x_count);
y_hr += image_subpixel_size;
fg_ptr += stride;
} while(--y_count);
fg[0] >>= image_filter_shift;
fg[1] >>= image_filter_shift;
fg[2] >>= image_filter_shift;
fg[3] >>= image_filter_shift;
if(fg[0] < 0) fg[0] = 0;
if(fg[1] < 0) fg[1] = 0;
if(fg[2] < 0) fg[2] = 0;
if(fg[3] < 0) fg[3] = 0;
if(fg[0] > 255) fg[0] = 255;
if(fg[1] > 255) fg[1] = 255;
if(fg[2] > 255) fg[2] = 255;
if(fg[3] > 255) fg[3] = 255;
}
else
{
if(x_lr < start1 || y_lr < start1 ||
x_lr > maxx2 || y_lr > maxy2)
{
fg[Order::R] = back_r;
fg[Order::G] = back_g;
fg[Order::B] = back_b;
fg[Order::A] = back_a;
}
else
{
y_lr = (y >> image_subpixel_shift) + start;
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
do
{
x_count = dimension;
weight_y = weight_array[y_hr];
x_lr = (x >> image_subpixel_shift) + start;
x_hr = image_subpixel_mask - x_fract;
do
{
int weight = (weight_y * weight_array[x_hr] +
image_filter_size / 2) >>
image_filter_shift;
if(x_lr >= 0 && y_lr >= 0 &&
x_lr < int(base_type::source_image().width()) &&
y_lr < int(base_type::source_image().height()))
{
fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2);
fg[0] += *fg_ptr++ * weight;
fg[1] += *fg_ptr++ * weight;
fg[2] += *fg_ptr++ * weight;
fg[3] += *fg_ptr++ * weight;
}
else
{
fg[Order::R] += back_r * weight;
fg[Order::G] += back_g * weight;
fg[Order::B] += back_b * weight;
fg[Order::A] += back_a * weight;
}
x_hr += image_subpixel_size;
x_lr++;
} while(--x_count);
y_hr += image_subpixel_size;
y_lr++;
} while(--y_count);
fg[0] >>= image_filter_shift;
fg[1] >>= image_filter_shift;
fg[2] >>= image_filter_shift;
fg[3] >>= image_filter_shift;
if(fg[0] < 0) fg[0] = 0;
if(fg[1] < 0) fg[1] = 0;
if(fg[2] < 0) fg[2] = 0;
if(fg[3] < 0) fg[3] = 0;
if(fg[0] > 255) fg[0] = 255;
if(fg[1] > 255) fg[1] = 255;
if(fg[2] > 255) fg[2] = 255;
if(fg[3] > 255) fg[3] = 255;
}
}
span->r = fg[Order::R];
span->g = fg[Order::G];
span->b = fg[Order::B];
span->a = fg[Order::A];
++span;
++base_type::interpolator();
} while(--len);
return base_type::allocator().span();
}
};
}
#endif
@@ -0,0 +1,77 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED
#define AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED
#include "agg_basics.h"
namespace agg
{
//===============================================span_interpolator_adaptor
template<class Interpolator, class Distortion>
class span_interpolator_adaptor : public Interpolator
{
public:
typedef Interpolator base_type;
typedef typename base_type::trans_type trans_type;
typedef Distortion distortion_type;
//--------------------------------------------------------------------
span_interpolator_adaptor() {}
span_interpolator_adaptor(const trans_type& trans,
const distortion_type& dist) :
base_type(trans),
m_distortion(&dist)
{
}
//--------------------------------------------------------------------
span_interpolator_adaptor(const trans_type& trans,
const distortion_type& dist,
double x, double y, unsigned len) :
base_type(trans, x, y, len),
m_distortion(&dist)
{
}
//--------------------------------------------------------------------
const distortion_type& distortion() const
{
return *m_distortion;
}
//--------------------------------------------------------------------
void distortion(const distortion_type& dist)
{
m_distortion = dist;
}
//--------------------------------------------------------------------
void coordinates(int* x, int* y) const
{
base_type::coordinates(x, y);
m_distortion->calculate(x, y);
}
private:
//--------------------------------------------------------------------
const distortion_type* m_distortion;
};
}
#endif
@@ -0,0 +1,101 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED
#define AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED
#include "agg_basics.h"
#include "agg_dda_line.h"
#include "agg_trans_affine.h"
namespace agg
{
//================================================span_interpolator_linear
template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
class span_interpolator_linear
{
public:
typedef Transformer trans_type;
enum
{
subpixel_shift = SubpixelShift,
subpixel_size = 1 << subpixel_shift
};
//--------------------------------------------------------------------
span_interpolator_linear() {}
span_interpolator_linear(const trans_type& trans) : m_trans(&trans) {}
span_interpolator_linear(const trans_type& trans,
double x, double y, unsigned len) :
m_trans(&trans)
{
begin(x, y, len);
}
//----------------------------------------------------------------
const trans_type& transformer() const { return *m_trans; }
void transformer(const trans_type& trans) { m_trans = &trans; }
//----------------------------------------------------------------
void begin(double x, double y, unsigned len)
{
double tx;
double ty;
tx = x;
ty = y;
m_trans->transform(&tx, &ty);
int x1 = int(tx * subpixel_size);
int y1 = int(ty * subpixel_size);
tx = x + len;
ty = y;
m_trans->transform(&tx, &ty);
int x2 = int(tx * subpixel_size);
int y2 = int(ty * subpixel_size);
m_li_x = dda2_line_interpolator(x1, x2, len);
m_li_y = dda2_line_interpolator(y1, y2, len);
}
//----------------------------------------------------------------
void operator++()
{
++m_li_x;
++m_li_y;
}
//----------------------------------------------------------------
void coordinates(int* x, int* y) const
{
*x = m_li_x.y();
*y = m_li_y.y();
}
private:
const trans_type* m_trans;
dda2_line_interpolator m_li_x;
dda2_line_interpolator m_li_y;
};
}
#endif
@@ -0,0 +1,97 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Horizontal span interpolator for use with an arbitrary transformer
// The efficiency highly depends on the operations done in the transformer
//
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED
#define AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED
#include "agg_basics.h"
namespace agg
{
//=================================================span_interpolator_trans
template<class Transformer, unsigned SubpixelShift = 8>
class span_interpolator_trans
{
public:
typedef Transformer trans_type;
enum
{
subpixel_shift = SubpixelShift,
subpixel_size = 1 << subpixel_shift
};
//--------------------------------------------------------------------
span_interpolator_trans() {}
span_interpolator_trans(const trans_type& trans) : m_trans(&trans) {}
span_interpolator_trans(const trans_type& trans,
double x, double y, unsigned) :
m_trans(&trans)
{
begin(x, y, 0);
}
//----------------------------------------------------------------
const trans_type& transformer() const { return *m_trans; }
void transformer(const trans_type& trans) { m_trans = &trans; }
//----------------------------------------------------------------
void begin(double x, double y, unsigned)
{
m_x = x;
m_y = y;
transform();
}
//----------------------------------------------------------------
void operator++()
{
m_x += 1.0;
transform();
}
//----------------------------------------------------------------
void coordinates(int* x, int* y) const
{
*x = m_ix;
*y = m_iy;
}
private:
//----------------------------------------------------------------
void transform()
{
double x = m_x;
double y = m_y;
m_trans->transform(&x, &y);
m_ix = int(x * subpixel_size);
m_iy = int(y * subpixel_size);
}
const trans_type* m_trans;
double m_x;
double m_y;
int m_ix;
int m_iy;
};
}
#endif
+78
View File
@@ -0,0 +1,78 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_PATTERN_INCLUDED
#define AGG_SPAN_PATTERN_INCLUDED
#include "agg_basics.h"
#include "agg_rendering_buffer.h"
#include "agg_span_generator.h"
namespace agg
{
//--------------------------------------------------------span_pattern
template<class ColorT, class AlphaT, class Allocator>
class span_pattern : public span_generator<ColorT, Allocator>
{
public:
typedef ColorT color_type;
typedef AlphaT alpha_type;
typedef Allocator alloc_type;
//----------------------------------------------------------------
span_pattern(alloc_type& alloc) :
span_generator<color_type, alloc_type>(alloc)
{}
//----------------------------------------------------------------
span_pattern(alloc_type& alloc,
const rendering_buffer& src,
unsigned offset_x, unsigned offset_y,
alpha_type alpha) :
span_generator<color_type, alloc_type>(alloc),
m_src(&src),
m_offset_x(offset_x),
m_offset_y(offset_y),
m_alpha(alpha)
{}
//----------------------------------------------------------------
const rendering_buffer& source_image() const { return *m_src; }
unsigned offset_x() const { return m_offset_x; }
unsigned offset_y() const { return m_offset_y; }
alpha_type alpha() const { return m_alpha; }
//----------------------------------------------------------------
void source_image(const rendering_buffer& v) { m_src = &v; }
void offset_x(unsigned v) { m_offset_x = v; }
void offset_y(unsigned v) { m_offset_y = v; }
void alpha(alpha_type v) { m_alpha = v; }
//----------------------------------------------------------------
private:
const rendering_buffer* m_src;
unsigned m_offset_x;
unsigned m_offset_y;
alpha_type m_alpha;
};
}
#endif
+79
View File
@@ -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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_PATTERN_RGB24_INCLUDED
#define AGG_SPAN_PATTERN_RGB24_INCLUDED
#include "agg_basics.h"
#include "agg_pixfmt_rgb24.h"
#include "agg_span_pattern.h"
namespace agg
{
//=======================================================span_pattern_rgb24
template<class Order, class Allocator = span_allocator<rgba8> >
class span_pattern_rgb24 : public span_pattern<rgba8, int8u, Allocator>
{
public:
typedef Allocator alloc_type;
typedef rgba8 color_type;
typedef span_pattern<color_type, int8u, alloc_type> base_type;
//--------------------------------------------------------------------
span_pattern_rgb24(alloc_type& alloc) : base_type(alloc) {}
//----------------------------------------------------------------
span_pattern_rgb24(alloc_type& alloc,
const rendering_buffer& src,
unsigned offset_x, unsigned offset_y,
int8u alpha = 255) :
base_type(alloc, src, offset_x, offset_y, alpha)
{}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
color_type* span = base_type::allocator().span();
unsigned sx = (base_type::offset_x() + x) % base_type::source_image().width();
unsigned wp = base_type::source_image().width() * 3;
const int8u* p = base_type::source_image().row((base_type::offset_y() + y) % base_type::source_image().height());
p += sx * 3;
do
{
span->r = p[Order::R];
span->g = p[Order::G];
span->b = p[Order::B];
span->a = base_type::alpha();
p += 3;
++sx;
++span;
if(sx >= base_type::source_image().width())
{
sx -= base_type::source_image().width();
p -= wp;
}
}
while(--len);
return base_type::allocator().span();
}
};
}
#endif
@@ -0,0 +1,77 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_PATTERN_RGBA32_INCLUDED
#define AGG_SPAN_PATTERN_RGBA32_INCLUDED
#include "agg_basics.h"
#include "agg_pixfmt_rgba32.h"
#include "agg_span_pattern.h"
namespace agg
{
//======================================================span_pattern_rgba32
template<class Order, class Allocator = span_allocator<rgba8> >
class span_pattern_rgba32 : public span_pattern<rgba8, int8u, Allocator>
{
public:
typedef Allocator alloc_type;
typedef rgba8 color_type;
typedef span_pattern<color_type, int8u, alloc_type> base_type;
//--------------------------------------------------------------------
span_pattern_rgba32(alloc_type& alloc) : base_type(alloc) {}
//----------------------------------------------------------------
span_pattern_rgba32(alloc_type& alloc,
const rendering_buffer& src,
unsigned offset_x, unsigned offset_y) :
base_type(alloc, src, offset_x, offset_y, 0)
{}
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
color_type* span = base_type::allocator().span();
unsigned sx = (base_type::offset_x() + x) % base_type::source_image().width();
unsigned wp = base_type::source_image().width() << 2;
const int8u* p = base_type::source_image().row((base_type::offset_y() + y) % base_type::source_image().height());
p += sx << 2;
do
{
span->r = p[Order::R];
span->g = p[Order::G];
span->b = p[Order::B];
span->a = p[Order::A];
p += 4;
++sx;
++span;
if(sx >= base_type::source_image().width())
{
sx -= base_type::source_image().width();
p -= wp;
}
}
while(--len);
return base_type::allocator().span();
}
};
}
#endif
+63
View File
@@ -0,0 +1,63 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// span_solid_rgba8
//
//----------------------------------------------------------------------------
#ifndef AGG_SPAN_SOLID_INCLUDED
#define AGG_SPAN_SOLID_INCLUDED
#include "agg_basics.h"
#include "agg_span_generator.h"
namespace agg
{
//--------------------------------------------------------------span_solid
template<class ColorT, class Allocator = span_allocator<ColorT> >
class span_solid : public span_generator<ColorT, Allocator>
{
public:
typedef Allocator alloc_type;
typedef ColorT color_type;
typedef span_generator<color_type, alloc_type> base_type;
//--------------------------------------------------------------------
span_solid(alloc_type& alloc) : base_type(alloc) {}
//--------------------------------------------------------------------
void color(const color_type& c) { m_color = c; }
const color_type& color() const { return m_color; }
//--------------------------------------------------------------------
color_type* generate(int x, int y, unsigned len)
{
color_type* span = base_type::allocator().span();
do
{
*span++ = m_color;
}
while(--len);
return base_type::allocator().span();
}
private:
color_type m_color;
};
}
#endif
+339
View File
@@ -0,0 +1,339 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Affine transformation classes.
//
//----------------------------------------------------------------------------
#ifndef AGG_TRANS_AFFINE_INCLUDED
#define AGG_TRANS_AFFINE_INCLUDED
#include <math.h>
#include "agg_basics.h"
namespace agg
{
const double affine_epsilon = 1e-14; // About of precision of doubles
//============================================================trans_affine
//
// See Implementation agg_trans_affine.cpp
//
// Affine transformation are linear transformations in Cartesian coordinates
// (strictly speaking not only in Cartesian, but for the beginning we will
// think so). They are rotation, scaling, translation and skewing.
// After any affine transformation a line segment remains a line segment
// and it will never become a curve.
//
// There will be no math about matrix calculations, since it has been
// described many times. Ask yourself a very simple question:
// "why do we need to understand and use some matrix stuff instead of just
// rotating, scaling and so on". The answers are:
//
// 1. Any combination of transformations can be done by only 4 multiplications
// and 4 additions in floating point.
// 2. One matrix transformation is equivalent to the number of consecutive
// discrete transformations, i.e. the matrix "accumulates" all transformations
// in the order of their settings. Suppose we have 4 transformations:
// * rotate by 30 degrees,
// * scale X to 2.0,
// * scale Y to 1.5,
// * move to (100, 100).
// The result will depend on the order of these transformations,
// and the advantage of matrix is that the sequence of discret calls:
// rotate(30), scaleX(2.0), scaleY(1.5), move(100,100)
// will have exactly the same result as the following matrix transformations:
//
// affine_matrix m;
// m *= rotate_matrix(30);
// m *= scaleX_matrix(2.0);
// m *= scaleY_matrix(1.5);
// m *= move_matrix(100,100);
//
// m.transform_my_point_at_last(x, y);
//
// What is the good of it? In real life we will set-up the matrix only once
// and then transform many points, let alone the convenience to set any
// combination of transformations.
//
// So, how to use it? Very easy - literally as it's shown above. Not quite,
// let us write a correct example:
//
// agg::trans_affine m;
// m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0);
// m *= agg::trans_affine_scaling(2.0, 1.5);
// m *= agg::trans_affine_translation(100.0, 100.0);
// m.transform(&x, &y);
//
// The affine matrix is all you need to perform any linear transformation,
// but all transformations have origin point (0,0). It means that we need to
// use 2 translations if we want to rotate someting around (100,100):
//
// m *= agg::trans_affine_translation(-100.0, -100.0); // move to (0,0)
// m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate
// m *= agg::trans_affine_translation(100.0, 100.0); // move back to (100,100)
//----------------------------------------------------------------------
class trans_affine
{
public:
//------------------------------------------ Construction
// Construct an identity matrix - it does not transform anything
trans_affine() :
m0(1.0), m1(0.0), m2(0.0), m3(1.0), m4(0.0), m5(0.0)
{}
// Construct a custom matrix. Usually used in derived classes
trans_affine(double v0, double v1, double v2, double v3, double v4, double v5) :
m0(v0), m1(v1), m2(v2), m3(v3), m4(v4), m5(v5)
{}
// Construct a matrix to transform a parallelogram to another one.
trans_affine(const double* rect, const double* parl)
{
parl_to_parl(rect, parl);
}
// Construct a matrix to transform a rectangle to a parallelogram.
trans_affine(double x1, double y1, double x2, double y2,
const double* parl)
{
rect_to_parl(x1, y1, x2, y2, parl);
}
// Construct a matrix to transform a parallelogram to a rectangle.
trans_affine(const double* parl,
double x1, double y1, double x2, double y2)
{
parl_to_rect(parl, x1, y1, x2, y2);
}
//---------------------------------- Parellelogram transformations
// Calculate a matrix to transform a parallelogram to another one.
// src and dst are pointers to arrays of three points
// (double[6], x,y,...) that identify three corners of the
// parallelograms assuming implicit fourth points.
// There are also transformations rectangtle to parallelogram and
// parellelogram to rectangle
const trans_affine& parl_to_parl(const double* src,
const double* dst);
const trans_affine& rect_to_parl(double x1, double y1,
double x2, double y2,
const double* parl);
const trans_affine& parl_to_rect(const double* parl,
double x1, double y1,
double x2, double y2);
//------------------------------------------ Operations
// Reset - actually load an identity matrix
const trans_affine& reset();
// Multiply matrix to another one
const trans_affine& multiply(const trans_affine& m);
// Multiply "m" to "this" and assign the result to "this"
const trans_affine& premultiply(const trans_affine& m);
// Invert matrix. Do not try to invert degenerate matrices,
// there's no check for validity. If you set scale to 0 and
// then try to invert matrix, expect unpredictable result.
const trans_affine& invert();
// Mirroring around X
const trans_affine& flip_x();
// Mirroring around Y
const trans_affine& flip_y();
//------------------------------------------- Load/Store
// Store matrix to an array [6] of double
void store_to(double* m) const
{
*m++ = m0; *m++ = m1; *m++ = m2; *m++ = m3; *m++ = m4; *m++ = m5;
}
// Load matrix from an array [6] of double
const trans_affine& load_from(const double* m)
{
m0 = *m++; m1 = *m++; m2 = *m++; m3 = *m++; m4 = *m++; m5 = *m++;
return *this;
}
//------------------------------------------- Operators
// Multiply current matrix to another one
const trans_affine& operator *= (const trans_affine& m)
{
return multiply(m);
}
// Multiply current matrix to another one and return
// the result in a separete matrix.
trans_affine operator * (const trans_affine& m)
{
return trans_affine(*this).multiply(m);
}
// Calculate and return the inverse matrix
trans_affine operator ~ () const
{
trans_affine ret = *this;
return ret.invert();
}
// Equal operator with default epsilon
bool operator == (const trans_affine& m) const
{
return is_equal(m, affine_epsilon);
}
// Not Equal operator with default epsilon
bool operator != (const trans_affine& m) const
{
return !is_equal(m, affine_epsilon);
}
//-------------------------------------------- Transformations
// Direct transformation x and y
void transform(double* x, double* y) const;
// Inverse transformation x and y. It works slower than the
// direct transformation, so if the performance is critical
// it's better to invert() the matrix and then use transform()
void inverse_transform(double* x, double* y) const;
//-------------------------------------------- Auxiliary
// Calculate the determinant of matrix
double determinant() const
{
return 1.0 / (m0 * m3 - m1 * m2);
}
// Get the average scale (by X and Y).
// Basically used to calculate the approximation_scale when
// decomposinting curves into line segments.
double scale() const;
// Check to see if it's an identity matrix
bool is_identity(double epsilon = affine_epsilon) const;
// Check to see if two matrices are equal
bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const;
// Determine the major parameters. Use carefully considering degenerate matrices
double rotation() const;
void translation(double* dx, double* dy) const;
void scaling(double* sx, double* sy) const;
private:
double m0;
double m1;
double m2;
double m3;
double m4;
double m5;
};
//------------------------------------------------------------------------
inline void trans_affine::transform(double* x, double* y) const
{
register double tx = *x;
*x = tx * m0 + *y * m2 + m4;
*y = tx * m1 + *y * m3 + m5;
}
//------------------------------------------------------------------------
inline void trans_affine::inverse_transform(double* x, double* y) const
{
register double d = determinant();
register double a = (*x - m4) * d;
register double b = (*y - m5) * d;
*x = a * m3 - b * m2;
*y = b * m0 - a * m1;
}
//------------------------------------------------------------------------
inline double trans_affine::scale() const
{
double x = 0.707106781 * m0 + 0.707106781 * m2;
double y = 0.707106781 * m1 + 0.707106781 * m3;
return sqrt(x*x + y*y);
}
//------------------------------------------------------------------------
inline const trans_affine& trans_affine::premultiply(const trans_affine& m)
{
trans_affine t = m;
return *this = t.multiply(*this);
}
//====================================================trans_affine_rotation
// Rotation matrix. sin() and cos() are calculated twice for the same angle.
// There's no harm because the performance of sin()/cos() is very good on all
// modern processors. Besides, this operation is not going to be invoked too
// often.
class trans_affine_rotation : public trans_affine
{
public:
trans_affine_rotation(double a) :
trans_affine(cos(a), sin(a), -sin(a), cos(a), 0.0, 0.0)
{}
};
//====================================================trans_affine_scaling
// Scaling matrix. sx, sy - scale coefficients by X and Y respectively
class trans_affine_scaling : public trans_affine
{
public:
trans_affine_scaling(double sx, double sy) :
trans_affine(sx, 0.0, 0.0, sy, 0.0, 0.0)
{}
trans_affine_scaling(double s) :
trans_affine(s, 0.0, 0.0, s, 0.0, 0.0)
{}
};
//================================================trans_affine_translation
// Translation matrix
class trans_affine_translation : public trans_affine
{
public:
trans_affine_translation(double tx, double ty) :
trans_affine(1.0, 0.0, 0.0, 1.0, tx, ty)
{}
};
//====================================================trans_affine_skewing
// Sckewing (shear) matrix
class trans_affine_skewing : public trans_affine
{
public:
trans_affine_skewing(double sx, double sy) :
trans_affine(1.0, tan(sy), tan(sx), 1.0, 0.0, 0.0)
{}
};
}
#endif
+134
View File
@@ -0,0 +1,134 @@
//----------------------------------------------------------------------------
// 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: [email protected]
// [email protected]
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Bilinear 2D transformations
//
//----------------------------------------------------------------------------
#ifndef AGG_TRANS_BILINEAR_INCLUDED
#define AGG_TRANS_BILINEAR_INCLUDED
#include "agg_basics.h"
#include "agg_simul_eq.h"
namespace agg
{
//==========================================================trans_bilinear
class trans_bilinear
{
public:
//--------------------------------------------------------------------
trans_bilinear() : m_valid(false) {}
//--------------------------------------------------------------------
// Arbitrary quadrangle transformations
trans_bilinear(const double* src, const double* dst)
{
quad_to_quad(src, dst);
}
//--------------------------------------------------------------------
// Direct transformations
trans_bilinear(double x1, double y1, double x2, double y2,
const double* quad)
{
rect_to_quad(x1, y1, x2, y2, quad);
}
//--------------------------------------------------------------------
// Reverse transformations
trans_bilinear(const double* quad,
double x1, double y1, double x2, double y2)
{
quad_to_rect(quad, x1, y1, x2, y2);
}
//--------------------------------------------------------------------
// Set the transformations using two arbitrary quadrangles.
void quad_to_quad(const double* src, const double* dst)
{
double left[4][4];
double right[4][2];
unsigned i;
for(i = 0; i < 4; i++)
{
unsigned ix = i * 2;
unsigned iy = ix + 1;
left[i][0] = 1.0;
left[i][1] = src[ix] * src[iy];
left[i][2] = src[ix];
left[i][3] = src[iy];
right[i][0] = dst[ix];
right[i][1] = dst[iy];
}
m_valid = simul_eq<4, 2>::solve(left, right, m_mtx);
}
//--------------------------------------------------------------------
// Set the direct transformations, i.e., rectangle -> quadrangle
void rect_to_quad(double x1, double y1, double x2, double y2,
const double* quad)
{
double src[8];
src[0] = src[6] = x1;
src[2] = src[4] = x2;
src[1] = src[3] = y1;
src[5] = src[7] = y2;
quad_to_quad(src, quad);
}
//--------------------------------------------------------------------
// Set the reverse transformations, i.e., quadrangle -> rectangle
void quad_to_rect(const double* quad,
double x1, double y1, double x2, double y2)
{
double dst[8];
dst[0] = dst[6] = x1;
dst[2] = dst[4] = x2;
dst[1] = dst[3] = y1;
dst[5] = dst[7] = y2;
quad_to_quad(quad, dst);
}
//--------------------------------------------------------------------
// Check if the equations were solved successfully
bool is_valid() const { return m_valid; }
//--------------------------------------------------------------------
// Transform a point (x, y)
void transform(double* x, double* y) const
{
double tx = *x;
double ty = *y;
double xy = tx * ty;
*x = m_mtx[0][0] + m_mtx[1][0] * xy + m_mtx[2][0] * tx + m_mtx[3][0] * ty;
*y = m_mtx[0][1] + m_mtx[1][1] * xy + m_mtx[2][1] * tx + m_mtx[3][1] * ty;
}
private:
double m_mtx[4][2];
bool m_valid;
};
}
#endif

Some files were not shown because too many files have changed in this diff Show More