precommit

This commit is contained in:
Mathis Logemann 2022-08-17 17:19:59 +02:00
parent f6bcdac258
commit f48589738f
234 changed files with 58907 additions and 58207 deletions

16
.pre-commit-config.yaml Normal file
View file

@ -0,0 +1,16 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
hooks:
- id: trailing-whitespace
files: ^.*\.cmake|CMakeLists\.txt$
- id: end-of-file-fixer
files: ^.*\.cmake|CMakeLists\.txt$
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v14.0.6
hooks:
- id: clang-format
types_or: [c++, c]

View file

@ -23,477 +23,427 @@
#include "agg_basics.h" #include "agg_basics.h"
#include "agg_rendering_buffer.h" #include "agg_rendering_buffer.h"
namespace agg namespace agg {
//===================================================one_component_mask_u8
struct one_component_mask_u8
{ {
//===================================================one_component_mask_u8 static unsigned calculate(const int8u* p) { return *p; }
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; }
};
//=====================================================rgb_to_gray_mask_u8 //==========================================================alpha_mask_u8
template<unsigned R, unsigned G, unsigned B> template<unsigned Step = 1, unsigned Offset = 0, class MaskF = one_component_mask_u8>
struct rgb_to_gray_mask_u8 class alpha_mask_u8
{
public:
typedef int8u cover_type;
typedef alpha_mask_u8<Step, Offset, MaskF> self_type;
enum cover_scale_e { cover_shift = 8, cover_none = 0, cover_full = 255 };
alpha_mask_u8()
: m_rbuf(0)
{}
explicit 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
{ {
static unsigned calculate(const int8u* p) if (x >= 0 && y >= 0 && x < (int)m_rbuf->width() && y < (int)m_rbuf->height())
{ {
return (p[R]*77 + p[G]*150 + p[B]*29) >> 8; return (cover_type)m_mask_function.calculate(m_rbuf->row_ptr(y) + x * Step + Offset);
} }
}; return 0;
}
//==========================================================alpha_mask_u8 //--------------------------------------------------------------------
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8> cover_type combine_pixel(int x, int y, cover_type val) const
class alpha_mask_u8
{ {
public: if (x >= 0 && y >= 0 && x < (int)m_rbuf->width() && y < (int)m_rbuf->height())
typedef int8u cover_type;
typedef alpha_mask_u8<Step, Offset, MaskF> self_type;
enum cover_scale_e
{ {
cover_shift = 8, return (
cover_none = 0, cover_type)((cover_full + val * m_mask_function.calculate(m_rbuf->row_ptr(y) + x * Step + Offset)) >>
cover_full = 255 cover_shift);
}; }
return 0;
}
alpha_mask_u8() : m_rbuf(0) {} //--------------------------------------------------------------------
explicit alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {} 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;
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; } int count = num_pix;
cover_type* covers = dst;
MaskF& mask_function() { return m_mask_function; } if (y < 0 || y > ymax)
const MaskF& mask_function() const { return m_mask_function; }
//--------------------------------------------------------------------
cover_type pixel(int x, int y) const
{ {
if(x >= 0 && y >= 0 && memset(dst, 0, num_pix * sizeof(cover_type));
x < (int)m_rbuf->width() && return;
y < (int)m_rbuf->height())
{
return (cover_type)m_mask_function.calculate(
m_rbuf->row_ptr(y) + x * Step + Offset);
}
return 0;
} }
//-------------------------------------------------------------------- if (x < 0)
cover_type combine_pixel(int x, int y, cover_type val) const
{ {
if(x >= 0 && y >= 0 && count += x;
x < (int)m_rbuf->width() && if (count <= 0)
y < (int)m_rbuf->height())
{
return (cover_type)((cover_full + val *
m_mask_function.calculate(
m_rbuf->row_ptr(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)); memset(dst, 0, num_pix * sizeof(cover_type));
return; return;
} }
memset(covers, 0, -x * sizeof(cover_type));
if(x < 0) covers -= x;
{ 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_ptr(y) + x * Step + Offset;
do
{
*covers++ = (cover_type)m_mask_function.calculate(mask);
mask += Step;
}
while(--count);
} }
if (x + count > xmax)
//--------------------------------------------------------------------
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
{ {
int xmax = m_rbuf->width() - 1; int rest = x + count - xmax - 1;
int ymax = m_rbuf->height() - 1; count -= rest;
if (count <= 0)
int count = num_pix;
cover_type* covers = dst;
if(y < 0 || y > ymax)
{ {
memset(dst, 0, num_pix * sizeof(cover_type)); memset(dst, 0, num_pix * sizeof(cover_type));
return; return;
} }
memset(covers + count, 0, rest * sizeof(cover_type));
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_ptr(y) + x * Step + Offset;
do
{
*covers = (cover_type)((cover_full + (*covers) *
m_mask_function.calculate(mask)) >>
cover_shift);
++covers;
mask += Step;
}
while(--count);
} }
//-------------------------------------------------------------------- const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const do
{ {
int xmax = m_rbuf->width() - 1; *covers++ = (cover_type)m_mask_function.calculate(mask);
int ymax = m_rbuf->height() - 1; mask += Step;
} while (--count);
}
int count = num_pix; //--------------------------------------------------------------------
cover_type* covers = dst; void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
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_ptr(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_ptr(y) + x * Step + Offset;
do
{
*covers = (cover_type)((cover_full + (*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: int xmax = m_rbuf->width() - 1;
typedef int8u cover_type; int ymax = m_rbuf->height() - 1;
typedef amask_no_clip_u8<Step, Offset, MaskF> self_type;
enum cover_scale_e int count = num_pix;
cover_type* covers = dst;
if (y < 0 || y > ymax)
{ {
cover_shift = 8, memset(dst, 0, num_pix * sizeof(cover_type));
cover_none = 0, return;
cover_full = 255
};
amask_no_clip_u8() : m_rbuf(0) {}
explicit 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_ptr(y) + x * Step + Offset);
} }
if (x < 0)
//--------------------------------------------------------------------
cover_type combine_pixel(int x, int y, cover_type val) const
{ {
return (cover_type)((cover_full + val * count += x;
m_mask_function.calculate( if (count <= 0)
m_rbuf->row_ptr(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_ptr(y) + x * Step + Offset;
do
{ {
*dst++ = (cover_type)m_mask_function.calculate(mask); memset(dst, 0, num_pix * sizeof(cover_type));
mask += Step; return;
} }
while(--num_pix); memset(covers, 0, -x * sizeof(cover_type));
covers -= x;
x = 0;
} }
if (x + count > xmax)
//--------------------------------------------------------------------
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
{ {
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; int rest = x + count - xmax - 1;
do count -= rest;
if (count <= 0)
{ {
*dst = (cover_type)((cover_full + (*dst) * memset(dst, 0, num_pix * sizeof(cover_type));
m_mask_function.calculate(mask)) >> return;
cover_shift);
++dst;
mask += Step;
} }
while(--num_pix); memset(covers + count, 0, rest * sizeof(cover_type));
} }
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
//-------------------------------------------------------------------- do
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
{ {
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; *covers = (cover_type)((cover_full + (*covers) * m_mask_function.calculate(mask)) >> cover_shift);
do ++covers;
{ mask += Step;
*dst++ = (cover_type)m_mask_function.calculate(mask); } while (--count);
mask += m_rbuf->stride(); }
}
while(--num_pix);
}
//--------------------------------------------------------------------
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;
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const cover_type* covers = dst;
if (x < 0 || x > xmax)
{ {
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; memset(dst, 0, num_pix * sizeof(cover_type));
do return;
{
*dst = (cover_type)((cover_full + (*dst) *
m_mask_function.calculate(mask)) >>
cover_shift);
++dst;
mask += m_rbuf->stride();
}
while(--num_pix);
} }
private: if (y < 0)
amask_no_clip_u8(const self_type&); {
const self_type& operator = (const self_type&); 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;
}
rendering_buffer* m_rbuf; if (y + count > ymax)
MaskF m_mask_function; {
}; 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_ptr(y) + x * Step + Offset;
do
{
*covers++ = (cover_type)m_mask_function.calculate(mask);
mask += m_rbuf->stride();
} while (--count);
}
typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8 //--------------------------------------------------------------------
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;
typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r int count = num_pix;
typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g; //----amask_no_clip_rgb24g cover_type* covers = dst;
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 if (x < 0 || x > xmax)
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 memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r if (y < 0)
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 count += y;
typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a if (count <= 0)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
memset(covers, 0, -y * sizeof(cover_type));
covers -= y;
y = 0;
}
typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r if (y + count > ymax)
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 int rest = y + count - ymax - 1;
typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a count -= rest;
if (count <= 0)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
memset(covers + count, 0, rest * sizeof(cover_type));
}
typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g do
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 *covers = (cover_type)((cover_full + (*covers) * m_mask_function.calculate(mask)) >> cover_shift);
++covers;
mask += m_rbuf->stride();
} while (--count);
}
typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r private:
typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g alpha_mask_u8(const self_type&);
typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b const self_type& operator=(const self_type&);
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 rendering_buffer* m_rbuf;
typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray; //----amask_no_clip_bgr24gray MaskF m_mask_function;
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
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_scale_e { cover_shift = 8, cover_none = 0, cover_full = 255 };
amask_no_clip_u8()
: m_rbuf(0)
{}
explicit 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_ptr(y) + x * Step + Offset);
}
//--------------------------------------------------------------------
cover_type combine_pixel(int x, int y, cover_type val) const
{
return (cover_type)((cover_full + val * m_mask_function.calculate(m_rbuf->row_ptr(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_ptr(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_ptr(y) + x * Step + Offset;
do
{
*dst = (cover_type)((cover_full + (*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_ptr(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_ptr(y) + x * Step + Offset;
do
{
*dst = (cover_type)((cover_full + (*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
} // namespace agg
#endif #endif

View file

@ -23,52 +23,46 @@
#include <cmath> #include <cmath>
#include "agg_basics.h" #include "agg_basics.h"
namespace agg 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);
//=====================================================================arc void init(double x, double y, double rx, double ry, double a1, double a2, bool ccw = true);
//
// 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, void approximation_scale(double s);
double rx, double ry, double approximation_scale() const { return m_scale; }
double a1, double a2,
bool ccw=true);
void approximation_scale(double s); void rewind(unsigned);
double approximation_scale() const { return m_scale; } unsigned vertex(double* x, double* y);
void rewind(unsigned); private:
unsigned vertex(double* x, double* y); void normalize(double a1, double a2, bool ccw);
private: double m_x;
void normalize(double a1, double a2, bool ccw); double m_y;
double m_rx;
double m_x; double m_ry;
double m_y; double m_angle;
double m_rx; double m_start;
double m_ry; double m_end;
double m_angle; double m_scale;
double m_start; double m_da;
double m_end; bool m_ccw;
double m_scale; bool m_initialized;
double m_da; unsigned m_path_cmd;
bool m_ccw; };
bool m_initialized;
unsigned m_path_cmd;
};
}
} // namespace agg
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -21,62 +21,61 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//===============================================================arrowhead
//
// See implementation agg_arrowhead.cpp
//
class arrowhead
{ {
public:
arrowhead();
//===============================================================arrowhead void head(double d1, double d2, double d3, double d4)
//
// See implementation agg_arrowhead.cpp
//
class arrowhead
{ {
public: m_head_d1 = d1;
arrowhead(); m_head_d2 = d2;
m_head_d3 = d3;
m_head_d4 = d4;
m_head_flag = true;
}
void head(double d1, double d2, double d3, double d4) void head() { m_head_flag = true; }
{ void no_head() { m_head_flag = false; }
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 tail(double d1, double d2, double d3, double d4)
void no_head() { m_head_flag = false; } {
m_tail_d1 = d1;
m_tail_d2 = d2;
m_tail_d3 = d3;
m_tail_d4 = d4;
m_tail_flag = true;
}
void tail(double d1, double d2, double d3, double d4) void tail() { m_tail_flag = true; }
{ void no_tail() { m_tail_flag = false; }
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 rewind(unsigned path_id);
void no_tail() { m_tail_flag = false; } unsigned vertex(double* x, double* y);
void rewind(unsigned path_id); private:
unsigned vertex(double* x, double* y); 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;
};
private: } // namespace agg
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 #endif

View file

@ -23,41 +23,41 @@
#ifdef AGG_CUSTOM_ALLOCATOR #ifdef AGG_CUSTOM_ALLOCATOR
#include "agg_allocator.h" #include "agg_allocator.h"
#else #else
namespace agg namespace agg {
// The policy of all AGG containers and memory allocation strategy
// in general is that no allocated data requires explicit construction.
// It means that the allocator can be really simple; you can even
// replace new/delete to malloc/free. The constructors and destructors
// won't be called in this case, however everything will remain working.
// The second argument of deallocate() is the size of the allocated
// block. You can use this information if you wish.
//------------------------------------------------------------pod_allocator
template<class T>
struct pod_allocator
{ {
// The policy of all AGG containers and memory allocation strategy // static T* allocate(unsigned num) { return static_cast<T*>(::operator new(sizeof(T)*num));}
// in general is that no allocated data requires explicit construction. // static void deallocate(T* ptr, unsigned) { ::operator delete(ptr) ;}
// It means that the allocator can be really simple; you can even static T* allocate(unsigned num) { return new T[num]; }
// replace new/delete to malloc/free. The constructors and destructors static void deallocate(T* ptr, unsigned) { delete[] ptr; }
// won't be called in this case, however everything will remain working. };
// The second argument of deallocate() is the size of the allocated
// block. You can use this information if you wish.
//------------------------------------------------------------pod_allocator
template<class T> struct pod_allocator
{
//static T* allocate(unsigned num) { return static_cast<T*>(::operator new(sizeof(T)*num));}
//static void deallocate(T* ptr, unsigned) { ::operator delete(ptr) ;}
static T* allocate(unsigned num) { return new T [num]; }
static void deallocate(T* ptr, unsigned) { delete [] ptr; }
};
// Single object allocator. It's also can be replaced with your custom // Single object allocator. It's also can be replaced with your custom
// allocator. The difference is that it can only allocate a single // allocator. The difference is that it can only allocate a single
// object and the constructor and destructor must be called. // object and the constructor and destructor must be called.
// In AGG there is no need to allocate an array of objects with // In AGG there is no need to allocate an array of objects with
// calling their constructors (only single ones). So that, if you // calling their constructors (only single ones). So that, if you
// replace these new/delete to malloc/free make sure that the in-place // replace these new/delete to malloc/free make sure that the in-place
// new is called and take care of calling the destructor too. // new is called and take care of calling the destructor too.
//------------------------------------------------------------obj_allocator //------------------------------------------------------------obj_allocator
template<class T> struct obj_allocator template<class T>
{ struct obj_allocator
static T* allocate() { return new T; } {
static void deallocate(T* ptr) { delete ptr; } static T* allocate() { return new T; }
}; static void deallocate(T* ptr) { delete ptr; }
} };
} // namespace agg
#endif #endif
//-------------------------------------------------------- Default basic types //-------------------------------------------------------- Default basic types
// //
// If the compiler has different capacity of the basic types you can redefine // If the compiler has different capacity of the basic types you can redefine
@ -98,7 +98,7 @@ namespace agg
//------------------------------------------------ Some fixes for MS Visual C++ //------------------------------------------------ Some fixes for MS Visual C++
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma warning(disable:4786) // Identifier was truncated... #pragma warning(disable: 4786) // Identifier was truncated...
#endif #endif
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -107,372 +107,407 @@ namespace agg
#define AGG_INLINE inline #define AGG_INLINE inline
#endif #endif
namespace agg namespace agg {
//-------------------------------------------------------------------------
typedef AGG_INT8 int8; //----int8
typedef AGG_INT8U int8u; //----int8u
typedef AGG_INT16 int16; //----int16
typedef AGG_INT16U int16u; //----int16u
typedef AGG_INT32 int32; //----int32
typedef AGG_INT32U int32u; //----int32u
typedef AGG_INT64 int64; //----int64
typedef AGG_INT64U int64u; //----int64u
AGG_INLINE int iround(double v)
{ {
//------------------------------------------------------------------------- return int((v < 0.0) ? v - 0.5 : v + 0.5);
typedef AGG_INT8 int8; //----int8 }
typedef AGG_INT8U int8u; //----int8u AGG_INLINE int uround(double v)
typedef AGG_INT16 int16; //----int16 {
typedef AGG_INT16U int16u; //----int16u return unsigned(v + 0.5);
typedef AGG_INT32 int32; //----int32 }
typedef AGG_INT32U int32u; //----int32u AGG_INLINE unsigned ufloor(double v)
typedef AGG_INT64 int64; //----int64 {
typedef AGG_INT64U int64u; //----int64u return unsigned(v);
}
AGG_INLINE int iround(double v) AGG_INLINE unsigned uceil(double v)
{ {
return int((v < 0.0) ? v - 0.5 : v + 0.5); return unsigned(std::ceil(v));
}
AGG_INLINE int uround(double v)
{
return unsigned(v + 0.5);
}
AGG_INLINE unsigned ufloor(double v)
{
return unsigned(v);
}
AGG_INLINE unsigned uceil(double v)
{
return unsigned(std::ceil(v));
}
//---------------------------------------------------------------saturation
template<int Limit> struct saturation
{
AGG_INLINE static int iround(double v)
{
if(v < double(-Limit)) return -Limit;
if(v > double( Limit)) return Limit;
return agg::iround(v);
}
};
//------------------------------------------------------------------mul_one
template<unsigned Shift> struct mul_one
{
AGG_INLINE static unsigned mul(unsigned a, unsigned b)
{
unsigned q = a * b + (1 << (Shift-1));
return (q + (q >> Shift)) >> Shift;
}
};
//-------------------------------------------------------------------------
typedef unsigned char cover_type; //----cover_type
enum cover_scale_e
{
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
};
//----------------------------------------------------poly_subpixel_scale_e
// These constants determine the subpixel accuracy, to be more precise,
// the number of bits of the fractional part of the coordinates.
// The possible coordinate capacity in bits can be calculated by formula:
// sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and
// 8-bits fractional part the capacity is 24 bits.
enum poly_subpixel_scale_e
{
poly_subpixel_shift = 8, //----poly_subpixel_shift
poly_subpixel_scale = 1<<poly_subpixel_shift, //----poly_subpixel_scale
poly_subpixel_mask = poly_subpixel_scale-1 //----poly_subpixel_mask
};
//----------------------------------------------------------filling_rule_e
enum filling_rule_e
{
fill_non_zero,
fill_even_odd
};
//-----------------------------------------------------------------------pi
const double pi = 3.14159265358979323846;
//------------------------------------------------------------------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 T value_type;
typedef rect_base<T> self_type;
T x1, y1, x2, y2;
rect_base() {}
rect_base(T x1_, T y1_, T x2_, T y2_) :
x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
void init(T x1_, T y1_, T x2_, T y2_)
{
x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_;
}
const self_type& normalize()
{
T t;
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;
}
bool hit_test(T x, T y) const
{
return (x >= x1 && x <= x2 && y >= y1 && y <= 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_i; //----rect_i
typedef rect_base<float> rect_f; //----rect_f
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_curveN = 5, //----path_cmd_curveN
path_cmd_catrom = 6, //----path_cmd_catrom
path_cmd_ubspline = 7, //----path_cmd_ubspline
path_cmd_end_poly = 0x0F, //----path_cmd_end_poly
path_cmd_mask = 0x0F //----path_cmd_mask
};
//------------------------------------------------------------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_drawing
inline bool is_drawing(unsigned c)
{
return c >= path_cmd_line_to && c < path_cmd_end_poly;
}
//-----------------------------------------------------------------is_stop
inline bool is_stop(unsigned c)
{
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_base
template<class T> struct point_base
{
typedef T value_type;
T x,y;
point_base() {}
point_base(T x_, T y_) : x(x_), y(y_) {}
};
typedef point_base<int> point_i; //-----point_i
typedef point_base<float> point_f; //-----point_f
typedef point_base<double> point_d; //-----point_d
//-------------------------------------------------------------vertex_base
template<class T> struct vertex_base
{
typedef T value_type;
T x,y;
unsigned cmd;
vertex_base() {}
vertex_base(T x_, T y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {}
};
typedef vertex_base<int> vertex_i; //-----vertex_i
typedef vertex_base<float> vertex_f; //-----vertex_f
typedef vertex_base<double> vertex_d; //-----vertex_d
//----------------------------------------------------------------row_info
template<class T> struct row_info
{
int x1, x2;
T* ptr;
row_info() {}
row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {}
};
//----------------------------------------------------------const_row_info
template<class T> struct const_row_info
{
int x1, x2;
const T* ptr;
const_row_info() {}
const_row_info(int x1_, int x2_, const T* ptr_) :
x1(x1_), x2(x2_), ptr(ptr_) {}
};
//------------------------------------------------------------is_equal_eps
template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon)
{
return std::fabs(v1 - v2) <= double(epsilon);
}
} }
//---------------------------------------------------------------saturation
template<int Limit>
struct saturation
{
AGG_INLINE static int iround(double v)
{
if (v < double(-Limit))
return -Limit;
if (v > double(Limit))
return Limit;
return agg::iround(v);
}
};
//------------------------------------------------------------------mul_one
template<unsigned Shift>
struct mul_one
{
AGG_INLINE static unsigned mul(unsigned a, unsigned b)
{
unsigned q = a * b + (1 << (Shift - 1));
return (q + (q >> Shift)) >> Shift;
}
};
//-------------------------------------------------------------------------
typedef unsigned char cover_type; //----cover_type
enum cover_scale_e {
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
};
//----------------------------------------------------poly_subpixel_scale_e
// These constants determine the subpixel accuracy, to be more precise,
// the number of bits of the fractional part of the coordinates.
// The possible coordinate capacity in bits can be calculated by formula:
// sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and
// 8-bits fractional part the capacity is 24 bits.
enum poly_subpixel_scale_e {
poly_subpixel_shift = 8, //----poly_subpixel_shift
poly_subpixel_scale = 1 << poly_subpixel_shift, //----poly_subpixel_scale
poly_subpixel_mask = poly_subpixel_scale - 1 //----poly_subpixel_mask
};
//----------------------------------------------------------filling_rule_e
enum filling_rule_e { fill_non_zero, fill_even_odd };
//-----------------------------------------------------------------------pi
const double pi = 3.14159265358979323846;
//------------------------------------------------------------------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 T value_type;
typedef rect_base<T> self_type;
T x1, y1, x2, y2;
rect_base() {}
rect_base(T x1_, T y1_, T x2_, T y2_)
: x1(x1_)
, y1(y1_)
, x2(x2_)
, y2(y2_)
{}
void init(T x1_, T y1_, T x2_, T y2_)
{
x1 = x1_;
y1 = y1_;
x2 = x2_;
y2 = y2_;
}
const self_type& normalize()
{
T t;
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; }
bool hit_test(T x, T y) const { return (x >= x1 && x <= x2 && y >= y1 && y <= 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_i; //----rect_i
typedef rect_base<float> rect_f; //----rect_f
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_curveN = 5, //----path_cmd_curveN
path_cmd_catrom = 6, //----path_cmd_catrom
path_cmd_ubspline = 7, //----path_cmd_ubspline
path_cmd_end_poly = 0x0F, //----path_cmd_end_poly
path_cmd_mask = 0x0F //----path_cmd_mask
};
//------------------------------------------------------------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_drawing
inline bool is_drawing(unsigned c)
{
return c >= path_cmd_line_to && c < path_cmd_end_poly;
}
//-----------------------------------------------------------------is_stop
inline bool is_stop(unsigned c)
{
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_base
template<class T>
struct point_base
{
typedef T value_type;
T x, y;
point_base() {}
point_base(T x_, T y_)
: x(x_)
, y(y_)
{}
};
typedef point_base<int> point_i; //-----point_i
typedef point_base<float> point_f; //-----point_f
typedef point_base<double> point_d; //-----point_d
//-------------------------------------------------------------vertex_base
template<class T>
struct vertex_base
{
typedef T value_type;
T x, y;
unsigned cmd;
vertex_base() {}
vertex_base(T x_, T y_, unsigned cmd_)
: x(x_)
, y(y_)
, cmd(cmd_)
{}
};
typedef vertex_base<int> vertex_i; //-----vertex_i
typedef vertex_base<float> vertex_f; //-----vertex_f
typedef vertex_base<double> vertex_d; //-----vertex_d
//----------------------------------------------------------------row_info
template<class T>
struct row_info
{
int x1, x2;
T* ptr;
row_info() {}
row_info(int x1_, int x2_, T* ptr_)
: x1(x1_)
, x2(x2_)
, ptr(ptr_)
{}
};
//----------------------------------------------------------const_row_info
template<class T>
struct const_row_info
{
int x1, x2;
const T* ptr;
const_row_info() {}
const_row_info(int x1_, int x2_, const T* ptr_)
: x1(x1_)
, x2(x2_)
, ptr(ptr_)
{}
};
//------------------------------------------------------------is_equal_eps
template<class T>
inline bool is_equal_eps(T v1, T v2, T epsilon)
{
return std::fabs(v1 - v2) <= double(epsilon);
}
} // namespace agg
#endif #endif

View file

@ -23,137 +23,127 @@
#include "agg_conv_transform.h" #include "agg_conv_transform.h"
namespace agg 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:
//----------------------------------------------------------------------- //--------------------------------------------------------------------
void arc_to_bezier(double cx, double cy, double rx, double ry, bezier_arc()
double start_angle, double sweep_angle, : m_vertex(26)
double* curve); , m_num_vertices(0)
, m_cmd(path_cmd_line_to)
{}
//==============================================================bezier_arc bezier_arc(double x, double y, double rx, double ry, double start_angle, double sweep_angle)
//
// See implemantaion agg_bezier_arc.cpp
//
class bezier_arc
{ {
public: init(x, y, rx, ry, start_angle, sweep_angle);
//-------------------------------------------------------------------- }
bezier_arc() : m_vertex(26), m_num_vertices(0), m_cmd(path_cmd_line_to) {}
bezier_arc(double x, double y,
double rx, double ry,
double start_angle,
double sweep_angle)
{
init(x, y, rx, ry, start_angle, sweep_angle);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void init(double x, double y, void init(double x, double y, double rx, double ry, double start_angle, double sweep_angle);
double rx, double ry,
double start_angle,
double sweep_angle);
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void rewind(unsigned) void rewind(unsigned) { m_vertex = 0; }
{
m_vertex = 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
unsigned vertex(double* x, double* y) 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) ? (unsigned)path_cmd_move_to : m_cmd;
}
// 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];
unsigned m_cmd;
};
//==========================================================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: if (m_vertex >= m_num_vertices)
//-------------------------------------------------------------------- return path_cmd_stop;
bezier_arc_svg() : m_arc(), m_radii_ok(false) {} *x = m_vertices[m_vertex];
*y = m_vertices[m_vertex + 1];
m_vertex += 2;
return (m_vertex == 2) ? (unsigned)path_cmd_move_to : m_cmd;
}
bezier_arc_svg(double x1, double y1, // Supplemantary functions. num_vertices() actually returns doubled
double rx, double ry, // number of vertices. That is, for 1 vertex it returns 2.
double angle, //--------------------------------------------------------------------
bool large_arc_flag, unsigned num_vertices() const { return m_num_vertices; }
bool sweep_flag, const double* vertices() const { return m_vertices; }
double x2, double y2) : double* vertices() { return m_vertices; }
m_arc(), m_radii_ok(false)
{
init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2);
}
//-------------------------------------------------------------------- private:
void init(double x1, double y1, unsigned m_vertex;
double rx, double ry, unsigned m_num_vertices;
double angle, double m_vertices[26];
bool large_arc_flag, unsigned m_cmd;
bool sweep_flag, };
double x2, double y2);
//-------------------------------------------------------------------- //==========================================================bezier_arc_svg
bool radii_ok() const { return m_radii_ok; } // 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,
void rewind(unsigned) double y1,
{ double rx,
m_arc.rewind(0); 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);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
unsigned vertex(double* x, double* y) void init(double x1,
{ double y1,
return m_arc.vertex(x, y); double rx,
} double ry,
double angle,
bool large_arc_flag,
bool sweep_flag,
double x2,
double y2);
// Supplemantary functions. num_vertices() actually returns doubled //--------------------------------------------------------------------
// number of vertices. That is, for 1 vertex it returns 2. bool radii_ok() const { return m_radii_ok; }
//--------------------------------------------------------------------
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; void rewind(unsigned) { m_arc.rewind(0); }
bool m_radii_ok;
};
//--------------------------------------------------------------------
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;
};
} } // namespace agg
#endif #endif

View file

@ -18,37 +18,33 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
class bitset_iterator
{ {
public:
bitset_iterator(const int8u* bits, unsigned offset = 0)
: m_bits(bits + (offset >> 3))
, m_mask(0x80 >> (offset & 7))
{}
class bitset_iterator void operator++()
{ {
public: m_mask >>= 1;
bitset_iterator(const int8u* bits, unsigned offset = 0) : if (m_mask == 0)
m_bits(bits + (offset >> 3)),
m_mask(0x80 >> (offset & 7))
{}
void operator ++ ()
{ {
m_mask >>= 1; ++m_bits;
if(m_mask == 0) m_mask = 0x80;
{
++m_bits;
m_mask = 0x80;
}
} }
}
unsigned bit() const unsigned bit() const { return (*m_bits) & m_mask; }
{
return (*m_bits) & m_mask;
}
private: private:
const int8u* m_bits; const int8u* m_bits;
int8u m_mask; int8u m_mask;
}; };
} } // namespace agg
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -21,76 +21,38 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg 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;
//-----------------------------------------------------------bounding_rect *x1 = CoordT(1);
template<class VertexSource, class GetId, class CoordT> *y1 = CoordT(1);
bool bounding_rect(VertexSource& vs, GetId& gi, *x2 = CoordT(0);
unsigned start, unsigned num, *y2 = CoordT(0);
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
for (i = 0; i < num; i++)
{ {
unsigned i; vs.rewind(gi[start + i]);
double x;
double y;
bool first = true;
*x1 = CoordT(1);
*y1 = CoordT(1);
*x2 = CoordT(0);
*y2 = CoordT(0);
for(i = 0; i < num; i++)
{
vs.rewind(gi[start + i]);
unsigned cmd;
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
if(is_vertex(cmd))
{
if(first)
{
*x1 = CoordT(x);
*y1 = CoordT(y);
*x2 = CoordT(x);
*y2 = CoordT(y);
first = false;
}
else
{
if(CoordT(x) < *x1) *x1 = CoordT(x);
if(CoordT(y) < *y1) *y1 = CoordT(y);
if(CoordT(x) > *x2) *x2 = CoordT(x);
if(CoordT(y) > *y2) *y2 = CoordT(y);
}
}
}
}
return *x1 <= *x2 && *y1 <= *y2;
}
//-----------------------------------------------------bounding_rect_single
template<class VertexSource, class CoordT>
bool bounding_rect_single(VertexSource& vs, unsigned path_id,
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
{
double x;
double y;
bool first = true;
*x1 = CoordT(1);
*y1 = CoordT(1);
*x2 = CoordT(0);
*y2 = CoordT(0);
vs.rewind(path_id);
unsigned cmd; unsigned cmd;
while(!is_stop(cmd = vs.vertex(&x, &y))) while (!is_stop(cmd = vs.vertex(&x, &y)))
{ {
if(is_vertex(cmd)) if (is_vertex(cmd))
{ {
if(first) if (first)
{ {
*x1 = CoordT(x); *x1 = CoordT(x);
*y1 = CoordT(y); *y1 = CoordT(y);
@ -100,17 +62,64 @@ namespace agg
} }
else else
{ {
if(CoordT(x) < *x1) *x1 = CoordT(x); if (CoordT(x) < *x1)
if(CoordT(y) < *y1) *y1 = CoordT(y); *x1 = CoordT(x);
if(CoordT(x) > *x2) *x2 = CoordT(x); if (CoordT(y) < *y1)
if(CoordT(y) > *y2) *y2 = CoordT(y); *y1 = CoordT(y);
if (CoordT(x) > *x2)
*x2 = CoordT(x);
if (CoordT(y) > *y2)
*y2 = CoordT(y);
} }
} }
} }
return *x1 <= *x2 && *y1 <= *y2;
} }
return *x1 <= *x2 && *y1 <= *y2;
} }
//-----------------------------------------------------bounding_rect_single
template<class VertexSource, class CoordT>
bool bounding_rect_single(VertexSource& vs, unsigned path_id, CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
{
double x;
double y;
bool first = true;
*x1 = CoordT(1);
*y1 = CoordT(1);
*x2 = CoordT(0);
*y2 = CoordT(0);
vs.rewind(path_id);
unsigned cmd;
while (!is_stop(cmd = vs.vertex(&x, &y)))
{
if (is_vertex(cmd))
{
if (first)
{
*x1 = CoordT(x);
*y1 = CoordT(y);
*x2 = CoordT(x);
*y2 = CoordT(y);
first = false;
}
else
{
if (CoordT(x) < *x1)
*x1 = CoordT(x);
if (CoordT(y) < *y1)
*y1 = CoordT(y);
if (CoordT(x) > *x2)
*x2 = CoordT(x);
if (CoordT(y) > *y2)
*y2 = CoordT(y);
}
}
}
return *x1 <= *x2 && *y1 <= *y2;
}
} // namespace agg
#endif #endif

View file

@ -22,55 +22,53 @@
#include "agg_array.h" #include "agg_array.h"
namespace agg 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
{ {
//----------------------------------------------------------------bspline public:
// A very simple class of Bi-cubic Spline interpolation. bspline();
// First call init(num, x[], y[]) where num - number of source points, bspline(int num);
// x, y - arrays of X and Y values respectively. Here Y must be a function bspline(int num, const double* x, const double* y);
// 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(int num);
bspline(int num, const double* x, const double* y);
void init(int num); void init(int num);
void add_point(double x, double y); void add_point(double x, double y);
void prepare(); void prepare();
void init(int num, const double* x, const double* y); void init(int num, const double* x, const double* y);
double get(double x) const; double get(double x) const;
double get_stateful(double x) const; double get_stateful(double x) const;
private: private:
bspline(const bspline&); bspline(const bspline&);
const bspline& operator = (const bspline&); const bspline& operator=(const bspline&);
static void bsearch(int n, const double *x, double x0, int *i); static void bsearch(int n, const double* x, double x0, int* i);
double extrapolation_left(double x) const; double extrapolation_left(double x) const;
double extrapolation_right(double x) const; double extrapolation_right(double x) const;
double interpolation(double x, int i) const; double interpolation(double x, int i) const;
int m_max; int m_max;
int m_num; int m_num;
double* m_x; double* m_x;
double* m_y; double* m_y;
pod_array<double> m_am; pod_array<double> m_am;
mutable int m_last_idx; mutable int m_last_idx;
}; };
} // namespace agg
}
#endif #endif

View file

@ -21,313 +21,296 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//------------------------------------------------------------------------
enum clipping_flags_e {
clipping_flags_x1_clipped = 4,
clipping_flags_x2_clipped = 1,
clipping_flags_y1_clipped = 8,
clipping_flags_y2_clipped = 2,
clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped,
clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped
};
//----------------------------------------------------------clipping_flags
// Determine the clipping code of the vertex according to the
// Cyrus-Beck line clipping algorithm
//
// | |
// 0110 | 0010 | 0011
// | |
// -------+--------+-------- clip_box.y2
// | |
// 0100 | 0000 | 0001
// | |
// -------+--------+-------- clip_box.y1
// | |
// 1100 | 1000 | 1001
// | |
// clip_box.x1 clip_box.x2
//
//
template<class T>
inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box)
{ {
return (x > clip_box.x2) | ((y > clip_box.y2) << 1) | ((x < clip_box.x1) << 2) | ((y < clip_box.y1) << 3);
}
//------------------------------------------------------------------------ //--------------------------------------------------------clipping_flags_x
enum clipping_flags_e template<class T>
{ inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box)
clipping_flags_x1_clipped = 4, {
clipping_flags_x2_clipped = 1, return (x > clip_box.x2) | ((x < clip_box.x1) << 2);
clipping_flags_y1_clipped = 8, }
clipping_flags_y2_clipped = 2,
clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped,
clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped
};
//----------------------------------------------------------clipping_flags //--------------------------------------------------------clipping_flags_y
// Determine the clipping code of the vertex according to the template<class T>
// Cyrus-Beck line clipping algorithm inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box)
// {
// | | return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3);
// 0110 | 0010 | 0011 }
// | |
// -------+--------+-------- clip_box.y2 //-------------------------------------------------------clip_liang_barsky
// | | template<class T>
// 0100 | 0000 | 0001 inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, const rect_base<T>& clip_box, T* x, T* y)
// | | {
// -------+--------+-------- clip_box.y1 const double nearzero = 1e-30;
// | |
// 1100 | 1000 | 1001 double deltax = x2 - x1;
// | | double deltay = y2 - y1;
// clip_box.x1 clip_box.x2 double xin;
// double xout;
// double yin;
template<class T> double yout;
inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box) double tinx;
double tiny;
double toutx;
double touty;
double tin1;
double tin2;
double tout1;
unsigned np = 0;
if (deltax == 0.0)
{ {
return (x > clip_box.x2) | // bump off of the vertical
((y > clip_box.y2) << 1) | deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
((x < clip_box.x1) << 2) |
((y < clip_box.y1) << 3);
} }
//--------------------------------------------------------clipping_flags_x if (deltay == 0.0)
template<class T>
inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box)
{ {
return (x > clip_box.x2) | ((x < clip_box.x1) << 2); // bump off of the horizontal
deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
} }
if (deltax > 0.0)
//--------------------------------------------------------clipping_flags_y
template<class T>
inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box)
{ {
return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3); // points to right
xin = clip_box.x1;
xout = clip_box.x2;
}
else
{
xin = clip_box.x2;
xout = clip_box.x1;
} }
if (deltay > 0.0)
//-------------------------------------------------------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; // points up
yin = clip_box.y1;
yout = clip_box.y2;
}
else
{
yin = clip_box.y2;
yout = clip_box.y1;
}
double deltax = x2 - x1; tinx = (xin - x1) / deltax;
double deltay = y2 - y1; tiny = (yin - y1) / deltay;
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) 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)
{ {
// bump off of the vertical *x++ = (T)xin;
deltax = (x1 > clip_box.x1) ? -nearzero : nearzero; *y++ = (T)yin;
++np;
} }
if(deltay == 0.0) if (tin2 <= 1.0)
{ {
// bump off of the horizontal toutx = (xout - x1) / deltax;
deltay = (y1 > clip_box.y1) ? -nearzero : nearzero; touty = (yout - y1) / deltay;
}
if(deltax > 0.0) tout1 = (toutx < touty) ? toutx : touty;
{
// points to right
xin = clip_box.x1;
xout = clip_box.x2;
}
else
{
xin = clip_box.x2;
xout = clip_box.x1;
}
if(deltay > 0.0) if (tin2 > 0.0 || tout1 > 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; if (tin2 <= tout1)
*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(tin2 > 0.0) if (tinx > tiny)
{
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; *x++ = (T)xin;
*y++ = (T)yout; *y++ = (T)(y1 + tinx * deltay);
} }
else else
{ {
*x++ = (T)xout; *x++ = (T)(x1 + tiny * deltax);
*y++ = (T)yin; *y++ = (T)yin;
} }
++np; ++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;
} }
return np;
//----------------------------------------------------------------------------
template<class T>
bool clip_move_point(T x1, T y1, T x2, T y2,
const rect_base<T>& clip_box,
T* x, T* y, unsigned flags)
{
T bound;
if(flags & clipping_flags_x_clipped)
{
if(x1 == x2)
{
return false;
}
bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2;
*y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1);
*x = bound;
}
flags = clipping_flags_y(*y, clip_box);
if(flags & clipping_flags_y_clipped)
{
if(y1 == y2)
{
return false;
}
bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2;
*x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1);
*y = bound;
}
return true;
}
//-------------------------------------------------------clip_line_segment
// Returns: ret >= 4 - Fully clipped
// (ret & 1) != 0 - First point has been moved
// (ret & 2) != 0 - Second point has been moved
//
template<class T>
unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2,
const rect_base<T>& clip_box)
{
unsigned f1 = clipping_flags(*x1, *y1, clip_box);
unsigned f2 = clipping_flags(*x2, *y2, clip_box);
unsigned ret = 0;
if((f2 | f1) == 0)
{
// Fully visible
return 0;
}
if((f1 & clipping_flags_x_clipped) != 0 &&
(f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped))
{
// Fully clipped
return 4;
}
if((f1 & clipping_flags_y_clipped) != 0 &&
(f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped))
{
// Fully clipped
return 4;
}
T tx1 = *x1;
T ty1 = *y1;
T tx2 = *x2;
T ty2 = *y2;
if(f1)
{
if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1))
{
return 4;
}
if(*x1 == *x2 && *y1 == *y2)
{
return 4;
}
ret |= 1;
}
if(f2)
{
if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2))
{
return 4;
}
if(*x1 == *x2 && *y1 == *y2)
{
return 4;
}
ret |= 2;
}
return ret;
}
} }
//----------------------------------------------------------------------------
template<class T>
bool clip_move_point(T x1, T y1, T x2, T y2, const rect_base<T>& clip_box, T* x, T* y, unsigned flags)
{
T bound;
if (flags & clipping_flags_x_clipped)
{
if (x1 == x2)
{
return false;
}
bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2;
*y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1);
*x = bound;
}
flags = clipping_flags_y(*y, clip_box);
if (flags & clipping_flags_y_clipped)
{
if (y1 == y2)
{
return false;
}
bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2;
*x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1);
*y = bound;
}
return true;
}
//-------------------------------------------------------clip_line_segment
// Returns: ret >= 4 - Fully clipped
// (ret & 1) != 0 - First point has been moved
// (ret & 2) != 0 - Second point has been moved
//
template<class T>
unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2, const rect_base<T>& clip_box)
{
unsigned f1 = clipping_flags(*x1, *y1, clip_box);
unsigned f2 = clipping_flags(*x2, *y2, clip_box);
unsigned ret = 0;
if ((f2 | f1) == 0)
{
// Fully visible
return 0;
}
if ((f1 & clipping_flags_x_clipped) != 0 && (f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped))
{
// Fully clipped
return 4;
}
if ((f1 & clipping_flags_y_clipped) != 0 && (f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped))
{
// Fully clipped
return 4;
}
T tx1 = *x1;
T ty1 = *y1;
T tx2 = *x2;
T ty2 = *y2;
if (f1)
{
if (!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1))
{
return 4;
}
if (*x1 == *x2 && *y1 == *y2)
{
return 4;
}
ret |= 1;
}
if (f2)
{
if (!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2))
{
return 4;
}
if (*x1 == *x2 && *y1 == *y2)
{
return 4;
}
ret |= 2;
}
return ret;
}
} // namespace agg
#endif #endif

View file

@ -31,21 +31,19 @@
#include "agg_basics.h" #include "agg_basics.h"
#include "agg_color_rgba.h" #include "agg_color_rgba.h"
namespace agg namespace agg {
{
//===================================================================gray8 //===================================================================gray8
template<class Colorspace> template<class Colorspace>
struct gray8T struct gray8T
{ {
typedef int8u value_type; typedef int8u value_type;
typedef int32u calc_type; typedef int32u calc_type;
typedef int32 long_type; typedef int32 long_type;
enum base_scale_e enum base_scale_e {
{
base_shift = 8, base_shift = 8,
base_scale = 1 << base_shift, base_scale = 1 << base_shift,
base_mask = base_scale - 1, base_mask = base_scale - 1,
base_MSB = 1 << (base_shift - 1) base_MSB = 1 << (base_shift - 1)
}; };
typedef gray8T self_type; typedef gray8T self_type;
@ -105,17 +103,22 @@ struct gray8T
gray8T() {} gray8T() {}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray8T(unsigned v_, unsigned a_=base_mask) : gray8T(unsigned v_, unsigned a_ = base_mask)
v(int8u(v_)), a(int8u(a_)) {} : v(int8u(v_))
, a(int8u(a_))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray8T(const self_type& c, unsigned a_) : gray8T(const self_type& c, unsigned a_)
v(c.v), a(value_type(a_)) {} : v(c.v)
, a(value_type(a_))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray8T(const rgba& c) : gray8T(const rgba& c)
v(luminance(c)), : v(luminance(c))
a(value_type(uround(c.a * base_mask))) {} , a(value_type(uround(c.a * base_mask)))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
template<class T> template<class T>
@ -147,36 +150,18 @@ struct gray8T
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba8 make_rgba8(const linear&) const rgba8 make_rgba8(const linear&) const { return rgba8(v, v, v, a); }
{
return rgba8(v, v, v, a);
}
rgba8 make_rgba8(const sRGB&) const rgba8 make_rgba8(const sRGB&) const { return convert_from_sRGB<srgba8>(); }
{
return convert_from_sRGB<srgba8>();
}
operator rgba8() const operator rgba8() const { return make_rgba8(Colorspace()); }
{
return make_rgba8(Colorspace());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
srgba8 make_srgba8(const linear&) const srgba8 make_srgba8(const linear&) const { return convert_to_sRGB<rgba8>(); }
{
return convert_to_sRGB<rgba8>();
}
srgba8 make_srgba8(const sRGB&) const srgba8 make_srgba8(const sRGB&) const { return srgba8(v, v, v, a); }
{
return srgba8(v, v, v, a);
}
operator srgba8() const operator srgba8() const { return make_rgba8(Colorspace()); }
{
return make_rgba8(Colorspace());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba16 make_rgba16(const linear&) const rgba16 make_rgba16(const linear&) const
@ -185,15 +170,9 @@ struct gray8T
return rgba16(rgb, rgb, rgb, (a << 8) | a); return rgba16(rgb, rgb, rgb, (a << 8) | a);
} }
rgba16 make_rgba16(const sRGB&) const rgba16 make_rgba16(const sRGB&) const { return convert_from_sRGB<rgba16>(); }
{
return convert_from_sRGB<rgba16>();
}
operator rgba16() const operator rgba16() const { return make_rgba16(Colorspace()); }
{
return make_rgba16(Colorspace());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba32 make_rgba32(const linear&) const rgba32 make_rgba32(const linear&) const
@ -202,51 +181,27 @@ struct gray8T
return rgba32(v32, v32, v32, a / 255.0); return rgba32(v32, v32, v32, a / 255.0);
} }
rgba32 make_rgba32(const sRGB&) const rgba32 make_rgba32(const sRGB&) const { return convert_from_sRGB<rgba32>(); }
{
return convert_from_sRGB<rgba32>();
}
operator rgba32() const operator rgba32() const { return make_rgba32(Colorspace()); }
{
return make_rgba32(Colorspace());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a) static AGG_INLINE double to_double(value_type a) { return double(a) / base_mask; }
{
return double(a) / base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a) static AGG_INLINE value_type from_double(double a) { return value_type(uround(a * base_mask)); }
{
return value_type(uround(a * base_mask));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type empty_value() static AGG_INLINE value_type empty_value() { return 0; }
{
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type full_value() static AGG_INLINE value_type full_value() { return base_mask; }
{
return base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const AGG_INLINE bool is_transparent() const { return a == 0; }
{
return a == 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const AGG_INLINE bool is_opaque() const { return a == base_mask; }
{
return a == base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Fixed-point multiply, exact over int8u. // Fixed-point multiply, exact over int8u.
@ -267,7 +222,8 @@ struct gray8T
{ {
return base_mask; return base_mask;
} }
else return value_type((a * base_mask + (b >> 1)) / b); else
return value_type((a * base_mask + (b >> 1)) / b);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -287,23 +243,14 @@ struct gray8T
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Fixed-point multiply, exact over int8u. // Fixed-point multiply, exact over int8u.
// Specifically for multiplying a color component by a cover. // Specifically for multiplying a color component by a cover.
static AGG_INLINE value_type mult_cover(value_type a, value_type b) static AGG_INLINE value_type mult_cover(value_type a, value_type b) { return multiply(a, b); }
{
return multiply(a, b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return multiply(b, a); }
{
return multiply(b, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a, assuming q is premultiplied by a. // Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) { return p + q - multiply(p, a); }
{
return p + q - multiply(p, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a. // Interpolate p to q by a.
@ -330,25 +277,27 @@ struct gray8T
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& opacity(double a_) self_type& opacity(double a_)
{ {
if (a_ < 0) a = 0; if (a_ < 0)
else if (a_ > 1) a = 1; a = 0;
else a = (value_type)uround(a_ * double(base_mask)); else if (a_ > 1)
a = 1;
else
a = (value_type)uround(a_ * double(base_mask));
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
double opacity() const double opacity() const { return double(a) / double(base_mask); }
{
return double(a) / double(base_mask);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& premultiply() self_type& premultiply()
{ {
if (a < base_mask) if (a < base_mask)
{ {
if (a == 0) v = 0; if (a == 0)
else v = multiply(v, a); v = 0;
else
v = multiply(v, a);
} }
return *this; return *this;
} }
@ -408,24 +357,22 @@ struct gray8T
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0); } static self_type no_color() { return self_type(0, 0); }
}; };
typedef gray8T<linear> gray8; typedef gray8T<linear> gray8;
typedef gray8T<sRGB> sgray8; typedef gray8T<sRGB> sgray8;
//==================================================================gray16 //==================================================================gray16
struct gray16 struct gray16
{ {
typedef int16u value_type; typedef int16u value_type;
typedef int32u calc_type; typedef int32u calc_type;
typedef int64 long_type; typedef int64 long_type;
enum base_scale_e enum base_scale_e {
{
base_shift = 16, base_shift = 16,
base_scale = 1 << base_shift, base_scale = 1 << base_shift,
base_mask = base_scale - 1, base_mask = base_scale - 1,
base_MSB = 1 << (base_shift - 1) base_MSB = 1 << (base_shift - 1)
}; };
typedef gray16 self_type; typedef gray16 self_type;
@ -445,67 +392,65 @@ struct gray16
return value_type((13933u * c.r + 46872u * c.g + 4732u * c.b) >> 16); return value_type((13933u * c.r + 46872u * c.g + 4732u * c.b) >> 16);
} }
static value_type luminance(const rgba8& c) static value_type luminance(const rgba8& c) { return luminance(rgba16(c)); }
{
return luminance(rgba16(c));
}
static value_type luminance(const srgba8& c) static value_type luminance(const srgba8& c) { return luminance(rgba16(c)); }
{
return luminance(rgba16(c));
}
static value_type luminance(const rgba32& c) static value_type luminance(const rgba32& c) { return luminance(rgba(c)); }
{
return luminance(rgba(c));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray16() {} gray16() {}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray16(unsigned v_, unsigned a_ = base_mask) : gray16(unsigned v_, unsigned a_ = base_mask)
v(int16u(v_)), a(int16u(a_)) {} : v(int16u(v_))
, a(int16u(a_))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray16(const self_type& c, unsigned a_) : gray16(const self_type& c, unsigned a_)
v(c.v), a(value_type(a_)) {} : v(c.v)
, a(value_type(a_))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray16(const rgba& c) : gray16(const rgba& c)
v(luminance(c)), : v(luminance(c))
a((value_type)uround(c.a * double(base_mask))) {} , a((value_type)uround(c.a * double(base_mask)))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray16(const rgba8& c) : gray16(const rgba8& c)
v(luminance(c)), : v(luminance(c))
a((value_type(c.a) << 8) | c.a) {} , a((value_type(c.a) << 8) | c.a)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray16(const srgba8& c) : gray16(const srgba8& c)
v(luminance(c)), : v(luminance(c))
a((value_type(c.a) << 8) | c.a) {} , a((value_type(c.a) << 8) | c.a)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray16(const rgba16& c) : gray16(const rgba16& c)
v(luminance(c)), : v(luminance(c))
a(c.a) {} , a(c.a)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray16(const gray8& c) : gray16(const gray8& c)
v((value_type(c.v) << 8) | c.v), : v((value_type(c.v) << 8) | c.v)
a((value_type(c.a) << 8) | c.a) {} , a((value_type(c.a) << 8) | c.a)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray16(const sgray8& c) : gray16(const sgray8& c)
v(sRGB_conv<value_type>::rgb_from_sRGB(c.v)), : v(sRGB_conv<value_type>::rgb_from_sRGB(c.v))
a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {} , a(sRGB_conv<value_type>::alpha_from_sRGB(c.a))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba8() const operator rgba8() const { return rgba8(v >> 8, v >> 8, v >> 8, a >> 8); }
{
return rgba8(v >> 8, v >> 8, v >> 8, a >> 8);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator srgba8() const operator srgba8() const
@ -515,60 +460,34 @@ struct gray16
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba16() const operator rgba16() const { return rgba16(v, v, v, a); }
{
return rgba16(v, v, v, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator gray8() const operator gray8() const { return gray8(v >> 8, a >> 8); }
{
return gray8(v >> 8, a >> 8);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator sgray8() const operator sgray8() const
{ {
return sgray8( return sgray8(sRGB_conv<value_type>::rgb_to_sRGB(v), sRGB_conv<value_type>::alpha_to_sRGB(a));
sRGB_conv<value_type>::rgb_to_sRGB(v),
sRGB_conv<value_type>::alpha_to_sRGB(a));
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a) static AGG_INLINE double to_double(value_type a) { return double(a) / base_mask; }
{
return double(a) / base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a) static AGG_INLINE value_type from_double(double a) { return value_type(uround(a * base_mask)); }
{
return value_type(uround(a * base_mask));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type empty_value() static AGG_INLINE value_type empty_value() { return 0; }
{
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type full_value() static AGG_INLINE value_type full_value() { return base_mask; }
{
return base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const AGG_INLINE bool is_transparent() const { return a == 0; }
{
return a == 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const AGG_INLINE bool is_opaque() const { return a == base_mask; }
{
return a == base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Fixed-point multiply, exact over int16u. // Fixed-point multiply, exact over int16u.
@ -589,7 +508,8 @@ struct gray16
{ {
return base_mask; return base_mask;
} }
else return value_type((a * base_mask + (b >> 1)) / b); else
return value_type((a * base_mask + (b >> 1)) / b);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -609,23 +529,14 @@ struct gray16
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Fixed-point multiply, almost exact over int16u. // Fixed-point multiply, almost exact over int16u.
// Specifically for multiplying a color component by a cover. // Specifically for multiplying a color component by a cover.
static AGG_INLINE value_type mult_cover(value_type a, cover_type b) static AGG_INLINE value_type mult_cover(value_type a, cover_type b) { return multiply(a, b << 8 | b); }
{
return multiply(a, b << 8 | b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return mult_cover(b, a) >> 8; }
{
return mult_cover(b, a) >> 8;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a, assuming q is premultiplied by a. // Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) { return p + q - multiply(p, a); }
{
return p + q - multiply(p, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a. // Interpolate p to q by a.
@ -652,26 +563,27 @@ struct gray16
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& opacity(double a_) self_type& opacity(double a_)
{ {
if (a_ < 0) a = 0; if (a_ < 0)
else if(a_ > 1) a = 1; a = 0;
else a = (value_type)uround(a_ * double(base_mask)); else if (a_ > 1)
a = 1;
else
a = (value_type)uround(a_ * double(base_mask));
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
double opacity() const double opacity() const { return double(a) / double(base_mask); }
{
return double(a) / double(base_mask);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& premultiply() self_type& premultiply()
{ {
if (a < base_mask) if (a < base_mask)
{ {
if(a == 0) v = 0; if (a == 0)
else v = multiply(v, a); v = 0;
else
v = multiply(v, a);
} }
return *this; return *this;
} }
@ -731,10 +643,9 @@ struct gray16
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0); } static self_type no_color() { return self_type(0, 0); }
}; };
//===================================================================gray32 //===================================================================gray32
struct gray32 struct gray32
{ {
@ -746,11 +657,10 @@ struct gray32
value_type v; value_type v;
value_type a; value_type a;
enum base_scale_e enum base_scale_e {
{
base_shift = 8, base_shift = 8,
base_scale = 1 << base_shift, base_scale = 1 << base_shift,
base_mask = base_scale - 1, base_mask = base_scale - 1,
}; };
// Calculate grayscale value as per ITU-R BT.709. // Calculate grayscale value as per ITU-R BT.709.
@ -759,103 +669,92 @@ struct gray32
return value_type(0.2126 * r + 0.7152 * g + 0.0722 * b); return value_type(0.2126 * r + 0.7152 * g + 0.0722 * b);
} }
static value_type luminance(const rgba& c) static value_type luminance(const rgba& c) { return luminance(c.r, c.g, c.b); }
{
return luminance(c.r, c.g, c.b);
}
static value_type luminance(const rgba32& c) static value_type luminance(const rgba32& c) { return luminance(c.r, c.g, c.b); }
{
return luminance(c.r, c.g, c.b);
}
static value_type luminance(const rgba8& c) static value_type luminance(const rgba8& c) { return luminance(c.r / 255.0, c.g / 255.0, c.g / 255.0); }
{
return luminance(c.r / 255.0, c.g / 255.0, c.g / 255.0);
}
static value_type luminance(const rgba16& c) static value_type luminance(const rgba16& c) { return luminance(c.r / 65535.0, c.g / 65535.0, c.g / 65535.0); }
{
return luminance(c.r / 65535.0, c.g / 65535.0, c.g / 65535.0);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray32() {} gray32() {}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray32(value_type v_, value_type a_ = 1) : gray32(value_type v_, value_type a_ = 1)
v(v_), a(a_) {} : v(v_)
, a(a_)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray32(const self_type& c, value_type a_) : gray32(const self_type& c, value_type a_)
v(c.v), a(a_) {} : v(c.v)
, a(a_)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray32(const rgba& c) : gray32(const rgba& c)
v(luminance(c)), : v(luminance(c))
a(value_type(c.a)) {} , a(value_type(c.a))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray32(const rgba8& c) : gray32(const rgba8& c)
v(luminance(c)), : v(luminance(c))
a(value_type(c.a / 255.0)) {} , a(value_type(c.a / 255.0))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray32(const srgba8& c) : gray32(const srgba8& c)
v(luminance(rgba32(c))), : v(luminance(rgba32(c)))
a(value_type(c.a / 255.0)) {} , a(value_type(c.a / 255.0))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray32(const rgba16& c) : gray32(const rgba16& c)
v(luminance(c)), : v(luminance(c))
a(value_type(c.a / 65535.0)) {} , a(value_type(c.a / 65535.0))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray32(const rgba32& c) : gray32(const rgba32& c)
v(luminance(c)), : v(luminance(c))
a(value_type(c.a)) {} , a(value_type(c.a))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray32(const gray8& c) : gray32(const gray8& c)
v(value_type(c.v / 255.0)), : v(value_type(c.v / 255.0))
a(value_type(c.a / 255.0)) {} , a(value_type(c.a / 255.0))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray32(const sgray8& c) : gray32(const sgray8& c)
v(sRGB_conv<value_type>::rgb_from_sRGB(c.v)), : v(sRGB_conv<value_type>::rgb_from_sRGB(c.v))
a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {} , a(sRGB_conv<value_type>::alpha_from_sRGB(c.a))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray32(const gray16& c) : gray32(const gray16& c)
v(value_type(c.v / 65535.0)), : v(value_type(c.v / 65535.0))
a(value_type(c.a / 65535.0)) {} , a(value_type(c.a / 65535.0))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba() const operator rgba() const { return rgba(v, v, v, a); }
{
return rgba(v, v, v, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator gray8() const operator gray8() const { return gray8(uround(v * 255.0), uround(a * 255.0)); }
{
return gray8(uround(v * 255.0), uround(a * 255.0));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator sgray8() const operator sgray8() const
{ {
// Return (non-premultiplied) sRGB values. // Return (non-premultiplied) sRGB values.
return sgray8( return sgray8(sRGB_conv<value_type>::rgb_to_sRGB(v), sRGB_conv<value_type>::alpha_to_sRGB(a));
sRGB_conv<value_type>::rgb_to_sRGB(v),
sRGB_conv<value_type>::alpha_to_sRGB(a));
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator gray16() const operator gray16() const { return gray16(uround(v * 65535.0), uround(a * 65535.0)); }
{
return gray16(uround(v * 65535.0), uround(a * 65535.0));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba8() const operator rgba8() const
@ -879,58 +778,31 @@ struct gray32
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a) static AGG_INLINE double to_double(value_type a) { return a; }
{
return a;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a) static AGG_INLINE value_type from_double(double a) { return value_type(a); }
{
return value_type(a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type empty_value() static AGG_INLINE value_type empty_value() { return 0; }
{
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type full_value() static AGG_INLINE value_type full_value() { return 1; }
{
return 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const AGG_INLINE bool is_transparent() const { return a <= 0; }
{
return a <= 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const AGG_INLINE bool is_opaque() const { return a >= 1; }
{
return a >= 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type invert(value_type x) static AGG_INLINE value_type invert(value_type x) { return 1 - x; }
{
return 1 - x;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type multiply(value_type a, value_type b) static AGG_INLINE value_type multiply(value_type a, value_type b) { return value_type(a * b); }
{
return value_type(a * b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type demultiply(value_type a, value_type b) static AGG_INLINE value_type demultiply(value_type a, value_type b) { return (b == 0) ? 0 : value_type(a / b); }
{
return (b == 0) ? 0 : value_type(a / b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
template<typename T> template<typename T>
@ -947,16 +819,10 @@ struct gray32
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type mult_cover(value_type a, cover_type b) static AGG_INLINE value_type mult_cover(value_type a, cover_type b) { return value_type(a * b / cover_mask); }
{
return value_type(a * b / cover_mask);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return cover_type(uround(a * b)); }
{
return cover_type(uround(a * b));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a, assuming q is premultiplied by a. // Interpolate p to q by a, assuming q is premultiplied by a.
@ -993,49 +859,47 @@ struct gray32
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& opacity(double a_) self_type& opacity(double a_)
{ {
if (a_ < 0) a = 0; if (a_ < 0)
else if (a_ > 1) a = 1; a = 0;
else a = value_type(a_); else if (a_ > 1)
a = 1;
else
a = value_type(a_);
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
double opacity() const double opacity() const { return a; }
{
return a;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& premultiply() self_type& premultiply()
{ {
if (a < 0) v = 0; if (a < 0)
else if(a < 1) v *= a; v = 0;
else if (a < 1)
v *= a;
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& demultiply() self_type& demultiply()
{ {
if (a < 0) v = 0; if (a < 0)
else if (a < 1) v /= a; v = 0;
else if (a < 1)
v /= a;
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type gradient(self_type c, double k) const self_type gradient(self_type c, double k) const
{ {
return self_type( return self_type(value_type(v + (c.v - v) * k), value_type(a + (c.a - a) * k));
value_type(v + (c.v - v) * k),
value_type(a + (c.a - a) * k));
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0); } static self_type no_color() { return self_type(0, 0); }
}; };
} } // namespace agg
#endif #endif

View file

@ -28,20 +28,39 @@
#include "agg_basics.h" #include "agg_basics.h"
#include "agg_gamma_lut.h" #include "agg_gamma_lut.h"
namespace agg namespace agg {
{
// Supported byte orders for RGB and RGBA pixel formats // Supported byte orders for RGB and RGBA pixel formats
//======================================================================= //=======================================================================
struct order_rgb { enum rgb_e { R=0, G=1, B=2, rgb_tag, hasAlpha=false }; }; //----order_rgb struct order_rgb
struct order_bgr { enum bgr_e { B=0, G=1, R=2, rgb_tag, hasAlpha=false }; }; //----order_bgr {
struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag, hasAlpha=true }; }; //----order_rgba enum rgb_e { R = 0, G = 1, B = 2, rgb_tag, hasAlpha = false };
struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag, hasAlpha=true }; }; //----order_argb }; //----order_rgb
struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag, hasAlpha=true }; }; //----order_abgr struct order_bgr
struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag, hasAlpha=true }; }; //----order_bgra {
enum bgr_e { B = 0, G = 1, R = 2, rgb_tag, hasAlpha = false };
}; //----order_bgr
struct order_rgba
{
enum rgba_e { R = 0, G = 1, B = 2, A = 3, rgba_tag, hasAlpha = true };
}; //----order_rgba
struct order_argb
{
enum argb_e { A = 0, R = 1, G = 2, B = 3, rgba_tag, hasAlpha = true };
}; //----order_argb
struct order_abgr
{
enum abgr_e { A = 0, B = 1, G = 2, R = 3, rgba_tag, hasAlpha = true };
}; //----order_abgr
struct order_bgra
{
enum bgra_e { B = 0, G = 1, R = 2, A = 3, rgba_tag, hasAlpha = true };
}; //----order_bgra
// Colorspace tag types. // Colorspace tag types.
struct linear {}; struct linear
struct sRGB {}; {};
struct sRGB
{};
//====================================================================rgba //====================================================================rgba
struct rgba struct rgba
@ -57,11 +76,20 @@ struct rgba
rgba() {} rgba() {}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba(double r_, double g_, double b_, double a_=1.0) : rgba(double r_, double g_, double b_, double a_ = 1.0)
r(r_), g(g_), b(b_), a(a_) {} : r(r_)
, g(g_)
, b(b_)
, a(a_)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {} rgba(const rgba& c, double a_)
: r(c.r)
, g(c.g)
, b(c.b)
, a(a_)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba& clear() rgba& clear()
@ -80,17 +108,17 @@ struct rgba
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba& opacity(double a_) rgba& opacity(double a_)
{ {
if (a_ < 0) a = 0; if (a_ < 0)
else if (a_ > 1) a = 1; a = 0;
else a = a_; else if (a_ > 1)
a = 1;
else
a = a_;
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
double opacity() const double opacity() const { return a; }
{
return a;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba& premultiply() rgba& premultiply()
@ -114,7 +142,7 @@ struct rgba
r *= a_; r *= a_;
g *= a_; g *= a_;
b *= a_; b *= a_;
a = a_; a = a_;
} }
return *this; return *this;
} }
@ -136,7 +164,6 @@ struct rgba
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba gradient(rgba c, double k) const rgba gradient(rgba c, double k) const
{ {
@ -167,17 +194,13 @@ struct rgba
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static rgba no_color() { return rgba(0,0,0,0); } static rgba no_color() { return rgba(0, 0, 0, 0); }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static rgba from_wavelength(double wl, double gamma = 1.0); static rgba from_wavelength(double wl, double gamma = 1.0);
//-------------------------------------------------------------------- //--------------------------------------------------------------------
explicit rgba(double wavelen, double gamma=1.0) explicit rgba(double wavelen, double gamma = 1.0) { *this = from_wavelength(wavelen, gamma); }
{
*this = from_wavelength(wavelen, gamma);
}
}; };
inline rgba operator+(const rgba& a, const rgba& b) inline rgba operator+(const rgba& a, const rgba& b)
@ -226,8 +249,10 @@ inline rgba rgba::from_wavelength(double wl, double gamma)
} }
double s = 1.0; double s = 1.0;
if (wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0); if (wl > 700.0)
else if (wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.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.r = pow(t.r * s, gamma);
t.g = pow(t.g * s, gamma); t.g = pow(t.g * s, gamma);
@ -240,24 +265,21 @@ inline rgba rgba_pre(double r, double g, double b, double a)
return rgba(r, g, b, a).premultiply(); return rgba(r, g, b, a).premultiply();
} }
//===================================================================rgba8 //===================================================================rgba8
template<class Colorspace> template<class Colorspace>
struct rgba8T struct rgba8T
{ {
typedef int8u value_type; typedef int8u value_type;
typedef int32u calc_type; typedef int32u calc_type;
typedef int32 long_type; typedef int32 long_type;
enum base_scale_e enum base_scale_e {
{
base_shift = 8, base_shift = 8,
base_scale = 1 << base_shift, base_scale = 1 << base_shift,
base_mask = base_scale - 1, base_mask = base_scale - 1,
base_MSB = 1 << (base_shift - 1) base_MSB = 1 << (base_shift - 1)
}; };
typedef rgba8T self_type; typedef rgba8T self_type;
value_type r; value_type r;
value_type g; value_type g;
value_type b; value_type b;
@ -317,21 +339,23 @@ struct rgba8T
rgba8T() {} rgba8T() {}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba8T(unsigned r_, unsigned g_, unsigned b_, unsigned a_ = base_mask) : rgba8T(unsigned r_, unsigned g_, unsigned b_, unsigned a_ = base_mask)
r(value_type(r_)), : r(value_type(r_))
g(value_type(g_)), , g(value_type(g_))
b(value_type(b_)), , b(value_type(b_))
a(value_type(a_)) {} , a(value_type(a_))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba8T(const rgba& c) rgba8T(const rgba& c) { convert(*this, c); }
{
convert(*this, c);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba8T(const self_type& c, unsigned a_) : rgba8T(const self_type& c, unsigned a_)
r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} : r(c.r)
, g(c.g)
, b(c.b)
, a(value_type(a_))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
template<class T> template<class T>
@ -349,46 +373,25 @@ struct rgba8T
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a) static AGG_INLINE double to_double(value_type a) { return double(a) / base_mask; }
{
return double(a) / base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a) static AGG_INLINE value_type from_double(double a) { return value_type(uround(a * base_mask)); }
{
return value_type(uround(a * base_mask));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type empty_value() static AGG_INLINE value_type empty_value() { return 0; }
{
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type full_value() static AGG_INLINE value_type full_value() { return base_mask; }
{
return base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const AGG_INLINE bool is_transparent() const { return a == 0; }
{
return a == 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const AGG_INLINE bool is_opaque() const { return a == base_mask; }
{
return a == base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type invert(value_type x) static AGG_INLINE value_type invert(value_type x) { return base_mask - x; }
{
return base_mask - x;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Fixed-point multiply, exact over int8u. // Fixed-point multiply, exact over int8u.
@ -409,7 +412,8 @@ struct rgba8T
{ {
return base_mask; return base_mask;
} }
else return value_type((a * base_mask + (b >> 1)) / b); else
return value_type((a * base_mask + (b >> 1)) / b);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -429,23 +433,14 @@ struct rgba8T
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Fixed-point multiply, exact over int8u. // Fixed-point multiply, exact over int8u.
// Specifically for multiplying a color component by a cover. // Specifically for multiplying a color component by a cover.
static AGG_INLINE value_type mult_cover(value_type a, cover_type b) static AGG_INLINE value_type mult_cover(value_type a, cover_type b) { return multiply(a, b); }
{
return multiply(a, b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return multiply(b, a); }
{
return multiply(b, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a, assuming q is premultiplied by a. // Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) { return p + q - multiply(p, a); }
{
return p + q - multiply(p, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a. // Interpolate p to q by a.
@ -472,17 +467,17 @@ struct rgba8T
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& opacity(double a_) self_type& opacity(double a_)
{ {
if (a_ < 0) a = 0; if (a_ < 0)
else if (a_ > 1) a = 1; a = 0;
else a = (value_type)uround(a_ * double(base_mask)); else if (a_ > 1)
a = 1;
else
a = (value_type)uround(a_ * double(base_mask));
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
double opacity() const double opacity() const { return double(a) / double(base_mask); }
{
return double(a) / double(base_mask);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE self_type& premultiply() AGG_INLINE self_type& premultiply()
@ -604,7 +599,7 @@ struct rgba8T
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0,0,0); } static self_type no_color() { return self_type(0, 0, 0, 0); }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static self_type from_wavelength(double wl, double gamma = 1.0) static self_type from_wavelength(double wl, double gamma = 1.0)
@ -617,10 +612,9 @@ typedef rgba8T<linear> rgba8;
typedef rgba8T<sRGB> srgba8; typedef rgba8T<sRGB> srgba8;
//-------------------------------------------------------------rgba8_pre //-------------------------------------------------------------rgba8_pre
inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, unsigned a = rgba8::base_mask)
unsigned a = rgba8::base_mask)
{ {
return rgba8(r,g,b,a).premultiply(); return rgba8(r, g, b, a).premultiply();
} }
inline rgba8 rgba8_pre(const rgba8& c) inline rgba8 rgba8_pre(const rgba8& c)
{ {
@ -628,7 +622,7 @@ inline rgba8 rgba8_pre(const rgba8& c)
} }
inline rgba8 rgba8_pre(const rgba8& c, unsigned a) inline rgba8 rgba8_pre(const rgba8& c, unsigned a)
{ {
return rgba8(c,a).premultiply(); return rgba8(c, a).premultiply();
} }
inline rgba8 rgba8_pre(const rgba& c) inline rgba8 rgba8_pre(const rgba& c)
{ {
@ -636,12 +630,9 @@ inline rgba8 rgba8_pre(const rgba& c)
} }
inline rgba8 rgba8_pre(const rgba& c, double a) inline rgba8 rgba8_pre(const rgba& c, double a)
{ {
return rgba8(c,a).premultiply(); return rgba8(c, a).premultiply();
} }
//-------------------------------------------------------------rgb8_packed //-------------------------------------------------------------rgb8_packed
inline rgba8 rgb8_packed(unsigned v) inline rgba8 rgb8_packed(unsigned v)
{ {
@ -674,19 +665,16 @@ rgba8 rgba8_gamma_inv(rgba8 c, const GammaLUT& gamma)
return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
} }
//==================================================================rgba16 //==================================================================rgba16
struct rgba16 struct rgba16
{ {
typedef int16u value_type; typedef int16u value_type;
typedef int32u calc_type; typedef int32u calc_type;
typedef int64 long_type; typedef int64 long_type;
enum base_scale_e enum base_scale_e {
{
base_shift = 16, base_shift = 16,
base_scale = 1 << base_shift, base_scale = 1 << base_shift,
base_mask = base_scale - 1, base_mask = base_scale - 1,
base_MSB = 1 << (base_shift - 1) base_MSB = 1 << (base_shift - 1)
}; };
typedef rgba16 self_type; typedef rgba16 self_type;
@ -700,105 +688,81 @@ struct rgba16
rgba16() {} rgba16() {}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) : rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_ = base_mask)
r(value_type(r_)), : r(value_type(r_))
g(value_type(g_)), , g(value_type(g_))
b(value_type(b_)), , b(value_type(b_))
a(value_type(a_)) {} , a(value_type(a_))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba16(const self_type& c, unsigned a_) : rgba16(const self_type& c, unsigned a_)
r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} : r(c.r)
, g(c.g)
, b(c.b)
, a(value_type(a_))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba16(const rgba& c) : rgba16(const rgba& c)
r((value_type)uround(c.r * double(base_mask))), : r((value_type)uround(c.r * double(base_mask)))
g((value_type)uround(c.g * double(base_mask))), , g((value_type)uround(c.g * double(base_mask)))
b((value_type)uround(c.b * double(base_mask))), , b((value_type)uround(c.b * double(base_mask)))
a((value_type)uround(c.a * double(base_mask))) {} , a((value_type)uround(c.a * double(base_mask)))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba16(const rgba8& c) : rgba16(const rgba8& c)
r(value_type((value_type(c.r) << 8) | c.r)), : r(value_type((value_type(c.r) << 8) | c.r))
g(value_type((value_type(c.g) << 8) | c.g)), , g(value_type((value_type(c.g) << 8) | c.g))
b(value_type((value_type(c.b) << 8) | c.b)), , b(value_type((value_type(c.b) << 8) | c.b))
a(value_type((value_type(c.a) << 8) | c.a)) {} , a(value_type((value_type(c.a) << 8) | c.a))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba16(const srgba8& c) : rgba16(const srgba8& c)
r(sRGB_conv<value_type>::rgb_from_sRGB(c.r)), : r(sRGB_conv<value_type>::rgb_from_sRGB(c.r))
g(sRGB_conv<value_type>::rgb_from_sRGB(c.g)), , g(sRGB_conv<value_type>::rgb_from_sRGB(c.g))
b(sRGB_conv<value_type>::rgb_from_sRGB(c.b)), , b(sRGB_conv<value_type>::rgb_from_sRGB(c.b))
a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {} , a(sRGB_conv<value_type>::alpha_from_sRGB(c.a))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba() const operator rgba() const { return rgba(r / 65535.0, g / 65535.0, b / 65535.0, a / 65535.0); }
{
return rgba(
r / 65535.0,
g / 65535.0,
b / 65535.0,
a / 65535.0);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba8() const operator rgba8() const { return rgba8(r >> 8, g >> 8, b >> 8, a >> 8); }
{
return rgba8(r >> 8, g >> 8, b >> 8, a >> 8);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator srgba8() const operator srgba8() const
{ {
// Return (non-premultiplied) sRGB values. // Return (non-premultiplied) sRGB values.
return srgba8( return srgba8(sRGB_conv<value_type>::rgb_to_sRGB(r),
sRGB_conv<value_type>::rgb_to_sRGB(r), sRGB_conv<value_type>::rgb_to_sRGB(g),
sRGB_conv<value_type>::rgb_to_sRGB(g), sRGB_conv<value_type>::rgb_to_sRGB(b),
sRGB_conv<value_type>::rgb_to_sRGB(b), sRGB_conv<value_type>::alpha_to_sRGB(a));
sRGB_conv<value_type>::alpha_to_sRGB(a));
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a) static AGG_INLINE double to_double(value_type a) { return double(a) / base_mask; }
{
return double(a) / base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a) static AGG_INLINE value_type from_double(double a) { return value_type(uround(a * base_mask)); }
{
return value_type(uround(a * base_mask));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type empty_value() static AGG_INLINE value_type empty_value() { return 0; }
{
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type full_value() static AGG_INLINE value_type full_value() { return base_mask; }
{
return base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const AGG_INLINE bool is_transparent() const { return a == 0; }
{
return a == 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const AGG_INLINE bool is_opaque() const { return a == base_mask; }
{
return a == base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type invert(value_type x) static AGG_INLINE value_type invert(value_type x) { return base_mask - x; }
{
return base_mask - x;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Fixed-point multiply, exact over int16u. // Fixed-point multiply, exact over int16u.
@ -819,7 +783,8 @@ struct rgba16
{ {
return base_mask; return base_mask;
} }
else return value_type((a * base_mask + (b >> 1)) / b); else
return value_type((a * base_mask + (b >> 1)) / b);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -839,23 +804,14 @@ struct rgba16
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Fixed-point multiply, almost exact over int16u. // Fixed-point multiply, almost exact over int16u.
// Specifically for multiplying a color component by a cover. // Specifically for multiplying a color component by a cover.
static AGG_INLINE value_type mult_cover(value_type a, cover_type b) static AGG_INLINE value_type mult_cover(value_type a, cover_type b) { return multiply(a, (b << 8) | b); }
{
return multiply(a, (b << 8) | b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return multiply((a << 8) | a, b) >> 8; }
{
return multiply((a << 8) | a, b) >> 8;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a, assuming q is premultiplied by a. // Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) { return p + q - multiply(p, a); }
{
return p + q - multiply(p, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a. // Interpolate p to q by a.
@ -882,17 +838,16 @@ struct rgba16
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE self_type& opacity(double a_) AGG_INLINE self_type& opacity(double a_)
{ {
if (a_ < 0) a = 0; if (a_ < 0)
if (a_ > 1) a = 1; a = 0;
if (a_ > 1)
a = 1;
a = value_type(uround(a_ * double(base_mask))); a = value_type(uround(a_ * double(base_mask)));
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
double opacity() const double opacity() const { return double(a) / double(base_mask); }
{
return double(a) / double(base_mask);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE self_type& premultiply() AGG_INLINE self_type& premultiply()
@ -1014,7 +969,7 @@ struct rgba16
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0,0,0); } static self_type no_color() { return self_type(0, 0, 0, 0); }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static self_type from_wavelength(double wl, double gamma = 1.0) static self_type from_wavelength(double wl, double gamma = 1.0)
@ -1023,7 +978,6 @@ struct rgba16
} }
}; };
//------------------------------------------------------rgba16_gamma_dir //------------------------------------------------------rgba16_gamma_dir
template<class GammaLUT> template<class GammaLUT>
rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma) rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma)
@ -1055,127 +1009,100 @@ struct rgba32
rgba32() {} rgba32() {}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba32(value_type r_, value_type g_, value_type b_, value_type a_= 1) : rgba32(value_type r_, value_type g_, value_type b_, value_type a_ = 1)
r(r_), g(g_), b(b_), a(a_) {} : r(r_)
, g(g_)
, b(b_)
, a(a_)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba32(const self_type& c, float a_) : rgba32(const self_type& c, float a_)
r(c.r), g(c.g), b(c.b), a(a_) {} : r(c.r)
, g(c.g)
, b(c.b)
, a(a_)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba32(const rgba& c) : rgba32(const rgba& c)
r(value_type(c.r)), g(value_type(c.g)), b(value_type(c.b)), a(value_type(c.a)) {} : r(value_type(c.r))
, g(value_type(c.g))
, b(value_type(c.b))
, a(value_type(c.a))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba32(const rgba8& c) : rgba32(const rgba8& c)
r(value_type(c.r / 255.0)), : r(value_type(c.r / 255.0))
g(value_type(c.g / 255.0)), , g(value_type(c.g / 255.0))
b(value_type(c.b / 255.0)), , b(value_type(c.b / 255.0))
a(value_type(c.a / 255.0)) {} , a(value_type(c.a / 255.0))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba32(const srgba8& c) : rgba32(const srgba8& c)
r(sRGB_conv<value_type>::rgb_from_sRGB(c.r)), : r(sRGB_conv<value_type>::rgb_from_sRGB(c.r))
g(sRGB_conv<value_type>::rgb_from_sRGB(c.g)), , g(sRGB_conv<value_type>::rgb_from_sRGB(c.g))
b(sRGB_conv<value_type>::rgb_from_sRGB(c.b)), , b(sRGB_conv<value_type>::rgb_from_sRGB(c.b))
a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {} , a(sRGB_conv<value_type>::alpha_from_sRGB(c.a))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba32(const rgba16& c) : rgba32(const rgba16& c)
r(value_type(c.r / 65535.0)), : r(value_type(c.r / 65535.0))
g(value_type(c.g / 65535.0)), , g(value_type(c.g / 65535.0))
b(value_type(c.b / 65535.0)), , b(value_type(c.b / 65535.0))
a(value_type(c.a / 65535.0)) {} , a(value_type(c.a / 65535.0))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba() const operator rgba() const { return rgba(r, g, b, a); }
{
return rgba(r, g, b, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba8() const operator rgba8() const { return rgba8(uround(r * 255.0), uround(g * 255.0), uround(b * 255.0), uround(a * 255.0)); }
{
return rgba8(
uround(r * 255.0),
uround(g * 255.0),
uround(b * 255.0),
uround(a * 255.0));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator srgba8() const operator srgba8() const
{ {
return srgba8( return srgba8(sRGB_conv<value_type>::rgb_to_sRGB(r),
sRGB_conv<value_type>::rgb_to_sRGB(r), sRGB_conv<value_type>::rgb_to_sRGB(g),
sRGB_conv<value_type>::rgb_to_sRGB(g), sRGB_conv<value_type>::rgb_to_sRGB(b),
sRGB_conv<value_type>::rgb_to_sRGB(b), sRGB_conv<value_type>::alpha_to_sRGB(a));
sRGB_conv<value_type>::alpha_to_sRGB(a));
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba16() const operator rgba16() const
{ {
return rgba8( return rgba8(uround(r * 65535.0), uround(g * 65535.0), uround(b * 65535.0), uround(a * 65535.0));
uround(r * 65535.0),
uround(g * 65535.0),
uround(b * 65535.0),
uround(a * 65535.0));
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a) static AGG_INLINE double to_double(value_type a) { return a; }
{
return a;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a) static AGG_INLINE value_type from_double(double a) { return value_type(a); }
{
return value_type(a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type empty_value() static AGG_INLINE value_type empty_value() { return 0; }
{
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type full_value() static AGG_INLINE value_type full_value() { return 1; }
{
return 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const AGG_INLINE bool is_transparent() const { return a <= 0; }
{
return a <= 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const AGG_INLINE bool is_opaque() const { return a >= 1; }
{
return a >= 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type invert(value_type x) static AGG_INLINE value_type invert(value_type x) { return 1 - x; }
{
return 1 - x;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type multiply(value_type a, value_type b) static AGG_INLINE value_type multiply(value_type a, value_type b) { return value_type(a * b); }
{
return value_type(a * b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type demultiply(value_type a, value_type b) static AGG_INLINE value_type demultiply(value_type a, value_type b) { return (b == 0) ? 0 : value_type(a / b); }
{
return (b == 0) ? 0 : value_type(a / b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
template<typename T> template<typename T>
@ -1192,16 +1119,10 @@ struct rgba32
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type mult_cover(value_type a, cover_type b) static AGG_INLINE value_type mult_cover(value_type a, cover_type b) { return value_type(a * b / cover_mask); }
{
return value_type(a * b / cover_mask);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return cover_type(uround(a * b)); }
{
return cover_type(uround(a * b));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a, assuming q is premultiplied by a. // Interpolate p to q by a, assuming q is premultiplied by a.
@ -1238,17 +1159,17 @@ struct rgba32
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE self_type& opacity(double a_) AGG_INLINE self_type& opacity(double a_)
{ {
if (a_ < 0) a = 0; if (a_ < 0)
else if (a_ > 1) a = 1; a = 0;
else a = value_type(a_); else if (a_ > 1)
a = 1;
else
a = value_type(a_);
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
double opacity() const double opacity() const { return a; }
{
return a;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE self_type& premultiply() AGG_INLINE self_type& premultiply()
@ -1324,10 +1245,14 @@ struct rgba32
b += mult_cover(c.b, cover); b += mult_cover(c.b, cover);
a += mult_cover(c.a, cover); a += mult_cover(c.a, cover);
} }
if (a > 1) a = 1; if (a > 1)
if (r > a) r = a; a = 1;
if (g > a) g = a; if (r > a)
if (b > a) b = a; r = a;
if (g > a)
g = a;
if (b > a)
b = a;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -1349,7 +1274,7 @@ struct rgba32
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0,0,0); } static self_type no_color() { return self_type(0, 0, 0, 0); }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static self_type from_wavelength(double wl, double gamma = 1) static self_type from_wavelength(double wl, double gamma = 1)
@ -1357,8 +1282,6 @@ struct rgba32
return self_type(rgba::from_wavelength(wl, gamma)); return self_type(rgba::from_wavelength(wl, gamma));
} }
}; };
} } // namespace agg
#endif #endif

View file

@ -26,7 +26,6 @@
// but it won't result any crash and the rest of the library will remain // but it won't result any crash and the rest of the library will remain
// fully functional. // fully functional.
//--------------------------------------- //---------------------------------------
// 2. Default rendering_buffer type. Can be: // 2. Default rendering_buffer type. Can be:
// //

View file

@ -18,106 +18,95 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//------------------------------------------------------------null_markers
struct null_markers
{ {
//------------------------------------------------------------null_markers void remove_all() {}
struct null_markers void add_vertex(double, double, unsigned) {}
void prepare_src() {}
void rewind(unsigned) {}
unsigned vertex(double*, double*) { return path_cmd_stop; }
unsigned type() const { return 0; }
};
//------------------------------------------------------conv_adaptor_vcgen
template<class VertexSource, class Generator, class Markers = null_markers>
class conv_adaptor_vcgen
{
enum status { initial, accumulate, generate };
public:
explicit conv_adaptor_vcgen(VertexSource& source)
: m_source(&source)
, m_status(initial)
{}
conv_adaptor_vcgen(conv_adaptor_vcgen<VertexSource, Generator, Markers>&&) = default;
void attach(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 path_id)
{ {
void remove_all() {} m_source->rewind(path_id);
void add_vertex(double, double, unsigned) {} m_status = initial;
void prepare_src() {} }
void rewind(unsigned) {} unsigned vertex(double* x, double* y);
unsigned vertex(double*, double*) { return path_cmd_stop; } unsigned type() const { return m_source->type(); }
unsigned type() const { return 0; }
};
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>&);
//------------------------------------------------------conv_adaptor_vcgen VertexSource* m_source;
template<class VertexSource, Generator m_generator;
class Generator, Markers m_markers;
class Markers=null_markers> class conv_adaptor_vcgen 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)
{ {
enum status switch (m_status)
{ {
initial,
accumulate,
generate
};
public:
explicit conv_adaptor_vcgen(VertexSource& source) :
m_source(&source),
m_status(initial)
{}
conv_adaptor_vcgen(conv_adaptor_vcgen<VertexSource, Generator, Markers> &&) = default;
void attach(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 path_id)
{
m_source->rewind(path_id);
m_status = initial;
}
unsigned vertex(double* x, double* y);
unsigned type() const { return m_source->type(); }
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: case initial:
m_markers.remove_all(); m_markers.remove_all();
m_last_cmd = m_source->vertex(&m_start_x, &m_start_y); m_last_cmd = m_source->vertex(&m_start_x, &m_start_y);
m_status = accumulate; m_status = accumulate;
case accumulate: case accumulate:
if(is_stop(m_last_cmd)) return path_cmd_stop; if (is_stop(m_last_cmd))
return path_cmd_stop;
m_generator.remove_all(); m_generator.remove_all();
m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to); 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); m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
for(;;) for (;;)
{ {
cmd = m_source->vertex(x, y); cmd = m_source->vertex(x, y);
if(is_vertex(cmd)) if (is_vertex(cmd))
{ {
m_last_cmd = cmd; m_last_cmd = cmd;
if(is_move_to(cmd)) if (is_move_to(cmd))
{ {
m_start_x = *x; m_start_x = *x;
m_start_y = *y; m_start_y = *y;
@ -128,12 +117,12 @@ namespace agg
} }
else else
{ {
if(is_stop(cmd)) if (is_stop(cmd))
{ {
m_last_cmd = path_cmd_stop; m_last_cmd = path_cmd_stop;
break; break;
} }
if(is_end_poly(cmd)) if (is_end_poly(cmd))
{ {
m_generator.add_vertex(*x, *y, cmd); m_generator.add_vertex(*x, *y, cmd);
break; break;
@ -145,18 +134,18 @@ namespace agg
case generate: case generate:
cmd = m_generator.vertex(x, y); cmd = m_generator.vertex(x, y);
if(is_stop(cmd)) if (is_stop(cmd))
{ {
m_status = accumulate; m_status = accumulate;
break; break;
} }
done = true; done = true;
break; break;
}
} }
return cmd;
} }
return cmd;
} }
} // namespace agg
#endif #endif

View file

@ -18,143 +18,140 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//======================================================conv_adaptor_vpgen
template<class VertexSource, class VPGen>
class conv_adaptor_vpgen
{ {
public:
explicit conv_adaptor_vpgen(VertexSource& source)
: m_source(&source)
{}
void attach(VertexSource& source) { m_source = &source; }
//======================================================conv_adaptor_vpgen VPGen& vpgen() { return m_vpgen; }
template<class VertexSource, class VPGen> class conv_adaptor_vpgen const VPGen& vpgen() const { return m_vpgen; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
unsigned type() const { return m_source->type(); }
private:
conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);
const conv_adaptor_vpgen<VertexSource, VPGen>& operator=(const conv_adaptor_vpgen<VertexSource, VPGen>&);
VertexSource* m_source;
VPGen m_vpgen;
double m_start_x;
double m_start_y;
unsigned m_poly_flags;
int m_vertices;
};
//------------------------------------------------------------------------
template<class VertexSource, class VPGen>
void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id)
{
m_source->rewind(path_id);
m_vpgen.reset();
m_start_x = 0;
m_start_y = 0;
m_poly_flags = 0;
m_vertices = 0;
}
//------------------------------------------------------------------------
template<class VertexSource, class VPGen>
unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_stop;
for (;;)
{ {
public: cmd = m_vpgen.vertex(x, y);
explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {} if (!is_stop(cmd))
void attach(VertexSource& source) { m_source = &source; } break;
VPGen& vpgen() { return m_vpgen; } if (m_poly_flags && !m_vpgen.auto_unclose())
const VPGen& vpgen() const { return m_vpgen; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
unsigned type() const { return m_source->type(); }
private:
conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);
const conv_adaptor_vpgen<VertexSource, VPGen>&
operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&);
VertexSource* m_source;
VPGen m_vpgen;
double m_start_x;
double m_start_y;
unsigned m_poly_flags;
int m_vertices;
};
//------------------------------------------------------------------------
template<class VertexSource, class VPGen>
void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id)
{
m_source->rewind(path_id);
m_vpgen.reset();
m_start_x = 0;
m_start_y = 0;
m_poly_flags = 0;
m_vertices = 0;
}
//------------------------------------------------------------------------
template<class VertexSource, class VPGen>
unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_stop;
for(;;)
{ {
cmd = m_vpgen.vertex(x, y); *x = 0.0;
if(!is_stop(cmd)) break; *y = 0.0;
cmd = m_poly_flags;
m_poly_flags = 0;
break;
}
if(m_poly_flags && !m_vpgen.auto_unclose()) if (m_vertices < 0)
{
if (m_vertices < -1)
{ {
*x = 0.0; m_vertices = 0;
*y = 0.0; return path_cmd_stop;
cmd = m_poly_flags;
m_poly_flags = 0;
break;
} }
m_vpgen.move_to(m_start_x, m_start_y);
m_vertices = 1;
continue;
}
if(m_vertices < 0) double tx, ty;
cmd = m_source->vertex(&tx, &ty);
if (is_vertex(cmd))
{
if (is_move_to(cmd))
{ {
if(m_vertices < -1) if (m_vpgen.auto_close() && m_vertices > 2)
{ {
m_vertices = 0; m_vpgen.line_to(m_start_x, m_start_y);
return path_cmd_stop; m_poly_flags = path_cmd_end_poly | path_flags_close;
m_start_x = tx;
m_start_y = ty;
m_vertices = -1;
continue;
} }
m_vpgen.move_to(m_start_x, m_start_y); m_vpgen.move_to(tx, ty);
m_start_x = tx;
m_start_y = ty;
m_vertices = 1; m_vertices = 1;
continue;
} }
else
double tx, ty;
cmd = m_source->vertex(&tx, &ty);
if(is_vertex(cmd))
{ {
if(is_move_to(cmd)) m_vpgen.line_to(tx, ty);
++m_vertices;
}
}
else
{
if (is_end_poly(cmd))
{
m_poly_flags = cmd;
if (is_closed(cmd) || m_vpgen.auto_close())
{ {
if(m_vpgen.auto_close() && m_vertices > 2) if (m_vpgen.auto_close())
m_poly_flags |= path_flags_close;
if (m_vertices > 2)
{ {
m_vpgen.line_to(m_start_x, m_start_y); m_vpgen.line_to(m_start_x, m_start_y);
m_poly_flags = path_cmd_end_poly | path_flags_close;
m_start_x = tx;
m_start_y = ty;
m_vertices = -1;
continue;
} }
m_vpgen.move_to(tx, ty); m_vertices = 0;
m_start_x = tx;
m_start_y = ty;
m_vertices = 1;
}
else
{
m_vpgen.line_to(tx, ty);
++m_vertices;
} }
} }
else else
{ {
if(is_end_poly(cmd)) // path_cmd_stop
if (m_vpgen.auto_close() && m_vertices > 2)
{ {
m_poly_flags = cmd; m_vpgen.line_to(m_start_x, m_start_y);
if(is_closed(cmd) || m_vpgen.auto_close()) m_poly_flags = path_cmd_end_poly | path_flags_close;
{ m_vertices = -2;
if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close; continue;
if(m_vertices > 2)
{
m_vpgen.line_to(m_start_x, m_start_y);
}
m_vertices = 0;
}
}
else
{
// path_cmd_stop
if(m_vpgen.auto_close() && m_vertices > 2)
{
m_vpgen.line_to(m_start_x, m_start_y);
m_poly_flags = path_cmd_end_poly | path_flags_close;
m_vertices = -2;
continue;
}
break;
} }
break;
} }
} }
return cmd;
} }
return cmd;
} }
} // namespace agg
#endif #endif

View file

@ -19,30 +19,26 @@
#include "agg_vcgen_bspline.h" #include "agg_vcgen_bspline.h"
#include "agg_conv_adaptor_vcgen.h" #include "agg_conv_adaptor_vcgen.h"
namespace agg {
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 conv_bspline(VertexSource& vs)
template<class VertexSource> : conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs)
struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline> {}
{
typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type;
conv_bspline(VertexSource& vs) : void interpolation_step(double v) { base_type::generator().interpolation_step(v); }
conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) {} double interpolation_step() const { return base_type::generator().interpolation_step(); }
void interpolation_step(double v) { base_type::generator().interpolation_step(v); } private:
double interpolation_step() const { return base_type::generator().interpolation_step(); } conv_bspline(const conv_bspline<VertexSource>&);
const conv_bspline<VertexSource>& operator=(const conv_bspline<VertexSource>&);
private: };
conv_bspline(const conv_bspline<VertexSource>&);
const conv_bspline<VertexSource>&
operator = (const conv_bspline<VertexSource>&);
};
}
} // namespace agg
#endif #endif

View file

@ -30,35 +30,31 @@
#include "agg_conv_adaptor_vpgen.h" #include "agg_conv_adaptor_vpgen.h"
#include "agg_vpgen_clip_polygon.h" #include "agg_vpgen_clip_polygon.h"
namespace agg 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 conv_clip_polygon(VertexSource& vs)
template<class VertexSource> : conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs)
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) : void clip_box(double _x1, double _y1, double _x2, double _y2) { base_type::vpgen().clip_box(_x1, _y1, _x2, _y2); }
conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) {}
void clip_box(double _x1, double _y1, double _x2, double _y2) double x1() const { return base_type::vpgen().x1(); }
{ double y1() const { return base_type::vpgen().y1(); }
base_type::vpgen().clip_box(_x1, _y1, _x2, _y2); double x2() const { return base_type::vpgen().x2(); }
} double y2() const { return base_type::vpgen().y2(); }
unsigned type() const { return base_type::type(); }
double x1() const { return base_type::vpgen().x1(); } private:
double y1() const { return base_type::vpgen().y1(); } conv_clip_polygon(const conv_clip_polygon<VertexSource>&);
double x2() const { return base_type::vpgen().x2(); } const conv_clip_polygon<VertexSource>& operator=(const conv_clip_polygon<VertexSource>&);
double y2() const { return base_type::vpgen().y2(); } };
unsigned type() const { return base_type::type(); }
private: } // namespace agg
conv_clip_polygon(const conv_clip_polygon<VertexSource>&);
const conv_clip_polygon<VertexSource>&
operator = (const conv_clip_polygon<VertexSource>&);
};
}
#endif #endif

View file

@ -30,35 +30,31 @@
#include "agg_conv_adaptor_vpgen.h" #include "agg_conv_adaptor_vpgen.h"
#include "agg_vpgen_clip_polyline.h" #include "agg_vpgen_clip_polyline.h"
namespace agg namespace agg {
//=======================================================conv_clip_polyline
template<class VertexSource>
struct conv_clip_polyline : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>
{ {
typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> base_type;
//=======================================================conv_clip_polyline conv_clip_polyline(VertexSource& vs)
template<class VertexSource> : conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(vs)
struct conv_clip_polyline : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> {}
{
typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> base_type;
conv_clip_polyline(VertexSource& vs) : void clip_box(double _x1, double _y1, double _x2, double _y2) { base_type::vpgen().clip_box(_x1, _y1, _x2, _y2); }
conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(vs) {}
void clip_box(double _x1, double _y1, double _x2, double _y2) double x1() const { return base_type::vpgen().x1(); }
{ double y1() const { return base_type::vpgen().y1(); }
base_type::vpgen().clip_box(_x1, _y1, _x2, _y2); double x2() const { return base_type::vpgen().x2(); }
} double y2() const { return base_type::vpgen().y2(); }
unsigned type() const { return base_type::type(); }
double x1() const { return base_type::vpgen().x1(); } private:
double y1() const { return base_type::vpgen().y1(); } conv_clip_polyline(const conv_clip_polyline<VertexSource>&);
double x2() const { return base_type::vpgen().x2(); } const conv_clip_polyline<VertexSource>& operator=(const conv_clip_polyline<VertexSource>&);
double y2() const { return base_type::vpgen().y2(); } };
unsigned type() const { return base_type::type(); }
private: } // namespace agg
conv_clip_polyline(const conv_clip_polyline<VertexSource>&);
const conv_clip_polyline<VertexSource>&
operator = (const conv_clip_polyline<VertexSource>&);
};
}
#endif #endif

View file

@ -18,108 +18,105 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//======================================================conv_close_polygon
template<class VertexSource>
class conv_close_polygon
{ {
public:
explicit conv_close_polygon(VertexSource& vs)
: m_source(&vs)
{}
void attach(VertexSource& source) { m_source = &source; }
//======================================================conv_close_polygon void rewind(unsigned path_id);
template<class VertexSource> class conv_close_polygon unsigned vertex(double* x, double* y);
{
public:
explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
void attach(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id); private:
unsigned vertex(double* x, double* y); conv_close_polygon(const conv_close_polygon<VertexSource>&);
const conv_close_polygon<VertexSource>& operator=(const conv_close_polygon<VertexSource>&);
private: VertexSource* m_source;
conv_close_polygon(const conv_close_polygon<VertexSource>&); unsigned m_cmd[2];
const conv_close_polygon<VertexSource>& double m_x[2];
operator = (const conv_close_polygon<VertexSource>&); double m_y[2];
unsigned m_vertex;
VertexSource* m_source; bool m_line_to;
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;
}
//------------------------------------------------------------------------
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;
}
} // namespace agg
#endif #endif

View file

@ -18,56 +18,57 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg 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
{ {
//=============================================================conv_concat public:
// Concatenation of two paths. Usually used to combine lines or curves conv_concat(VS1& source1, VS2& source2)
// with markers such as arrowheads : m_source1(&source1)
template<class VS1, class VS2> class conv_concat , m_source2(&source2)
, m_status(2)
{}
void attach1(VS1& source) { m_source1 = &source; }
void attach2(VS2& source) { m_source2 = &source; }
void rewind(unsigned path_id)
{ {
public: m_source1->rewind(path_id);
conv_concat(VS1& source1, VS2& source2) : m_source2->rewind(0);
m_source1(&source1), m_source2(&source2), m_status(2) {} m_status = 0;
void attach1(VS1& source) { m_source1 = &source; } }
void attach2(VS2& source) { m_source2 = &source; }
unsigned vertex(double* x, double* y)
void rewind(unsigned path_id) {
unsigned cmd;
if (m_status == 0)
{ {
m_source1->rewind(path_id); cmd = m_source1->vertex(x, y);
m_source2->rewind(0); if (!is_stop(cmd))
m_status = 0; return cmd;
m_status = 1;
} }
if (m_status == 1)
unsigned vertex(double* x, double* y)
{ {
unsigned cmd; cmd = m_source2->vertex(x, y);
if(m_status == 0) if (!is_stop(cmd))
{ return cmd;
cmd = m_source1->vertex(x, y); m_status = 2;
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;
} }
return path_cmd_stop;
}
private: private:
conv_concat(const conv_concat<VS1, VS2>&); conv_concat(const conv_concat<VS1, VS2>&);
const conv_concat<VS1, VS2>& const conv_concat<VS1, VS2>& operator=(const conv_concat<VS1, VS2>&);
operator = (const conv_concat<VS1, VS2>&);
VS1* m_source1;
VS2* m_source2;
int m_status;
};
}
VS1* m_source1;
VS2* m_source2;
int m_status;
};
} // namespace agg
#endif #endif

View file

@ -23,43 +23,40 @@
#include "agg_vcgen_contour.h" #include "agg_vcgen_contour.h"
#include "agg_conv_adaptor_vcgen.h" #include "agg_conv_adaptor_vcgen.h"
namespace agg 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 conv_contour(VertexSource& vs)
template<class VertexSource> : conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs)
struct conv_contour : public conv_adaptor_vcgen<VertexSource, vcgen_contour> {}
{
typedef conv_adaptor_vcgen<VertexSource, vcgen_contour> base_type;
conv_contour(VertexSource& vs) : void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs) void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
{ void width(double w) { base_type::generator().width(w); }
} void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); }
void line_join(line_join_e lj) { base_type::generator().line_join(lj); } line_join_e line_join() const { return base_type::generator().line_join(); }
void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); } inner_join_e inner_join() const { return base_type::generator().inner_join(); }
void width(double w) { base_type::generator().width(w); } double width() const { return base_type::generator().width(); }
void miter_limit(double ml) { base_type::generator().miter_limit(ml); } double miter_limit() const { return base_type::generator().miter_limit(); }
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); } double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); } double approximation_scale() const { return base_type::generator().approximation_scale(); }
void approximation_scale(double as) { base_type::generator().approximation_scale(as); } bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); }
void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); }
line_join_e line_join() const { return base_type::generator().line_join(); } private:
inner_join_e inner_join() const { return base_type::generator().inner_join(); } conv_contour(const conv_contour<VertexSource>&);
double width() const { return base_type::generator().width(); } const conv_contour<VertexSource>& operator=(const conv_contour<VertexSource>&);
double miter_limit() const { return base_type::generator().miter_limit(); } };
double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
double approximation_scale() const { return base_type::generator().approximation_scale(); }
bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); }
private: } // namespace agg
conv_contour(const conv_contour<VertexSource>&);
const conv_contour<VertexSource>&
operator = (const conv_contour<VertexSource>&);
};
}
#endif #endif

View file

@ -23,157 +23,140 @@
#include "agg_basics.h" #include "agg_basics.h"
#include "agg_curves.h" #include "agg_curves.h"
namespace agg 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 circular and elliptical. Curves are approximated
// with straight lines and one of the approaches is just to store the whole
// sequence of vertices that approximate our curve. It takes additional
// memory, and at the same time the consecutive vertices can be calculated
// on demand.
//
// Initially, path storages are not suppose to keep all the vertices of the
// curves (although, nothing prevents us from doing so). Instead, path_storage
// keeps only vertices, needed to calculate a curve on demand. Those vertices
// are marked with special commands. So, if the path_storage contains curves
// (which are not real curves yet), and we render this storage directly,
// 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 Curve3 = curve3, class Curve4 = curve4>
class conv_curve
{ {
public:
typedef Curve3 curve3_type;
typedef Curve4 curve4_type;
typedef conv_curve<VertexSource, Curve3, Curve4> self_type;
explicit conv_curve(VertexSource& source)
: m_source(&source)
, m_last_x(0.0)
, m_last_y(0.0)
{}
//---------------------------------------------------------------conv_curve conv_curve(self_type&&) = default;
// Curve converter class. Any path storage can have Bezier curves defined
// by their control points. There're two types of curves supported: curve3 void attach(VertexSource& source) { m_source = &source; }
// 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 void approximation_method(curve_approximation_method_e v)
// to interpolate more complicated curves. Curve4, unlike curve3 can be used
// to approximate arcs, both circular and elliptical. Curves are approximated
// with straight lines and one of the approaches is just to store the whole
// sequence of vertices that approximate our curve. It takes additional
// memory, and at the same time the consecutive vertices can be calculated
// on demand.
//
// Initially, path storages are not suppose to keep all the vertices of the
// curves (although, nothing prevents us from doing so). Instead, path_storage
// keeps only vertices, needed to calculate a curve on demand. Those vertices
// are marked with special commands. So, if the path_storage contains curves
// (which are not real curves yet), and we render this storage directly,
// 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 Curve3=curve3,
class Curve4=curve4> class conv_curve
{ {
public: m_curve3.approximation_method(v);
typedef Curve3 curve3_type; m_curve4.approximation_method(v);
typedef Curve4 curve4_type;
typedef conv_curve<VertexSource, Curve3, Curve4> self_type;
explicit conv_curve(VertexSource& source) :
m_source(&source), m_last_x(0.0), m_last_y(0.0) {}
conv_curve(self_type &&) = default;
void attach(VertexSource& source) { m_source = &source; }
void approximation_method(curve_approximation_method_e v)
{
m_curve3.approximation_method(v);
m_curve4.approximation_method(v);
}
curve_approximation_method_e approximation_method() const
{
return m_curve4.approximation_method();
}
void approximation_scale(double s)
{
m_curve3.approximation_scale(s);
m_curve4.approximation_scale(s);
}
double approximation_scale() const
{
return m_curve4.approximation_scale();
}
void angle_tolerance(double v)
{
m_curve3.angle_tolerance(v);
m_curve4.angle_tolerance(v);
}
double angle_tolerance() const
{
return m_curve4.angle_tolerance();
}
void cusp_limit(double v)
{
m_curve3.cusp_limit(v);
m_curve4.cusp_limit(v);
}
double cusp_limit() const
{
return m_curve4.cusp_limit();
}
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
private:
conv_curve(const self_type&);
const self_type& operator = (const self_type&);
VertexSource* m_source;
double m_last_x;
double m_last_y;
curve3_type m_curve3;
curve4_type m_curve4;
};
//------------------------------------------------------------------------
template<class VertexSource, class Curve3, class Curve4>
void conv_curve<VertexSource, Curve3, Curve4>::rewind(unsigned path_id)
{
m_source->rewind(path_id);
m_last_x = 0.0;
m_last_y = 0.0;
m_curve3.reset();
m_curve4.reset();
} }
curve_approximation_method_e approximation_method() const { return m_curve4.approximation_method(); }
//------------------------------------------------------------------------ void approximation_scale(double s)
template<class VertexSource, class Curve3, class Curve4>
unsigned conv_curve<VertexSource, Curve3, Curve4>::vertex(double* x, double* y)
{ {
if(!is_stop(m_curve3.vertex(x, y))) m_curve3.approximation_scale(s);
{ m_curve4.approximation_scale(s);
m_last_x = *x; }
m_last_y = *y;
return path_cmd_line_to;
}
if(!is_stop(m_curve4.vertex(x, y))) double approximation_scale() const { return m_curve4.approximation_scale(); }
{
m_last_x = *x;
m_last_y = *y;
return path_cmd_line_to;
}
double ct2_x=0; void angle_tolerance(double v)
double ct2_y=0; {
double end_x=0; m_curve3.angle_tolerance(v);
double end_y=0; m_curve4.angle_tolerance(v);
}
unsigned cmd = m_source->vertex(x, y); double angle_tolerance() const { return m_curve4.angle_tolerance(); }
switch(cmd)
{ void cusp_limit(double v)
{
m_curve3.cusp_limit(v);
m_curve4.cusp_limit(v);
}
double cusp_limit() const { return m_curve4.cusp_limit(); }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
private:
conv_curve(const self_type&);
const self_type& operator=(const self_type&);
VertexSource* m_source;
double m_last_x;
double m_last_y;
curve3_type m_curve3;
curve4_type m_curve4;
};
//------------------------------------------------------------------------
template<class VertexSource, class Curve3, class Curve4>
void conv_curve<VertexSource, Curve3, Curve4>::rewind(unsigned path_id)
{
m_source->rewind(path_id);
m_last_x = 0.0;
m_last_y = 0.0;
m_curve3.reset();
m_curve4.reset();
}
//------------------------------------------------------------------------
template<class VertexSource, class Curve3, class Curve4>
unsigned conv_curve<VertexSource, Curve3, Curve4>::vertex(double* x, double* y)
{
if (!is_stop(m_curve3.vertex(x, y)))
{
m_last_x = *x;
m_last_y = *y;
return path_cmd_line_to;
}
if (!is_stop(m_curve4.vertex(x, y)))
{
m_last_x = *x;
m_last_y = *y;
return path_cmd_line_to;
}
double ct2_x = 0;
double ct2_y = 0;
double end_x = 0;
double end_y = 0;
unsigned cmd = m_source->vertex(x, y);
switch (cmd)
{
case path_cmd_curve3: case path_cmd_curve3:
m_source->vertex(&end_x, &end_y); m_source->vertex(&end_x, &end_y);
m_curve3.init(m_last_x, m_last_y, m_curve3.init(m_last_x, m_last_y, *x, *y, end_x, end_y);
*x, *y,
end_x, end_y);
m_curve3.vertex(x, y); // First call returns path_cmd_move_to m_curve3.vertex(x, y); // First call returns path_cmd_move_to
m_curve3.vertex(x, y); // This is the first vertex of the curve m_curve3.vertex(x, y); // This is the first vertex of the curve
cmd = path_cmd_line_to; cmd = path_cmd_line_to;
break; break;
@ -181,24 +164,18 @@ namespace agg
m_source->vertex(&ct2_x, &ct2_y); m_source->vertex(&ct2_x, &ct2_y);
m_source->vertex(&end_x, &end_y); m_source->vertex(&end_x, &end_y);
m_curve4.init(m_last_x, m_last_y, m_curve4.init(m_last_x, m_last_y, *x, *y, ct2_x, ct2_y, end_x, end_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); // First call returns path_cmd_move_to
m_curve4.vertex(x, y); // This is the first vertex of the curve m_curve4.vertex(x, y); // This is the first vertex of the curve
cmd = path_cmd_line_to; cmd = path_cmd_line_to;
break; break;
}
m_last_x = *x;
m_last_y = *y;
return cmd;
} }
m_last_x = *x;
m_last_y = *y;
return cmd;
} }
} // namespace agg
#endif #endif

View file

@ -23,46 +23,33 @@
#include "agg_vcgen_dash.h" #include "agg_vcgen_dash.h"
#include "agg_conv_adaptor_vcgen.h" #include "agg_conv_adaptor_vcgen.h"
namespace agg 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 conv_dash(VertexSource& vs)
template<class VertexSource, class Markers=null_markers> : conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs)
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) : void remove_all_dashes() { base_type::generator().remove_all_dashes(); }
conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs)
{
}
void remove_all_dashes() void add_dash(double dash_len, double gap_len) { base_type::generator().add_dash(dash_len, gap_len); }
{
base_type::generator().remove_all_dashes();
}
void add_dash(double dash_len, double gap_len) void dash_start(double ds) { base_type::generator().dash_start(ds); }
{
base_type::generator().add_dash(dash_len, gap_len);
}
void dash_start(double ds) void shorten(double s) { base_type::generator().shorten(s); }
{ double shorten() const { return base_type::generator().shorten(); }
base_type::generator().dash_start(ds);
}
void shorten(double s) { base_type::generator().shorten(s); } private:
double shorten() const { return base_type::generator().shorten(); } conv_dash(const conv_dash<VertexSource, Markers>&);
const conv_dash<VertexSource, Markers>& operator=(const conv_dash<VertexSource, Markers>&);
};
private: } // namespace agg
conv_dash(const conv_dash<VertexSource, Markers>&);
const conv_dash<VertexSource, Markers>&
operator = (const conv_dash<VertexSource, Markers>&);
};
}
#endif #endif

View file

@ -33,400 +33,348 @@ extern "C"
#include "gpc.h" #include "gpc.h"
} }
namespace agg 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 gpc_op_e enum status { status_move_to, status_line_to, status_stop };
struct contour_header_type
{ {
gpc_or, int num_vertices;
gpc_and, int hole_flag;
gpc_xor, gpc_vertex* vertices;
gpc_a_minus_b,
gpc_b_minus_a
}; };
typedef pod_bvector<gpc_vertex, 8> vertex_array_type;
typedef pod_bvector<contour_header_type, 6> contour_header_array_type;
//================================================================conv_gpc public:
template<class VSA, class VSB> class conv_gpc 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)
{ {
enum status memset(&m_poly_a, 0, sizeof(m_poly_a));
{ memset(&m_poly_b, 0, sizeof(m_poly_b));
status_move_to,
status_line_to,
status_stop
};
struct contour_header_type
{
int num_vertices;
int hole_flag;
gpc_vertex* vertices;
};
typedef pod_bvector<gpc_vertex, 8> vertex_array_type;
typedef pod_bvector<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 attach1(VSA& source) { m_src_a = &source; }
void attach2(VSB& source) { m_src_b = &source; }
void operation(gpc_op_e v) { m_operation = v; }
// Vertex Source Interface
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
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++)
{
pod_allocator<gpc_vertex>::deallocate(p.contour[i].vertex,
p.contour[i].num_vertices);
}
pod_allocator<gpc_vertex_list>::deallocate(p.contour, p.num_contours);
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)); memset(&m_result, 0, sizeof(m_result));
} }
void attach1(VSA& source) { m_src_a = &source; }
void attach2(VSB& source) { m_src_b = &source; }
//------------------------------------------------------------------------ void operation(gpc_op_e v) { m_operation = v; }
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::free_gpc_data() // Vertex Source Interface
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
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)
{ {
free_polygon(m_poly_a); unsigned cmd;
free_polygon(m_poly_b); double x, y;
free_result(); 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)))
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) if (is_vertex(cmd))
{ {
contour_header_type& h = if (is_move_to(cmd))
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 = pod_allocator<gpc_vertex>::allocate(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]; if (line_to)
d->x = s.x; {
d->y = s.y; end_contour(orientation);
++d; orientation = 0;
}
start_contour();
start_x = x;
start_y = y;
} }
add_vertex(x, y);
line_to = true;
} }
else else
{ {
m_vertex_accumulator.remove_last(); if (is_end_poly(cmd))
}
}
}
//------------------------------------------------------------------------
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();
p.hole = 0;
p.contour = pod_allocator<gpc_vertex_list>::allocate(p.num_contours);
int i;
gpc_vertex_list* pv = p.contour;
for(i = 0; i < p.num_contours; i++)
{
const contour_header_type& h = m_contour_accumulator[i];
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 path_id)
{
free_result();
m_src_a->rewind(path_id);
m_src_b->rewind(path_id);
add(*m_src_a, m_poly_a);
add(*m_src_b, m_poly_b);
switch(m_operation)
{
case gpc_or:
gpc_polygon_clip(GPC_UNION,
&m_poly_a,
&m_poly_b,
&m_result);
break;
case gpc_and:
gpc_polygon_clip(GPC_INT,
&m_poly_a,
&m_poly_b,
&m_result);
break;
case gpc_xor:
gpc_polygon_clip(GPC_XOR,
&m_poly_a,
&m_poly_b,
&m_result);
break;
case gpc_a_minus_b:
gpc_polygon_clip(GPC_DIFF,
&m_poly_a,
&m_poly_b,
&m_result);
break;
case gpc_b_minus_a:
gpc_polygon_clip(GPC_DIFF,
&m_poly_b,
&m_poly_a,
&m_result);
break;
}
start_extracting();
}
//------------------------------------------------------------------------
template<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; orientation = get_orientation(cmd);
return path_cmd_move_to; if (line_to && is_closed(cmd))
{
add_vertex(start_x, start_y);
}
} }
m_status = status_stop; }
return path_cmd_end_poly | path_flags_close; }
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++)
{
pod_allocator<gpc_vertex>::deallocate(p.contour[i].vertex, p.contour[i].num_vertices);
}
pod_allocator<gpc_vertex_list>::deallocate(p.contour, p.num_contours);
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 = pod_allocator<gpc_vertex>::allocate(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 else
{ {
if(next_vertex(x, y)) m_vertex_accumulator.remove_last();
{
return path_cmd_line_to;
}
else
{
m_status = status_move_to;
}
return path_cmd_end_poly | path_flags_close;
} }
return path_cmd_stop;
} }
} }
//------------------------------------------------------------------------
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();
p.hole = 0;
p.contour = pod_allocator<gpc_vertex_list>::allocate(p.num_contours);
int i;
gpc_vertex_list* pv = p.contour;
for (i = 0; i < p.num_contours; i++)
{
const contour_header_type& h = m_contour_accumulator[i];
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 path_id)
{
free_result();
m_src_a->rewind(path_id);
m_src_b->rewind(path_id);
add(*m_src_a, m_poly_a);
add(*m_src_b, m_poly_b);
switch (m_operation)
{
case gpc_or:
gpc_polygon_clip(GPC_UNION, &m_poly_a, &m_poly_b, &m_result);
break;
case gpc_and:
gpc_polygon_clip(GPC_INT, &m_poly_a, &m_poly_b, &m_result);
break;
case gpc_xor:
gpc_polygon_clip(GPC_XOR, &m_poly_a, &m_poly_b, &m_result);
break;
case gpc_a_minus_b:
gpc_polygon_clip(GPC_DIFF, &m_poly_a, &m_poly_b, &m_result);
break;
case gpc_b_minus_a:
gpc_polygon_clip(GPC_DIFF, &m_poly_b, &m_poly_a, &m_result);
break;
}
start_extracting();
}
//------------------------------------------------------------------------
template<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;
}
} // namespace agg
#endif #endif

View file

@ -22,82 +22,70 @@
#include "agg_basics.h" #include "agg_basics.h"
#include "agg_trans_affine.h" #include "agg_trans_affine.h"
namespace agg namespace agg {
//-------------------------------------------------------------conv_marker
template<class MarkerLocator, class MarkerShapes>
class conv_marker
{ {
//-------------------------------------------------------------conv_marker public:
template<class MarkerLocator, class MarkerShapes> conv_marker(MarkerLocator& ml, MarkerShapes& ms);
class conv_marker
trans_affine& transform() { return m_transform; }
const trans_affine& transform() const { return m_transform; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
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))
{ {
public: switch (m_status)
conv_marker(MarkerLocator& ml, MarkerShapes& ms);
trans_affine& transform() { return m_transform; }
const trans_affine& transform() const { return m_transform; }
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
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: case initial:
if(m_num_markers == 0) if (m_num_markers == 0)
{ {
cmd = path_cmd_stop; cmd = path_cmd_stop;
break; break;
} }
m_marker_locator->rewind(m_marker); m_marker_locator->rewind(m_marker);
++m_marker; ++m_marker;
@ -105,12 +93,12 @@ namespace agg
m_status = markers; m_status = markers;
case markers: case markers:
if(is_stop(m_marker_locator->vertex(&x1, &y1))) if (is_stop(m_marker_locator->vertex(&x1, &y1)))
{ {
m_status = initial; m_status = initial;
break; break;
} }
if(is_stop(m_marker_locator->vertex(&x2, &y2))) if (is_stop(m_marker_locator->vertex(&x2, &y2)))
{ {
m_status = initial; m_status = initial;
break; break;
@ -124,7 +112,7 @@ namespace agg
case polygon: case polygon:
cmd = m_marker_shapes->vertex(x, y); cmd = m_marker_shapes->vertex(x, y);
if(is_stop(cmd)) if (is_stop(cmd))
{ {
cmd = path_cmd_move_to; cmd = path_cmd_move_to;
m_status = markers; m_status = markers;
@ -136,13 +124,11 @@ namespace agg
case stop: case stop:
cmd = path_cmd_stop; cmd = path_cmd_stop;
break; break;
}
} }
return cmd;
} }
return cmd;
} }
} // namespace agg
#endif #endif

View file

@ -20,32 +20,27 @@
#include "agg_conv_adaptor_vcgen.h" #include "agg_conv_adaptor_vcgen.h"
#include "agg_vcgen_vertex_sequence.h" #include "agg_vcgen_vertex_sequence.h"
namespace agg 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 conv_marker_adaptor(VertexSource& vs)
template<class VertexSource, class Markers=null_markers> : conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>(vs)
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) : void shorten(double s) { base_type::generator().shorten(s); }
conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>(vs) double shorten() const { return base_type::generator().shorten(); }
{
}
void shorten(double s) { base_type::generator().shorten(s); } private:
double shorten() const { return base_type::generator().shorten(); } conv_marker_adaptor(const conv_marker_adaptor<VertexSource, Markers>&);
const conv_marker_adaptor<VertexSource, Markers>& operator=(const conv_marker_adaptor<VertexSource, Markers>&);
};
private: } // namespace agg
conv_marker_adaptor(const conv_marker_adaptor<VertexSource, Markers>&);
const conv_marker_adaptor<VertexSource, Markers>&
operator = (const conv_marker_adaptor<VertexSource, Markers>&);
};
}
#endif #endif

View file

@ -22,59 +22,53 @@
#include "agg_array.h" #include "agg_array.h"
#include "clipper.hpp" #include "clipper.hpp"
namespace agg namespace agg {
{
template<class VSA> class conv_offset template<class VSA>
class conv_offset
{ {
enum status { status_move_to, status_line_to, status_stop }; enum status { status_move_to, status_line_to, status_stop };
typedef VSA source_a_type; typedef VSA source_a_type;
typedef conv_offset<source_a_type> self_type; typedef conv_offset<source_a_type> self_type;
private: private:
source_a_type* m_src_a; source_a_type* m_src_a;
double m_offset; double m_offset;
status m_status; status m_status;
int m_vertex; int m_vertex;
int m_contour; int m_contour;
int m_scaling_factor; int m_scaling_factor;
pod_bvector<ClipperLib::IntPoint, 8> m_vertex_accumulator; pod_bvector<ClipperLib::IntPoint, 8> m_vertex_accumulator;
ClipperLib::Paths m_poly_a; ClipperLib::Paths m_poly_a;
ClipperLib::Paths m_result; ClipperLib::Paths m_result;
ClipperLib::ClipperOffset m_clipper_offset; ClipperLib::ClipperOffset m_clipper_offset;
int Round(double val) int Round(double val)
{ {
if ((val < 0)) return (int)(val - 0.5); else return (int)(val + 0.5); if ((val < 0))
return (int)(val - 0.5);
else
return (int)(val + 0.5);
} }
public: public:
conv_offset(source_a_type &a, double offset = 0.0, conv_offset(source_a_type& a, double offset = 0.0, int scaling_factor = 0)
int scaling_factor = 0) : m_src_a(&a)
: m_src_a(&a), , m_offset(offset)
m_offset(offset), , m_status(status_move_to)
m_status(status_move_to), , m_vertex(-1)
m_vertex(-1), , m_contour(-1)
m_contour(-1)
{ {
m_scaling_factor = std::max(std::min(scaling_factor, 6),0); m_scaling_factor = std::max(std::min(scaling_factor, 6), 0);
m_scaling_factor = Round(std::pow((double)10, m_scaling_factor)); m_scaling_factor = Round(std::pow((double)10, m_scaling_factor));
} }
~conv_offset() ~conv_offset() {}
{
}
void set_offset(double offset) { m_offset = offset;} void set_offset(double offset) { m_offset = offset; }
unsigned type() const unsigned type() const { return static_cast<unsigned>(m_src_a->type()); }
{
return static_cast<unsigned>(m_src_a->type());
}
double get_offset() const double get_offset() const { return m_offset; }
{
return m_offset;
}
void rewind(unsigned path_id); void rewind(unsigned path_id);
unsigned vertex(double* x, double* y); unsigned vertex(double* x, double* y);
@ -82,13 +76,17 @@ public:
bool next_contour(); bool next_contour();
bool next_vertex(double* x, double* y); bool next_vertex(double* x, double* y);
void start_extracting(); void start_extracting();
void add_vertex_(double &x, double &y); void add_vertex_(double& x, double& y);
void end_contour(ClipperLib::Paths &p); void end_contour(ClipperLib::Paths& p);
template<class VS> void add(VS &src, ClipperLib::Paths &p) template<class VS>
void add(VS& src, ClipperLib::Paths& p)
{ {
unsigned cmd; unsigned cmd;
double x; double y; double start_x; double start_y; double x;
double y;
double start_x;
double start_y;
bool starting_first_line; bool starting_first_line;
start_x = 0.0; start_x = 0.0;
@ -96,26 +94,27 @@ public:
starting_first_line = true; starting_first_line = true;
p.resize(0); p.resize(0);
cmd = src->vertex( &x , &y ); cmd = src->vertex(&x, &y);
while(!is_stop(cmd)) while (!is_stop(cmd))
{ {
if(is_vertex(cmd)) if (is_vertex(cmd))
{ {
if(is_move_to(cmd)) if (is_move_to(cmd))
{ {
if(!starting_first_line ) end_contour(p); if (!starting_first_line)
end_contour(p);
start_x = x; start_x = x;
start_y = y; start_y = y;
} }
add_vertex_( x, y ); add_vertex_(x, y);
starting_first_line = false; starting_first_line = false;
} }
else if(is_end_poly(cmd)) else if (is_end_poly(cmd))
{ {
if(!starting_first_line && is_closed(cmd)) if (!starting_first_line && is_closed(cmd))
add_vertex_( start_x, start_y ); add_vertex_(start_x, start_y);
} }
cmd = src->vertex( &x, &y ); cmd = src->vertex(&x, &y);
} }
end_contour(p); end_contour(p);
} }
@ -135,42 +134,43 @@ void conv_offset<VSA>::start_extracting()
template<class VSA> template<class VSA>
void conv_offset<VSA>::rewind(unsigned path_id) void conv_offset<VSA>::rewind(unsigned path_id)
{ {
m_src_a->rewind( path_id ); m_src_a->rewind(path_id);
//m_src_b->rewind( path_id ); // m_src_b->rewind( path_id );
add( m_src_a , m_poly_a ); add(m_src_a, m_poly_a);
//add( m_src_b , m_poly_b ); // add( m_src_b , m_poly_b );
m_result.resize(0); m_result.resize(0);
m_clipper_offset.Clear(); m_clipper_offset.Clear();
m_clipper_offset.AddPaths(m_poly_a,ClipperLib::jtMiter, ClipperLib::etOpenButt);//ClosedLine);//Polygon); m_clipper_offset.AddPaths(m_poly_a, ClipperLib::jtMiter, ClipperLib::etOpenButt); // ClosedLine);//Polygon);
m_clipper_offset.Execute(m_result, m_offset * m_scaling_factor); m_clipper_offset.Execute(m_result, m_offset * m_scaling_factor);
start_extracting(); start_extracting();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class VSA> template<class VSA>
void conv_offset<VSA>::end_contour( ClipperLib::Paths &p) void conv_offset<VSA>::end_contour(ClipperLib::Paths& p)
{ {
unsigned i, len; unsigned i, len;
if( m_vertex_accumulator.size() < 3 ) return; if (m_vertex_accumulator.size() < 3)
return;
len = p.size(); len = p.size();
p.resize(len+1); p.resize(len + 1);
p[len].resize(m_vertex_accumulator.size()); p[len].resize(m_vertex_accumulator.size());
for( i = 0 ; i < m_vertex_accumulator.size() ; i++ ) for (i = 0; i < m_vertex_accumulator.size(); i++)
p[len][i] = m_vertex_accumulator[i]; p[len][i] = m_vertex_accumulator[i];
m_vertex_accumulator.remove_all(); m_vertex_accumulator.remove_all();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class VSA> template<class VSA>
void conv_offset<VSA>::add_vertex_(double &x, double &y) void conv_offset<VSA>::add_vertex_(double& x, double& y)
{ {
ClipperLib::IntPoint v; ClipperLib::IntPoint v;
v.X = Round(x * m_scaling_factor); v.X = Round(x * m_scaling_factor);
v.Y = Round(y * m_scaling_factor); v.Y = Round(y * m_scaling_factor);
m_vertex_accumulator.add( v ); m_vertex_accumulator.add(v);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -178,33 +178,35 @@ template<class VSA>
bool conv_offset<VSA>::next_contour() bool conv_offset<VSA>::next_contour()
{ {
m_contour++; m_contour++;
if(m_contour >= (int)m_result.size()) return false; if (m_contour >= (int)m_result.size())
m_vertex =-1; return false;
m_vertex = -1;
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class VSA> template<class VSA>
bool conv_offset<VSA>::next_vertex(double *x, double *y) bool conv_offset<VSA>::next_vertex(double* x, double* y)
{ {
m_vertex++; m_vertex++;
if(m_vertex >= (int)m_result[m_contour].size()) return false; if (m_vertex >= (int)m_result[m_contour].size())
*x = (double)m_result[ m_contour ][ m_vertex ].X / m_scaling_factor; return false;
*y = (double)m_result[ m_contour ][ m_vertex ].Y / m_scaling_factor; *x = (double)m_result[m_contour][m_vertex].X / m_scaling_factor;
*y = (double)m_result[m_contour][m_vertex].Y / m_scaling_factor;
return true; return true;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class VSA> template<class VSA>
unsigned conv_offset<VSA>::vertex(double *x, double *y) unsigned conv_offset<VSA>::vertex(double* x, double* y)
{ {
if( m_status == status_move_to ) if (m_status == status_move_to)
{ {
if( next_contour() ) if (next_contour())
{ {
if( next_vertex( x, y ) ) if (next_vertex(x, y))
{ {
m_status =status_line_to; m_status = status_line_to;
return path_cmd_move_to; return path_cmd_move_to;
} }
else else
@ -218,7 +220,7 @@ unsigned conv_offset<VSA>::vertex(double *x, double *y)
} }
else else
{ {
if( next_vertex( x, y ) ) if (next_vertex(x, y))
{ {
return path_cmd_line_to; return path_cmd_line_to;
} }
@ -231,6 +233,5 @@ unsigned conv_offset<VSA>::vertex(double *x, double *y)
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
} // namespace agg
} //namespace agg #endif // AGG_CONV_OFFSET_INCLUDED
#endif //AGG_CONV_OFFSET_INCLUDED

View file

@ -20,29 +20,26 @@
#include "agg_conv_adaptor_vpgen.h" #include "agg_conv_adaptor_vpgen.h"
#include "agg_vpgen_segmentator.h" #include "agg_vpgen_segmentator.h"
namespace agg 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 conv_segmentator(VertexSource& vs)
template<class VertexSource> : conv_adaptor_vpgen<VertexSource, vpgen_segmentator>(vs)
struct conv_segmentator : public conv_adaptor_vpgen<VertexSource, vpgen_segmentator> {}
{
typedef conv_adaptor_vpgen<VertexSource, vpgen_segmentator> base_type;
conv_segmentator(VertexSource& vs) : void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); }
conv_adaptor_vpgen<VertexSource, vpgen_segmentator>(vs) {} double approximation_scale() const { return base_type::vpgen().approximation_scale(); }
void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); } private:
double approximation_scale() const { return base_type::vpgen().approximation_scale(); } conv_segmentator(const conv_segmentator<VertexSource>&);
const conv_segmentator<VertexSource>& operator=(const conv_segmentator<VertexSource>&);
};
private: } // namespace agg
conv_segmentator(const conv_segmentator<VertexSource>&);
const conv_segmentator<VertexSource>&
operator = (const conv_segmentator<VertexSource>&);
};
}
#endif #endif

View file

@ -20,31 +20,27 @@
#include "agg_conv_adaptor_vcgen.h" #include "agg_conv_adaptor_vcgen.h"
#include "agg_vcgen_vertex_sequence.h" #include "agg_vcgen_vertex_sequence.h"
namespace agg 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 conv_shorten_path(VertexSource& vs)
template<class VertexSource> class conv_shorten_path : : conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>(vs)
public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> {}
{
public:
typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> base_type;
conv_shorten_path(VertexSource& vs) : void shorten(double s) { base_type::generator().shorten(s); }
conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>(vs) double shorten() const { return base_type::generator().shorten(); }
{
}
void shorten(double s) { base_type::generator().shorten(s); } private:
double shorten() const { return base_type::generator().shorten(); } conv_shorten_path(const conv_shorten_path<VertexSource>&);
const conv_shorten_path<VertexSource>& operator=(const conv_shorten_path<VertexSource>&);
};
private: } // namespace agg
conv_shorten_path(const conv_shorten_path<VertexSource>&);
const conv_shorten_path<VertexSource>&
operator = (const conv_shorten_path<VertexSource>&);
};
}
#endif #endif

View file

@ -24,70 +24,62 @@
#include "agg_conv_adaptor_vcgen.h" #include "agg_conv_adaptor_vcgen.h"
#include "agg_conv_curve.h" #include "agg_conv_curve.h"
namespace agg {
namespace agg //-------------------------------------------------------conv_smooth
template<class VertexSource, class VertexGenerator>
struct conv_smooth : public conv_adaptor_vcgen<VertexSource, VertexGenerator>
{ {
typedef conv_adaptor_vcgen<VertexSource, VertexGenerator> base_type;
//-------------------------------------------------------conv_smooth conv_smooth(VertexSource& vs)
template<class VertexSource, class VertexGenerator> : conv_adaptor_vcgen<VertexSource, VertexGenerator>(vs)
struct conv_smooth : {}
public conv_adaptor_vcgen<VertexSource, VertexGenerator>
conv_smooth(conv_smooth<VertexSource, VertexGenerator>&&) = default;
conv_smooth(const conv_smooth<VertexSource, VertexGenerator>&) = delete;
const conv_smooth<VertexSource, VertexGenerator>&
operator=(const conv_smooth<VertexSource, VertexGenerator>&) = delete;
void smooth_value(double v) { base_type::generator().smooth_value(v); }
double smooth_value() const { return base_type::generator().smooth_value(); }
unsigned type() const { return base_type::type(); }
};
template<class VertexSource>
using conv_smooth_poly1 = conv_smooth<VertexSource, vcgen_smooth_poly1>;
//-------------------------------------------------conv_smooth_curve
template<class VertexSource, class VertexGenerator>
struct conv_smooth_curve : public conv_curve<conv_smooth<VertexSource, VertexGenerator>>
{
conv_smooth_curve(VertexSource& vs)
: conv_curve<conv_smooth<VertexSource, VertexGenerator>>(m_smooth)
, m_smooth(vs)
{}
conv_smooth_curve(conv_smooth_curve<VertexSource, VertexGenerator>&& rhs)
: conv_curve<conv_smooth<VertexSource, VertexGenerator>>(std::move(rhs))
, m_smooth(std::move(rhs.m_smooth))
{ {
typedef conv_adaptor_vcgen<VertexSource, VertexGenerator> base_type; this->attach(m_smooth);
}
conv_smooth(VertexSource& vs) : conv_smooth_curve(const conv_smooth_curve<VertexSource, VertexGenerator>&) = delete;
conv_adaptor_vcgen<VertexSource, VertexGenerator>(vs) const conv_smooth_curve<VertexSource, VertexGenerator>&
{ operator=(const conv_smooth_curve<VertexSource, VertexGenerator>&) = delete;
}
conv_smooth(conv_smooth<VertexSource, VertexGenerator> &&) = default; void smooth_value(double v) { m_smooth.generator().smooth_value(v); }
double smooth_value() const { return m_smooth.generator().smooth_value(); }
unsigned type() const { return m_smooth.type(); }
conv_smooth(const conv_smooth<VertexSource, VertexGenerator>&) = delete; private:
const conv_smooth<VertexSource, VertexGenerator>& conv_smooth<VertexSource, VertexGenerator> m_smooth;
operator = (const conv_smooth<VertexSource, VertexGenerator>&) = delete; };
void smooth_value(double v) { base_type::generator().smooth_value(v); }
double smooth_value() const { return base_type::generator().smooth_value(); }
unsigned type() const { return base_type::type(); }
};
template<class VertexSource>
using conv_smooth_poly1 = conv_smooth<VertexSource, vcgen_smooth_poly1>;
//-------------------------------------------------conv_smooth_curve
template<class VertexSource, class VertexGenerator>
struct conv_smooth_curve :
public conv_curve<conv_smooth<VertexSource, VertexGenerator>>
{
conv_smooth_curve(VertexSource& vs) :
conv_curve<conv_smooth<VertexSource, VertexGenerator>>(m_smooth),
m_smooth(vs)
{
}
conv_smooth_curve(conv_smooth_curve<VertexSource, VertexGenerator> && rhs) :
conv_curve<conv_smooth<VertexSource, VertexGenerator>>(std::move(rhs)),
m_smooth(std::move(rhs.m_smooth))
{
this->attach(m_smooth);
}
conv_smooth_curve(const conv_smooth_curve<VertexSource, VertexGenerator>&) = delete;
const conv_smooth_curve<VertexSource, VertexGenerator>&
operator = (const conv_smooth_curve<VertexSource, VertexGenerator>&) = delete;
void smooth_value(double v) { m_smooth.generator().smooth_value(v); }
double smooth_value() const { return m_smooth.generator().smooth_value(); }
unsigned type() const { return m_smooth.type(); }
private:
conv_smooth<VertexSource, VertexGenerator> m_smooth;
};
template<class VertexSource>
using conv_smooth_poly1_curve = conv_smooth_curve<VertexSource, vcgen_smooth_poly1>;
}
template<class VertexSource>
using conv_smooth_poly1_curve = conv_smooth_curve<VertexSource, vcgen_smooth_poly1>;
} // namespace agg
#endif #endif

View file

@ -23,51 +23,46 @@
#include "agg_vcgen_stroke.h" #include "agg_vcgen_stroke.h"
#include "agg_conv_adaptor_vcgen.h" #include "agg_conv_adaptor_vcgen.h"
namespace agg 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 conv_stroke(VertexSource& vs)
template<class VertexSource, class Markers=null_markers> : conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs)
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) : void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); }
conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs) void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
{ void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
}
void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); } line_cap_e line_cap() const { return base_type::generator().line_cap(); }
void line_join(line_join_e lj) { base_type::generator().line_join(lj); } line_join_e line_join() const { return base_type::generator().line_join(); }
void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); } inner_join_e inner_join() const { return base_type::generator().inner_join(); }
line_cap_e line_cap() const { return base_type::generator().line_cap(); } void width(double w) { base_type::generator().width(w); }
line_join_e line_join() const { return base_type::generator().line_join(); } void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
inner_join_e inner_join() const { return base_type::generator().inner_join(); } void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
void width(double w) { base_type::generator().width(w); } double width() const { return base_type::generator().width(); }
void miter_limit(double ml) { base_type::generator().miter_limit(ml); } double miter_limit() const { return base_type::generator().miter_limit(); }
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); } double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); } double approximation_scale() const { return base_type::generator().approximation_scale(); }
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
double width() const { return base_type::generator().width(); } void shorten(double s) { base_type::generator().shorten(s); }
double miter_limit() const { return base_type::generator().miter_limit(); } double shorten() const { return base_type::generator().shorten(); }
double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
double approximation_scale() const { return base_type::generator().approximation_scale(); }
void shorten(double s) { base_type::generator().shorten(s); } private:
double shorten() const { return base_type::generator().shorten(); } conv_stroke(const conv_stroke<VertexSource, Markers>&);
const conv_stroke<VertexSource, Markers>& operator=(const conv_stroke<VertexSource, Markers>&);
};
private: } // namespace agg
conv_stroke(const conv_stroke<VertexSource, Markers>&);
const conv_stroke<VertexSource, Markers>&
operator = (const conv_stroke<VertexSource, Markers>&);
};
}
#endif #endif

View file

@ -22,50 +22,44 @@
#include "agg_basics.h" #include "agg_basics.h"
#include "agg_trans_affine.h" #include "agg_trans_affine.h"
namespace agg namespace agg {
//----------------------------------------------------------conv_transform
template<class VertexSource, class Transformer = trans_affine>
class conv_transform
{ {
public:
conv_transform(VertexSource& source, Transformer& tr)
: m_source(&source)
, m_trans(&tr)
{}
//----------------------------------------------------------conv_transform void attach(VertexSource& source) { m_source = &source; }
template<class VertexSource, class Transformer=trans_affine> class conv_transform
void rewind(unsigned path_id) { m_source->rewind(path_id); }
unsigned vertex(double* x, double* y)
{ {
public: unsigned cmd = m_source->vertex(x, y);
conv_transform(VertexSource& source, Transformer& tr) : if (is_vertex(cmd))
m_source(&source), m_trans(&tr) {}
void attach(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id)
{ {
m_source->rewind(path_id); m_trans->transform(x, y);
} }
return cmd;
}
unsigned vertex(double* x, double* y) void transformer(Transformer& tr) { m_trans = &tr; }
{
unsigned cmd = m_source->vertex(x, y);
if(is_vertex(cmd))
{
m_trans->transform(x, y);
}
return cmd;
}
void transformer(Transformer& tr) unsigned type() const { return m_source->type(); }
{
m_trans = &tr;
}
unsigned type() const { return m_source->type(); } private:
conv_transform(const conv_transform<VertexSource>&);
const conv_transform<VertexSource>& operator=(const conv_transform<VertexSource>&);
private: VertexSource* m_source;
conv_transform(const conv_transform<VertexSource>&); const Transformer* m_trans;
const conv_transform<VertexSource>& };
operator = (const conv_transform<VertexSource>&);
VertexSource* m_source; } // namespace agg
const Transformer* m_trans;
};
}
#endif #endif

View file

@ -18,35 +18,34 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//====================================================conv_unclose_polygon
template<class VertexSource>
class conv_unclose_polygon
{ {
//====================================================conv_unclose_polygon public:
template<class VertexSource> class conv_unclose_polygon explicit conv_unclose_polygon(VertexSource& vs)
: m_source(&vs)
{}
void attach(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id) { m_source->rewind(path_id); }
unsigned vertex(double* x, double* y)
{ {
public: unsigned cmd = m_source->vertex(x, y);
explicit conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {} if (is_end_poly(cmd))
void attach(VertexSource& source) { m_source = &source; } cmd &= ~path_flags_close;
return cmd;
}
void rewind(unsigned path_id) private:
{ conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&);
m_source->rewind(path_id); const conv_unclose_polygon<VertexSource>& operator=(const conv_unclose_polygon<VertexSource>&);
}
unsigned vertex(double* x, double* y) VertexSource* m_source;
{ };
unsigned cmd = m_source->vertex(x, y);
if(is_end_poly(cmd)) cmd &= ~path_flags_close;
return cmd;
}
private: } // namespace agg
conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&);
const conv_unclose_polygon<VertexSource>&
operator = (const conv_unclose_polygon<VertexSource>&);
VertexSource* m_source;
};
}
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -23,268 +23,229 @@
#include <cstdlib> #include <cstdlib>
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//===================================================dda_line_interpolator
template<int FractionShift, int YShift = 0>
class dda_line_interpolator
{ {
static constexpr int factor = 2 << (FractionShift - 1);
//===================================================dda_line_interpolator public:
template<int FractionShift, int YShift = 0> class dda_line_interpolator //--------------------------------------------------------------------
dda_line_interpolator() {}
//--------------------------------------------------------------------
dda_line_interpolator(int y1, int y2, unsigned count)
: m_y(y1)
, m_inc(((y2 - y1) * factor) / static_cast<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_e { 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)
{ {
static constexpr int factor = 2 << (FractionShift - 1); if (m_mod <= 0)
public:
//--------------------------------------------------------------------
dda_line_interpolator() {}
//--------------------------------------------------------------------
dda_line_interpolator(int y1, int y2, unsigned count) :
m_y(y1),
m_inc(((y2 - y1) * factor) / static_cast<int>(count)),
m_dy(0)
{ {
m_mod += count;
m_rem += count;
m_lft--;
} }
m_mod -= count;
}
//-------------------------------------------------------------------- //-------------------------------------------- Backward-adjusted line
void operator ++ () dda2_line_interpolator(int y1, int y2, int count, int)
{ : m_cnt(count <= 0 ? 1 : count)
m_dy += m_inc; , m_lft((y2 - y1) / m_cnt)
} , m_rem((y2 - y1) % m_cnt)
, m_mod(m_rem)
//-------------------------------------------------------------------- , m_y(y1)
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: if (m_mod <= 0)
typedef int save_data_type;
enum save_size_e { 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_mod += count; m_lft--;
m_rem += count;
m_lft--;
}
m_mod -= count;
} }
}
//-------------------------------------------- Backward-adjusted line //-------------------------------------------- Backward-adjusted line
dda2_line_interpolator(int y1, int y2, int count, int) : dda2_line_interpolator(int y, int count)
m_cnt(count <= 0 ? 1 : count), : m_cnt(count <= 0 ? 1 : count)
m_lft((y2 - y1) / m_cnt), , m_lft(y / m_cnt)
m_rem((y2 - y1) % m_cnt), , m_rem(y % m_cnt)
m_mod(m_rem), , m_mod(m_rem)
m_y(y1) , m_y(0)
{
if (m_mod <= 0)
{ {
if(m_mod <= 0) m_mod += count;
{ m_rem += count;
m_mod += count; m_lft--;
m_rem += count;
m_lft--;
}
} }
}
//-------------------------------------------- Backward-adjusted line //--------------------------------------------------------------------
dda2_line_interpolator(int y, int count) : void save(save_data_type* data) const
m_cnt(count <= 0 ? 1 : count), {
m_lft(y / m_cnt), data[0] = m_mod;
m_rem(y % m_cnt), data[1] = m_y;
m_mod(m_rem), }
m_y(0)
{
if(m_mod <= 0)
{
m_mod += count;
m_rem += count;
m_lft--;
}
}
//--------------------------------------------------------------------
void load(const save_data_type* data)
{
m_mod = data[0];
m_y = data[1];
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void save(save_data_type* data) const void operator++()
{ {
data[0] = m_mod; m_mod += m_rem;
data[1] = m_y; m_y += m_lft;
} if (m_mod > 0)
//--------------------------------------------------------------------
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; m_mod -= m_cnt;
m_y++;
} }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void adjust_backward() void operator--()
{
if (m_mod <= m_rem)
{ {
m_mod += m_cnt; m_mod += m_cnt;
m_y--;
} }
m_mod -= m_rem;
m_y -= m_lft;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
int mod() const { return m_mod; } void adjust_forward() { m_mod -= m_cnt; }
int rem() const { return m_rem; }
int lft() const { return m_lft; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
int y() const { return m_y; } void adjust_backward() { m_mod += m_cnt; }
private: //--------------------------------------------------------------------
int m_cnt; int mod() const { return m_mod; }
int m_lft; int rem() const { return m_rem; }
int m_rem; int lft() const { return m_lft; }
int m_mod;
int m_y; //--------------------------------------------------------------------
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_scale_e {
subpixel_shift = 8,
subpixel_scale = 1 << subpixel_shift,
subpixel_mask = subpixel_scale - 1
}; };
//--------------------------------------------------------------------
static int line_lr(int v) { return v >> subpixel_shift; }
//--------------------------------------------------------------------
line_bresenham_interpolator(int x1, int y1, int x2, int y2)
: m_x1_lr(line_lr(x1))
, m_y1_lr(line_lr(y1))
, m_x2_lr(line_lr(x2))
, m_y2_lr(line_lr(y2))
, m_ver(std::abs(m_x2_lr - m_x1_lr) < std::abs(m_y2_lr - m_y1_lr))
, m_len(m_ver ? std::abs(m_y2_lr - m_y1_lr) : std::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()
//---------------------------------------------line_bresenham_interpolator
class line_bresenham_interpolator
{ {
public: ++m_interpolator;
enum subpixel_scale_e m_x1_lr += m_inc;
{ }
subpixel_shift = 8,
subpixel_scale = 1 << subpixel_shift,
subpixel_mask = subpixel_scale - 1
};
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static int line_lr(int v) { return v >> subpixel_shift; } void vstep()
{
++m_interpolator;
m_y1_lr += m_inc;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
line_bresenham_interpolator(int x1, int y1, int x2, int y2) : int x1() const { return m_x1_lr; }
m_x1_lr(line_lr(x1)), int y1() const { return m_y1_lr; }
m_y1_lr(line_lr(y1)), int x2() const { return line_lr(m_interpolator.y()); }
m_x2_lr(line_lr(x2)), int y2() const { return line_lr(m_interpolator.y()); }
m_y2_lr(line_lr(y2)), int x2_hr() const { return m_interpolator.y(); }
m_ver(std::abs(m_x2_lr - m_x1_lr) < std::abs(m_y2_lr - m_y1_lr)), int y2_hr() const { return m_interpolator.y(); }
m_len(m_ver ? std::abs(m_y2_lr - m_y1_lr) :
std::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;
};
}
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;
};
} // namespace agg
#endif #endif

View file

@ -23,102 +23,111 @@
#include "agg_basics.h" #include "agg_basics.h"
#include <cmath> #include <cmath>
namespace agg namespace agg {
//----------------------------------------------------------------ellipse
class ellipse
{ {
public:
ellipse()
: m_x(0.0)
, m_y(0.0)
, m_rx(1.0)
, m_ry(1.0)
, m_scale(1.0)
, m_num(4)
, m_step(0)
, m_cw(false)
{}
//----------------------------------------------------------------ellipse ellipse(double x, double y, double rx, double ry, unsigned num_steps = 0, bool cw = false)
class ellipse : m_x(x)
, m_y(y)
, m_rx(rx)
, m_ry(ry)
, m_scale(1.0)
, m_num(num_steps)
, m_step(0)
, m_cw(cw)
{ {
public: if (m_num == 0)
ellipse() : calc_num_steps();
m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_scale(1.0),
m_num(4), m_step(0), m_cw(false) {}
ellipse(double x, double y, double rx, double ry,
unsigned num_steps=0, bool cw=false) :
m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0),
m_num(num_steps), m_step(0), m_cw(cw)
{
if(m_num == 0) calc_num_steps();
}
void init(double x, double y, double rx, double ry,
unsigned num_steps=0, bool cw=false);
void approximation_scale(double scale);
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
unsigned num_steps() { return m_num; }
private:
void calc_num_steps();
double m_x;
double m_y;
double m_rx;
double m_ry;
double m_scale;
unsigned m_num;
unsigned m_step;
bool m_cw;
};
//------------------------------------------------------------------------
inline void ellipse::init(double x, double y, double rx, double ry,
unsigned num_steps, bool cw)
{
m_x = x;
m_y = y;
m_rx = rx;
m_ry = ry;
m_num = num_steps;
m_step = 0;
m_cw = cw;
if(m_num == 0) calc_num_steps();
} }
//------------------------------------------------------------------------ void init(double x, double y, double rx, double ry, unsigned num_steps = 0, bool cw = false);
inline void ellipse::approximation_scale(double scale)
{ void approximation_scale(double scale);
m_scale = scale; void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
unsigned num_steps() { return m_num; }
private:
void calc_num_steps();
double m_x;
double m_y;
double m_rx;
double m_ry;
double m_scale;
unsigned m_num;
unsigned m_step;
bool m_cw;
};
//------------------------------------------------------------------------
inline void ellipse::init(double x, double y, double rx, double ry, unsigned num_steps, bool cw)
{
m_x = x;
m_y = y;
m_rx = rx;
m_ry = ry;
m_num = num_steps;
m_step = 0;
m_cw = cw;
if (m_num == 0)
calc_num_steps(); calc_num_steps();
}
//------------------------------------------------------------------------
inline void ellipse::calc_num_steps()
{
double ra = (std::fabs(m_rx) + std::fabs(m_ry)) / 2;
double da = std::acos(ra / (ra + 0.125 / m_scale)) * 2;
m_num = uround(2*pi / da);
}
//------------------------------------------------------------------------
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;
if(m_cw) angle = 2.0 * pi - angle;
*x = m_x + std::cos(angle) * m_rx;
*y = m_y + std::sin(angle) * m_ry;
m_step++;
return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to);
}
} }
//------------------------------------------------------------------------
inline void ellipse::approximation_scale(double scale)
{
m_scale = scale;
calc_num_steps();
}
//------------------------------------------------------------------------
inline void ellipse::calc_num_steps()
{
double ra = (std::fabs(m_rx) + std::fabs(m_ry)) / 2;
double da = std::acos(ra / (ra + 0.125 / m_scale)) * 2;
m_num = uround(2 * pi / da);
}
//------------------------------------------------------------------------
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;
if (m_cw)
angle = 2.0 * pi - angle;
*x = m_x + std::cos(angle) * m_rx;
*y = m_y + std::sin(angle) * m_ry;
m_step++;
return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to);
}
} // namespace agg
#endif #endif

View file

@ -20,94 +20,92 @@
#ifndef AGG_ELLIPSE_BRESENHAM_INCLUDED #ifndef AGG_ELLIPSE_BRESENHAM_INCLUDED
#define AGG_ELLIPSE_BRESENHAM_INCLUDED #define AGG_ELLIPSE_BRESENHAM_INCLUDED
#include "agg_basics.h" #include "agg_basics.h"
namespace agg {
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)
{}
//------------------------------------------ellipse_bresenham_interpolator int dx() const { return m_dx; }
class ellipse_bresenham_interpolator int dy() const { return m_dy; }
void operator++()
{ {
public: int mx, my, mxy, min_m;
ellipse_bresenham_interpolator(int rx, int ry) : int fx, fy, fxy;
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; } mx = fx = m_cur_f + m_inc_x + m_ry2;
int dy() const { return m_dy; } if (mx < 0)
mx = -mx;
void operator++ () 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)
{ {
int mx, my, mxy, min_m; min_m = my;
int fx, fy, fxy; flag = false;
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: m_dx = m_dy = 0;
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;
}; 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;
};
} // namespace agg
#endif #endif

View file

@ -18,42 +18,41 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
{ extern const int8u gse4x6[];
extern const int8u gse4x6[]; extern const int8u gse4x8[];
extern const int8u gse4x8[]; extern const int8u gse5x7[];
extern const int8u gse5x7[]; extern const int8u gse5x9[];
extern const int8u gse5x9[]; extern const int8u gse6x12[];
extern const int8u gse6x12[]; extern const int8u gse6x9[];
extern const int8u gse6x9[]; extern const int8u gse7x11[];
extern const int8u gse7x11[]; extern const int8u gse7x11_bold[];
extern const int8u gse7x11_bold[]; extern const int8u gse7x15[];
extern const int8u gse7x15[]; extern const int8u gse7x15_bold[];
extern const int8u gse7x15_bold[]; extern const int8u gse8x16[];
extern const int8u gse8x16[]; extern const int8u gse8x16_bold[];
extern const int8u gse8x16_bold[]; extern const int8u mcs11_prop[];
extern const int8u mcs11_prop[]; extern const int8u mcs11_prop_condensed[];
extern const int8u mcs11_prop_condensed[]; extern const int8u mcs12_prop[];
extern const int8u mcs12_prop[]; extern const int8u mcs13_prop[];
extern const int8u mcs13_prop[]; extern const int8u mcs5x10_mono[];
extern const int8u mcs5x10_mono[]; extern const int8u mcs5x11_mono[];
extern const int8u mcs5x11_mono[]; extern const int8u mcs6x10_mono[];
extern const int8u mcs6x10_mono[]; extern const int8u mcs6x11_mono[];
extern const int8u mcs6x11_mono[]; extern const int8u mcs7x12_mono_high[];
extern const int8u mcs7x12_mono_high[]; extern const int8u mcs7x12_mono_low[];
extern const int8u mcs7x12_mono_low[]; extern const int8u verdana12[];
extern const int8u verdana12[]; extern const int8u verdana12_bold[];
extern const int8u verdana12_bold[]; extern const int8u verdana13[];
extern const int8u verdana13[]; extern const int8u verdana13_bold[];
extern const int8u verdana13_bold[]; extern const int8u verdana14[];
extern const int8u verdana14[]; extern const int8u verdana14_bold[];
extern const int8u verdana14_bold[]; extern const int8u verdana16[];
extern const int8u verdana16[]; extern const int8u verdana16_bold[];
extern const int8u verdana16_bold[]; extern const int8u verdana17[];
extern const int8u verdana17[]; extern const int8u verdana17_bold[];
extern const int8u verdana17_bold[]; extern const int8u verdana18[];
extern const int8u verdana18[]; extern const int8u verdana18_bold[];
extern const int8u verdana18_bold[]; } // namespace agg
}
#endif #endif

View file

@ -19,307 +19,265 @@
#include <cstring> #include <cstring>
#include "agg_array.h" #include "agg_array.h"
namespace agg 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_i bounds;
double advance_x;
double advance_y;
};
//---------------------------------------------------------glyph_data_type //--------------------------------------------------------------font_cache
enum glyph_data_type class font_cache
{
public:
enum block_size_e { block_size = 16384 - 16 };
//--------------------------------------------------------------------
font_cache()
: m_allocator(block_size)
, m_font_signature(0)
{}
//--------------------------------------------------------------------
void signature(const char* font_signature)
{ {
glyph_data_invalid = 0, m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1);
glyph_data_mono = 1, strcpy(m_font_signature, font_signature);
glyph_data_gray8 = 2, memset(m_glyphs, 0, sizeof(m_glyphs));
glyph_data_outline = 3 }
};
//--------------------------------------------------------------------
bool font_is(const char* font_signature) const { return strcmp(font_signature, m_font_signature) == 0; }
//-------------------------------------------------------------glyph_cache //--------------------------------------------------------------------
struct glyph_cache const glyph_cache* find_glyph(unsigned glyph_code) const
{ {
unsigned glyph_index; unsigned msb = (glyph_code >> 8) & 0xFF;
int8u* data; if (m_glyphs[msb])
unsigned data_size; {
glyph_data_type data_type; return m_glyphs[msb][glyph_code & 0xFF];
rect_i bounds; }
double advance_x; return 0;
double advance_y; }
};
//--------------------------------------------------------------------
//--------------------------------------------------------------font_cache glyph_cache* cache_glyph(unsigned glyph_code,
class font_cache unsigned glyph_index,
unsigned data_size,
glyph_data_type data_type,
const rect_i& bounds,
double advance_x,
double advance_y)
{ {
public: unsigned msb = (glyph_code >> 8) & 0xFF;
enum block_size_e { block_size = 16384-16 }; if (m_glyphs[msb] == 0)
//--------------------------------------------------------------------
font_cache() :
m_allocator(block_size),
m_font_signature(0)
{}
//--------------------------------------------------------------------
void signature(const char* font_signature)
{ {
m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1); m_glyphs[msb] = (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256, sizeof(glyph_cache*));
strcpy(m_font_signature, font_signature); memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
memset(m_glyphs, 0, sizeof(m_glyphs));
} }
//-------------------------------------------------------------------- unsigned lsb = glyph_code & 0xFF;
bool font_is(const char* font_signature) const if (m_glyphs[msb][lsb])
{ return 0; // Already exists, do not overwrite
return strcmp(font_signature, m_font_signature) == 0;
}
//-------------------------------------------------------------------- glyph_cache* glyph = (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache), sizeof(double));
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->glyph_index = glyph_index;
glyph_cache* cache_glyph(unsigned glyph_code, glyph->data = m_allocator.allocate(data_size);
unsigned glyph_index, glyph->data_size = data_size;
unsigned data_size, glyph->data_type = data_type;
glyph_data_type data_type, glyph->bounds = bounds;
const rect_i& bounds, glyph->advance_x = advance_x;
double advance_x, glyph->advance_y = advance_y;
double advance_y) return m_glyphs[msb][lsb] = glyph;
{ }
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; private:
if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite block_allocator m_allocator;
glyph_cache** m_glyphs[256];
char* m_font_signature;
};
glyph_cache* glyph = //---------------------------------------------------------font_cache_pool
(glyph_cache*)m_allocator.allocate(sizeof(glyph_cache), class font_cache_pool
sizeof(double)); {
public:
glyph->glyph_index = glyph_index; //--------------------------------------------------------------------
glyph->data = m_allocator.allocate(data_size); ~font_cache_pool()
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:
block_allocator m_allocator;
glyph_cache** m_glyphs[256];
char* m_font_signature;
};
//---------------------------------------------------------font_cache_pool
class font_cache_pool
{ {
public: unsigned i;
//-------------------------------------------------------------------- for (i = 0; i < m_num_fonts; ++i)
~font_cache_pool()
{ {
unsigned i; obj_allocator<font_cache>::deallocate(m_fonts[i]);
for(i = 0; i < m_num_fonts; ++i)
{
obj_allocator<font_cache>::deallocate(m_fonts[i]);
}
pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts);
} }
pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
font_cache_pool(unsigned max_fonts=32) : font_cache_pool(unsigned max_fonts = 32)
m_fonts(pod_allocator<font_cache*>::allocate(max_fonts)), : m_fonts(pod_allocator<font_cache*>::allocate(max_fonts))
m_max_fonts(max_fonts), , m_max_fonts(max_fonts)
m_num_fonts(0), , m_num_fonts(0)
m_cur_font(0) , m_cur_font(0)
{} {}
//--------------------------------------------------------------------
//-------------------------------------------------------------------- void font(const char* font_signature, bool reset_cache = false)
void font(const char* font_signature, bool reset_cache = false)
{
int idx = find_font(font_signature);
if(idx >= 0)
{
if(reset_cache)
{
obj_allocator<font_cache>::deallocate(m_fonts[idx]);
m_fonts[idx] = obj_allocator<font_cache>::allocate();
m_fonts[idx]->signature(font_signature);
}
m_cur_font = m_fonts[idx];
}
else
{
if(m_num_fonts >= m_max_fonts)
{
obj_allocator<font_cache>::deallocate(m_fonts[0]);
memcpy(m_fonts,
m_fonts + 1,
(m_max_fonts - 1) * sizeof(font_cache*));
m_num_fonts = m_max_fonts - 1;
}
m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate();
m_fonts[m_num_fonts]->signature(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_i& 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, int idx = find_font(font_signature);
glyph_ren_native_gray8, if (idx >= 0)
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)
{}
//--------------------------------------------------------------------
void reset_last_glyph()
{ {
m_prev_glyph = m_last_glyph = 0; if (reset_cache)
{
obj_allocator<font_cache>::deallocate(m_fonts[idx]);
m_fonts[idx] = obj_allocator<font_cache>::allocate();
m_fonts[idx]->signature(font_signature);
}
m_cur_font = m_fonts[idx];
} }
else
//--------------------------------------------------------------------
const glyph_cache* glyph(unsigned glyph_code)
{ {
synchronize(); if (m_num_fonts >= m_max_fonts)
const glyph_cache* gl = m_fonts.find_glyph(glyph_code); {
if(gl) obj_allocator<font_cache>::deallocate(m_fonts[0]);
memcpy(m_fonts, m_fonts + 1, (m_max_fonts - 1) * sizeof(font_cache*));
m_num_fonts = m_max_fonts - 1;
}
m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate();
m_fonts[m_num_fonts]->signature(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_i& 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)
{}
//--------------------------------------------------------------------
void reset_last_glyph() { m_prev_glyph = 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_prev_glyph = m_last_glyph;
return m_last_glyph = gl; 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;
} }
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;
} }
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void init_embedded_adaptors(const glyph_cache* gl, void init_embedded_adaptors(const glyph_cache* gl, double x, double y, double scale = 1.0)
double x, double y, {
double scale=1.0) if (gl)
{ {
if(gl) switch (gl->data_type)
{ {
switch(gl->data_type) default:
{ return;
default: return;
case glyph_data_mono: case glyph_data_mono:
m_mono_adaptor.init(gl->data, gl->data_size, x, y); m_mono_adaptor.init(gl->data, gl->data_size, x, y);
break; break;
@ -331,79 +289,76 @@ namespace agg
case glyph_data_outline: case glyph_data_outline:
m_path_adaptor.init(gl->data, gl->data_size, x, y, scale); m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);
break; 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; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
path_adaptor_type& path_adaptor() { return m_path_adaptor; } const glyph_cache* perv_glyph() const { return m_prev_glyph; }
gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; } const glyph_cache* last_glyph() const { return m_last_glyph; }
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; } bool add_kerning(double* x, double* y)
const glyph_cache* last_glyph() const { return m_last_glyph; } {
if (m_prev_glyph && 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 m_engine.add_kerning(m_prev_glyph->glyph_index,
m_last_glyph->glyph_index,
x, y);
}
return false;
} }
return false;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void precache(unsigned from, unsigned to) void precache(unsigned from, unsigned to)
{ {
for(; from <= to; ++from) glyph(from); for (; from <= to; ++from)
} glyph(from);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void reset_cache() 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(), true); m_fonts.font(m_engine.font_signature());
m_change_stamp = m_engine.change_stamp(); m_change_stamp = m_engine.change_stamp();
m_prev_glyph = m_last_glyph = 0; m_prev_glyph = m_last_glyph = 0;
} }
}
private: font_cache_pool m_fonts;
//-------------------------------------------------------------------- font_engine_type& m_engine;
font_cache_manager(const self_type&); int m_change_stamp;
const self_type& operator = (const self_type&); 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;
};
//-------------------------------------------------------------------- } // namespace agg
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 #endif

View file

@ -19,116 +19,135 @@
#include <cmath> #include <cmath>
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//===============================================================gamma_none
struct gamma_none
{ {
//===============================================================gamma_none double operator()(double x) const { return x; }
struct gamma_none };
//==============================================================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
{ {
double operator()(double x) const { return x; } if (x == 0.0)
}; return 0.0;
return pow(x, m_gamma);
//==============================================================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
{
if (x == 0.0) return 0.0;
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;
double delta = m_end - m_start;
// avoid nan from potential zero division
// https://github.com/mapnik/mapnik/issues/761
if (delta <= 0.0) return 0.0;
return (x - m_start) / delta;
}
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;
};
inline double sRGB_to_linear(double x)
{
return (x <= 0.04045) ? (x / 12.92) : pow((x + 0.055) / (1.055), 2.4);
} }
inline double linear_to_sRGB(double x) 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)
{ {
return (x <= 0.0031308) ? (x * 12.92) : (1.055 * pow(x, 1 / 2.4) - 0.055); 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;
double delta = m_end - m_start;
// avoid nan from potential zero division
// https://github.com/mapnik/mapnik/issues/761
if (delta <= 0.0)
return 0.0;
return (x - m_start) / delta;
}
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;
};
inline double sRGB_to_linear(double x)
{
return (x <= 0.04045) ? (x / 12.92) : pow((x + 0.055) / (1.055), 2.4);
} }
inline double linear_to_sRGB(double x)
{
return (x <= 0.0031308) ? (x * 12.92) : (1.055 * pow(x, 1 / 2.4) - 0.055);
}
} // namespace agg
#endif #endif

View file

@ -20,286 +20,247 @@
#include "agg_basics.h" #include "agg_basics.h"
#include "agg_gamma_functions.h" #include "agg_gamma_functions.h"
namespace agg namespace agg {
template<class LoResT = int8u, class HiResT = int8u, unsigned GammaShift = 8, unsigned HiResShift = 8>
class gamma_lut
{ {
template<class LoResT=int8u, public:
class HiResT=int8u, typedef gamma_lut<LoResT, HiResT, GammaShift, HiResShift> self_type;
unsigned GammaShift=8,
unsigned HiResShift=8> class gamma_lut enum gamma_scale_e { gamma_shift = GammaShift, gamma_size = 1 << gamma_shift, gamma_mask = gamma_size - 1 };
enum hi_res_scale_e { hi_res_shift = HiResShift, hi_res_size = 1 << hi_res_shift, hi_res_mask = hi_res_size - 1 };
~gamma_lut()
{ {
public: pod_allocator<LoResT>::deallocate(m_inv_gamma, hi_res_size);
typedef gamma_lut<LoResT, HiResT, GammaShift, HiResShift> self_type; pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size);
}
enum gamma_scale_e gamma_lut()
{ : m_gamma(1.0)
gamma_shift = GammaShift, , m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size))
gamma_size = 1 << gamma_shift, , m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
gamma_mask = gamma_size - 1
};
enum hi_res_scale_e
{
hi_res_shift = HiResShift,
hi_res_size = 1 << hi_res_shift,
hi_res_mask = hi_res_size - 1
};
~gamma_lut()
{
pod_allocator<LoResT>::deallocate(m_inv_gamma, hi_res_size);
pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size);
}
gamma_lut() :
m_gamma(1.0),
m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
{
unsigned i;
for(i = 0; i < gamma_size; i++)
{
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(pod_allocator<HiResT>::allocate(gamma_size)),
m_inv_gamma(pod_allocator<LoResT>::allocate(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)
uround(pow(i / double(gamma_mask), m_gamma) * double(hi_res_mask));
}
double inv_g = 1.0 / g;
for(i = 0; i < hi_res_size; i++)
{
m_inv_gamma[i] = (LoResT)
uround(pow(i / double(hi_res_mask), inv_g) * double(gamma_mask));
}
}
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:
gamma_lut(const self_type&);
const self_type& operator = (const self_type&);
double m_gamma;
HiResT* m_dir_gamma;
LoResT* m_inv_gamma;
};
//
// sRGB support classes
//
// Optimized sRGB lookup table. The direct conversion (sRGB to linear)
// is a straightforward lookup. The inverse conversion (linear to sRGB)
// is implemented using binary search.
template<class LinearType>
class sRGB_lut_base
{ {
public: unsigned i;
LinearType dir(int8u v) const for (i = 0; i < gamma_size; i++)
{ {
return m_dir_table[v]; m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift));
} }
int8u inv(LinearType v) const for (i = 0; i < hi_res_size; i++)
{ {
// Unrolled binary search. m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift));
int8u x = 0;
if (v > m_inv_table[128]) x = 128;
if (v > m_inv_table[x + 64]) x += 64;
if (v > m_inv_table[x + 32]) x += 32;
if (v > m_inv_table[x + 16]) x += 16;
if (v > m_inv_table[x + 8]) x += 8;
if (v > m_inv_table[x + 4]) x += 4;
if (v > m_inv_table[x + 2]) x += 2;
if (v > m_inv_table[x + 1]) x += 1;
return x;
} }
}
protected: gamma_lut(double g)
LinearType m_dir_table[256]; : m_gamma(1.0)
LinearType m_inv_table[256]; , m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size))
, m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
// Only derived classes may instantiate.
sRGB_lut_base()
{
}
};
// sRGB_lut - implements sRGB conversion for the various types.
// Base template is undefined, specializations are provided below.
template<class LinearType>
class sRGB_lut;
template<>
class sRGB_lut<float> : public sRGB_lut_base<float>
{ {
public: gamma(g);
sRGB_lut() }
{
// Generate lookup tables.
m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{
// Floating-point RGB is in range [0,1].
m_dir_table[i] = float(sRGB_to_linear(i / 255.0));
m_inv_table[i] = float(sRGB_to_linear((i - 0.5) / 255.0));
}
}
};
template<> void gamma(double g)
class sRGB_lut<int16u> : public sRGB_lut_base<int16u>
{ {
public: m_gamma = g;
sRGB_lut()
{
// Generate lookup tables.
m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{
// 16-bit RGB is in range [0,65535].
m_dir_table[i] = uround(65535.0 * sRGB_to_linear(i / 255.0));
m_inv_table[i] = uround(65535.0 * sRGB_to_linear((i - 0.5) / 255.0));
}
}
};
template<> unsigned i;
class sRGB_lut<int8u> : public sRGB_lut_base<int8u> for (i = 0; i < gamma_size; i++)
{
m_dir_gamma[i] = (HiResT)uround(pow(i / double(gamma_mask), m_gamma) * double(hi_res_mask));
}
double inv_g = 1.0 / g;
for (i = 0; i < hi_res_size; i++)
{
m_inv_gamma[i] = (LoResT)uround(pow(i / double(hi_res_mask), inv_g) * double(gamma_mask));
}
}
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:
gamma_lut(const self_type&);
const self_type& operator=(const self_type&);
double m_gamma;
HiResT* m_dir_gamma;
LoResT* m_inv_gamma;
};
//
// sRGB support classes
//
// Optimized sRGB lookup table. The direct conversion (sRGB to linear)
// is a straightforward lookup. The inverse conversion (linear to sRGB)
// is implemented using binary search.
template<class LinearType>
class sRGB_lut_base
{
public:
LinearType dir(int8u v) const { return m_dir_table[v]; }
int8u inv(LinearType v) const
{ {
public: // Unrolled binary search.
sRGB_lut() int8u x = 0;
{ if (v > m_inv_table[128])
// Generate lookup tables. x = 128;
m_dir_table[0] = 0; if (v > m_inv_table[x + 64])
m_inv_table[0] = 0; x += 64;
for (unsigned i = 1; i <= 255; ++i) if (v > m_inv_table[x + 32])
{ x += 32;
// 8-bit RGB is handled with simple bidirectional lookup tables. if (v > m_inv_table[x + 16])
m_dir_table[i] = uround(255.0 * sRGB_to_linear(i / 255.0)); x += 16;
m_inv_table[i] = uround(255.0 * linear_to_sRGB(i / 255.0)); if (v > m_inv_table[x + 8])
} x += 8;
} if (v > m_inv_table[x + 4])
x += 4;
if (v > m_inv_table[x + 2])
x += 2;
if (v > m_inv_table[x + 1])
x += 1;
return x;
}
int8u inv(int8u v) const protected:
{ LinearType m_dir_table[256];
// In this case, the inverse transform is a simple lookup. LinearType m_inv_table[256];
return m_inv_table[v];
}
};
// Common base class for sRGB_conv objects. Defines an internal // Only derived classes may instantiate.
// sRGB_lut object so that users don't have to. sRGB_lut_base() {}
template<class T> };
class sRGB_conv_base
// sRGB_lut - implements sRGB conversion for the various types.
// Base template is undefined, specializations are provided below.
template<class LinearType>
class sRGB_lut;
template<>
class sRGB_lut<float> : public sRGB_lut_base<float>
{
public:
sRGB_lut()
{ {
public: // Generate lookup tables.
static T rgb_from_sRGB(int8u x) m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{ {
return lut.dir(x); // Floating-point RGB is in range [0,1].
m_dir_table[i] = float(sRGB_to_linear(i / 255.0));
m_inv_table[i] = float(sRGB_to_linear((i - 0.5) / 255.0));
} }
}
};
static int8u rgb_to_sRGB(T x) template<>
{ class sRGB_lut<int16u> : public sRGB_lut_base<int16u>
return lut.inv(x); {
} public:
sRGB_lut()
private:
static sRGB_lut<T> lut;
};
// Definition of sRGB_conv_base::lut. Due to the fact that this a template,
// we don't need to place the definition in a cpp file. Hurrah.
template<class T>
sRGB_lut<T> sRGB_conv_base<T>::lut;
// Wrapper for sRGB-linear conversion.
// Base template is undefined, specializations are provided below.
template<class T>
class sRGB_conv;
template<>
class sRGB_conv<float> : public sRGB_conv_base<float>
{ {
public: // Generate lookup tables.
static float alpha_from_sRGB(int8u x) m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{ {
return float(x / 255.0); // 16-bit RGB is in range [0,65535].
m_dir_table[i] = uround(65535.0 * sRGB_to_linear(i / 255.0));
m_inv_table[i] = uround(65535.0 * sRGB_to_linear((i - 0.5) / 255.0));
} }
}
};
static int8u alpha_to_sRGB(float x) template<>
{ class sRGB_lut<int8u> : public sRGB_lut_base<int8u>
if (x <= 0) return 0; {
else if (x >= 1) return 255; public:
else return int8u(0.5 + x * 255); sRGB_lut()
}
};
template<>
class sRGB_conv<int16u> : public sRGB_conv_base<int16u>
{ {
public: // Generate lookup tables.
static int16u alpha_from_sRGB(int8u x) m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{ {
return (x << 8) | x; // 8-bit RGB is handled with simple bidirectional lookup tables.
m_dir_table[i] = uround(255.0 * sRGB_to_linear(i / 255.0));
m_inv_table[i] = uround(255.0 * linear_to_sRGB(i / 255.0));
} }
}
static int8u alpha_to_sRGB(int16u x) int8u inv(int8u v) const
{
return x >> 8;
}
};
template<>
class sRGB_conv<int8u> : public sRGB_conv_base<int8u>
{ {
public: // In this case, the inverse transform is a simple lookup.
static int8u alpha_from_sRGB(int8u x) return m_inv_table[v];
{ }
return x; };
}
static int8u alpha_to_sRGB(int8u x) // Common base class for sRGB_conv objects. Defines an internal
{ // sRGB_lut object so that users don't have to.
return x; template<class T>
} class sRGB_conv_base
}; {
} public:
static T rgb_from_sRGB(int8u x) { return lut.dir(x); }
static int8u rgb_to_sRGB(T x) { return lut.inv(x); }
private:
static sRGB_lut<T> lut;
};
// Definition of sRGB_conv_base::lut. Due to the fact that this a template,
// we don't need to place the definition in a cpp file. Hurrah.
template<class T>
sRGB_lut<T> sRGB_conv_base<T>::lut;
// Wrapper for sRGB-linear conversion.
// Base template is undefined, specializations are provided below.
template<class T>
class sRGB_conv;
template<>
class sRGB_conv<float> : public sRGB_conv_base<float>
{
public:
static float alpha_from_sRGB(int8u x) { return float(x / 255.0); }
static int8u alpha_to_sRGB(float x)
{
if (x <= 0)
return 0;
else if (x >= 1)
return 255;
else
return int8u(0.5 + x * 255);
}
};
template<>
class sRGB_conv<int16u> : public sRGB_conv_base<int16u>
{
public:
static int16u alpha_from_sRGB(int8u x) { return (x << 8) | x; }
static int8u alpha_to_sRGB(int16u x) { return x >> 8; }
};
template<>
class sRGB_conv<int8u> : public sRGB_conv_base<int8u>
{
public:
static int8u alpha_from_sRGB(int8u x) { return x; }
static int8u alpha_to_sRGB(int8u x) { return x; }
};
} // namespace agg
#endif #endif

View file

@ -19,137 +19,134 @@
#include <cstring> #include <cstring>
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//========================================================glyph_raster_bin
template<class ColorT>
class glyph_raster_bin
{ {
public:
typedef ColorT color_type;
//========================================================glyph_raster_bin //--------------------------------------------------------------------
template<class ColorT> class glyph_raster_bin struct glyph_rect
{ {
public: int x1, y1, x2, y2;
typedef ColorT color_type; double dx, dy;
//--------------------------------------------------------------------
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;
}; };
//--------------------------------------------------------------------
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;
};
} // namespace agg
#endif #endif

View file

@ -21,226 +21,200 @@
#include "agg_color_rgba.h" #include "agg_color_rgba.h"
#include "agg_color_gray.h" #include "agg_color_gray.h"
namespace agg namespace agg {
//======================================================color_interpolator
template<class ColorT>
struct color_interpolator
{ {
public:
typedef ColorT color_type;
//======================================================color_interpolator color_interpolator(const color_type& c1, const color_type& c2, unsigned len)
template<class ColorT> struct color_interpolator : m_c1(c1)
, m_c2(c2)
, m_len(len)
, m_count(0)
{}
void operator++() { ++m_count; }
color_type color() const { return m_c1.gradient(m_c2, double(m_count) / m_len); }
private:
color_type m_c1;
color_type m_c2;
unsigned m_len;
unsigned m_count;
};
//========================================================================
// Fast specialization for rgba8
template<>
struct color_interpolator<rgba8>
{
public:
typedef rgba8 color_type;
color_interpolator(const color_type& c1, const color_type& c2, unsigned len)
: r(c1.r, c2.r, len)
, g(c1.g, c2.g, len)
, b(c1.b, c2.b, len)
, a(c1.a, c2.a, len)
{}
void operator++()
{ {
public: ++r;
typedef ColorT color_type; ++g;
++b;
color_interpolator(const color_type& c1, ++a;
const color_type& c2,
unsigned len) :
m_c1(c1),
m_c2(c2),
m_len(len),
m_count(0)
{}
void operator ++ ()
{
++m_count;
}
color_type color() const
{
return m_c1.gradient(m_c2, double(m_count) / m_len);
}
private:
color_type m_c1;
color_type m_c2;
unsigned m_len;
unsigned m_count;
};
//========================================================================
// Fast specialization for rgba8
template<> struct color_interpolator<rgba8>
{
public:
typedef rgba8 color_type;
color_interpolator(const color_type& c1,
const color_type& c2,
unsigned len) :
r(c1.r, c2.r, len),
g(c1.g, c2.g, len),
b(c1.b, c2.b, len),
a(c1.a, c2.a, len)
{}
void operator ++ ()
{
++r; ++g; ++b; ++a;
}
color_type color() const
{
return color_type(r.y(), g.y(), b.y(), a.y());
}
private:
agg::dda_line_interpolator<14> r, g, b, a;
};
//========================================================================
// Fast specialization for gray8
template<> struct color_interpolator<gray8>
{
public:
typedef gray8 color_type;
color_interpolator(const color_type& c1,
const color_type& c2,
unsigned len) :
v(c1.v, c2.v, len),
a(c1.a, c2.a, len)
{}
void operator ++ ()
{
++v; ++a;
}
color_type color() const
{
return color_type(v.y(), a.y());
}
private:
agg::dda_line_interpolator<14> v,a;
};
//============================================================gradient_lut
template<class ColorInterpolator,
unsigned ColorLutSize=256> class gradient_lut
{
public:
typedef ColorInterpolator interpolator_type;
typedef typename interpolator_type::color_type color_type;
enum { color_lut_size = ColorLutSize };
//--------------------------------------------------------------------
gradient_lut() : m_color_lut(color_lut_size) {}
// Build Gradient Lut
// First, call remove_all(), then add_color() at least twice,
// then build_lut(). Argument "offset" in add_color must be
// in range [0...1] and defines a color stop as it is described
// in SVG specification, section Gradients and Patterns.
// The simplest linear gradient is:
// gradient_lut.add_color(0.0, start_color);
// gradient_lut.add_color(1.0, end_color);
//--------------------------------------------------------------------
void remove_all();
void add_color(double offset, const color_type& color);
bool build_lut();
// Size-index Interface. This class can be used directly as the
// ColorF in span_gradient. All it needs is two access methods
// size() and operator [].
//--------------------------------------------------------------------
static unsigned size()
{
return color_lut_size;
}
const color_type& operator [] (unsigned i) const
{
return m_color_lut[i];
}
private:
//--------------------------------------------------------------------
struct color_point
{
double offset;
color_type color;
color_point() {}
color_point(double off, const color_type& c) :
offset(off), color(c)
{
if(offset < 0.0) offset = 0.0;
if(offset > 1.0) offset = 1.0;
}
};
typedef agg::pod_bvector<color_point, 4> color_profile_type;
typedef agg::pod_array<color_type> color_lut_type;
static bool offset_less(const color_point& a, const color_point& b)
{
return a.offset < b.offset;
}
static bool offset_equal(const color_point& a, const color_point& b)
{
return a.offset == b.offset;
}
//--------------------------------------------------------------------
color_profile_type m_color_profile;
color_lut_type m_color_lut;
};
//------------------------------------------------------------------------
template<class T, unsigned S>
void gradient_lut<T,S>::remove_all()
{
m_color_profile.remove_all();
} }
//------------------------------------------------------------------------ color_type color() const { return color_type(r.y(), g.y(), b.y(), a.y()); }
template<class T, unsigned S>
void gradient_lut<T,S>::add_color(double offset, const color_type& color) private:
agg::dda_line_interpolator<14> r, g, b, a;
};
//========================================================================
// Fast specialization for gray8
template<>
struct color_interpolator<gray8>
{
public:
typedef gray8 color_type;
color_interpolator(const color_type& c1, const color_type& c2, unsigned len)
: v(c1.v, c2.v, len)
, a(c1.a, c2.a, len)
{}
void operator++()
{ {
m_color_profile.add(color_point(offset, color)); ++v;
++a;
} }
//------------------------------------------------------------------------ color_type color() const { return color_type(v.y(), a.y()); }
template<class T, unsigned S>
bool gradient_lut<T,S>::build_lut() private:
agg::dda_line_interpolator<14> v, a;
};
//============================================================gradient_lut
template<class ColorInterpolator, unsigned ColorLutSize = 256>
class gradient_lut
{
public:
typedef ColorInterpolator interpolator_type;
typedef typename interpolator_type::color_type color_type;
enum { color_lut_size = ColorLutSize };
//--------------------------------------------------------------------
gradient_lut()
: m_color_lut(color_lut_size)
{}
// Build Gradient Lut
// First, call remove_all(), then add_color() at least twice,
// then build_lut(). Argument "offset" in add_color must be
// in range [0...1] and defines a color stop as it is described
// in SVG specification, section Gradients and Patterns.
// The simplest linear gradient is:
// gradient_lut.add_color(0.0, start_color);
// gradient_lut.add_color(1.0, end_color);
//--------------------------------------------------------------------
void remove_all();
void add_color(double offset, const color_type& color);
bool build_lut();
// Size-index Interface. This class can be used directly as the
// ColorF in span_gradient. All it needs is two access methods
// size() and operator [].
//--------------------------------------------------------------------
static unsigned size() { return color_lut_size; }
const color_type& operator[](unsigned i) const { return m_color_lut[i]; }
private:
//--------------------------------------------------------------------
struct color_point
{ {
quick_sort(m_color_profile, offset_less); double offset;
m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal)); color_type color;
if(m_color_profile.size() >= 2)
color_point() {}
color_point(double off, const color_type& c)
: offset(off)
, color(c)
{ {
unsigned i; if (offset < 0.0)
unsigned start = uround(m_color_profile[0].offset * color_lut_size); offset = 0.0;
unsigned end = 0; if (offset > 1.0)
color_type c = m_color_profile[0].color; offset = 1.0;
for(i = 0; i < start; i++)
{
m_color_lut[i] = c;
}
for(i = 1; i < m_color_profile.size(); i++)
{
end = uround(m_color_profile[i].offset * color_lut_size);
interpolator_type ci(m_color_profile[i-1].color,
m_color_profile[i ].color,
end - start + 1);
while(start < end)
{
m_color_lut[start] = ci.color();
++ci;
++start;
}
}
c = m_color_profile.last().color;
for(; end < m_color_lut.size(); end++)
{
m_color_lut[end] = c;
}
return true;
} }
return false; };
} typedef agg::pod_bvector<color_point, 4> color_profile_type;
typedef agg::pod_array<color_type> color_lut_type;
static bool offset_less(const color_point& a, const color_point& b) { return a.offset < b.offset; }
static bool offset_equal(const color_point& a, const color_point& b) { return a.offset == b.offset; }
//--------------------------------------------------------------------
color_profile_type m_color_profile;
color_lut_type m_color_lut;
};
//------------------------------------------------------------------------
template<class T, unsigned S>
void gradient_lut<T, S>::remove_all()
{
m_color_profile.remove_all();
} }
//------------------------------------------------------------------------
template<class T, unsigned S>
void gradient_lut<T, S>::add_color(double offset, const color_type& color)
{
m_color_profile.add(color_point(offset, color));
}
//------------------------------------------------------------------------
template<class T, unsigned S>
bool gradient_lut<T, S>::build_lut()
{
quick_sort(m_color_profile, offset_less);
m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal));
if (m_color_profile.size() >= 2)
{
unsigned i;
unsigned start = uround(m_color_profile[0].offset * color_lut_size);
unsigned end = 0;
color_type c = m_color_profile[0].color;
for (i = 0; i < start; i++)
{
m_color_lut[i] = c;
}
for (i = 1; i < m_color_profile.size(); i++)
{
end = uround(m_color_profile[i].offset * color_lut_size);
interpolator_type ci(m_color_profile[i - 1].color, m_color_profile[i].color, end - start + 1);
while (start < end)
{
m_color_lut[start] = ci.color();
++ci;
++start;
}
}
c = m_color_profile.last().color;
for (; end < m_color_lut.size(); end++)
{
m_color_lut[end] = c;
}
return true;
}
return false;
}
} // namespace agg
#endif #endif

View file

@ -24,130 +24,107 @@
#include "agg_conv_stroke.h" #include "agg_conv_stroke.h"
#include "agg_conv_transform.h" #include "agg_conv_transform.h"
namespace agg 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; }
// See Implementation agg_gsv_text.cpp void load_font(const char* file);
// void size(double height, double width = 0.0);
class gsv_text void space(double space);
void line_space(double line_space);
void start_point(double x, double y);
void text(const char* text);
double text_width();
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
private:
// not supposed to be copied
gsv_text(const gsv_text&);
const gsv_text& operator=(const gsv_text&);
int16u value(const int8u* p) const
{ {
enum status int16u v;
if (m_big_endian)
{ {
initial, *(int8u*)&v = p[1];
next_char, *((int8u*)&v + 1) = p[0];
start_glyph,
glyph
};
public:
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);
double text_width();
void rewind(unsigned path_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;
} }
else
{
*(int8u*)&v = p[0];
*((int8u*)&v + 1) = p[1];
}
return v;
}
private: private:
double m_x; double m_x;
double m_y; double m_y;
double m_start_x; double m_start_x;
double m_width; double m_width;
double m_height; double m_height;
double m_space; double m_space;
double m_line_space; double m_line_space;
char m_chr[2]; char m_chr[2];
char* m_text; char* m_text;
pod_array<char> m_text_buf; pod_array<char> m_text_buf;
char* m_cur_chr; char* m_cur_chr;
const void* m_font; const void* m_font;
pod_array<char> m_loaded_font; pod_array<char> m_loaded_font;
status m_status; status m_status;
bool m_big_endian; bool m_big_endian;
bool m_flip; bool m_flip;
int8u* m_indices; int8u* m_indices;
int8* m_glyphs; int8* m_glyphs;
int8* m_bglyph; int8* m_bglyph;
int8* m_eglyph; int8* m_eglyph;
double m_w; double m_w;
double m_h; 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); }
//--------------------------------------------------------gsv_text_outline void rewind(unsigned path_id)
template<class Transformer = trans_affine> class gsv_text_outline
{ {
public: m_trans.rewind(path_id);
gsv_text_outline(gsv_text& text, const Transformer& trans) : m_polyline.line_join(round_join);
m_polyline(text), m_polyline.line_cap(round_cap);
m_trans(m_polyline, trans) }
{
}
void width(double w) unsigned vertex(double* x, double* y) { return m_trans.vertex(x, y); }
{
m_polyline.width(w);
}
void transformer(const Transformer* trans) private:
{ conv_stroke<gsv_text> m_polyline;
m_trans->transformer(trans); conv_transform<conv_stroke<gsv_text>, Transformer> m_trans;
} };
void rewind(unsigned path_id)
{
m_trans.rewind(path_id);
m_polyline.line_join(round_join);
m_polyline.line_cap(round_cap);
}
unsigned vertex(double* x, double* y)
{
return m_trans.vertex(x, y);
}
private:
conv_stroke<gsv_text> m_polyline;
conv_transform<conv_stroke<gsv_text>, Transformer> m_trans;
};
}
} // namespace agg
#endif #endif

View file

@ -18,464 +18,439 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//-----------------------------------------------------image_accessor_clip
template<class PixFmt>
class image_accessor_clip
{ {
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
//-----------------------------------------------------image_accessor_clip image_accessor_clip() {}
template<class PixFmt> class image_accessor_clip explicit image_accessor_clip(const pixfmt_type& pixf, const color_type& bk)
: m_pixf(&pixf)
{ {
public: pixfmt_type::make_pix(m_bk_buf, bk);
typedef PixFmt pixfmt_type; }
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_clip() {} void attach(const pixfmt_type& pixf) { m_pixf = &pixf; }
explicit image_accessor_clip(const pixfmt_type& pixf,
const color_type& bk) :
m_pixf(&pixf)
{
pixfmt_type::make_pix(m_bk_buf, bk);
}
void attach(const pixfmt_type& pixf) void background_color(const color_type& bk) { pixfmt_type::make_pix(m_bk_buf, bk); }
{
m_pixf = &pixf;
}
void background_color(const color_type& bk) private:
{ AGG_INLINE const int8u* pixel() const
pixfmt_type::make_pix(m_bk_buf, bk);
}
private:
AGG_INLINE const int8u* pixel() const
{
if(m_y >= 0 && m_y < (int)m_pixf->height() &&
m_x >= 0 && m_x < (int)m_pixf->width())
{
return m_pixf->pix_ptr(m_x, m_y);
}
return m_bk_buf;
}
public:
AGG_INLINE const int8u* span(int x, int y, unsigned len)
{
m_x = m_x0 = x;
m_y = y;
if(y >= 0 && y < (int)m_pixf->height() &&
x >= 0 && x+(int)len <= (int)m_pixf->width())
{
return m_pix_ptr = m_pixf->pix_ptr(x, y);
}
m_pix_ptr = 0;
return pixel();
}
AGG_INLINE const int8u* next_x()
{
if(m_pix_ptr) return m_pix_ptr += pix_width;
++m_x;
return pixel();
}
AGG_INLINE const int8u* next_y()
{
++m_y;
m_x = m_x0;
if(m_pix_ptr &&
m_y >= 0 && m_y < (int)m_pixf->height())
{
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
}
m_pix_ptr = 0;
return pixel();
}
private:
const pixfmt_type* m_pixf;
int8u m_bk_buf[4];
int m_x, m_x0, m_y;
const int8u* m_pix_ptr;
};
//--------------------------------------------------image_accessor_no_clip
template<class PixFmt> class image_accessor_no_clip
{ {
public: if (m_y >= 0 && m_y < (int)m_pixf->height() && m_x >= 0 && m_x < (int)m_pixf->width())
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_no_clip() {}
explicit image_accessor_no_clip(const pixfmt_type& pixf) :
m_pixf(&pixf)
{}
void attach(const pixfmt_type& pixf)
{ {
m_pixf = &pixf; return m_pixf->pix_ptr(m_x, m_y);
} }
return m_bk_buf;
}
AGG_INLINE const int8u* span(int x, int y, unsigned) public:
AGG_INLINE const int8u* span(int x, int y, unsigned len)
{
m_x = m_x0 = x;
m_y = y;
if (y >= 0 && y < (int)m_pixf->height() && x >= 0 && x + (int)len <= (int)m_pixf->width())
{ {
m_x = x;
m_y = y;
return m_pix_ptr = m_pixf->pix_ptr(x, y); return m_pix_ptr = m_pixf->pix_ptr(x, y);
} }
m_pix_ptr = 0;
return pixel();
}
AGG_INLINE const int8u* next_x() AGG_INLINE const int8u* next_x()
{ {
if (m_pix_ptr)
return m_pix_ptr += pix_width; return m_pix_ptr += pix_width;
} ++m_x;
return pixel();
}
AGG_INLINE const int8u* next_y() AGG_INLINE const int8u* next_y()
{
++m_y;
m_x = m_x0;
if (m_pix_ptr && m_y >= 0 && m_y < (int)m_pixf->height())
{ {
++m_y;
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
} }
m_pix_ptr = 0;
return pixel();
}
private: private:
const pixfmt_type* m_pixf; const pixfmt_type* m_pixf;
int m_x, m_y; int8u m_bk_buf[4];
const int8u* m_pix_ptr; int m_x, m_x0, m_y;
}; const int8u* m_pix_ptr;
};
//--------------------------------------------------image_accessor_no_clip
template<class PixFmt>
class image_accessor_no_clip
{
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_no_clip() {}
explicit image_accessor_no_clip(const pixfmt_type& pixf)
: m_pixf(&pixf)
{}
void attach(const pixfmt_type& pixf) { m_pixf = &pixf; }
//----------------------------------------------------image_accessor_clone AGG_INLINE const int8u* span(int x, int y, unsigned)
template<class PixFmt> class image_accessor_clone
{ {
public: m_x = x;
typedef PixFmt pixfmt_type; m_y = y;
typedef typename pixfmt_type::color_type color_type; return m_pix_ptr = m_pixf->pix_ptr(x, y);
typedef typename pixfmt_type::order_type order_type; }
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_clone() {} AGG_INLINE const int8u* next_x() { return m_pix_ptr += pix_width; }
explicit image_accessor_clone(const pixfmt_type& pixf) :
m_pixf(&pixf)
{}
void attach(const pixfmt_type& pixf) AGG_INLINE const int8u* next_y()
{
m_pixf = &pixf;
}
private:
AGG_INLINE const int8u* pixel() const
{
int x = m_x;
int y = m_y;
if(x < 0) x = 0;
if(y < 0) y = 0;
if(x >= (int)m_pixf->width()) x = m_pixf->width() - 1;
if(y >= (int)m_pixf->height()) y = m_pixf->height() - 1;
return m_pixf->pix_ptr(x, y);
}
public:
AGG_INLINE const int8u* span(int x, int y, unsigned len)
{
m_x = m_x0 = x;
m_y = y;
if(y >= 0 && y < (int)m_pixf->height() &&
x >= 0 && x+(int)len <= (int)m_pixf->width())
{
return m_pix_ptr = m_pixf->pix_ptr(x, y);
}
m_pix_ptr = 0;
return pixel();
}
AGG_INLINE const int8u* next_x()
{
if(m_pix_ptr) return m_pix_ptr += pix_width;
++m_x;
return pixel();
}
AGG_INLINE const int8u* next_y()
{
++m_y;
m_x = m_x0;
if(m_pix_ptr &&
m_y >= 0 && m_y < (int)m_pixf->height())
{
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
}
m_pix_ptr = 0;
return pixel();
}
private:
const pixfmt_type* m_pixf;
int m_x, m_x0, m_y;
const int8u* m_pix_ptr;
};
//-----------------------------------------------------image_accessor_wrap
template<class PixFmt, class WrapX, class WrapY> class image_accessor_wrap
{ {
public: ++m_y;
typedef PixFmt pixfmt_type; return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
typedef typename pixfmt_type::color_type color_type; }
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_wrap() {} private:
explicit image_accessor_wrap(const pixfmt_type& pixf) : const pixfmt_type* m_pixf;
m_pixf(&pixf), int m_x, m_y;
m_wrap_x(pixf.width()), const int8u* m_pix_ptr;
m_wrap_y(pixf.height()) };
{}
void attach(const pixfmt_type& pixf) //----------------------------------------------------image_accessor_clone
{ template<class PixFmt>
m_pixf = &pixf; class image_accessor_clone
} {
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
AGG_INLINE const int8u* span(int x, int y, unsigned) image_accessor_clone() {}
{ explicit image_accessor_clone(const pixfmt_type& pixf)
m_x = x; : m_pixf(&pixf)
m_row_ptr = m_pixf->row_ptr(m_wrap_y(y)); {}
return m_row_ptr + m_wrap_x(x) * pix_width;
}
AGG_INLINE const int8u* next_x() void attach(const pixfmt_type& pixf) { m_pixf = &pixf; }
{
int x = ++m_wrap_x;
return m_row_ptr + x * pix_width;
}
AGG_INLINE const int8u* next_y() private:
{ AGG_INLINE const int8u* pixel() const
m_row_ptr = m_pixf->row_ptr(++m_wrap_y);
return m_row_ptr + m_wrap_x(m_x) * pix_width;
}
private:
const pixfmt_type* m_pixf;
const int8u* m_row_ptr;
int m_x;
WrapX m_wrap_x;
WrapY m_wrap_y;
};
//--------------------------------------------------------wrap_mode_repeat
class wrap_mode_repeat
{ {
public: int x = m_x;
wrap_mode_repeat() {} int y = m_y;
wrap_mode_repeat(unsigned size) : if (x < 0)
m_size(size), x = 0;
m_add(size * (0x3FFFFFFF / size)), if (y < 0)
m_value(0) y = 0;
{} if (x >= (int)m_pixf->width())
x = m_pixf->width() - 1;
if (y >= (int)m_pixf->height())
y = m_pixf->height() - 1;
return m_pixf->pix_ptr(x, y);
}
AGG_INLINE unsigned operator() (int v) public:
{ AGG_INLINE const int8u* span(int x, int y, unsigned len)
return m_value = (unsigned(v) + m_add) % m_size;
}
AGG_INLINE unsigned operator++ ()
{
++m_value;
if(m_value >= m_size) m_value = 0;
return m_value;
}
private:
unsigned m_size;
unsigned m_add;
unsigned m_value;
};
//---------------------------------------------------wrap_mode_repeat_pow2
class wrap_mode_repeat_pow2
{ {
public: m_x = m_x0 = x;
wrap_mode_repeat_pow2() {} m_y = y;
wrap_mode_repeat_pow2(unsigned size) : m_value(0) if (y >= 0 && y < (int)m_pixf->height() && x >= 0 && x + (int)len <= (int)m_pixf->width())
{ {
m_mask = 1; return m_pix_ptr = m_pixf->pix_ptr(x, y);
while(m_mask < size) m_mask = (m_mask << 1) | 1;
m_mask >>= 1;
} }
AGG_INLINE unsigned operator() (int v) m_pix_ptr = 0;
return pixel();
}
AGG_INLINE const int8u* next_x()
{
if (m_pix_ptr)
return m_pix_ptr += pix_width;
++m_x;
return pixel();
}
AGG_INLINE const int8u* next_y()
{
++m_y;
m_x = m_x0;
if (m_pix_ptr && m_y >= 0 && m_y < (int)m_pixf->height())
{ {
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
}
m_pix_ptr = 0;
return pixel();
}
private:
const pixfmt_type* m_pixf;
int m_x, m_x0, m_y;
const int8u* m_pix_ptr;
};
//-----------------------------------------------------image_accessor_wrap
template<class PixFmt, class WrapX, class WrapY>
class image_accessor_wrap
{
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_wrap() {}
explicit image_accessor_wrap(const pixfmt_type& pixf)
: m_pixf(&pixf)
, m_wrap_x(pixf.width())
, m_wrap_y(pixf.height())
{}
void attach(const pixfmt_type& pixf) { m_pixf = &pixf; }
AGG_INLINE const int8u* span(int x, int y, unsigned)
{
m_x = x;
m_row_ptr = m_pixf->row_ptr(m_wrap_y(y));
return m_row_ptr + m_wrap_x(x) * pix_width;
}
AGG_INLINE const int8u* next_x()
{
int x = ++m_wrap_x;
return m_row_ptr + x * pix_width;
}
AGG_INLINE const int8u* next_y()
{
m_row_ptr = m_pixf->row_ptr(++m_wrap_y);
return m_row_ptr + m_wrap_x(m_x) * pix_width;
}
private:
const pixfmt_type* m_pixf;
const int8u* m_row_ptr;
int m_x;
WrapX m_wrap_x;
WrapY m_wrap_y;
};
//--------------------------------------------------------wrap_mode_repeat
class wrap_mode_repeat
{
public:
wrap_mode_repeat() {}
wrap_mode_repeat(unsigned size)
: m_size(size)
, m_add(size * (0x3FFFFFFF / size))
, m_value(0)
{}
AGG_INLINE unsigned operator()(int v) { return m_value = (unsigned(v) + m_add) % m_size; }
AGG_INLINE unsigned operator++()
{
++m_value;
if (m_value >= m_size)
m_value = 0;
return m_value;
}
private:
unsigned m_size;
unsigned m_add;
unsigned m_value;
};
//---------------------------------------------------wrap_mode_repeat_pow2
class wrap_mode_repeat_pow2
{
public:
wrap_mode_repeat_pow2() {}
wrap_mode_repeat_pow2(unsigned size)
: m_value(0)
{
m_mask = 1;
while (m_mask < size)
m_mask = (m_mask << 1) | 1;
m_mask >>= 1;
}
AGG_INLINE unsigned operator()(int v) { return m_value = unsigned(v) & m_mask; }
AGG_INLINE unsigned operator++()
{
++m_value;
if (m_value > m_mask)
m_value = 0;
return m_value;
}
private:
unsigned m_mask;
unsigned m_value;
};
//----------------------------------------------wrap_mode_repeat_auto_pow2
class wrap_mode_repeat_auto_pow2
{
public:
wrap_mode_repeat_auto_pow2() {}
wrap_mode_repeat_auto_pow2(unsigned size)
: m_size(size)
, m_add(size * (0x3FFFFFFF / size))
, m_mask((m_size & (m_size - 1)) ? 0 : m_size - 1)
, m_value(0)
{}
AGG_INLINE unsigned operator()(int v)
{
if (m_mask)
return m_value = unsigned(v) & m_mask; return m_value = unsigned(v) & m_mask;
} return m_value = (unsigned(v) + m_add) % m_size;
AGG_INLINE unsigned operator++ () }
{ AGG_INLINE unsigned operator++()
++m_value;
if(m_value > m_mask) m_value = 0;
return m_value;
}
private:
unsigned m_mask;
unsigned m_value;
};
//----------------------------------------------wrap_mode_repeat_auto_pow2
class wrap_mode_repeat_auto_pow2
{ {
public: ++m_value;
wrap_mode_repeat_auto_pow2() {} if (m_value >= m_size)
wrap_mode_repeat_auto_pow2(unsigned size) : m_value = 0;
m_size(size), return m_value;
m_add(size * (0x3FFFFFFF / size)), }
m_mask((m_size & (m_size-1)) ? 0 : m_size-1),
m_value(0)
{}
AGG_INLINE unsigned operator() (int v) private:
{ unsigned m_size;
if(m_mask) return m_value = unsigned(v) & m_mask; unsigned m_add;
return m_value = (unsigned(v) + m_add) % m_size; unsigned m_mask;
} unsigned m_value;
AGG_INLINE unsigned operator++ () };
{
++m_value;
if(m_value >= m_size) m_value = 0;
return m_value;
}
private: //-------------------------------------------------------wrap_mode_reflect
unsigned m_size; class wrap_mode_reflect
unsigned m_add; {
unsigned m_mask; public:
unsigned m_value; wrap_mode_reflect() {}
}; wrap_mode_reflect(unsigned size)
: m_size(size)
, m_size2(size * 2)
, m_add(m_size2 * (0x3FFFFFFF / m_size2))
, m_value(0)
{}
AGG_INLINE unsigned operator()(int v)
//-------------------------------------------------------wrap_mode_reflect
class wrap_mode_reflect
{ {
public: m_value = (unsigned(v) + m_add) % m_size2;
wrap_mode_reflect() {} if (m_value >= m_size)
wrap_mode_reflect(unsigned size) : return m_size2 - m_value - 1;
m_size(size), return m_value;
m_size2(size * 2), }
m_add(m_size2 * (0x3FFFFFFF / m_size2)),
m_value(0)
{}
AGG_INLINE unsigned operator() (int v) AGG_INLINE unsigned operator++()
{
m_value = (unsigned(v) + m_add) % m_size2;
if(m_value >= m_size) return m_size2 - m_value - 1;
return m_value;
}
AGG_INLINE unsigned operator++ ()
{
++m_value;
if(m_value >= m_size2) m_value = 0;
if(m_value >= m_size) return m_size2 - m_value - 1;
return m_value;
}
private:
unsigned m_size;
unsigned m_size2;
unsigned m_add;
unsigned m_value;
};
//--------------------------------------------------wrap_mode_reflect_pow2
class wrap_mode_reflect_pow2
{ {
public: ++m_value;
wrap_mode_reflect_pow2() {} if (m_value >= m_size2)
wrap_mode_reflect_pow2(unsigned size) : m_value(0) m_value = 0;
{ if (m_value >= m_size)
m_mask = 1; return m_size2 - m_value - 1;
m_size = 1; return m_value;
while(m_mask < size) }
{
m_mask = (m_mask << 1) | 1;
m_size <<= 1;
}
}
AGG_INLINE unsigned operator() (int v)
{
m_value = unsigned(v) & m_mask;
if(m_value >= m_size) return m_mask - m_value;
return m_value;
}
AGG_INLINE unsigned operator++ ()
{
++m_value;
m_value &= m_mask;
if(m_value >= m_size) return m_mask - m_value;
return m_value;
}
private:
unsigned m_size;
unsigned m_mask;
unsigned m_value;
};
private:
unsigned m_size;
unsigned m_size2;
unsigned m_add;
unsigned m_value;
};
//--------------------------------------------------wrap_mode_reflect_pow2
//---------------------------------------------wrap_mode_reflect_auto_pow2 class wrap_mode_reflect_pow2
class wrap_mode_reflect_auto_pow2 {
public:
wrap_mode_reflect_pow2() {}
wrap_mode_reflect_pow2(unsigned size)
: m_value(0)
{ {
public: m_mask = 1;
wrap_mode_reflect_auto_pow2() {} m_size = 1;
wrap_mode_reflect_auto_pow2(unsigned size) : while (m_mask < size)
m_size(size),
m_size2(size * 2),
m_add(m_size2 * (0x3FFFFFFF / m_size2)),
m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1),
m_value(0)
{}
AGG_INLINE unsigned operator() (int v)
{ {
m_value = m_mask ? unsigned(v) & m_mask : m_mask = (m_mask << 1) | 1;
(unsigned(v) + m_add) % m_size2; m_size <<= 1;
if(m_value >= m_size) return m_size2 - m_value - 1;
return m_value;
}
AGG_INLINE unsigned operator++ ()
{
++m_value;
if(m_value >= m_size2) m_value = 0;
if(m_value >= m_size) return m_size2 - m_value - 1;
return m_value;
} }
}
AGG_INLINE unsigned operator()(int v)
{
m_value = unsigned(v) & m_mask;
if (m_value >= m_size)
return m_mask - m_value;
return m_value;
}
AGG_INLINE unsigned operator++()
{
++m_value;
m_value &= m_mask;
if (m_value >= m_size)
return m_mask - m_value;
return m_value;
}
private: private:
unsigned m_size; unsigned m_size;
unsigned m_size2; unsigned m_mask;
unsigned m_add; unsigned m_value;
unsigned m_mask; };
unsigned m_value;
};
//---------------------------------------------wrap_mode_reflect_auto_pow2
class wrap_mode_reflect_auto_pow2
{
public:
wrap_mode_reflect_auto_pow2() {}
wrap_mode_reflect_auto_pow2(unsigned size)
: m_size(size)
, m_size2(size * 2)
, m_add(m_size2 * (0x3FFFFFFF / m_size2))
, m_mask((m_size2 & (m_size2 - 1)) ? 0 : m_size2 - 1)
, m_value(0)
{}
} AGG_INLINE unsigned operator()(int v)
{
m_value = m_mask ? unsigned(v) & m_mask : (unsigned(v) + m_add) % m_size2;
if (m_value >= m_size)
return m_size2 - m_value - 1;
return m_value;
}
AGG_INLINE unsigned operator++()
{
++m_value;
if (m_value >= m_size2)
m_value = 0;
if (m_value >= m_size)
return m_size2 - m_value - 1;
return m_value;
}
private:
unsigned m_size;
unsigned m_size2;
unsigned m_add;
unsigned m_mask;
unsigned m_value;
};
} // namespace agg
#endif #endif

View file

@ -23,426 +23,499 @@
#include "agg_array.h" #include "agg_array.h"
#include "agg_math.h" #include "agg_math.h"
namespace agg namespace agg {
// See Implementation agg_image_filters.cpp
enum image_filter_scale_e {
image_filter_shift = 14, //----image_filter_shift
image_filter_scale = 1 << image_filter_shift, //----image_filter_scale
image_filter_mask = image_filter_scale - 1 //----image_filter_mask
};
enum image_subpixel_scale_e {
image_subpixel_shift = 8, //----image_subpixel_shift
image_subpixel_scale = 1 << image_subpixel_shift, //----image_subpixel_scale
image_subpixel_mask = image_subpixel_scale - 1 //----image_subpixel_mask
};
//-----------------------------------------------------image_filter_lut
class image_filter_lut
{ {
public:
// See Implementation agg_image_filters.cpp template<class FilterF>
void calculate(const FilterF& filter, bool normalization = true)
enum image_filter_scale_e
{ {
image_filter_shift = 14, //----image_filter_shift double r = filter.radius();
image_filter_scale = 1 << image_filter_shift, //----image_filter_scale realloc_lut(r);
image_filter_mask = image_filter_scale - 1 //----image_filter_mask unsigned i;
}; unsigned pivot = diameter() << (image_subpixel_shift - 1);
for (i = 0; i < pivot; i++)
enum image_subpixel_scale_e
{
image_subpixel_shift = 8, //----image_subpixel_shift
image_subpixel_scale = 1 << image_subpixel_shift, //----image_subpixel_scale
image_subpixel_mask = image_subpixel_scale - 1 //----image_subpixel_mask
};
//-----------------------------------------------------image_filter_lut
class image_filter_lut
{
public:
template<class FilterF> void calculate(const FilterF& filter,
bool normalization=true)
{ {
double r = filter.radius(); double x = double(i) / double(image_subpixel_scale);
realloc_lut(r); double y = filter.calc_weight(x);
unsigned i; m_weight_array[pivot + i] = m_weight_array[pivot - i] = (int16)iround(y * image_filter_scale);
unsigned pivot = diameter() << (image_subpixel_shift - 1);
for(i = 0; i < pivot; i++)
{
double x = double(i) / double(image_subpixel_scale);
double y = filter.calc_weight(x);
m_weight_array[pivot + i] =
m_weight_array[pivot - i] = (int16)iround(y * image_filter_scale);
}
unsigned end = (diameter() << image_subpixel_shift) - 1;
m_weight_array[0] = m_weight_array[end];
if(normalization)
{
normalize();
}
} }
unsigned end = (diameter() << image_subpixel_shift) - 1;
image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {} m_weight_array[0] = m_weight_array[end];
if (normalization)
template<class FilterF> image_filter_lut(const FilterF& filter,
bool normalization=true)
{ {
calculate(filter, normalization); normalize();
} }
}
double radius() const { return m_radius; } image_filter_lut()
unsigned diameter() const { return m_diameter; } : m_radius(0)
int start() const { return m_start; } , m_diameter(0)
const int16* weight_array() const { return &m_weight_array[0]; } , m_start(0)
void normalize(); {}
private: template<class FilterF>
void realloc_lut(double radius); image_filter_lut(const FilterF& filter, bool normalization = true)
image_filter_lut(const image_filter_lut&);
const image_filter_lut& operator = (const image_filter_lut&);
double m_radius;
unsigned m_diameter;
int m_start;
pod_array<int16> m_weight_array;
};
//--------------------------------------------------------image_filter
template<class FilterF> class image_filter : public image_filter_lut
{ {
public: calculate(filter, normalization);
image_filter() }
double radius() const { return m_radius; }
unsigned diameter() const { return m_diameter; }
int start() const { return m_start; }
const int16* weight_array() const { return &m_weight_array[0]; }
void normalize();
private:
void realloc_lut(double radius);
image_filter_lut(const image_filter_lut&);
const image_filter_lut& operator=(const image_filter_lut&);
double m_radius;
unsigned m_diameter;
int m_start;
pod_array<int16> m_weight_array;
};
//--------------------------------------------------------image_filter
template<class FilterF>
class image_filter : public image_filter_lut
{
public:
image_filter() { calculate(m_filter_function); }
private:
FilterF m_filter_function;
};
//-----------------------------------------------image_filter_bilinear
struct image_filter_bilinear
{
static double radius() { return 1.0; }
static double calc_weight(double x) { return 1.0 - x; }
};
//-----------------------------------------------image_filter_hanning
struct image_filter_hanning
{
static double radius() { return 1.0; }
static double calc_weight(double x) { return 0.5 + 0.5 * std::cos(pi * x); }
};
//-----------------------------------------------image_filter_hamming
struct image_filter_hamming
{
static double radius() { return 1.0; }
static double calc_weight(double x) { return 0.54 + 0.46 * std::cos(pi * x); }
};
//-----------------------------------------------image_filter_hermite
struct image_filter_hermite
{
static double radius() { return 1.0; }
static double calc_weight(double x) { return (2.0 * x - 3.0) * x * x + 1.0; }
};
//------------------------------------------------image_filter_quadric
struct image_filter_quadric
{
static double radius() { return 1.5; }
static double calc_weight(double x)
{
double t;
if (x < 0.5)
return 0.75 - x * x;
if (x < 1.5)
{ {
calculate(m_filter_function); t = x - 1.5;
return 0.5 * t * t;
} }
private: return 0.0;
FilterF m_filter_function; }
}; };
//------------------------------------------------image_filter_bicubic
class image_filter_bicubic
{
static double pow3(double x) { return (x <= 0.0) ? 0.0 : x * x * x; }
//-----------------------------------------------image_filter_bilinear public:
struct image_filter_bilinear static double radius() { return 2.0; }
static double calc_weight(double x)
{ {
static double radius() { return 1.0; } return (1.0 / 6.0) * (pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1));
static double calc_weight(double x) }
};
//-------------------------------------------------image_filter_kaiser
class image_filter_kaiser
{
double a;
double i0a;
double epsilon;
public:
image_filter_kaiser(double b = 6.33)
: a(b)
, epsilon(1e-12)
{
i0a = 1.0 / bessel_i0(b);
}
static double radius() { return 1.0; }
double calc_weight(double x) const { return bessel_i0(a * sqrt(1. - x * x)) * i0a; }
private:
double bessel_i0(double x) const
{
int i;
double sum, y, t;
sum = 1.;
y = x * x / 4.;
t = y;
for (i = 2; t > epsilon; i++)
{ {
return 1.0 - x; sum += t;
t *= (double)y / (i * i);
} }
}; return sum;
}
};
//----------------------------------------------image_filter_catrom
//-----------------------------------------------image_filter_hanning struct image_filter_catrom
struct image_filter_hanning {
static double radius() { return 2.0; }
static double calc_weight(double x)
{ {
static double radius() { return 1.0; } if (x < 1.0)
static double calc_weight(double x) return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0));
if (x < 2.0)
return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x)));
return 0.;
}
};
//---------------------------------------------image_filter_mitchell
class image_filter_mitchell
{
double p0, p2, p3;
double q0, q1, q2, q3;
public:
image_filter_mitchell(double b = 1.0 / 3.0, double c = 1.0 / 3.0)
: p0((6.0 - 2.0 * b) / 6.0)
, p2((-18.0 + 12.0 * b + 6.0 * c) / 6.0)
, p3((12.0 - 9.0 * b - 6.0 * c) / 6.0)
, q0((8.0 * b + 24.0 * c) / 6.0)
, q1((-12.0 * b - 48.0 * c) / 6.0)
, q2((6.0 * b + 30.0 * c) / 6.0)
, q3((-b - 6.0 * c) / 6.0)
{}
static double radius() { return 2.0; }
double calc_weight(double x) const
{
if (x < 1.0)
return p0 + x * x * (p2 + x * p3);
if (x < 2.0)
return q0 + x * (q1 + x * (q2 + x * q3));
return 0.0;
}
};
//----------------------------------------------image_filter_spline16
struct image_filter_spline16
{
static double radius() { return 2.0; }
static double calc_weight(double x)
{
if (x < 1.0)
{ {
return 0.5 + 0.5 * std::cos(pi * x); 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
//-----------------------------------------------image_filter_hamming struct image_filter_spline36
struct image_filter_hamming {
static double radius() { return 3.0; }
static double calc_weight(double x)
{ {
static double radius() { return 1.0; } if (x < 1.0)
static double calc_weight(double x)
{ {
return 0.54 + 0.46 * std::cos(pi * x); return ((13.0 / 11.0 * x - 453.0 / 209.0) * x - 3.0 / 209.0) * x + 1.0;
} }
}; if (x < 2.0)
//-----------------------------------------------image_filter_hermite
struct image_filter_hermite
{
static double radius() { return 1.0; }
static double calc_weight(double x)
{ {
return (2.0 * x - 3.0) * x * x + 1.0; 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_quadric //----------------------------------------------image_filter_gaussian
struct image_filter_quadric struct image_filter_gaussian
{
static double radius() { return 2.0; }
static double calc_weight(double x) { return exp(-2.0 * x * x) * sqrt(2.0 / pi); }
};
//------------------------------------------------image_filter_bessel
struct image_filter_bessel
{
static double radius() { return 3.2383; }
static double calc_weight(double x) { return (x == 0.0) ? pi / 4.0 : besj(pi * x, 1) / (2.0 * x); }
};
//-------------------------------------------------image_filter_sinc
class image_filter_sinc
{
public:
image_filter_sinc(double r)
: m_radius(r < 2.0 ? 2.0 : r)
{}
double radius() const { return m_radius; }
double calc_weight(double x) const
{ {
static double radius() { return 1.5; } if (x == 0.0)
static double calc_weight(double x) return 1.0;
{ x *= pi;
double t; return std::sin(x) / x;
if(x < 0.5) return 0.75 - x * x; }
if(x < 1.5) {t = x - 1.5; return 0.5 * t * t;}
private:
double m_radius;
};
//-----------------------------------------------image_filter_lanczos
class image_filter_lanczos
{
public:
image_filter_lanczos(double r)
: m_radius(r < 2.0 ? 2.0 : r)
{}
double radius() const { return m_radius; }
double calc_weight(double x) const
{
if (x == 0.0)
return 1.0;
if (x > m_radius)
return 0.0; return 0.0;
} x *= pi;
}; double xr = x / m_radius;
return (std::sin(x) / x) * (std::sin(xr) / xr);
}
//------------------------------------------------image_filter_bicubic private:
class image_filter_bicubic double m_radius;
};
//----------------------------------------------image_filter_blackman
class image_filter_blackman
{
public:
image_filter_blackman(double r)
: m_radius(r < 2.0 ? 2.0 : r)
{}
double radius() const { return m_radius; }
double calc_weight(double x) const
{ {
static double pow3(double x) if (x == 0.0)
{ return 1.0;
return (x <= 0.0) ? 0.0 : x * x * x; if (x > m_radius)
}
public:
static double radius() { return 2.0; }
static double calc_weight(double x)
{
return
(1.0/6.0) *
(pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1));
}
};
//-------------------------------------------------image_filter_kaiser
class image_filter_kaiser
{
double a;
double i0a;
double epsilon;
public:
image_filter_kaiser(double b = 6.33) :
a(b), epsilon(1e-12)
{
i0a = 1.0 / bessel_i0(b);
}
static double radius() { return 1.0; }
double calc_weight(double x) const
{
return bessel_i0(a * sqrt(1. - x * x)) * i0a;
}
private:
double bessel_i0(double x) const
{
int i;
double sum, y, t;
sum = 1.;
y = x * x / 4.;
t = y;
for(i = 2; t > epsilon; i++)
{
sum += t;
t *= (double)y / (i * i);
}
return sum;
}
};
//----------------------------------------------image_filter_catrom
struct image_filter_catrom
{
static double radius() { return 2.0; }
static double calc_weight(double x)
{
if(x < 1.0) return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0));
if(x < 2.0) return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x)));
return 0.;
}
};
//---------------------------------------------image_filter_mitchell
class image_filter_mitchell
{
double p0, p2, p3;
double q0, q1, q2, q3;
public:
image_filter_mitchell(double b = 1.0/3.0, double c = 1.0/3.0) :
p0((6.0 - 2.0 * b) / 6.0),
p2((-18.0 + 12.0 * b + 6.0 * c) / 6.0),
p3((12.0 - 9.0 * b - 6.0 * c) / 6.0),
q0((8.0 * b + 24.0 * c) / 6.0),
q1((-12.0 * b - 48.0 * c) / 6.0),
q2((6.0 * b + 30.0 * c) / 6.0),
q3((-b - 6.0 * c) / 6.0)
{}
static double radius() { return 2.0; }
double calc_weight(double x) const
{
if(x < 1.0) return p0 + x * x * (p2 + x * p3);
if(x < 2.0) return q0 + x * (q1 + x * (q2 + x * q3));
return 0.0; return 0.0;
} x *= pi;
}; double xr = x / m_radius;
return (std::sin(x) / x) * (0.42 + 0.5 * std::cos(xr) + 0.08 * std::cos(2 * xr));
}
private:
double m_radius;
};
//----------------------------------------------image_filter_spline16 //------------------------------------------------image_filter_sinc36
struct image_filter_spline16 class image_filter_sinc36 : public image_filter_sinc
{ {
static double radius() { return 2.0; } public:
static double calc_weight(double x) image_filter_sinc36()
{ : image_filter_sinc(3.0)
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_sinc64
class image_filter_sinc64 : public image_filter_sinc
{
public:
image_filter_sinc64()
: image_filter_sinc(4.0)
{}
};
//---------------------------------------------image_filter_spline36 //-----------------------------------------------image_filter_sinc100
struct image_filter_spline36 class image_filter_sinc100 : public image_filter_sinc
{ {
static double radius() { return 3.0; } public:
static double calc_weight(double x) image_filter_sinc100()
{ : image_filter_sinc(5.0)
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_sinc144
class image_filter_sinc144 : public image_filter_sinc
{
public:
image_filter_sinc144()
: image_filter_sinc(6.0)
{}
};
//----------------------------------------------image_filter_gaussian //-----------------------------------------------image_filter_sinc196
struct image_filter_gaussian class image_filter_sinc196 : public image_filter_sinc
{ {
static double radius() { return 2.0; } public:
static double calc_weight(double x) image_filter_sinc196()
{ : image_filter_sinc(7.0)
return exp(-2.0 * x * x) * sqrt(2.0 / pi); {}
} };
};
//-----------------------------------------------image_filter_sinc256
class image_filter_sinc256 : public image_filter_sinc
{
public:
image_filter_sinc256()
: image_filter_sinc(8.0)
{}
};
//------------------------------------------------image_filter_bessel //---------------------------------------------image_filter_lanczos36
struct image_filter_bessel class image_filter_lanczos36 : public image_filter_lanczos
{ {
static double radius() { return 3.2383; } public:
static double calc_weight(double x) image_filter_lanczos36()
{ : image_filter_lanczos(3.0)
return (x == 0.0) ? pi / 4.0 : besj(pi * x, 1) / (2.0 * x); {}
} };
};
//---------------------------------------------image_filter_lanczos64
class image_filter_lanczos64 : public image_filter_lanczos
{
public:
image_filter_lanczos64()
: image_filter_lanczos(4.0)
{}
};
//-------------------------------------------------image_filter_sinc //--------------------------------------------image_filter_lanczos100
class image_filter_sinc class image_filter_lanczos100 : public image_filter_lanczos
{ {
public: public:
image_filter_sinc(double r) : m_radius(r < 2.0 ? 2.0 : r) {} image_filter_lanczos100()
double radius() const { return m_radius; } : image_filter_lanczos(5.0)
double calc_weight(double x) const {}
{ };
if(x == 0.0) return 1.0;
x *= pi;
return std::sin(x) / x;
}
private:
double m_radius;
};
//--------------------------------------------image_filter_lanczos144
class image_filter_lanczos144 : public image_filter_lanczos
{
public:
image_filter_lanczos144()
: image_filter_lanczos(6.0)
{}
};
//-----------------------------------------------image_filter_lanczos //--------------------------------------------image_filter_lanczos196
class image_filter_lanczos class image_filter_lanczos196 : public image_filter_lanczos
{ {
public: public:
image_filter_lanczos(double r) : m_radius(r < 2.0 ? 2.0 : r) {} image_filter_lanczos196()
double radius() const { return m_radius; } : image_filter_lanczos(7.0)
double calc_weight(double x) const {}
{ };
if(x == 0.0) return 1.0;
if(x > m_radius) return 0.0;
x *= pi;
double xr = x / m_radius;
return (std::sin(x) / x) * (std::sin(xr) / xr);
}
private:
double m_radius;
};
//--------------------------------------------image_filter_lanczos256
class image_filter_lanczos256 : public image_filter_lanczos
{
public:
image_filter_lanczos256()
: image_filter_lanczos(8.0)
{}
};
//----------------------------------------------image_filter_blackman //--------------------------------------------image_filter_blackman36
class image_filter_blackman class image_filter_blackman36 : public image_filter_blackman
{ {
public: public:
image_filter_blackman(double r) : m_radius(r < 2.0 ? 2.0 : r) {} image_filter_blackman36()
double radius() const { return m_radius; } : image_filter_blackman(3.0)
double calc_weight(double x) const {}
{ };
if(x == 0.0) return 1.0;
if(x > m_radius) return 0.0;
x *= pi;
double xr = x / m_radius;
return (std::sin(x) / x) * (0.42 + 0.5 * std::cos(xr) + 0.08 * std::cos(2*xr));
}
private:
double m_radius;
};
//------------------------------------------------image_filter_sinc36 //--------------------------------------------image_filter_blackman64
class image_filter_sinc36 : public image_filter_sinc class image_filter_blackman64 : public image_filter_blackman
{ public: image_filter_sinc36() : image_filter_sinc(3.0){} }; {
public:
image_filter_blackman64()
: image_filter_blackman(4.0)
{}
};
//------------------------------------------------image_filter_sinc64 //-------------------------------------------image_filter_blackman100
class image_filter_sinc64 : public image_filter_sinc class image_filter_blackman100 : public image_filter_blackman
{ public: image_filter_sinc64() : image_filter_sinc(4.0){} }; {
public:
image_filter_blackman100()
: image_filter_blackman(5.0)
{}
};
//-----------------------------------------------image_filter_sinc100 //-------------------------------------------image_filter_blackman144
class image_filter_sinc100 : public image_filter_sinc class image_filter_blackman144 : public image_filter_blackman
{ public: image_filter_sinc100() : image_filter_sinc(5.0){} }; {
public:
image_filter_blackman144()
: image_filter_blackman(6.0)
{}
};
//-----------------------------------------------image_filter_sinc144 //-------------------------------------------image_filter_blackman196
class image_filter_sinc144 : public image_filter_sinc class image_filter_blackman196 : public image_filter_blackman
{ public: image_filter_sinc144() : image_filter_sinc(6.0){} }; {
public:
image_filter_blackman196()
: image_filter_blackman(7.0)
{}
};
//-----------------------------------------------image_filter_sinc196 //-------------------------------------------image_filter_blackman256
class image_filter_sinc196 : public image_filter_sinc class image_filter_blackman256 : public image_filter_blackman
{ public: image_filter_sinc196() : image_filter_sinc(7.0){} }; {
public:
image_filter_blackman256()
: image_filter_blackman(8.0)
{}
};
//-----------------------------------------------image_filter_sinc256 } // namespace agg
class image_filter_sinc256 : public image_filter_sinc
{ public: image_filter_sinc256() : image_filter_sinc(8.0){} };
//---------------------------------------------image_filter_lanczos36
class image_filter_lanczos36 : public image_filter_lanczos
{ public: image_filter_lanczos36() : image_filter_lanczos(3.0){} };
//---------------------------------------------image_filter_lanczos64
class image_filter_lanczos64 : public image_filter_lanczos
{ public: image_filter_lanczos64() : image_filter_lanczos(4.0){} };
//--------------------------------------------image_filter_lanczos100
class image_filter_lanczos100 : public image_filter_lanczos
{ public: image_filter_lanczos100() : image_filter_lanczos(5.0){} };
//--------------------------------------------image_filter_lanczos144
class image_filter_lanczos144 : public image_filter_lanczos
{ public: image_filter_lanczos144() : image_filter_lanczos(6.0){} };
//--------------------------------------------image_filter_lanczos196
class image_filter_lanczos196 : public image_filter_lanczos
{ public: image_filter_lanczos196() : image_filter_lanczos(7.0){} };
//--------------------------------------------image_filter_lanczos256
class image_filter_lanczos256 : public image_filter_lanczos
{ public: image_filter_lanczos256() : image_filter_lanczos(8.0){} };
//--------------------------------------------image_filter_blackman36
class image_filter_blackman36 : public image_filter_blackman
{ public: image_filter_blackman36() : image_filter_blackman(3.0){} };
//--------------------------------------------image_filter_blackman64
class image_filter_blackman64 : public image_filter_blackman
{ public: image_filter_blackman64() : image_filter_blackman(4.0){} };
//-------------------------------------------image_filter_blackman100
class image_filter_blackman100 : public image_filter_blackman
{ public: image_filter_blackman100() : image_filter_blackman(5.0){} };
//-------------------------------------------image_filter_blackman144
class image_filter_blackman144 : public image_filter_blackman
{ public: image_filter_blackman144() : image_filter_blackman(6.0){} };
//-------------------------------------------image_filter_blackman196
class image_filter_blackman196 : public image_filter_blackman
{ public: image_filter_blackman196() : image_filter_blackman(7.0){} };
//-------------------------------------------image_filter_blackman256
class image_filter_blackman256 : public image_filter_blackman
{ public: image_filter_blackman256() : image_filter_blackman(8.0){} };
}
#endif #endif

View file

@ -18,172 +18,154 @@
#include <cstdlib> #include <cstdlib>
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
// See Implementation agg_line_aa_basics.cpp
//-------------------------------------------------------------------------
enum line_subpixel_scale_e {
line_subpixel_shift = 8, //----line_subpixel_shift
line_subpixel_scale = 1 << line_subpixel_shift, //----line_subpixel_scale
line_subpixel_mask = line_subpixel_scale - 1, //----line_subpixel_mask
line_max_coord = (1 << 28) - 1, //----line_max_coord
line_max_length = 1 << (line_subpixel_shift + 10) //----line_max_length
};
//-------------------------------------------------------------------------
enum line_mr_subpixel_scale_e {
line_mr_subpixel_shift = 4, //----line_mr_subpixel_shift
line_mr_subpixel_scale = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_scale
line_mr_subpixel_mask = line_mr_subpixel_scale - 1 //----line_mr_subpixel_mask
};
//------------------------------------------------------------------line_mr
AGG_INLINE int line_mr(int x)
{ {
return x >> (line_subpixel_shift - line_mr_subpixel_shift);
// See Implementation agg_line_aa_basics.cpp
//-------------------------------------------------------------------------
enum line_subpixel_scale_e
{
line_subpixel_shift = 8, //----line_subpixel_shift
line_subpixel_scale = 1 << line_subpixel_shift, //----line_subpixel_scale
line_subpixel_mask = line_subpixel_scale - 1, //----line_subpixel_mask
line_max_coord = (1 << 28) - 1, //----line_max_coord
line_max_length = 1 << (line_subpixel_shift + 10) //----line_max_length
};
//-------------------------------------------------------------------------
enum line_mr_subpixel_scale_e
{
line_mr_subpixel_shift = 4, //----line_mr_subpixel_shift
line_mr_subpixel_scale = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_scale
line_mr_subpixel_mask = line_mr_subpixel_scale - 1 //----line_mr_subpixel_mask
};
//------------------------------------------------------------------line_mr
AGG_INLINE int line_mr(int x)
{
return x >> (line_subpixel_shift - line_mr_subpixel_shift);
}
//-------------------------------------------------------------------line_hr
AGG_INLINE int line_hr(int x)
{
return x << (line_subpixel_shift - line_mr_subpixel_shift);
}
//---------------------------------------------------------------line_dbl_hr
AGG_INLINE int line_dbl_hr(int x)
{
return x * line_subpixel_scale;
}
//---------------------------------------------------------------line_coord
struct line_coord
{
AGG_INLINE static int conv(double x)
{
return iround(x * line_subpixel_scale);
}
};
//-----------------------------------------------------------line_coord_sat
struct line_coord_sat
{
AGG_INLINE static int conv(double x)
{
return saturation<line_max_coord>::iround(x * line_subpixel_scale);
}
};
//==========================================================line_parameters
struct line_parameters
{
//---------------------------------------------------------------------
line_parameters() {}
line_parameters(int x1_, int y1_, int x2_, int y2_, int len_) :
x1(x1_), y1(y1_), x2(x2_), y2(y2_),
dx(std::abs(x2_ - x1_)),
dy(std::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];
}
//---------------------------------------------------------------------
void divide(line_parameters& lp1, line_parameters& lp2) const
{
int xmid = (x1 + x2) >> 1;
int ymid = (y1 + y2) >> 1;
int len2 = len >> 1;
lp1 = *this;
lp2 = *this;
lp1.x2 = xmid;
lp1.y2 = ymid;
lp1.len = len2;
lp1.dx = std::abs(lp1.x2 - lp1.x1);
lp1.dy = std::abs(lp1.y2 - lp1.y1);
lp2.x1 = xmid;
lp2.y1 = ymid;
lp2.len = len2;
lp2.dx = std::abs(lp2.x2 - lp2.x1);
lp2.dy = std::abs(lp2.y2 - lp2.y1);
}
//---------------------------------------------------------------------
int x1, y1, x2, y2, dx, dy, sx, sy;
bool vertical;
int inc;
int len;
int octant;
//---------------------------------------------------------------------
static const int8u s_orthogonal_quadrant[8];
static const int8u s_diagonal_quadrant[8];
};
// See Implementation agg_line_aa_basics.cpp
//----------------------------------------------------------------bisectrix
void bisectrix(const line_parameters& l1,
const line_parameters& l2,
int* x, int* y);
//-------------------------------------------fix_degenerate_bisectrix_start
void inline fix_degenerate_bisectrix_start(const line_parameters& lp,
int* x, int* y)
{
int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) -
double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
if(d < line_subpixel_scale/2)
{
*x = lp.x1 + (lp.y2 - lp.y1);
*y = lp.y1 - (lp.x2 - lp.x1);
}
}
//---------------------------------------------fix_degenerate_bisectrix_end
void inline fix_degenerate_bisectrix_end(const line_parameters& lp,
int* x, int* y)
{
int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) -
double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
if(d < line_subpixel_scale/2)
{
*x = lp.x2 + (lp.y2 - lp.y1);
*y = lp.y2 - (lp.x2 - lp.x1);
}
}
} }
//-------------------------------------------------------------------line_hr
AGG_INLINE int line_hr(int x)
{
return x << (line_subpixel_shift - line_mr_subpixel_shift);
}
//---------------------------------------------------------------line_dbl_hr
AGG_INLINE int line_dbl_hr(int x)
{
return x * line_subpixel_scale;
}
//---------------------------------------------------------------line_coord
struct line_coord
{
AGG_INLINE static int conv(double x) { return iround(x * line_subpixel_scale); }
};
//-----------------------------------------------------------line_coord_sat
struct line_coord_sat
{
AGG_INLINE static int conv(double x) { return saturation<line_max_coord>::iround(x * line_subpixel_scale); }
};
//==========================================================line_parameters
struct line_parameters
{
//---------------------------------------------------------------------
line_parameters() {}
line_parameters(int x1_, int y1_, int x2_, int y2_, int len_)
: x1(x1_)
, y1(y1_)
, x2(x2_)
, y2(y2_)
, dx(std::abs(x2_ - x1_))
, dy(std::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];
}
//---------------------------------------------------------------------
void divide(line_parameters& lp1, line_parameters& lp2) const
{
int xmid = (x1 + x2) >> 1;
int ymid = (y1 + y2) >> 1;
int len2 = len >> 1;
lp1 = *this;
lp2 = *this;
lp1.x2 = xmid;
lp1.y2 = ymid;
lp1.len = len2;
lp1.dx = std::abs(lp1.x2 - lp1.x1);
lp1.dy = std::abs(lp1.y2 - lp1.y1);
lp2.x1 = xmid;
lp2.y1 = ymid;
lp2.len = len2;
lp2.dx = std::abs(lp2.x2 - lp2.x1);
lp2.dy = std::abs(lp2.y2 - lp2.y1);
}
//---------------------------------------------------------------------
int x1, y1, x2, y2, dx, dy, sx, sy;
bool vertical;
int inc;
int len;
int octant;
//---------------------------------------------------------------------
static const int8u s_orthogonal_quadrant[8];
static const int8u s_diagonal_quadrant[8];
};
// See Implementation agg_line_aa_basics.cpp
//----------------------------------------------------------------bisectrix
void bisectrix(const line_parameters& l1, const line_parameters& l2, int* x, int* y);
//-------------------------------------------fix_degenerate_bisectrix_start
void inline fix_degenerate_bisectrix_start(const line_parameters& lp, int* x, int* y)
{
int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) - double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
if (d < line_subpixel_scale / 2)
{
*x = lp.x1 + (lp.y2 - lp.y1);
*y = lp.y1 - (lp.x2 - lp.x1);
}
}
//---------------------------------------------fix_degenerate_bisectrix_end
void inline fix_degenerate_bisectrix_end(const line_parameters& lp, int* x, int* y)
{
int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) - double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
if (d < line_subpixel_scale / 2)
{
*x = lp.x2 + (lp.y2 - lp.y1);
*y = lp.y2 - (lp.x2 - lp.x1);
}
}
} // namespace agg
#endif #endif

View file

@ -22,251 +22,236 @@
#include <cmath> #include <cmath>
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//------------------------------------------------------vertex_dist_epsilon
// Coinciding points maximal distance (Epsilon)
const double vertex_dist_epsilon = 1e-5;
//-----------------------------------------------------intersection_epsilon
// See calc_intersection
const double intersection_epsilon = 1.0e-30;
//------------------------------------------------------------cross_product
AGG_INLINE double cross_product(double x1, double y1, double x2, double y2, double x, double y)
{ {
return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
}
//------------------------------------------------------vertex_dist_epsilon //--------------------------------------------------------point_in_triangle
// Coinciding points maximal distance (Epsilon) AGG_INLINE bool point_in_triangle(double x1, double y1, double x2, double y2, double x3, double y3, double x, double y)
const double vertex_dist_epsilon = 1e-5; {
bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0;
bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0;
bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0;
return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
}
//-----------------------------------------------------intersection_epsilon //-----------------------------------------------------------calc_distance
// See calc_intersection AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2)
const double intersection_epsilon = 1.0e-30; {
double dx = x2 - x1;
double dy = y2 - y1;
return sqrt(dx * dx + dy * dy);
}
//------------------------------------------------------------cross_product //--------------------------------------------------------calc_sq_distance
AGG_INLINE double cross_product(double x1, double y1, AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2)
double x2, double y2, {
double x, double y) double dx = x2 - x1;
double dy = y2 - y1;
return dx * dx + dy * dy;
}
//------------------------------------------------calc_line_point_distance
AGG_INLINE double calc_line_point_distance(double x1, double y1, double x2, double y2, double x, double y)
{
double dx = x2 - x1;
double dy = y2 - y1;
double d = sqrt(dx * dx + dy * dy);
if (d < vertex_dist_epsilon)
{ {
return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1); return calc_distance(x1, y1, x, y);
}
return ((x - x2) * dy - (y - y2) * dx) / d;
}
//-------------------------------------------------------calc_line_point_u
AGG_INLINE double calc_segment_point_u(double x1, double y1, double x2, double y2, double x, double y)
{
double dx = x2 - x1;
double dy = y2 - y1;
if (dx == 0 && dy == 0)
{
return 0;
} }
//--------------------------------------------------------point_in_triangle double pdx = x - x1;
AGG_INLINE bool point_in_triangle(double x1, double y1, double pdy = y - y1;
double x2, double y2,
double x3, double y3,
double x, double y)
{
bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0;
bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0;
bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0;
return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
}
//-----------------------------------------------------------calc_distance return (pdx * dx + pdy * dy) / (dx * dx + dy * dy);
AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2) }
{
double dx = x2-x1;
double dy = y2-y1;
return sqrt(dx * dx + dy * dy);
}
//--------------------------------------------------------calc_sq_distance //---------------------------------------------calc_line_point_sq_distance
AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2) AGG_INLINE double
calc_segment_point_sq_distance(double x1, double y1, double x2, double y2, double x, double y, double u)
{
if (u <= 0)
{ {
double dx = x2-x1; return calc_sq_distance(x, y, x1, y1);
double dy = y2-y1;
return dx * dx + dy * dy;
} }
else if (u >= 1)
//------------------------------------------------calc_line_point_distance
AGG_INLINE double calc_line_point_distance(double x1, double y1,
double x2, double y2,
double x, double y)
{ {
double dx = x2-x1; return calc_sq_distance(x, y, x2, y2);
double dy = y2-y1; }
double d = sqrt(dx * dx + dy * dy); return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1));
if(d < vertex_dist_epsilon) }
//---------------------------------------------calc_line_point_sq_distance
AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, double x2, double y2, double x, double y)
{
return calc_segment_point_sq_distance(x1, y1, x2, y2, x, y, calc_segment_point_u(x1, y1, x2, y2, x, y));
}
//-------------------------------------------------------calc_intersection
AGG_INLINE bool calc_intersection(double ax,
double ay,
double bx,
double by,
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 (std::fabs(den) < intersection_epsilon)
return false;
double r = num / den;
*x = ax + r * (bx - ax);
*y = ay + r * (by - ay);
return true;
}
//-----------------------------------------------------intersection_exists
AGG_INLINE bool
intersection_exists(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
{
// It's less expensive but you can't control the
// boundary conditions: Less or LessEqual
double dx1 = x2 - x1;
double dy1 = y2 - y1;
double dx2 = x4 - x3;
double dy2 = y4 - y3;
return ((x3 - x2) * dy1 - (y3 - y2) * dx1 < 0.0) != ((x4 - x2) * dy1 - (y4 - y2) * dx1 < 0.0) &&
((x1 - x4) * dy2 - (y1 - y4) * dx2 < 0.0) != ((x2 - x4) * dy2 - (y2 - y4) * dx2 < 0.0);
// It's is more expensive but more flexible
// in terms of boundary conditions.
//--------------------
// double den = (x2-x1) * (y4-y3) - (y2-y1) * (x4-x3);
// if(std::fabs(den) < intersection_epsilon) return false;
// double nom1 = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3);
// double nom2 = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3);
// double ua = nom1 / den;
// double ub = nom2 / den;
// return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0;
}
//--------------------------------------------------------calc_orthogonal
AGG_INLINE void calc_orthogonal(double thickness, double x1, double y1, double x2, double y2, double* x, double* y)
{
double dx = x2 - x1;
double dy = y2 - y1;
double d = sqrt(dx * dx + dy * dy);
*x = thickness * dy / d;
*y = -thickness * dx / d;
}
//--------------------------------------------------------dilate_triangle
AGG_INLINE void
dilate_triangle(double x1, double y1, double x2, double y2, double x3, double y3, double* x, double* y, double d)
{
double dx1 = 0.0;
double dy1 = 0.0;
double dx2 = 0.0;
double dy2 = 0.0;
double dx3 = 0.0;
double dy3 = 0.0;
double loc = cross_product(x1, y1, x2, y2, x3, y3);
if (std::fabs(loc) > intersection_epsilon)
{
if (cross_product(x1, y1, x2, y2, x3, y3) > 0.0)
{ {
return calc_distance(x1, y1, x, y); d = -d;
} }
return ((x - x2) * dy - (y - y2) * dx) / 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_line_point_u //------------------------------------------------------calc_triangle_area
AGG_INLINE double calc_segment_point_u(double x1, double y1, AGG_INLINE double calc_triangle_area(double x1, double y1, double x2, double y2, double x3, double y3)
double x2, double y2, {
double x, double y) return (x1 * y2 - x2 * y1 + x2 * y3 - x3 * y2 + x3 * y1 - x1 * y3) * 0.5;
}
//-------------------------------------------------------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++)
{ {
double dx = x2 - x1; const typename Storage::value_type& v = st[i];
double dy = y2 - y1; sum += x * v.y - y * v.x;
x = v.x;
if(dx == 0 && dy == 0) y = v.y;
{
return 0;
}
double pdx = x - x1;
double pdy = y - y1;
return (pdx * dx + pdy * dy) / (dx * dx + dy * dy);
} }
return (sum + x * ys - y * xs) * 0.5;
}
//---------------------------------------------calc_line_point_sq_distance //------------------------------------------------------------------------
AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, // Tables for fast sqrt
double x2, double y2, extern int16u g_sqrt_table[1024];
double x, double y, extern int8 g_elder_bit_table[256];
double u)
{
if(u <= 0)
{
return calc_sq_distance(x, y, x1, y1);
}
else
if(u >= 1)
{
return calc_sq_distance(x, y, x2, y2);
}
return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1));
}
//---------------------------------------------calc_line_point_sq_distance //---------------------------------------------------------------fast_sqrt
AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, // Fast integer Sqrt - really fast: no cycles, divisions or multiplications
double x2, double y2, #if defined(_MSC_VER)
double x, double y) #pragma warning(push)
{ #pragma warning(disable: 4035) // Disable warning "no return value"
return #endif
calc_segment_point_sq_distance( AGG_INLINE unsigned fast_sqrt(unsigned val)
x1, y1, x2, y2, x, y, {
calc_segment_point_u(x1, y1, x2, y2, x, y)); #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
//-------------------------------------------------------calc_intersection // significant bit of the value. For other processors
AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by, //(and maybe compilers) the pure C "#else" section is used.
double cx, double cy, double dx, double dy, __asm {
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(std::fabs(den) < intersection_epsilon) return false;
double r = num / den;
*x = ax + r * (bx-ax);
*y = ay + r * (by-ay);
return true;
}
//-----------------------------------------------------intersection_exists
AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2,
double x3, double y3, double x4, double y4)
{
// It's less expensive but you can't control the
// boundary conditions: Less or LessEqual
double dx1 = x2 - x1;
double dy1 = y2 - y1;
double dx2 = x4 - x3;
double dy2 = y4 - y3;
return ((x3 - x2) * dy1 - (y3 - y2) * dx1 < 0.0) !=
((x4 - x2) * dy1 - (y4 - y2) * dx1 < 0.0) &&
((x1 - x4) * dy2 - (y1 - y4) * dx2 < 0.0) !=
((x2 - x4) * dy2 - (y2 - y4) * dx2 < 0.0);
// It's is more expensive but more flexible
// in terms of boundary conditions.
//--------------------
//double den = (x2-x1) * (y4-y3) - (y2-y1) * (x4-x3);
//if(std::fabs(den) < intersection_epsilon) return false;
//double nom1 = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3);
//double nom2 = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3);
//double ua = nom1 / den;
//double ub = nom2 / den;
//return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0;
}
//--------------------------------------------------------calc_orthogonal
AGG_INLINE void calc_orthogonal(double thickness,
double x1, double y1,
double x2, double y2,
double* x, double* y)
{
double dx = x2 - x1;
double dy = y2 - y1;
double d = sqrt(dx*dx + dy*dy);
*x = thickness * dy / d;
*y = -thickness * dx / d;
}
//--------------------------------------------------------dilate_triangle
AGG_INLINE void dilate_triangle(double x1, double y1,
double x2, double y2,
double x3, double y3,
double *x, double* y,
double d)
{
double dx1=0.0;
double dy1=0.0;
double dx2=0.0;
double dy2=0.0;
double dx3=0.0;
double dy3=0.0;
double loc = cross_product(x1, y1, x2, y2, x3, y3);
if(std::fabs(loc) > intersection_epsilon)
{
if(cross_product(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_triangle_area
AGG_INLINE double calc_triangle_area(double x1, double y1,
double x2, double y2,
double x3, double y3)
{
return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5;
}
//-------------------------------------------------------calc_polygon_area
template<class Storage> double calc_polygon_area(const Storage& st)
{
unsigned i;
double sum = 0.0;
double x = st[0].x;
double y = st[0].y;
double xs = x;
double ys = y;
for(i = 1; i < st.size(); i++)
{
const typename Storage::value_type& v = st[i];
sum += x * v.y - y * v.x;
x = v.x;
y = v.y;
}
return (sum + x * ys - y * xs) * 0.5;
}
//------------------------------------------------------------------------
// Tables for fast sqrt
extern int16u g_sqrt_table[1024];
extern int8 g_elder_bit_table[256];
//---------------------------------------------------------------fast_sqrt
//Fast integer Sqrt - really fast: no cycles, divisions or multiplications
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4035) //Disable warning "no return value"
#endif
AGG_INLINE unsigned fast_sqrt(unsigned val)
{
#if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM)
//For Ix86 family processors this assembler code is used.
//The key command here is bsr - determination the number of the most
//significant bit of the value. For other processors
//(and maybe compilers) the pure C "#else" section is used.
__asm
{
mov ebx, val mov ebx, val
mov edx, 11 mov edx, 11
bsr ecx, ebx bsr ecx, ebx
@ -282,156 +267,153 @@ namespace agg
mov ax, g_sqrt_table[ebx*2] mov ax, g_sqrt_table[ebx*2]
mov ecx, edx mov ecx, edx
shr eax, cl shr eax, cl
} }
#else #else
//This code is actually pure C and portable to most // This code is actually pure C and portable to most
//arcitectures including 64bit ones. // arcitectures including 64bit ones.
unsigned t = val; unsigned t = val;
int bit=0; int bit = 0;
unsigned shift = 11; unsigned shift = 11;
//The following piece of code is just an emulation of the // The following piece of code is just an emulation of the
//Ix86 assembler command "bsr" (see above). However on old // Ix86 assembler command "bsr" (see above). However on old
//Intels (like Intel MMX 233MHz) this code is about twice // Intels (like Intel MMX 233MHz) this code is about twice
//faster (sic!) then just one "bsr". On PIII and PIV the // faster (sic!) then just one "bsr". On PIII and PIV the
//bsr is optimized quite well. // bsr is optimized quite well.
bit = t >> 24; bit = t >> 24;
if(bit) if (bit)
{
bit = g_elder_bit_table[bit] + 24;
}
else
{
bit = (t >> 16) & 0xFF;
if (bit)
{ {
bit = g_elder_bit_table[bit] + 24; bit = g_elder_bit_table[bit] + 16;
} }
else else
{ {
bit = (t >> 16) & 0xFF; bit = (t >> 8) & 0xFF;
if(bit) if (bit)
{ {
bit = g_elder_bit_table[bit] + 16; bit = g_elder_bit_table[bit] + 8;
} }
else else
{ {
bit = (t >> 8) & 0xFF; bit = g_elder_bit_table[t];
if(bit)
{
bit = g_elder_bit_table[bit] + 8;
}
else
{
bit = g_elder_bit_table[t];
}
} }
} }
//This code calculates the sqrt.
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
// This code calculates the sqrt.
bit -= 9;
if (bit > 0)
//--------------------------------------------------------------------besj
// Function BESJ calculates Bessel function of first kind of order n
// Arguments:
// n - an integer (>=0), the order
// x - value at which the Bessel function is required
//--------------------
// C++ Mathematical Library
// Convereted from equivalent FORTRAN library
// Converetd by Gareth Walker for use by course 392 computational project
// All functions tested and yield the same results as the corresponding
// FORTRAN versions.
//
// If you have any problems using these functions please report them to
// M.Muldoon@UMIST.ac.uk
//
// Documentation available on the web
// http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html
// Version 1.0 8/98
// 29 October, 1999
//--------------------
// Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com)
//------------------------------------------------------------------------
inline double besj(double x, int n)
{ {
if(n < 0) bit = (bit >> 1) + (bit & 1);
{ shift -= bit;
return 0; val >>= (bit << 1);
} }
double d = 1E-6; return g_sqrt_table[val] >> shift;
double b = 0; #endif
if(std::fabs(x) <= d) }
{ #if defined(_MSC_VER)
if(n != 0) return 0; #pragma warning(pop)
return 1; #endif
}
double b1 = 0; // b1 is the value from the previous iteration
// Set up a starting order for recurrence
int m1 = (int)fabs(x) + 6;
if(std::fabs(x) > 5)
{
m1 = (int)(std::fabs(1.4 * x + 60 / x));
}
int m2 = (int)(n + 2 + std::fabs(x) / 4);
if (m1 > m2)
{
m2 = m1;
}
// Apply recurrence down from curent max order //--------------------------------------------------------------------besj
for(;;) // Function BESJ calculates Bessel function of first kind of order n
// Arguments:
// n - an integer (>=0), the order
// x - value at which the Bessel function is required
//--------------------
// C++ Mathematical Library
// Convereted from equivalent FORTRAN library
// Converetd by Gareth Walker for use by course 392 computational project
// All functions tested and yield the same results as the corresponding
// FORTRAN versions.
//
// If you have any problems using these functions please report them to
// M.Muldoon@UMIST.ac.uk
//
// Documentation available on the web
// http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html
// Version 1.0 8/98
// 29 October, 1999
//--------------------
// Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com)
//------------------------------------------------------------------------
inline double besj(double x, int n)
{
if (n < 0)
{
return 0;
}
double d = 1E-6;
double b = 0;
if (std::fabs(x) <= d)
{
if (n != 0)
return 0;
return 1;
}
double b1 = 0; // b1 is the value from the previous iteration
// Set up a starting order for recurrence
int m1 = (int)fabs(x) + 6;
if (std::fabs(x) > 5)
{
m1 = (int)(std::fabs(1.4 * x + 60 / x));
}
int m2 = (int)(n + 2 + std::fabs(x) / 4);
if (m1 > m2)
{
m2 = m1;
}
// Apply recurrence down from curent max order
for (;;)
{
double c3 = 0;
double c2 = 1E-30;
double c4 = 0;
int m8 = 1;
if (m2 / 2 * 2 == m2)
{ {
double c3 = 0; m8 = -1;
double c2 = 1E-30; }
double c4 = 0; int imax = m2 - 2;
int m8 = 1; for (int i = 1; i <= imax; i++)
if (m2 / 2 * 2 == m2) {
{ double c6 = 2 * (m2 - i) * c2 / x - c3;
m8 = -1; c3 = c2;
} c2 = c6;
int imax = m2 - 2; if (m2 - i - 1 == n)
for (int i = 1; i <= imax; i++)
{
double c6 = 2 * (m2 - i) * c2 / x - c3;
c3 = c2;
c2 = c6;
if(m2 - i - 1 == n)
{
b = c6;
}
m8 = -1 * m8;
if (m8 > 0)
{
c4 = c4 + 2 * c6;
}
}
double c6 = 2 * c2 / x - c3;
if(n == 0)
{ {
b = c6; b = c6;
} }
c4 += c6; m8 = -1 * m8;
b /= c4; if (m8 > 0)
if(std::fabs(b - b1) < d)
{ {
return b; c4 = c4 + 2 * c6;
} }
b1 = b;
m2 += 3;
} }
double c6 = 2 * c2 / x - c3;
if (n == 0)
{
b = c6;
}
c4 += c6;
b /= c4;
if (std::fabs(b - b1) < d)
{
return b;
}
b1 = b;
m2 += 3;
} }
} }
} // namespace agg
#endif #endif

View file

@ -23,254 +23,236 @@
#include "agg_math.h" #include "agg_math.h"
#include "agg_vertex_sequence.h" #include "agg_vertex_sequence.h"
namespace agg namespace agg {
//-------------------------------------------------------------line_cap_e
enum line_cap_e { butt_cap, square_cap, round_cap };
//------------------------------------------------------------line_join_e
enum line_join_e { miter_join = 0, miter_join_revert = 1, round_join = 2, bevel_join = 3, miter_join_round = 4 };
//-----------------------------------------------------------inner_join_e
enum inner_join_e { inner_bevel, inner_miter, inner_jag, inner_round };
//------------------------------------------------------------math_stroke
template<class VertexConsumer>
class math_stroke
{ {
//-------------------------------------------------------------line_cap_e public:
enum line_cap_e typedef typename VertexConsumer::value_type coord_type;
{
butt_cap, math_stroke();
square_cap,
round_cap void line_cap(line_cap_e lc) { m_line_cap = lc; }
}; void line_join(line_join_e lj) { m_line_join = lj; }
void inner_join(inner_join_e ij) { m_inner_join = ij; }
//------------------------------------------------------------line_join_e
enum line_join_e line_cap_e line_cap() const { return m_line_cap; }
{ line_join_e line_join() const { return m_line_join; }
miter_join = 0, inner_join_e inner_join() const { return m_inner_join; }
miter_join_revert = 1,
round_join = 2, void width(double w);
bevel_join = 3, void miter_limit(double ml) { m_miter_limit = ml; }
miter_join_round = 4 void miter_limit_theta(double t);
}; void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
void approximation_scale(double as) { m_approx_scale = as; }
//-----------------------------------------------------------inner_join_e double width() const { return m_width * 2.0; }
enum inner_join_e double miter_limit() const { return m_miter_limit; }
{ double inner_miter_limit() const { return m_inner_miter_limit; }
inner_bevel, double approximation_scale() const { return m_approx_scale; }
inner_miter,
inner_jag, void calc_cap(VertexConsumer& vc, const vertex_dist& v0, const vertex_dist& v1, double len);
inner_round
}; void calc_join(VertexConsumer& vc,
const vertex_dist& v0,
//------------------------------------------------------------math_stroke const vertex_dist& v1,
template<class VertexConsumer> class math_stroke const vertex_dist& v2,
{ double len1,
public: double len2);
typedef typename VertexConsumer::value_type coord_type;
private:
math_stroke(); AGG_INLINE void add_vertex(VertexConsumer& vc, double x, double y) { vc.add(coord_type(x, y)); }
void line_cap(line_cap_e lc) { m_line_cap = lc; } void calc_arc(VertexConsumer& vc, double x, double y, double dx1, double dy1, double dx2, double dy2);
void line_join(line_join_e lj) { m_line_join = lj; }
void inner_join(inner_join_e ij) { m_inner_join = ij; } void calc_miter(VertexConsumer& vc,
const vertex_dist& v0,
line_cap_e line_cap() const { return m_line_cap; } const vertex_dist& v1,
line_join_e line_join() const { return m_line_join; } const vertex_dist& v2,
inner_join_e inner_join() const { return m_inner_join; } double dx1,
double dy1,
void width(double w); double dx2,
void miter_limit(double ml) { m_miter_limit = ml; } double dy2,
void miter_limit_theta(double t); line_join_e lj,
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; } double mlimit,
void approximation_scale(double as) { m_approx_scale = as; } double dbevel);
double width() const { return m_width * 2.0; } double m_width;
double miter_limit() const { return m_miter_limit; } double m_width_abs;
double inner_miter_limit() const { return m_inner_miter_limit; } double m_width_eps;
double approximation_scale() const { return m_approx_scale; } int m_width_sign;
double m_miter_limit;
void calc_cap(VertexConsumer& vc, double m_inner_miter_limit;
const vertex_dist& v0, double m_approx_scale;
const vertex_dist& v1, line_cap_e m_line_cap;
double len); line_join_e m_line_join;
inner_join_e m_inner_join;
void calc_join(VertexConsumer& vc, };
const vertex_dist& v0,
const vertex_dist& v1, //-----------------------------------------------------------------------
const vertex_dist& v2, template<class VC>
double len1, math_stroke<VC>::math_stroke()
double len2); : m_width(0.5)
, m_width_abs(0.5)
private: , m_width_eps(0.5 / 1024.0)
AGG_INLINE void add_vertex(VertexConsumer& vc, double x, double y) , m_width_sign(1)
{ , m_miter_limit(4.0)
vc.add(coord_type(x, y)); , m_inner_miter_limit(1.01)
} , m_approx_scale(1.0)
, m_line_cap(butt_cap)
void calc_arc(VertexConsumer& vc, , m_line_join(miter_join)
double x, double y, , m_inner_join(inner_miter)
double dx1, double dy1, {}
double dx2, double dy2);
//-----------------------------------------------------------------------
void calc_miter(VertexConsumer& vc, template<class VC>
const vertex_dist& v0, void math_stroke<VC>::width(double w)
const vertex_dist& v1, {
const vertex_dist& v2, m_width = w * 0.5;
double dx1, double dy1, if (m_width < 0)
double dx2, double dy2,
line_join_e lj,
double mlimit,
double dbevel);
double m_width;
double m_width_abs;
double m_width_eps;
int m_width_sign;
double m_miter_limit;
double m_inner_miter_limit;
double m_approx_scale;
line_cap_e m_line_cap;
line_join_e m_line_join;
inner_join_e m_inner_join;
};
//-----------------------------------------------------------------------
template<class VC> math_stroke<VC>::math_stroke() :
m_width(0.5),
m_width_abs(0.5),
m_width_eps(0.5/1024.0),
m_width_sign(1),
m_miter_limit(4.0),
m_inner_miter_limit(1.01),
m_approx_scale(1.0),
m_line_cap(butt_cap),
m_line_join(miter_join),
m_inner_join(inner_miter)
{ {
m_width_abs = -m_width;
m_width_sign = -1;
} }
else
//-----------------------------------------------------------------------
template<class VC> void math_stroke<VC>::width(double w)
{ {
m_width = w * 0.5; m_width_abs = m_width;
if(m_width < 0) m_width_sign = 1;
{
m_width_abs = -m_width;
m_width_sign = -1;
}
else
{
m_width_abs = m_width;
m_width_sign = 1;
}
m_width_eps = m_width / 1024.0;
} }
m_width_eps = m_width / 1024.0;
}
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
template<class VC> void math_stroke<VC>::miter_limit_theta(double t) template<class VC>
void math_stroke<VC>::miter_limit_theta(double t)
{
m_miter_limit = 1.0 / std::sin(t * 0.5);
}
//-----------------------------------------------------------------------
template<class VC>
void math_stroke<VC>::calc_arc(VC& vc, double x, double y, double dx1, double dy1, double dx2, double dy2)
{
double a1 = std::atan2(dy1 * m_width_sign, dx1 * m_width_sign);
double a2 = std::atan2(dy2 * m_width_sign, dx2 * m_width_sign);
double da = a1 - a2;
int i, n;
da = std::acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
add_vertex(vc, x + dx1, y + dy1);
if (m_width_sign > 0)
{ {
m_miter_limit = 1.0 / std::sin(t * 0.5) ; if (a1 > a2)
} a2 += 2 * pi;
n = int((a2 - a1) / da);
//----------------------------------------------------------------------- da = (a2 - a1) / (n + 1);
template<class VC> a1 += da;
void math_stroke<VC>::calc_arc(VC& vc, for (i = 0; i < n; i++)
double x, double y,
double dx1, double dy1,
double dx2, double dy2)
{
double a1 = std::atan2(dy1 * m_width_sign, dx1 * m_width_sign);
double a2 = std::atan2(dy2 * m_width_sign, dx2 * m_width_sign);
double da = a1 - a2;
int i, n;
da = std::acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
add_vertex(vc, x + dx1, y + dy1);
if(m_width_sign > 0)
{ {
if(a1 > a2) a2 += 2 * pi; add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width);
n = int((a2 - a1) / da);
da = (a2 - a1) / (n + 1);
a1 += da; a1 += da;
for(i = 0; i < n; i++)
{
add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width);
a1 += da;
}
} }
else }
else
{
if (a1 < a2)
a2 -= 2 * pi;
n = int((a1 - a2) / da);
da = (a1 - a2) / (n + 1);
a1 -= da;
for (i = 0; i < n; i++)
{ {
if(a1 < a2) a2 -= 2 * pi; add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width);
n = int((a1 - a2) / da);
da = (a1 - a2) / (n + 1);
a1 -= da; a1 -= da;
for(i = 0; i < n; i++)
{
add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width);
a1 -= da;
}
} }
add_vertex(vc, x + dx2, y + dy2); }
add_vertex(vc, x + dx2, y + dy2);
}
//-----------------------------------------------------------------------
template<class VC>
void math_stroke<VC>::calc_miter(VC& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double dx1,
double dy1,
double dx2,
double dy2,
line_join_e lj,
double mlimit,
double dbevel)
{
double xi = v1.x;
double yi = v1.y;
double di = 1;
double lim = m_width_abs * mlimit;
bool miter_limit_exceeded = true; // Assume the worst
bool intersection_failed = true; // Assume the worst
if (calc_intersection(v0.x + dx1,
v0.y - dy1,
v1.x + dx1,
v1.y - dy1,
v1.x + dx2,
v1.y - dy2,
v2.x + dx2,
v2.y - dy2,
&xi,
&yi))
{
// Calculation of the intersection succeeded
//---------------------
di = calc_distance(v1.x, v1.y, xi, yi);
if (di <= lim)
{
// Inside the miter limit
//---------------------
add_vertex(vc, xi, yi);
miter_limit_exceeded = false;
}
intersection_failed = false;
}
else
{
// Calculation of the intersection failed, most probably
// the three points lie one straight line.
// First check if v0 and v2 lie on the opposite sides of vector:
// (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular
// to the line determined by vertices v0 and v1.
// This condition determines whether the next line segments continues
// the previous one or goes back.
//----------------
double x2 = v1.x + dx1;
double y2 = v1.y - dy1;
if ((cross_product(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) ==
(cross_product(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0))
{
// This case means that the next segment continues
// the previous one (straight line)
//-----------------
add_vertex(vc, v1.x + dx1, v1.y - dy1);
miter_limit_exceeded = false;
}
} }
//----------------------------------------------------------------------- if (miter_limit_exceeded)
template<class VC>
void math_stroke<VC>::calc_miter(VC& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double dx1, double dy1,
double dx2, double dy2,
line_join_e lj,
double mlimit,
double dbevel)
{ {
double xi = v1.x; // Miter limit exceeded
double yi = v1.y; //------------------------
double di = 1; switch (lj)
double lim = m_width_abs * mlimit;
bool miter_limit_exceeded = true; // Assume the worst
bool intersection_failed = true; // Assume the worst
if(calc_intersection(v0.x + dx1, v0.y - dy1,
v1.x + dx1, v1.y - dy1,
v1.x + dx2, v1.y - dy2,
v2.x + dx2, v2.y - dy2,
&xi, &yi))
{ {
// Calculation of the intersection succeeded
//---------------------
di = calc_distance(v1.x, v1.y, xi, yi);
if(di <= lim)
{
// Inside the miter limit
//---------------------
add_vertex(vc, xi, yi);
miter_limit_exceeded = false;
}
intersection_failed = false;
}
else
{
// Calculation of the intersection failed, most probably
// the three points lie one straight line.
// First check if v0 and v2 lie on the opposite sides of vector:
// (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular
// to the line determined by vertices v0 and v1.
// This condition determines whether the next line segments continues
// the previous one or goes back.
//----------------
double x2 = v1.x + dx1;
double y2 = v1.y - dy1;
if((cross_product(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) ==
(cross_product(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0))
{
// This case means that the next segment continues
// the previous one (straight line)
//-----------------
add_vertex(vc, v1.x + dx1, v1.y - dy1);
miter_limit_exceeded = false;
}
}
if(miter_limit_exceeded)
{
// Miter limit exceeded
//------------------------
switch(lj)
{
case miter_join_revert: case miter_join_revert:
// For the compatibility with SVG, PDF, etc, // For the compatibility with SVG, PDF, etc,
// we use a simple bevel join instead of // we use a simple bevel join instead of
@ -287,13 +269,11 @@ namespace agg
default: default:
// If no miter-revert, calculate new dx1, dy1, dx2, dy2 // If no miter-revert, calculate new dx1, dy1, dx2, dy2
//---------------- //----------------
if(intersection_failed) if (intersection_failed)
{ {
mlimit *= m_width_sign; mlimit *= m_width_sign;
add_vertex(vc, v1.x + dx1 + dy1 * mlimit, add_vertex(vc, v1.x + dx1 + dy1 * mlimit, v1.y - dy1 + dx1 * mlimit);
v1.y - dy1 + dx1 * mlimit); add_vertex(vc, v1.x + dx2 - dy2 * mlimit, v1.y - dy2 - dx2 * mlimit);
add_vertex(vc, v1.x + dx2 - dy2 * mlimit,
v1.y - dy2 - dx2 * mlimit);
} }
else else
{ {
@ -302,208 +282,196 @@ namespace agg
double x2 = v1.x + dx2; double x2 = v1.x + dx2;
double y2 = v1.y - dy2; double y2 = v1.y - dy2;
di = (lim - dbevel) / (di - dbevel); di = (lim - dbevel) / (di - dbevel);
add_vertex(vc, x1 + (xi - x1) * di, add_vertex(vc, x1 + (xi - x1) * di, y1 + (yi - y1) * di);
y1 + (yi - y1) * di); add_vertex(vc, x2 + (xi - x2) * di, y2 + (yi - y2) * di);
add_vertex(vc, x2 + (xi - x2) * di,
y2 + (yi - y2) * di);
} }
break; break;
}
} }
} }
}
//--------------------------------------------------------stroke_calc_cap //--------------------------------------------------------stroke_calc_cap
template<class VC> template<class VC>
void math_stroke<VC>::calc_cap(VC& vc, void math_stroke<VC>::calc_cap(VC& vc, const vertex_dist& v0, const vertex_dist& v1, double len)
const vertex_dist& v0, {
const vertex_dist& v1, vc.remove_all();
double len)
double dx1 = (v1.y - v0.y) / len;
double dy1 = (v1.x - v0.x) / len;
double dx2 = 0;
double dy2 = 0;
dx1 *= m_width;
dy1 *= m_width;
if (m_line_cap != round_cap)
{ {
vc.remove_all(); if (m_line_cap == square_cap)
double dx1 = (v1.y - v0.y) / len;
double dy1 = (v1.x - v0.x) / len;
double dx2 = 0;
double dy2 = 0;
dx1 *= m_width;
dy1 *= m_width;
if(m_line_cap != round_cap)
{ {
if(m_line_cap == square_cap) dx2 = dy1 * m_width_sign;
dy2 = dx1 * m_width_sign;
}
add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2);
add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2);
}
else
{
double da = std::acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
double a1;
int i;
int n = int(pi / da);
da = pi / (n + 1);
add_vertex(vc, v0.x - dx1, v0.y + dy1);
if (m_width_sign > 0)
{
a1 = std::atan2(dy1, -dx1);
a1 += da;
for (i = 0; i < n; i++)
{ {
dx2 = dy1 * m_width_sign; add_vertex(vc, v0.x + std::cos(a1) * m_width, v0.y + std::sin(a1) * m_width);
dy2 = dx1 * m_width_sign; a1 += da;
} }
add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2);
add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2);
} }
else else
{ {
double da = std::acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2; a1 = std::atan2(-dy1, dx1);
double a1; a1 -= da;
int i; for (i = 0; i < n; i++)
int n = int(pi / da);
da = pi / (n + 1);
add_vertex(vc, v0.x - dx1, v0.y + dy1);
if(m_width_sign > 0)
{ {
a1 = std::atan2(dy1, -dx1); add_vertex(vc, v0.x + std::cos(a1) * m_width, v0.y + std::sin(a1) * m_width);
a1 += da;
for(i = 0; i < n; i++)
{
add_vertex(vc, v0.x + std::cos(a1) * m_width,
v0.y + std::sin(a1) * m_width);
a1 += da;
}
}
else
{
a1 = std::atan2(-dy1, dx1);
a1 -= da; a1 -= da;
for(i = 0; i < n; i++)
{
add_vertex(vc, v0.x + std::cos(a1) * m_width,
v0.y + std::sin(a1) * m_width);
a1 -= da;
}
} }
add_vertex(vc, v0.x + dx1, v0.y - dy1);
} }
add_vertex(vc, v0.x + dx1, v0.y - dy1);
} }
}
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
template<class VC> template<class VC>
void math_stroke<VC>::calc_join(VC& vc, void math_stroke<VC>::calc_join(VC& vc,
const vertex_dist& v0, const vertex_dist& v0,
const vertex_dist& v1, const vertex_dist& v1,
const vertex_dist& v2, const vertex_dist& v2,
double len1, double len1,
double len2) double len2)
{
double dx1 = m_width * (v1.y - v0.y) / len1;
double dy1 = m_width * (v1.x - v0.x) / len1;
double dx2 = m_width * (v2.y - v1.y) / len2;
double dy2 = m_width * (v2.x - v1.x) / len2;
vc.remove_all();
double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y);
if (cp != 0 && (cp > 0) == (m_width > 0) && m_width_abs > 0)
{ {
double dx1 = m_width * (v1.y - v0.y) / len1; // Inner join
double dy1 = m_width * (v1.x - v0.x) / len1; //---------------
double dx2 = m_width * (v2.y - v1.y) / len2; double limit = ((len1 < len2) ? len1 : len2) / m_width_abs;
double dy2 = m_width * (v2.x - v1.x) / len2; if (limit < m_inner_miter_limit)
vc.remove_all();
double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y);
if (cp != 0 && (cp > 0) == (m_width > 0) && m_width_abs > 0)
{ {
// Inner join limit = m_inner_miter_limit;
//--------------- }
double limit = ((len1 < len2) ? len1 : len2) / m_width_abs;
if (limit < m_inner_miter_limit)
{
limit = m_inner_miter_limit;
}
switch(m_inner_join) switch (m_inner_join)
{ {
default: // inner_bevel default: // inner_bevel
add_vertex(vc, v1.x + dx1, v1.y - dy1); add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x + dx2, v1.y - dy2); add_vertex(vc, v1.x + dx2, v1.y - dy2);
break; break;
case inner_miter: case inner_miter:
calc_miter(vc, calc_miter(vc, v0, v1, v2, dx1, dy1, dx2, dy2, miter_join_revert, limit, 0);
v0, v1, v2, dx1, dy1, dx2, dy2,
miter_join_revert,
limit, 0);
break; break;
case inner_jag: case inner_jag:
case inner_round: case inner_round:
cp = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2); cp = (dx1 - dx2) * (dx1 - dx2) + (dy1 - dy2) * (dy1 - dy2);
if(cp < len1 * len1 && cp < len2 * len2) if (cp < len1 * len1 && cp < len2 * len2)
{ {
calc_miter(vc, calc_miter(vc, v0, v1, v2, dx1, dy1, dx2, dy2, miter_join_revert, limit, 0);
v0, v1, v2, dx1, dy1, dx2, dy2,
miter_join_revert,
limit, 0);
} }
else else
{ {
if(m_inner_join == inner_jag) if (m_inner_join == inner_jag)
{ {
add_vertex(vc, v1.x + dx1, v1.y - dy1); add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x, v1.y ); add_vertex(vc, v1.x, v1.y);
add_vertex(vc, v1.x + dx2, v1.y - dy2); add_vertex(vc, v1.x + dx2, v1.y - dy2);
} }
else else
{ {
add_vertex(vc, v1.x + dx1, v1.y - dy1); add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x, v1.y ); add_vertex(vc, v1.x, v1.y);
calc_arc(vc, v1.x, v1.y, dx2, -dy2, dx1, -dy1); calc_arc(vc, v1.x, v1.y, dx2, -dy2, dx1, -dy1);
add_vertex(vc, v1.x, v1.y ); add_vertex(vc, v1.x, v1.y);
add_vertex(vc, v1.x + dx2, v1.y - dy2); add_vertex(vc, v1.x + dx2, v1.y - dy2);
} }
} }
break; break;
}
}
else
{
// Outer join
//---------------
// Calculate the distance between v1 and
// the central point of the bevel line segment
//---------------
double dx = (dx1 + dx2) / 2;
double dy = (dy1 + dy2) / 2;
double dbevel = sqrt(dx * dx + dy * dy);
if (m_line_join == round_join || m_line_join == bevel_join)
{
// This is an optimization that reduces the number of points
// in cases of almost collinear segments. If there's no
// visible difference between bevel and miter joins we'd rather
// use miter join because it adds only one point instead of two.
//
// Here we calculate the middle point between the bevel points
// and then, the distance between v1 and this middle point.
// At outer joins this distance always less than stroke width,
// because it's actually the height of an isosceles triangle of
// v1 and its two bevel points. If the difference between this
// width and this value is small (no visible bevel) we can
// add just one point.
//
// The constant in the expression makes the result approximately
// the same as in round joins and caps. You can safely comment
// out this entire "if".
//-------------------
if (m_approx_scale * (m_width_abs - dbevel) < m_width_eps)
{
if (calc_intersection(v0.x + dx1,
v0.y - dy1,
v1.x + dx1,
v1.y - dy1,
v1.x + dx2,
v1.y - dy2,
v2.x + dx2,
v2.y - dy2,
&dx,
&dy))
{
add_vertex(vc, dx, dy);
}
else
{
add_vertex(vc, v1.x + dx1, v1.y - dy1);
}
return;
} }
} }
else
switch (m_line_join)
{ {
// Outer join
//---------------
// Calculate the distance between v1 and
// the central point of the bevel line segment
//---------------
double dx = (dx1 + dx2) / 2;
double dy = (dy1 + dy2) / 2;
double dbevel = sqrt(dx * dx + dy * dy);
if(m_line_join == round_join || m_line_join == bevel_join)
{
// This is an optimization that reduces the number of points
// in cases of almost collinear segments. If there's no
// visible difference between bevel and miter joins we'd rather
// use miter join because it adds only one point instead of two.
//
// Here we calculate the middle point between the bevel points
// and then, the distance between v1 and this middle point.
// At outer joins this distance always less than stroke width,
// because it's actually the height of an isosceles triangle of
// v1 and its two bevel points. If the difference between this
// width and this value is small (no visible bevel) we can
// add just one point.
//
// The constant in the expression makes the result approximately
// the same as in round joins and caps. You can safely comment
// out this entire "if".
//-------------------
if(m_approx_scale * (m_width_abs - dbevel) < m_width_eps)
{
if(calc_intersection(v0.x + dx1, v0.y - dy1,
v1.x + dx1, v1.y - dy1,
v1.x + dx2, v1.y - dy2,
v2.x + dx2, v2.y - dy2,
&dx, &dy))
{
add_vertex(vc, dx, dy);
}
else
{
add_vertex(vc, v1.x + dx1, v1.y - dy1);
}
return;
}
}
switch(m_line_join)
{
case miter_join: case miter_join:
case miter_join_revert: case miter_join_revert:
case miter_join_round: case miter_join_round:
calc_miter(vc, calc_miter(vc, v0, v1, v2, dx1, dy1, dx2, dy2, m_line_join, m_miter_limit, dbevel);
v0, v1, v2, dx1, dy1, dx2, dy2,
m_line_join,
m_miter_limit,
dbevel);
break; break;
case round_join: case round_join:
@ -514,13 +482,10 @@ namespace agg
add_vertex(vc, v1.x + dx1, v1.y - dy1); add_vertex(vc, v1.x + dx1, v1.y - dy1);
add_vertex(vc, v1.x + dx2, v1.y - dy2); add_vertex(vc, v1.x + dx2, v1.y - dy2);
break; break;
}
} }
} }
} }
} // namespace agg
#endif #endif

View file

@ -17,49 +17,48 @@
#include "agg_math.h" #include "agg_math.h"
namespace agg namespace agg {
template<class VertexSource>
double path_length(VertexSource& vs, unsigned path_id = 0)
{ {
template<class VertexSource> double len = 0.0;
double path_length(VertexSource& vs, unsigned path_id = 0) double start_x = 0.0;
{ double start_y = 0.0;
double len = 0.0; double x1 = 0.0;
double start_x = 0.0; double y1 = 0.0;
double start_y = 0.0; double x2 = 0.0;
double x1 = 0.0; double y2 = 0.0;
double y1 = 0.0; bool first = true;
double x2 = 0.0;
double y2 = 0.0;
bool first = true;
unsigned cmd; unsigned cmd;
vs.rewind(path_id); vs.rewind(path_id);
while(!is_stop(cmd = vs.vertex(&x2, &y2))) while (!is_stop(cmd = vs.vertex(&x2, &y2)))
{
if (is_vertex(cmd))
{ {
if(is_vertex(cmd)) if (first || is_move_to(cmd))
{ {
if(first || is_move_to(cmd)) start_x = x2;
{ start_y = y2;
start_x = x2;
start_y = y2;
}
else
{
len += calc_distance(x1, y1, x2, y2);
}
x1 = x2;
y1 = y2;
first = false;
} }
else else
{ {
if(is_close(cmd) && !first) len += calc_distance(x1, y1, x2, y2);
{ }
len += calc_distance(x1, y1, start_x, start_y); x1 = x2;
} y1 = y2;
first = false;
}
else
{
if (is_close(cmd) && !first)
{
len += calc_distance(x1, y1, start_x, start_y);
} }
} }
return len;
} }
return len;
} }
} // namespace agg
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -19,277 +19,259 @@
#include <cstring> #include <cstring>
#include "agg_array.h" #include "agg_array.h"
namespace agg namespace agg {
//---------------------------------------------------------vertex_integer
template<class T, unsigned CoordShift = 6>
struct vertex_integer
{ {
//---------------------------------------------------------vertex_integer enum path_cmd { cmd_move_to = 0, cmd_line_to = 1, cmd_curve3 = 2, cmd_curve4 = 3 };
template<class T, unsigned CoordShift=6> struct vertex_integer
enum coord_scale_e { coord_shift = CoordShift, coord_scale = 1 << coord_shift };
T x, y;
vertex_integer() {}
vertex_integer(T x_, T y_, unsigned flag)
: x(((x_ << 1) & ~1) | (flag & 1))
, y(((y_ << 1) & ~1) | (flag >> 1))
{}
unsigned vertex(double* x_, double* y_, double dx = 0, double dy = 0, double scale = 1.0) const
{ {
enum path_cmd *x_ = dx + (double(x >> 1) / coord_scale) * scale;
*y_ = dy + (double(y >> 1) / coord_scale) * scale;
switch (((y & 1) << 1) | (x & 1))
{ {
cmd_move_to = 0, case cmd_move_to:
cmd_line_to = 1, return path_cmd_move_to;
cmd_curve3 = 2, case cmd_line_to:
cmd_curve4 = 3 return path_cmd_line_to;
}; case cmd_curve3:
return path_cmd_curve3;
case cmd_curve4:
return path_cmd_curve4;
}
return path_cmd_stop;
}
};
enum coord_scale_e //---------------------------------------------------path_storage_integer
template<class T, unsigned CoordShift = 6>
class path_storage_integer
{
public:
typedef T value_type;
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, double* x, double* y) const { return m_storage[idx].vertex(x, y); }
//--------------------------------------------------------------------
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++)
{ {
coord_shift = CoordShift, memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type));
coord_scale = 1 << coord_shift ptr += sizeof(vertex_integer_type);
}; }
}
T x,y; //--------------------------------------------------------------------
vertex_integer() {} void rewind(unsigned)
vertex_integer(T x_, T y_, unsigned flag) : {
x(((x_ << 1) & ~1) | (flag & 1)), m_vertex_idx = 0;
y(((y_ << 1) & ~1) | (flag >> 1)) {} m_closed = true;
}
unsigned vertex(double* x_, double* y_, //--------------------------------------------------------------------
double dx=0, double dy=0, unsigned vertex(double* x, double* y)
double scale=1.0) const {
if (m_storage.size() < 2 || m_vertex_idx > m_storage.size())
{ {
*x_ = dx + (double(x >> 1) / coord_scale) * scale; *x = 0;
*y_ = dy + (double(y >> 1) / coord_scale) * scale; *y = 0;
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; 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;
}
//--------------------------------------------------------------------
//---------------------------------------------------path_storage_integer rect_d bounding_rect() const
template<class T, unsigned CoordShift=6> class path_storage_integer
{ {
public: rect_d bounds(1e100, 1e100, -1e100, -1e100);
typedef T value_type; if (m_storage.size() == 0)
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)); bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0;
} }
else
//--------------------------------------------------------------------
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, double* x, double* y) const
{
return m_storage[idx].vertex(x, y);
}
//--------------------------------------------------------------------
unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); }
void serialize(int8u* ptr) const
{ {
unsigned i; unsigned i;
for(i = 0; i < m_storage.size(); i++) for (i = 0; i < m_storage.size(); i++)
{ {
memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type)); double x, y;
ptr += sizeof(vertex_integer_type); 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:
void rewind(unsigned) pod_bvector<vertex_integer_type, 6> m_storage;
{ unsigned m_vertex_idx;
m_vertex_idx = 0; bool m_closed;
m_closed = true; };
}
//-------------------------------------------------------------------- //-----------------------------------------serialized_integer_path_adaptor
unsigned vertex(double* x, double* y) template<class T, unsigned CoordShift = 6>
{ class serialized_integer_path_adaptor
if(m_storage.size() < 2 || m_vertex_idx > m_storage.size()) {
{ public:
*x = 0; typedef vertex_integer<T, CoordShift> vertex_integer_type;
*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 serialized_integer_path_adaptor()
{ : m_data(0)
rect_d bounds(1e100, 1e100, -1e100, -1e100); , m_end(0)
if(m_storage.size() == 0) , m_ptr(0)
{ , m_dx(0.0)
bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0; , m_dy(0.0)
} , m_scale(1.0)
else , m_vertices(0)
{ {}
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_bvector<vertex_integer_type, 6> m_storage; serialized_integer_path_adaptor(const int8u* data, unsigned size, double dx, double dy)
unsigned m_vertex_idx; : m_data(data)
bool m_closed; , m_end(data + size)
}; , m_ptr(data)
, m_dx(dx)
, m_dy(dy)
, m_vertices(0)
{}
//--------------------------------------------------------------------
void init(const int8u* data, unsigned size, double dx, double dy, double scale = 1.0)
//-----------------------------------------serialized_integer_path_adaptor
template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor
{ {
public: m_data = data;
typedef vertex_integer<T, CoordShift> vertex_integer_type; m_end = data + size;
m_ptr = data;
m_dx = dx;
m_dy = dy;
m_scale = scale;
m_vertices = 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
serialized_integer_path_adaptor() : void rewind(unsigned)
m_data(0), {
m_end(0), m_ptr = m_data;
m_ptr(0), m_vertices = 0;
m_dx(0.0), }
m_dy(0.0),
m_scale(1.0),
m_vertices(0)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
serialized_integer_path_adaptor(const int8u* data, unsigned size, unsigned vertex(double* x, double* y)
double dx, double dy) : {
m_data(data), if (m_data == 0 || m_ptr > m_end)
m_end(data + size),
m_ptr(data),
m_dx(dx),
m_dy(dy),
m_vertices(0)
{}
//--------------------------------------------------------------------
void init(const int8u* data, unsigned size,
double dx, double dy, double scale=1.0)
{ {
m_data = data; *x = 0;
m_end = data + size; *y = 0;
m_ptr = data; return path_cmd_stop;
m_dx = dx;
m_dy = dy;
m_scale = scale;
m_vertices = 0;
} }
if (m_ptr == m_end)
//--------------------------------------------------------------------
void rewind(unsigned)
{ {
m_ptr = m_data; *x = 0;
m_vertices = 0; *y = 0;
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
if(m_data == 0 || m_ptr > m_end)
{
*x = 0;
*y = 0;
return path_cmd_stop;
}
if(m_ptr == m_end)
{
*x = 0;
*y = 0;
m_ptr += sizeof(vertex_integer_type);
return path_cmd_end_poly | path_flags_close;
}
vertex_integer_type v;
memcpy(&v, m_ptr, sizeof(vertex_integer_type));
unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale);
if(is_move_to(cmd) && m_vertices > 2)
{
*x = 0;
*y = 0;
m_vertices = 0;
return path_cmd_end_poly | path_flags_close;
}
++m_vertices;
m_ptr += sizeof(vertex_integer_type); m_ptr += sizeof(vertex_integer_type);
return cmd; return path_cmd_end_poly | path_flags_close;
} }
private: vertex_integer_type v;
const int8u* m_data; memcpy(&v, m_ptr, sizeof(vertex_integer_type));
const int8u* m_end; unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale);
const int8u* m_ptr; if (is_move_to(cmd) && m_vertices > 2)
double m_dx; {
double m_dy; *x = 0;
double m_scale; *y = 0;
unsigned m_vertices; m_vertices = 0;
}; return path_cmd_end_poly | path_flags_close;
}
++m_vertices;
m_ptr += sizeof(vertex_integer_type);
return cmd;
}
} private:
const int8u* m_data;
const int8u* m_end;
const int8u* m_ptr;
double m_dx;
double m_dy;
double m_scale;
unsigned m_vertices;
};
} // namespace agg
#endif #endif

View file

@ -19,104 +19,90 @@
#include "agg_line_aa_basics.h" #include "agg_line_aa_basics.h"
#include "agg_color_rgba.h" #include "agg_color_rgba.h"
namespace agg {
namespace agg //=======================================================pattern_filter_nn
template<class ColorT>
struct pattern_filter_nn
{ {
typedef ColorT color_type;
static unsigned dilation() { return 0; }
//=======================================================pattern_filter_nn static void AGG_INLINE pixel_low_res(color_type const* const* buf, color_type* p, int x, int y) { *p = buf[y][x]; }
template<class ColorT> struct pattern_filter_nn
static void AGG_INLINE pixel_high_res(color_type const* const* buf, color_type* p, int x, int y)
{ {
typedef ColorT color_type; *p = buf[y >> line_subpixel_shift][x >> line_subpixel_shift];
static unsigned dilation() { return 0; } }
};
static void AGG_INLINE pixel_low_res(color_type const* const* buf, typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8;
color_type* p, int x, int y) typedef pattern_filter_nn<rgba16> pattern_filter_nn_rgba16;
{
*p = buf[y][x];
}
static void AGG_INLINE pixel_high_res(color_type const* const* buf, //===========================================pattern_filter_bilinear_rgba
color_type* p, int x, int y) template<class ColorT>
{ struct pattern_filter_bilinear_rgba
*p = buf[y >> line_subpixel_shift] {
[x >> line_subpixel_shift]; typedef ColorT color_type;
} typedef typename color_type::value_type value_type;
}; typedef typename color_type::calc_type calc_type;
typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8; static unsigned dilation() { return 1; }
typedef pattern_filter_nn<rgba16> pattern_filter_nn_rgba16;
static AGG_INLINE void pixel_low_res(color_type const* const* buf, color_type* p, int x, int y) { *p = buf[y][x]; }
//===========================================pattern_filter_bilinear_rgba static AGG_INLINE void pixel_high_res(color_type const* const* buf, color_type* p, int x, int y)
template<class ColorT> struct pattern_filter_bilinear_rgba
{ {
typedef ColorT color_type; calc_type r, g, b, a;
typedef typename color_type::value_type value_type; r = g = b = a = line_subpixel_scale * line_subpixel_scale / 2;
typedef typename color_type::calc_type calc_type;
calc_type weight;
int x_lr = x >> line_subpixel_shift;
int y_lr = y >> line_subpixel_shift;
static unsigned dilation() { return 1; } x &= line_subpixel_mask;
y &= line_subpixel_mask;
const color_type* ptr = buf[y_lr] + x_lr;
static AGG_INLINE void pixel_low_res(color_type const* const* buf, weight = (line_subpixel_scale - x) * (line_subpixel_scale - y);
color_type* p, int x, int y) r += weight * ptr->r;
{ g += weight * ptr->g;
*p = buf[y][x]; b += weight * ptr->b;
} a += weight * ptr->a;
static AGG_INLINE void pixel_high_res(color_type const* const* buf, ++ptr;
color_type* p, int x, int y)
{
calc_type r, g, b, a;
r = g = b = a = line_subpixel_scale * line_subpixel_scale / 2;
calc_type weight; weight = x * (line_subpixel_scale - y);
int x_lr = x >> line_subpixel_shift; r += weight * ptr->r;
int y_lr = y >> line_subpixel_shift; g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
x &= line_subpixel_mask; ptr = buf[y_lr + 1] + x_lr;
y &= line_subpixel_mask;
const color_type* ptr = buf[y_lr] + x_lr;
weight = (line_subpixel_scale - x) * weight = (line_subpixel_scale - x) * y;
(line_subpixel_scale - y); r += weight * ptr->r;
r += weight * ptr->r; g += weight * ptr->g;
g += weight * ptr->g; b += weight * ptr->b;
b += weight * ptr->b; a += weight * ptr->a;
a += weight * ptr->a;
++ptr; ++ptr;
weight = x * (line_subpixel_scale - y); weight = x * y;
r += weight * ptr->r; r += weight * ptr->r;
g += weight * ptr->g; g += weight * ptr->g;
b += weight * ptr->b; b += weight * ptr->b;
a += weight * ptr->a; a += weight * ptr->a;
ptr = buf[y_lr + 1] + x_lr; p->r = (value_type)(r >> line_subpixel_shift * 2);
p->g = (value_type)(g >> line_subpixel_shift * 2);
p->b = (value_type)(b >> line_subpixel_shift * 2);
p->a = (value_type)(a >> line_subpixel_shift * 2);
}
};
weight = (line_subpixel_scale - x) * y; typedef pattern_filter_bilinear_rgba<rgba8> pattern_filter_bilinear_rgba8;
r += weight * ptr->r; typedef pattern_filter_bilinear_rgba<rgba16> pattern_filter_bilinear_rgba16;
g += weight * ptr->g; } // namespace agg
b += weight * ptr->b;
a += weight * ptr->a;
++ptr;
weight = x * y;
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
p->r = (value_type)(r >> line_subpixel_shift * 2);
p->g = (value_type)(g >> line_subpixel_shift * 2);
p->b = (value_type)(b >> line_subpixel_shift * 2);
p->a = (value_type)(a >> line_subpixel_shift * 2);
}
};
typedef pattern_filter_bilinear_rgba<rgba8> pattern_filter_bilinear_rgba8;
typedef pattern_filter_bilinear_rgba<rgba16> pattern_filter_bilinear_rgba16;
}
#endif #endif

View file

@ -16,225 +16,196 @@
#ifndef AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED #ifndef AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
#define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED #define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
#include <cstring> #include <cstring>
#include "agg_array.h" #include "agg_array.h"
#include "agg_rendering_buffer.h" #include "agg_rendering_buffer.h"
namespace agg {
namespace agg //==================================================pixfmt_amask_adaptor
template<class PixFmt, class AlphaMask>
class pixfmt_amask_adaptor
{ {
//==================================================pixfmt_amask_adaptor public:
template<class PixFmt, class AlphaMask> class pixfmt_amask_adaptor typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::row_data row_data;
typedef AlphaMask amask_type;
typedef typename amask_type::cover_type cover_type;
private:
enum span_extra_tail_e { span_extra_tail = 256 };
void realloc_span(unsigned len)
{ {
public: if (len > m_span.size())
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::row_data row_data;
typedef AlphaMask amask_type;
typedef typename amask_type::cover_type cover_type;
private:
enum span_extra_tail_e { span_extra_tail = 256 };
void realloc_span(unsigned len)
{ {
if(len > m_span.size()) m_span.resize(len + span_extra_tail);
{
m_span.resize(len + span_extra_tail);
}
} }
}
void init_span(unsigned len) void init_span(unsigned len)
{ {
realloc_span(len); realloc_span(len);
memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type)); memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type));
} }
void init_span(unsigned len, const cover_type* covers) void init_span(unsigned len, const cover_type* covers)
{ {
realloc_span(len); realloc_span(len);
memcpy(&m_span[0], covers, len * sizeof(cover_type)); memcpy(&m_span[0], covers, len * sizeof(cover_type));
} }
public:
pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask)
: m_pixf(&pixf)
, m_mask(&mask)
, m_span()
{}
public: void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; }
pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) : void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; }
m_pixf(&pixf), m_mask(&mask), m_span()
{}
void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; } //--------------------------------------------------------------------
void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; } template<class PixFmt2>
bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2)
{
return m_pixf->attach(pixf, x1, y1, x2, y2);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
template<class PixFmt2> unsigned width() const { return m_pixf->width(); }
bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2) unsigned height() const { return m_pixf->height(); }
{
return m_pixf->attach(pixf, x1, y1, x2, y2);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
unsigned width() const { return m_pixf->width(); } color_type pixel(int x, int y) { return m_pixf->pixel(x, y); }
unsigned height() const { return m_pixf->height(); }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
color_type pixel(int x, int y) void copy_pixel(int x, int y, const color_type& c) { m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y)); }
{
return m_pixf->pixel(x, y);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c) void blend_pixel(int x, int y, const color_type& c, cover_type cover)
{ {
m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y)); m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover));
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, cover_type cover) void copy_hline(int x, int y, unsigned len, const color_type& c)
{ {
m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover)); realloc_span(len);
} m_mask->fill_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_hline(int x, int y, void blend_hline(int x, int y, unsigned len, const color_type& c, cover_type cover)
unsigned len, {
const color_type& c) init_span(len);
{ m_mask->combine_hspan(x, y, &m_span[0], len);
realloc_span(len); m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
m_mask->fill_hspan(x, y, &m_span[0], len); }
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_hline(int x, int y, void copy_vline(int x, int y, unsigned len, const color_type& c)
unsigned len, {
const color_type& c, realloc_span(len);
cover_type cover) m_mask->fill_vspan(x, y, &m_span[0], len);
{ m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
init_span(len); }
m_mask->combine_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_vline(int x, int y, void blend_vline(int x, int y, unsigned len, const color_type& c, cover_type cover)
unsigned len, {
const color_type& c) init_span(len);
{ m_mask->combine_vspan(x, y, &m_span[0], len);
realloc_span(len); m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
m_mask->fill_vspan(x, y, &m_span[0], len); }
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_vline(int x, int y, void copy_from(const rendering_buffer& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len)
unsigned len, {
const color_type& c, m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len);
cover_type cover) }
{
init_span(len);
m_mask->combine_vspan(x, y, &m_span[0], len);
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_from(const rendering_buffer& from, void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const cover_type* covers)
int xdst, int ydst, {
int xsrc, int ysrc, init_span(len, covers);
unsigned len) m_mask->combine_hspan(x, y, &m_span[0], len);
{ m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len); }
}
//--------------------------------------------------------------------
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[0], len);
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, void copy_color_hspan(int x, int y, unsigned len, const color_type* colors)
unsigned len, {
const color_type& c, realloc_span(len);
const cover_type* covers) m_mask->fill_hspan(x, y, &m_span[0], len);
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full);
}
//--------------------------------------------------------------------
void copy_color_vspan(int x, int y, unsigned len, const color_type* colors)
{
realloc_span(len);
m_mask->fill_vspan(x, y, &m_span[0], len);
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full);
}
//--------------------------------------------------------------------
void blend_color_hspan(int x,
int y,
unsigned len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
if (covers)
{ {
init_span(len, covers); init_span(len, covers);
m_mask->combine_hspan(x, y, &m_span[0], len); m_mask->combine_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
} }
else
//--------------------------------------------------------------------
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[0], len);
m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
void copy_color_hspan(int x, int y, unsigned len, const color_type* colors)
{ {
realloc_span(len); realloc_span(len);
m_mask->fill_hspan(x, y, &m_span[0], len); m_mask->fill_hspan(x, y, &m_span[0], len);
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full);
} }
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) 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[0], len);
}
else
{ {
realloc_span(len); realloc_span(len);
m_mask->fill_vspan(x, y, &m_span[0], len); m_mask->fill_vspan(x, y, &m_span[0], len);
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full);
} }
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover);
}
//-------------------------------------------------------------------- private:
void blend_color_hspan(int x, int y, pixfmt_type* m_pixf;
unsigned len, const amask_type* m_mask;
const color_type* colors, pod_array<cover_type> m_span;
const cover_type* covers, };
cover_type cover = cover_full)
{
if(covers)
{
init_span(len, covers);
m_mask->combine_hspan(x, y, &m_span[0], len);
}
else
{
realloc_span(len);
m_mask->fill_hspan(x, y, &m_span[0], len);
}
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover);
}
} // namespace agg
//--------------------------------------------------------------------
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[0], len);
}
else
{
realloc_span(len);
m_mask->fill_vspan(x, y, &m_span[0], len);
}
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover);
}
private:
pixfmt_type* m_pixf;
const amask_type* m_mask;
pod_array<cover_type> m_span;
};
}
#endif #endif

View file

@ -20,78 +20,69 @@
#include "agg_color_gray.h" #include "agg_color_gray.h"
#include "agg_color_rgba.h" #include "agg_color_rgba.h"
namespace agg namespace agg {
struct pixfmt_gray_tag
{};
struct pixfmt_rgb_tag
{};
struct pixfmt_rgba_tag
{};
//--------------------------------------------------------------blender_base
template<class ColorT, class Order = void>
struct blender_base
{ {
struct pixfmt_gray_tag typedef ColorT color_type;
{ typedef Order order_type;
}; typedef typename color_type::value_type value_type;
struct pixfmt_rgb_tag static rgba get(value_type r, value_type g, value_type b, value_type a, cover_type cover = cover_full)
{ {
}; if (cover > cover_none)
struct pixfmt_rgba_tag
{
};
//--------------------------------------------------------------blender_base
template<class ColorT, class Order = void>
struct blender_base
{
typedef ColorT color_type;
typedef Order order_type;
typedef typename color_type::value_type value_type;
static rgba get(value_type r, value_type g, value_type b, value_type a, cover_type cover = cover_full)
{ {
if (cover > cover_none) rgba c(color_type::to_double(r),
color_type::to_double(g),
color_type::to_double(b),
color_type::to_double(a));
if (cover < cover_full)
{ {
rgba c( double x = double(cover) / cover_full;
color_type::to_double(r), c.r *= x;
color_type::to_double(g), c.g *= x;
color_type::to_double(b), c.b *= x;
color_type::to_double(a)); c.a *= x;
if (cover < cover_full)
{
double x = double(cover) / cover_full;
c.r *= x;
c.g *= x;
c.b *= x;
c.a *= x;
}
return c;
} }
else return rgba::no_color();
}
static rgba get(const value_type* p, cover_type cover = cover_full) return c;
{
return get(
p[order_type::R],
p[order_type::G],
p[order_type::B],
p[order_type::A],
cover);
} }
else
return rgba::no_color();
}
static void set(value_type* p, value_type r, value_type g, value_type b, value_type a) static rgba get(const value_type* p, cover_type cover = cover_full)
{ {
p[order_type::R] = r; return get(p[order_type::R], p[order_type::G], p[order_type::B], p[order_type::A], cover);
p[order_type::G] = g; }
p[order_type::B] = b;
p[order_type::A] = a;
}
static void set(value_type* p, const rgba& c) static void set(value_type* p, value_type r, value_type g, value_type b, value_type a)
{ {
p[order_type::R] = color_type::from_double(c.r); p[order_type::R] = r;
p[order_type::G] = color_type::from_double(c.g); p[order_type::G] = g;
p[order_type::B] = color_type::from_double(c.b); p[order_type::B] = b;
p[order_type::A] = color_type::from_double(c.a); p[order_type::A] = a;
} }
};
} static void set(value_type* p, const rgba& c)
{
p[order_type::R] = color_type::from_double(c.r);
p[order_type::G] = color_type::from_double(c.g);
p[order_type::B] = color_type::from_double(c.b);
p[order_type::A] = color_type::from_double(c.a);
}
};
} // namespace agg
#endif #endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -18,140 +18,99 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//=======================================================pixfmt_transposer
template<class PixFmt>
class pixfmt_transposer
{ {
//=======================================================pixfmt_transposer public:
template<class PixFmt> class pixfmt_transposer typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::row_data row_data;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
//--------------------------------------------------------------------
pixfmt_transposer()
: m_pixf(0)
{}
explicit pixfmt_transposer(pixfmt_type& pixf)
: m_pixf(&pixf)
{}
void attach(pixfmt_type& pixf) { m_pixf = &pixf; }
//--------------------------------------------------------------------
AGG_INLINE unsigned width() const { return m_pixf->height(); }
AGG_INLINE unsigned height() const { return m_pixf->width(); }
//--------------------------------------------------------------------
AGG_INLINE color_type pixel(int x, int y) const { return m_pixf->pixel(y, x); }
//--------------------------------------------------------------------
AGG_INLINE void copy_pixel(int x, int y, const color_type& c) { m_pixf->copy_pixel(y, x, c); }
//--------------------------------------------------------------------
AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) { m_pixf->blend_pixel(y, x, c, cover); }
//--------------------------------------------------------------------
AGG_INLINE void copy_hline(int x, int y, unsigned len, const color_type& c) { m_pixf->copy_vline(y, x, len, c); }
//--------------------------------------------------------------------
AGG_INLINE void copy_vline(int x, int y, unsigned len, const color_type& c) { m_pixf->copy_hline(y, x, len, c); }
//--------------------------------------------------------------------
AGG_INLINE void blend_hline(int x, int y, unsigned len, const color_type& c, int8u cover)
{ {
public: m_pixf->blend_vline(y, x, len, c, cover);
typedef PixFmt pixfmt_type; }
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::row_data row_data;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
//-------------------------------------------------------------------- //--------------------------------------------------------------------
pixfmt_transposer() : m_pixf(0) {} AGG_INLINE void blend_vline(int x, int y, unsigned len, const color_type& c, int8u cover)
explicit pixfmt_transposer(pixfmt_type& pixf) : m_pixf(&pixf) {} {
void attach(pixfmt_type& pixf) { m_pixf = &pixf; } m_pixf->blend_hline(y, x, len, c, cover);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE unsigned width() const { return m_pixf->height(); } AGG_INLINE void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers)
AGG_INLINE unsigned height() const { return m_pixf->width(); } {
m_pixf->blend_solid_vspan(y, x, len, c, covers);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE color_type pixel(int x, int y) const AGG_INLINE void blend_solid_vspan(int x, int y, unsigned len, const color_type& c, const int8u* covers)
{ {
return m_pixf->pixel(y, x); m_pixf->blend_solid_hspan(y, x, len, c, covers);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE void copy_pixel(int x, int y, const color_type& c) AGG_INLINE void copy_color_hspan(int x, int y, unsigned len, const color_type* colors)
{ {
m_pixf->copy_pixel(y, x, c); m_pixf->copy_color_vspan(y, x, len, colors);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE void blend_pixel(int x, int y, AGG_INLINE void copy_color_vspan(int x, int y, unsigned len, const color_type* colors)
const color_type& c, {
int8u cover) m_pixf->copy_color_hspan(y, x, len, colors);
{ }
m_pixf->blend_pixel(y, x, c, cover);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE void copy_hline(int x, int y, AGG_INLINE void
unsigned len, blend_color_hspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover)
const color_type& c) {
{ m_pixf->blend_color_vspan(y, x, len, colors, covers, cover);
m_pixf->copy_vline(y, x, len, c); }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE void copy_vline(int x, int y, AGG_INLINE void
unsigned len, blend_color_vspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover)
const color_type& c) {
{ m_pixf->blend_color_hspan(y, x, len, colors, covers, cover);
m_pixf->copy_hline(y, x, len, c); }
}
//-------------------------------------------------------------------- private:
AGG_INLINE void blend_hline(int x, int y, pixfmt_type* m_pixf;
unsigned len, };
const color_type& c, } // namespace agg
int8u cover)
{
m_pixf->blend_vline(y, x, len, c, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_vline(int x, int y,
unsigned len,
const color_type& c,
int8u cover)
{
m_pixf->blend_hline(y, x, len, c, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_solid_hspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
m_pixf->blend_solid_vspan(y, x, len, c, covers);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_solid_vspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
m_pixf->blend_solid_hspan(y, x, len, c, covers);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_color_hspan(int x, int y,
unsigned len,
const color_type* colors)
{
m_pixf->copy_color_vspan(y, x, len, colors);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_color_vspan(int x, int y,
unsigned len,
const color_type* colors)
{
m_pixf->copy_color_hspan(y, x, len, colors);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_color_hspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
m_pixf->blend_color_vspan(y, x, len, colors, covers, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_color_vspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
m_pixf->blend_color_hspan(y, x, len, colors, covers, cover);
}
private:
pixfmt_type* m_pixf;
};
}
#endif #endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -17,131 +17,116 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//======================================================rasterizer_outline
template<class Renderer>
class rasterizer_outline
{ {
//======================================================rasterizer_outline public:
template<class Renderer> class rasterizer_outline explicit rasterizer_outline(Renderer& ren)
: m_ren(&ren)
, m_start_x(0)
, m_start_y(0)
, m_vertices(0)
{}
void attach(Renderer& ren) { m_ren = &ren; }
//--------------------------------------------------------------------
void move_to(int x, int y)
{ {
public: m_vertices = 1;
explicit rasterizer_outline(Renderer& ren) : m_ren->move_to(m_start_x = x, m_start_y = y);
m_ren(&ren), }
m_start_x(0),
m_start_y(0),
m_vertices(0)
{}
void attach(Renderer& ren) { m_ren = &ren; }
//--------------------------------------------------------------------
void line_to(int x, int y)
{
++m_vertices;
m_ren->line_to(x, y);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void move_to(int x, int y) void move_to_d(double x, double y) { move_to(m_ren->coord(x), m_ren->coord(y)); }
//--------------------------------------------------------------------
void line_to_d(double x, double y) { line_to(m_ren->coord(x), m_ren->coord(y)); }
//--------------------------------------------------------------------
void close()
{
if (m_vertices > 2)
{ {
m_vertices = 1; line_to(m_start_x, m_start_y);
m_ren->move_to(m_start_x = x, m_start_y = y);
} }
m_vertices = 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void line_to(int x, int y) void add_vertex(double x, double y, unsigned cmd)
{
if (is_move_to(cmd))
{ {
++m_vertices; move_to_d(x, y);
m_ren->line_to(x, y);
} }
else
//--------------------------------------------------------------------
void move_to_d(double x, double y)
{ {
move_to(m_ren->coord(x), m_ren->coord(y)); if (is_end_poly(cmd))
}
//--------------------------------------------------------------------
void line_to_d(double x, double y)
{
line_to(m_ren->coord(x), m_ren->coord(y));
}
//--------------------------------------------------------------------
void close()
{
if(m_vertices > 2)
{ {
line_to(m_start_x, m_start_y); if (is_closed(cmd))
} close();
m_vertices = 0;
}
//--------------------------------------------------------------------
void add_vertex(double x, double y, unsigned cmd)
{
if(is_move_to(cmd))
{
move_to_d(x, y);
} }
else else
{ {
if(is_end_poly(cmd)) line_to_d(x, y);
{
if(is_closed(cmd)) close();
}
else
{
line_to_d(x, y);
}
} }
} }
}
//--------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id = 0)
{
double x;
double y;
//-------------------------------------------------------------------- unsigned cmd;
template<class VertexSource> vs.rewind(path_id);
void add_path(VertexSource& vs, unsigned path_id=0) while (!is_stop(cmd = vs.vertex(&x, &y)))
{ {
double x; add_vertex(x, y, cmd);
double y;
unsigned cmd;
vs.rewind(path_id);
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
add_vertex(x, y, cmd);
}
} }
}
//--------------------------------------------------------------------
//-------------------------------------------------------------------- template<class VertexSource, class ColorStorage, class PathId>
template<class VertexSource, class ColorStorage, class PathId> void render_all_paths(VertexSource& vs, const ColorStorage& colors, const PathId& path_id, unsigned num_paths)
void render_all_paths(VertexSource& vs, {
const ColorStorage& colors, for (unsigned i = 0; i < num_paths; i++)
const PathId& path_id,
unsigned num_paths)
{ {
for(unsigned i = 0; i < num_paths; i++) m_ren->line_color(colors[i]);
{ add_path(vs, path_id[i]);
m_ren->line_color(colors[i]);
add_path(vs, path_id[i]);
}
} }
}
//--------------------------------------------------------------------
//-------------------------------------------------------------------- template<class Ctrl>
template<class Ctrl> void render_ctrl(Ctrl& c) void render_ctrl(Ctrl& c)
{
unsigned i;
for (i = 0; i < c.num_paths(); i++)
{ {
unsigned i; m_ren->line_color(c.color(i));
for(i = 0; i < c.num_paths(); i++) add_path(c, i);
{
m_ren->line_color(c.color(i));
add_path(c, i);
}
} }
}
private:
Renderer* m_ren;
int m_start_x;
int m_start_y;
unsigned m_vertices;
};
private: } // namespace agg
Renderer* m_ren;
int m_start_x;
int m_start_y;
unsigned m_vertices;
};
}
#endif #endif

View file

@ -19,275 +19,254 @@
#include "agg_line_aa_basics.h" #include "agg_line_aa_basics.h"
#include "agg_vertex_sequence.h" #include "agg_vertex_sequence.h"
namespace agg 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
inline bool cmp_dist_start(int d) { return d > 0; } // Vertex (x, y) with the distance to the next one. The last vertex has
inline bool cmp_dist_end(int d) { return d <= 0; } // 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)
//-----------------------------------------------------------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; double dx = val.x - x;
int y; double dy = val.y - y;
int len; return (len = uround(sqrt(dx * dx + dy * dy))) > (line_subpixel_scale + line_subpixel_scale / 2);
}
};
line_aa_vertex() {} //----------------------------------------------------------outline_aa_join_e
line_aa_vertex(int x_, int y_) : enum outline_aa_join_e {
x(x_), outline_no_join, //-----outline_no_join
y(y_), outline_miter_join, //-----outline_miter_join
len(0) outline_round_join, //-----outline_round_join
{ outline_miter_accurate_join //-----outline_accurate_join
} };
bool operator () (const line_aa_vertex& val) //=======================================================rasterizer_outline_aa
{ template<class Renderer, class Coord = line_coord>
double dx = val.x - x; class rasterizer_outline_aa
double dy = val.y - y; {
return (len = uround(sqrt(dx * dx + dy * dy))) > private:
(line_subpixel_scale + line_subpixel_scale / 2); //------------------------------------------------------------------------
} 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);
//----------------------------------------------------------outline_aa_join_e public:
enum outline_aa_join_e typedef line_aa_vertex vertex_type;
typedef vertex_sequence<vertex_type, 6> vertex_storage_type;
explicit rasterizer_outline_aa(Renderer& ren)
: m_ren(&ren)
, m_line_join(ren.accurate_join_only() ? outline_miter_accurate_join : outline_round_join)
, m_round_cap(false)
, m_start_x(0)
, m_start_y(0)
{}
void attach(Renderer& ren) { m_ren = &ren; }
//------------------------------------------------------------------------
void line_join(outline_aa_join_e join)
{ {
outline_no_join, //-----outline_no_join m_line_join = m_ren->accurate_join_only() ? outline_miter_accurate_join : join;
outline_miter_join, //-----outline_miter_join }
outline_round_join, //-----outline_round_join bool line_join() const { return m_line_join; }
outline_miter_accurate_join //-----outline_accurate_join
};
//=======================================================rasterizer_outline_aa //------------------------------------------------------------------------
template<class Renderer, class Coord=line_coord> class rasterizer_outline_aa 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(Coord::conv(x), Coord::conv(y)); }
//------------------------------------------------------------------------
void line_to_d(double x, double y) { line_to(Coord::conv(x), Coord::conv(y)); }
//------------------------------------------------------------------------
void render(bool close_polygon);
//------------------------------------------------------------------------
void add_vertex(double x, double y, unsigned cmd)
{ {
private: if (is_move_to(cmd))
//------------------------------------------------------------------------
struct draw_vars
{ {
unsigned idx; render(false);
int x1, y1, x2, y2; move_to_d(x, y);
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;
explicit rasterizer_outline_aa(Renderer& ren) :
m_ren(&ren),
m_line_join(ren.accurate_join_only() ?
outline_miter_accurate_join :
outline_round_join),
m_round_cap(false),
m_start_x(0),
m_start_y(0)
{}
void attach(Renderer& ren) { m_ren = &ren; }
//------------------------------------------------------------------------
void line_join(outline_aa_join_e join)
{
m_line_join = m_ren->accurate_join_only() ?
outline_miter_accurate_join :
join;
} }
bool line_join() const { return m_line_join; } else
//------------------------------------------------------------------------
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)); if (is_end_poly(cmd))
}
//------------------------------------------------------------------------
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(Coord::conv(x), Coord::conv(y));
}
//------------------------------------------------------------------------
void line_to_d(double x, double y)
{
line_to(Coord::conv(x), Coord::conv(y));
}
//------------------------------------------------------------------------
void render(bool close_polygon);
//------------------------------------------------------------------------
void add_vertex(double x, double y, unsigned cmd)
{
if(is_move_to(cmd))
{ {
render(false); render(is_closed(cmd));
move_to_d(x, y); if (is_closed(cmd))
{
move_to(m_start_x, m_start_y);
}
} }
else else
{ {
if(is_end_poly(cmd)) line_to_d(x, y);
{
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> template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id=0) void add_path(VertexSource& vs, unsigned path_id = 0)
{
double x;
double y;
unsigned cmd;
vs.rewind(path_id);
while (!is_stop(cmd = vs.vertex(&x, &y)))
{ {
double x; add_vertex(x, y, cmd);
double y;
unsigned cmd;
vs.rewind(path_id);
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
add_vertex(x, y, cmd);
}
render(false);
} }
render(false);
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------ template<class VertexSource, class ColorStorage, class PathId>
template<class VertexSource, class ColorStorage, class PathId> void render_all_paths(VertexSource& vs, const ColorStorage& colors, const PathId& path_id, unsigned num_paths)
void render_all_paths(VertexSource& vs, {
const ColorStorage& colors, for (unsigned i = 0; i < num_paths; i++)
const PathId& path_id,
unsigned num_paths)
{ {
for(unsigned i = 0; i < num_paths; i++) m_ren->color(colors[i]);
{ add_path(vs, path_id[i]);
m_ren->color(colors[i]);
add_path(vs, path_id[i]);
}
} }
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------ template<class Ctrl>
template<class Ctrl> void render_ctrl(Ctrl& c) 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, Coord>&);
const rasterizer_outline_aa<Renderer, Coord>& operator =
(const rasterizer_outline_aa<Renderer, Coord>&);
Renderer* m_ren;
vertex_storage_type m_src_vertices;
outline_aa_join_e m_line_join;
bool m_round_cap;
int m_start_x;
int m_start_y;
};
//----------------------------------------------------------------------------
template<class Renderer, class Coord>
void rasterizer_outline_aa<Renderer, Coord>::draw(draw_vars& dv,
unsigned start,
unsigned end)
{ {
unsigned i; unsigned i;
const vertex_storage_type::value_type* v; for (i = 0; i < c.num_paths(); i++)
for(i = start; i < end; i++)
{ {
if(m_line_join == outline_round_join) m_ren->color(c.color(i));
{ add_path(c, i);
dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1); }
dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1); }
dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1);
dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1);
}
switch(dv.flags) private:
{ rasterizer_outline_aa(const rasterizer_outline_aa<Renderer, Coord>&);
case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break; const rasterizer_outline_aa<Renderer, Coord>& operator=(const rasterizer_outline_aa<Renderer, Coord>&);
case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break;
case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break;
case 3: m_ren->line0(dv.curr); break;
}
if(m_line_join == outline_round_join && (dv.flags & 2) == 0) Renderer* m_ren;
{ vertex_storage_type m_src_vertices;
m_ren->pie(dv.curr.x2, dv.curr.y2, outline_aa_join_e m_line_join;
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), bool m_round_cap;
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1), int m_start_x;
dv.curr.x2 + (dv.next.y2 - dv.next.y1), int m_start_y;
dv.curr.y2 - (dv.next.x2 - dv.next.x1)); };
}
dv.x1 = dv.x2; //----------------------------------------------------------------------------
dv.y1 = dv.y2; template<class Renderer, class Coord>
dv.lcurr = dv.lnext; void rasterizer_outline_aa<Renderer, Coord>::draw(draw_vars& dv, unsigned start, unsigned end)
dv.lnext = m_src_vertices[dv.idx].len; {
unsigned i;
const vertex_storage_type::value_type* v;
++dv.idx; for (i = start; i < end; i++)
if(dv.idx >= m_src_vertices.size()) dv.idx = 0; {
if (m_line_join == outline_round_join)
{
dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1);
dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1);
dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1);
dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1);
}
v = &m_src_vertices[dv.idx]; switch (dv.flags)
dv.x2 = v->x; {
dv.y2 = v->y; 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.curr = dv.next; if (m_line_join == outline_round_join && (dv.flags & 2) == 0)
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); {
dv.xb1 = dv.xb2; m_ren->pie(dv.curr.x2,
dv.yb1 = dv.yb2; dv.curr.y2,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1),
dv.curr.x2 + (dv.next.y2 - dv.next.y1),
dv.curr.y2 - (dv.next.x2 - dv.next.x1));
}
switch(m_line_join) 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;
switch (m_line_join)
{
case outline_no_join: case outline_no_join:
dv.flags = 3; dv.flags = 3;
break; break;
case outline_miter_join: case outline_miter_join:
dv.flags >>= 1; dv.flags >>= 1;
dv.flags |= ((dv.curr.diagonal_quadrant() == dv.flags |= ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
dv.next.diagonal_quadrant()) << 1); if ((dv.flags & 2) == 0)
if((dv.flags & 2) == 0)
{ {
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
} }
@ -295,302 +274,282 @@ namespace agg
case outline_round_join: case outline_round_join:
dv.flags >>= 1; dv.flags >>= 1;
dv.flags |= ((dv.curr.diagonal_quadrant() == dv.flags |= ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
dv.next.diagonal_quadrant()) << 1);
break; break;
case outline_miter_accurate_join: case outline_miter_accurate_join:
dv.flags = 0; dv.flags = 0;
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
break; break;
}
} }
} }
}
//----------------------------------------------------------------------------
template<class Renderer, class Coord>
void rasterizer_outline_aa<Renderer, Coord>::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 && (m_src_vertices.size() >= 3))
//----------------------------------------------------------------------------
template<class Renderer, class Coord>
void rasterizer_outline_aa<Renderer, Coord>::render(bool close_polygon)
{ {
m_src_vertices.close(close_polygon); dv.idx = 2;
draw_vars dv;
const vertex_storage_type::value_type* v;
int x1;
int y1;
int x2;
int y2;
int lprev;
if(close_polygon && (m_src_vertices.size() >= 3)) 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;
switch (m_line_join)
{ {
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;
switch(m_line_join)
{
case outline_no_join: case outline_no_join:
dv.flags = 3; dv.flags = 3;
break; break;
case outline_miter_join: case outline_miter_join:
case outline_round_join: case outline_round_join:
dv.flags = dv.flags = (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
break; break;
case outline_miter_accurate_join: case outline_miter_accurate_join:
dv.flags = 0; dv.flags = 0;
break; break;
}
if((dv.flags & 1) == 0 && m_line_join != outline_round_join)
{
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
}
if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
{
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
}
draw(dv, 0, m_src_vertices.size());
} }
else
if ((dv.flags & 1) == 0 && m_line_join != outline_round_join)
{ {
switch(m_src_vertices.size()) bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
{ }
case 0:
case 1:
break;
case 2: if ((dv.flags & 2) == 0 && m_line_join != outline_round_join)
{ {
v = &m_src_vertices[0]; bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
x1 = v->x; }
y1 = v->y; draw(dv, 0, m_src_vertices.size());
lprev = v->len; }
v = &m_src_vertices[1]; else
x2 = v->x; {
y2 = v->y; switch (m_src_vertices.size())
line_parameters lp(x1, y1, x2, y2, lprev); {
if(m_round_cap) case 0:
{ case 1:
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; break;
case 3: 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)
{ {
int x3, y3; m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
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);
if(m_round_cap)
{
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
}
if(m_line_join == outline_round_join)
{
m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
x2 + (y2 - y1), y2 - (x2 - x1));
m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1),
x2 + (y3 - y2), y2 - (x3 - x2));
m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2),
x3 + (y3 - y2), y3 - (x3 - x2));
}
else
{
bisectrix(lp1, lp2, &dv.xb1, &dv.yb1);
m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1),
dv.xb1, dv.yb1);
m_ren->line3(lp2, dv.xb1, dv.yb1,
x3 + (y3 - y2), y3 - (x3 - x2));
}
if(m_round_cap)
{
m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2));
}
} }
break; m_ren->line3(lp, x1 + (y2 - y1), y1 - (x2 - x1), x2 + (y2 - y1), y2 - (x2 - x1));
if (m_round_cap)
default:
{ {
dv.idx = 3; m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
}
}
break;
v = &m_src_vertices[0]; case 3: {
x1 = v->x; int x3, y3;
y1 = v->y; int lnext;
lprev = v->len; 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);
v = &m_src_vertices[1]; if (m_round_cap)
x2 = v->x; {
y2 = v->y; m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
dv.lcurr = v->len; }
line_parameters prev(x1, y1, x2, y2, lprev);
v = &m_src_vertices[2]; if (m_line_join == outline_round_join)
dv.x1 = v->x; {
dv.y1 = v->y; m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), x2 + (y2 - y1), y2 - (x2 - x1));
dv.lnext = v->len;
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
v = &m_src_vertices[dv.idx]; m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1), x2 + (y3 - y2), y2 - (x3 - x2));
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; m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2), x3 + (y3 - y2), y3 - (x3 - x2));
dv.yb1 = 0; }
dv.xb2 = 0; else
dv.yb2 = 0; {
bisectrix(lp1, lp2, &dv.xb1, &dv.yb1);
m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), dv.xb1, dv.yb1);
switch(m_line_join) 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;
switch (m_line_join)
{
case outline_no_join: case outline_no_join:
dv.flags = 3; dv.flags = 3;
break; break;
case outline_miter_join: case outline_miter_join:
case outline_round_join: case outline_round_join:
dv.flags = dv.flags = (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
break; break;
case outline_miter_accurate_join: case outline_miter_accurate_join:
dv.flags = 0; dv.flags = 0;
break; break;
} }
if(m_round_cap) if (m_round_cap)
{
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
}
if ((dv.flags & 1) == 0)
{
if (m_line_join == outline_round_join)
{ {
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), x2 + (y2 - y1), y2 - (x2 - x1));
} m_ren->pie(prev.x2,
if((dv.flags & 1) == 0) prev.y2,
{ x2 + (y2 - y1),
if(m_line_join == outline_round_join) y2 - (x2 - x1),
{ dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), dv.curr.y1 - (dv.curr.x2 - dv.curr.x1));
x2 + (y2 - y1), y2 - (x2 - x1));
m_ren->pie(prev.x2, prev.y2,
x2 + (y2 - y1), y2 - (x2 - x1),
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1));
}
else
{
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
dv.xb1, dv.yb1);
}
} }
else else
{ {
m_ren->line1(prev, bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
x1 + (y2 - y1), m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), dv.xb1, dv.yb1);
y1 - (x2 - x1));
}
if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
{
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
} }
}
else
{
m_ren->line1(prev, x1 + (y2 - y1), y1 - (x2 - x1));
}
if ((dv.flags & 2) == 0 && m_line_join != outline_round_join)
{
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
}
draw(dv, 1, m_src_vertices.size() - 2); draw(dv, 1, m_src_vertices.size() - 2);
if((dv.flags & 1) == 0) if ((dv.flags & 1) == 0)
{
if (m_line_join == outline_round_join)
{ {
if(m_line_join == outline_round_join) m_ren->line3(dv.curr,
{ dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
m_ren->line3(dv.curr, dv.curr.y1 - (dv.curr.x2 - dv.curr.x1),
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1),
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}
else
{
m_ren->line3(dv.curr, dv.xb1, dv.yb1,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}
}
else
{
m_ren->line2(dv.curr,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
} }
if(m_round_cap) else
{ {
m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2, m_ren->line3(dv.curr,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), dv.xb1,
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); dv.yb1,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
} }
} }
break; 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();
} }
m_src_vertices.remove_all();
} }
} // namespace agg
#endif #endif

View file

@ -33,477 +33,445 @@
#include "agg_rasterizer_sl_clip.h" #include "agg_rasterizer_sl_clip.h"
#include "agg_gamma_functions.h" #include "agg_gamma_functions.h"
namespace agg {
namespace agg //-----------------------------------------------------------------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
{ {
int x;
int y;
int cover;
int area;
void initial()
//-----------------------------------------------------------------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
{ {
int x; x = 0x7FFFFFFF;
int y; y = 0x7FFFFFFF;
int cover; cover = 0;
int area; area = 0;
}
void initial() void style(const cell_aa&) {}
{
x = 0x7FFFFFFF;
y = 0x7FFFFFFF;
cover = 0;
area = 0;
}
void style(const cell_aa&) {} int not_equal(int ex, int ey, const cell_aa&) const { return (ex - x) | (ey - y); }
};
int not_equal(int ex, int ey, const cell_aa&) const //==================================================rasterizer_scanline_aa
{ // Polygon rasterizer that is used to render filled polygons with
return (ex - x) | (ey - y); // 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_subpixel_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<class Clip = rasterizer_sl_clip_int>
class rasterizer_scanline_aa
{
enum status { status_initial, status_move_to, status_line_to, status_closed };
public:
typedef Clip clip_type;
typedef typename Clip::conv_type conv_type;
typedef typename Clip::coord_type coord_type;
enum aa_scale_e {
aa_shift = 8,
aa_scale = 1 << aa_shift,
aa_mask = aa_scale - 1,
aa_scale2 = aa_scale * 2,
aa_mask2 = aa_scale2 - 1
}; };
//--------------------------------------------------------------------
//==================================================rasterizer_scanline_aa rasterizer_scanline_aa()
// Polygon rasterizer that is used to render filled polygons with : m_outline()
// high-quality Anti-Aliasing. Internally, by default, the class uses , m_clipper()
// integer coordinates in format 24.8, i.e. 24 bits for integer part , m_filling_rule(fill_non_zero)
// and 8 bits for fractional - see poly_subpixel_shift. This class can be , m_auto_close(true)
// used in the following way: , m_start_x(0)
// , m_start_y(0)
// 1. filling_rule(filling_rule_e ft) - optional. , m_status(status_initial)
//
// 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<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa
{ {
enum status int i;
{ for (i = 0; i < aa_scale; i++)
status_initial, m_gamma[i] = i;
status_move_to, }
status_line_to,
status_closed
};
public: //--------------------------------------------------------------------
typedef Clip clip_type; template<class GammaF>
typedef typename Clip::conv_type conv_type; rasterizer_scanline_aa(const GammaF& gamma_function)
typedef typename Clip::coord_type coord_type; : m_outline()
, m_clipper(m_outline)
, m_filling_rule(fill_non_zero)
, m_auto_close(true)
, m_start_x(0)
, m_start_y(0)
, m_status(status_initial)
{
gamma(gamma_function);
}
enum aa_scale_e //--------------------------------------------------------------------
{ void reset();
aa_shift = 8, void reset_clipping();
aa_scale = 1 << aa_shift, void clip_box(double x1, double y1, double x2, double y2);
aa_mask = aa_scale - 1, void filling_rule(filling_rule_e filling_rule);
aa_scale2 = aa_scale * 2, void auto_close(bool flag) { m_auto_close = flag; }
aa_mask2 = aa_scale2 - 1
};
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rasterizer_scanline_aa() : template<class GammaF>
m_outline(), void gamma(const GammaF& gamma_function)
m_clipper(), {
m_filling_rule(fill_non_zero), int i;
m_auto_close(true), for (i = 0; i < aa_scale; i++)
m_start_x(0),
m_start_y(0),
m_status(status_initial)
{ {
int i; m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask);
for(i = 0; i < aa_scale; i++) m_gamma[i] = i;
} }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
template<class GammaF> unsigned apply_gamma(unsigned cover) const { return m_gamma[cover]; }
rasterizer_scanline_aa(const GammaF& gamma_function) :
m_outline(), //--------------------------------------------------------------------
m_clipper(m_outline), void move_to(int x, int y);
m_filling_rule(fill_non_zero), void line_to(int x, int y);
m_auto_close(true), void move_to_d(double x, double y);
m_start_x(0), void line_to_d(double x, double y);
m_start_y(0), void close_polygon();
m_status(status_initial) void add_vertex(double x, double y, unsigned cmd);
void edge(int x1, int y1, int x2, int y2);
void edge_d(double x1, double y1, double x2, double y2);
//-------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id = 0)
{
double x;
double y;
unsigned cmd;
vs.rewind(path_id);
if (m_outline.sorted())
reset();
while (!is_stop(cmd = vs.vertex(&x, &y)))
{ {
gamma(gamma_function); add_vertex(x, y, cmd);
} }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void reset(); int min_x() const { return m_outline.min_x(); }
void reset_clipping(); int min_y() const { return m_outline.min_y(); }
void clip_box(double x1, double y1, double x2, double y2); int max_x() const { return m_outline.max_x(); }
void filling_rule(filling_rule_e filling_rule); int max_y() const { return m_outline.max_y(); }
void auto_close(bool flag) { m_auto_close = flag; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
template<class GammaF> void gamma(const GammaF& gamma_function) void sort();
bool rewind_scanlines();
bool navigate_scanline(int y);
//--------------------------------------------------------------------
AGG_INLINE unsigned calculate_alpha(int area) const
{
int cover = area >> (poly_subpixel_shift * 2 + 1 - aa_shift);
if (cover < 0)
cover = -cover;
if (m_filling_rule == fill_even_odd)
{ {
int i; cover &= aa_mask2;
for(i = 0; i < aa_scale; i++) if (cover > aa_scale)
{ {
m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask); cover = aa_scale2 - cover;
} }
} }
if (cover > aa_mask)
cover = aa_mask;
return m_gamma[cover];
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
unsigned apply_gamma(unsigned cover) const template<class Scanline>
bool sweep_scanline(Scanline& sl)
{
for (;;)
{ {
return m_gamma[cover]; if (m_scan_y > m_outline.max_y())
} return false;
sl.reset_spans();
unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y);
unsigned cover = 0;
//-------------------------------------------------------------------- while (num_cells)
void move_to(int x, int y);
void line_to(int x, int y);
void move_to_d(double x, double y);
void line_to_d(double x, double y);
void close_polygon();
void add_vertex(double x, double y, unsigned cmd);
void edge(int x1, int y1, int x2, int y2);
void edge_d(double x1, double y1, double x2, double y2);
//-------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id=0)
{
double x;
double y;
unsigned cmd;
vs.rewind(path_id);
if(m_outline.sorted()) reset();
while(!is_stop(cmd = vs.vertex(&x, &y)))
{ {
add_vertex(x, y, cmd); const cell_aa* cur_cell = *cells;
} int x = cur_cell->x;
} int area = cur_cell->area;
unsigned alpha;
//-------------------------------------------------------------------- cover += cur_cell->cover;
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(); }
//-------------------------------------------------------------------- // accumulate all cells with the same X
void sort(); while (--num_cells)
bool rewind_scanlines();
bool navigate_scanline(int y);
//--------------------------------------------------------------------
AGG_INLINE unsigned calculate_alpha(int area) const
{
int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
if(cover < 0) cover = -cover;
if(m_filling_rule == fill_even_odd)
{
cover &= aa_mask2;
if(cover > aa_scale)
{ {
cover = aa_scale2 - cover; cur_cell = *++cells;
} if (cur_cell->x != x)
} break;
if(cover > aa_mask) cover = aa_mask; area += cur_cell->area;
return m_gamma[cover];
}
//--------------------------------------------------------------------
template<class Scanline> bool sweep_scanline(Scanline& sl)
{
for(;;)
{
if(m_scan_y > m_outline.max_y()) return false;
sl.reset_spans();
unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y);
unsigned cover = 0;
while(num_cells)
{
const cell_aa* cur_cell = *cells;
int x = cur_cell->x;
int area = cur_cell->area;
unsigned alpha;
cover += cur_cell->cover; cover += cur_cell->cover;
//accumulate all cells with the same X
while(--num_cells)
{
cur_cell = *++cells;
if(cur_cell->x != x) break;
area += cur_cell->area;
cover += cur_cell->cover;
}
if(area)
{
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
if(alpha)
{
sl.add_cell(x, alpha);
}
x++;
}
if(num_cells && cur_cell->x > x)
{
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
if(alpha)
{
sl.add_span(x, cur_cell->x - x, alpha);
}
}
} }
if(sl.num_spans()) break; if (area)
++m_scan_y; {
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
if (alpha)
{
sl.add_cell(x, alpha);
}
x++;
}
if (num_cells && cur_cell->x > x)
{
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
if (alpha)
{
sl.add_span(x, cur_cell->x - x, alpha);
}
}
} }
sl.finalize(m_scan_y); if (sl.num_spans())
break;
++m_scan_y; ++m_scan_y;
return true;
} }
//-------------------------------------------------------------------- sl.finalize(m_scan_y);
bool hit_test(int tx, int ty); ++m_scan_y;
private:
//--------------------------------------------------------------------
// Disable copying
rasterizer_scanline_aa(const rasterizer_scanline_aa<Clip>&);
const rasterizer_scanline_aa<Clip>&
operator = (const rasterizer_scanline_aa<Clip>&);
private:
rasterizer_cells_aa<cell_aa> m_outline;
clip_type m_clipper;
int m_gamma[aa_scale];
filling_rule_e m_filling_rule;
bool m_auto_close;
coord_type m_start_x;
coord_type m_start_y;
unsigned m_status;
int m_scan_y;
};
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::reset()
{
m_outline.reset();
m_status = status_initial;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::filling_rule(filling_rule_e filling_rule)
{
m_filling_rule = filling_rule;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::clip_box(double x1, double y1,
double x2, double y2)
{
reset();
m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1),
conv_type::upscale(x2), conv_type::upscale(y2));
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::reset_clipping()
{
reset();
m_clipper.reset_clipping();
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::close_polygon()
{
if(m_status == status_line_to)
{
m_clipper.line_to(m_outline, m_start_x, m_start_y);
m_status = status_closed;
}
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::move_to(int x, int y)
{
if(m_outline.sorted()) reset();
if(m_auto_close) close_polygon();
m_clipper.move_to(m_start_x = conv_type::downscale(x),
m_start_y = conv_type::downscale(y));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::line_to(int x, int y)
{
m_clipper.line_to(m_outline,
conv_type::downscale(x),
conv_type::downscale(y));
m_status = status_line_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y)
{
if(m_outline.sorted()) reset();
if(m_auto_close) close_polygon();
m_clipper.move_to(m_start_x = conv_type::upscale(x),
m_start_y = conv_type::upscale(y));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::line_to_d(double x, double y)
{
m_clipper.line_to(m_outline,
conv_type::upscale(x),
conv_type::upscale(y));
m_status = status_line_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::add_vertex(double x, double y, unsigned cmd)
{
if(is_move_to(cmd))
{
move_to_d(x, y);
}
else
if(is_vertex(cmd))
{
line_to_d(x, y);
}
else
if(is_close(cmd))
{
close_polygon();
}
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::edge(int x1, int y1, int x2, int y2)
{
if(m_outline.sorted()) reset();
m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
m_clipper.line_to(m_outline,
conv_type::downscale(x2),
conv_type::downscale(y2));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::edge_d(double x1, double y1,
double x2, double y2)
{
if(m_outline.sorted()) reset();
m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
m_clipper.line_to(m_outline,
conv_type::upscale(x2),
conv_type::upscale(y2));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::sort()
{
if(m_auto_close) close_polygon();
m_outline.sort_cells();
}
//------------------------------------------------------------------------
template<class Clip>
AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines()
{
if(m_auto_close) close_polygon();
m_outline.sort_cells();
if(m_outline.total_cells() == 0)
{
return false;
}
m_scan_y = m_outline.min_y();
return true; return true;
} }
//--------------------------------------------------------------------
bool hit_test(int tx, int ty);
//------------------------------------------------------------------------ private:
template<class Clip> //--------------------------------------------------------------------
AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y) // Disable copying
{ rasterizer_scanline_aa(const rasterizer_scanline_aa<Clip>&);
if(m_auto_close) close_polygon(); const rasterizer_scanline_aa<Clip>& operator=(const rasterizer_scanline_aa<Clip>&);
m_outline.sort_cells();
if(m_outline.total_cells() == 0 ||
y < m_outline.min_y() ||
y > m_outline.max_y())
{
return false;
}
m_scan_y = y;
return true;
}
//------------------------------------------------------------------------
template<class Clip>
bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty)
{
if(!navigate_scanline(ty)) return false;
scanline_hit_test sl(tx);
sweep_scanline(sl);
return sl.hit();
}
private:
rasterizer_cells_aa<cell_aa> m_outline;
clip_type m_clipper;
int m_gamma[aa_scale];
filling_rule_e m_filling_rule;
bool m_auto_close;
coord_type m_start_x;
coord_type m_start_y;
unsigned m_status;
int m_scan_y;
};
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::reset()
{
m_outline.reset();
m_status = status_initial;
} }
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::filling_rule(filling_rule_e filling_rule)
{
m_filling_rule = filling_rule;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::clip_box(double x1, double y1, double x2, double y2)
{
reset();
m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), conv_type::upscale(x2), conv_type::upscale(y2));
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::reset_clipping()
{
reset();
m_clipper.reset_clipping();
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::close_polygon()
{
if (m_status == status_line_to)
{
m_clipper.line_to(m_outline, m_start_x, m_start_y);
m_status = status_closed;
}
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::move_to(int x, int y)
{
if (m_outline.sorted())
reset();
if (m_auto_close)
close_polygon();
m_clipper.move_to(m_start_x = conv_type::downscale(x), m_start_y = conv_type::downscale(y));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::line_to(int x, int y)
{
m_clipper.line_to(m_outline, conv_type::downscale(x), conv_type::downscale(y));
m_status = status_line_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y)
{
if (m_outline.sorted())
reset();
if (m_auto_close)
close_polygon();
m_clipper.move_to(m_start_x = conv_type::upscale(x), m_start_y = conv_type::upscale(y));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::line_to_d(double x, double y)
{
m_clipper.line_to(m_outline, conv_type::upscale(x), conv_type::upscale(y));
m_status = status_line_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::add_vertex(double x, double y, unsigned cmd)
{
if (is_move_to(cmd))
{
move_to_d(x, y);
}
else if (is_vertex(cmd))
{
line_to_d(x, y);
}
else if (is_close(cmd))
{
close_polygon();
}
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::edge(int x1, int y1, int x2, int y2)
{
if (m_outline.sorted())
reset();
m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
m_clipper.line_to(m_outline, conv_type::downscale(x2), conv_type::downscale(y2));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::edge_d(double x1, double y1, double x2, double y2)
{
if (m_outline.sorted())
reset();
m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
m_clipper.line_to(m_outline, conv_type::upscale(x2), conv_type::upscale(y2));
m_status = status_move_to;
}
//------------------------------------------------------------------------
template<class Clip>
void rasterizer_scanline_aa<Clip>::sort()
{
if (m_auto_close)
close_polygon();
m_outline.sort_cells();
}
//------------------------------------------------------------------------
template<class Clip>
AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines()
{
if (m_auto_close)
close_polygon();
m_outline.sort_cells();
if (m_outline.total_cells() == 0)
{
return false;
}
m_scan_y = m_outline.min_y();
return true;
}
//------------------------------------------------------------------------
template<class Clip>
AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y)
{
if (m_auto_close)
close_polygon();
m_outline.sort_cells();
if (m_outline.total_cells() == 0 || y < m_outline.min_y() || y > m_outline.max_y())
{
return false;
}
m_scan_y = y;
return true;
}
//------------------------------------------------------------------------
template<class Clip>
bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty)
{
if (!navigate_scanline(ty))
return false;
scanline_hit_test sl(tx);
sweep_scanline(sl);
return sl.hit();
}
} // namespace agg
#endif #endif

View file

@ -17,226 +17,201 @@
#include "agg_clip_liang_barsky.h" #include "agg_clip_liang_barsky.h"
namespace agg namespace agg {
//--------------------------------------------------------poly_max_coord_e
enum poly_max_coord_e {
poly_max_coord = (1 << 30) - 1 //----poly_max_coord
};
//------------------------------------------------------------ras_conv_int
struct ras_conv_int
{ {
//--------------------------------------------------------poly_max_coord_e typedef int coord_type;
enum poly_max_coord_e static AGG_INLINE int mul_div(double a, double b, double c) { return iround(a * b / c); }
static int xi(int v) { return v; }
static int yi(int v) { return v; }
static int upscale(double v) { return iround(v * poly_subpixel_scale); }
static int downscale(int v) { return v; }
};
//--------------------------------------------------------ras_conv_int_sat
struct ras_conv_int_sat
{
typedef int coord_type;
static AGG_INLINE int mul_div(double a, double b, double c)
{ {
poly_max_coord = (1 << 30) - 1 //----poly_max_coord return saturation<poly_max_coord>::iround(a * b / c);
}; }
static int xi(int v) { return v; }
static int yi(int v) { return v; }
static int upscale(double v) { return saturation<poly_max_coord>::iround(v * poly_subpixel_scale); }
static int downscale(int v) { return v; }
};
//------------------------------------------------------------ras_conv_int //---------------------------------------------------------ras_conv_int_3x
struct ras_conv_int struct ras_conv_int_3x
{
typedef int coord_type;
static AGG_INLINE int mul_div(double a, double b, double c) { return iround(a * b / c); }
static int xi(int v) { return v * 3; }
static int yi(int v) { return v; }
static int upscale(double v) { return iround(v * poly_subpixel_scale); }
static int downscale(int v) { return v; }
};
//-----------------------------------------------------------ras_conv_dbl
struct ras_conv_dbl
{
typedef double coord_type;
static AGG_INLINE double mul_div(double a, double b, double c) { return a * b / c; }
static int xi(double v) { return iround(v * poly_subpixel_scale); }
static int yi(double v) { return iround(v * poly_subpixel_scale); }
static double upscale(double v) { return v; }
static double downscale(int v) { return v / double(poly_subpixel_scale); }
};
//--------------------------------------------------------ras_conv_dbl_3x
struct ras_conv_dbl_3x
{
typedef double coord_type;
static AGG_INLINE double mul_div(double a, double b, double c) { return a * b / c; }
static int xi(double v) { return iround(v * poly_subpixel_scale * 3); }
static int yi(double v) { return iround(v * poly_subpixel_scale); }
static double upscale(double v) { return v; }
static double downscale(int v) { return v / double(poly_subpixel_scale); }
};
//------------------------------------------------------rasterizer_sl_clip
template<class Conv>
class rasterizer_sl_clip
{
public:
typedef Conv conv_type;
typedef typename Conv::coord_type coord_type;
typedef rect_base<coord_type> rect_type;
//--------------------------------------------------------------------
rasterizer_sl_clip()
: m_clip_box(0, 0, 0, 0)
, m_x1(0)
, m_y1(0)
, m_f1(0)
, m_clipping(false)
{}
//--------------------------------------------------------------------
void reset_clipping() { m_clipping = false; }
//--------------------------------------------------------------------
void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2)
{ {
typedef int coord_type; m_clip_box = rect_type(x1, y1, x2, y2);
static AGG_INLINE int mul_div(double a, double b, double c) m_clip_box.normalize();
{ m_clipping = true;
return iround(a * b / c); }
}
static int xi(int v) { return v; }
static int yi(int v) { return v; }
static int upscale(double v) { return iround(v * poly_subpixel_scale); }
static int downscale(int v) { return v; }
};
//--------------------------------------------------------ras_conv_int_sat //--------------------------------------------------------------------
struct ras_conv_int_sat void move_to(coord_type x1, coord_type y1)
{ {
typedef int coord_type; m_x1 = x1;
static AGG_INLINE int mul_div(double a, double b, double c) m_y1 = y1;
{ if (m_clipping)
return saturation<poly_max_coord>::iround(a * b / c); m_f1 = clipping_flags(x1, y1, m_clip_box);
} }
static int xi(int v) { return v; }
static int yi(int v) { return v; }
static int upscale(double v)
{
return saturation<poly_max_coord>::iround(v * poly_subpixel_scale);
}
static int downscale(int v) { return v; }
};
//---------------------------------------------------------ras_conv_int_3x private:
struct ras_conv_int_3x //------------------------------------------------------------------------
template<class Rasterizer>
AGG_INLINE void
line_clip_y(Rasterizer& ras, coord_type x1, coord_type y1, coord_type x2, coord_type y2, unsigned f1, unsigned f2)
const
{ {
typedef int coord_type; f1 &= 10;
static AGG_INLINE int mul_div(double a, double b, double c) f2 &= 10;
if ((f1 | f2) == 0)
{ {
return iround(a * b / c); // Fully visible
ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2));
} }
static int xi(int v) { return v * 3; } else
static int yi(int v) { return v; }
static int upscale(double v) { return iround(v * poly_subpixel_scale); }
static int downscale(int v) { return v; }
};
//-----------------------------------------------------------ras_conv_dbl
struct ras_conv_dbl
{
typedef double coord_type;
static AGG_INLINE double mul_div(double a, double b, double c)
{ {
return a * b / c; if (f1 == f2)
}
static int xi(double v) { return iround(v * poly_subpixel_scale); }
static int yi(double v) { return iround(v * poly_subpixel_scale); }
static double upscale(double v) { return v; }
static double downscale(int v) { return v / double(poly_subpixel_scale); }
};
//--------------------------------------------------------ras_conv_dbl_3x
struct ras_conv_dbl_3x
{
typedef double coord_type;
static AGG_INLINE double mul_div(double a, double b, double c)
{
return a * b / c;
}
static int xi(double v) { return iround(v * poly_subpixel_scale * 3); }
static int yi(double v) { return iround(v * poly_subpixel_scale); }
static double upscale(double v) { return v; }
static double downscale(int v) { return v / double(poly_subpixel_scale); }
};
//------------------------------------------------------rasterizer_sl_clip
template<class Conv> class rasterizer_sl_clip
{
public:
typedef Conv conv_type;
typedef typename Conv::coord_type coord_type;
typedef rect_base<coord_type> rect_type;
//--------------------------------------------------------------------
rasterizer_sl_clip() :
m_clip_box(0,0,0,0),
m_x1(0),
m_y1(0),
m_f1(0),
m_clipping(false)
{}
//--------------------------------------------------------------------
void reset_clipping()
{
m_clipping = false;
}
//--------------------------------------------------------------------
void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2)
{
m_clip_box = rect_type(x1, y1, x2, y2);
m_clip_box.normalize();
m_clipping = true;
}
//--------------------------------------------------------------------
void move_to(coord_type x1, coord_type y1)
{
m_x1 = x1;
m_y1 = y1;
if(m_clipping) m_f1 = clipping_flags(x1, y1, m_clip_box);
}
private:
//------------------------------------------------------------------------
template<class Rasterizer>
AGG_INLINE void line_clip_y(Rasterizer& ras,
coord_type x1, coord_type y1,
coord_type x2, coord_type y2,
unsigned f1, unsigned f2) const
{
f1 &= 10;
f2 &= 10;
if((f1 | f2) == 0)
{ {
// Fully visible // Invisible by Y
ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2)); return;
} }
else
coord_type tx1 = x1;
coord_type ty1 = y1;
coord_type tx2 = x2;
coord_type ty2 = y2;
if (f1 & 8) // y1 < clip.y1
{ {
if(f1 == f2) tx1 = x1 + Conv::mul_div(m_clip_box.y1 - y1, x2 - x1, y2 - y1);
{ ty1 = m_clip_box.y1;
// Invisible by Y
return;
}
coord_type tx1 = x1;
coord_type ty1 = y1;
coord_type tx2 = x2;
coord_type ty2 = y2;
if(f1 & 8) // y1 < clip.y1
{
tx1 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
ty1 = m_clip_box.y1;
}
if(f1 & 2) // y1 > clip.y2
{
tx1 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
ty1 = m_clip_box.y2;
}
if(f2 & 8) // y2 < clip.y1
{
tx2 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
ty2 = m_clip_box.y1;
}
if(f2 & 2) // y2 > clip.y2
{
tx2 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
ty2 = m_clip_box.y2;
}
ras.line(Conv::xi(tx1), Conv::yi(ty1),
Conv::xi(tx2), Conv::yi(ty2));
} }
}
if (f1 & 2) // y1 > clip.y2
public:
//--------------------------------------------------------------------
template<class Rasterizer>
void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
{
if(m_clipping)
{ {
unsigned f2 = clipping_flags(x2, y2, m_clip_box); tx1 = x1 + Conv::mul_div(m_clip_box.y2 - y1, x2 - x1, y2 - y1);
ty1 = m_clip_box.y2;
}
if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0) if (f2 & 8) // y2 < clip.y1
{ {
// Invisible by Y tx2 = x1 + Conv::mul_div(m_clip_box.y1 - y1, x2 - x1, y2 - y1);
m_x1 = x2; ty2 = m_clip_box.y1;
m_y1 = y2; }
m_f1 = f2;
return;
}
coord_type x1 = m_x1; if (f2 & 2) // y2 > clip.y2
coord_type y1 = m_y1; {
unsigned f1 = m_f1; tx2 = x1 + Conv::mul_div(m_clip_box.y2 - y1, x2 - x1, y2 - y1);
coord_type y3, y4; ty2 = m_clip_box.y2;
unsigned f3, f4; }
ras.line(Conv::xi(tx1), Conv::yi(ty1), Conv::xi(tx2), Conv::yi(ty2));
}
}
switch(((f1 & 5) << 1) | (f2 & 5)) public:
{ //--------------------------------------------------------------------
template<class Rasterizer>
void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
{
if (m_clipping)
{
unsigned f2 = clipping_flags(x2, y2, m_clip_box);
if ((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0)
{
// Invisible by Y
m_x1 = x2;
m_y1 = y2;
m_f1 = f2;
return;
}
coord_type x1 = m_x1;
coord_type y1 = m_y1;
unsigned f1 = m_f1;
coord_type y3, y4;
unsigned f3, f4;
switch (((f1 & 5) << 1) | (f2 & 5))
{
case 0: // Visible by X case 0: // Visible by X
line_clip_y(ras, x1, y1, x2, y2, f1, f2); line_clip_y(ras, x1, y1, x2, y2, f1, f2);
break; break;
case 1: // x2 > clip.x2 case 1: // x2 > clip.x2
y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); y3 = y1 + Conv::mul_div(m_clip_box.x2 - x1, y2 - y1, x2 - x1);
f3 = clipping_flags_y(y3, m_clip_box); f3 = clipping_flags_y(y3, m_clip_box);
line_clip_y(ras, x1, y1, m_clip_box.x2, y3, f1, f3); line_clip_y(ras, x1, y1, m_clip_box.x2, y3, f1, f3);
line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x2, y2, f3, f2); line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x2, y2, f3, f2);
break; break;
case 2: // x1 > clip.x2 case 2: // x1 > clip.x2
y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); y3 = y1 + Conv::mul_div(m_clip_box.x2 - x1, y2 - y1, x2 - x1);
f3 = clipping_flags_y(y3, m_clip_box); f3 = clipping_flags_y(y3, m_clip_box);
line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3); line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3);
line_clip_y(ras, m_clip_box.x2, y3, x2, y2, f3, f2); line_clip_y(ras, m_clip_box.x2, y3, x2, y2, f3, f2);
@ -247,15 +222,15 @@ namespace agg
break; break;
case 4: // x2 < clip.x1 case 4: // x2 < clip.x1
y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); y3 = y1 + Conv::mul_div(m_clip_box.x1 - x1, y2 - y1, x2 - x1);
f3 = clipping_flags_y(y3, m_clip_box); f3 = clipping_flags_y(y3, m_clip_box);
line_clip_y(ras, x1, y1, m_clip_box.x1, y3, f1, f3); line_clip_y(ras, x1, y1, m_clip_box.x1, y3, f1, f3);
line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x1, y2, f3, f2); line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x1, y2, f3, f2);
break; break;
case 6: // x1 > clip.x2 && x2 < clip.x1 case 6: // x1 > clip.x2 && x2 < clip.x1
y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); y3 = y1 + Conv::mul_div(m_clip_box.x2 - x1, y2 - y1, x2 - x1);
y4 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); y4 = y1 + Conv::mul_div(m_clip_box.x1 - x1, y2 - y1, x2 - x1);
f3 = clipping_flags_y(y3, m_clip_box); f3 = clipping_flags_y(y3, m_clip_box);
f4 = clipping_flags_y(y4, m_clip_box); f4 = clipping_flags_y(y4, m_clip_box);
line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3); line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3);
@ -264,15 +239,15 @@ namespace agg
break; break;
case 8: // x1 < clip.x1 case 8: // x1 < clip.x1
y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); y3 = y1 + Conv::mul_div(m_clip_box.x1 - x1, y2 - y1, x2 - x1);
f3 = clipping_flags_y(y3, m_clip_box); f3 = clipping_flags_y(y3, m_clip_box);
line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3); line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3);
line_clip_y(ras, m_clip_box.x1, y3, x2, y2, f3, f2); line_clip_y(ras, m_clip_box.x1, y3, x2, y2, f3, f2);
break; break;
case 9: // x1 < clip.x1 && x2 > clip.x2 case 9: // x1 < clip.x1 && x2 > clip.x2
y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); y3 = y1 + Conv::mul_div(m_clip_box.x1 - x1, y2 - y1, x2 - x1);
y4 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); y4 = y1 + Conv::mul_div(m_clip_box.x2 - x1, y2 - y1, x2 - x1);
f3 = clipping_flags_y(y3, m_clip_box); f3 = clipping_flags_y(y3, m_clip_box);
f4 = clipping_flags_y(y4, m_clip_box); f4 = clipping_flags_y(y4, m_clip_box);
line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3); line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3);
@ -283,69 +258,69 @@ namespace agg
case 12: // x1 < clip.x1 && x2 < clip.x1 case 12: // x1 < clip.x1 && x2 < clip.x1
line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y2, f1, f2); line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y2, f1, f2);
break; break;
}
m_f1 = f2;
} }
else m_f1 = f2;
{
ras.line(Conv::xi(m_x1), Conv::yi(m_y1),
Conv::xi(x2), Conv::yi(y2));
}
m_x1 = x2;
m_y1 = y2;
} }
else
private:
rect_type m_clip_box;
coord_type m_x1;
coord_type m_y1;
unsigned m_f1;
bool m_clipping;
};
//---------------------------------------------------rasterizer_sl_no_clip
class rasterizer_sl_no_clip
{
public:
typedef ras_conv_int conv_type;
typedef int coord_type;
rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {}
void reset_clipping() {}
void clip_box(coord_type /*x1*/, coord_type /*y1*/, coord_type /*x2*/, coord_type /*y2*/) {}
void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; }
template<class Rasterizer>
void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
{ {
ras.line(m_x1, m_y1, x2, y2); ras.line(Conv::xi(m_x1), Conv::yi(m_y1), Conv::xi(x2), Conv::yi(y2));
m_x1 = x2;
m_y1 = y2;
} }
m_x1 = x2;
m_y1 = y2;
}
private: private:
int m_x1, m_y1; rect_type m_clip_box;
}; coord_type m_x1;
coord_type m_y1;
unsigned m_f1;
bool m_clipping;
};
//---------------------------------------------------rasterizer_sl_no_clip
class rasterizer_sl_no_clip
{
public:
typedef ras_conv_int conv_type;
typedef int coord_type;
// -----rasterizer_sl_clip_int rasterizer_sl_no_clip()
// -----rasterizer_sl_clip_int_sat : m_x1(0)
// -----rasterizer_sl_clip_int_3x , m_y1(0)
// -----rasterizer_sl_clip_dbl {}
// -----rasterizer_sl_clip_dbl_3x
//------------------------------------------------------------------------
typedef rasterizer_sl_clip<ras_conv_int> rasterizer_sl_clip_int;
typedef rasterizer_sl_clip<ras_conv_int_sat> rasterizer_sl_clip_int_sat;
typedef rasterizer_sl_clip<ras_conv_int_3x> rasterizer_sl_clip_int_3x;
typedef rasterizer_sl_clip<ras_conv_dbl> rasterizer_sl_clip_dbl;
typedef rasterizer_sl_clip<ras_conv_dbl_3x> rasterizer_sl_clip_dbl_3x;
void reset_clipping() {}
void clip_box(coord_type /*x1*/, coord_type /*y1*/, coord_type /*x2*/, coord_type /*y2*/) {}
void move_to(coord_type x1, coord_type y1)
{
m_x1 = x1;
m_y1 = y1;
}
} template<class Rasterizer>
void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
{
ras.line(m_x1, m_y1, x2, y2);
m_x1 = x2;
m_y1 = y2;
}
private:
int m_x1, m_y1;
};
// -----rasterizer_sl_clip_int
// -----rasterizer_sl_clip_int_sat
// -----rasterizer_sl_clip_int_3x
// -----rasterizer_sl_clip_dbl
// -----rasterizer_sl_clip_dbl_3x
//------------------------------------------------------------------------
typedef rasterizer_sl_clip<ras_conv_int> rasterizer_sl_clip_int;
typedef rasterizer_sl_clip<ras_conv_int_sat> rasterizer_sl_clip_int_sat;
typedef rasterizer_sl_clip<ras_conv_int_3x> rasterizer_sl_clip_int_3x;
typedef rasterizer_sl_clip<ras_conv_dbl> rasterizer_sl_clip_dbl;
typedef rasterizer_sl_clip<ras_conv_dbl_3x> rasterizer_sl_clip_dbl_3x;
} // namespace agg
#endif #endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -24,326 +24,303 @@
#include "agg_array.h" #include "agg_array.h"
#include "agg_renderer_base.h" #include "agg_renderer_base.h"
namespace agg namespace agg {
//----------------------------------------------------------renderer_mclip
template<class PixelFormat>
class renderer_mclip
{ {
public:
typedef PixelFormat pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::row_data row_data;
typedef renderer_base<pixfmt_type> base_ren_type;
//----------------------------------------------------------renderer_mclip //--------------------------------------------------------------------
template<class PixelFormat> class renderer_mclip explicit renderer_mclip(pixfmt_type& pixf)
: m_ren(pixf)
, m_curr_cb(0)
, m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax())
{}
void attach(pixfmt_type& pixf)
{ {
public: m_ren.attach(pixf);
typedef PixelFormat pixfmt_type; reset_clipping(true);
typedef typename pixfmt_type::color_type color_type; }
typedef typename pixfmt_type::row_data row_data;
typedef renderer_base<pixfmt_type> base_ren_type;
//-------------------------------------------------------------------- //--------------------------------------------------------------------
explicit renderer_mclip(pixfmt_type& pixf) : const pixfmt_type& ren() const { return m_ren.ren(); }
m_ren(pixf), pixfmt_type& ren() { return m_ren.ren(); }
m_curr_cb(0),
m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax()) //--------------------------------------------------------------------
{} unsigned width() const { return m_ren.width(); }
void attach(pixfmt_type& pixf) unsigned height() const { return m_ren.height(); }
//--------------------------------------------------------------------
const rect_i& clip_box() const { return m_ren.clip_box(); }
int xmin() const { return m_ren.xmin(); }
int ymin() const { return m_ren.ymin(); }
int xmax() const { return m_ren.xmax(); }
int ymax() const { return m_ren.ymax(); }
//--------------------------------------------------------------------
const rect_i& bounding_clip_box() const { return m_bounds; }
int bounding_xmin() const { return m_bounds.x1; }
int bounding_ymin() const { return m_bounds.y1; }
int bounding_xmax() const { return m_bounds.x2; }
int bounding_ymax() const { return m_bounds.y2; }
//--------------------------------------------------------------------
void first_clip_box()
{
m_curr_cb = 0;
if (m_clip.size())
{ {
m_ren.attach(pixf); const rect_i& cb = m_clip[0];
reset_clipping(true); m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
} }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
const pixfmt_type& ren() const { return m_ren.ren(); } bool next_clip_box()
pixfmt_type& ren() { return m_ren.ren(); } {
if (++m_curr_cb < m_clip.size())
//--------------------------------------------------------------------
unsigned width() const { return m_ren.width(); }
unsigned height() const { return m_ren.height(); }
//--------------------------------------------------------------------
const rect_i& clip_box() const { return m_ren.clip_box(); }
int xmin() const { return m_ren.xmin(); }
int ymin() const { return m_ren.ymin(); }
int xmax() const { return m_ren.xmax(); }
int ymax() const { return m_ren.ymax(); }
//--------------------------------------------------------------------
const rect_i& bounding_clip_box() const { return m_bounds; }
int bounding_xmin() const { return m_bounds.x1; }
int bounding_ymin() const { return m_bounds.y1; }
int bounding_xmax() const { return m_bounds.x2; }
int bounding_ymax() const { return m_bounds.y2; }
//--------------------------------------------------------------------
void first_clip_box()
{ {
m_curr_cb = 0; const rect_i& cb = m_clip[m_curr_cb];
if(m_clip.size()) 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_i cb(x1, y1, x2, y2);
cb.normalize();
if (cb.clip(rect_i(0, 0, width() - 1, height() - 1)))
{
m_clip.add(cb);
if (cb.x1 < m_bounds.x1)
m_bounds.x1 = cb.x1;
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))
{ {
const rect_i& cb = m_clip[0]; m_ren.ren().copy_pixel(x, y, c);
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); break;
} }
} } while (next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
bool next_clip_box() void blend_pixel(int x, int y, const color_type& c, cover_type cover)
{
first_clip_box();
do
{ {
if(++m_curr_cb < m_clip.size()) if (m_ren.inbox(x, y))
{ {
const rect_i& cb = m_clip[m_curr_cb]; m_ren.ren().blend_pixel(x, y, c, cover);
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); break;
return true;
} }
return false; } while (next_clip_box());
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void reset_clipping(bool visibility) color_type pixel(int x, int y) const
{
first_clip_box();
do
{ {
m_ren.reset_clipping(visibility); if (m_ren.inbox(x, y))
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_i cb(x1, y1, x2, y2);
cb.normalize();
if(cb.clip(rect_i(0, 0, width() - 1, height() - 1)))
{ {
m_clip.add(cb); return m_ren.ren().pixel(x, y);
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;
} }
} } while (next_clip_box());
return color_type::no_color();
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void clear(const color_type& c) void copy_hline(int x1, int y, int x2, const color_type& c)
{
first_clip_box();
do
{ {
m_ren.clear(c); m_ren.copy_hline(x1, y, x2, c);
} } while (next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c) void copy_vline(int x, int y1, int y2, const color_type& c)
{
first_clip_box();
do
{ {
first_clip_box(); m_ren.copy_vline(x, y1, y2, c);
do } while (next_clip_box());
{ }
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) void blend_hline(int x1, int y, int x2, const color_type& c, cover_type cover)
{
first_clip_box();
do
{ {
first_clip_box(); m_ren.blend_hline(x1, y, x2, c, cover);
do } while (next_clip_box());
{ }
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 void blend_vline(int x, int y1, int y2, const color_type& c, cover_type cover)
{
first_clip_box();
do
{ {
first_clip_box(); m_ren.blend_vline(x, y1, y2, c, cover);
do } while (next_clip_box());
{ }
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) void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
{
first_clip_box();
do
{ {
first_clip_box(); m_ren.copy_bar(x1, y1, x2, y2, c);
do } while (next_clip_box());
{ }
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) void blend_bar(int x1, int y1, int x2, int y2, const color_type& c, cover_type cover)
{
first_clip_box();
do
{ {
first_clip_box(); m_ren.blend_bar(x1, y1, x2, y2, c, cover);
do } while (next_clip_box());
{ }
m_ren.copy_vline(x, y1, y2, c);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_hline(int x1, int y, int x2, void blend_solid_hspan(int x, int y, int len, const color_type& c, const cover_type* covers)
const color_type& c, cover_type cover) {
first_clip_box();
do
{ {
first_clip_box(); m_ren.blend_solid_hspan(x, y, len, c, covers);
do } while (next_clip_box());
{ }
m_ren.blend_hline(x1, y, x2, c, cover);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_vline(int x, int y1, int y2, void blend_solid_vspan(int x, int y, int len, const color_type& c, const cover_type* covers)
const color_type& c, cover_type cover) {
first_clip_box();
do
{ {
first_clip_box(); m_ren.blend_solid_vspan(x, y, len, c, covers);
do } while (next_clip_box());
{ }
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) void copy_color_hspan(int x, int y, int len, const color_type* colors)
{
first_clip_box();
do
{ {
first_clip_box(); m_ren.copy_color_hspan(x, y, len, colors);
do } while (next_clip_box());
{ }
m_ren.copy_bar(x1, y1, x2, y2, c);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_bar(int x1, int y1, int x2, int y2, void blend_color_hspan(int x,
const color_type& c, cover_type cover) int y,
int len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
first_clip_box();
do
{ {
first_clip_box(); m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
do } while (next_clip_box());
{ }
m_ren.blend_bar(x1, y1, x2, y2, c, cover);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, int len, void blend_color_vspan(int x,
const color_type& c, const cover_type* covers) int y,
int len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
first_clip_box();
do
{ {
first_clip_box(); m_ren.blend_color_vspan(x, y, len, colors, covers, cover);
do } while (next_clip_box());
{ }
m_ren.blend_solid_hspan(x, y, len, c, covers);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_solid_vspan(int x, int y, int len, void copy_from(const rendering_buffer& from, const rect_i* rc = 0, int x_to = 0, int y_to = 0)
const color_type& c, const cover_type* covers) {
first_clip_box();
do
{ {
first_clip_box(); m_ren.copy_from(from, rc, x_to, y_to);
do } while (next_clip_box());
{ }
m_ren.blend_solid_vspan(x, y, len, c, covers);
}
while(next_clip_box());
}
//--------------------------------------------------------------------
//-------------------------------------------------------------------- template<class SrcPixelFormatRenderer>
void copy_color_hspan(int x, int y, int len, const color_type* colors) void blend_from(const SrcPixelFormatRenderer& src,
const rect_i* rect_src_ptr = 0,
int dx = 0,
int dy = 0,
cover_type cover = cover_full)
{
first_clip_box();
do
{ {
first_clip_box(); m_ren.blend_from(src, rect_src_ptr, dx, dy, cover);
do } while (next_clip_box());
{ }
m_ren.copy_color_hspan(x, y, len, colors);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- private:
void blend_color_hspan(int x, int y, int len, renderer_mclip(const renderer_mclip<PixelFormat>&);
const color_type* colors, const renderer_mclip<PixelFormat>& operator=(const renderer_mclip<PixelFormat>&);
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());
}
//-------------------------------------------------------------------- base_ren_type m_ren;
void blend_color_vspan(int x, int y, int len, pod_bvector<rect_i, 4> m_clip;
const color_type* colors, unsigned m_curr_cb;
const cover_type* covers, rect_i m_bounds;
cover_type cover = cover_full) };
{
first_clip_box();
do
{
m_ren.blend_color_vspan(x, y, len, colors, covers, cover);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- } // namespace agg
void copy_from(const rendering_buffer& from,
const rect_i* rc=0,
int x_to=0,
int y_to=0)
{
first_clip_box();
do
{
m_ren.copy_from(from, rc, x_to, y_to);
}
while(next_clip_box());
}
//--------------------------------------------------------------------
template<class SrcPixelFormatRenderer>
void blend_from(const SrcPixelFormatRenderer& src,
const rect_i* rect_src_ptr = 0,
int dx = 0,
int dy = 0,
cover_type cover = cover_full)
{
first_clip_box();
do
{
m_ren.blend_from(src, rect_src_ptr, dx, dy, cover);
}
while(next_clip_box());
}
private:
renderer_mclip(const renderer_mclip<PixelFormat>&);
const renderer_mclip<PixelFormat>&
operator = (const renderer_mclip<PixelFormat>&);
base_ren_type m_ren;
pod_bvector<rect_i, 4> m_clip;
unsigned m_curr_cb;
rect_i m_bounds;
};
}
#endif #endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -25,200 +25,190 @@
#include "agg_dda_line.h" #include "agg_dda_line.h"
#include "agg_ellipse_bresenham.h" #include "agg_ellipse_bresenham.h"
namespace agg namespace agg {
//-----------------------------------------------------renderer_primitives
template<class BaseRenderer>
class renderer_primitives
{ {
//-----------------------------------------------------renderer_primitives public:
template<class BaseRenderer> class renderer_primitives typedef BaseRenderer base_ren_type;
typedef typename base_ren_type::color_type color_type;
//--------------------------------------------------------------------
explicit renderer_primitives(base_ren_type& ren)
: m_ren(&ren)
, m_fill_color()
, m_line_color()
, m_curr_x(0)
, m_curr_y(0)
{}
void attach(base_ren_type& ren) { m_ren = &ren; }
//--------------------------------------------------------------------
static int coord(double c) { return iround(c * line_bresenham_interpolator::subpixel_scale); }
//--------------------------------------------------------------------
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)
{ {
public: m_ren->blend_hline(x1, y1, x2 - 1, m_line_color, cover_full);
typedef BaseRenderer base_ren_type; m_ren->blend_vline(x2, y1, y2 - 1, m_line_color, cover_full);
typedef typename base_ren_type::color_type color_type; 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);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
explicit renderer_primitives(base_ren_type& ren) : void solid_rectangle(int x1, int y1, int x2, int y2) { m_ren->blend_bar(x1, y1, x2, y2, m_fill_color, cover_full); }
m_ren(&ren),
m_fill_color(),
m_line_color(),
m_curr_x(0),
m_curr_y(0)
{}
void attach(base_ren_type& ren) { m_ren = &ren; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static int coord(double c) 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
{ {
return iround(c * line_bresenham_interpolator::subpixel_scale); 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)
void fill_color(const color_type& c) { m_fill_color = c; } ++len;
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; }
//-------------------------------------------------------------------- if (li.is_ver())
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 do
{ {
dx += ei.dx(); m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full);
dy += ei.dy(); li.vstep();
m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full); } while (--len);
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);
} }
else
//--------------------------------------------------------------------
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 do
{ {
dx += ei.dx(); m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full);
dy += ei.dy(); li.hstep();
} while (--len);
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) void move_to(int x, int y)
{ {
ellipse_bresenham_interpolator ei(rx, ry); m_curr_x = x;
int dx = 0; m_curr_y = y;
int dy = -ry; }
do //--------------------------------------------------------------------
{ void line_to(int x, int y, bool last = false)
dx += ei.dx(); {
dy += ei.dy(); line(m_curr_x, m_curr_y, x, y, last);
m_curr_x = x;
m_curr_y = y;
}
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); const base_ren_type& ren() const { return *m_ren; }
m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full); base_ren_type& ren() { return *m_ren; }
m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
if(ei.dy() && dx) //--------------------------------------------------------------------
{ const rendering_buffer& rbuf() const { return m_ren->rbuf(); }
m_ren->blend_hline(x-dx+1, y+dy, x+dx-1, m_fill_color, cover_full); rendering_buffer& rbuf() { return m_ren->rbuf(); }
m_ren->blend_hline(x-dx+1, y-dy, x+dx-1, m_fill_color, cover_full);
}
++ei;
}
while(dy < 0);
}
//-------------------------------------------------------------------- private:
void line(int x1, int y1, int x2, int y2, bool last=false) base_ren_type* m_ren;
{ color_type m_fill_color;
line_bresenham_interpolator li(x1, y1, x2, y2); color_type m_line_color;
int m_curr_x;
int m_curr_y;
};
unsigned len = li.len(); } // namespace agg
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 #endif

View file

@ -18,247 +18,215 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg 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 renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph)
template<class BaseRenderer, class GlyphGenerator> : m_ren(&ren)
class renderer_raster_htext_solid , m_glyph(&glyph)
{}
void attach(ren_type& ren) { m_ren = &ren; }
//--------------------------------------------------------------------
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)
{ {
public: glyph_rect r;
typedef BaseRenderer ren_type; while (*str)
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 attach(ren_type& ren) { m_ren = &ren; }
//--------------------------------------------------------------------
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; m_glyph->prepare(&r, x, y, *str, flip);
while(*str) if (r.x2 >= r.x1)
{ {
m_glyph->prepare(&r, x, y, *str, flip); int i;
if(r.x2 >= r.x1) if (flip)
{ {
int i; for (i = r.y1; i <= r.y2; 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));
{
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; else
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; for (i = r.y1; i <= r.y2; 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(i - r.y1));
{
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;
} }
x += r.dx;
y += r.dy;
++str;
} }
}
private: private:
ren_type* m_ren; ren_type* m_ren;
glyph_gen_type* m_glyph; glyph_gen_type* m_glyph;
color_type m_color; 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>
//===================================================renderer_raster_htext void render_text(double x, double y, const CharT* str, bool flip = false)
template<class ScanlineRenderer, class GlyphGenerator>
class renderer_raster_htext
{ {
public: glyph_rect r;
typedef ScanlineRenderer ren_type; while (*str)
typedef GlyphGenerator glyph_gen_type;
typedef typename glyph_gen_type::glyph_rect glyph_rect;
class scanline_single_span
{ {
public: m_glyph->prepare(&r, x, y, *str, !flip);
typedef agg::cover_type cover_type; if (r.x2 >= r.x1)
//----------------------------------------------------------------
struct const_span
{ {
int x; int i;
unsigned len; if (flip)
const cover_type* covers; {
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;
}
}
const_span() {} private:
const_span(int x_, unsigned len_, const cover_type* covers_) : ren_type* m_ren;
x(x_), len(len_), covers(covers_) glyph_gen_type* m_glyph;
{} color_type m_color;
}; };
typedef const const_span* const_iterator; //===================================================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
scanline_single_span(int x, int y, unsigned len, {
const cover_type* covers) : public:
m_y(y), typedef agg::cover_type cover_type;
m_span(x, len, covers)
//----------------------------------------------------------------
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_)
{} {}
//----------------------------------------------------------------
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;
}; };
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)
{}
//-------------------------------------------------------------------- //----------------------------------------------------------------
renderer_raster_htext(ren_type& ren, glyph_gen_type& glyph) : int y() const { return m_y; }
m_ren(&ren), unsigned num_spans() const { return 1; }
m_glyph(&glyph) const_iterator begin() const { return &m_span; }
{
}
private:
//-------------------------------------------------------------------- //----------------------------------------------------------------
template<class CharT> int m_y;
void render_text(double x, double y, const CharT* str, bool flip=false) const_span m_span;
{
glyph_rect r;
while(*str)
{
m_glyph->prepare(&r, x, y, *str, flip);
if(r.x2 >= r.x1)
{
m_ren->prepare();
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;
}; };
//--------------------------------------------------------------------
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();
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;
};
} } // namespace agg
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -22,284 +22,261 @@
#include "agg_array.h" #include "agg_array.h"
namespace agg namespace agg {
//===========================================================row_accessor
template<class T>
class row_accessor
{ {
public:
typedef const_row_info<T> row_data;
//===========================================================row_accessor //-------------------------------------------------------------------
template<class T> class row_accessor row_accessor()
: m_buf(0)
, m_start(0)
, m_width(0)
, m_height(0)
, m_stride(0)
{}
//--------------------------------------------------------------------
row_accessor(T* buf, unsigned width, unsigned height, int stride)
: m_buf(0)
, m_start(0)
, m_width(0)
, m_height(0)
, m_stride(0)
{ {
public: attach(buf, width, height, stride);
typedef const_row_info<T> row_data; }
//------------------------------------------------------------------- //--------------------------------------------------------------------
row_accessor() : void attach(T* buf, unsigned width, unsigned height, int stride)
m_buf(0),
m_start(0),
m_width(0),
m_height(0),
m_stride(0)
{
}
//--------------------------------------------------------------------
row_accessor(T* buf, unsigned width, unsigned height, int stride) :
m_buf(0),
m_start(0),
m_width(0),
m_height(0),
m_stride(0)
{
attach(buf, width, height, stride);
}
//--------------------------------------------------------------------
void attach(T* buf, unsigned width, unsigned height, int stride)
{
m_buf = m_start = buf;
m_width = width;
m_height = height;
m_stride = stride;
if(stride < 0)
{
m_start = m_buf - int(height - 1) * stride;
}
}
//--------------------------------------------------------------------
AGG_INLINE T* buf() { return m_buf; }
AGG_INLINE const T* buf() const { return m_buf; }
AGG_INLINE unsigned width() const { return m_width; }
AGG_INLINE unsigned height() const { return m_height; }
AGG_INLINE int stride() const { return m_stride; }
AGG_INLINE unsigned stride_abs() const
{
return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
}
//--------------------------------------------------------------------
AGG_INLINE T* row_ptr(int, int y, unsigned)
{
return m_start + y * m_stride;
}
AGG_INLINE T* row_ptr(int y) { return m_start + y * m_stride; }
AGG_INLINE const T* row_ptr(int y) const { return m_start + y * m_stride; }
AGG_INLINE row_data row (int y) const
{
return row_data(0, m_width-1, row_ptr(y));
}
//--------------------------------------------------------------------
template<class RenBuf>
void copy_from(const RenBuf& src)
{
unsigned h = height();
if(src.height() < h) h = src.height();
unsigned l = stride_abs();
if(src.stride_abs() < l) l = src.stride_abs();
l *= sizeof(T);
unsigned y;
unsigned w = width();
for (y = 0; y < h; y++)
{
memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
}
}
//--------------------------------------------------------------------
void clear(T value)
{
unsigned y;
unsigned w = width();
unsigned stride = stride_abs();
for(y = 0; y < height(); y++)
{
T* p = row_ptr(0, y, w);
unsigned x;
for(x = 0; x < stride; x++)
{
*p++ = value;
}
}
}
private:
//--------------------------------------------------------------------
T* m_buf; // Pointer to rendering buffer
T* m_start; // Pointer to first pixel depending on stride
unsigned m_width; // Width in pixels
unsigned m_height; // Height in pixels
int m_stride; // Number of bytes per row. Can be < 0
};
//==========================================================row_ptr_cache
template<class T> class row_ptr_cache
{ {
public: m_buf = m_start = buf;
typedef const_row_info<T> row_data; m_width = width;
m_height = height;
//------------------------------------------------------------------- m_stride = stride;
row_ptr_cache() : if (stride < 0)
m_buf(0),
m_rows(),
m_width(0),
m_height(0),
m_stride(0)
{ {
m_start = m_buf - int(height - 1) * stride;
} }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) : AGG_INLINE T* buf() { return m_buf; }
m_buf(0), AGG_INLINE const T* buf() const { return m_buf; }
m_rows(), AGG_INLINE unsigned width() const { return m_width; }
m_width(0), AGG_INLINE unsigned height() const { return m_height; }
m_height(0), AGG_INLINE int stride() const { return m_stride; }
m_stride(0) AGG_INLINE unsigned stride_abs() const { return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); }
//--------------------------------------------------------------------
AGG_INLINE T* row_ptr(int, int y, unsigned) { return m_start + y * m_stride; }
AGG_INLINE T* row_ptr(int y) { return m_start + y * m_stride; }
AGG_INLINE const T* row_ptr(int y) const { return m_start + y * m_stride; }
AGG_INLINE row_data row(int y) const { return row_data(0, m_width - 1, row_ptr(y)); }
//--------------------------------------------------------------------
template<class RenBuf>
void copy_from(const RenBuf& src)
{
unsigned h = height();
if (src.height() < h)
h = src.height();
unsigned l = stride_abs();
if (src.stride_abs() < l)
l = src.stride_abs();
l *= sizeof(T);
unsigned y;
unsigned w = width();
for (y = 0; y < h; y++)
{ {
attach(buf, width, height, stride); memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
} }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void attach(T* buf, unsigned width, unsigned height, int stride) void clear(T value)
{
unsigned y;
unsigned w = width();
unsigned stride = stride_abs();
for (y = 0; y < height(); y++)
{ {
m_buf = buf; T* p = row_ptr(0, y, w);
m_width = width; unsigned x;
m_height = height; for (x = 0; x < stride; x++)
m_stride = stride;
if(height > m_rows.size())
{ {
m_rows.resize(height); *p++ = value;
}
else if(height == 0)
{
return;
}
T* row_ptr = m_buf;
if(stride < 0)
{
row_ptr = m_buf - int(height - 1) * stride;
}
T** rows = &m_rows[0];
while(height > 0)
{
*rows++ = row_ptr;
row_ptr += stride;
--height;
} }
} }
}
//-------------------------------------------------------------------- private:
AGG_INLINE T* buf() { return m_buf; } //--------------------------------------------------------------------
AGG_INLINE const T* buf() const { return m_buf; } T* m_buf; // Pointer to rendering buffer
AGG_INLINE unsigned width() const { return m_width; } T* m_start; // Pointer to first pixel depending on stride
AGG_INLINE unsigned height() const { return m_height; } unsigned m_width; // Width in pixels
AGG_INLINE int stride() const { return m_stride; } unsigned m_height; // Height in pixels
AGG_INLINE unsigned stride_abs() const int m_stride; // Number of bytes per row. Can be < 0
};
//==========================================================row_ptr_cache
template<class T>
class row_ptr_cache
{
public:
typedef const_row_info<T> row_data;
//-------------------------------------------------------------------
row_ptr_cache()
: m_buf(0)
, m_rows()
, m_width(0)
, m_height(0)
, m_stride(0)
{}
//--------------------------------------------------------------------
row_ptr_cache(T* buf, unsigned width, unsigned height, int stride)
: m_buf(0)
, m_rows()
, m_width(0)
, m_height(0)
, m_stride(0)
{
attach(buf, width, height, stride);
}
//--------------------------------------------------------------------
void attach(T* buf, unsigned width, unsigned height, int stride)
{
m_buf = buf;
m_width = width;
m_height = height;
m_stride = stride;
if (height > m_rows.size())
{ {
return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); m_rows.resize(height);
}
else if (height == 0)
{
return;
} }
//-------------------------------------------------------------------- T* row_ptr = m_buf;
AGG_INLINE T* row_ptr(int, int y, unsigned)
if (stride < 0)
{ {
return m_rows[y]; row_ptr = m_buf - int(height - 1) * stride;
}
AGG_INLINE T* row_ptr(int y) { return m_rows[y]; }
AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; }
AGG_INLINE row_data row (int y) const
{
return row_data(0, m_width-1, m_rows[y]);
} }
//-------------------------------------------------------------------- T** rows = &m_rows[0];
T const* const* rows() const { return &m_rows[0]; }
//-------------------------------------------------------------------- while (height > 0)
template<class RenBuf>
void copy_from(const RenBuf& src)
{ {
unsigned h = height(); *rows++ = row_ptr;
if(src.height() < h) h = src.height(); row_ptr += stride;
--height;
}
}
unsigned l = stride_abs(); //--------------------------------------------------------------------
if(src.stride_abs() < l) l = src.stride_abs(); AGG_INLINE T* buf() { return m_buf; }
AGG_INLINE const T* buf() const { return m_buf; }
AGG_INLINE unsigned width() const { return m_width; }
AGG_INLINE unsigned height() const { return m_height; }
AGG_INLINE int stride() const { return m_stride; }
AGG_INLINE unsigned stride_abs() const { return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); }
l *= sizeof(T); //--------------------------------------------------------------------
AGG_INLINE T* row_ptr(int, int y, unsigned) { return m_rows[y]; }
AGG_INLINE T* row_ptr(int y) { return m_rows[y]; }
AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; }
AGG_INLINE row_data row(int y) const { return row_data(0, m_width - 1, m_rows[y]); }
unsigned y; //--------------------------------------------------------------------
unsigned w = width(); T const* const* rows() const { return &m_rows[0]; }
for (y = 0; y < h; y++)
//--------------------------------------------------------------------
template<class RenBuf>
void copy_from(const RenBuf& src)
{
unsigned h = height();
if (src.height() < h)
h = src.height();
unsigned l = stride_abs();
if (src.stride_abs() < l)
l = src.stride_abs();
l *= sizeof(T);
unsigned y;
unsigned w = width();
for (y = 0; y < h; y++)
{
memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
}
}
//--------------------------------------------------------------------
void clear(T value)
{
unsigned y;
unsigned w = width();
unsigned stride = stride_abs();
for (y = 0; y < height(); y++)
{
T* p = row_ptr(0, y, w);
unsigned x;
for (x = 0; x < stride; x++)
{ {
memcpy(row_ptr(0, y, w), src.row_ptr(y), l); *p++ = value;
} }
} }
}
//-------------------------------------------------------------------- private:
void clear(T value) //--------------------------------------------------------------------
{ T* m_buf; // Pointer to rendering buffer
unsigned y; pod_array<T*> m_rows; // Pointers to each row of the buffer
unsigned w = width(); unsigned m_width; // Width in pixels
unsigned stride = stride_abs(); unsigned m_height; // Height in pixels
for(y = 0; y < height(); y++) int m_stride; // Number of bytes per row. Can be < 0
{ };
T* p = row_ptr(0, y, w);
unsigned x;
for(x = 0; x < stride; x++)
{
*p++ = value;
}
}
}
private: //========================================================rendering_buffer
//-------------------------------------------------------------------- //
T* m_buf; // Pointer to rendering buffer // The definition of the main type for accessing the rows in the frame
pod_array<T*> m_rows; // Pointers to each row of the buffer // buffer. It provides functionality to navigate to the rows in a
unsigned m_width; // Width in pixels // rectangular matrix, from top to bottom or from bottom to top depending
unsigned m_height; // Height in pixels // on stride.
int m_stride; // Number of bytes per row. Can be < 0 //
}; // row_accessor is cheap to create/destroy, but performs one multiplication
// when calling row_ptr().
//
// row_ptr_cache creates an array of pointers to rows, so, the access
// via row_ptr() may be faster. But it requires memory allocation
//========================================================rendering_buffer // when creating. For example, on typical Intel Pentium hardware
// // row_ptr_cache speeds span_image_filter_rgb_nn up to 10%
// The definition of the main type for accessing the rows in the frame //
// buffer. It provides functionality to navigate to the rows in a // It's used only in short hand typedefs like pixfmt_rgba32 and can be
// rectangular matrix, from top to bottom or from bottom to top depending // redefined in agg_config.h
// on stride. // In real applications you can use both, depending on your needs
// //------------------------------------------------------------------------
// row_accessor is cheap to create/destroy, but performs one multiplication
// when calling row_ptr().
//
// row_ptr_cache creates an array of pointers to rows, so, the access
// via row_ptr() may be faster. But it requires memory allocation
// when creating. For example, on typical Intel Pentium hardware
// row_ptr_cache speeds span_image_filter_rgb_nn up to 10%
//
// It's used only in short hand typedefs like pixfmt_rgba32 and can be
// redefined in agg_config.h
// In real applications you can use both, depending on your needs
//------------------------------------------------------------------------
#ifdef AGG_RENDERING_BUFFER #ifdef AGG_RENDERING_BUFFER
typedef AGG_RENDERING_BUFFER rendering_buffer; typedef AGG_RENDERING_BUFFER rendering_buffer;
#else #else
typedef row_ptr_cache<int8u> rendering_buffer; typedef row_ptr_cache<int8u> rendering_buffer;
//typedef row_accessor<int8u> rendering_buffer; // typedef row_accessor<int8u> rendering_buffer;
#endif #endif
} } // namespace agg
#endif #endif

View file

@ -22,116 +22,114 @@
#include "agg_array.h" #include "agg_array.h"
namespace agg namespace agg {
//===============================================rendering_buffer_dynarow
// Rendering buffer class with dynamic allocation of the rows.
// The rows are allocated as needed when requesting for span_ptr().
// The class automatically calculates min_x and max_x for each row.
// Generally it's more efficient to use this class as a temporary buffer
// for rendering a few lines and then to blend it with another buffer.
//
class rendering_buffer_dynarow
{ {
public:
typedef row_info<int8u> row_data;
//===============================================rendering_buffer_dynarow //-------------------------------------------------------------------
// Rendering buffer class with dynamic allocation of the rows. ~rendering_buffer_dynarow() { init(0, 0, 0); }
// The rows are allocated as needed when requesting for span_ptr().
// The class automatically calculates min_x and max_x for each row. //-------------------------------------------------------------------
// Generally it's more efficient to use this class as a temporary buffer rendering_buffer_dynarow()
// for rendering a few lines and then to blend it with another buffer. : m_rows()
// , m_width(0)
class rendering_buffer_dynarow , m_height(0)
, m_byte_width(0)
{}
// Allocate and clear the buffer
//--------------------------------------------------------------------
rendering_buffer_dynarow(unsigned width, unsigned height, unsigned byte_width)
: m_rows(height)
, m_width(width)
, m_height(height)
, m_byte_width(byte_width)
{ {
public: memset(&m_rows[0], 0, sizeof(row_data) * height);
typedef row_info<int8u> row_data; }
//------------------------------------------------------------------- // Allocate and clear the buffer
~rendering_buffer_dynarow() //--------------------------------------------------------------------
void init(unsigned width, unsigned height, unsigned byte_width)
{
unsigned i;
for (i = 0; i < m_height; ++i)
{ {
init(0,0,0); pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width);
} }
if (width && height)
//-------------------------------------------------------------------
rendering_buffer_dynarow() :
m_rows(),
m_width(0),
m_height(0),
m_byte_width(0)
{
}
// Allocate and clear the buffer
//--------------------------------------------------------------------
rendering_buffer_dynarow(unsigned width, unsigned height,
unsigned byte_width) :
m_rows(height),
m_width(width),
m_height(height),
m_byte_width(byte_width)
{ {
m_width = width;
m_height = height;
m_byte_width = byte_width;
m_rows.resize(height);
memset(&m_rows[0], 0, sizeof(row_data) * height); memset(&m_rows[0], 0, sizeof(row_data) * height);
} }
}
// Allocate and clear the buffer //--------------------------------------------------------------------
//-------------------------------------------------------------------- unsigned width() const { return m_width; }
void init(unsigned width, unsigned height, unsigned byte_width) unsigned height() const { return m_height; }
unsigned byte_width() const { return m_byte_width; }
// The main function used for rendering. Returns pointer to the
// pre-allocated span. Memory for the row is allocated as needed.
//--------------------------------------------------------------------
int8u* row_ptr(int x, int y, unsigned len)
{
row_data* r = &m_rows[y];
int x2 = x + len - 1;
if (r->ptr)
{ {
unsigned i; if (x < r->x1)
for(i = 0; i < m_height; ++i)
{ {
pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width); r->x1 = x;
} }
if(width && height) if (x2 > r->x2)
{ {
m_width = width; r->x2 = x2;
m_height = height;
m_byte_width = byte_width;
m_rows.resize(height);
memset(&m_rows[0], 0, sizeof(row_data) * height);
} }
} }
else
//--------------------------------------------------------------------
unsigned width() const { return m_width; }
unsigned height() const { return m_height; }
unsigned byte_width() const { return m_byte_width; }
// The main function used for rendering. Returns pointer to the
// pre-allocated span. Memory for the row is allocated as needed.
//--------------------------------------------------------------------
int8u* row_ptr(int x, int y, unsigned len)
{ {
row_data* r = &m_rows[y]; int8u* p = pod_allocator<int8u>::allocate(m_byte_width);
int x2 = x + len - 1; r->ptr = p;
if(r->ptr) r->x1 = x;
{ r->x2 = x2;
if(x < r->x1) { r->x1 = x; } memset(p, 0, m_byte_width);
if(x2 > r->x2) { r->x2 = x2; }
}
else
{
int8u* p = pod_allocator<int8u>::allocate(m_byte_width);
r->ptr = p;
r->x1 = x;
r->x2 = x2;
memset(p, 0, m_byte_width);
}
return (int8u*)r->ptr;
} }
return (int8u*)r->ptr;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
const int8u* row_ptr(int y) const { return m_rows[y].ptr; } const int8u* row_ptr(int y) const { return m_rows[y].ptr; }
int8u* row_ptr(int y) { return row_ptr(0, y, m_width); } int8u* row_ptr(int y) { return row_ptr(0, y, m_width); }
row_data row (int y) const { return m_rows[y]; } row_data row(int y) const { return m_rows[y]; }
private: private:
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Prohibit copying // Prohibit copying
rendering_buffer_dynarow(const rendering_buffer_dynarow&); rendering_buffer_dynarow(const rendering_buffer_dynarow&);
const rendering_buffer_dynarow& operator = (const rendering_buffer_dynarow&); const rendering_buffer_dynarow& operator=(const rendering_buffer_dynarow&);
private: private:
//-------------------------------------------------------------------- //--------------------------------------------------------------------
pod_array<row_data> m_rows; // Pointers to each row of the buffer pod_array<row_data> m_rows; // Pointers to each row of the buffer
unsigned m_width; // Width in pixels unsigned m_width; // Width in pixels
unsigned m_height; // Height in pixels unsigned m_height; // Height in pixels
unsigned m_byte_width; // Width in bytes unsigned m_byte_width; // Width in bytes
}; };
}
} // namespace agg
#endif #endif

View file

@ -23,50 +23,47 @@
#include "agg_basics.h" #include "agg_basics.h"
#include "agg_arc.h" #include "agg_arc.h"
namespace agg namespace agg {
//------------------------------------------------------------rounded_rect
//
// See Implemantation agg_rounded_rect.cpp
//
class rounded_rect
{ {
//------------------------------------------------------------rounded_rect public:
// rounded_rect() {}
// See Implemantation agg_rounded_rect.cpp rounded_rect(double x1, double y1, double x2, double y2, double r);
//
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 rect(double x1, double y1, double x2, double y2);
void radius(double r); void radius(double r);
void radius(double rx, double ry); void radius(double rx, double ry);
void radius(double rx_bottom, double ry_bottom, double rx_top, double ry_top); void radius(double rx_bottom, double ry_bottom, double rx_top, double ry_top);
void radius(double rx1, double ry1, double rx2, double ry2, void radius(double rx1, double ry1, double rx2, double ry2, double rx3, double ry3, double rx4, double ry4);
double rx3, double ry3, double rx4, double ry4); void normalize_radius();
void normalize_radius();
void approximation_scale(double s) { m_arc.approximation_scale(s); } void approximation_scale(double s) { m_arc.approximation_scale(s); }
double approximation_scale() const { return m_arc.approximation_scale(); } double approximation_scale() const { return m_arc.approximation_scale(); }
void rewind(unsigned); void rewind(unsigned);
unsigned vertex(double* x, double* y); unsigned vertex(double* x, double* y);
private: private:
double m_x1; double m_x1;
double m_y1; double m_y1;
double m_x2; double m_x2;
double m_y2; double m_y2;
double m_rx1; double m_rx1;
double m_ry1; double m_ry1;
double m_rx2; double m_rx2;
double m_ry2; double m_ry2;
double m_rx3; double m_rx3;
double m_ry3; double m_ry3;
double m_rx4; double m_rx4;
double m_ry4; double m_ry4;
unsigned m_status; unsigned m_status;
arc m_arc; arc m_arc;
}; };
} } // namespace agg
#endif #endif

View file

@ -30,235 +30,215 @@
#include "agg_array.h" #include "agg_array.h"
namespace agg 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.
//
//------------------------------------------------------------------------
class scanline_bin
{ {
public:
typedef int32 coord_type;
//=============================================================scanline_bin struct span
//
// This is binary scaline container which supports the interface
// used in the rasterizer::render(). See description of agg_scanline_u8
// for details.
//
//------------------------------------------------------------------------
class scanline_bin
{ {
public: int16 x;
typedef int32 coord_type; int16 len;
struct span
{
int16 x;
int16 len;
};
typedef const span* const_iterator;
//--------------------------------------------------------------------
scanline_bin() :
m_last_x(0x7FFFFFF0),
m_spans(),
m_cur_span(0)
{
}
//--------------------------------------------------------------------
void reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 3;
if(max_len > m_spans.size())
{
m_spans.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_cur_span = &m_spans[0];
}
//--------------------------------------------------------------------
void add_cell(int x, unsigned)
{
if(x == m_last_x+1)
{
m_cur_span->len++;
}
else
{
++m_cur_span;
m_cur_span->x = (int16)x;
m_cur_span->len = 1;
}
m_last_x = x;
}
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned)
{
if(x == m_last_x+1)
{
m_cur_span->len = (int16)(m_cur_span->len + len);
}
else
{
++m_cur_span;
m_cur_span->x = (int16)x;
m_cur_span->len = (int16)len;
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void add_cells(int x, unsigned len, const void*)
{
add_span(x, len, 0);
}
//--------------------------------------------------------------------
void finalize(int y)
{
m_y = y;
}
//--------------------------------------------------------------------
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cur_span = &m_spans[0];
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
const_iterator begin() const { return &m_spans[1]; }
private:
scanline_bin(const scanline_bin&);
const scanline_bin operator = (const scanline_bin&);
int m_last_x;
int m_y;
pod_array<span> m_spans;
span* m_cur_span;
}; };
typedef const span* const_iterator;
//--------------------------------------------------------------------
scanline_bin()
: m_last_x(0x7FFFFFF0)
, m_spans()
, m_cur_span(0)
{}
//--------------------------------------------------------------------
void reset(int min_x, int max_x)
//===========================================================scanline32_bin
class scanline32_bin
{ {
public: unsigned max_len = max_x - min_x + 3;
typedef int32 coord_type; if (max_len > m_spans.size())
//--------------------------------------------------------------------
struct span
{ {
span() {} m_spans.resize(max_len);
span(coord_type x_, coord_type len_) : x(x_), len(len_) {}
coord_type x;
coord_type len;
};
typedef pod_bvector<span, 4> span_array_type;
//--------------------------------------------------------------------
class const_iterator
{
public:
const_iterator(const span_array_type& spans) :
m_spans(spans),
m_span_idx(0)
{}
const span& operator*() const { return m_spans[m_span_idx]; }
const span* operator->() const { return &m_spans[m_span_idx]; }
void operator ++ () { ++m_span_idx; }
private:
const span_array_type& m_spans;
unsigned m_span_idx;
};
//--------------------------------------------------------------------
scanline32_bin() : m_max_len(0), m_last_x(0x7FFFFFF0) {}
//--------------------------------------------------------------------
void reset(int, int)
{
m_last_x = 0x7FFFFFF0;
m_spans.remove_all();
} }
m_last_x = 0x7FFFFFF0;
m_cur_span = &m_spans[0];
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void add_cell(int x, unsigned) void add_cell(int x, unsigned)
{
if (x == m_last_x + 1)
{ {
if(x == m_last_x+1) m_cur_span->len++;
{
m_spans.last().len++;
}
else
{
m_spans.add(span(coord_type(x), 1));
}
m_last_x = x;
} }
else
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned)
{ {
if(x == m_last_x+1) ++m_cur_span;
{ m_cur_span->x = (int16)x;
m_spans.last().len += coord_type(len); m_cur_span->len = 1;
}
else
{
m_spans.add(span(coord_type(x), coord_type(len)));
}
m_last_x = x + len - 1;
} }
m_last_x = x;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void add_cells(int x, unsigned len, const void*) void add_span(int x, unsigned len, unsigned)
{
if (x == m_last_x + 1)
{ {
add_span(x, len, 0); m_cur_span->len = (int16)(m_cur_span->len + len);
} }
else
//--------------------------------------------------------------------
void finalize(int y)
{ {
m_y = y; ++m_cur_span;
m_cur_span->x = (int16)x;
m_cur_span->len = (int16)len;
} }
m_last_x = x + len - 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void reset_spans() void add_cells(int x, unsigned len, const void*) { add_span(x, len, 0); }
{
m_last_x = 0x7FFFFFF0;
m_spans.remove_all();
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
int y() const { return m_y; } void finalize(int y) { m_y = y; }
unsigned num_spans() const { return m_spans.size(); }
const_iterator begin() const { return const_iterator(m_spans); }
private: //--------------------------------------------------------------------
scanline32_bin(const scanline32_bin&); void reset_spans()
const scanline32_bin operator = (const scanline32_bin&); {
m_last_x = 0x7FFFFFF0;
m_cur_span = &m_spans[0];
}
unsigned m_max_len; //--------------------------------------------------------------------
int m_last_x; int y() const { return m_y; }
int m_y; unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
span_array_type m_spans; const_iterator begin() const { return &m_spans[1]; }
private:
scanline_bin(const scanline_bin&);
const scanline_bin operator=(const scanline_bin&);
int m_last_x;
int m_y;
pod_array<span> m_spans;
span* m_cur_span;
};
//===========================================================scanline32_bin
class scanline32_bin
{
public:
typedef int32 coord_type;
//--------------------------------------------------------------------
struct span
{
span() {}
span(coord_type x_, coord_type len_)
: x(x_)
, len(len_)
{}
coord_type x;
coord_type len;
};
typedef pod_bvector<span, 4> span_array_type;
//--------------------------------------------------------------------
class const_iterator
{
public:
const_iterator(const span_array_type& spans)
: m_spans(spans)
, m_span_idx(0)
{}
const span& operator*() const { return m_spans[m_span_idx]; }
const span* operator->() const { return &m_spans[m_span_idx]; }
void operator++() { ++m_span_idx; }
private:
const span_array_type& m_spans;
unsigned m_span_idx;
}; };
//--------------------------------------------------------------------
scanline32_bin()
: m_max_len(0)
, m_last_x(0x7FFFFFF0)
{}
//--------------------------------------------------------------------
void reset(int, int)
{
m_last_x = 0x7FFFFFF0;
m_spans.remove_all();
}
//--------------------------------------------------------------------
void add_cell(int x, unsigned)
{
if (x == m_last_x + 1)
{
m_spans.last().len++;
}
else
{
m_spans.add(span(coord_type(x), 1));
}
m_last_x = x;
}
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned)
{
if (x == m_last_x + 1)
{
m_spans.last().len += coord_type(len);
}
else
{
m_spans.add(span(coord_type(x), coord_type(len)));
}
m_last_x = x + len - 1;
}
} //--------------------------------------------------------------------
void add_cells(int x, unsigned len, const void*) { add_span(x, len, 0); }
//--------------------------------------------------------------------
void finalize(int y) { m_y = y; }
//--------------------------------------------------------------------
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_spans.remove_all();
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return m_spans.size(); }
const_iterator begin() const { return const_iterator(m_spans); }
private:
scanline32_bin(const scanline32_bin&);
const scanline32_bin operator=(const scanline32_bin&);
unsigned m_max_len;
int m_last_x;
int m_y;
span_array_type m_spans;
};
} // namespace agg
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -29,301 +29,279 @@
#include "agg_array.h" #include "agg_array.h"
namespace agg namespace agg {
//=============================================================scanline_p8
//
// This is a general purpose scaline container which supports the interface
// used in the rasterizer::render(). See description of scanline_u8
// for details.
//
//------------------------------------------------------------------------
class scanline_p8
{ {
public:
typedef scanline_p8 self_type;
typedef int8u cover_type;
typedef int16 coord_type;
//=============================================================scanline_p8 //--------------------------------------------------------------------
// struct span
// This is a general purpose scaline container which supports the interface
// used in the rasterizer::render(). See description of scanline_u8
// for details.
//
//------------------------------------------------------------------------
class scanline_p8
{ {
public: coord_type x;
typedef scanline_p8 self_type; coord_type len; // If negative, it's a solid span, covers is valid
typedef int8u cover_type; const cover_type* covers;
typedef int16 coord_type; };
//-------------------------------------------------------------------- typedef span* iterator;
struct span typedef const span* const_iterator;
{
coord_type x; scanline_p8()
coord_type len; // If negative, it's a solid span, covers is valid : m_last_x(0x7FFFFFF0)
const cover_type* covers; , m_covers()
}; , m_cover_ptr(0)
, m_spans()
typedef span* iterator; , m_cur_span(0)
typedef const span* const_iterator; {}
scanline_p8() : //--------------------------------------------------------------------
m_last_x(0x7FFFFFF0), void reset(int min_x, int max_x)
m_covers(), {
m_cover_ptr(0), unsigned max_len = max_x - min_x + 3;
m_spans(), if (max_len > m_spans.size())
m_cur_span(0)
{ {
m_spans.resize(max_len);
m_covers.resize(max_len);
} }
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_cur_span = &m_spans[0];
m_cur_span->len = 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void reset(int min_x, int max_x) void add_cell(int x, unsigned cover)
{
*m_cover_ptr = (cover_type)cover;
if (x == m_last_x + 1 && m_cur_span->len > 0)
{ {
unsigned max_len = max_x - min_x + 3; m_cur_span->len++;
if(max_len > m_spans.size())
{
m_spans.resize(max_len);
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_cur_span = &m_spans[0];
m_cur_span->len = 0;
} }
else
{
m_cur_span++;
m_cur_span->covers = m_cover_ptr;
m_cur_span->x = (int16)x;
m_cur_span->len = 1;
}
m_last_x = x;
m_cover_ptr++;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void add_cell(int x, unsigned cover) void add_cells(int x, unsigned len, const cover_type* covers)
{
memcpy(m_cover_ptr, covers, len * sizeof(cover_type));
if (x == m_last_x + 1 && m_cur_span->len > 0)
{
m_cur_span->len += (int16)len;
}
else
{
m_cur_span++;
m_cur_span->covers = m_cover_ptr;
m_cur_span->x = (int16)x;
m_cur_span->len = (int16)len;
}
m_cover_ptr += len;
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned cover)
{
if (x == m_last_x + 1 && m_cur_span->len < 0 && cover == *m_cur_span->covers)
{
m_cur_span->len -= (int16)len;
}
else
{ {
*m_cover_ptr = (cover_type)cover; *m_cover_ptr = (cover_type)cover;
if(x == m_last_x+1 && m_cur_span->len > 0) m_cur_span++;
{ m_cur_span->covers = m_cover_ptr++;
m_cur_span->len++; m_cur_span->x = (int16)x;
} m_cur_span->len = (int16)(-int(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++;
} }
m_last_x = x + len - 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void add_cells(int x, unsigned len, const cover_type* covers) void finalize(int y) { m_y = y; }
{
memcpy(m_cover_ptr, covers, len * sizeof(cover_type));
if(x == m_last_x+1 && m_cur_span->len > 0)
{
m_cur_span->len += (int16)len;
}
else
{
m_cur_span++;
m_cur_span->covers = m_cover_ptr;
m_cur_span->x = (int16)x;
m_cur_span->len = (int16)len;
}
m_cover_ptr += len;
m_last_x = x + len - 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned cover) void reset_spans()
{ {
if(x == m_last_x+1 && m_last_x = 0x7FFFFFF0;
m_cur_span->len < 0 && m_cover_ptr = &m_covers[0];
cover == *m_cur_span->covers) m_cur_span = &m_spans[0];
{ m_cur_span->len = 0;
m_cur_span->len -= (int16)len; }
}
else
{
*m_cover_ptr = (cover_type)cover;
m_cur_span++;
m_cur_span->covers = m_cover_ptr++;
m_cur_span->x = (int16)x;
m_cur_span->len = (int16)(-int(len));
}
m_last_x = x + len - 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void finalize(int y) int y() const { return m_y; }
{ unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
m_y = y; const_iterator begin() const { return &m_spans[1]; }
}
//-------------------------------------------------------------------- private:
void reset_spans() scanline_p8(const self_type&);
{ const self_type& operator=(const self_type&);
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_cur_span = &m_spans[0];
m_cur_span->len = 0;
}
//-------------------------------------------------------------------- int m_last_x;
int y() const { return m_y; } int m_y;
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } pod_array<cover_type> m_covers;
const_iterator begin() const { return &m_spans[1]; } cover_type* m_cover_ptr;
pod_array<span> m_spans;
span* m_cur_span;
};
private: //==========================================================scanline32_p8
scanline_p8(const self_type&); class scanline32_p8
const self_type& operator = (const self_type&); {
public:
typedef scanline32_p8 self_type;
typedef int8u cover_type;
typedef int32 coord_type;
int m_last_x; struct span
int m_y; {
pod_array<cover_type> m_covers; span() {}
cover_type* m_cover_ptr; span(coord_type x_, coord_type len_, const cover_type* covers_)
pod_array<span> m_spans; : x(x_)
span* m_cur_span; , len(len_)
, covers(covers_)
{}
coord_type x;
coord_type len; // If negative, it's a solid span, covers is valid
const cover_type* covers;
};
typedef pod_bvector<span, 4> span_array_type;
//--------------------------------------------------------------------
class const_iterator
{
public:
const_iterator(const span_array_type& spans)
: m_spans(spans)
, m_span_idx(0)
{}
const span& operator*() const { return m_spans[m_span_idx]; }
const span* operator->() const { return &m_spans[m_span_idx]; }
void operator++() { ++m_span_idx; }
private:
const span_array_type& m_spans;
unsigned m_span_idx;
}; };
//--------------------------------------------------------------------
scanline32_p8()
: m_max_len(0)
, m_last_x(0x7FFFFFF0)
, m_covers()
, m_cover_ptr(0)
{}
//--------------------------------------------------------------------
void reset(int min_x, int max_x)
//==========================================================scanline32_p8
class scanline32_p8
{ {
public: unsigned max_len = max_x - min_x + 3;
typedef scanline32_p8 self_type; if (max_len > m_covers.size())
typedef int8u cover_type;
typedef int32 coord_type;
struct span
{
span() {}
span(coord_type x_, coord_type len_, const cover_type* covers_) :
x(x_), len(len_), covers(covers_) {}
coord_type x;
coord_type len; // If negative, it's a solid span, covers is valid
const cover_type* covers;
};
typedef pod_bvector<span, 4> span_array_type;
//--------------------------------------------------------------------
class const_iterator
{
public:
const_iterator(const span_array_type& spans) :
m_spans(spans),
m_span_idx(0)
{}
const span& operator*() const { return m_spans[m_span_idx]; }
const span* operator->() const { return &m_spans[m_span_idx]; }
void operator ++ () { ++m_span_idx; }
private:
const span_array_type& m_spans;
unsigned m_span_idx;
};
//--------------------------------------------------------------------
scanline32_p8() :
m_max_len(0),
m_last_x(0x7FFFFFF0),
m_covers(),
m_cover_ptr(0)
{ {
m_covers.resize(max_len);
} }
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_spans.remove_all();
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void reset(int min_x, int max_x) void add_cell(int x, unsigned cover)
{
*m_cover_ptr = cover_type(cover);
if (x == m_last_x + 1 && m_spans.size() && m_spans.last().len > 0)
{ {
unsigned max_len = max_x - min_x + 3; m_spans.last().len++;
if(max_len > m_covers.size())
{
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_spans.remove_all();
} }
else
{
m_spans.add(span(coord_type(x), 1, m_cover_ptr));
}
m_last_x = x;
m_cover_ptr++;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void add_cell(int x, unsigned cover) void add_cells(int x, unsigned len, const cover_type* covers)
{
memcpy(m_cover_ptr, covers, len * sizeof(cover_type));
if (x == m_last_x + 1 && m_spans.size() && m_spans.last().len > 0)
{
m_spans.last().len += coord_type(len);
}
else
{
m_spans.add(span(coord_type(x), coord_type(len), m_cover_ptr));
}
m_cover_ptr += len;
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned cover)
{
if (x == m_last_x + 1 && m_spans.size() && m_spans.last().len < 0 && cover == *m_spans.last().covers)
{
m_spans.last().len -= coord_type(len);
}
else
{ {
*m_cover_ptr = cover_type(cover); *m_cover_ptr = cover_type(cover);
if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0) m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++));
{
m_spans.last().len++;
}
else
{
m_spans.add(span(coord_type(x), 1, m_cover_ptr));
}
m_last_x = x;
m_cover_ptr++;
} }
m_last_x = x + len - 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void add_cells(int x, unsigned len, const cover_type* covers) void finalize(int y) { m_y = y; }
{
memcpy(m_cover_ptr, covers, len * sizeof(cover_type));
if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0)
{
m_spans.last().len += coord_type(len);
}
else
{
m_spans.add(span(coord_type(x), coord_type(len), m_cover_ptr));
}
m_cover_ptr += len;
m_last_x = x + len - 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned cover) void reset_spans()
{ {
if(x == m_last_x+1 && m_last_x = 0x7FFFFFF0;
m_spans.size() && m_cover_ptr = &m_covers[0];
m_spans.last().len < 0 && m_spans.remove_all();
cover == *m_spans.last().covers) }
{
m_spans.last().len -= coord_type(len);
}
else
{
*m_cover_ptr = cover_type(cover);
m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++));
}
m_last_x = x + len - 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void finalize(int y) int y() const { return m_y; }
{ unsigned num_spans() const { return m_spans.size(); }
m_y = y; const_iterator begin() const { return const_iterator(m_spans); }
}
//-------------------------------------------------------------------- private:
void reset_spans() scanline32_p8(const self_type&);
{ const self_type& operator=(const self_type&);
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_spans.remove_all();
}
//-------------------------------------------------------------------- unsigned m_max_len;
int y() const { return m_y; } int m_last_x;
unsigned num_spans() const { return m_spans.size(); } int m_y;
const_iterator begin() const { return const_iterator(m_spans); } pod_array<cover_type> m_covers;
cover_type* m_cover_ptr;
private: span_array_type m_spans;
scanline32_p8(const self_type&); };
const self_type& operator = (const self_type&);
unsigned m_max_len;
int m_last_x;
int m_y;
pod_array<cover_type> m_covers;
cover_type* m_cover_ptr;
span_array_type m_spans;
};
}
} // namespace agg
#endif #endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -26,475 +26,456 @@
#include "agg_array.h" #include "agg_array.h"
namespace agg namespace agg {
//=============================================================scanline_u8
//
// Unpacked scanline container class
//
// This class is used to transfer data from a scanline rasterizer
// to the rendering buffer. It's organized very simple. The class stores
// information of horizontal spans to render it into a pixel-map buffer.
// Each span has staring X, length, and an array of bytes that determine the
// 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 scanline is generally faster. When is consists
// of more than one span the conditions for the processor cash system
// are better, because switching between two different areas of memory
// (that can be very large) occurs less frequently.
//------------------------------------------------------------------------
class scanline_u8
{ {
//=============================================================scanline_u8 public:
// typedef scanline_u8 self_type;
// Unpacked scanline container class typedef int8u cover_type;
// typedef int16 coord_type;
// This class is used to transfer data from a scanline rasterizer
// to the rendering buffer. It's organized very simple. The class stores //--------------------------------------------------------------------
// information of horizontal spans to render it into a pixel-map buffer. struct span
// 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 scanline is generally faster. When is consists
// of more than one span the conditions for the processor cash system
// are better, because switching between two different areas of memory
// (that can be very large) occurs less frequently.
//------------------------------------------------------------------------
class scanline_u8
{ {
public: coord_type x;
typedef scanline_u8 self_type; coord_type len;
typedef int8u cover_type; cover_type* covers;
typedef int16 coord_type; };
//-------------------------------------------------------------------- typedef span* iterator;
struct span typedef const span* const_iterator;
//--------------------------------------------------------------------
scanline_u8()
: m_min_x(0)
, m_last_x(0x7FFFFFF0)
, m_cur_span(0)
{}
//--------------------------------------------------------------------
void reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 2;
if (max_len > m_spans.size())
{ {
coord_type x; m_spans.resize(max_len);
coord_type len; m_covers.resize(max_len);
cover_type* covers; }
}; m_last_x = 0x7FFFFFF0;
m_min_x = min_x;
m_cur_span = &m_spans[0];
}
typedef span* iterator; //--------------------------------------------------------------------
typedef const span* const_iterator; void add_cell(int x, unsigned cover)
{
x -= m_min_x;
m_covers[x] = (cover_type)cover;
if (x == m_last_x + 1)
{
m_cur_span->len++;
}
else
{
m_cur_span++;
m_cur_span->x = (coord_type)(x + m_min_x);
m_cur_span->len = 1;
m_cur_span->covers = &m_covers[x];
}
m_last_x = x;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
scanline_u8() : void add_cells(int x, unsigned len, const cover_type* covers)
m_min_x(0), {
m_last_x(0x7FFFFFF0), x -= m_min_x;
m_cur_span(0) memcpy(&m_covers[x], covers, len * sizeof(cover_type));
if (x == m_last_x + 1)
{
m_cur_span->len += (coord_type)len;
}
else
{
m_cur_span++;
m_cur_span->x = (coord_type)(x + m_min_x);
m_cur_span->len = (coord_type)len;
m_cur_span->covers = &m_covers[x];
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned cover)
{
x -= m_min_x;
memset(&m_covers[x], cover, len);
if (x == m_last_x + 1)
{
m_cur_span->len += (coord_type)len;
}
else
{
m_cur_span++;
m_cur_span->x = (coord_type)(x + m_min_x);
m_cur_span->len = (coord_type)len;
m_cur_span->covers = &m_covers[x];
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void finalize(int y) { m_y = y; }
//--------------------------------------------------------------------
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cur_span = &m_spans[0];
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
const_iterator begin() const { return &m_spans[1]; }
iterator begin() { return &m_spans[1]; }
private:
scanline_u8(const self_type&);
const self_type& operator=(const self_type&);
private:
int m_min_x;
int m_last_x;
int m_y;
pod_array<cover_type> m_covers;
pod_array<span> m_spans;
span* m_cur_span;
};
//==========================================================scanline_u8_am
//
// The scanline container with alpha-masking
//
//------------------------------------------------------------------------
template<class AlphaMask>
class scanline_u8_am : public scanline_u8
{
public:
typedef scanline_u8 base_type;
typedef AlphaMask alpha_mask_type;
typedef base_type::cover_type cover_type;
typedef base_type::coord_type coord_type;
scanline_u8_am()
: base_type()
, m_alpha_mask(0)
{}
scanline_u8_am(const AlphaMask& am)
: base_type()
, m_alpha_mask(&am)
{}
//--------------------------------------------------------------------
void finalize(int span_y)
{
base_type::finalize(span_y);
if (m_alpha_mask)
{
typename base_type::iterator span = base_type::begin();
unsigned count = base_type::num_spans();
do
{
m_alpha_mask->combine_hspan(span->x, base_type::y(), span->covers, span->len);
++span;
} while (--count);
}
}
private:
const AlphaMask* m_alpha_mask;
};
//===========================================================scanline32_u8
class scanline32_u8
{
public:
typedef scanline32_u8 self_type;
typedef int8u cover_type;
typedef int32 coord_type;
//--------------------------------------------------------------------
struct span
{
span() {}
span(coord_type x_, coord_type len_, cover_type* covers_)
: x(x_)
, len(len_)
, covers(covers_)
{} {}
//-------------------------------------------------------------------- coord_type x;
void reset(int min_x, int max_x) coord_type len;
{ cover_type* covers;
unsigned max_len = max_x - min_x + 2;
if(max_len > m_spans.size())
{
m_spans.resize(max_len);
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_min_x = min_x;
m_cur_span = &m_spans[0];
}
//--------------------------------------------------------------------
void add_cell(int x, unsigned cover)
{
x -= m_min_x;
m_covers[x] = (cover_type)cover;
if(x == m_last_x+1)
{
m_cur_span->len++;
}
else
{
m_cur_span++;
m_cur_span->x = (coord_type)(x + m_min_x);
m_cur_span->len = 1;
m_cur_span->covers = &m_covers[x];
}
m_last_x = x;
}
//--------------------------------------------------------------------
void add_cells(int x, unsigned len, const cover_type* covers)
{
x -= m_min_x;
memcpy(&m_covers[x], covers, len * sizeof(cover_type));
if(x == m_last_x+1)
{
m_cur_span->len += (coord_type)len;
}
else
{
m_cur_span++;
m_cur_span->x = (coord_type)(x + m_min_x);
m_cur_span->len = (coord_type)len;
m_cur_span->covers = &m_covers[x];
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned cover)
{
x -= m_min_x;
memset(&m_covers[x], cover, len);
if(x == m_last_x+1)
{
m_cur_span->len += (coord_type)len;
}
else
{
m_cur_span++;
m_cur_span->x = (coord_type)(x + m_min_x);
m_cur_span->len = (coord_type)len;
m_cur_span->covers = &m_covers[x];
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void finalize(int y)
{
m_y = y;
}
//--------------------------------------------------------------------
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cur_span = &m_spans[0];
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
const_iterator begin() const { return &m_spans[1]; }
iterator begin() { return &m_spans[1]; }
private:
scanline_u8(const self_type&);
const self_type& operator = (const self_type&);
private:
int m_min_x;
int m_last_x;
int m_y;
pod_array<cover_type> m_covers;
pod_array<span> m_spans;
span* m_cur_span;
}; };
typedef pod_bvector<span, 4> span_array_type;
//--------------------------------------------------------------------
class const_iterator
//==========================================================scanline_u8_am
//
// The scanline container with alpha-masking
//
//------------------------------------------------------------------------
template<class AlphaMask>
class scanline_u8_am : public scanline_u8
{ {
public: public:
typedef scanline_u8 base_type; const_iterator(const span_array_type& spans)
typedef AlphaMask alpha_mask_type; : m_spans(spans)
typedef base_type::cover_type cover_type; , m_span_idx(0)
typedef base_type::coord_type coord_type;
scanline_u8_am() : base_type(), m_alpha_mask(0) {}
scanline_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
//--------------------------------------------------------------------
void finalize(int span_y)
{
base_type::finalize(span_y);
if(m_alpha_mask)
{
typename base_type::iterator span = base_type::begin();
unsigned count = base_type::num_spans();
do
{
m_alpha_mask->combine_hspan(span->x,
base_type::y(),
span->covers,
span->len);
++span;
}
while(--count);
}
}
private:
const AlphaMask* m_alpha_mask;
};
//===========================================================scanline32_u8
class scanline32_u8
{
public:
typedef scanline32_u8 self_type;
typedef int8u cover_type;
typedef int32 coord_type;
//--------------------------------------------------------------------
struct span
{
span() {}
span(coord_type x_, coord_type len_, cover_type* covers_) :
x(x_), len(len_), covers(covers_) {}
coord_type x;
coord_type len;
cover_type* covers;
};
typedef pod_bvector<span, 4> span_array_type;
//--------------------------------------------------------------------
class const_iterator
{
public:
const_iterator(const span_array_type& spans) :
m_spans(spans),
m_span_idx(0)
{}
const span& operator*() const { return m_spans[m_span_idx]; }
const span* operator->() const { return &m_spans[m_span_idx]; }
void operator ++ () { ++m_span_idx; }
private:
const span_array_type& m_spans;
unsigned m_span_idx;
};
//--------------------------------------------------------------------
class iterator
{
public:
iterator(span_array_type& spans) :
m_spans(spans),
m_span_idx(0)
{}
span& operator*() { return m_spans[m_span_idx]; }
span* operator->() { return &m_spans[m_span_idx]; }
void operator ++ () { ++m_span_idx; }
private:
span_array_type& m_spans;
unsigned m_span_idx;
};
//--------------------------------------------------------------------
scanline32_u8() :
m_min_x(0),
m_last_x(0x7FFFFFF0),
m_covers()
{} {}
//-------------------------------------------------------------------- const span& operator*() const { return m_spans[m_span_idx]; }
void reset(int min_x, int max_x) const span* operator->() const { return &m_spans[m_span_idx]; }
{
unsigned max_len = max_x - min_x + 2;
if(max_len > m_covers.size())
{
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_min_x = min_x;
m_spans.remove_all();
}
//-------------------------------------------------------------------- void operator++() { ++m_span_idx; }
void add_cell(int x, unsigned cover)
{
x -= m_min_x;
m_covers[x] = cover_type(cover);
if(x == m_last_x+1)
{
m_spans.last().len++;
}
else
{
m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x]));
}
m_last_x = x;
}
//-------------------------------------------------------------------- private:
void add_cells(int x, unsigned len, const cover_type* covers) const span_array_type& m_spans;
{ unsigned m_span_idx;
x -= m_min_x;
memcpy(&m_covers[x], covers, len * sizeof(cover_type));
if(x == m_last_x+1)
{
m_spans.last().len += coord_type(len);
}
else
{
m_spans.add(span(coord_type(x + m_min_x),
coord_type(len),
&m_covers[x]));
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned cover)
{
x -= m_min_x;
memset(&m_covers[x], cover, len);
if(x == m_last_x+1)
{
m_spans.last().len += coord_type(len);
}
else
{
m_spans.add(span(coord_type(x + m_min_x),
coord_type(len),
&m_covers[x]));
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void finalize(int y)
{
m_y = y;
}
//--------------------------------------------------------------------
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_spans.remove_all();
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return m_spans.size(); }
const_iterator begin() const { return const_iterator(m_spans); }
iterator begin() { return iterator(m_spans); }
private:
scanline32_u8(const self_type&);
const self_type& operator = (const self_type&);
private:
int m_min_x;
int m_last_x;
int m_y;
pod_array<cover_type> m_covers;
span_array_type m_spans;
}; };
//--------------------------------------------------------------------
class iterator
//========================================================scanline32_u8_am
//
// The scanline container with alpha-masking
//
//------------------------------------------------------------------------
template<class AlphaMask>
class scanline32_u8_am : public scanline32_u8
{ {
public: public:
typedef scanline32_u8 base_type; iterator(span_array_type& spans)
typedef AlphaMask alpha_mask_type; : m_spans(spans)
typedef base_type::cover_type cover_type; , m_span_idx(0)
typedef base_type::coord_type coord_type; {}
span& operator*() { return m_spans[m_span_idx]; }
span* operator->() { return &m_spans[m_span_idx]; }
scanline32_u8_am() : base_type(), m_alpha_mask(0) {} void operator++() { ++m_span_idx; }
scanline32_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
//-------------------------------------------------------------------- private:
void finalize(int span_y) span_array_type& m_spans;
{ unsigned m_span_idx;
base_type::finalize(span_y);
if(m_alpha_mask)
{
typename base_type::iterator span = base_type::begin();
unsigned count = base_type::num_spans();
do
{
m_alpha_mask->combine_hspan(span->x,
base_type::y(),
span->covers,
span->len);
++span;
}
while(--count);
}
}
private:
const AlphaMask* m_alpha_mask;
}; };
//--------------------------------------------------------------------
scanline32_u8()
: m_min_x(0)
, m_last_x(0x7FFFFFF0)
, m_covers()
{}
//--------------------------------------------------------------------
void reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 2;
if (max_len > m_covers.size())
{
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_min_x = min_x;
m_spans.remove_all();
}
} //--------------------------------------------------------------------
void add_cell(int x, unsigned cover)
{
x -= m_min_x;
m_covers[x] = cover_type(cover);
if (x == m_last_x + 1)
{
m_spans.last().len++;
}
else
{
m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x]));
}
m_last_x = x;
}
//--------------------------------------------------------------------
void add_cells(int x, unsigned len, const cover_type* covers)
{
x -= m_min_x;
memcpy(&m_covers[x], covers, len * sizeof(cover_type));
if (x == m_last_x + 1)
{
m_spans.last().len += coord_type(len);
}
else
{
m_spans.add(span(coord_type(x + m_min_x), coord_type(len), &m_covers[x]));
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned cover)
{
x -= m_min_x;
memset(&m_covers[x], cover, len);
if (x == m_last_x + 1)
{
m_spans.last().len += coord_type(len);
}
else
{
m_spans.add(span(coord_type(x + m_min_x), coord_type(len), &m_covers[x]));
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void finalize(int y) { m_y = y; }
//--------------------------------------------------------------------
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_spans.remove_all();
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return m_spans.size(); }
const_iterator begin() const { return const_iterator(m_spans); }
iterator begin() { return iterator(m_spans); }
private:
scanline32_u8(const self_type&);
const self_type& operator=(const self_type&);
private:
int m_min_x;
int m_last_x;
int m_y;
pod_array<cover_type> m_covers;
span_array_type m_spans;
};
//========================================================scanline32_u8_am
//
// The scanline container with alpha-masking
//
//------------------------------------------------------------------------
template<class AlphaMask>
class scanline32_u8_am : public scanline32_u8
{
public:
typedef scanline32_u8 base_type;
typedef AlphaMask alpha_mask_type;
typedef base_type::cover_type cover_type;
typedef base_type::coord_type coord_type;
scanline32_u8_am()
: base_type()
, m_alpha_mask(0)
{}
scanline32_u8_am(const AlphaMask& am)
: base_type()
, m_alpha_mask(&am)
{}
//--------------------------------------------------------------------
void finalize(int span_y)
{
base_type::finalize(span_y);
if (m_alpha_mask)
{
typename base_type::iterator span = base_type::begin();
unsigned count = base_type::num_spans();
do
{
m_alpha_mask->combine_hspan(span->x, base_type::y(), span->covers, span->len);
++span;
} while (--count);
}
}
private:
const AlphaMask* m_alpha_mask;
};
} // namespace agg
#endif #endif

View file

@ -19,48 +19,48 @@
#include "agg_basics.h" #include "agg_basics.h"
#include "agg_vertex_sequence.h" #include "agg_vertex_sequence.h"
namespace agg namespace agg {
//===========================================================shorten_path
template<class VertexSequence>
void shorten_path(VertexSequence& vs, double s, unsigned closed = 0)
{ {
typedef typename VertexSequence::value_type vertex_type;
//===========================================================shorten_path if (s > 0.0 && vs.size() > 1)
template<class VertexSequence>
void shorten_path(VertexSequence& vs, double s, unsigned closed = 0)
{ {
typedef typename VertexSequence::value_type vertex_type; double d;
int n = int(vs.size() - 2);
if(s > 0.0 && vs.size() > 1) while (n)
{ {
double d; d = vs[n].dist;
int n = int(vs.size() - 2); if (d > s)
while(n) break;
{ vs.remove_last();
d = vs[n].dist; s -= d;
if(d > s) break; --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.remove_last();
s -= d; vs.close(closed != 0);
--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);
}
} }
} }
} }
} // namespace agg
#endif #endif

View file

@ -22,126 +22,119 @@
#include <cmath> #include <cmath>
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//=============================================================swap_arrays
template<class T>
void swap_arrays(T* a1, T* a2, unsigned n)
{ {
unsigned i;
//=============================================================swap_arrays for (i = 0; i < n; i++)
template<class T> void swap_arrays(T* a1, T* a2, unsigned n)
{ {
unsigned i; T tmp = *a1;
for(i = 0; i < n; i++) *a1++ = *a2;
{ *a2++ = tmp;
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 = std::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;
}
};
} }
//============================================================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 = std::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;
}
};
} // namespace agg
#endif #endif

View file

@ -18,37 +18,34 @@
#include "agg_array.h" #include "agg_array.h"
namespace agg namespace agg {
//----------------------------------------------------------span_allocator
template<class ColorT>
class span_allocator
{ {
//----------------------------------------------------------span_allocator public:
template<class ColorT> class span_allocator typedef ColorT color_type;
//--------------------------------------------------------------------
AGG_INLINE color_type* allocate(unsigned span_len)
{ {
public: if (span_len > m_span.size())
typedef ColorT color_type;
//--------------------------------------------------------------------
AGG_INLINE color_type* allocate(unsigned span_len)
{ {
if(span_len > m_span.size()) // To reduce the number of reallocs we align the
{ // span_len to 256 color elements.
// To reduce the number of reallocs we align the // Well, I just like this number and it looks reasonable.
// span_len to 256 color elements. //-----------------------
// Well, I just like this number and it looks reasonable. m_span.resize(((span_len + 255) >> 8) << 8);
//-----------------------
m_span.resize(((span_len + 255) >> 8) << 8);
}
return &m_span[0];
} }
return &m_span[0];
}
AGG_INLINE color_type* span() { return &m_span[0]; } AGG_INLINE color_type* span() { return &m_span[0]; }
AGG_INLINE unsigned max_span_len() const { return m_span.size(); } AGG_INLINE unsigned max_span_len() const { return m_span.size(); }
private:
pod_array<color_type> m_span;
};
}
private:
pod_array<color_type> m_span;
};
} // namespace agg
#endif #endif

View file

@ -18,39 +18,41 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg namespace agg {
//----------------------------------------------------------span_converter
template<class SpanGenerator, class SpanConverter>
class span_converter
{ {
//----------------------------------------------------------span_converter public:
template<class SpanGenerator, class SpanConverter> class span_converter typedef typename SpanGenerator::color_type color_type;
span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv)
: m_span_gen(&span_gen)
, m_span_cnv(&span_cnv)
{}
void attach_generator(SpanGenerator& span_gen) { m_span_gen = &span_gen; }
void attach_converter(SpanConverter& span_cnv) { m_span_cnv = &span_cnv; }
//--------------------------------------------------------------------
void prepare()
{ {
public: m_span_gen->prepare();
typedef typename SpanGenerator::color_type color_type; m_span_cnv->prepare();
}
span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv) : //--------------------------------------------------------------------
m_span_gen(&span_gen), m_span_cnv(&span_cnv) {} void generate(color_type* span, int x, int y, unsigned len)
{
m_span_gen->generate(span, x, y, len);
m_span_cnv->generate(span, x, y, len);
}
void attach_generator(SpanGenerator& span_gen) { m_span_gen = &span_gen; } private:
void attach_converter(SpanConverter& span_cnv) { m_span_cnv = &span_cnv; } SpanGenerator* m_span_gen;
SpanConverter* m_span_cnv;
};
//-------------------------------------------------------------------- } // namespace agg
void prepare()
{
m_span_gen->prepare();
m_span_cnv->prepare();
}
//--------------------------------------------------------------------
void generate(color_type* span, int x, int y, unsigned len)
{
m_span_gen->generate(span, x, y, len);
m_span_cnv->generate(span, x, y, len);
}
private:
SpanGenerator* m_span_gen;
SpanConverter* m_span_cnv;
};
}
#endif #endif

View file

@ -19,154 +19,176 @@
#include "agg_basics.h" #include "agg_basics.h"
#include "agg_math.h" #include "agg_math.h"
namespace agg namespace agg {
//============================================================span_gouraud
template<class ColorT>
class span_gouraud
{ {
public:
typedef ColorT color_type;
//============================================================span_gouraud struct coord_type
template<class ColorT> class span_gouraud
{ {
public: double x;
typedef ColorT color_type; double y;
color_type color;
struct coord_type
{
double x;
double y;
color_type color;
};
//--------------------------------------------------------------------
span_gouraud() :
m_vertex(0)
{
m_cmd[0] = path_cmd_stop;
}
//--------------------------------------------------------------------
span_gouraud(const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1, double y1,
double x2, double y2,
double x3, double y3,
double d) :
m_vertex(0)
{
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;
}; };
} //--------------------------------------------------------------------
span_gouraud()
: m_vertex(0)
{
m_cmd[0] = path_cmd_stop;
}
//--------------------------------------------------------------------
span_gouraud(const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
double d)
: m_vertex(0)
{
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;
};
} // namespace agg
#endif #endif

View file

@ -29,213 +29,222 @@
#include "agg_dda_line.h" #include "agg_dda_line.h"
#include "agg_span_gouraud.h" #include "agg_span_gouraud.h"
namespace agg namespace agg {
//=======================================================span_gouraud_gray
template<class ColorT>
class span_gouraud_gray : public span_gouraud<ColorT>
{ {
public:
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
typedef span_gouraud<color_type> base_type;
typedef typename base_type::coord_type coord_type;
enum subpixel_scale_e { subpixel_shift = 4, subpixel_scale = 1 << subpixel_shift };
//=======================================================span_gouraud_gray private:
template<class ColorT> class span_gouraud_gray : public span_gouraud<ColorT> //--------------------------------------------------------------------
struct gray_calc
{ {
public: void init(const coord_type& c1, const coord_type& c2)
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
typedef span_gouraud<color_type> base_type;
typedef typename base_type::coord_type coord_type;
enum subpixel_scale_e
{ {
subpixel_shift = 4, m_x1 = c1.x - 0.5;
subpixel_scale = 1 << subpixel_shift m_y1 = c1.y - 0.5;
}; m_dx = c2.x - c1.x;
double dy = c2.y - c1.y;
private: m_1dy = (std::fabs(dy) < 1e-10) ? 1e10 : 1.0 / dy;
//-------------------------------------------------------------------- m_v1 = c1.color.v;
struct gray_calc m_a1 = c1.color.a;
{ m_dv = c2.color.v - m_v1;
void init(const coord_type& c1, const coord_type& c2) m_da = c2.color.a - m_a1;
{
m_x1 = c1.x - 0.5;
m_y1 = c1.y - 0.5;
m_dx = c2.x - c1.x;
double dy = c2.y - c1.y;
m_1dy = (std::fabs(dy) < 1e-10) ? 1e10 : 1.0 / dy;
m_v1 = c1.color.v;
m_a1 = c1.color.a;
m_dv = c2.color.v - m_v1;
m_da = c2.color.a - m_a1;
}
void calc(double y)
{
double k = (y - m_y1) * m_1dy;
if(k < 0.0) k = 0.0;
if(k > 1.0) k = 1.0;
m_v = m_v1 + iround(m_dv * k);
m_a = m_a1 + iround(m_da * k);
m_x = iround((m_x1 + m_dx * k) * subpixel_scale);
}
double m_x1;
double m_y1;
double m_dx;
double m_1dy;
int m_v1;
int m_a1;
int m_dv;
int m_da;
int m_v;
int m_a;
int m_x;
};
public:
//--------------------------------------------------------------------
span_gouraud_gray() {}
span_gouraud_gray(const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1, double y1,
double x2, double y2,
double x3, double y3,
double d = 0) :
base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
{}
//--------------------------------------------------------------------
void prepare()
{
coord_type coord[3];
base_type::arrange_vertices(coord);
m_y2 = int(coord[1].y);
m_swap = cross_product(coord[0].x, coord[0].y,
coord[2].x, coord[2].y,
coord[1].x, coord[1].y) < 0.0;
m_c1.init(coord[0], coord[2]);
m_c2.init(coord[0], coord[1]);
m_c3.init(coord[1], coord[2]);
} }
//-------------------------------------------------------------------- void calc(double y)
void generate(color_type* span, int x, int y, unsigned len)
{ {
m_c1.calc(y); double k = (y - m_y1) * m_1dy;
const gray_calc* pc1 = &m_c1; if (k < 0.0)
const gray_calc* pc2 = &m_c2; k = 0.0;
if (k > 1.0)
if(y < m_y2) k = 1.0;
{ m_v = m_v1 + iround(m_dv * k);
// Bottom part of the triangle (first subtriangle) m_a = m_a1 + iround(m_da * k);
//------------------------- m_x = iround((m_x1 + m_dx * k) * subpixel_scale);
m_c2.calc(y + m_c2.m_1dy);
}
else
{
// Upper part (second subtriangle)
//-------------------------
m_c3.calc(y - m_c3.m_1dy);
pc2 = &m_c3;
}
if(m_swap)
{
// It means that the triangle is oriented clockwise,
// so that we need to swap the controlling structures
//-------------------------
const gray_calc* t = pc2;
pc2 = pc1;
pc1 = t;
}
// Get the horizontal length with subpixel accuracy
// and protect it from division by zero
//-------------------------
int nlen = std::abs(pc2->m_x - pc1->m_x);
if(nlen <= 0) nlen = 1;
dda_line_interpolator<14> v(pc1->m_v, pc2->m_v, nlen);
dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen);
// Calculate the starting point of the gradient with subpixel
// accuracy and correct (roll back) the interpolators.
// This operation will also clip the beginning of the span
// if necessary.
//-------------------------
int start = pc1->m_x - (x << subpixel_shift);
v -= start;
a -= start;
nlen += start;
int vv, va;
enum lim_e { lim = color_type::base_mask };
// Beginning part of the span. Since we rolled back the
// interpolators, the color values may have overflow.
// So that, we render the beginning part with checking
// for overflow. It lasts until "start" is positive;
// typically it's 1-2 pixels, but may be more in some cases.
//-------------------------
while(len && start > 0)
{
vv = v.y();
va = a.y();
if(vv < 0) vv = 0; if(vv > lim) vv = lim;
if(va < 0) va = 0; if(va > lim) va = lim;
span->v = (value_type)vv;
span->a = (value_type)va;
v += subpixel_scale;
a += subpixel_scale;
nlen -= subpixel_scale;
start -= subpixel_scale;
++span;
--len;
}
// Middle part, no checking for overflow.
// Actual spans can be longer than the calculated length
// because of anti-aliasing, thus, the interpolators can
// overflow. But while "nlen" is positive we are safe.
//-------------------------
while(len && nlen > 0)
{
span->v = (value_type)v.y();
span->a = (value_type)a.y();
v += subpixel_scale;
a += subpixel_scale;
nlen -= subpixel_scale;
++span;
--len;
}
// Ending part; checking for overflow.
// Typically it's 1-2 pixels, but may be more in some cases.
//-------------------------
while(len)
{
vv = v.y();
va = a.y();
if(vv < 0) vv = 0; if(vv > lim) vv = lim;
if(va < 0) va = 0; if(va > lim) va = lim;
span->v = (value_type)vv;
span->a = (value_type)va;
v += subpixel_scale;
a += subpixel_scale;
++span;
--len;
}
} }
double m_x1;
private: double m_y1;
bool m_swap; double m_dx;
int m_y2; double m_1dy;
gray_calc m_c1; int m_v1;
gray_calc m_c2; int m_a1;
gray_calc m_c3; int m_dv;
int m_da;
int m_v;
int m_a;
int m_x;
}; };
public:
//--------------------------------------------------------------------
span_gouraud_gray() {}
span_gouraud_gray(const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
double d = 0)
: base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
{}
} //--------------------------------------------------------------------
void prepare()
{
coord_type coord[3];
base_type::arrange_vertices(coord);
m_y2 = int(coord[1].y);
m_swap = cross_product(coord[0].x, coord[0].y, coord[2].x, coord[2].y, coord[1].x, coord[1].y) < 0.0;
m_c1.init(coord[0], coord[2]);
m_c2.init(coord[0], coord[1]);
m_c3.init(coord[1], coord[2]);
}
//--------------------------------------------------------------------
void generate(color_type* span, 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)
{
// Bottom part of the triangle (first subtriangle)
//-------------------------
m_c2.calc(y + m_c2.m_1dy);
}
else
{
// Upper part (second subtriangle)
//-------------------------
m_c3.calc(y - m_c3.m_1dy);
pc2 = &m_c3;
}
if (m_swap)
{
// It means that the triangle is oriented clockwise,
// so that we need to swap the controlling structures
//-------------------------
const gray_calc* t = pc2;
pc2 = pc1;
pc1 = t;
}
// Get the horizontal length with subpixel accuracy
// and protect it from division by zero
//-------------------------
int nlen = std::abs(pc2->m_x - pc1->m_x);
if (nlen <= 0)
nlen = 1;
dda_line_interpolator<14> v(pc1->m_v, pc2->m_v, nlen);
dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen);
// Calculate the starting point of the gradient with subpixel
// accuracy and correct (roll back) the interpolators.
// This operation will also clip the beginning of the span
// if necessary.
//-------------------------
int start = pc1->m_x - (x << subpixel_shift);
v -= start;
a -= start;
nlen += start;
int vv, va;
enum lim_e { lim = color_type::base_mask };
// Beginning part of the span. Since we rolled back the
// interpolators, the color values may have overflow.
// So that, we render the beginning part with checking
// for overflow. It lasts until "start" is positive;
// typically it's 1-2 pixels, but may be more in some cases.
//-------------------------
while (len && start > 0)
{
vv = v.y();
va = a.y();
if (vv < 0)
vv = 0;
if (vv > lim)
vv = lim;
if (va < 0)
va = 0;
if (va > lim)
va = lim;
span->v = (value_type)vv;
span->a = (value_type)va;
v += subpixel_scale;
a += subpixel_scale;
nlen -= subpixel_scale;
start -= subpixel_scale;
++span;
--len;
}
// Middle part, no checking for overflow.
// Actual spans can be longer than the calculated length
// because of anti-aliasing, thus, the interpolators can
// overflow. But while "nlen" is positive we are safe.
//-------------------------
while (len && nlen > 0)
{
span->v = (value_type)v.y();
span->a = (value_type)a.y();
v += subpixel_scale;
a += subpixel_scale;
nlen -= subpixel_scale;
++span;
--len;
}
// Ending part; checking for overflow.
// Typically it's 1-2 pixels, but may be more in some cases.
//-------------------------
while (len)
{
vv = v.y();
va = a.y();
if (vv < 0)
vv = 0;
if (vv > lim)
vv = lim;
if (va < 0)
va = 0;
if (va > lim)
va = lim;
span->v = (value_type)vv;
span->a = (value_type)va;
v += subpixel_scale;
a += subpixel_scale;
++span;
--len;
}
}
private:
bool m_swap;
int m_y2;
gray_calc m_c1;
gray_calc m_c2;
gray_calc m_c3;
};
} // namespace agg
#endif #endif

View file

@ -29,249 +29,271 @@
#include "agg_dda_line.h" #include "agg_dda_line.h"
#include "agg_span_gouraud.h" #include "agg_span_gouraud.h"
namespace agg namespace agg {
//=======================================================span_gouraud_rgba
template<class ColorT>
class span_gouraud_rgba : public span_gouraud<ColorT>
{ {
public:
typedef ColorT color_type;
typedef typename ColorT::value_type value_type;
typedef span_gouraud<color_type> base_type;
typedef typename base_type::coord_type coord_type;
enum subpixel_scale_e { subpixel_shift = 4, subpixel_scale = 1 << subpixel_shift };
//=======================================================span_gouraud_rgba private:
template<class ColorT> class span_gouraud_rgba : public span_gouraud<ColorT> //--------------------------------------------------------------------
struct rgba_calc
{ {
public: void init(const coord_type& c1, const coord_type& c2)
typedef ColorT color_type;
typedef typename ColorT::value_type value_type;
typedef span_gouraud<color_type> base_type;
typedef typename base_type::coord_type coord_type;
enum subpixel_scale_e
{ {
subpixel_shift = 4, m_x1 = c1.x - 0.5;
subpixel_scale = 1 << subpixel_shift m_y1 = c1.y - 0.5;
}; m_dx = c2.x - c1.x;
double dy = c2.y - c1.y;
private: m_1dy = (dy < 1e-5) ? 1e5 : 1.0 / dy;
//-------------------------------------------------------------------- m_r1 = c1.color.r;
struct rgba_calc m_g1 = c1.color.g;
{ m_b1 = c1.color.b;
void init(const coord_type& c1, const coord_type& c2) m_a1 = c1.color.a;
{ m_dr = c2.color.r - m_r1;
m_x1 = c1.x - 0.5; m_dg = c2.color.g - m_g1;
m_y1 = c1.y - 0.5; m_db = c2.color.b - m_b1;
m_dx = c2.x - c1.x; m_da = c2.color.a - m_a1;
double dy = c2.y - c1.y;
m_1dy = (dy < 1e-5) ? 1e5 : 1.0 / dy;
m_r1 = c1.color.r;
m_g1 = c1.color.g;
m_b1 = c1.color.b;
m_a1 = c1.color.a;
m_dr = c2.color.r - m_r1;
m_dg = c2.color.g - m_g1;
m_db = c2.color.b - m_b1;
m_da = c2.color.a - m_a1;
}
void calc(double y)
{
double k = (y - m_y1) * m_1dy;
if(k < 0.0) k = 0.0;
if(k > 1.0) k = 1.0;
m_r = m_r1 + iround(m_dr * k);
m_g = m_g1 + iround(m_dg * k);
m_b = m_b1 + iround(m_db * k);
m_a = m_a1 + iround(m_da * k);
m_x = iround((m_x1 + m_dx * k) * subpixel_scale);
}
double m_x1;
double m_y1;
double m_dx;
double m_1dy;
int m_r1;
int m_g1;
int m_b1;
int m_a1;
int m_dr;
int m_dg;
int m_db;
int m_da;
int m_r;
int m_g;
int m_b;
int m_a;
int m_x;
};
public:
//--------------------------------------------------------------------
span_gouraud_rgba() {}
span_gouraud_rgba(const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1, double y1,
double x2, double y2,
double x3, double y3,
double d = 0) :
base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
{}
//--------------------------------------------------------------------
void prepare()
{
coord_type coord[3];
base_type::arrange_vertices(coord);
m_y2 = int(coord[1].y);
m_swap = cross_product(coord[0].x, coord[0].y,
coord[2].x, coord[2].y,
coord[1].x, coord[1].y) < 0.0;
m_rgba1.init(coord[0], coord[2]);
m_rgba2.init(coord[0], coord[1]);
m_rgba3.init(coord[1], coord[2]);
} }
//-------------------------------------------------------------------- void calc(double y)
void generate(color_type* span, int x, int y, unsigned len)
{ {
m_rgba1.calc(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y); double k = (y - m_y1) * m_1dy;
const rgba_calc* pc1 = &m_rgba1; if (k < 0.0)
const rgba_calc* pc2 = &m_rgba2; k = 0.0;
if (k > 1.0)
if(y <= m_y2) k = 1.0;
{ m_r = m_r1 + iround(m_dr * k);
// Bottom part of the triangle (first subtriangle) m_g = m_g1 + iround(m_dg * k);
//------------------------- m_b = m_b1 + iround(m_db * k);
m_rgba2.calc(y + m_rgba2.m_1dy); m_a = m_a1 + iround(m_da * k);
} m_x = iround((m_x1 + m_dx * k) * subpixel_scale);
else
{
// Upper part (second subtriangle)
m_rgba3.calc(y - m_rgba3.m_1dy);
//-------------------------
pc2 = &m_rgba3;
}
if(m_swap)
{
// It means that the triangle is oriented clockwise,
// so that we need to swap the controlling structures
//-------------------------
const rgba_calc* t = pc2;
pc2 = pc1;
pc1 = t;
}
// Get the horizontal length with subpixel accuracy
// and protect it from division by zero
//-------------------------
int nlen = std::abs(pc2->m_x - pc1->m_x);
if(nlen <= 0) nlen = 1;
dda_line_interpolator<14> r(pc1->m_r, pc2->m_r, nlen);
dda_line_interpolator<14> g(pc1->m_g, pc2->m_g, nlen);
dda_line_interpolator<14> b(pc1->m_b, pc2->m_b, nlen);
dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen);
// Calculate the starting point of the gradient with subpixel
// accuracy and correct (roll back) the interpolators.
// This operation will also clip the beginning of the span
// if necessary.
//-------------------------
int start = pc1->m_x - (x << subpixel_shift);
r -= start;
g -= start;
b -= start;
a -= start;
nlen += start;
int vr, vg, vb, va;
enum lim_e { lim = color_type::base_mask };
// Beginning part of the span. Since we rolled back the
// interpolators, the color values may have overflow.
// So that, we render the beginning part with checking
// for overflow. It lasts until "start" is positive;
// typically it's 1-2 pixels, but may be more in some cases.
//-------------------------
while(len && start > 0)
{
vr = r.y();
vg = g.y();
vb = b.y();
va = a.y();
if(vr < 0) vr = 0; if(vr > lim) vr = lim;
if(vg < 0) vg = 0; if(vg > lim) vg = lim;
if(vb < 0) vb = 0; if(vb > lim) vb = lim;
if(va < 0) va = 0; if(va > lim) va = lim;
span->r = (value_type)vr;
span->g = (value_type)vg;
span->b = (value_type)vb;
span->a = (value_type)va;
r += subpixel_scale;
g += subpixel_scale;
b += subpixel_scale;
a += subpixel_scale;
nlen -= subpixel_scale;
start -= subpixel_scale;
++span;
--len;
}
// Middle part, no checking for overflow.
// Actual spans can be longer than the calculated length
// because of anti-aliasing, thus, the interpolators can
// overflow. But while "nlen" is positive we are safe.
//-------------------------
while(len && nlen > 0)
{
span->r = (value_type)r.y();
span->g = (value_type)g.y();
span->b = (value_type)b.y();
span->a = (value_type)a.y();
r += subpixel_scale;
g += subpixel_scale;
b += subpixel_scale;
a += subpixel_scale;
nlen -= subpixel_scale;
++span;
--len;
}
// Ending part; checking for overflow.
// Typically it's 1-2 pixels, but may be more in some cases.
//-------------------------
while(len)
{
vr = r.y();
vg = g.y();
vb = b.y();
va = a.y();
if(vr < 0) vr = 0; if(vr > lim) vr = lim;
if(vg < 0) vg = 0; if(vg > lim) vg = lim;
if(vb < 0) vb = 0; if(vb > lim) vb = lim;
if(va < 0) va = 0; if(va > lim) va = lim;
span->r = (value_type)vr;
span->g = (value_type)vg;
span->b = (value_type)vb;
span->a = (value_type)va;
r += subpixel_scale;
g += subpixel_scale;
b += subpixel_scale;
a += subpixel_scale;
++span;
--len;
}
} }
private: double m_x1;
bool m_swap; double m_y1;
int m_y2; double m_dx;
rgba_calc m_rgba1; double m_1dy;
rgba_calc m_rgba2; int m_r1;
rgba_calc m_rgba3; int m_g1;
int m_b1;
int m_a1;
int m_dr;
int m_dg;
int m_db;
int m_da;
int m_r;
int m_g;
int m_b;
int m_a;
int m_x;
}; };
public:
//--------------------------------------------------------------------
span_gouraud_rgba() {}
span_gouraud_rgba(const color_type& c1,
const color_type& c2,
const color_type& c3,
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
double d = 0)
: base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
{}
} //--------------------------------------------------------------------
void prepare()
{
coord_type coord[3];
base_type::arrange_vertices(coord);
m_y2 = int(coord[1].y);
m_swap = cross_product(coord[0].x, coord[0].y, coord[2].x, coord[2].y, coord[1].x, coord[1].y) < 0.0;
m_rgba1.init(coord[0], coord[2]);
m_rgba2.init(coord[0], coord[1]);
m_rgba3.init(coord[1], coord[2]);
}
//--------------------------------------------------------------------
void generate(color_type* span, int x, int y, unsigned len)
{
m_rgba1.calc(y); //(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y);
const rgba_calc* pc1 = &m_rgba1;
const rgba_calc* pc2 = &m_rgba2;
if (y <= m_y2)
{
// Bottom part of the triangle (first subtriangle)
//-------------------------
m_rgba2.calc(y + m_rgba2.m_1dy);
}
else
{
// Upper part (second subtriangle)
m_rgba3.calc(y - m_rgba3.m_1dy);
//-------------------------
pc2 = &m_rgba3;
}
if (m_swap)
{
// It means that the triangle is oriented clockwise,
// so that we need to swap the controlling structures
//-------------------------
const rgba_calc* t = pc2;
pc2 = pc1;
pc1 = t;
}
// Get the horizontal length with subpixel accuracy
// and protect it from division by zero
//-------------------------
int nlen = std::abs(pc2->m_x - pc1->m_x);
if (nlen <= 0)
nlen = 1;
dda_line_interpolator<14> r(pc1->m_r, pc2->m_r, nlen);
dda_line_interpolator<14> g(pc1->m_g, pc2->m_g, nlen);
dda_line_interpolator<14> b(pc1->m_b, pc2->m_b, nlen);
dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen);
// Calculate the starting point of the gradient with subpixel
// accuracy and correct (roll back) the interpolators.
// This operation will also clip the beginning of the span
// if necessary.
//-------------------------
int start = pc1->m_x - (x << subpixel_shift);
r -= start;
g -= start;
b -= start;
a -= start;
nlen += start;
int vr, vg, vb, va;
enum lim_e { lim = color_type::base_mask };
// Beginning part of the span. Since we rolled back the
// interpolators, the color values may have overflow.
// So that, we render the beginning part with checking
// for overflow. It lasts until "start" is positive;
// typically it's 1-2 pixels, but may be more in some cases.
//-------------------------
while (len && start > 0)
{
vr = r.y();
vg = g.y();
vb = b.y();
va = a.y();
if (vr < 0)
vr = 0;
if (vr > lim)
vr = lim;
if (vg < 0)
vg = 0;
if (vg > lim)
vg = lim;
if (vb < 0)
vb = 0;
if (vb > lim)
vb = lim;
if (va < 0)
va = 0;
if (va > lim)
va = lim;
span->r = (value_type)vr;
span->g = (value_type)vg;
span->b = (value_type)vb;
span->a = (value_type)va;
r += subpixel_scale;
g += subpixel_scale;
b += subpixel_scale;
a += subpixel_scale;
nlen -= subpixel_scale;
start -= subpixel_scale;
++span;
--len;
}
// Middle part, no checking for overflow.
// Actual spans can be longer than the calculated length
// because of anti-aliasing, thus, the interpolators can
// overflow. But while "nlen" is positive we are safe.
//-------------------------
while (len && nlen > 0)
{
span->r = (value_type)r.y();
span->g = (value_type)g.y();
span->b = (value_type)b.y();
span->a = (value_type)a.y();
r += subpixel_scale;
g += subpixel_scale;
b += subpixel_scale;
a += subpixel_scale;
nlen -= subpixel_scale;
++span;
--len;
}
// Ending part; checking for overflow.
// Typically it's 1-2 pixels, but may be more in some cases.
//-------------------------
while (len)
{
vr = r.y();
vg = g.y();
vb = b.y();
va = a.y();
if (vr < 0)
vr = 0;
if (vr > lim)
vr = lim;
if (vg < 0)
vg = 0;
if (vg > lim)
vg = lim;
if (vb < 0)
vb = 0;
if (vb > lim)
vb = lim;
if (va < 0)
va = 0;
if (va > lim)
va = lim;
span->r = (value_type)vr;
span->g = (value_type)vg;
span->b = (value_type)vb;
span->a = (value_type)va;
r += subpixel_scale;
g += subpixel_scale;
b += subpixel_scale;
a += subpixel_scale;
++span;
--len;
}
}
private:
bool m_swap;
int m_y2;
rgba_calc m_rgba1;
rgba_calc m_rgba2;
rgba_calc m_rgba3;
};
} // namespace agg
#endif #endif

View file

@ -23,342 +23,326 @@
#include "agg_math.h" #include "agg_math.h"
#include "agg_array.h" #include "agg_array.h"
namespace agg {
namespace agg enum gradient_subpixel_scale_e {
gradient_subpixel_shift = 4, //-----gradient_subpixel_shift
gradient_subpixel_scale = 1 << gradient_subpixel_shift, //-----gradient_subpixel_scale
gradient_subpixel_mask = gradient_subpixel_scale - 1 //-----gradient_subpixel_mask
};
//==========================================================span_gradient
template<class ColorT, class Interpolator, class GradientF, class ColorF>
class span_gradient
{ {
public:
typedef Interpolator interpolator_type;
typedef ColorT color_type;
enum gradient_subpixel_scale_e enum downscale_shift_e { downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift };
//--------------------------------------------------------------------
span_gradient() {}
//--------------------------------------------------------------------
span_gradient(interpolator_type& inter,
const GradientF& gradient_function,
const ColorF& color_function,
double d1,
double d2)
: m_interpolator(&inter)
, m_gradient_function(&gradient_function)
, m_color_function(&color_function)
, m_d1(iround(d1 * gradient_subpixel_scale))
, m_d2(iround(d2 * gradient_subpixel_scale))
{}
//--------------------------------------------------------------------
interpolator_type& interpolator() { return *m_interpolator; }
const GradientF& gradient_function() const { return *m_gradient_function; }
const ColorF& color_function() const { return *m_color_function; }
double d1() const { return double(m_d1) / gradient_subpixel_scale; }
double d2() const { return double(m_d2) / gradient_subpixel_scale; }
//--------------------------------------------------------------------
void interpolator(interpolator_type& i) { m_interpolator = &i; }
void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
void color_function(const ColorF& cf) { m_color_function = &cf; }
void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); }
void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); }
//--------------------------------------------------------------------
void prepare() {}
//--------------------------------------------------------------------
void generate(color_type* span, int x, int y, unsigned len)
{ {
gradient_subpixel_shift = 4, //-----gradient_subpixel_shift int dd = m_d2 - m_d1;
gradient_subpixel_scale = 1 << gradient_subpixel_shift, //-----gradient_subpixel_scale if (dd < 1)
gradient_subpixel_mask = gradient_subpixel_scale - 1 //-----gradient_subpixel_mask 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, m_d2);
d = ((d - m_d1) * (int)m_color_function->size()) / dd;
if (d < 0)
d = 0;
if (d >= (int)m_color_function->size())
d = m_color_function->size() - 1;
*span++ = (*m_color_function)[d];
++(*m_interpolator);
} while (--len);
}
private:
interpolator_type* m_interpolator;
const GradientF* m_gradient_function;
const ColorF* m_color_function;
int m_d1;
int m_d2;
};
//=====================================================gradient_linear_color
template<class ColorT>
struct gradient_linear_color
{
typedef ColorT color_type;
//==========================================================span_gradient gradient_linear_color() {}
template<class ColorT, gradient_linear_color(const color_type& c1, const color_type& c2, unsigned size = 256)
class Interpolator, : m_c1(c1)
class GradientF, , m_c2(c2)
class ColorF> , m_size(size)
class span_gradient {}
unsigned size() const { return m_size; }
color_type operator[](unsigned v) const { return m_c1.gradient(m_c2, double(v) / double(m_size - 1)); }
void colors(const color_type& c1, const color_type& c2, unsigned size = 256)
{ {
public: m_c1 = c1;
typedef Interpolator interpolator_type; m_c2 = c2;
typedef ColorT color_type; m_size = size;
}
enum downscale_shift_e color_type m_c1;
color_type m_c2;
unsigned m_size;
};
//==========================================================gradient_circle
class gradient_circle
{
// Actually the same as radial. Just for compatibility
public:
static AGG_INLINE int calculate(int x, int y, int) { return int(fast_sqrt(x * x + y * y)); }
};
//==========================================================gradient_radial
class gradient_radial
{
public:
static AGG_INLINE int calculate(int x, int y, int) { return int(fast_sqrt(x * x + y * y)); }
};
//========================================================gradient_radial_d
class gradient_radial_d
{
public:
static AGG_INLINE int calculate(int x, int y, int)
{
return uround(sqrt(double(x) * double(x) + double(y) * double(y)));
}
};
//====================================================gradient_radial_focus
class gradient_radial_focus
{
public:
//---------------------------------------------------------------------
gradient_radial_focus()
: m_r(100 * gradient_subpixel_scale)
, m_fx(0)
, m_fy(0)
{
update_values();
}
//---------------------------------------------------------------------
gradient_radial_focus(double r, double fx, double fy)
: m_r(iround(r * gradient_subpixel_scale))
, m_fx(iround(fx * gradient_subpixel_scale))
, m_fy(iround(fy * gradient_subpixel_scale))
{
update_values();
}
//---------------------------------------------------------------------
void init(double r, double fx, double fy)
{
m_r = iround(r * gradient_subpixel_scale);
m_fx = iround(fx * gradient_subpixel_scale);
m_fy = iround(fy * gradient_subpixel_scale);
update_values();
}
//---------------------------------------------------------------------
double radius() const { return double(m_r) / gradient_subpixel_scale; }
double focus_x() const { return double(m_fx) / gradient_subpixel_scale; }
double focus_y() const { return double(m_fy) / gradient_subpixel_scale; }
//---------------------------------------------------------------------
int calculate(int x, int y, int) const
{
double dx = x - m_fx;
double dy = y - m_fy;
double d2 = dx * m_fy - dy * m_fx;
double d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2;
return iround((dx * m_fx + dy * m_fy + sqrt(std::fabs(d3))) * m_mul);
}
private:
//---------------------------------------------------------------------
void update_values()
{
// Calculate the invariant values. In case the focal center
// lies exactly on the gradient circle the divisor degenerates
// into zero. In this case we just move the focal center by
// one subpixel unit possibly in the direction to the origin (0,0)
// and calculate the values again.
//-------------------------
m_r2 = double(m_r) * double(m_r);
m_fx2 = double(m_fx) * double(m_fx);
m_fy2 = double(m_fy) * double(m_fy);
double d = (m_r2 - (m_fx2 + m_fy2));
if (d == 0)
{ {
downscale_shift = interpolator_type::subpixel_shift - if (m_fx)
gradient_subpixel_shift
};
//--------------------------------------------------------------------
span_gradient() {}
//--------------------------------------------------------------------
span_gradient(interpolator_type& inter,
const GradientF& gradient_function,
const ColorF& color_function,
double d1, double d2) :
m_interpolator(&inter),
m_gradient_function(&gradient_function),
m_color_function(&color_function),
m_d1(iround(d1 * gradient_subpixel_scale)),
m_d2(iround(d2 * gradient_subpixel_scale))
{}
//--------------------------------------------------------------------
interpolator_type& interpolator() { return *m_interpolator; }
const GradientF& gradient_function() const { return *m_gradient_function; }
const ColorF& color_function() const { return *m_color_function; }
double d1() const { return double(m_d1) / gradient_subpixel_scale; }
double d2() const { return double(m_d2) / gradient_subpixel_scale; }
//--------------------------------------------------------------------
void interpolator(interpolator_type& i) { m_interpolator = &i; }
void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
void color_function(const ColorF& cf) { m_color_function = &cf; }
void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); }
void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); }
//--------------------------------------------------------------------
void prepare() {}
//--------------------------------------------------------------------
void generate(color_type* span, int x, int y, unsigned len)
{
int dd = m_d2 - m_d1;
if(dd < 1) dd = 1;
m_interpolator->begin(x+0.5, y+0.5, len);
do
{ {
m_interpolator->coordinates(&x, &y); if (m_fx < 0)
int d = m_gradient_function->calculate(x >> downscale_shift, ++m_fx;
y >> downscale_shift, m_d2); else
d = ((d - m_d1) * (int)m_color_function->size()) / dd; --m_fx;
if(d < 0) d = 0; }
if(d >= (int)m_color_function->size()) d = m_color_function->size() - 1; if (m_fy)
*span++ = (*m_color_function)[d]; {
++(*m_interpolator); if (m_fy < 0)
++m_fy;
else
--m_fy;
} }
while(--len);
}
private:
interpolator_type* m_interpolator;
const GradientF* m_gradient_function;
const ColorF* m_color_function;
int m_d1;
int m_d2;
};
//=====================================================gradient_linear_color
template<class ColorT>
struct gradient_linear_color
{
typedef ColorT color_type;
gradient_linear_color() {}
gradient_linear_color(const color_type& c1, const color_type& c2,
unsigned size = 256) :
m_c1(c1), m_c2(c2), m_size(size) {}
unsigned size() const { return m_size; }
color_type operator [] (unsigned v) const
{
return m_c1.gradient(m_c2, double(v) / double(m_size - 1));
}
void colors(const color_type& c1, const color_type& c2, unsigned size = 256)
{
m_c1 = c1;
m_c2 = c2;
m_size = size;
}
color_type m_c1;
color_type m_c2;
unsigned m_size;
};
//==========================================================gradient_circle
class gradient_circle
{
// Actually the same as radial. Just for compatibility
public:
static AGG_INLINE int calculate(int x, int y, int)
{
return int(fast_sqrt(x*x + y*y));
}
};
//==========================================================gradient_radial
class gradient_radial
{
public:
static AGG_INLINE int calculate(int x, int y, int)
{
return int(fast_sqrt(x*x + y*y));
}
};
//========================================================gradient_radial_d
class gradient_radial_d
{
public:
static AGG_INLINE int calculate(int x, int y, int)
{
return uround(sqrt(double(x)*double(x) + double(y)*double(y)));
}
};
//====================================================gradient_radial_focus
class gradient_radial_focus
{
public:
//---------------------------------------------------------------------
gradient_radial_focus() :
m_r(100 * gradient_subpixel_scale),
m_fx(0),
m_fy(0)
{
update_values();
}
//---------------------------------------------------------------------
gradient_radial_focus(double r, double fx, double fy) :
m_r (iround(r * gradient_subpixel_scale)),
m_fx(iround(fx * gradient_subpixel_scale)),
m_fy(iround(fy * gradient_subpixel_scale))
{
update_values();
}
//---------------------------------------------------------------------
void init(double r, double fx, double fy)
{
m_r = iround(r * gradient_subpixel_scale);
m_fx = iround(fx * gradient_subpixel_scale);
m_fy = iround(fy * gradient_subpixel_scale);
update_values();
}
//---------------------------------------------------------------------
double radius() const { return double(m_r) / gradient_subpixel_scale; }
double focus_x() const { return double(m_fx) / gradient_subpixel_scale; }
double focus_y() const { return double(m_fy) / gradient_subpixel_scale; }
//---------------------------------------------------------------------
int calculate(int x, int y, int) const
{
double dx = x - m_fx;
double dy = y - m_fy;
double d2 = dx * m_fy - dy * m_fx;
double d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2;
return iround((dx * m_fx + dy * m_fy + sqrt(std::fabs(d3))) * m_mul);
}
private:
//---------------------------------------------------------------------
void update_values()
{
// Calculate the invariant values. In case the focal center
// lies exactly on the gradient circle the divisor degenerates
// into zero. In this case we just move the focal center by
// one subpixel unit possibly in the direction to the origin (0,0)
// and calculate the values again.
//-------------------------
m_r2 = double(m_r) * double(m_r);
m_fx2 = double(m_fx) * double(m_fx); m_fx2 = double(m_fx) * double(m_fx);
m_fy2 = double(m_fy) * double(m_fy); m_fy2 = double(m_fy) * double(m_fy);
double d = (m_r2 - (m_fx2 + m_fy2)); d = (m_r2 - (m_fx2 + m_fy2));
if(d == 0)
{
if(m_fx) { if(m_fx < 0) ++m_fx; else --m_fx; }
if(m_fy) { if(m_fy < 0) ++m_fy; else --m_fy; }
m_fx2 = double(m_fx) * double(m_fx);
m_fy2 = double(m_fy) * double(m_fy);
d = (m_r2 - (m_fx2 + m_fy2));
}
m_mul = m_r / d;
} }
m_mul = m_r / d;
}
int m_r; int m_r;
int m_fx; int m_fx;
int m_fy; int m_fy;
double m_r2; double m_r2;
double m_fx2; double m_fx2;
double m_fy2; double m_fy2;
double m_mul; double m_mul;
}; };
//==============================================================gradient_x
class gradient_x
{
public:
static int calculate(int x, int, int) { return x; }
};
//==============================================================gradient_x //==============================================================gradient_y
class gradient_x class gradient_y
{
public:
static int calculate(int, int y, int) { return y; }
};
//========================================================gradient_diamond
class gradient_diamond
{
public:
static AGG_INLINE int calculate(int x, int y, int)
{ {
public: int ax = std::abs(x);
static int calculate(int x, int, int) { return x; } int ay = std::abs(y);
}; return ax > ay ? ax : ay;
}
};
//=============================================================gradient_xy
class gradient_xy
{
public:
static AGG_INLINE int calculate(int x, int y, int d) { return std::abs(x) * std::abs(y) / d; }
};
//==============================================================gradient_y //========================================================gradient_sqrt_xy
class gradient_y class gradient_sqrt_xy
{
public:
static AGG_INLINE int calculate(int x, int y, int) { return fast_sqrt(std::abs(x) * std::abs(y)); }
};
//==========================================================gradient_conic
class gradient_conic
{
public:
static AGG_INLINE int calculate(int x, int y, int d)
{ {
public: return uround(std::fabs(std::atan2(double(y), double(x))) * double(d) / pi);
static int calculate(int, int y, int) { return y; } }
}; };
//========================================================gradient_diamond //=================================================gradient_repeat_adaptor
class gradient_diamond template<class GradientF>
class gradient_repeat_adaptor
{
public:
gradient_repeat_adaptor(const GradientF& gradient)
: m_gradient(&gradient)
{}
AGG_INLINE int calculate(int x, int y, int d) const
{ {
public: int ret = m_gradient->calculate(x, y, d) % d;
static AGG_INLINE int calculate(int x, int y, int) if (ret < 0)
{ ret += d;
int ax = std::abs(x); return ret;
int ay = std::abs(y); }
return ax > ay ? ax : ay;
}
};
//=============================================================gradient_xy private:
class gradient_xy const GradientF* m_gradient;
};
//================================================gradient_reflect_adaptor
template<class GradientF>
class gradient_reflect_adaptor
{
public:
gradient_reflect_adaptor(const GradientF& gradient)
: m_gradient(&gradient)
{}
AGG_INLINE int calculate(int x, int y, int d) const
{ {
public: int d2 = d << 1;
static AGG_INLINE int calculate(int x, int y, int d) int ret = m_gradient->calculate(x, y, d) % d2;
{ if (ret < 0)
return std::abs(x) * std::abs(y) / d; ret += d2;
} if (ret >= d)
}; ret = d2 - ret;
return ret;
}
//========================================================gradient_sqrt_xy private:
class gradient_sqrt_xy const GradientF* m_gradient;
{ };
public:
static AGG_INLINE int calculate(int x, int y, int)
{
return fast_sqrt(std::abs(x) * std::abs(y));
}
};
//==========================================================gradient_conic } // namespace agg
class gradient_conic
{
public:
static AGG_INLINE int calculate(int x, int y, int d)
{
return uround(std::fabs(std::atan2(double(y), double(x))) * double(d) / pi);
}
};
//=================================================gradient_repeat_adaptor
template<class GradientF> class gradient_repeat_adaptor
{
public:
gradient_repeat_adaptor(const GradientF& gradient) :
m_gradient(&gradient) {}
AGG_INLINE int calculate(int x, int y, int d) const
{
int ret = m_gradient->calculate(x, y, d) % d;
if(ret < 0) ret += d;
return ret;
}
private:
const GradientF* m_gradient;
};
//================================================gradient_reflect_adaptor
template<class GradientF> class gradient_reflect_adaptor
{
public:
gradient_reflect_adaptor(const GradientF& gradient) :
m_gradient(&gradient) {}
AGG_INLINE int calculate(int x, int y, int d) const
{
int d2 = d << 1;
int ret = m_gradient->calculate(x, y, d) % d2;
if(ret < 0) ret += d2;
if(ret >= d) ret = d2 - ret;
return ret;
}
private:
const GradientF* m_gradient;
};
}
#endif #endif

View file

@ -18,109 +18,103 @@
#include "agg_span_gradient.h" #include "agg_span_gradient.h"
namespace agg namespace agg {
//======================================================span_gradient_alpha
template<class ColorT, class Interpolator, class GradientF, class AlphaF>
class span_gradient_alpha
{ {
//======================================================span_gradient_alpha public:
template<class ColorT, typedef Interpolator interpolator_type;
class Interpolator, typedef ColorT color_type;
class GradientF, typedef typename color_type::value_type alpha_type;
class AlphaF>
class span_gradient_alpha
{
public:
typedef Interpolator interpolator_type;
typedef ColorT color_type;
typedef typename color_type::value_type alpha_type;
enum downscale_shift_e enum downscale_shift_e { downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift };
//--------------------------------------------------------------------
span_gradient_alpha() {}
//--------------------------------------------------------------------
span_gradient_alpha(interpolator_type& inter,
const GradientF& gradient_function,
const AlphaF& alpha_function,
double d1,
double d2)
: m_interpolator(&inter)
, m_gradient_function(&gradient_function)
, m_alpha_function(&alpha_function)
, m_d1(iround(d1 * gradient_subpixel_scale))
, m_d2(iround(d2 * gradient_subpixel_scale))
{}
//--------------------------------------------------------------------
interpolator_type& interpolator() { return *m_interpolator; }
const GradientF& gradient_function() const { return *m_gradient_function; }
const AlphaF& alpha_function() const { return *m_alpha_function; }
double d1() const { return double(m_d1) / gradient_subpixel_scale; }
double d2() const { return double(m_d2) / gradient_subpixel_scale; }
//--------------------------------------------------------------------
void interpolator(interpolator_type& i) { m_interpolator = &i; }
void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
void alpha_function(const AlphaF& af) { m_alpha_function = &af; }
void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); }
void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); }
//--------------------------------------------------------------------
void prepare() {}
//--------------------------------------------------------------------
void generate(color_type* span, int x, int y, unsigned len)
{
int dd = m_d2 - m_d1;
if (dd < 1)
dd = 1;
m_interpolator->begin(x + 0.5, y + 0.5, len);
do
{ {
downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift m_interpolator->coordinates(&x, &y);
}; int d = m_gradient_function->calculate(x >> downscale_shift, y >> downscale_shift, m_d2);
d = ((d - m_d1) * (int)m_alpha_function->size()) / dd;
if (d < 0)
d = 0;
if (d >= (int)m_alpha_function->size())
d = m_alpha_function->size() - 1;
span->a = (*m_alpha_function)[d];
++span;
++(*m_interpolator);
} while (--len);
}
private:
interpolator_type* m_interpolator;
const GradientF* m_gradient_function;
const AlphaF* m_alpha_function;
int m_d1;
int m_d2;
};
//-------------------------------------------------------------------- //=======================================================gradient_alpha_x
span_gradient_alpha() {} template<class ColorT>
struct gradient_alpha_x
{
typedef typename ColorT::value_type alpha_type;
alpha_type operator[](alpha_type x) const { return x; }
};
//-------------------------------------------------------------------- //====================================================gradient_alpha_x_u8
span_gradient_alpha(interpolator_type& inter, struct gradient_alpha_x_u8
const GradientF& gradient_function, {
const AlphaF& alpha_function, typedef int8u alpha_type;
double d1, double d2) : alpha_type operator[](alpha_type x) const { return x; }
m_interpolator(&inter), };
m_gradient_function(&gradient_function),
m_alpha_function(&alpha_function),
m_d1(iround(d1 * gradient_subpixel_scale)),
m_d2(iround(d2 * gradient_subpixel_scale))
{}
//-------------------------------------------------------------------- //==========================================gradient_alpha_one_munus_x_u8
interpolator_type& interpolator() { return *m_interpolator; } struct gradient_alpha_one_munus_x_u8
const GradientF& gradient_function() const { return *m_gradient_function; } {
const AlphaF& alpha_function() const { return *m_alpha_function; } typedef int8u alpha_type;
double d1() const { return double(m_d1) / gradient_subpixel_scale; } alpha_type operator[](alpha_type x) const { return 255 - x; }
double d2() const { return double(m_d2) / gradient_subpixel_scale; } };
//-------------------------------------------------------------------- } // namespace agg
void interpolator(interpolator_type& i) { m_interpolator = &i; }
void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
void alpha_function(const AlphaF& af) { m_alpha_function = &af; }
void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); }
void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); }
//--------------------------------------------------------------------
void prepare() {}
//--------------------------------------------------------------------
void generate(color_type* span, int x, int y, unsigned len)
{
int dd = m_d2 - m_d1;
if(dd < 1) dd = 1;
m_interpolator->begin(x+0.5, y+0.5, len);
do
{
m_interpolator->coordinates(&x, &y);
int d = m_gradient_function->calculate(x >> downscale_shift,
y >> downscale_shift, m_d2);
d = ((d - m_d1) * (int)m_alpha_function->size()) / dd;
if(d < 0) d = 0;
if(d >= (int)m_alpha_function->size()) d = m_alpha_function->size() - 1;
span->a = (*m_alpha_function)[d];
++span;
++(*m_interpolator);
}
while(--len);
}
private:
interpolator_type* m_interpolator;
const GradientF* m_gradient_function;
const AlphaF* m_alpha_function;
int m_d1;
int m_d2;
};
//=======================================================gradient_alpha_x
template<class ColorT> struct gradient_alpha_x
{
typedef typename ColorT::value_type alpha_type;
alpha_type operator [] (alpha_type x) const { return x; }
};
//====================================================gradient_alpha_x_u8
struct gradient_alpha_x_u8
{
typedef int8u alpha_type;
alpha_type operator [] (alpha_type x) const { return x; }
};
//==========================================gradient_alpha_one_munus_x_u8
struct gradient_alpha_one_munus_x_u8
{
typedef int8u alpha_type;
alpha_type operator [] (alpha_type x) const { return 255-x; }
};
}
#endif #endif

View file

@ -23,224 +23,216 @@
#include "agg_image_filters.h" #include "agg_image_filters.h"
#include "agg_span_interpolator_linear.h" #include "agg_span_interpolator_linear.h"
namespace agg namespace agg {
//-------------------------------------------------------span_image_filter
template<class Source, class Interpolator>
class span_image_filter
{ {
public:
typedef Source source_type;
typedef Interpolator interpolator_type;
//-------------------------------------------------------span_image_filter //--------------------------------------------------------------------
template<class Source, class Interpolator> class span_image_filter span_image_filter() {}
span_image_filter(source_type& src, interpolator_type& interpolator, const image_filter_lut* filter)
: m_src(&src)
, m_interpolator(&interpolator)
, m_filter(filter)
, m_dx_dbl(0.5)
, m_dy_dbl(0.5)
, m_dx_int(image_subpixel_scale / 2)
, m_dy_int(image_subpixel_scale / 2)
{}
void attach(source_type& v) { m_src = &v; }
//--------------------------------------------------------------------
source_type& source() { return *m_src; }
const source_type& source() const { return *m_src; }
const image_filter_lut& filter() const { return *m_filter; }
int filter_dx_int() const { return m_dx_int; }
int filter_dy_int() const { return m_dy_int; }
double filter_dx_dbl() const { return m_dx_dbl; }
double filter_dy_dbl() const { return m_dy_dbl; }
//--------------------------------------------------------------------
void interpolator(interpolator_type& v) { m_interpolator = &v; }
void filter(const image_filter_lut& v) { m_filter = &v; }
void filter_offset(double dx, double dy)
{ {
public: m_dx_dbl = dx;
typedef Source source_type; m_dy_dbl = dy;
typedef Interpolator interpolator_type; m_dx_int = iround(dx * image_subpixel_scale);
m_dy_int = iround(dy * image_subpixel_scale);
}
void filter_offset(double d) { filter_offset(d, d); }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
span_image_filter() {} interpolator_type& interpolator() { return *m_interpolator; }
span_image_filter(source_type& src,
interpolator_type& interpolator,
const image_filter_lut* filter) :
m_src(&src),
m_interpolator(&interpolator),
m_filter(filter),
m_dx_dbl(0.5),
m_dy_dbl(0.5),
m_dx_int(image_subpixel_scale / 2),
m_dy_int(image_subpixel_scale / 2)
{}
void attach(source_type& v) { m_src = &v; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
source_type& source() { return *m_src; } void prepare() {}
const source_type& source() const { return *m_src; }
const image_filter_lut& filter() const { return *m_filter; }
int filter_dx_int() const { return m_dx_int; }
int filter_dy_int() const { return m_dy_int; }
double filter_dx_dbl() const { return m_dx_dbl; }
double filter_dy_dbl() const { return m_dy_dbl; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void interpolator(interpolator_type& v) { m_interpolator = &v; } private:
void filter(const image_filter_lut& v) { m_filter = &v; } source_type* m_src;
void filter_offset(double dx, double dy) interpolator_type* m_interpolator;
{ const image_filter_lut* m_filter;
m_dx_dbl = dx; double m_dx_dbl;
m_dy_dbl = dy; double m_dy_dbl;
m_dx_int = iround(dx * image_subpixel_scale); unsigned m_dx_int;
m_dy_int = iround(dy * image_subpixel_scale); unsigned m_dy_int;
} };
void filter_offset(double d) { filter_offset(d, d); }
//-------------------------------------------------------------------- //==============================================span_image_resample_affine
interpolator_type& interpolator() { return *m_interpolator; } template<class Source>
class span_image_resample_affine : public span_image_filter<Source, span_interpolator_linear<trans_affine>>
{
public:
typedef Source source_type;
typedef span_interpolator_linear<trans_affine> interpolator_type;
typedef span_image_filter<source_type, interpolator_type> base_type;
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void prepare() {} span_image_resample_affine()
: m_scale_limit(200.0)
, m_blur_x(1.0)
, m_blur_y(1.0)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
private: span_image_resample_affine(source_type& src, interpolator_type& inter, const image_filter_lut& filter)
source_type* m_src; : base_type(src, inter, &filter)
interpolator_type* m_interpolator; , m_scale_limit(200.0)
const image_filter_lut* m_filter; , m_blur_x(1.0)
double m_dx_dbl; , m_blur_y(1.0)
double m_dy_dbl; {}
unsigned m_dx_int;
unsigned m_dy_int;
};
//--------------------------------------------------------------------
int scale_limit() const { return uround(m_scale_limit); }
void scale_limit(int v) { m_scale_limit = v; }
//--------------------------------------------------------------------
double blur_x() const { return m_blur_x; }
double blur_y() const { return m_blur_y; }
void blur_x(double v) { m_blur_x = v; }
void blur_y(double v) { m_blur_y = v; }
void blur(double v) { m_blur_x = m_blur_y = v; }
//--------------------------------------------------------------------
//==============================================span_image_resample_affine void prepare()
template<class Source>
class span_image_resample_affine :
public span_image_filter<Source, span_interpolator_linear<trans_affine> >
{ {
public: double scale_x;
typedef Source source_type; double scale_y;
typedef span_interpolator_linear<trans_affine> interpolator_type;
typedef span_image_filter<source_type, interpolator_type> base_type;
//-------------------------------------------------------------------- base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y);
span_image_resample_affine() :
m_scale_limit(200.0),
m_blur_x(1.0),
m_blur_y(1.0)
{}
//-------------------------------------------------------------------- if (scale_x * scale_y > m_scale_limit)
span_image_resample_affine(source_type& src,
interpolator_type& inter,
const image_filter_lut& filter) :
base_type(src, inter, &filter),
m_scale_limit(200.0),
m_blur_x(1.0),
m_blur_y(1.0)
{}
//--------------------------------------------------------------------
int scale_limit() const { return uround(m_scale_limit); }
void scale_limit(int v) { m_scale_limit = v; }
//--------------------------------------------------------------------
double blur_x() const { return m_blur_x; }
double blur_y() const { return m_blur_y; }
void blur_x(double v) { m_blur_x = v; }
void blur_y(double v) { m_blur_y = v; }
void blur(double v) { m_blur_x = m_blur_y = v; }
//--------------------------------------------------------------------
void prepare()
{ {
double scale_x; scale_x = scale_x * m_scale_limit / (scale_x * scale_y);
double scale_y; scale_y = scale_y * m_scale_limit / (scale_x * scale_y);
base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y);
if(scale_x * scale_y > m_scale_limit)
{
scale_x = scale_x * m_scale_limit / (scale_x * scale_y);
scale_y = scale_y * m_scale_limit / (scale_x * scale_y);
}
if(scale_x < 1) scale_x = 1;
if(scale_y < 1) scale_y = 1;
if(scale_x > m_scale_limit) scale_x = m_scale_limit;
if(scale_y > m_scale_limit) scale_y = m_scale_limit;
scale_x *= m_blur_x;
scale_y *= m_blur_y;
if(scale_x < 1) scale_x = 1;
if(scale_y < 1) scale_y = 1;
m_rx = uround( scale_x * double(image_subpixel_scale));
m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale));
m_ry = uround( scale_y * double(image_subpixel_scale));
m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale));
} }
protected: if (scale_x < 1)
int m_rx; scale_x = 1;
int m_ry; if (scale_y < 1)
int m_rx_inv; scale_y = 1;
int m_ry_inv;
private: if (scale_x > m_scale_limit)
double m_scale_limit; scale_x = m_scale_limit;
double m_blur_x; if (scale_y > m_scale_limit)
double m_blur_y; scale_y = m_scale_limit;
};
scale_x *= m_blur_x;
scale_y *= m_blur_y;
if (scale_x < 1)
scale_x = 1;
if (scale_y < 1)
scale_y = 1;
//=====================================================span_image_resample m_rx = uround(scale_x * double(image_subpixel_scale));
template<class Source, class Interpolator> m_rx_inv = uround(1.0 / scale_x * double(image_subpixel_scale));
class span_image_resample :
public span_image_filter<Source, Interpolator> m_ry = uround(scale_y * double(image_subpixel_scale));
m_ry_inv = uround(1.0 / scale_y * double(image_subpixel_scale));
}
protected:
int m_rx;
int m_ry;
int m_rx_inv;
int m_ry_inv;
private:
double m_scale_limit;
double m_blur_x;
double m_blur_y;
};
//=====================================================span_image_resample
template<class Source, class Interpolator>
class span_image_resample : public span_image_filter<Source, Interpolator>
{
public:
typedef Source source_type;
typedef Interpolator interpolator_type;
typedef span_image_filter<source_type, interpolator_type> base_type;
//--------------------------------------------------------------------
span_image_resample()
: m_scale_limit(20)
, m_blur_x(image_subpixel_scale)
, m_blur_y(image_subpixel_scale)
{}
//--------------------------------------------------------------------
span_image_resample(source_type& src, interpolator_type& inter, const image_filter_lut& filter)
: base_type(src, inter, &filter)
, m_scale_limit(20)
, m_blur_x(image_subpixel_scale)
, m_blur_y(image_subpixel_scale)
{}
//--------------------------------------------------------------------
int scale_limit() const { return m_scale_limit; }
void scale_limit(int v) { m_scale_limit = v; }
//--------------------------------------------------------------------
double blur_x() const { return double(m_blur_x) / double(image_subpixel_scale); }
double blur_y() const { return double(m_blur_y) / double(image_subpixel_scale); }
void blur_x(double v) { m_blur_x = uround(v * double(image_subpixel_scale)); }
void blur_y(double v) { m_blur_y = uround(v * double(image_subpixel_scale)); }
void blur(double v) { m_blur_x = m_blur_y = uround(v * double(image_subpixel_scale)); }
protected:
AGG_INLINE void adjust_scale(int* rx, int* ry)
{ {
public: if (*rx < image_subpixel_scale)
typedef Source source_type; *rx = image_subpixel_scale;
typedef Interpolator interpolator_type; if (*ry < image_subpixel_scale)
typedef span_image_filter<source_type, interpolator_type> base_type; *ry = image_subpixel_scale;
if (*rx > image_subpixel_scale * m_scale_limit)
//--------------------------------------------------------------------
span_image_resample() :
m_scale_limit(20),
m_blur_x(image_subpixel_scale),
m_blur_y(image_subpixel_scale)
{}
//--------------------------------------------------------------------
span_image_resample(source_type& src,
interpolator_type& inter,
const image_filter_lut& filter) :
base_type(src, inter, &filter),
m_scale_limit(20),
m_blur_x(image_subpixel_scale),
m_blur_y(image_subpixel_scale)
{}
//--------------------------------------------------------------------
int scale_limit() const { return m_scale_limit; }
void scale_limit(int v) { m_scale_limit = v; }
//--------------------------------------------------------------------
double blur_x() const { return double(m_blur_x) / double(image_subpixel_scale); }
double blur_y() const { return double(m_blur_y) / double(image_subpixel_scale); }
void blur_x(double v) { m_blur_x = uround(v * double(image_subpixel_scale)); }
void blur_y(double v) { m_blur_y = uround(v * double(image_subpixel_scale)); }
void blur(double v) { m_blur_x =
m_blur_y = uround(v * double(image_subpixel_scale)); }
protected:
AGG_INLINE void adjust_scale(int* rx, int* ry)
{ {
if(*rx < image_subpixel_scale) *rx = image_subpixel_scale; *rx = image_subpixel_scale * m_scale_limit;
if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
if(*rx > image_subpixel_scale * m_scale_limit)
{
*rx = image_subpixel_scale * m_scale_limit;
}
if(*ry > image_subpixel_scale * m_scale_limit)
{
*ry = image_subpixel_scale * m_scale_limit;
}
*rx = (*rx * m_blur_x) >> image_subpixel_shift;
*ry = (*ry * m_blur_y) >> image_subpixel_shift;
if(*rx < image_subpixel_scale) *rx = image_subpixel_scale;
if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
} }
if (*ry > image_subpixel_scale * m_scale_limit)
{
*ry = image_subpixel_scale * m_scale_limit;
}
*rx = (*rx * m_blur_x) >> image_subpixel_shift;
*ry = (*ry * m_blur_y) >> image_subpixel_shift;
if (*rx < image_subpixel_scale)
*rx = image_subpixel_scale;
if (*ry < image_subpixel_scale)
*ry = image_subpixel_scale;
}
int m_scale_limit; int m_scale_limit;
int m_blur_x; int m_blur_x;
int m_blur_y; int m_blur_y;
}; };
} // namespace agg
}
#endif #endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -18,60 +18,47 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg 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 //--------------------------------------------------------------------
template<class Interpolator, class Distortion> span_interpolator_adaptor() {}
class span_interpolator_adaptor : public Interpolator 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
{ {
public: base_type::coordinates(x, y);
typedef Interpolator base_type; m_distortion->calculate(x, y);
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;
};
}
private:
//--------------------------------------------------------------------
const distortion_type* m_distortion;
};
} // namespace agg
#endif #endif

View file

@ -20,213 +20,199 @@
#include "agg_dda_line.h" #include "agg_dda_line.h"
#include "agg_trans_affine.h" #include "agg_trans_affine.h"
namespace agg namespace agg {
//================================================span_interpolator_linear
template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
class span_interpolator_linear
{ {
public:
typedef Transformer trans_type;
//================================================span_interpolator_linear enum subpixel_scale_e { subpixel_shift = SubpixelShift, subpixel_scale = 1 << subpixel_shift };
template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
class span_interpolator_linear //--------------------------------------------------------------------
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)
{ {
public: begin(x, y, len);
typedef Transformer trans_type; }
enum subpixel_scale_e //----------------------------------------------------------------
{ const trans_type& transformer() const { return *m_trans; }
subpixel_shift = SubpixelShift, void transformer(const trans_type& trans) { m_trans = &trans; }
subpixel_scale = 1 << subpixel_shift
};
//-------------------------------------------------------------------- //----------------------------------------------------------------
span_interpolator_linear() {} void begin(double x, double y, unsigned len)
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 = iround(tx * subpixel_scale);
int y1 = iround(ty * subpixel_scale);
tx = x + len;
ty = y;
m_trans->transform(&tx, &ty);
int x2 = iround(tx * subpixel_scale);
int y2 = iround(ty * subpixel_scale);
m_li_x = dda2_line_interpolator(x1, x2, len);
m_li_y = dda2_line_interpolator(y1, y2, len);
}
//----------------------------------------------------------------
void resynchronize(double xe, double ye, unsigned len)
{
m_trans->transform(&xe, &ye);
m_li_x = dda2_line_interpolator(m_li_x.y(), iround(xe * subpixel_scale), len);
m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ye * subpixel_scale), len);
}
//----------------------------------------------------------------
void operator++()
{
++m_li_x;
++m_li_y;
}
//----------------------------------------------------------------
void coordinates(int* x, int* y) const
{
*x = m_li_x.y();
*y = m_li_y.y();
}
private:
const trans_type* m_trans;
dda2_line_interpolator m_li_x;
dda2_line_interpolator m_li_y;
};
//=====================================span_interpolator_linear_subdiv
template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
class span_interpolator_linear_subdiv
{ {
public: double tx;
typedef Transformer trans_type; double ty;
enum subpixel_scale_e tx = x;
ty = y;
m_trans->transform(&tx, &ty);
int x1 = iround(tx * subpixel_scale);
int y1 = iround(ty * subpixel_scale);
tx = x + len;
ty = y;
m_trans->transform(&tx, &ty);
int x2 = iround(tx * subpixel_scale);
int y2 = iround(ty * subpixel_scale);
m_li_x = dda2_line_interpolator(x1, x2, len);
m_li_y = dda2_line_interpolator(y1, y2, len);
}
//----------------------------------------------------------------
void resynchronize(double xe, double ye, unsigned len)
{
m_trans->transform(&xe, &ye);
m_li_x = dda2_line_interpolator(m_li_x.y(), iround(xe * subpixel_scale), len);
m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ye * subpixel_scale), len);
}
//----------------------------------------------------------------
void operator++()
{
++m_li_x;
++m_li_y;
}
//----------------------------------------------------------------
void coordinates(int* x, int* y) const
{
*x = m_li_x.y();
*y = m_li_y.y();
}
private:
const trans_type* m_trans;
dda2_line_interpolator m_li_x;
dda2_line_interpolator m_li_y;
};
//=====================================span_interpolator_linear_subdiv
template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
class span_interpolator_linear_subdiv
{
public:
typedef Transformer trans_type;
enum subpixel_scale_e { subpixel_shift = SubpixelShift, subpixel_scale = 1 << subpixel_shift };
//----------------------------------------------------------------
span_interpolator_linear_subdiv()
: m_subdiv_shift(4)
, m_subdiv_size(1 << m_subdiv_shift)
, m_subdiv_mask(m_subdiv_size - 1)
{}
span_interpolator_linear_subdiv(const trans_type& trans, unsigned subdiv_shift = 4)
: m_subdiv_shift(subdiv_shift)
, m_subdiv_size(1 << m_subdiv_shift)
, m_subdiv_mask(m_subdiv_size - 1)
, m_trans(&trans)
{}
span_interpolator_linear_subdiv(const trans_type& trans,
double x,
double y,
unsigned len,
unsigned subdiv_shift = 4)
: m_subdiv_shift(subdiv_shift)
, m_subdiv_size(1 << m_subdiv_shift)
, m_subdiv_mask(m_subdiv_size - 1)
, m_trans(&trans)
{
begin(x, y, len);
}
//----------------------------------------------------------------
const trans_type& transformer() const { return *m_trans; }
void transformer(const trans_type& trans) { m_trans = &trans; }
//----------------------------------------------------------------
unsigned subdiv_shift() const { return m_subdiv_shift; }
void subdiv_shift(unsigned shift)
{
m_subdiv_shift = shift;
m_subdiv_size = 1 << m_subdiv_shift;
m_subdiv_mask = m_subdiv_size - 1;
}
//----------------------------------------------------------------
void begin(double x, double y, unsigned len)
{
double tx;
double ty;
m_pos = 1;
m_src_x = iround(x * subpixel_scale) + subpixel_scale;
m_src_y = y;
m_len = len;
if (len > m_subdiv_size)
len = m_subdiv_size;
tx = x;
ty = y;
m_trans->transform(&tx, &ty);
int x1 = iround(tx * subpixel_scale);
int y1 = iround(ty * subpixel_scale);
tx = x + len;
ty = y;
m_trans->transform(&tx, &ty);
m_li_x = dda2_line_interpolator(x1, iround(tx * subpixel_scale), len);
m_li_y = dda2_line_interpolator(y1, iround(ty * subpixel_scale), len);
}
//----------------------------------------------------------------
void operator++()
{
++m_li_x;
++m_li_y;
if (m_pos >= m_subdiv_size)
{ {
subpixel_shift = SubpixelShift, unsigned len = m_len;
subpixel_scale = 1 << subpixel_shift if (len > m_subdiv_size)
}; len = m_subdiv_size;
double tx = double(m_src_x) / double(subpixel_scale) + len;
double ty = m_src_y;
//----------------------------------------------------------------
span_interpolator_linear_subdiv() :
m_subdiv_shift(4),
m_subdiv_size(1 << m_subdiv_shift),
m_subdiv_mask(m_subdiv_size - 1) {}
span_interpolator_linear_subdiv(const trans_type& trans,
unsigned subdiv_shift = 4) :
m_subdiv_shift(subdiv_shift),
m_subdiv_size(1 << m_subdiv_shift),
m_subdiv_mask(m_subdiv_size - 1),
m_trans(&trans) {}
span_interpolator_linear_subdiv(const trans_type& trans,
double x, double y, unsigned len,
unsigned subdiv_shift = 4) :
m_subdiv_shift(subdiv_shift),
m_subdiv_size(1 << m_subdiv_shift),
m_subdiv_mask(m_subdiv_size - 1),
m_trans(&trans)
{
begin(x, y, len);
}
//----------------------------------------------------------------
const trans_type& transformer() const { return *m_trans; }
void transformer(const trans_type& trans) { m_trans = &trans; }
//----------------------------------------------------------------
unsigned subdiv_shift() const { return m_subdiv_shift; }
void subdiv_shift(unsigned shift)
{
m_subdiv_shift = shift;
m_subdiv_size = 1 << m_subdiv_shift;
m_subdiv_mask = m_subdiv_size - 1;
}
//----------------------------------------------------------------
void begin(double x, double y, unsigned len)
{
double tx;
double ty;
m_pos = 1;
m_src_x = iround(x * subpixel_scale) + subpixel_scale;
m_src_y = y;
m_len = len;
if(len > m_subdiv_size) len = m_subdiv_size;
tx = x;
ty = y;
m_trans->transform(&tx, &ty); m_trans->transform(&tx, &ty);
int x1 = iround(tx * subpixel_scale); m_li_x = dda2_line_interpolator(m_li_x.y(), iround(tx * subpixel_scale), len);
int y1 = iround(ty * subpixel_scale); m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ty * subpixel_scale), len);
m_pos = 0;
tx = x + len;
ty = y;
m_trans->transform(&tx, &ty);
m_li_x = dda2_line_interpolator(x1, iround(tx * subpixel_scale), len);
m_li_y = dda2_line_interpolator(y1, iround(ty * subpixel_scale), len);
} }
m_src_x += subpixel_scale;
++m_pos;
--m_len;
}
//---------------------------------------------------------------- //----------------------------------------------------------------
void operator++() void coordinates(int* x, int* y) const
{ {
++m_li_x; *x = m_li_x.y();
++m_li_y; *y = m_li_y.y();
if(m_pos >= m_subdiv_size) }
{
unsigned len = m_len;
if(len > m_subdiv_size) len = m_subdiv_size;
double tx = double(m_src_x) / double(subpixel_scale) + len;
double ty = m_src_y;
m_trans->transform(&tx, &ty);
m_li_x = dda2_line_interpolator(m_li_x.y(), iround(tx * subpixel_scale), len);
m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ty * subpixel_scale), len);
m_pos = 0;
}
m_src_x += subpixel_scale;
++m_pos;
--m_len;
}
//----------------------------------------------------------------
void coordinates(int* x, int* y) const
{
*x = m_li_x.y();
*y = m_li_y.y();
}
private:
unsigned m_subdiv_shift;
unsigned m_subdiv_size;
unsigned m_subdiv_mask;
const trans_type* m_trans;
dda2_line_interpolator m_li_x;
dda2_line_interpolator m_li_y;
int m_src_x;
double m_src_y;
unsigned m_pos;
unsigned m_len;
};
}
private:
unsigned m_subdiv_shift;
unsigned m_subdiv_size;
unsigned m_subdiv_mask;
const trans_type* m_trans;
dda2_line_interpolator m_li_x;
dda2_line_interpolator m_li_y;
int m_src_x;
double m_src_y;
unsigned m_pos;
unsigned m_len;
};
} // namespace agg
#endif #endif

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