pre-commit run -a

This commit is contained in:
Mathis Logemann 2022-08-16 18:52:30 +02:00
parent df141876d0
commit e3d8e55a79
154 changed files with 44003 additions and 41746 deletions

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -23,427 +23,477 @@
#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
{ {
static unsigned calculate(const int8u* p) { return *p; } //===================================================one_component_mask_u8
}; struct one_component_mask_u8
//=====================================================rgb_to_gray_mask_u8
template<unsigned R, unsigned G, unsigned B>
struct rgb_to_gray_mask_u8
{
static unsigned calculate(const int8u* p) { return (p[R] * 77 + p[G] * 150 + p[B] * 29) >> 8; }
};
//==========================================================alpha_mask_u8
template<unsigned Step = 1, unsigned Offset = 0, class MaskF = one_component_mask_u8>
class alpha_mask_u8
{
public:
typedef int8u cover_type;
typedef alpha_mask_u8<Step, Offset, MaskF> self_type;
enum cover_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
{ {
if (x >= 0 && y >= 0 && x < (int)m_rbuf->width() && y < (int)m_rbuf->height()) static unsigned calculate(const int8u* p) { return *p; }
{ };
return (cover_type)m_mask_function.calculate(m_rbuf->row_ptr(y) + x * Step + Offset);
//=====================================================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;
} }
return 0; };
}
//-------------------------------------------------------------------- //==========================================================alpha_mask_u8
cover_type combine_pixel(int x, int y, cover_type val) const template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
class alpha_mask_u8
{ {
if (x >= 0 && y >= 0 && x < (int)m_rbuf->width() && y < (int)m_rbuf->height()) 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
{ {
return ( if(x >= 0 && y >= 0 &&
cover_type)((cover_full + val * m_mask_function.calculate(m_rbuf->row_ptr(y) + x * Step + Offset)) >> x < (int)m_rbuf->width() &&
cover_shift); y < (int)m_rbuf->height())
} {
return 0; return (cover_type)m_mask_function.calculate(
} m_rbuf->row_ptr(y) + x * Step + Offset);
}
//-------------------------------------------------------------------- return 0;
void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
{
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int count = num_pix;
cover_type* covers = dst;
if (y < 0 || y > ymax)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
} }
if (x < 0) //--------------------------------------------------------------------
cover_type combine_pixel(int x, int y, cover_type val) const
{ {
count += x; if(x >= 0 && y >= 0 &&
if (count <= 0) x < (int)m_rbuf->width() &&
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));
covers -= x; if(x < 0)
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 rest = x + count - xmax - 1; int xmax = m_rbuf->width() - 1;
count -= rest; int ymax = m_rbuf->height() - 1;
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; //--------------------------------------------------------------------
do void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
{ {
*covers++ = (cover_type)m_mask_function.calculate(mask); int xmax = m_rbuf->width() - 1;
mask += Step; int ymax = m_rbuf->height() - 1;
} while (--count);
}
//-------------------------------------------------------------------- int count = num_pix;
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const cover_type* covers = dst;
{
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int count = num_pix; if(x < 0 || x > xmax)
cover_type* covers = dst;
if (y < 0 || y > ymax)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
if (x < 0)
{
count += x;
if (count <= 0)
{ {
memset(dst, 0, num_pix * sizeof(cover_type)); memset(dst, 0, num_pix * sizeof(cover_type));
return; return;
} }
memset(covers, 0, -x * sizeof(cover_type));
covers -= x; if(y < 0)
x = 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);
} }
if (x + count > xmax) //--------------------------------------------------------------------
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
{ {
int rest = x + count - xmax - 1; int xmax = m_rbuf->width() - 1;
count -= rest; int ymax = m_rbuf->height() - 1;
if (count <= 0)
int count = num_pix;
cover_type* covers = dst;
if(x < 0 || x > xmax)
{ {
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));
}
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; if(y < 0)
do
{
*covers = (cover_type)((cover_full + (*covers) * m_mask_function.calculate(mask)) >> cover_shift);
++covers;
mask += Step;
} while (--count);
}
//--------------------------------------------------------------------
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
{
int xmax = m_rbuf->width() - 1;
int ymax = m_rbuf->height() - 1;
int count = num_pix;
cover_type* covers = dst;
if (x < 0 || x > xmax)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
if (y < 0)
{
count += y;
if (count <= 0)
{ {
memset(dst, 0, num_pix * sizeof(cover_type)); count += y;
return; if(count <= 0)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
memset(covers, 0, -y * sizeof(cover_type));
covers -= y;
y = 0;
} }
memset(covers, 0, -y * sizeof(cover_type));
covers -= y;
y = 0;
}
if (y + count > ymax) if(y + count > ymax)
{
int rest = y + count - ymax - 1;
count -= rest;
if (count <= 0)
{ {
memset(dst, 0, num_pix * sizeof(cover_type)); int rest = y + count - ymax - 1;
return; count -= rest;
if(count <= 0)
{
memset(dst, 0, num_pix * sizeof(cover_type));
return;
}
memset(covers + count, 0, rest * sizeof(cover_type));
} }
memset(covers + count, 0, rest * sizeof(cover_type));
}
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do 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)); *covers = (cover_type)((cover_full + (*covers) *
return; m_mask_function.calculate(mask)) >>
cover_shift);
++covers;
mask += m_rbuf->stride();
} }
memset(covers, 0, -y * sizeof(cover_type)); while(--count);
covers -= y;
y = 0;
} }
if (y + count > ymax)
private:
alpha_mask_u8(const self_type&);
const self_type& operator = (const self_type&);
rendering_buffer* m_rbuf;
MaskF m_mask_function;
};
typedef alpha_mask_u8<1, 0> alpha_mask_gray8; //----alpha_mask_gray8
typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r; //----alpha_mask_rgb24r
typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g; //----alpha_mask_rgb24g
typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b; //----alpha_mask_rgb24b
typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r; //----alpha_mask_bgr24r
typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g; //----alpha_mask_bgr24g
typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b; //----alpha_mask_bgr24b
typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r
typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g
typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b
typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a
typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r
typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g
typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b
typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a
typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r
typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g
typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b
typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a
typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r
typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g
typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b
typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray; //----alpha_mask_rgb24gray
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray; //----alpha_mask_bgr24gray
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray
//==========================================================amask_no_clip_u8
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
class amask_no_clip_u8
{
public:
typedef int8u cover_type;
typedef amask_no_clip_u8<Step, Offset, MaskF> self_type;
enum cover_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
{ {
int rest = y + count - ymax - 1; return (cover_type)m_mask_function.calculate(
count -= rest; m_rbuf->row_ptr(y) + x * Step + Offset);
if (count <= 0) }
//--------------------------------------------------------------------
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
{ {
memset(dst, 0, num_pix * sizeof(cover_type)); *dst++ = (cover_type)m_mask_function.calculate(mask);
return; mask += Step;
} }
memset(covers + count, 0, rest * sizeof(cover_type)); while(--num_pix);
} }
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
do
//--------------------------------------------------------------------
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
{ {
*covers = (cover_type)((cover_full + (*covers) * m_mask_function.calculate(mask)) >> cover_shift); const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
++covers; do
mask += m_rbuf->stride(); {
} while (--count); *dst = (cover_type)((cover_full + (*dst) *
} m_mask_function.calculate(mask)) >>
cover_shift);
++dst;
mask += Step;
}
while(--num_pix);
}
private:
alpha_mask_u8(const self_type&);
const self_type& operator=(const self_type&);
rendering_buffer* m_rbuf; //--------------------------------------------------------------------
MaskF m_mask_function; void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
};
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); const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
mask += Step; do
} while (--num_pix); {
} *dst++ = (cover_type)m_mask_function.calculate(mask);
mask += m_rbuf->stride();
}
while(--num_pix);
}
//--------------------------------------------------------------------
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const //--------------------------------------------------------------------
{ 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); const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
++dst; do
mask += Step; {
} while (--num_pix); *dst = (cover_type)((cover_full + (*dst) *
} m_mask_function.calculate(mask)) >>
cover_shift);
++dst;
mask += m_rbuf->stride();
}
while(--num_pix);
}
//-------------------------------------------------------------------- private:
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const amask_no_clip_u8(const self_type&);
{ const self_type& operator = (const self_type&);
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);
}
//-------------------------------------------------------------------- rendering_buffer* m_rbuf;
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const MaskF m_mask_function;
{ };
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: typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8
amask_no_clip_u8(const self_type&);
const self_type& operator=(const self_type&);
rendering_buffer* m_rbuf; typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r
MaskF m_mask_function; 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<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8 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<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r
typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g; //----amask_no_clip_rgb24g typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g
typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b; //----amask_no_clip_rgb24b 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<3, 2> amask_no_clip_bgr24r; //----amask_no_clip_bgr24r typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r
typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g; //----amask_no_clip_bgr24g typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g
typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b; //----amask_no_clip_bgr24b 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, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r 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_rgba32g; //----amask_no_clip_rgba32g typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g
typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b 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_rgba32a; //----amask_no_clip_rgba32a typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a
typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r 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_argb32g; //----amask_no_clip_argb32g typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g
typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b 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_argb32a; //----amask_no_clip_argb32a typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a
typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r 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<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g 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> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b 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, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a 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 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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -23,46 +23,52 @@
#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);
void init(double x, double y, double rx, double ry, double a1, double a2, bool ccw = true); //=====================================================================arc
//
// See Implementation agg_arc.cpp
//
class arc
{
public:
arc() : m_scale(1.0), m_initialized(false) {}
arc(double x, double y,
double rx, double ry,
double a1, double a2,
bool ccw=true);
void approximation_scale(double s); void init(double x, double y,
double approximation_scale() const { return m_scale; } double rx, double ry,
double a1, double a2,
bool ccw=true);
void rewind(unsigned); void approximation_scale(double s);
unsigned vertex(double* x, double* y); double approximation_scale() const { return m_scale; }
private: void rewind(unsigned);
void normalize(double a1, double a2, bool ccw); unsigned vertex(double* x, double* y);
double m_x; private:
double m_y; void normalize(double a1, double a2, bool ccw);
double m_rx;
double m_ry; double m_x;
double m_angle; double m_y;
double m_start; double m_rx;
double m_end; double m_ry;
double m_scale; double m_angle;
double m_da; double m_start;
bool m_ccw; double m_end;
bool m_initialized; double m_scale;
unsigned m_path_cmd; double m_da;
}; 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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -13,7 +13,7 @@
// http://www.antigrain.com // http://www.antigrain.com
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
// Simple arrowhead/arrowtail generator // Simple arrowhead/arrowtail generator
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
#ifndef AGG_ARROWHEAD_INCLUDED #ifndef AGG_ARROWHEAD_INCLUDED
@ -21,61 +21,62 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg { namespace agg
//===============================================================arrowhead
//
// See implementation agg_arrowhead.cpp
//
class arrowhead
{ {
public:
arrowhead();
void head(double d1, double d2, double d3, double d4) //===============================================================arrowhead
//
// See implementation agg_arrowhead.cpp
//
class arrowhead
{ {
m_head_d1 = d1; public:
m_head_d2 = d2; arrowhead();
m_head_d3 = d3;
m_head_d4 = d4;
m_head_flag = true;
}
void head() { m_head_flag = true; } void head(double d1, double d2, double d3, double d4)
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 tail(double d1, double d2, double d3, double d4) void head() { m_head_flag = true; }
{ 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() { m_tail_flag = true; } void tail(double d1, double d2, double d3, double d4)
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 rewind(unsigned path_id); void tail() { m_tail_flag = true; }
unsigned vertex(double* x, double* y); void no_tail() { m_tail_flag = false; }
private: void rewind(unsigned path_id);
double m_head_d1; unsigned vertex(double* x, double* y);
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;
};
} // namespace agg private:
double m_head_d1;
double m_head_d2;
double m_head_d3;
double m_head_d4;
double m_tail_d1;
double m_tail_d2;
double m_tail_d3;
double m_tail_d4;
bool m_head_flag;
bool m_tail_flag;
double m_coord[16];
unsigned m_cmd[8];
unsigned m_curr_id;
unsigned m_curr_coord;
};
}
#endif #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
{ {
// static T* allocate(unsigned num) { return static_cast<T*>(::operator new(sizeof(T)*num));} // The policy of all AGG containers and memory allocation strategy
// static void deallocate(T* ptr, unsigned) { ::operator delete(ptr) ;} // in general is that no allocated data requires explicit construction.
static T* allocate(unsigned num) { return new T[num]; } // It means that the allocator can be really simple; you can even
static void deallocate(T* ptr, unsigned) { delete[] ptr; } // replace new/delete to malloc/free. The constructors and destructors
}; // won't be called in this case, however everything will remain working.
// The second argument of deallocate() is the size of the allocated
// block. You can use this information if you wish.
//------------------------------------------------------------pod_allocator
template<class T> struct pod_allocator
{
//static T* allocate(unsigned num) { return 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> template<class T> struct obj_allocator
struct obj_allocator {
{ static T* allocate() { return new T; }
static T* allocate() { return new T; } static void deallocate(T* ptr) { delete ptr; }
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 @@ struct obj_allocator
//------------------------------------------------ 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,408 +107,372 @@ struct obj_allocator
#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_INT8 int8; //----int8
typedef AGG_INT16 int16; //----int16 typedef AGG_INT8U int8u; //----int8u
typedef AGG_INT16U int16u; //----int16u typedef AGG_INT16 int16; //----int16
typedef AGG_INT32 int32; //----int32 typedef AGG_INT16U int16u; //----int16u
typedef AGG_INT32U int32u; //----int32u typedef AGG_INT32 int32; //----int32
typedef AGG_INT64 int64; //----int64 typedef AGG_INT32U int32u; //----int32u
typedef AGG_INT64U int64u; //----int64u typedef AGG_INT64 int64; //----int64
typedef AGG_INT64U int64u; //----int64u
AGG_INLINE int iround(double v) AGG_INLINE int iround(double v)
{
return int((v < 0.0) ? v - 0.5 : v + 0.5);
}
AGG_INLINE int uround(double v)
{
return unsigned(v + 0.5);
}
AGG_INLINE unsigned ufloor(double v)
{
return unsigned(v);
}
AGG_INLINE unsigned uceil(double v)
{
return unsigned(std::ceil(v));
}
//---------------------------------------------------------------saturation
template<int Limit>
struct saturation
{
AGG_INLINE static int iround(double v)
{ {
if (v < double(-Limit)) return int((v < 0.0) ? v - 0.5 : v + 0.5);
return -Limit;
if (v > double(Limit))
return Limit;
return agg::iround(v);
} }
}; AGG_INLINE int uround(double 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 unsigned(v + 0.5);
return (q + (q >> Shift)) >> Shift;
} }
}; AGG_INLINE unsigned ufloor(double v)
//-------------------------------------------------------------------------
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_; return unsigned(v);
y1 = y1_; }
x2 = x2_; AGG_INLINE unsigned uceil(double v)
y2 = y2_; {
return unsigned(std::ceil(v));
} }
const self_type& normalize() //---------------------------------------------------------------saturation
template<int Limit> struct saturation
{ {
T t; AGG_INLINE static int iround(double v)
if (x1 > x2)
{ {
t = x1; if(v < double(-Limit)) return -Limit;
x1 = x2; if(v > double( Limit)) return Limit;
x2 = t; return agg::iround(v);
} }
if (y1 > y2) };
{
t = y1;
y1 = y2;
y2 = t;
}
return *this;
}
bool clip(const self_type& r) //------------------------------------------------------------------mul_one
template<unsigned Shift> struct mul_one
{ {
if (x2 > r.x2) AGG_INLINE static unsigned mul(unsigned a, unsigned b)
x2 = r.x2; {
if (y2 > r.y2) unsigned q = a * b + (1 << (Shift-1));
y2 = r.y2; return (q + (q >> Shift)) >> Shift;
if (x1 < r.x1) }
x1 = r.x1; };
if (y1 < r.y1)
y1 = r.y1; //-------------------------------------------------------------------------
return x1 <= x2 && y1 <= y2; 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;
} }
bool is_valid() const { return x1 <= x2 && y1 <= y2; } //------------------------------------------------------------------rad2deg
inline double rad2deg(double rad)
{
return rad * 180.0 / pi;
}
bool hit_test(T x, T y) const { return (x >= x1 && x <= x2 && y >= y1 && y <= y2); } //----------------------------------------------------------------rect_base
}; template<class T> struct rect_base
{
typedef T value_type;
typedef rect_base<T> self_type;
T x1, y1, x2, y2;
//-----------------------------------------------------intersect_rectangles rect_base() {}
template<class Rect> rect_base(T x1_, T y1_, T x2_, T y2_) :
inline Rect intersect_rectangles(const Rect& r1, const Rect& r2) x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
{
Rect r = r1; 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 | static_cast<path_commands_e>(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);
}
// 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 | static_cast<path_commands_e>(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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -13,7 +13,7 @@
// http://www.antigrain.com // http://www.antigrain.com
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e., // Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e.,
// 4, 7, 10, or 13 vertices. // 4, 7, 10, or 13 vertices.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -23,127 +23,137 @@
#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:
//-------------------------------------------------------------------- //-----------------------------------------------------------------------
bezier_arc() void arc_to_bezier(double cx, double cy, double rx, double ry,
: m_vertex(26) double start_angle, double sweep_angle,
, m_num_vertices(0) double* curve);
, m_cmd(path_cmd_line_to)
{}
bezier_arc(double x, double y, double rx, double ry, double start_angle, double sweep_angle) //==============================================================bezier_arc
//
// See implemantaion agg_bezier_arc.cpp
//
class bezier_arc
{ {
init(x, y, rx, ry, start_angle, sweep_angle); public:
} //--------------------------------------------------------------------
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, double rx, double ry, double start_angle, double sweep_angle); void init(double x, double y,
double rx, double ry,
double start_angle,
double sweep_angle);
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void rewind(unsigned) { m_vertex = 0; } void rewind(unsigned)
{
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
{ {
if (m_vertex >= m_num_vertices) public:
return path_cmd_stop; //--------------------------------------------------------------------
*x = m_vertices[m_vertex]; bezier_arc_svg() : m_arc(), m_radii_ok(false) {}
*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 bezier_arc_svg(double x1, double y1,
// number of vertices. That is, for 1 vertex it returns 2. double rx, double ry,
//-------------------------------------------------------------------- double angle,
unsigned num_vertices() const { return m_num_vertices; } bool large_arc_flag,
const double* vertices() const { return m_vertices; } bool sweep_flag,
double* vertices() { return m_vertices; } double x2, double y2) :
m_arc(), m_radii_ok(false)
{
init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2);
}
private: //--------------------------------------------------------------------
unsigned m_vertex; void init(double x1, double y1,
unsigned m_num_vertices; double rx, double ry,
double m_vertices[26]; double angle,
unsigned m_cmd; bool large_arc_flag,
}; bool sweep_flag,
double x2, double y2);
//==========================================================bezier_arc_svg //--------------------------------------------------------------------
// Compute an SVG-style bezier arc. bool radii_ok() const { return m_radii_ok; }
//
// Computes an elliptical arc from (x1, y1) to (x2, y2). The size and
// orientation of the ellipse are defined by two radii (rx, ry)
// and an x-axis-rotation, which indicates how the ellipse as a whole
// is rotated relative to the current coordinate system. The center
// (cx, cy) of the ellipse is calculated automatically to satisfy the
// constraints imposed by the other parameters.
// large-arc-flag and sweep-flag contribute to the automatic calculations
// and help determine how the arc is drawn.
class bezier_arc_svg
{
public:
//--------------------------------------------------------------------
bezier_arc_svg()
: m_arc()
, m_radii_ok(false)
{}
bezier_arc_svg(double x1, //--------------------------------------------------------------------
double y1, void rewind(unsigned)
double rx, {
double ry, m_arc.rewind(0);
double angle, }
bool large_arc_flag,
bool sweep_flag,
double x2,
double y2)
: m_arc()
, m_radii_ok(false)
{
init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void init(double x1, unsigned vertex(double* x, double* y)
double y1, {
double rx, return m_arc.vertex(x, y);
double ry, }
double angle,
bool large_arc_flag,
bool sweep_flag,
double x2,
double y2);
//-------------------------------------------------------------------- // Supplemantary functions. num_vertices() actually returns doubled
bool radii_ok() const { return m_radii_ok; } // 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:
void rewind(unsigned) { m_arc.rewind(0); } bezier_arc m_arc;
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -18,33 +18,37 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg { namespace agg
class bitset_iterator
{ {
public:
bitset_iterator(const int8u* bits, unsigned offset = 0) class bitset_iterator
: m_bits(bits + (offset >> 3))
, m_mask(0x80 >> (offset & 7))
{}
void operator++()
{ {
m_mask >>= 1; public:
if (m_mask == 0) bitset_iterator(const int8u* bits, unsigned offset = 0) :
m_bits(bits + (offset >> 3)),
m_mask(0x80 >> (offset & 7))
{}
void operator ++ ()
{ {
++m_bits; m_mask >>= 1;
m_mask = 0x80; if(m_mask == 0)
{
++m_bits;
m_mask = 0x80;
}
} }
}
unsigned bit() const { return (*m_bits) & m_mask; } unsigned bit() const
{
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -21,38 +21,76 @@
#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;
*x1 = CoordT(1); //-----------------------------------------------------------bounding_rect
*y1 = CoordT(1); template<class VertexSource, class GetId, class CoordT>
*x2 = CoordT(0); bool bounding_rect(VertexSource& vs, GetId& gi,
*y2 = CoordT(0); unsigned start, unsigned num,
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
for (i = 0; i < num; i++)
{ {
vs.rewind(gi[start + i]); unsigned i;
unsigned cmd; double x;
while (!is_stop(cmd = vs.vertex(&x, &y))) double y;
bool first = true;
*x1 = CoordT(1);
*y1 = CoordT(1);
*x2 = CoordT(0);
*y2 = CoordT(0);
for(i = 0; i < num; i++)
{ {
if (is_vertex(cmd)) vs.rewind(gi[start + i]);
unsigned cmd;
while(!is_stop(cmd = vs.vertex(&x, &y)))
{ {
if (first) if(is_vertex(cmd))
{
if(first)
{
*x1 = CoordT(x);
*y1 = CoordT(y);
*x2 = CoordT(x);
*y2 = CoordT(y);
first = false;
}
else
{
if(CoordT(x) < *x1) *x1 = CoordT(x);
if(CoordT(y) < *y1) *y1 = CoordT(y);
if(CoordT(x) > *x2) *x2 = CoordT(x);
if(CoordT(y) > *y2) *y2 = CoordT(y);
}
}
}
}
return *x1 <= *x2 && *y1 <= *y2;
}
//-----------------------------------------------------bounding_rect_single
template<class VertexSource, class CoordT>
bool bounding_rect_single(VertexSource& vs, unsigned path_id,
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
{
double x;
double y;
bool first = true;
*x1 = CoordT(1);
*y1 = CoordT(1);
*x2 = CoordT(0);
*y2 = CoordT(0);
vs.rewind(path_id);
unsigned cmd;
while(!is_stop(cmd = vs.vertex(&x, &y)))
{
if(is_vertex(cmd))
{
if(first)
{ {
*x1 = CoordT(x); *x1 = CoordT(x);
*y1 = CoordT(y); *y1 = CoordT(y);
@ -62,64 +100,17 @@ bool bounding_rect(VertexSource& vs,
} }
else else
{ {
if (CoordT(x) < *x1) if(CoordT(x) < *x1) *x1 = CoordT(x);
*x1 = CoordT(x); if(CoordT(y) < *y1) *y1 = CoordT(y);
if (CoordT(y) < *y1) if(CoordT(x) > *x2) *x2 = CoordT(x);
*y1 = CoordT(y); if(CoordT(y) > *y2) *y2 = 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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -22,53 +22,55 @@
#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
{ {
public: //----------------------------------------------------------------bspline
bspline(); // A very simple class of Bi-cubic Spline interpolation.
bspline(int num); // First call init(num, x[], y[]) where num - number of source points,
bspline(int num, const double* x, const double* y); // x, y - arrays of X and Y values respectively. Here Y must be a function
// of X. It means that all the X-coordinates must be arranged in the ascending
// order.
// Then call get(x) that calculates a value Y for the respective X.
// The class supports extrapolation, i.e. you can call get(x) where x is
// outside the given with init() X-range. Extrapolation is a simple linear
// function.
//
// See Implementation agg_bspline.cpp
//------------------------------------------------------------------------
class bspline
{
public:
bspline();
bspline(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:
bspline(const bspline&);
const bspline& operator = (const bspline&);
private: static void bsearch(int n, const double *x, double x0, int *i);
bspline(const bspline&); double extrapolation_left(double x) const;
const bspline& operator=(const bspline&); double extrapolation_right(double x) const;
double interpolation(double x, int i) const;
static void bsearch(int n, const double* x, double x0, int* i); int m_max;
double extrapolation_left(double x) const; int m_num;
double extrapolation_right(double x) const; double* m_x;
double interpolation(double x, int i) const; double* m_y;
pod_array<double> m_am;
mutable int m_last_idx;
};
int m_max;
int m_num;
double* m_x;
double* m_y;
pod_array<double> m_am;
mutable int m_last_idx;
};
} // namespace agg }
#endif #endif

View file

@ -21,296 +21,313 @@
#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 //------------------------------------------------------------------------
template<class T> enum clipping_flags_e
inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box)
{
return (x > clip_box.x2) | ((x < clip_box.x1) << 2);
}
//--------------------------------------------------------clipping_flags_y
template<class T>
inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box)
{
return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3);
}
//-------------------------------------------------------clip_liang_barsky
template<class T>
inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, const rect_base<T>& clip_box, T* x, T* y)
{
const double nearzero = 1e-30;
double deltax = x2 - x1;
double deltay = y2 - y1;
double xin;
double xout;
double yin;
double yout;
double tinx;
double tiny;
double toutx;
double touty;
double tin1;
double tin2;
double tout1;
unsigned np = 0;
if (deltax == 0.0)
{ {
// bump off of the vertical clipping_flags_x1_clipped = 4,
deltax = (x1 > clip_box.x1) ? -nearzero : nearzero; 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);
} }
if (deltay == 0.0) //--------------------------------------------------------clipping_flags_x
template<class T>
inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box)
{ {
// bump off of the horizontal return (x > clip_box.x2) | ((x < clip_box.x1) << 2);
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)
{ {
// points to right return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3);
xin = clip_box.x1;
xout = clip_box.x2;
}
else
{
xin = clip_box.x2;
xout = clip_box.x1;
} }
if (deltay > 0.0)
{
// points up
yin = clip_box.y1;
yout = clip_box.y2;
}
else
{
yin = clip_box.y2;
yout = clip_box.y1;
}
tinx = (xin - x1) / deltax; //-------------------------------------------------------clip_liang_barsky
tiny = (yin - y1) / deltay; 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;
if (tinx < tiny) double deltax = x2 - x1;
{ double deltay = y2 - y1;
// hits x first double xin;
tin1 = tinx; double xout;
tin2 = tiny; double yin;
} double yout;
else double tinx;
{ double tiny;
// hits y first double toutx;
tin1 = tiny; double touty;
tin2 = tinx; double tin1;
} double tin2;
double tout1;
unsigned np = 0;
if (tin1 <= 1.0) if(deltax == 0.0)
{
if (0.0 < tin1)
{ {
*x++ = (T)xin; // bump off of the vertical
*y++ = (T)yin; deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
++np;
} }
if (tin2 <= 1.0) if(deltay == 0.0)
{ {
toutx = (xout - x1) / deltax; // bump off of the horizontal
touty = (yout - y1) / deltay; deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
}
tout1 = (toutx < touty) ? toutx : touty; if(deltax > 0.0)
{
// points to right
xin = clip_box.x1;
xout = clip_box.x2;
}
else
{
xin = clip_box.x2;
xout = clip_box.x1;
}
if (tin2 > 0.0 || tout1 > 0.0) if(deltay > 0.0)
{
// points up
yin = clip_box.y1;
yout = clip_box.y2;
}
else
{
yin = clip_box.y2;
yout = clip_box.y1;
}
tinx = (xin - x1) / deltax;
tiny = (yin - y1) / deltay;
if (tinx < tiny)
{
// hits x first
tin1 = tinx;
tin2 = tiny;
}
else
{
// hits y first
tin1 = tiny;
tin2 = tinx;
}
if(tin1 <= 1.0)
{
if(0.0 < tin1)
{ {
if (tin2 <= tout1) *x++ = (T)xin;
*y++ = (T)yin;
++np;
}
if(tin2 <= 1.0)
{
toutx = (xout - x1) / deltax;
touty = (yout - y1) / deltay;
tout1 = (toutx < touty) ? toutx : touty;
if(tin2 > 0.0 || tout1 > 0.0)
{ {
if (tin2 > 0.0) if(tin2 <= tout1)
{ {
if (tinx > tiny) if(tin2 > 0.0)
{ {
*x++ = (T)xin; if(tinx > tiny)
*y++ = (T)(y1 + tinx * deltay); {
*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 else
{ {
*x++ = (T)(x1 + tiny * deltax); *x++ = x2;
*y++ = y2;
}
++np;
}
else
{
if(tinx > tiny)
{
*x++ = (T)xin;
*y++ = (T)yout;
}
else
{
*x++ = (T)xout;
*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,19 +31,21 @@
#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;
@ -103,22 +105,17 @@ struct gray8T
gray8T() {} gray8T() {}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray8T(unsigned v_, unsigned a_ = base_mask) gray8T(unsigned v_, unsigned a_=base_mask) :
: v(int8u(v_)) v(int8u(v_)), a(int8u(a_)) {}
, a(int8u(a_))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray8T(const self_type& c, unsigned a_) gray8T(const self_type& c, unsigned a_) :
: v(c.v) v(c.v), a(value_type(a_)) {}
, 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>
@ -150,18 +147,36 @@ struct gray8T
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba8 make_rgba8(const linear&) const { return rgba8(v, v, v, a); } rgba8 make_rgba8(const linear&) const
{
return rgba8(v, v, v, a);
}
rgba8 make_rgba8(const sRGB&) const { return convert_from_sRGB<srgba8>(); } rgba8 make_rgba8(const sRGB&) const
{
return convert_from_sRGB<srgba8>();
}
operator rgba8() const { return make_rgba8(Colorspace()); } operator rgba8() const
{
return make_rgba8(Colorspace());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
srgba8 make_srgba8(const linear&) const { return convert_to_sRGB<rgba8>(); } srgba8 make_srgba8(const linear&) const
{
return convert_to_sRGB<rgba8>();
}
srgba8 make_srgba8(const sRGB&) const { return srgba8(v, v, v, a); } srgba8 make_srgba8(const sRGB&) const
{
return srgba8(v, v, v, a);
}
operator srgba8() const { return make_rgba8(Colorspace()); } operator srgba8() const
{
return make_rgba8(Colorspace());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba16 make_rgba16(const linear&) const rgba16 make_rgba16(const linear&) const
@ -170,9 +185,15 @@ struct gray8T
return rgba16(rgb, rgb, rgb, (a << 8) | a); return rgba16(rgb, rgb, rgb, (a << 8) | a);
} }
rgba16 make_rgba16(const sRGB&) const { return convert_from_sRGB<rgba16>(); } rgba16 make_rgba16(const sRGB&) const
{
return convert_from_sRGB<rgba16>();
}
operator rgba16() const { return make_rgba16(Colorspace()); } operator rgba16() const
{
return make_rgba16(Colorspace());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba32 make_rgba32(const linear&) const rgba32 make_rgba32(const linear&) const
@ -181,27 +202,51 @@ struct gray8T
return rgba32(v32, v32, v32, a / 255.0); return rgba32(v32, v32, v32, a / 255.0);
} }
rgba32 make_rgba32(const sRGB&) const { return convert_from_sRGB<rgba32>(); } rgba32 make_rgba32(const sRGB&) const
{
return convert_from_sRGB<rgba32>();
}
operator rgba32() const { return make_rgba32(Colorspace()); } operator rgba32() const
{
return make_rgba32(Colorspace());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a) { return double(a) / base_mask; } static AGG_INLINE double to_double(value_type a)
{
return double(a) / base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a) { return value_type(uround(a * base_mask)); } static AGG_INLINE value_type from_double(double a)
{
return value_type(uround(a * base_mask));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type empty_value() { return 0; } static AGG_INLINE value_type empty_value()
{
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type full_value() { return base_mask; } static AGG_INLINE value_type full_value()
{
return base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const { return a == 0; } AGG_INLINE bool is_transparent() const
{
return a == 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const { return a == base_mask; } AGG_INLINE bool is_opaque() const
{
return a == base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Fixed-point multiply, exact over int8u. // Fixed-point multiply, exact over int8u.
@ -222,8 +267,7 @@ struct gray8T
{ {
return base_mask; return base_mask;
} }
else else return value_type((a * base_mask + (b >> 1)) / b);
return value_type((a * base_mask + (b >> 1)) / b);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -243,14 +287,23 @@ 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) { return multiply(a, b); } static AGG_INLINE value_type mult_cover(value_type a, value_type b)
{
return multiply(a, b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return multiply(b, a); } static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
{
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) { return p + q - multiply(p, a); } static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a. // Interpolate p to q by a.
@ -277,27 +330,25 @@ struct gray8T
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& opacity(double a_) self_type& opacity(double a_)
{ {
if (a_ < 0) if (a_ < 0) a = 0;
a = 0; else if (a_ > 1) a = 1;
else if (a_ > 1) else a = (value_type)uround(a_ * double(base_mask));
a = 1;
else
a = (value_type)uround(a_ * double(base_mask));
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
double opacity() const { return double(a) / double(base_mask); } double opacity() const
{
return double(a) / double(base_mask);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& premultiply() self_type& premultiply()
{ {
if (a < base_mask) if (a < base_mask)
{ {
if (a == 0) if (a == 0) v = 0;
v = 0; else v = multiply(v, a);
else
v = multiply(v, a);
} }
return *this; return *this;
} }
@ -357,22 +408,24 @@ 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;
@ -383,7 +436,8 @@ struct gray16
static value_type luminance(const rgba& c) static value_type luminance(const rgba& c)
{ {
// Calculate grayscale value as per ITU-R BT.709. // Calculate grayscale value as per ITU-R BT.709.
return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * static_cast<double>(base_mask))); return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b)
* static_cast<double>(base_mask)));
} }
static value_type luminance(const rgba16& c) static value_type luminance(const rgba16& c)
@ -392,65 +446,67 @@ 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) { return luminance(rgba16(c)); } static value_type luminance(const rgba8& c)
{
return luminance(rgba16(c));
}
static value_type luminance(const srgba8& c) { return luminance(rgba16(c)); } static value_type luminance(const srgba8& c)
{
return luminance(rgba16(c));
}
static value_type luminance(const rgba32& c) { return luminance(rgba(c)); } static value_type luminance(const rgba32& c)
{
return luminance(rgba(c));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray16() {} gray16() {}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray16(unsigned v_, unsigned a_ = base_mask) gray16(unsigned v_, unsigned a_ = base_mask) :
: v(int16u(v_)) v(int16u(v_)), a(int16u(a_)) {}
, a(int16u(a_))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray16(const self_type& c, unsigned a_) gray16(const self_type& c, unsigned a_) :
: v(c.v) v(c.v), a(value_type(a_)) {}
, 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 { return rgba8(v >> 8, v >> 8, v >> 8, a >> 8); } operator rgba8() const
{
return rgba8(v >> 8, v >> 8, v >> 8, a >> 8);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator srgba8() const operator srgba8() const
@ -460,19 +516,30 @@ struct gray16
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba16() const { return rgba16(v, v, v, a); } operator rgba16() const
{
return rgba16(v, v, v, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator gray8() const { return gray8(v >> 8, a >> 8); } operator gray8() const
{
return gray8(v >> 8, a >> 8);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator sgray8() const operator sgray8() const
{ {
return sgray8(sRGB_conv<value_type>::rgb_to_sRGB(v), sRGB_conv<value_type>::alpha_to_sRGB(a)); return sgray8(
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) { return static_cast<double>(a) / static_cast<double>(base_mask); } static AGG_INLINE double to_double(value_type a)
{
return static_cast<double>(a) / static_cast<double>(base_mask);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a) static AGG_INLINE value_type from_double(double a)
@ -481,16 +548,28 @@ struct gray16
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type empty_value() { return 0; } static AGG_INLINE value_type empty_value()
{
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type full_value() { return base_mask; } static AGG_INLINE value_type full_value()
{
return base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const { return a == 0; } AGG_INLINE bool is_transparent() const
{
return a == 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const { return a == base_mask; } AGG_INLINE bool is_opaque() const
{
return a == base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Fixed-point multiply, exact over int16u. // Fixed-point multiply, exact over int16u.
@ -511,8 +590,7 @@ struct gray16
{ {
return base_mask; return base_mask;
} }
else else return value_type((a * base_mask + (b >> 1)) / b);
return value_type((a * base_mask + (b >> 1)) / b);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -532,14 +610,23 @@ 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) { return multiply(a, b << 8 | b); } static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
{
return multiply(a, b << 8 | b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return mult_cover(b, a) >> 8; } static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
{
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) { return p + q - multiply(p, a); } static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a. // Interpolate p to q by a.
@ -566,27 +653,26 @@ struct gray16
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& opacity(double a_) self_type& opacity(double a_)
{ {
if (a_ < 0) if (a_ < 0) a = 0;
a = 0; else if(a_ > 1) a = 1;
else if (a_ > 1) else a = (value_type)uround(a_ * double(base_mask));
a = 1;
else
a = (value_type)uround(a_ * double(base_mask));
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
double opacity() const { return double(a) / double(base_mask); } double opacity() const
{
return double(a) / double(base_mask);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& premultiply() self_type& premultiply()
{ {
if (a < base_mask) if (a < base_mask)
{ {
if (a == 0) if(a == 0) v = 0;
v = 0; else v = multiply(v, a);
else
v = multiply(v, a);
} }
return *this; return *this;
} }
@ -646,9 +732,10 @@ 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
{ {
@ -660,10 +747,11 @@ 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.
@ -672,92 +760,103 @@ 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) { return luminance(c.r, c.g, c.b); } static value_type luminance(const rgba& c)
{
return luminance(c.r, c.g, c.b);
}
static value_type luminance(const rgba32& c) { return luminance(c.r, c.g, c.b); } static value_type luminance(const rgba32& c)
{
return luminance(c.r, c.g, c.b);
}
static value_type luminance(const rgba8& c) { return luminance(c.r / 255.0, c.g / 255.0, c.g / 255.0); } static value_type luminance(const rgba8& c)
{
return luminance(c.r / 255.0, c.g / 255.0, c.g / 255.0);
}
static value_type luminance(const rgba16& c) { return luminance(c.r / 65535.0, c.g / 65535.0, c.g / 65535.0); } static value_type luminance(const rgba16& c)
{
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_) v(v_), a(a_) {}
, a(a_)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
gray32(const self_type& c, value_type a_) gray32(const self_type& c, value_type a_) :
: v(c.v) v(c.v), a(a_) {}
, 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 { return rgba(v, v, v, a); } operator rgba() const
{
return rgba(v, v, v, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator gray8() const { return gray8(uround(v * 255.0), uround(a * 255.0)); } operator gray8() const
{
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(sRGB_conv<value_type>::rgb_to_sRGB(v), sRGB_conv<value_type>::alpha_to_sRGB(a)); return sgray8(
sRGB_conv<value_type>::rgb_to_sRGB(v),
sRGB_conv<value_type>::alpha_to_sRGB(a));
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator gray16() const { return gray16(uround(v * 65535.0), uround(a * 65535.0)); } operator gray16() const
{
return gray16(uround(v * 65535.0), uround(a * 65535.0));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba8() const operator rgba8() const
@ -781,31 +880,58 @@ struct gray32
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a) { return a; } static AGG_INLINE double to_double(value_type a)
{
return a;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a) { return value_type(a); } static AGG_INLINE value_type from_double(double a)
{
return value_type(a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type empty_value() { return 0; } static AGG_INLINE value_type empty_value()
{
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type full_value() { return 1; } static AGG_INLINE value_type full_value()
{
return 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const { return a <= 0; } AGG_INLINE bool is_transparent() const
{
return a <= 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const { return a >= 1; } AGG_INLINE bool is_opaque() const
{
return a >= 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type invert(value_type x) { return 1 - x; } static AGG_INLINE value_type invert(value_type x)
{
return 1 - x;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type multiply(value_type a, value_type b) { return value_type(a * b); } static AGG_INLINE value_type multiply(value_type a, value_type b)
{
return value_type(a * b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type demultiply(value_type a, value_type b) { return (b == 0) ? 0 : value_type(a / b); } static AGG_INLINE value_type demultiply(value_type a, value_type b)
{
return (b == 0) ? 0 : value_type(a / b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
template<typename T> template<typename T>
@ -828,7 +954,10 @@ struct gray32
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return cover_type(uround(a * b)); } static AGG_INLINE cover_type scale_cover(cover_type a, value_type 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.
@ -865,47 +994,49 @@ struct gray32
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& opacity(double a_) self_type& opacity(double a_)
{ {
if (a_ < 0) if (a_ < 0) a = 0;
a = 0; else if (a_ > 1) a = 1;
else if (a_ > 1) else a = value_type(a_);
a = 1;
else
a = value_type(a_);
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
double opacity() const { return a; } double opacity() const
{
return a;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& premultiply() self_type& premultiply()
{ {
if (a < 0) if (a < 0) v = 0;
v = 0; else if(a < 1) v *= a;
else if (a < 1)
v *= a;
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& demultiply() self_type& demultiply()
{ {
if (a < 0) if (a < 0) v = 0;
v = 0; else if (a < 1) v /= a;
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(value_type(v + (c.v - v) * k), value_type(a + (c.a - a) * k)); return self_type(
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,39 +28,20 @@
#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 struct order_rgb { enum rgb_e { R=0, G=1, B=2, rgb_tag, hasAlpha=false }; }; //----order_rgb
{ struct order_bgr { enum bgr_e { B=0, G=1, R=2, rgb_tag, hasAlpha=false }; }; //----order_bgr
enum rgb_e { R = 0, G = 1, B = 2, rgb_tag, hasAlpha = false }; struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag, hasAlpha=true }; }; //----order_rgba
}; //----order_rgb struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag, hasAlpha=true }; }; //----order_argb
struct order_bgr 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
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
@ -76,20 +57,11 @@ 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_) r(r_), g(g_), b(b_), a(a_) {}
, g(g_)
, b(b_)
, a(a_)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba(const rgba& c, double a_) rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {}
: r(c.r)
, g(c.g)
, b(c.b)
, a(a_)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba& clear() rgba& clear()
@ -108,17 +80,17 @@ struct rgba
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba& opacity(double a_) rgba& opacity(double a_)
{ {
if (a_ < 0) if (a_ < 0) a = 0;
a = 0; else if (a_ > 1) a = 1;
else if (a_ > 1) else a = a_;
a = 1;
else
a = a_;
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
double opacity() const { return a; } double opacity() const
{
return a;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba& premultiply() rgba& premultiply()
@ -142,7 +114,7 @@ struct rgba
r *= a_; r *= a_;
g *= a_; g *= a_;
b *= a_; b *= a_;
a = a_; a = a_;
} }
return *this; return *this;
} }
@ -164,6 +136,7 @@ struct rgba
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba gradient(rgba c, double k) const rgba gradient(rgba c, double k) const
{ {
@ -194,13 +167,17 @@ 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) { *this = from_wavelength(wavelen, gamma); } explicit rgba(double wavelen, double gamma=1.0)
{
*this = from_wavelength(wavelen, gamma);
}
}; };
inline rgba operator+(const rgba& a, const rgba& b) inline rgba operator+(const rgba& a, const rgba& b)
@ -249,10 +226,8 @@ inline rgba rgba::from_wavelength(double wl, double gamma)
} }
double s = 1.0; double s = 1.0;
if (wl > 700.0) if (wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0);
s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0); else if (wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0);
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);
@ -265,21 +240,24 @@ 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;
@ -339,23 +317,21 @@ 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) { convert(*this, c); } rgba8T(const rgba& c)
{
convert(*this, c);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba8T(const self_type& c, unsigned a_) rgba8T(const self_type& c, unsigned a_) :
: r(c.r) r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
, g(c.g)
, b(c.b)
, a(value_type(a_))
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
template<class T> template<class T>
@ -373,25 +349,46 @@ struct rgba8T
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a) { return double(a) / base_mask; } static AGG_INLINE double to_double(value_type a)
{
return double(a) / base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a) { return value_type(uround(a * base_mask)); } static AGG_INLINE value_type from_double(double a)
{
return value_type(uround(a * base_mask));
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type empty_value() { return 0; } static AGG_INLINE value_type empty_value()
{
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type full_value() { return base_mask; } static AGG_INLINE value_type full_value()
{
return base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const { return a == 0; } AGG_INLINE bool is_transparent() const
{
return a == 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const { return a == base_mask; } AGG_INLINE bool is_opaque() const
{
return a == base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type invert(value_type x) { return base_mask - x; } static AGG_INLINE value_type invert(value_type x)
{
return base_mask - x;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Fixed-point multiply, exact over int8u. // Fixed-point multiply, exact over int8u.
@ -412,8 +409,7 @@ struct rgba8T
{ {
return base_mask; return base_mask;
} }
else else return value_type((a * base_mask + (b >> 1)) / b);
return value_type((a * base_mask + (b >> 1)) / b);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -433,14 +429,23 @@ 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) { return multiply(a, b); } static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
{
return multiply(a, b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return multiply(b, a); } static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
{
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) { return p + q - multiply(p, a); } static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a. // Interpolate p to q by a.
@ -467,17 +472,17 @@ struct rgba8T
//-------------------------------------------------------------------- //--------------------------------------------------------------------
self_type& opacity(double a_) self_type& opacity(double a_)
{ {
if (a_ < 0) if (a_ < 0) a = 0;
a = 0; else if (a_ > 1) a = 1;
else if (a_ > 1) else a = (value_type)uround(a_ * double(base_mask));
a = 1;
else
a = (value_type)uround(a_ * double(base_mask));
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
double opacity() const { return double(a) / double(base_mask); } double opacity() const
{
return double(a) / double(base_mask);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE self_type& premultiply() AGG_INLINE self_type& premultiply()
@ -599,7 +604,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)
@ -612,9 +617,10 @@ 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, unsigned a = rgba8::base_mask) inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b,
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)
{ {
@ -622,7 +628,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)
{ {
@ -630,9 +636,12 @@ 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)
{ {
@ -665,16 +674,19 @@ 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;
@ -688,63 +700,69 @@ 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) r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
, 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 { return rgba(r / 65535.0, g / 65535.0, b / 65535.0, a / 65535.0); } operator rgba() const
{
return rgba(
r / 65535.0,
g / 65535.0,
b / 65535.0,
a / 65535.0);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba8() const { return rgba8(r >> 8, g >> 8, b >> 8, a >> 8); } operator rgba8() const
{
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(sRGB_conv<value_type>::rgb_to_sRGB(r), return srgba8(
sRGB_conv<value_type>::rgb_to_sRGB(g), sRGB_conv<value_type>::rgb_to_sRGB(r),
sRGB_conv<value_type>::rgb_to_sRGB(b), sRGB_conv<value_type>::rgb_to_sRGB(g),
sRGB_conv<value_type>::alpha_to_sRGB(a)); sRGB_conv<value_type>::rgb_to_sRGB(b),
sRGB_conv<value_type>::alpha_to_sRGB(a));
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE double to_double(value_type a) { return static_cast<double>(a) / static_cast<double>(base_mask); } static AGG_INLINE double to_double(value_type a)
{
return static_cast<double>(a) / static_cast<double>(base_mask);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a) static AGG_INLINE value_type from_double(double a)
@ -753,19 +771,34 @@ struct rgba16
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type empty_value() { return 0; } static AGG_INLINE value_type empty_value()
{
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type full_value() { return base_mask; } static AGG_INLINE value_type full_value()
{
return base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const { return a == 0; } AGG_INLINE bool is_transparent() const
{
return a == 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const { return a == base_mask; } AGG_INLINE bool is_opaque() const
{
return a == base_mask;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type invert(value_type x) { return base_mask - x; } static AGG_INLINE value_type invert(value_type x)
{
return base_mask - x;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Fixed-point multiply, exact over int16u. // Fixed-point multiply, exact over int16u.
@ -786,8 +819,7 @@ struct rgba16
{ {
return base_mask; return base_mask;
} }
else else return value_type((a * base_mask + (b >> 1)) / b);
return value_type((a * base_mask + (b >> 1)) / b);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -807,14 +839,23 @@ 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) { return multiply(a, (b << 8) | b); } static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
{
return multiply(a, (b << 8) | b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return multiply((a << 8) | a, b) >> 8; } static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
{
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) { return p + q - multiply(p, a); } static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Interpolate p to q by a. // Interpolate p to q by a.
@ -841,16 +882,17 @@ struct rgba16
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE self_type& opacity(double a_) AGG_INLINE self_type& opacity(double a_)
{ {
if (a_ < 0) if (a_ < 0) a = 0;
a = 0; if (a_ > 1) a = 1;
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 { return double(a) / double(base_mask); } double opacity() const
{
return double(a) / double(base_mask);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE self_type& premultiply() AGG_INLINE self_type& premultiply()
@ -972,7 +1014,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)
@ -981,6 +1023,7 @@ 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)
@ -1012,100 +1055,127 @@ 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_) r(r_), g(g_), b(b_), a(a_) {}
, g(g_)
, b(b_)
, a(a_)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba32(const self_type& c, float a_) rgba32(const self_type& c, float a_) :
: r(c.r) r(c.r), g(c.g), b(c.b), a(a_) {}
, g(c.g)
, b(c.b)
, a(a_)
{}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
rgba32(const rgba& c) rgba32(const rgba& c) :
: r(value_type(c.r)) r(value_type(c.r)), g(value_type(c.g)), b(value_type(c.b)), a(value_type(c.a)) {}
, 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 { return rgba(r, g, b, a); } operator rgba() const
{
return rgba(r, g, b, a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba8() const { return rgba8(uround(r * 255.0), uround(g * 255.0), uround(b * 255.0), uround(a * 255.0)); } operator rgba8() const
{
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(sRGB_conv<value_type>::rgb_to_sRGB(r), return srgba8(
sRGB_conv<value_type>::rgb_to_sRGB(g), sRGB_conv<value_type>::rgb_to_sRGB(r),
sRGB_conv<value_type>::rgb_to_sRGB(b), sRGB_conv<value_type>::rgb_to_sRGB(g),
sRGB_conv<value_type>::alpha_to_sRGB(a)); sRGB_conv<value_type>::rgb_to_sRGB(b),
sRGB_conv<value_type>::alpha_to_sRGB(a));
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
operator rgba16() const operator rgba16() const
{ {
return rgba8(uround(r * 65535.0), uround(g * 65535.0), uround(b * 65535.0), uround(a * 65535.0)); return rgba8(
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) { return a; } static AGG_INLINE double to_double(value_type a)
{
return a;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type from_double(double a) { return value_type(a); } static AGG_INLINE value_type from_double(double a)
{
return value_type(a);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type empty_value() { return 0; } static AGG_INLINE value_type empty_value()
{
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type full_value() { return 1; } static AGG_INLINE value_type full_value()
{
return 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_transparent() const { return a <= 0; } AGG_INLINE bool is_transparent() const
{
return a <= 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE bool is_opaque() const { return a >= 1; } AGG_INLINE bool is_opaque() const
{
return a >= 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type invert(value_type x) { return 1 - x; } static AGG_INLINE value_type invert(value_type x)
{
return 1 - x;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type multiply(value_type a, value_type b) { return value_type(a * b); } static AGG_INLINE value_type multiply(value_type a, value_type b)
{
return value_type(a * b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE value_type demultiply(value_type a, value_type b) { return (b == 0) ? 0 : value_type(a / b); } static AGG_INLINE value_type demultiply(value_type a, value_type b)
{
return (b == 0) ? 0 : value_type(a / b);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
template<typename T> template<typename T>
@ -1128,7 +1198,10 @@ struct rgba32
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) { return cover_type(uround(a * b)); } static AGG_INLINE cover_type scale_cover(cover_type a, value_type 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.
@ -1165,17 +1238,17 @@ struct rgba32
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE self_type& opacity(double a_) AGG_INLINE self_type& opacity(double a_)
{ {
if (a_ < 0) if (a_ < 0) a = 0;
a = 0; else if (a_ > 1) a = 1;
else if (a_ > 1) else a = value_type(a_);
a = 1;
else
a = value_type(a_);
return *this; return *this;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
double opacity() const { return a; } double opacity() const
{
return a;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE self_type& premultiply() AGG_INLINE self_type& premultiply()
@ -1251,14 +1324,10 @@ 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) if (a > 1) a = 1;
a = 1; if (r > a) r = a;
if (r > a) if (g > a) g = a;
r = a; if (b > a) b = a;
if (g > a)
g = a;
if (b > a)
b = a;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -1280,7 +1349,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)
@ -1288,6 +1357,8 @@ struct rgba32
return self_type(rgba::from_wavelength(wl, gamma)); return self_type(rgba::from_wavelength(wl, gamma));
} }
}; };
} // namespace agg }
#endif #endif

View file

@ -5,7 +5,7 @@
//--------------------------------------- //---------------------------------------
// 1. Default basic types such as: // 1. Default basic types such as:
// //
// AGG_INT8 // AGG_INT8
// AGG_INT8U // AGG_INT8U
// AGG_INT16 // AGG_INT16
@ -15,7 +15,7 @@
// AGG_INT64 // AGG_INT64
// AGG_INT64U // AGG_INT64U
// //
// Just replace this file with new defines if necessary. // Just replace this file with new defines if necessary.
// For example, if your compiler doesn't have a 64 bit integer type // For example, if your compiler doesn't have a 64 bit integer type
// you can still use AGG if you define the follows: // you can still use AGG if you define the follows:
// //
@ -23,21 +23,22 @@
// #define AGG_INT64U unsigned // #define AGG_INT64U unsigned
// //
// It will result in overflow in 16 bit-per-component image/pattern resampling // It will result in overflow in 16 bit-per-component image/pattern resampling
// but it won't result any crash and the rest of the library will remain // 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:
// //
// Provides faster access for massive pixel operations, // Provides faster access for massive pixel operations,
// such as blur, image filtering: // such as blur, image filtering:
#define AGG_RENDERING_BUFFER row_ptr_cache<int8u> #define AGG_RENDERING_BUFFER row_ptr_cache<int8u>
// //
// Provides cheaper creation and destruction (no mem allocs): // Provides cheaper creation and destruction (no mem allocs):
// #define AGG_RENDERING_BUFFER row_accessor<int8u> // #define AGG_RENDERING_BUFFER row_accessor<int8u>
// //
// You can still use both of them simultaneouslyin your applications // You can still use both of them simultaneouslyin your applications
// This #define is used only for default rendering_buffer type, // This #define is used only for default rendering_buffer type,
// in short hand typedefs like pixfmt_rgba32. // in short hand typedefs like pixfmt_rgba32.

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -18,95 +18,106 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg { namespace agg
//------------------------------------------------------------null_markers
struct null_markers
{ {
void remove_all() {} //------------------------------------------------------------null_markers
void add_vertex(double, double, unsigned) {} struct null_markers
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)
{ {
m_source->rewind(path_id); void remove_all() {}
m_status = initial; void add_vertex(double, double, unsigned) {}
} void prepare_src() {}
unsigned vertex(double* x, double* y); void rewind(unsigned) {}
unsigned type() const { return m_source->type(); } unsigned vertex(double*, double*) { return path_cmd_stop; }
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>&);
VertexSource* m_source; //------------------------------------------------------conv_adaptor_vcgen
Generator m_generator; template<class VertexSource,
Markers m_markers; class Generator,
status m_status; class Markers=null_markers> class conv_adaptor_vcgen
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) 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)
{
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)) if(is_stop(m_last_cmd)) return path_cmd_stop;
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;
@ -117,12 +128,12 @@ unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x,
} }
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;
@ -134,18 +145,18 @@ unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x,
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,140 +18,144 @@
#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; }
VPGen& vpgen() { return m_vpgen; } //======================================================conv_adaptor_vpgen
const VPGen& vpgen() const { return m_vpgen; } template<class VertexSource, class VPGen> class conv_adaptor_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); public:
if (!is_stop(cmd)) explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
break; void attach(VertexSource& source) { m_source = &source; }
if (m_poly_flags && !m_vpgen.auto_unclose()) VPGen& vpgen() { return m_vpgen; }
{ const VPGen& vpgen() const { return m_vpgen; }
*x = 0.0;
*y = 0.0;
cmd = m_poly_flags;
m_poly_flags = 0;
break;
}
if (m_vertices < 0) void rewind(unsigned path_id);
{ unsigned vertex(double* x, double* y);
if (m_vertices < -1) unsigned type() const { return m_source->type(); }
{
m_vertices = 0;
return path_cmd_stop;
}
m_vpgen.move_to(m_start_x, m_start_y);
m_vertices = 1;
continue;
}
double tx, ty; private:
cmd = m_source->vertex(&tx, &ty); conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);
if (is_vertex(cmd)) 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(;;)
{ {
if (is_move_to(cmd)) cmd = m_vpgen.vertex(x, y);
if(!is_stop(cmd)) break;
if(m_poly_flags && !m_vpgen.auto_unclose())
{ {
if (m_vpgen.auto_close() && m_vertices > 2) *x = 0.0;
{ *y = 0.0;
m_vpgen.line_to(m_start_x, m_start_y); cmd = m_poly_flags;
m_poly_flags = path_cmd_end_poly | static_cast<path_commands_e>(path_flags_close); m_poly_flags = 0;
m_start_x = tx;
m_start_y = ty;
m_vertices = -1;
continue;
}
m_vpgen.move_to(tx, ty);
m_start_x = tx;
m_start_y = ty;
m_vertices = 1;
}
else
{
m_vpgen.line_to(tx, ty);
++m_vertices;
}
}
else
{
if (is_end_poly(cmd))
{
m_poly_flags = cmd;
if (is_closed(cmd) || m_vpgen.auto_close())
{
if (m_vpgen.auto_close())
m_poly_flags |= path_flags_close;
if (m_vertices > 2)
{
m_vpgen.line_to(m_start_x, m_start_y);
}
m_vertices = 0;
}
}
else
{
// path_cmd_stop
if (m_vpgen.auto_close() && m_vertices > 2)
{
m_vpgen.line_to(m_start_x, m_start_y);
m_poly_flags = path_cmd_end_poly | static_cast<path_commands_e>(path_flags_close);
m_vertices = -2;
continue;
}
break; break;
} }
if(m_vertices < 0)
{
if(m_vertices < -1)
{
m_vertices = 0;
return path_cmd_stop;
}
m_vpgen.move_to(m_start_x, m_start_y);
m_vertices = 1;
continue;
}
double tx, ty;
cmd = m_source->vertex(&tx, &ty);
if(is_vertex(cmd))
{
if(is_move_to(cmd))
{
if(m_vpgen.auto_close() && m_vertices > 2)
{
m_vpgen.line_to(m_start_x, m_start_y);
m_poly_flags = path_cmd_end_poly
| static_cast<path_commands_e>(path_flags_close);
m_start_x = tx;
m_start_y = ty;
m_vertices = -1;
continue;
}
m_vpgen.move_to(tx, ty);
m_start_x = tx;
m_start_y = ty;
m_vertices = 1;
}
else
{
m_vpgen.line_to(tx, ty);
++m_vertices;
}
}
else
{
if(is_end_poly(cmd))
{
m_poly_flags = cmd;
if(is_closed(cmd) || m_vpgen.auto_close())
{
if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close;
if(m_vertices > 2)
{
m_vpgen.line_to(m_start_x, m_start_y);
}
m_vertices = 0;
}
}
else
{
// path_cmd_stop
if(m_vpgen.auto_close() && m_vertices > 2)
{
m_vpgen.line_to(m_start_x, m_start_y);
m_poly_flags = path_cmd_end_poly
| static_cast<path_commands_e>(path_flags_close);
m_vertices = -2;
continue;
}
break;
}
}
} }
return cmd;
} }
return cmd;
} }
} // namespace agg
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -19,26 +19,30 @@
#include "agg_vcgen_bspline.h" #include "agg_vcgen_bspline.h"
#include "agg_conv_adaptor_vcgen.h" #include "agg_conv_adaptor_vcgen.h"
namespace agg {
//---------------------------------------------------------conv_bspline namespace agg
template<class VertexSource>
struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline>
{ {
typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type;
conv_bspline(VertexSource& vs) //---------------------------------------------------------conv_bspline
: conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) template<class VertexSource>
{} struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline>
{
typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type;
void interpolation_step(double v) { base_type::generator().interpolation_step(v); } conv_bspline(VertexSource& vs) :
double interpolation_step() const { return base_type::generator().interpolation_step(); } conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) {}
private: void interpolation_step(double v) { base_type::generator().interpolation_step(v); }
conv_bspline(const conv_bspline<VertexSource>&); double interpolation_step() const { return base_type::generator().interpolation_step(); }
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -14,12 +14,12 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
// Polygon clipping converter // Polygon clipping converter
// There an optimized Liang-Basky algorithm is used. // There an optimized Liang-Basky algorithm is used.
// The algorithm doesn't optimize the degenerate edges, i.e. it will never // The algorithm doesn't optimize the degenerate edges, i.e. it will never
// break a closed polygon into two or more ones, instead, there will be // break a closed polygon into two or more ones, instead, there will be
// degenerate edges coinciding with the respective clipping boundaries. // degenerate edges coinciding with the respective clipping boundaries.
// This is a sub-optimal solution, because that optimization would require // This is a sub-optimal solution, because that optimization would require
// extra, rather expensive math while the rasterizer tolerates it quite well, // extra, rather expensive math while the rasterizer tolerates it quite well,
// without any considerable overhead. // without any considerable overhead.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -30,31 +30,35 @@
#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(VertexSource& vs) //=======================================================conv_clip_polygon
: conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) 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;
void clip_box(double _x1, double _y1, double _x2, double _y2) { base_type::vpgen().clip_box(_x1, _y1, _x2, _y2); } conv_clip_polygon(VertexSource& vs) :
conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) {}
double x1() const { return base_type::vpgen().x1(); } void clip_box(double _x1, double _y1, double _x2, double _y2)
double y1() const { return base_type::vpgen().y1(); } {
double x2() const { return base_type::vpgen().x2(); } base_type::vpgen().clip_box(_x1, _y1, _x2, _y2);
double y2() const { return base_type::vpgen().y2(); } }
unsigned type() const { return base_type::type(); }
private: double x1() const { return base_type::vpgen().x1(); }
conv_clip_polygon(const conv_clip_polygon<VertexSource>&); double y1() const { return base_type::vpgen().y1(); }
const conv_clip_polygon<VertexSource>& operator=(const conv_clip_polygon<VertexSource>&); double x2() const { return base_type::vpgen().x2(); }
}; double y2() const { return base_type::vpgen().y2(); }
unsigned type() const { return base_type::type(); }
} // namespace agg private:
conv_clip_polygon(const conv_clip_polygon<VertexSource>&);
const conv_clip_polygon<VertexSource>&
operator = (const conv_clip_polygon<VertexSource>&);
};
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -14,12 +14,12 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
// polyline clipping converter // polyline clipping converter
// There an optimized Liang-Basky algorithm is used. // There an optimized Liang-Basky algorithm is used.
// The algorithm doesn't optimize the degenerate edges, i.e. it will never // The algorithm doesn't optimize the degenerate edges, i.e. it will never
// break a closed polyline into two or more ones, instead, there will be // break a closed polyline into two or more ones, instead, there will be
// degenerate edges coinciding with the respective clipping boundaries. // degenerate edges coinciding with the respective clipping boundaries.
// This is a sub-optimal solution, because that optimization would require // This is a sub-optimal solution, because that optimization would require
// extra, rather expensive math while the rasterizer tolerates it quite well, // extra, rather expensive math while the rasterizer tolerates it quite well,
// without any considerable overhead. // without any considerable overhead.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -30,31 +30,35 @@
#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(VertexSource& vs) //=======================================================conv_clip_polyline
: conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(vs) 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;
void clip_box(double _x1, double _y1, double _x2, double _y2) { base_type::vpgen().clip_box(_x1, _y1, _x2, _y2); } conv_clip_polyline(VertexSource& vs) :
conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(vs) {}
double x1() const { return base_type::vpgen().x1(); } void clip_box(double _x1, double _y1, double _x2, double _y2)
double y1() const { return base_type::vpgen().y1(); } {
double x2() const { return base_type::vpgen().x2(); } base_type::vpgen().clip_box(_x1, _y1, _x2, _y2);
double y2() const { return base_type::vpgen().y2(); } }
unsigned type() const { return base_type::type(); }
private: double x1() const { return base_type::vpgen().x1(); }
conv_clip_polyline(const conv_clip_polyline<VertexSource>&); double y1() const { return base_type::vpgen().y1(); }
const conv_clip_polyline<VertexSource>& operator=(const conv_clip_polyline<VertexSource>&); double x2() const { return base_type::vpgen().x2(); }
}; double y2() const { return base_type::vpgen().y2(); }
unsigned type() const { return base_type::type(); }
} // namespace agg private:
conv_clip_polyline(const conv_clip_polyline<VertexSource>&);
const conv_clip_polyline<VertexSource>&
operator = (const conv_clip_polyline<VertexSource>&);
};
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -18,105 +18,108 @@
#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; }
void rewind(unsigned path_id); //======================================================conv_close_polygon
unsigned vertex(double* x, double* y); template<class VertexSource> class conv_close_polygon
private:
conv_close_polygon(const conv_close_polygon<VertexSource>&);
const conv_close_polygon<VertexSource>& operator=(const conv_close_polygon<VertexSource>&);
VertexSource* m_source;
unsigned m_cmd[2];
double m_x[2];
double m_y[2];
unsigned m_vertex;
bool m_line_to;
};
//------------------------------------------------------------------------
template<class VertexSource>
void conv_close_polygon<VertexSource>::rewind(unsigned path_id)
{
m_source->rewind(path_id);
m_vertex = 2;
m_line_to = false;
}
//------------------------------------------------------------------------
template<class VertexSource>
unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_stop;
for (;;)
{ {
if (m_vertex < 2) public:
{ explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
*x = m_x[m_vertex]; void attach(VertexSource& source) { m_source = &source; }
*y = m_y[m_vertex];
cmd = m_cmd[m_vertex];
++m_vertex;
break;
}
cmd = m_source->vertex(x, y); void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
if (is_end_poly(cmd)) private:
{ conv_close_polygon(const conv_close_polygon<VertexSource>&);
cmd |= path_flags_close; const conv_close_polygon<VertexSource>&
break; operator = (const conv_close_polygon<VertexSource>&);
}
if (is_stop(cmd)) VertexSource* m_source;
{ unsigned m_cmd[2];
if (m_line_to) double m_x[2];
{ double m_y[2];
m_cmd[0] = path_cmd_end_poly | path_flags_close; unsigned m_vertex;
m_cmd[1] = path_cmd_stop; bool m_line_to;
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; template<class VertexSource>
break; void conv_close_polygon<VertexSource>::rewind(unsigned path_id)
} {
m_source->rewind(path_id);
m_vertex = 2;
m_line_to = false;
} }
return cmd;
}
} // namespace agg
//------------------------------------------------------------------------
template<class VertexSource>
unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y)
{
unsigned cmd = path_cmd_stop;
for(;;)
{
if(m_vertex < 2)
{
*x = m_x[m_vertex];
*y = m_y[m_vertex];
cmd = m_cmd[m_vertex];
++m_vertex;
break;
}
cmd = m_source->vertex(x, y);
if(is_end_poly(cmd))
{
cmd |= path_flags_close;
break;
}
if(is_stop(cmd))
{
if(m_line_to)
{
m_cmd[0] = path_cmd_end_poly | path_flags_close;
m_cmd[1] = path_cmd_stop;
m_vertex = 0;
m_line_to = false;
continue;
}
break;
}
if(is_move_to(cmd))
{
if(m_line_to)
{
m_x[0] = 0.0;
m_y[0] = 0.0;
m_cmd[0] = path_cmd_end_poly | path_flags_close;
m_x[1] = *x;
m_y[1] = *y;
m_cmd[1] = cmd;
m_vertex = 0;
m_line_to = false;
continue;
}
break;
}
if(is_vertex(cmd))
{
m_line_to = true;
break;
}
}
return cmd;
}
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -18,57 +18,56 @@
#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
{ {
public: //=============================================================conv_concat
conv_concat(VS1& source1, VS2& source2) // Concatenation of two paths. Usually used to combine lines or curves
: m_source1(&source1) // with markers such as arrowheads
, m_source2(&source2) template<class VS1, class VS2> class conv_concat
, m_status(2)
{}
void attach1(VS1& source) { m_source1 = &source; }
void attach2(VS2& source) { m_source2 = &source; }
void rewind(unsigned path_id)
{ {
m_source1->rewind(path_id); public:
m_source2->rewind(0); conv_concat(VS1& source1, VS2& source2) :
m_status = 0; m_source1(&source1), m_source2(&source2), m_status(2) {}
} 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);
{ m_source2->rewind(0);
cmd = m_source1->vertex(x, y); m_status = 0;
if (!is_stop(cmd))
return cmd;
m_status = 1;
} }
if (m_status == 1)
unsigned vertex(double* x, double* y)
{ {
cmd = m_source2->vertex(x, y); unsigned cmd;
if (!is_stop(cmd)) if(m_status == 0)
return cmd; {
m_status = 2; cmd = m_source1->vertex(x, y);
if(!is_stop(cmd)) return cmd;
m_status = 1;
}
if(m_status == 1)
{
cmd = m_source2->vertex(x, y);
if(!is_stop(cmd)) return cmd;
m_status = 2;
}
return path_cmd_stop;
} }
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>& operator=(const conv_concat<VS1, VS2>&); const conv_concat<VS1, VS2>&
operator = (const conv_concat<VS1, VS2>&);
VS1* m_source1;
VS2* m_source2;
int m_status;
};
}
VS1* m_source1;
VS2* m_source2;
int m_status;
};
} // namespace agg
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -23,40 +23,43 @@
#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(VertexSource& vs) //-----------------------------------------------------------conv_contour
: conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs) template<class VertexSource>
{} struct conv_contour : public conv_adaptor_vcgen<VertexSource, vcgen_contour>
{
typedef conv_adaptor_vcgen<VertexSource, vcgen_contour> base_type;
void line_join(line_join_e lj) { base_type::generator().line_join(lj); } conv_contour(VertexSource& vs) :
void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); } conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs)
void width(double w) { base_type::generator().width(w); } {
void miter_limit(double ml) { base_type::generator().miter_limit(ml); } }
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); }
line_join_e line_join() const { return base_type::generator().line_join(); } void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
inner_join_e inner_join() const { return base_type::generator().inner_join(); } void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
double width() const { return base_type::generator().width(); } void width(double w) { base_type::generator().width(w); }
double miter_limit() const { return base_type::generator().miter_limit(); } void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); } void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
double approximation_scale() const { return base_type::generator().approximation_scale(); } void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); } void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); }
private: line_join_e line_join() const { return base_type::generator().line_join(); }
conv_contour(const conv_contour<VertexSource>&); inner_join_e inner_join() const { return base_type::generator().inner_join(); }
const conv_contour<VertexSource>& operator=(const conv_contour<VertexSource>&); double width() const { return base_type::generator().width(); }
}; double miter_limit() const { return base_type::generator().miter_limit(); }
double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
double approximation_scale() const { return base_type::generator().approximation_scale(); }
bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); }
} // namespace agg private:
conv_contour(const conv_contour<VertexSource>&);
const conv_contour<VertexSource>&
operator = (const conv_contour<VertexSource>&);
};
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -23,140 +23,157 @@
#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(self_type&&) = default; //---------------------------------------------------------------conv_curve
// Curve converter class. Any path storage can have Bezier curves defined
void attach(VertexSource& source) { m_source = &source; } // 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
void approximation_method(curve_approximation_method_e v) // 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
{ {
m_curve3.approximation_method(v); public:
m_curve4.approximation_method(v); 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(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)
{ {
m_curve3.approximation_scale(s); if(!is_stop(m_curve3.vertex(x, y)))
m_curve4.approximation_scale(s); {
} m_last_x = *x;
m_last_y = *y;
return path_cmd_line_to;
}
double approximation_scale() const { return m_curve4.approximation_scale(); } if(!is_stop(m_curve4.vertex(x, y)))
{
m_last_x = *x;
m_last_y = *y;
return path_cmd_line_to;
}
void angle_tolerance(double v) double ct2_x=0;
{ double ct2_y=0;
m_curve3.angle_tolerance(v); double end_x=0;
m_curve4.angle_tolerance(v); double end_y=0;
}
double angle_tolerance() const { return m_curve4.angle_tolerance(); } unsigned cmd = m_source->vertex(x, y);
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, *x, *y, end_x, end_y); m_curve3.init(m_last_x, m_last_y,
*x, *y,
end_x, end_y);
m_curve3.vertex(x, y); // First call returns path_cmd_move_to m_curve3.vertex(x, y); // 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;
@ -164,18 +181,24 @@ unsigned conv_curve<VertexSource, Curve3, Curve4>::vertex(double* x, double* y)
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, *x, *y, ct2_x, ct2_y, end_x, end_y); m_curve4.init(m_last_x, m_last_y,
*x, *y,
ct2_x, ct2_y,
end_x, end_y);
m_curve4.vertex(x, y); // First call returns path_cmd_move_to m_curve4.vertex(x, y); // 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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -23,33 +23,46 @@
#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(VertexSource& vs) //---------------------------------------------------------------conv_dash
: conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs) 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;
void remove_all_dashes() { base_type::generator().remove_all_dashes(); } conv_dash(VertexSource& vs) :
conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs)
{
}
void add_dash(double dash_len, double gap_len) { base_type::generator().add_dash(dash_len, gap_len); } void remove_all_dashes()
{
base_type::generator().remove_all_dashes();
}
void dash_start(double ds) { base_type::generator().dash_start(ds); } void add_dash(double dash_len, double gap_len)
{
base_type::generator().add_dash(dash_len, gap_len);
}
void shorten(double s) { base_type::generator().shorten(s); } void dash_start(double ds)
double shorten() const { return base_type::generator().shorten(); } {
base_type::generator().dash_start(ds);
}
private: void shorten(double s) { base_type::generator().shorten(s); }
conv_dash(const conv_dash<VertexSource, Markers>&); double shorten() const { return base_type::generator().shorten(); }
const conv_dash<VertexSource, Markers>& operator=(const conv_dash<VertexSource, Markers>&);
};
} // namespace agg private:
conv_dash(const conv_dash<VertexSource, Markers>&);
const conv_dash<VertexSource, Markers>&
operator = (const conv_dash<VertexSource, Markers>&);
};
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -13,7 +13,7 @@
// http://www.antigrain.com // http://www.antigrain.com
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
// General Polygon Clipper based on the GPC library by Alan Murta // General Polygon Clipper based on the GPC library by Alan Murta
// Union, Intersection, XOR, A-B, B-A // Union, Intersection, XOR, A-B, B-A
// Contact the author if you intend to use it in commercial applications! // Contact the author if you intend to use it in commercial applications!
// http://www.cs.man.ac.uk/aig/staff/alan/software/ // http://www.cs.man.ac.uk/aig/staff/alan/software/
@ -28,352 +28,405 @@
#include "agg_basics.h" #include "agg_basics.h"
#include "agg_array.h" #include "agg_array.h"
extern "C" { 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 status { status_move_to, status_line_to, status_stop }; enum gpc_op_e
struct contour_header_type
{ {
int num_vertices; gpc_or,
int hole_flag; gpc_and,
gpc_vertex* vertices; gpc_xor,
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;
public: //================================================================conv_gpc
typedef VSA source_a_type; template<class VSA, class VSB> class conv_gpc
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)); enum status
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>
// Vertex Source Interface void conv_gpc<VSA, VSB>::free_gpc_data()
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; free_polygon(m_poly_a);
double x, y; free_polygon(m_poly_b);
double start_x = 0.0; free_result();
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 (is_vertex(cmd)) if(m_vertex_accumulator.size() > 2)
{ {
if (is_move_to(cmd)) 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++)
{ {
if (line_to) const gpc_vertex& s = m_vertex_accumulator[i];
{ d->x = s.x;
end_contour(orientation); d->y = s.y;
orientation = 0; ++d;
}
start_contour();
start_x = x;
start_y = y;
} }
add_vertex(x, y);
line_to = true;
} }
else else
{ {
if (is_end_poly(cmd)) m_vertex_accumulator.remove_last();
{
orientation = get_orientation(cmd);
if (line_to && is_closed(cmd))
{
add_vertex(start_x, start_y);
}
}
} }
} }
if (line_to) }
//------------------------------------------------------------------------
template<class VSA, class VSB>
void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p)
{
free_polygon(p);
if(m_contour_accumulator.size())
{ {
end_contour(orientation); p.num_contours = m_contour_accumulator.size();
}
make_polygon(p);
}
private: p.hole = 0;
//-------------------------------------------------------------------- p.contour = pod_allocator<gpc_vertex_list>::allocate(p.num_contours);
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; int i;
for (i = 0; i < h.num_vertices; i++) gpc_vertex_list* pv = p.contour;
for(i = 0; i < p.num_contours; i++)
{ {
const gpc_vertex& s = m_vertex_accumulator[i]; const contour_header_type& h = m_contour_accumulator[i];
d->x = s.x; pv->num_vertices = h.num_vertices;
d->y = s.y; pv->vertex = h.vertices;
++d; ++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 else
{ {
m_vertex_accumulator.remove_last(); if(next_vertex(x, y))
}
}
}
//------------------------------------------------------------------------
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_line_to;
return path_cmd_move_to; }
else
{
m_status = status_move_to;
} }
m_status = status_stop;
return path_cmd_end_poly | path_flags_close; return path_cmd_end_poly | path_flags_close;
} }
return path_cmd_stop;
} }
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -22,70 +22,82 @@
#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
{ {
public: //-------------------------------------------------------------conv_marker
conv_marker(MarkerLocator& ml, MarkerShapes& ms); template<class MarkerLocator, class MarkerShapes>
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))
{ {
switch (m_status) public:
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;
@ -93,12 +105,12 @@ unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y)
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;
@ -112,7 +124,7 @@ unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y)
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;
@ -124,11 +136,13 @@ unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y)
case stop: case stop:
cmd = path_cmd_stop; cmd = path_cmd_stop;
break; break;
}
} }
return cmd;
} }
return cmd;
} }
} // namespace agg
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -20,27 +20,32 @@
#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(VertexSource& vs) //=====================================================conv_marker_adaptor
: conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>(vs) 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;
void shorten(double s) { base_type::generator().shorten(s); } conv_marker_adaptor(VertexSource& vs) :
double shorten() const { return base_type::generator().shorten(); } conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>(vs)
{
}
private: void shorten(double s) { base_type::generator().shorten(s); }
conv_marker_adaptor(const conv_marker_adaptor<VertexSource, Markers>&); double shorten() const { return base_type::generator().shorten(); }
const conv_marker_adaptor<VertexSource, Markers>& operator=(const conv_marker_adaptor<VertexSource, Markers>&);
};
} // namespace agg private:
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,53 +22,59 @@
#include "agg_array.h" #include "agg_array.h"
#include "clipper.hpp" #include "clipper.hpp"
namespace agg { namespace agg
{
template<class VSA> template<class VSA> class conv_offset
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)) if ((val < 0)) return (int)(val - 0.5); else return (int)(val + 0.5);
return (int)(val - 0.5);
else
return (int)(val + 0.5);
} }
public: public:
conv_offset(source_a_type& a, double offset = 0.0, int scaling_factor = 0) conv_offset(source_a_type &a, double offset = 0.0,
: m_src_a(&a) int scaling_factor = 0)
, m_offset(offset) : m_src_a(&a),
, m_status(status_move_to) m_offset(offset),
, m_vertex(-1) m_status(status_move_to),
, m_contour(-1) m_vertex(-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 { return static_cast<unsigned>(m_src_a->type()); } unsigned type() const
{
return static_cast<unsigned>(m_src_a->type());
}
double get_offset() const { return m_offset; } double get_offset() const
{
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);
@ -76,17 +82,13 @@ class conv_offset
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> template<class VS> void add(VS &src, ClipperLib::Paths &p)
void add(VS& src, ClipperLib::Paths& p)
{ {
unsigned cmd; unsigned cmd;
double x; double x; double y; double start_x; double start_y;
double y;
double start_x;
double start_y;
bool starting_first_line; bool starting_first_line;
start_x = 0.0; start_x = 0.0;
@ -94,27 +96,26 @@ class conv_offset
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) if(!starting_first_line ) end_contour(p);
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);
} }
@ -134,43 +135,42 @@ 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) if( m_vertex_accumulator.size() < 3 ) return;
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,35 +178,33 @@ 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()) if(m_contour >= (int)m_result.size()) return false;
return false; m_vertex =-1;
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()) if(m_vertex >= (int)m_result[m_contour].size()) return false;
return false; *x = (double)m_result[ m_contour ][ m_vertex ].X / 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;
*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
@ -220,7 +218,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;
} }
@ -233,5 +231,6 @@ unsigned conv_offset<VSA>::vertex(double* x, double* y)
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
} // namespace agg
#endif // AGG_CONV_OFFSET_INCLUDED } //namespace agg
#endif //AGG_CONV_OFFSET_INCLUDED

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -20,26 +20,29 @@
#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(VertexSource& vs) //========================================================conv_segmentator
: conv_adaptor_vpgen<VertexSource, vpgen_segmentator>(vs) template<class VertexSource>
{} struct conv_segmentator : public conv_adaptor_vpgen<VertexSource, vpgen_segmentator>
{
typedef conv_adaptor_vpgen<VertexSource, vpgen_segmentator> base_type;
void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); } conv_segmentator(VertexSource& vs) :
double approximation_scale() const { return base_type::vpgen().approximation_scale(); } conv_adaptor_vpgen<VertexSource, vpgen_segmentator>(vs) {}
private: void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); }
conv_segmentator(const conv_segmentator<VertexSource>&); double approximation_scale() const { return base_type::vpgen().approximation_scale(); }
const conv_segmentator<VertexSource>& operator=(const conv_segmentator<VertexSource>&);
};
} // namespace agg private:
conv_segmentator(const conv_segmentator<VertexSource>&);
const conv_segmentator<VertexSource>&
operator = (const conv_segmentator<VertexSource>&);
};
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -20,27 +20,31 @@
#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(VertexSource& vs) //=======================================================conv_shorten_path
: conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>(vs) 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;
void shorten(double s) { base_type::generator().shorten(s); } conv_shorten_path(VertexSource& vs) :
double shorten() const { return base_type::generator().shorten(); } conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>(vs)
{
}
private: void shorten(double s) { base_type::generator().shorten(s); }
conv_shorten_path(const conv_shorten_path<VertexSource>&); double shorten() const { return base_type::generator().shorten(); }
const conv_shorten_path<VertexSource>& operator=(const conv_shorten_path<VertexSource>&);
};
} // namespace agg private:
conv_shorten_path(const conv_shorten_path<VertexSource>&);
const conv_shorten_path<VertexSource>&
operator = (const conv_shorten_path<VertexSource>&);
};
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -24,62 +24,70 @@
#include "agg_conv_adaptor_vcgen.h" #include "agg_conv_adaptor_vcgen.h"
#include "agg_conv_curve.h" #include "agg_conv_curve.h"
namespace agg {
//-------------------------------------------------------conv_smooth namespace agg
template<class VertexSource, class VertexGenerator>
struct conv_smooth : public conv_adaptor_vcgen<VertexSource, VertexGenerator>
{ {
typedef conv_adaptor_vcgen<VertexSource, VertexGenerator> base_type;
conv_smooth(VertexSource& vs) //-------------------------------------------------------conv_smooth
: conv_adaptor_vcgen<VertexSource, VertexGenerator>(vs) template<class VertexSource, class VertexGenerator>
{} 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))
{ {
this->attach(m_smooth); typedef conv_adaptor_vcgen<VertexSource, VertexGenerator> base_type;
}
conv_smooth_curve(const conv_smooth_curve<VertexSource, VertexGenerator>&) = delete; conv_smooth(VertexSource& vs) :
const conv_smooth_curve<VertexSource, VertexGenerator>& conv_adaptor_vcgen<VertexSource, VertexGenerator>(vs)
operator=(const conv_smooth_curve<VertexSource, VertexGenerator>&) = delete; {
}
void smooth_value(double v) { m_smooth.generator().smooth_value(v); } conv_smooth(conv_smooth<VertexSource, VertexGenerator> &&) = default;
double smooth_value() const { return m_smooth.generator().smooth_value(); }
unsigned type() const { return m_smooth.type(); }
private: conv_smooth(const conv_smooth<VertexSource, VertexGenerator>&) = delete;
conv_smooth<VertexSource, VertexGenerator> m_smooth; 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))
{
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -23,46 +23,51 @@
#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(VertexSource& vs) //-------------------------------------------------------------conv_stroke
: conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs) 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;
void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); } conv_stroke(VertexSource& vs) :
void line_join(line_join_e lj) { base_type::generator().line_join(lj); } conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs)
void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); } {
}
line_cap_e line_cap() const { return base_type::generator().line_cap(); } void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); }
line_join_e line_join() const { return base_type::generator().line_join(); } void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
inner_join_e inner_join() const { return base_type::generator().inner_join(); } void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
void width(double w) { base_type::generator().width(w); } line_cap_e line_cap() const { return base_type::generator().line_cap(); }
void miter_limit(double ml) { base_type::generator().miter_limit(ml); } line_join_e line_join() const { return base_type::generator().line_join(); }
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); } inner_join_e inner_join() const { return base_type::generator().inner_join(); }
void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
double width() const { return base_type::generator().width(); } void width(double w) { base_type::generator().width(w); }
double miter_limit() const { return base_type::generator().miter_limit(); } void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); } void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
double approximation_scale() const { return base_type::generator().approximation_scale(); } 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 shorten(double s) { base_type::generator().shorten(s); } double width() const { return base_type::generator().width(); }
double shorten() const { return base_type::generator().shorten(); } 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(); }
private: void shorten(double s) { base_type::generator().shorten(s); }
conv_stroke(const conv_stroke<VertexSource, Markers>&); double shorten() const { return base_type::generator().shorten(); }
const conv_stroke<VertexSource, Markers>& operator=(const conv_stroke<VertexSource, Markers>&);
};
} // namespace agg private:
conv_stroke(const conv_stroke<VertexSource, Markers>&);
const conv_stroke<VertexSource, Markers>&
operator = (const conv_stroke<VertexSource, Markers>&);
};
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -22,44 +22,50 @@
#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)
{}
void attach(VertexSource& source) { m_source = &source; } //----------------------------------------------------------conv_transform
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)
{ {
unsigned cmd = m_source->vertex(x, y); public:
if (is_vertex(cmd)) conv_transform(VertexSource& source, Transformer& tr) :
{ m_source(&source), m_trans(&tr) {}
m_trans->transform(x, y);
void attach(VertexSource& source) { m_source = &source; }
void rewind(unsigned path_id)
{
m_source->rewind(path_id);
} }
return cmd;
}
void transformer(Transformer& tr) { m_trans = &tr; } unsigned vertex(double* x, double* y)
{
unsigned cmd = m_source->vertex(x, y);
if(is_vertex(cmd))
{
m_trans->transform(x, y);
}
return cmd;
}
unsigned type() const { return m_source->type(); } void transformer(Transformer& tr)
{
m_trans = &tr;
}
private: unsigned type() const { return m_source->type(); }
conv_transform(const conv_transform<VertexSource>&);
const conv_transform<VertexSource>& operator=(const conv_transform<VertexSource>&);
VertexSource* m_source; private:
const Transformer* m_trans; conv_transform(const conv_transform<VertexSource>&);
}; const conv_transform<VertexSource>&
operator = (const conv_transform<VertexSource>&);
} // namespace agg VertexSource* m_source;
const Transformer* m_trans;
};
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -18,34 +18,35 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg { namespace agg
//====================================================conv_unclose_polygon
template<class VertexSource>
class conv_unclose_polygon
{ {
public: //====================================================conv_unclose_polygon
explicit conv_unclose_polygon(VertexSource& vs) template<class VertexSource> class conv_unclose_polygon
: 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)
{ {
unsigned cmd = m_source->vertex(x, y); public:
if (is_end_poly(cmd)) explicit conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {}
cmd &= ~path_flags_close; void attach(VertexSource& source) { m_source = &source; }
return cmd;
}
private: void rewind(unsigned path_id)
conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&); {
const conv_unclose_polygon<VertexSource>& operator=(const conv_unclose_polygon<VertexSource>&); m_source->rewind(path_id);
}
VertexSource* m_source; unsigned vertex(double* x, double* y)
}; {
unsigned cmd = m_source->vertex(x, y);
if(is_end_poly(cmd)) cmd &= ~path_flags_close;
return cmd;
}
} // namespace agg private:
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,229 +23,268 @@
#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);
public: //===================================================dda_line_interpolator
//-------------------------------------------------------------------- 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)
{ {
if (m_mod <= 0) static constexpr int factor = 2 << (FractionShift - 1);
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 //--------------------------------------------------------------------
dda2_line_interpolator(int y1, int y2, int count, int) void operator ++ ()
: 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_dy += m_inc;
m_rem += count;
m_lft--;
} }
}
//-------------------------------------------- Backward-adjusted line //--------------------------------------------------------------------
dda2_line_interpolator(int y, int count) void operator -- ()
: m_cnt(count <= 0 ? 1 : count)
, m_lft(y / m_cnt)
, m_rem(y % m_cnt)
, m_mod(m_rem)
, m_y(0)
{
if (m_mod <= 0)
{ {
m_mod += count; m_dy -= m_inc;
m_rem += count;
m_lft--;
} }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void save(save_data_type* data) const void operator += (unsigned n)
{
data[0] = m_mod;
data[1] = m_y;
}
//--------------------------------------------------------------------
void load(const save_data_type* data)
{
m_mod = data[0];
m_y = data[1];
}
//--------------------------------------------------------------------
void operator++()
{
m_mod += m_rem;
m_y += m_lft;
if (m_mod > 0)
{ {
m_mod -= m_cnt; m_dy += m_inc * n;
m_y++;
} }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void operator--() void operator -= (unsigned n)
{
if (m_mod <= m_rem)
{ {
m_mod += m_cnt; m_dy -= m_inc * n;
m_y--;
} }
m_mod -= m_rem;
m_y -= m_lft;
}
//--------------------------------------------------------------------
void adjust_forward() { m_mod -= m_cnt; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void adjust_backward() { m_mod += m_cnt; } int y() const { return m_y + (m_dy >> (FractionShift - YShift)); }
int dy() const { return m_dy; }
//-------------------------------------------------------------------- private:
int mod() const { return m_mod; } int m_y;
int rem() const { return m_rem; } int m_inc;
int lft() const { return m_lft; } int m_dy;
//--------------------------------------------------------------------
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() //=================================================dda2_line_interpolator
class dda2_line_interpolator
{ {
++m_interpolator; public:
m_x1_lr += m_inc; typedef int save_data_type;
} enum save_size_e { save_size = 2 };
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void vstep() dda2_line_interpolator() {}
//-------------------------------------------- Forward-adjusted line
dda2_line_interpolator(int y1, int y2, int count) :
m_cnt(count <= 0 ? 1 : count),
m_lft((y2 - y1) / m_cnt),
m_rem((y2 - y1) % m_cnt),
m_mod(m_rem),
m_y(y1)
{
if(m_mod <= 0)
{
m_mod += count;
m_rem += count;
m_lft--;
}
m_mod -= count;
}
//-------------------------------------------- Backward-adjusted line
dda2_line_interpolator(int y1, int y2, int count, int) :
m_cnt(count <= 0 ? 1 : count),
m_lft((y2 - y1) / m_cnt),
m_rem((y2 - y1) % m_cnt),
m_mod(m_rem),
m_y(y1)
{
if(m_mod <= 0)
{
m_mod += count;
m_rem += count;
m_lft--;
}
}
//-------------------------------------------- Backward-adjusted line
dda2_line_interpolator(int y, int count) :
m_cnt(count <= 0 ? 1 : count),
m_lft(y / m_cnt),
m_rem(y % m_cnt),
m_mod(m_rem),
m_y(0)
{
if(m_mod <= 0)
{
m_mod += count;
m_rem += count;
m_lft--;
}
}
//--------------------------------------------------------------------
void save(save_data_type* data) const
{
data[0] = m_mod;
data[1] = m_y;
}
//--------------------------------------------------------------------
void load(const save_data_type* data)
{
m_mod = data[0];
m_y = data[1];
}
//--------------------------------------------------------------------
void operator++()
{
m_mod += m_rem;
m_y += m_lft;
if(m_mod > 0)
{
m_mod -= m_cnt;
m_y++;
}
}
//--------------------------------------------------------------------
void operator--()
{
if(m_mod <= m_rem)
{
m_mod += m_cnt;
m_y--;
}
m_mod -= m_rem;
m_y -= m_lft;
}
//--------------------------------------------------------------------
void adjust_forward()
{
m_mod -= m_cnt;
}
//--------------------------------------------------------------------
void adjust_backward()
{
m_mod += m_cnt;
}
//--------------------------------------------------------------------
int mod() const { return m_mod; }
int rem() const { return m_rem; }
int lft() const { return m_lft; }
//--------------------------------------------------------------------
int y() const { return m_y; }
private:
int m_cnt;
int m_lft;
int m_rem;
int m_mod;
int m_y;
};
//---------------------------------------------line_bresenham_interpolator
class line_bresenham_interpolator
{ {
++m_interpolator; public:
m_y1_lr += m_inc; enum subpixel_scale_e
} {
subpixel_shift = 8,
subpixel_scale = 1 << subpixel_shift,
subpixel_mask = subpixel_scale - 1
};
//-------------------------------------------------------------------- //--------------------------------------------------------------------
int x1() const { return m_x1_lr; } static int line_lr(int v) { return v >> subpixel_shift; }
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()); } line_bresenham_interpolator(int x1, int y1, int x2, int y2) :
int x2_hr() const { return m_interpolator.y(); } m_x1_lr(line_lr(x1)),
int y2_hr() const { return m_interpolator.y(); } 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()
{
++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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -23,111 +23,102 @@
#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(double x, double y, double rx, double ry, unsigned num_steps = 0, bool cw = false) //----------------------------------------------------------------ellipse
: m_x(x) class ellipse
, 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) public:
calc_num_steps(); ellipse() :
m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_scale(1.0),
m_num(4), m_step(0), m_cw(false) {}
ellipse(double x, double y, double rx, double ry,
unsigned num_steps=0, bool cw=false) :
m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0),
m_num(num_steps), m_step(0), m_cw(cw)
{
if(m_num == 0) calc_num_steps();
}
void init(double x, double y, double rx, double ry,
unsigned num_steps=0, bool cw=false);
void 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); {
void rewind(unsigned path_id); m_scale = scale;
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::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; inline void ellipse::calc_num_steps()
if (m_cw) {
angle = 2.0 * pi - angle; double ra = (std::fabs(m_rx) + std::fabs(m_ry)) / 2;
*x = m_x + std::cos(angle) * m_rx; double da = std::acos(ra / (ra + 0.125 / m_scale)) * 2;
*y = m_y + std::sin(angle) * m_ry; m_num = uround(2*pi / da);
m_step++; }
return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to);
//------------------------------------------------------------------------
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -20,92 +20,94 @@
#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 {
//------------------------------------------ellipse_bresenham_interpolator namespace agg
class ellipse_bresenham_interpolator
{ {
public:
ellipse_bresenham_interpolator(int rx, int ry)
: m_rx2(rx * rx)
, m_ry2(ry * ry)
, m_two_rx2(m_rx2 << 1)
, m_two_ry2(m_ry2 << 1)
, m_dx(0)
, m_dy(0)
, m_inc_x(0)
, m_inc_y(-ry * m_two_rx2)
, m_cur_f(0)
{}
int dx() const { return m_dx; } //------------------------------------------ellipse_bresenham_interpolator
int dy() const { return m_dy; } class ellipse_bresenham_interpolator
void operator++()
{ {
int mx, my, mxy, min_m; public:
int fx, fy, fxy; ellipse_bresenham_interpolator(int rx, int ry) :
m_rx2(rx * rx),
m_ry2(ry * ry),
m_two_rx2(m_rx2 << 1),
m_two_ry2(m_ry2 << 1),
m_dx(0),
m_dy(0),
m_inc_x(0),
m_inc_y(-ry * m_two_rx2),
m_cur_f(0)
{}
int dx() const { return m_dx; }
int dy() const { return m_dy; }
mx = fx = m_cur_f + m_inc_x + m_ry2; void operator++ ()
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; int mx, my, mxy, min_m;
flag = false; int fx, fy, fxy;
}
m_dx = m_dy = 0; 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;
}
if (min_m > mxy)
{
m_inc_x += m_two_ry2;
m_inc_y += m_two_rx2; m_inc_y += m_two_rx2;
m_cur_f = fxy; m_cur_f = fy;
m_dx = 1;
m_dy = 1; m_dy = 1;
return;
} }
if (flag) private:
{ int m_rx2;
m_inc_x += m_two_ry2; int m_ry2;
m_cur_f = fx; int m_two_rx2;
m_dx = 1; int m_two_ry2;
return; int m_dx;
} int m_dy;
int m_inc_x;
int m_inc_y;
int m_cur_f;
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -18,41 +18,42 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg { namespace agg
extern const int8u gse4x6[]; {
extern const int8u gse4x8[]; extern const int8u gse4x6[];
extern const int8u gse5x7[]; extern const int8u gse4x8[];
extern const int8u gse5x9[]; extern const int8u gse5x7[];
extern const int8u gse6x12[]; extern const int8u gse5x9[];
extern const int8u gse6x9[]; extern const int8u gse6x12[];
extern const int8u gse7x11[]; extern const int8u gse6x9[];
extern const int8u gse7x11_bold[]; extern const int8u gse7x11[];
extern const int8u gse7x15[]; extern const int8u gse7x11_bold[];
extern const int8u gse7x15_bold[]; extern const int8u gse7x15[];
extern const int8u gse8x16[]; extern const int8u gse7x15_bold[];
extern const int8u gse8x16_bold[]; extern const int8u gse8x16[];
extern const int8u mcs11_prop[]; extern const int8u gse8x16_bold[];
extern const int8u mcs11_prop_condensed[]; extern const int8u mcs11_prop[];
extern const int8u mcs12_prop[]; extern const int8u mcs11_prop_condensed[];
extern const int8u mcs13_prop[]; extern const int8u mcs12_prop[];
extern const int8u mcs5x10_mono[]; extern const int8u mcs13_prop[];
extern const int8u mcs5x11_mono[]; extern const int8u mcs5x10_mono[];
extern const int8u mcs6x10_mono[]; extern const int8u mcs5x11_mono[];
extern const int8u mcs6x11_mono[]; extern const int8u mcs6x10_mono[];
extern const int8u mcs7x12_mono_high[]; extern const int8u mcs6x11_mono[];
extern const int8u mcs7x12_mono_low[]; extern const int8u mcs7x12_mono_high[];
extern const int8u verdana12[]; extern const int8u mcs7x12_mono_low[];
extern const int8u verdana12_bold[]; extern const int8u verdana12[];
extern const int8u verdana13[]; extern const int8u verdana12_bold[];
extern const int8u verdana13_bold[]; extern const int8u verdana13[];
extern const int8u verdana14[]; extern const int8u verdana13_bold[];
extern const int8u verdana14_bold[]; extern const int8u verdana14[];
extern const int8u verdana16[]; extern const int8u verdana14_bold[];
extern const int8u verdana16_bold[]; extern const int8u verdana16[];
extern const int8u verdana17[]; extern const int8u verdana16_bold[];
extern const int8u verdana17_bold[]; extern const int8u verdana17[];
extern const int8u verdana18[]; extern const int8u verdana17_bold[];
extern const int8u verdana18_bold[]; extern const int8u verdana18[];
} // namespace agg extern const int8u verdana18_bold[];
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -19,265 +19,307 @@
#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;
};
//--------------------------------------------------------------font_cache //---------------------------------------------------------glyph_data_type
class font_cache enum glyph_data_type
{
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)
{ {
m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1); glyph_data_invalid = 0,
strcpy(m_font_signature, font_signature); glyph_data_mono = 1,
memset(m_glyphs, 0, sizeof(m_glyphs)); glyph_data_gray8 = 2,
} glyph_data_outline = 3
};
//--------------------------------------------------------------------
bool font_is(const char* font_signature) const { return strcmp(font_signature, m_font_signature) == 0; }
//-------------------------------------------------------------------- //-------------------------------------------------------------glyph_cache
const glyph_cache* find_glyph(unsigned glyph_code) const struct glyph_cache
{ {
unsigned msb = (glyph_code >> 8) & 0xFF; unsigned glyph_index;
if (m_glyphs[msb]) int8u* data;
unsigned data_size;
glyph_data_type data_type;
rect_i bounds;
double advance_x;
double advance_y;
};
//--------------------------------------------------------------font_cache
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)
{ {
return m_glyphs[msb][glyph_code & 0xFF]; m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1);
} strcpy(m_font_signature, font_signature);
return 0; memset(m_glyphs, 0, sizeof(m_glyphs));
}
//--------------------------------------------------------------------
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)
{
unsigned msb = (glyph_code >> 8) & 0xFF;
if (m_glyphs[msb] == 0)
{
m_glyphs[msb] = (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256, sizeof(glyph_cache*));
memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
} }
unsigned lsb = glyph_code & 0xFF; //--------------------------------------------------------------------
if (m_glyphs[msb][lsb]) bool font_is(const char* font_signature) const
return 0; // Already exists, do not overwrite
glyph_cache* glyph = (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache), sizeof(double));
glyph->glyph_index = glyph_index;
glyph->data = m_allocator.allocate(data_size);
glyph->data_size = data_size;
glyph->data_type = data_type;
glyph->bounds = bounds;
glyph->advance_x = advance_x;
glyph->advance_y = advance_y;
return m_glyphs[msb][lsb] = glyph;
}
private:
block_allocator m_allocator;
glyph_cache** m_glyphs[256];
char* m_font_signature;
};
//---------------------------------------------------------font_cache_pool
class font_cache_pool
{
public:
//--------------------------------------------------------------------
~font_cache_pool()
{
unsigned i;
for (i = 0; i < m_num_fonts; ++i)
{ {
obj_allocator<font_cache>::deallocate(m_fonts[i]); return strcmp(font_signature, m_font_signature) == 0;
} }
pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
font_cache_pool(unsigned max_fonts = 32) const glyph_cache* find_glyph(unsigned glyph_code) const
: m_fonts(pod_allocator<font_cache*>::allocate(max_fonts))
, m_max_fonts(max_fonts)
, m_num_fonts(0)
, m_cur_font(0)
{}
//--------------------------------------------------------------------
void font(const char* font_signature, bool reset_cache = false)
{
int idx = find_font(font_signature);
if (idx >= 0)
{ {
if (reset_cache) unsigned msb = (glyph_code >> 8) & 0xFF;
if(m_glyphs[msb])
{ {
obj_allocator<font_cache>::deallocate(m_fonts[idx]); return m_glyphs[msb][glyph_code & 0xFF];
m_fonts[idx] = obj_allocator<font_cache>::allocate();
m_fonts[idx]->signature(font_signature);
} }
m_cur_font = m_fonts[idx]; return 0;
} }
else
//--------------------------------------------------------------------
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_num_fonts >= m_max_fonts) unsigned msb = (glyph_code >> 8) & 0xFF;
if(m_glyphs[msb] == 0)
{ {
obj_allocator<font_cache>::deallocate(m_fonts[0]); m_glyphs[msb] =
memcpy(m_fonts, m_fonts + 1, (m_max_fonts - 1) * sizeof(font_cache*)); (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256,
m_num_fonts = m_max_fonts - 1; sizeof(glyph_cache*));
memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
} }
m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate();
m_fonts[m_num_fonts]->signature(font_signature); unsigned lsb = glyph_code & 0xFF;
m_cur_font = m_fonts[m_num_fonts]; if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
++m_num_fonts;
glyph_cache* glyph =
(glyph_cache*)m_allocator.allocate(sizeof(glyph_cache),
sizeof(double));
glyph->glyph_index = glyph_index;
glyph->data = m_allocator.allocate(data_size);
glyph->data_size = data_size;
glyph->data_type = data_type;
glyph->bounds = bounds;
glyph->advance_x = advance_x;
glyph->advance_y = advance_y;
return m_glyphs[msb][lsb] = glyph;
} }
}
//-------------------------------------------------------------------- private:
const font_cache* font() const { return m_cur_font; } block_allocator m_allocator;
glyph_cache** m_glyphs[256];
char* m_font_signature;
};
//--------------------------------------------------------------------
const glyph_cache* find_glyph(unsigned glyph_code) const
//---------------------------------------------------------font_cache_pool
class font_cache_pool
{ {
if (m_cur_font) public:
return m_cur_font->find_glyph(glyph_code); //--------------------------------------------------------------------
return 0; ~font_cache_pool()
}
//--------------------------------------------------------------------
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); unsigned 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);
} }
return 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
int find_font(const char* font_signature) font_cache_pool(unsigned max_fonts=32) :
{ m_fonts(pod_allocator<font_cache*>::allocate(max_fonts)),
unsigned i; m_max_fonts(max_fonts),
for (i = 0; i < m_num_fonts; i++) m_num_fonts(0),
m_cur_font(0)
{}
//--------------------------------------------------------------------
void font(const char* font_signature, bool reset_cache = false)
{ {
if (m_fonts[i]->font_is(font_signature)) int idx = find_font(font_signature);
return int(i); 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;
}
} }
return -1;
}
private: //--------------------------------------------------------------------
font_cache** m_fonts; const font_cache* font() const
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_cur_font;
return m_last_glyph = gl;
} }
else
//--------------------------------------------------------------------
const glyph_cache* find_glyph(unsigned glyph_code) const
{ {
if (m_engine.prepare_glyph(glyph_code)) 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; m_prev_glyph = m_last_glyph;
m_last_glyph = m_fonts.cache_glyph(glyph_code, return m_last_glyph = gl;
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
return 0;
}
//--------------------------------------------------------------------
void init_embedded_adaptors(const glyph_cache* gl, double x, double y, double scale = 1.0)
{
if (gl)
{
switch (gl->data_type)
{ {
default: if(m_engine.prepare_glyph(glyph_code))
return; {
m_prev_glyph = m_last_glyph;
m_last_glyph = m_fonts.cache_glyph(glyph_code,
m_engine.glyph_index(),
m_engine.data_size(),
m_engine.data_type(),
m_engine.bounds(),
m_engine.advance_x(),
m_engine.advance_y());
m_engine.write_glyph_to(m_last_glyph->data);
return m_last_glyph;
}
}
return 0;
}
//--------------------------------------------------------------------
void init_embedded_adaptors(const glyph_cache* gl,
double x, double y,
double scale=1.0)
{
if(gl)
{
switch(gl->data_type)
{
default: return;
case glyph_data_mono: 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;
@ -289,76 +331,79 @@ class font_cache_manager
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; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
const glyph_cache* perv_glyph() const { return m_prev_glyph; } path_adaptor_type& path_adaptor() { return m_path_adaptor; }
const glyph_cache* last_glyph() const { return m_last_glyph; } 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; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
bool add_kerning(double* x, double* y) const glyph_cache* perv_glyph() const { return m_prev_glyph; }
{ const glyph_cache* last_glyph() const { return m_last_glyph; }
if (m_prev_glyph && m_last_glyph)
//--------------------------------------------------------------------
bool add_kerning(double* x, double* y)
{ {
return m_engine.add_kerning(m_prev_glyph->glyph_index, m_last_glyph->glyph_index, x, y); if(m_prev_glyph && m_last_glyph)
{
return m_engine.add_kerning(m_prev_glyph->glyph_index,
m_last_glyph->glyph_index,
x, y);
}
return false;
} }
return false;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void precache(unsigned from, unsigned to) void precache(unsigned from, unsigned to)
{
for (; from <= to; ++from)
glyph(from);
}
//--------------------------------------------------------------------
void reset_cache()
{
m_fonts.font(m_engine.font_signature(), true);
m_change_stamp = m_engine.change_stamp();
m_prev_glyph = m_last_glyph = 0;
}
private:
//--------------------------------------------------------------------
font_cache_manager(const self_type&);
const self_type& operator=(const self_type&);
//--------------------------------------------------------------------
void synchronize()
{
if (m_change_stamp != m_engine.change_stamp())
{ {
m_fonts.font(m_engine.font_signature()); for(; from <= to; ++from) glyph(from);
}
//--------------------------------------------------------------------
void reset_cache()
{
m_fonts.font(m_engine.font_signature(), true);
m_change_stamp = m_engine.change_stamp(); m_change_stamp = m_engine.change_stamp();
m_prev_glyph = m_last_glyph = 0; m_prev_glyph = m_last_glyph = 0;
} }
}
font_cache_pool m_fonts; private:
font_engine_type& m_engine; //--------------------------------------------------------------------
int m_change_stamp; font_cache_manager(const self_type&);
double m_dx; const self_type& operator = (const self_type&);
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,135 +19,116 @@
#include <cmath> #include <cmath>
#include "agg_basics.h" #include "agg_basics.h"
namespace agg { namespace agg
//===============================================================gamma_none
struct gamma_none
{ {
double operator()(double x) const { return x; } //===============================================================gamma_none
}; 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
{ {
if (x == 0.0) double operator()(double x) const { return x; }
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);
} }
private: inline double linear_to_sRGB(double x)
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; return (x <= 0.0031308) ? (x * 12.92) : (1.055 * pow(x, 1 / 2.4) - 0.055);
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,247 +20,286 @@
#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
{ {
public: template<class LoResT=int8u,
typedef gamma_lut<LoResT, HiResT, GammaShift, HiResShift> self_type; class HiResT=int8u,
unsigned GammaShift=8,
enum gamma_scale_e { gamma_shift = GammaShift, gamma_size = 1 << gamma_shift, gamma_mask = gamma_size - 1 }; unsigned HiResShift=8> class gamma_lut
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); public:
pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size); typedef gamma_lut<LoResT, HiResT, GammaShift, HiResShift> self_type;
}
gamma_lut() enum gamma_scale_e
: 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)); 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()
{
pod_allocator<LoResT>::deallocate(m_inv_gamma, hi_res_size);
pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size);
} }
for (i = 0; i < hi_res_size; i++) 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))
{ {
m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift)); unsigned i;
} for(i = 0; i < gamma_size; i++)
} {
m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift));
}
gamma_lut(double g) for(i = 0; i < hi_res_size; i++)
: m_gamma(1.0) {
, m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)) m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift));
, 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; gamma_lut(double g) :
for (i = 0; i < hi_res_size; i++) m_gamma(1.0),
m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
{ {
m_inv_gamma[i] = (LoResT)uround(pow(i / double(hi_res_mask), inv_g) * double(gamma_mask)); gamma(g);
} }
}
double gamma() const { return m_gamma; } void gamma(double g)
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
{
// Unrolled binary search.
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:
LinearType m_dir_table[256];
LinearType m_inv_table[256];
// 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:
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_gamma = g;
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<> unsigned i;
class sRGB_lut<int16u> : public sRGB_lut_base<int16u> for(i = 0; i < gamma_size; i++)
{ {
public: m_dir_gamma[i] = (HiResT)
sRGB_lut() uround(pow(i / double(gamma_mask), m_gamma) * double(hi_res_mask));
{ }
// Generate lookup tables.
m_dir_table[0] = 0; double inv_g = 1.0 / g;
m_inv_table[0] = 0; for(i = 0; i < hi_res_size; i++)
for (unsigned i = 1; i <= 255; ++i) {
m_inv_gamma[i] = (LoResT)
uround(pow(i / double(hi_res_mask), inv_g) * double(gamma_mask));
}
}
double gamma() const
{ {
// 16-bit RGB is in range [0,65535]. return m_gamma;
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<> HiResT dir(LoResT v) const
class sRGB_lut<int8u> : public sRGB_lut_base<int8u>
{
public:
sRGB_lut()
{
// Generate lookup tables.
m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{ {
// 8-bit RGB is handled with simple bidirectional lookup tables. return m_dir_gamma[unsigned(v)];
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));
} }
}
int8u inv(int8u v) const 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
{ {
// In this case, the inverse transform is a simple lookup. public:
return m_inv_table[v]; LinearType dir(int8u v) const
} {
}; return m_dir_table[v];
}
// Common base class for sRGB_conv objects. Defines an internal int8u inv(LinearType v) const
// sRGB_lut object so that users don't have to. {
template<class T> // Unrolled binary search.
class sRGB_conv_base int8u x = 0;
{ if (v > m_inv_table[128]) x = 128;
public: if (v > m_inv_table[x + 64]) x += 64;
static T rgb_from_sRGB(int8u x) { return lut.dir(x); } 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;
}
static int8u rgb_to_sRGB(T x) { return lut.inv(x); } protected:
LinearType m_dir_table[256];
LinearType m_inv_table[256];
private: // Only derived classes may instantiate.
static sRGB_lut<T> lut; sRGB_lut_base()
}; {
}
};
// Definition of sRGB_conv_base::lut. Due to the fact that this a template, // sRGB_lut - implements sRGB conversion for the various types.
// we don't need to place the definition in a cpp file. Hurrah. // Base template is undefined, specializations are provided below.
template<class T> template<class LinearType>
sRGB_lut<T> sRGB_conv_base<T>::lut; class sRGB_lut;
// Wrapper for sRGB-linear conversion. template<>
// Base template is undefined, specializations are provided below. class sRGB_lut<float> : public sRGB_lut_base<float>
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) public:
return 0; sRGB_lut()
else if (x >= 1) {
return 255; // Generate lookup tables.
else m_dir_table[0] = 0;
return int8u(0.5 + x * 255); 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<> template<>
class sRGB_conv<int16u> : public sRGB_conv_base<int16u> class sRGB_lut<int16u> : public sRGB_lut_base<int16u>
{ {
public: public:
static int16u alpha_from_sRGB(int8u x) { return (x << 8) | x; } 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));
}
}
};
static int8u alpha_to_sRGB(int16u x) { return x >> 8; } template<>
}; class sRGB_lut<int8u> : public sRGB_lut_base<int8u>
{
public:
sRGB_lut()
{
// Generate lookup tables.
m_dir_table[0] = 0;
m_inv_table[0] = 0;
for (unsigned i = 1; i <= 255; ++i)
{
// 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));
}
}
template<> int8u inv(int8u v) const
class sRGB_conv<int8u> : public sRGB_conv_base<int8u> {
{ // In this case, the inverse transform is a simple lookup.
public: return m_inv_table[v];
static int8u alpha_from_sRGB(int8u x) { return x; } }
};
static int8u alpha_to_sRGB(int8u x) { return x; } // Common base class for sRGB_conv objects. Defines an internal
}; // sRGB_lut object so that users don't have to.
} // namespace agg 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;
}
};
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -19,134 +19,137 @@
#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
struct glyph_rect template<class ColorT> class glyph_raster_bin
{ {
int x1, y1, x2, y2; public:
double dx, dy; typedef ColorT color_type;
//--------------------------------------------------------------------
struct glyph_rect
{
int x1,y1,x2,y2;
double dx, dy;
};
//--------------------------------------------------------------------
glyph_raster_bin(const int8u* font) :
m_font(font),
m_big_endian(false)
{
int t = 1;
if(*(char*)&t == 0) m_big_endian = true;
memset(m_span, 0, sizeof(m_span));
}
//--------------------------------------------------------------------
const int8u* font() const { return m_font; }
void font(const int8u* f) { m_font = f; }
//--------------------------------------------------------------------
double height() const { return m_font[0]; }
double base_line() const { return m_font[1]; }
//--------------------------------------------------------------------
template<class CharT>
double width(const CharT* str) const
{
unsigned start_char = m_font[2];
unsigned num_chars = m_font[3];
unsigned w = 0;
while(*str)
{
unsigned glyph = *str;
const int8u* bits = m_font + 4 + num_chars * 2 +
value(m_font + 4 + (glyph - start_char) * 2);
w += *bits;
++str;
}
return w;
}
//--------------------------------------------------------------------
void prepare(glyph_rect* r, double x, double y, unsigned glyph, bool flip)
{
unsigned start_char = m_font[2];
unsigned num_chars = m_font[3];
m_bits = m_font + 4 + num_chars * 2 +
value(m_font + 4 + (glyph - start_char) * 2);
m_glyph_width = *m_bits++;
m_glyph_byte_width = (m_glyph_width + 7) >> 3;
r->x1 = int(x);
r->x2 = r->x1 + m_glyph_width - 1;
if(flip)
{
r->y1 = int(y) - m_font[0] + m_font[1];
r->y2 = r->y1 + m_font[0] - 1;
}
else
{
r->y1 = int(y) - m_font[1] + 1;
r->y2 = r->y1 + m_font[0] - 1;
}
r->dx = m_glyph_width;
r->dy = 0;
}
//--------------------------------------------------------------------
const cover_type* span(unsigned i)
{
i = m_font[0] - i - 1;
const int8u* bits = m_bits + i * m_glyph_byte_width;
unsigned j;
unsigned val = *bits;
unsigned nb = 0;
for(j = 0; j < m_glyph_width; ++j)
{
m_span[j] = (cover_type)((val & 0x80) ? cover_full : cover_none);
val <<= 1;
if(++nb >= 8)
{
val = *++bits;
nb = 0;
}
}
return m_span;
}
private:
//--------------------------------------------------------------------
int16u value(const int8u* p) const
{
int16u v;
if(m_big_endian)
{
*(int8u*)&v = p[1];
*((int8u*)&v + 1) = p[0];
}
else
{
*(int8u*)&v = p[0];
*((int8u*)&v + 1) = p[1];
}
return v;
}
//--------------------------------------------------------------------
const int8u* m_font;
bool m_big_endian;
cover_type m_span[32];
const int8u* m_bits;
unsigned m_glyph_width;
unsigned m_glyph_byte_width;
}; };
//--------------------------------------------------------------------
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -21,200 +21,226 @@
#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(const color_type& c1, const color_type& c2, unsigned len) //======================================================color_interpolator
: m_c1(c1) template<class ColorT> struct color_interpolator
, 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; public:
++g; typedef ColorT color_type;
++b;
++a;
}
color_type color() const { return color_type(r.y(), g.y(), b.y(), a.y()); } color_interpolator(const color_type& c1,
const color_type& c2,
unsigned len) :
m_c1(c1),
m_c2(c2),
m_len(len),
m_count(0)
{}
private: void operator ++ ()
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) ++m_count;
offset = 0.0;
if (offset > 1.0)
offset = 1.0;
} }
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;
}; };
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; } // Fast specialization for rgba8
template<> struct color_interpolator<rgba8>
//--------------------------------------------------------------------
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; public:
unsigned start = uround(m_color_profile[0].offset * color_lut_size); typedef rgba8 color_type;
unsigned end = 0;
color_type c = m_color_profile[0].color; color_interpolator(const color_type& c1,
for (i = 0; i < start; i++) 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 ++ ()
{ {
m_color_lut[i] = c; ++r; ++g; ++b; ++a;
} }
for (i = 1; i < m_color_profile.size(); i++)
color_type color() const
{ {
end = uround(m_color_profile[i].offset * color_lut_size); return color_type(r.y(), g.y(), b.y(), a.y());
interpolator_type ci(m_color_profile[i - 1].color, m_color_profile[i].color, end - start + 1); }
while (start < end)
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)
{ {
m_color_lut[start] = ci.color(); if(offset < 0.0) offset = 0.0;
++ci; if(offset > 1.0) offset = 1.0;
++start;
} }
} };
c = m_color_profile.last().color; typedef agg::pod_bvector<color_point, 4> color_profile_type;
for (; end < m_color_lut.size(); end++) typedef agg::pod_array<color_type> color_lut_type;
static bool offset_less(const color_point& a, const color_point& b)
{ {
m_color_lut[end] = c; return a.offset < b.offset;
} }
return true; 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;
} }
return false;
} }
} // namespace agg
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -24,107 +24,130 @@
#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();
void font(const void* font); //---------------------------------------------------------------gsv_text
void flip(bool flip_y) { m_flip = flip_y; } //
void load_font(const char* file); // See Implementation agg_gsv_text.cpp
void size(double height, double width = 0.0); //
void space(double space); class gsv_text
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; enum status
if (m_big_endian)
{ {
*(int8u*)&v = p[1]; initial,
*((int8u*)&v + 1) = p[0]; next_char,
} start_glyph,
else 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
{ {
*(int8u*)&v = p[0]; int16u v;
*((int8u*)&v + 1) = p[1]; 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;
} }
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); }
void rewind(unsigned path_id) //--------------------------------------------------------gsv_text_outline
template<class Transformer = trans_affine> class gsv_text_outline
{ {
m_trans.rewind(path_id); public:
m_polyline.line_join(round_join); gsv_text_outline(gsv_text& text, const Transformer& trans) :
m_polyline.line_cap(round_cap); m_polyline(text),
} m_trans(m_polyline, trans)
{
}
unsigned vertex(double* x, double* y) { return m_trans.vertex(x, y); } void width(double w)
{
m_polyline.width(w);
}
private: void transformer(const Transformer* trans)
conv_stroke<gsv_text> m_polyline; {
conv_transform<conv_stroke<gsv_text>, Transformer> m_trans; m_trans->transformer(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,439 +18,464 @@
#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
explicit image_accessor_clip(const pixfmt_type& pixf, const color_type& bk) template<class PixFmt> class image_accessor_clip
: m_pixf(&pixf)
{ {
pixfmt_type::make_pix(m_bk_buf, bk); 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 };
void attach(const pixfmt_type& pixf) { m_pixf = &pixf; } image_accessor_clip() {}
explicit image_accessor_clip(const pixfmt_type& pixf,
void background_color(const color_type& bk) { pixfmt_type::make_pix(m_bk_buf, bk); } const color_type& bk) :
m_pixf(&pixf)
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); pixfmt_type::make_pix(m_bk_buf, bk);
} }
return m_bk_buf;
}
public: void attach(const pixfmt_type& pixf)
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_pixf = &pixf;
}
void background_color(const color_type& bk)
{
pixfmt_type::make_pix(m_bk_buf, bk);
}
private:
AGG_INLINE const int8u* pixel() const
{
if(m_y >= 0 && m_y < (int)m_pixf->height() &&
m_x >= 0 && m_x < (int)m_pixf->width())
{
return m_pixf->pix_ptr(m_x, m_y);
}
return m_bk_buf;
}
public:
AGG_INLINE const int8u* span(int x, int y, unsigned len)
{
m_x = m_x0 = x;
m_y = y;
if(y >= 0 && y < (int)m_pixf->height() &&
x >= 0 && x+(int)len <= (int)m_pixf->width())
{
return m_pix_ptr = m_pixf->pix_ptr(x, y);
}
m_pix_ptr = 0;
return pixel();
}
AGG_INLINE const int8u* next_x()
{
if(m_pix_ptr) return m_pix_ptr += pix_width;
++m_x;
return pixel();
}
AGG_INLINE const int8u* next_y()
{
++m_y;
m_x = m_x0;
if(m_pix_ptr &&
m_y >= 0 && m_y < (int)m_pixf->height())
{
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
}
m_pix_ptr = 0;
return pixel();
}
private:
const pixfmt_type* m_pixf;
int8u m_bk_buf[4];
int m_x, m_x0, m_y;
const int8u* m_pix_ptr;
};
//--------------------------------------------------image_accessor_no_clip
template<class PixFmt> class image_accessor_no_clip
{
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_no_clip() {}
explicit image_accessor_no_clip(const pixfmt_type& pixf) :
m_pixf(&pixf)
{}
void attach(const pixfmt_type& pixf)
{
m_pixf = &pixf;
}
AGG_INLINE const int8u* span(int x, int y, unsigned)
{
m_x = x;
m_y = y;
return m_pix_ptr = m_pixf->pix_ptr(x, y); 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;
++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 += pix_width;
}
AGG_INLINE const int8u* next_y()
{
++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;
int8u m_bk_buf[4]; int m_x, m_y;
int m_x, m_x0, m_y; const int8u* m_pix_ptr;
const int8u* m_pix_ptr; };
};
//--------------------------------------------------image_accessor_no_clip
template<class PixFmt>
class image_accessor_no_clip
{
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_no_clip() {}
explicit image_accessor_no_clip(const pixfmt_type& pixf)
: m_pixf(&pixf)
{}
void attach(const pixfmt_type& pixf) { m_pixf = &pixf; }
AGG_INLINE const int8u* span(int x, int y, unsigned) //----------------------------------------------------image_accessor_clone
template<class PixFmt> class image_accessor_clone
{ {
m_x = x; public:
m_y = y; typedef PixFmt pixfmt_type;
return m_pix_ptr = m_pixf->pix_ptr(x, 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 };
AGG_INLINE const int8u* next_x() { return m_pix_ptr += pix_width; } image_accessor_clone() {}
explicit image_accessor_clone(const pixfmt_type& pixf) :
m_pixf(&pixf)
{}
AGG_INLINE const int8u* next_y() void attach(const pixfmt_type& pixf)
{
++m_y;
return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y);
}
private:
const pixfmt_type* m_pixf;
int m_x, m_y;
const int8u* m_pix_ptr;
};
//----------------------------------------------------image_accessor_clone
template<class PixFmt>
class image_accessor_clone
{
public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::order_type order_type;
typedef typename pixfmt_type::value_type value_type;
enum pix_width_e { pix_width = pixfmt_type::pix_width };
image_accessor_clone() {}
explicit image_accessor_clone(const pixfmt_type& pixf)
: m_pixf(&pixf)
{}
void attach(const pixfmt_type& pixf) { m_pixf = &pixf; }
private:
AGG_INLINE const int8u* pixel() const
{
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_pixf = &pixf;
} }
m_pix_ptr = 0;
return pixel();
}
AGG_INLINE const int8u* next_x() private:
{ AGG_INLINE const int8u* pixel() const
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); 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);
} }
m_pix_ptr = 0;
return pixel();
}
private: public:
const pixfmt_type* m_pixf; AGG_INLINE const int8u* span(int x, int y, unsigned len)
int m_x, m_x0, m_y; {
const int8u* m_pix_ptr; 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();
}
//-----------------------------------------------------image_accessor_wrap AGG_INLINE const int8u* next_x()
template<class PixFmt, class WrapX, class WrapY> {
class image_accessor_wrap if(m_pix_ptr) return m_pix_ptr += pix_width;
{ ++m_x;
public: return pixel();
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() {} AGG_INLINE const int8u* next_y()
explicit image_accessor_wrap(const pixfmt_type& pixf) {
: m_pixf(&pixf) ++m_y;
, m_wrap_x(pixf.width()) m_x = m_x0;
, m_wrap_y(pixf.height()) 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();
}
void attach(const pixfmt_type& pixf) { m_pixf = &pixf; } private:
const pixfmt_type* m_pixf;
int m_x, m_x0, m_y;
const int8u* m_pix_ptr;
};
AGG_INLINE const int8u* span(int x, int y, unsigned)
//-----------------------------------------------------image_accessor_wrap
template<class PixFmt, class WrapX, class WrapY> class image_accessor_wrap
{ {
m_x = x; public:
m_row_ptr = m_pixf->row_ptr(m_wrap_y(y)); typedef PixFmt pixfmt_type;
return m_row_ptr + m_wrap_x(x) * pix_width; 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* next_x() 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
{ {
int x = ++m_wrap_x; public:
return m_row_ptr + x * pix_width; wrap_mode_repeat() {}
} wrap_mode_repeat(unsigned size) :
m_size(size),
m_add(size * (0x3FFFFFFF / size)),
m_value(0)
{}
AGG_INLINE const int8u* next_y() 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
{ {
m_row_ptr = m_pixf->row_ptr(++m_wrap_y); public:
return m_row_ptr + m_wrap_x(m_x) * pix_width; wrap_mode_repeat_pow2() {}
} wrap_mode_repeat_pow2(unsigned size) : m_value(0)
{
private: m_mask = 1;
const pixfmt_type* m_pixf; while(m_mask < size) m_mask = (m_mask << 1) | 1;
const int8u* m_row_ptr; m_mask >>= 1;
int m_x; }
WrapX m_wrap_x; AGG_INLINE unsigned operator() (int v)
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++()
{
++m_value;
if (m_value >= m_size)
m_value = 0;
return m_value;
}
private:
unsigned m_size;
unsigned m_add;
unsigned m_mask;
unsigned m_value;
};
//-------------------------------------------------------wrap_mode_reflect
class wrap_mode_reflect
{
public:
wrap_mode_reflect() {}
wrap_mode_reflect(unsigned size)
: m_size(size)
, m_size2(size * 2)
, m_add(m_size2 * (0x3FFFFFFF / m_size2))
, m_value(0)
{}
AGG_INLINE unsigned operator()(int v)
{
m_value = (unsigned(v) + m_add) % m_size2;
if (m_value >= m_size)
return m_size2 - m_value - 1;
return m_value;
}
AGG_INLINE unsigned operator++()
{
++m_value;
if (m_value >= m_size2)
m_value = 0;
if (m_value >= m_size)
return m_size2 - m_value - 1;
return m_value;
}
private:
unsigned m_size;
unsigned m_size2;
unsigned m_add;
unsigned m_value;
};
//--------------------------------------------------wrap_mode_reflect_pow2
class wrap_mode_reflect_pow2
{
public:
wrap_mode_reflect_pow2() {}
wrap_mode_reflect_pow2(unsigned size)
: m_value(0)
{
m_mask = 1;
m_size = 1;
while (m_mask < size)
{
m_mask = (m_mask << 1) | 1;
m_size <<= 1;
} }
} AGG_INLINE unsigned operator++ ()
AGG_INLINE unsigned operator()(int v) {
++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
{ {
m_value = unsigned(v) & m_mask; public:
if (m_value >= m_size) wrap_mode_repeat_auto_pow2() {}
return m_mask - m_value; wrap_mode_repeat_auto_pow2(unsigned size) :
return m_value; m_size(size),
} m_add(size * (0x3FFFFFFF / size)),
AGG_INLINE unsigned operator++() m_mask((m_size & (m_size-1)) ? 0 : m_size-1),
m_value(0)
{}
AGG_INLINE unsigned operator() (int v)
{
if(m_mask) return m_value = unsigned(v) & m_mask;
return m_value = (unsigned(v) + m_add) % m_size;
}
AGG_INLINE unsigned operator++ ()
{
++m_value;
if(m_value >= m_size) m_value = 0;
return m_value;
}
private:
unsigned m_size;
unsigned m_add;
unsigned m_mask;
unsigned m_value;
};
//-------------------------------------------------------wrap_mode_reflect
class wrap_mode_reflect
{ {
++m_value; public:
m_value &= m_mask; wrap_mode_reflect() {}
if (m_value >= m_size) wrap_mode_reflect(unsigned size) :
return m_mask - m_value; m_size(size),
return m_value; m_size2(size * 2),
} m_add(m_size2 * (0x3FFFFFFF / m_size2)),
m_value(0)
{}
private: AGG_INLINE unsigned operator() (int v)
unsigned m_size; {
unsigned m_mask; m_value = (unsigned(v) + m_add) % m_size2;
unsigned m_value; if(m_value >= m_size) return m_size2 - m_value - 1;
}; return m_value;
}
//---------------------------------------------wrap_mode_reflect_auto_pow2 AGG_INLINE unsigned operator++ ()
class wrap_mode_reflect_auto_pow2 {
{ ++m_value;
public: if(m_value >= m_size2) m_value = 0;
wrap_mode_reflect_auto_pow2() {} if(m_value >= m_size) return m_size2 - m_value - 1;
wrap_mode_reflect_auto_pow2(unsigned size) return m_value;
: m_size(size) }
, m_size2(size * 2) private:
, m_add(m_size2 * (0x3FFFFFFF / m_size2)) unsigned m_size;
, m_mask((m_size2 & (m_size2 - 1)) ? 0 : m_size2 - 1) unsigned m_size2;
, m_value(0) unsigned m_add;
{} unsigned m_value;
};
AGG_INLINE unsigned operator()(int v)
//--------------------------------------------------wrap_mode_reflect_pow2
class wrap_mode_reflect_pow2
{ {
m_value = m_mask ? unsigned(v) & m_mask : (unsigned(v) + m_add) % m_size2; public:
if (m_value >= m_size) wrap_mode_reflect_pow2() {}
return m_size2 - m_value - 1; wrap_mode_reflect_pow2(unsigned size) : m_value(0)
return m_value; {
} m_mask = 1;
AGG_INLINE unsigned operator++() m_size = 1;
while(m_mask < size)
{
m_mask = (m_mask << 1) | 1;
m_size <<= 1;
}
}
AGG_INLINE unsigned operator() (int v)
{
m_value = unsigned(v) & m_mask;
if(m_value >= m_size) return m_mask - m_value;
return m_value;
}
AGG_INLINE unsigned operator++ ()
{
++m_value;
m_value &= m_mask;
if(m_value >= m_size) return m_mask - m_value;
return m_value;
}
private:
unsigned m_size;
unsigned m_mask;
unsigned m_value;
};
//---------------------------------------------wrap_mode_reflect_auto_pow2
class wrap_mode_reflect_auto_pow2
{ {
++m_value; public:
if (m_value >= m_size2) wrap_mode_reflect_auto_pow2() {}
m_value = 0; wrap_mode_reflect_auto_pow2(unsigned size) :
if (m_value >= m_size) m_size(size),
return m_size2 - m_value - 1; m_size2(size * 2),
return m_value; m_add(m_size2 * (0x3FFFFFFF / m_size2)),
} m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1),
m_value(0)
{}
private: AGG_INLINE unsigned operator() (int v)
unsigned m_size; {
unsigned m_size2; m_value = m_mask ? unsigned(v) & m_mask :
unsigned m_add; (unsigned(v) + m_add) % m_size2;
unsigned m_mask; if(m_value >= m_size) return m_size2 - m_value - 1;
unsigned m_value; 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

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

View file

@ -18,157 +18,172 @@
#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 - static_cast<line_subpixel_scale_e>(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 - static_cast<line_subpixel_scale_e>(line_mr_subpixel_shift));
}
//-------------------------------------------------------------------line_hr
AGG_INLINE int line_hr(int x)
{
return x << (line_subpixel_shift - static_cast<line_subpixel_scale_e>(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 * static_cast<double>(line_subpixel_scale));
}
};
//-----------------------------------------------------------line_coord_sat
struct line_coord_sat
{
AGG_INLINE static int conv(double x)
{
return saturation<line_max_coord>::iround(x * static_cast<double>(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 - static_cast<line_subpixel_scale_e>(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 * static_cast<double>(line_subpixel_scale)); }
};
//-----------------------------------------------------------line_coord_sat
struct line_coord_sat
{
AGG_INLINE static int conv(double x)
{
return saturation<line_max_coord>::iround(x * static_cast<double>(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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -12,7 +12,7 @@
// mcseemagg@yahoo.com // mcseemagg@yahoo.com
// http://www.antigrain.com // http://www.antigrain.com
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Bessel function (besj) was adapted for use in AGG library by Andy Wilk // Bessel function (besj) was adapted for use in AGG library by Andy Wilk
// Contact: castor.vulgaris@gmail.com // Contact: castor.vulgaris@gmail.com
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -22,236 +22,251 @@
#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);
}
//--------------------------------------------------------point_in_triangle //------------------------------------------------------vertex_dist_epsilon
AGG_INLINE bool point_in_triangle(double x1, double y1, double x2, double y2, double x3, double y3, double x, double y) // Coinciding points maximal distance (Epsilon)
{ 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;
}
//-----------------------------------------------------------calc_distance //-----------------------------------------------------intersection_epsilon
AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2) // See calc_intersection
{ const double intersection_epsilon = 1.0e-30;
double dx = x2 - x1;
double dy = y2 - y1;
return sqrt(dx * dx + dy * dy);
}
//--------------------------------------------------------calc_sq_distance //------------------------------------------------------------cross_product
AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2) AGG_INLINE double cross_product(double x1, double y1,
{ double x2, double y2,
double dx = x2 - x1; double x, double y)
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 calc_distance(x1, y1, x, y); return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
}
return ((x - x2) * dy - (y - y2) * dx) / d;
}
//-------------------------------------------------------calc_line_point_u
AGG_INLINE double calc_segment_point_u(double x1, double y1, double x2, double y2, double x, double y)
{
double dx = x2 - x1;
double dy = y2 - y1;
if (dx == 0 && dy == 0)
{
return 0;
} }
double pdx = x - x1; //--------------------------------------------------------point_in_triangle
double pdy = y - y1; AGG_INLINE bool point_in_triangle(double x1, double y1,
double x2, double y2,
return (pdx * dx + pdy * dy) / (dx * dx + dy * dy); double x3, double y3,
} double x, double y)
//---------------------------------------------calc_line_point_sq_distance
AGG_INLINE double
calc_segment_point_sq_distance(double x1, double y1, double x2, double y2, double x, double y, double u)
{
if (u <= 0)
{ {
return calc_sq_distance(x, y, x1, y1); 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;
} }
else if (u >= 1)
//-----------------------------------------------------------calc_distance
AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2)
{ {
return calc_sq_distance(x, y, x2, y2); double dx = x2-x1;
double dy = y2-y1;
return sqrt(dx * dx + dy * dy);
} }
return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1));
}
//---------------------------------------------calc_line_point_sq_distance //--------------------------------------------------------calc_sq_distance
AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, double x2, double y2, double x, double y) AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2)
{
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) 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)
{ {
d = -d; return calc_distance(x1, y1, x, y);
} }
calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1); return ((x - x2) * dy - (y - y2) * dx) / d;
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 //-------------------------------------------------------calc_line_point_u
AGG_INLINE double calc_triangle_area(double x1, double y1, double x2, double y2, double x3, double y3) AGG_INLINE double calc_segment_point_u(double x1, double y1,
{ double x2, double y2,
return (x1 * y2 - x2 * y1 + x2 * y3 - x3 * y2 + x3 * y1 - x1 * y3) * 0.5; double x, double y)
}
//-------------------------------------------------------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]; double dx = x2 - x1;
sum += x * v.y - y * v.x; double dy = y2 - y1;
x = v.x;
y = v.y; if(dx == 0 && dy == 0)
{
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
// Tables for fast sqrt AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
extern int16u g_sqrt_table[1024]; double x2, double y2,
extern int8 g_elder_bit_table[256]; double x, double y,
double u)
{
if(u <= 0)
{
return calc_sq_distance(x, y, x1, y1);
}
else
if(u >= 1)
{
return calc_sq_distance(x, y, x2, y2);
}
return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1));
}
//---------------------------------------------------------------fast_sqrt //---------------------------------------------calc_line_point_sq_distance
// Fast integer Sqrt - really fast: no cycles, divisions or multiplications AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1,
#if defined(_MSC_VER) double x2, double y2,
#pragma warning(push) double x, double y)
#pragma warning(disable: 4035) // Disable warning "no return value" {
#endif return
AGG_INLINE unsigned fast_sqrt(unsigned val) calc_segment_point_sq_distance(
{ x1, y1, x2, y2, x, y,
#if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM) calc_segment_point_u(x1, y1, x2, y2, x, y));
// 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 //-------------------------------------------------------calc_intersection
//(and maybe compilers) the pure C "#else" section is used. AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by,
__asm { 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)
{
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
@ -267,153 +282,156 @@ AGG_INLINE unsigned fast_sqrt(unsigned val)
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] + 16; bit = g_elder_bit_table[bit] + 24;
} }
else else
{ {
bit = (t >> 8) & 0xFF; bit = (t >> 16) & 0xFF;
if (bit) if(bit)
{ {
bit = g_elder_bit_table[bit] + 8; bit = g_elder_bit_table[bit] + 16;
} }
else else
{ {
bit = g_elder_bit_table[t]; bit = (t >> 8) & 0xFF;
if(bit)
{
bit = g_elder_bit_table[bit] + 8;
}
else
{
bit = g_elder_bit_table[t];
}
} }
} }
}
// This code calculates the sqrt. //This code calculates the sqrt.
bit -= 9; bit -= 9;
if (bit > 0) 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
//--------------------------------------------------------------------besj
// Function BESJ calculates Bessel function of first kind of order n
// Arguments:
// n - an integer (>=0), the order
// x - value at which the Bessel function is required
//--------------------
// C++ Mathematical Library
// Convereted from equivalent FORTRAN library
// Converetd by Gareth Walker for use by course 392 computational project
// All functions tested and yield the same results as the corresponding
// FORTRAN versions.
//
// If you have any problems using these functions please report them to
// M.Muldoon@UMIST.ac.uk
//
// Documentation available on the web
// http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html
// Version 1.0 8/98
// 29 October, 1999
//--------------------
// Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com)
//------------------------------------------------------------------------
inline double besj(double x, int n)
{
if (n < 0)
{
return 0;
}
double d = 1E-6;
double b = 0;
if (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)
{ {
m8 = -1; bit = (bit >> 1) + (bit & 1);
shift -= bit;
val >>= (bit << 1);
} }
int imax = m2 - 2; return g_sqrt_table[val] >> shift;
for (int i = 1; i <= imax; i++) #endif
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
//--------------------------------------------------------------------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)
{ {
double c6 = 2 * (m2 - i) * c2 / x - c3; return 0;
c3 = c2; }
c2 = c6; double d = 1E-6;
if (m2 - i - 1 == n) 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)
{
m8 = -1;
}
int imax = m2 - 2;
for (int i = 1; i <= imax; i++)
{
double c6 = 2 * (m2 - i) * c2 / x - c3;
c3 = c2;
c2 = c6;
if(m2 - i - 1 == n)
{
b = c6;
}
m8 = -1 * m8;
if (m8 > 0)
{
c4 = c4 + 2 * c6;
}
}
double c6 = 2 * c2 / x - c3;
if(n == 0)
{ {
b = c6; b = c6;
} }
m8 = -1 * m8; c4 += c6;
if (m8 > 0) b /= c4;
if(std::fabs(b - b1) < d)
{ {
c4 = c4 + 2 * c6; return b;
} }
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,236 +23,254 @@
#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
{ {
public: //-------------------------------------------------------------line_cap_e
typedef typename VertexConsumer::value_type coord_type; enum line_cap_e
math_stroke();
void line_cap(line_cap_e lc) { m_line_cap = lc; }
void line_join(line_join_e lj) { m_line_join = lj; }
void inner_join(inner_join_e ij) { m_inner_join = ij; }
line_cap_e line_cap() const { return m_line_cap; }
line_join_e line_join() const { return m_line_join; }
inner_join_e inner_join() const { return m_inner_join; }
void width(double w);
void miter_limit(double ml) { m_miter_limit = ml; }
void miter_limit_theta(double t);
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
void approximation_scale(double as) { m_approx_scale = as; }
double width() const { return m_width * 2.0; }
double miter_limit() const { return m_miter_limit; }
double inner_miter_limit() const { return m_inner_miter_limit; }
double approximation_scale() const { return m_approx_scale; }
void calc_cap(VertexConsumer& vc, const vertex_dist& v0, const vertex_dist& v1, double len);
void calc_join(VertexConsumer& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double len1,
double len2);
private:
AGG_INLINE void add_vertex(VertexConsumer& vc, double x, double y) { vc.add(coord_type(x, y)); }
void calc_arc(VertexConsumer& vc, double x, double y, double dx1, double dy1, double dx2, double dy2);
void calc_miter(VertexConsumer& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double dx1,
double dy1,
double dx2,
double dy2,
line_join_e lj,
double mlimit,
double dbevel);
double m_width;
double m_width_abs;
double m_width_eps;
int m_width_sign;
double m_miter_limit;
double m_inner_miter_limit;
double m_approx_scale;
line_cap_e m_line_cap;
line_join_e m_line_join;
inner_join_e m_inner_join;
};
//-----------------------------------------------------------------------
template<class VC>
math_stroke<VC>::math_stroke()
: m_width(0.5)
, m_width_abs(0.5)
, m_width_eps(0.5 / 1024.0)
, m_width_sign(1)
, m_miter_limit(4.0)
, m_inner_miter_limit(1.01)
, m_approx_scale(1.0)
, m_line_cap(butt_cap)
, m_line_join(miter_join)
, m_inner_join(inner_miter)
{}
//-----------------------------------------------------------------------
template<class VC>
void math_stroke<VC>::width(double w)
{
m_width = w * 0.5;
if (m_width < 0)
{ {
m_width_abs = -m_width; butt_cap,
m_width_sign = -1; square_cap,
} round_cap
else };
//------------------------------------------------------------line_join_e
enum line_join_e
{ {
m_width_abs = m_width; miter_join = 0,
m_width_sign = 1; miter_join_revert = 1,
} round_join = 2,
m_width_eps = m_width / 1024.0; bevel_join = 3,
} miter_join_round = 4
};
//-----------------------------------------------------------------------
template<class VC>
void math_stroke<VC>::miter_limit_theta(double t)
{
m_miter_limit = 1.0 / std::sin(t * 0.5);
}
//----------------------------------------------------------------------- //-----------------------------------------------------------inner_join_e
template<class VC> enum inner_join_e
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)
{ {
if (a1 > a2) inner_bevel,
a2 += 2 * pi; inner_miter,
n = int((a2 - a1) / da); inner_jag,
da = (a2 - a1) / (n + 1); inner_round
a1 += da; };
for (i = 0; i < n; i++)
//------------------------------------------------------------math_stroke
template<class VertexConsumer> class math_stroke
{
public:
typedef typename VertexConsumer::value_type coord_type;
math_stroke();
void line_cap(line_cap_e lc) { m_line_cap = lc; }
void line_join(line_join_e lj) { m_line_join = lj; }
void inner_join(inner_join_e ij) { m_inner_join = ij; }
line_cap_e line_cap() const { return m_line_cap; }
line_join_e line_join() const { return m_line_join; }
inner_join_e inner_join() const { return m_inner_join; }
void width(double w);
void miter_limit(double ml) { m_miter_limit = ml; }
void miter_limit_theta(double t);
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
void approximation_scale(double as) { m_approx_scale = as; }
double width() const { return m_width * 2.0; }
double miter_limit() const { return m_miter_limit; }
double inner_miter_limit() const { return m_inner_miter_limit; }
double approximation_scale() const { return m_approx_scale; }
void calc_cap(VertexConsumer& vc,
const vertex_dist& v0,
const vertex_dist& v1,
double len);
void calc_join(VertexConsumer& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double len1,
double len2);
private:
AGG_INLINE void add_vertex(VertexConsumer& vc, double x, double y)
{ {
add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width); vc.add(coord_type(x, y));
}
void calc_arc(VertexConsumer& vc,
double x, double y,
double dx1, double dy1,
double dx2, double dy2);
void calc_miter(VertexConsumer& vc,
const vertex_dist& v0,
const vertex_dist& v1,
const vertex_dist& v2,
double dx1, double dy1,
double dx2, double dy2,
line_join_e lj,
double mlimit,
double dbevel);
double m_width;
double m_width_abs;
double m_width_eps;
int m_width_sign;
double m_miter_limit;
double m_inner_miter_limit;
double m_approx_scale;
line_cap_e m_line_cap;
line_join_e m_line_join;
inner_join_e m_inner_join;
};
//-----------------------------------------------------------------------
template<class VC> math_stroke<VC>::math_stroke() :
m_width(0.5),
m_width_abs(0.5),
m_width_eps(0.5/1024.0),
m_width_sign(1),
m_miter_limit(4.0),
m_inner_miter_limit(1.01),
m_approx_scale(1.0),
m_line_cap(butt_cap),
m_line_join(miter_join),
m_inner_join(inner_miter)
{
}
//-----------------------------------------------------------------------
template<class VC> void math_stroke<VC>::width(double w)
{
m_width = w * 0.5;
if(m_width < 0)
{
m_width_abs = -m_width;
m_width_sign = -1;
}
else
{
m_width_abs = m_width;
m_width_sign = 1;
}
m_width_eps = m_width / 1024.0;
}
//-----------------------------------------------------------------------
template<class VC> void math_stroke<VC>::miter_limit_theta(double t)
{
m_miter_limit = 1.0 / 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)
{
if(a1 > a2) a2 += 2 * pi;
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++)
{ {
add_vertex(vc, x + std::cos(a1) * m_width, y + std::sin(a1) * m_width); if(a1 < a2) a2 -= 2 * pi;
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> template<class VC>
void math_stroke<VC>::calc_miter(VC& vc, void math_stroke<VC>::calc_miter(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 dx1, double dx1, double dy1,
double dy1, double dx2, double dy2,
double dx2, line_join_e lj,
double dy2, double mlimit,
line_join_e lj, double dbevel)
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 double xi = v1.x;
//--------------------- double yi = v1.y;
di = calc_distance(v1.x, v1.y, xi, yi); double di = 1;
if (di <= lim) 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))
{ {
// Inside the miter limit // Calculation of the intersection succeeded
//--------------------- //---------------------
add_vertex(vc, xi, yi); di = calc_distance(v1.x, v1.y, xi, yi);
miter_limit_exceeded = false; if(di <= lim)
{
// Inside the miter limit
//---------------------
add_vertex(vc, xi, yi);
miter_limit_exceeded = false;
}
intersection_failed = false;
} }
intersection_failed = false; else
}
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 // Calculation of the intersection failed, most probably
// the previous one (straight line) // the three points lie one straight line.
//----------------- // First check if v0 and v2 lie on the opposite sides of vector:
add_vertex(vc, v1.x + dx1, v1.y - dy1); // (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular
miter_limit_exceeded = false; // 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) if(miter_limit_exceeded)
{
// Miter limit exceeded
//------------------------
switch (lj)
{ {
// 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
@ -269,11 +287,13 @@ void math_stroke<VC>::calc_miter(VC& vc,
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, v1.y - dy1 + dx1 * mlimit); add_vertex(vc, v1.x + dx1 + dy1 * mlimit,
add_vertex(vc, v1.x + dx2 - dy2 * mlimit, v1.y - dy2 - dx2 * mlimit); v1.y - dy1 + dx1 * mlimit);
add_vertex(vc, v1.x + dx2 - dy2 * mlimit,
v1.y - dy2 - dx2 * mlimit);
} }
else else
{ {
@ -282,196 +302,208 @@ void math_stroke<VC>::calc_miter(VC& vc,
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, y1 + (yi - y1) * di); add_vertex(vc, x1 + (xi - x1) * di,
add_vertex(vc, x2 + (xi - x2) * di, y2 + (yi - y2) * di); y1 + (yi - y1) * di);
add_vertex(vc, x2 + (xi - x2) * di,
y2 + (yi - y2) * di);
} }
break; break;
}
}
}
//--------------------------------------------------------stroke_calc_cap
template<class VC>
void math_stroke<VC>::calc_cap(VC& vc, const vertex_dist& v0, const vertex_dist& v1, double len)
{
vc.remove_all();
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++)
{
add_vertex(vc, v0.x + std::cos(a1) * m_width, v0.y + std::sin(a1) * m_width);
a1 += da;
} }
} }
}
//--------------------------------------------------------stroke_calc_cap
template<class VC>
void math_stroke<VC>::calc_cap(VC& vc,
const vertex_dist& v0,
const vertex_dist& v1,
double len)
{
vc.remove_all();
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 else
{ {
a1 = std::atan2(-dy1, dx1); double da = std::acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
a1 -= da; double a1;
for (i = 0; i < n; i++) 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)
{ {
add_vertex(vc, v0.x + std::cos(a1) * m_width, v0.y + std::sin(a1) * m_width); 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;
}
} }
else
{
a1 = std::atan2(-dy1, dx1);
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)
{ {
// Inner join double dx1 = m_width * (v1.y - v0.y) / len1;
//--------------- double dy1 = m_width * (v1.x - v0.x) / len1;
double limit = ((len1 < len2) ? len1 : len2) / m_width_abs; double dx2 = m_width * (v2.y - v1.y) / len2;
if (limit < m_inner_miter_limit) double dy2 = m_width * (v2.x - v1.x) / len2;
{
limit = m_inner_miter_limit;
}
switch (m_inner_join) 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
//---------------
double limit = ((len1 < len2) ? len1 : len2) / m_width_abs;
if (limit < m_inner_miter_limit)
{
limit = m_inner_miter_limit;
}
switch(m_inner_join)
{
default: // inner_bevel 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, v0, v1, v2, dx1, dy1, dx2, dy2, miter_join_revert, limit, 0); calc_miter(vc,
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, v0, v1, v2, dx1, dy1, dx2, dy2, miter_join_revert, limit, 0); calc_miter(vc,
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, v0, v1, v2, dx1, dy1, dx2, dy2, m_line_join, m_miter_limit, dbevel); calc_miter(vc,
v0, v1, v2, dx1, dy1, dx2, dy2,
m_line_join,
m_miter_limit,
dbevel);
break; break;
case round_join: case round_join:
@ -482,10 +514,13 @@ void math_stroke<VC>::calc_join(VC& vc,
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -17,48 +17,49 @@
#include "agg_math.h" #include "agg_math.h"
namespace agg { namespace agg
template<class VertexSource>
double path_length(VertexSource& vs, unsigned path_id = 0)
{ {
double len = 0.0; template<class VertexSource>
double start_x = 0.0; double path_length(VertexSource& vs, unsigned path_id = 0)
double start_y = 0.0;
double x1 = 0.0;
double y1 = 0.0;
double x2 = 0.0;
double y2 = 0.0;
bool first = true;
unsigned cmd;
vs.rewind(path_id);
while (!is_stop(cmd = vs.vertex(&x2, &y2)))
{ {
if (is_vertex(cmd)) double len = 0.0;
double start_x = 0.0;
double start_y = 0.0;
double x1 = 0.0;
double y1 = 0.0;
double x2 = 0.0;
double y2 = 0.0;
bool first = true;
unsigned cmd;
vs.rewind(path_id);
while(!is_stop(cmd = vs.vertex(&x2, &y2)))
{ {
if (first || is_move_to(cmd)) if(is_vertex(cmd))
{ {
start_x = x2; if(first || is_move_to(cmd))
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
{ {
len += calc_distance(x1, y1, x2, y2); if(is_close(cmd) && !first)
} {
x1 = x2; len += calc_distance(x1, y1, start_x, start_y);
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -19,259 +19,277 @@
#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
{ {
enum path_cmd { cmd_move_to = 0, cmd_line_to = 1, cmd_curve3 = 2, cmd_curve4 = 3 }; //---------------------------------------------------------vertex_integer
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
{ {
*x_ = dx + (double(x >> 1) / coord_scale) * scale; enum path_cmd
*y_ = dy + (double(y >> 1) / coord_scale) * scale;
switch (((y & 1) << 1) | (x & 1))
{ {
case cmd_move_to: cmd_move_to = 0,
return path_cmd_move_to; cmd_line_to = 1,
case cmd_line_to: cmd_curve3 = 2,
return path_cmd_line_to; cmd_curve4 = 3
case cmd_curve3: };
return path_cmd_curve3;
case cmd_curve4:
return path_cmd_curve4;
}
return path_cmd_stop;
}
};
//---------------------------------------------------path_storage_integer enum coord_scale_e
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++)
{ {
memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type)); coord_shift = CoordShift,
ptr += sizeof(vertex_integer_type); coord_scale = 1 << coord_shift
} };
}
//-------------------------------------------------------------------- T x,y;
void rewind(unsigned) vertex_integer() {}
{ vertex_integer(T x_, T y_, unsigned flag) :
m_vertex_idx = 0; x(((x_ << 1) & ~1) | (flag & 1)),
m_closed = true; y(((y_ << 1) & ~1) | (flag >> 1)) {}
}
//-------------------------------------------------------------------- unsigned vertex(double* x_, double* y_,
unsigned vertex(double* x, double* y) double dx=0, double dy=0,
{ double scale=1.0) const
if (m_storage.size() < 2 || m_vertex_idx > m_storage.size())
{ {
*x = 0; *x_ = dx + (double(x >> 1) / coord_scale) * scale;
*y = 0; *y_ = dy + (double(y >> 1) / coord_scale) * scale;
switch(((y & 1) << 1) | (x & 1))
{
case cmd_move_to: return path_cmd_move_to;
case cmd_line_to: return path_cmd_line_to;
case cmd_curve3: return path_cmd_curve3;
case cmd_curve4: return path_cmd_curve4;
}
return path_cmd_stop; 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 //---------------------------------------------------path_storage_integer
template<class T, unsigned CoordShift=6> class path_storage_integer
{ {
rect_d bounds(1e100, 1e100, -1e100, -1e100); public:
if (m_storage.size() == 0) 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)
{ {
bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0; m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to));
} }
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++)
{ {
double x, y; memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type));
m_storage[i].vertex(&x, &y); ptr += sizeof(vertex_integer_type);
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; void rewind(unsigned)
unsigned m_vertex_idx; {
bool m_closed; m_vertex_idx = 0;
}; m_closed = true;
//-----------------------------------------serialized_integer_path_adaptor
template<class T, unsigned CoordShift = 6>
class serialized_integer_path_adaptor
{
public:
typedef vertex_integer<T, CoordShift> vertex_integer_type;
//--------------------------------------------------------------------
serialized_integer_path_adaptor()
: m_data(0)
, m_end(0)
, m_ptr(0)
, m_dx(0.0)
, m_dy(0.0)
, m_scale(1.0)
, m_vertices(0)
{}
//--------------------------------------------------------------------
serialized_integer_path_adaptor(const int8u* data, unsigned size, double dx, double dy)
: m_data(data)
, m_end(data + size)
, m_ptr(data)
, m_dx(dx)
, m_dy(dy)
, m_vertices(0)
{}
//--------------------------------------------------------------------
void init(const int8u* data, unsigned size, double dx, double dy, double scale = 1.0)
{
m_data = data;
m_end = data + size;
m_ptr = data;
m_dx = dx;
m_dy = dy;
m_scale = scale;
m_vertices = 0;
}
//--------------------------------------------------------------------
void rewind(unsigned)
{
m_ptr = m_data;
m_vertices = 0;
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
if (m_data == 0 || m_ptr > m_end)
{
*x = 0;
*y = 0;
return path_cmd_stop;
} }
if (m_ptr == m_end) //--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{ {
*x = 0; if(m_storage.size() < 2 || m_vertex_idx > m_storage.size())
*y = 0; {
m_ptr += sizeof(vertex_integer_type); *x = 0;
return path_cmd_end_poly | path_flags_close; *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;
} }
vertex_integer_type v; //--------------------------------------------------------------------
memcpy(&v, m_ptr, sizeof(vertex_integer_type)); rect_d bounding_rect() const
unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale);
if (is_move_to(cmd) && m_vertices > 2)
{ {
*x = 0; rect_d bounds(1e100, 1e100, -1e100, -1e100);
*y = 0; if(m_storage.size() == 0)
{
bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0;
}
else
{
unsigned i;
for(i = 0; i < m_storage.size(); i++)
{
double x, y;
m_storage[i].vertex(&x, &y);
if(x < bounds.x1) bounds.x1 = x;
if(y < bounds.y1) bounds.y1 = y;
if(x > bounds.x2) bounds.x2 = x;
if(y > bounds.y2) bounds.y2 = y;
}
}
return bounds;
}
private:
pod_bvector<vertex_integer_type, 6> m_storage;
unsigned m_vertex_idx;
bool m_closed;
};
//-----------------------------------------serialized_integer_path_adaptor
template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor
{
public:
typedef vertex_integer<T, CoordShift> vertex_integer_type;
//--------------------------------------------------------------------
serialized_integer_path_adaptor() :
m_data(0),
m_end(0),
m_ptr(0),
m_dx(0.0),
m_dy(0.0),
m_scale(1.0),
m_vertices(0)
{}
//--------------------------------------------------------------------
serialized_integer_path_adaptor(const int8u* data, unsigned size,
double dx, double dy) :
m_data(data),
m_end(data + size),
m_ptr(data),
m_dx(dx),
m_dy(dy),
m_vertices(0)
{}
//--------------------------------------------------------------------
void init(const int8u* data, unsigned size,
double dx, double dy, double scale=1.0)
{
m_data = data;
m_end = data + size;
m_ptr = data;
m_dx = dx;
m_dy = dy;
m_scale = scale;
m_vertices = 0; 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 //--------------------------------------------------------------------
void rewind(unsigned)
{
m_ptr = m_data;
m_vertices = 0;
}
//--------------------------------------------------------------------
unsigned vertex(double* x, double* y)
{
if(m_data == 0 || m_ptr > m_end)
{
*x = 0;
*y = 0;
return path_cmd_stop;
}
if(m_ptr == m_end)
{
*x = 0;
*y = 0;
m_ptr += sizeof(vertex_integer_type);
return path_cmd_end_poly | path_flags_close;
}
vertex_integer_type v;
memcpy(&v, m_ptr, sizeof(vertex_integer_type));
unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale);
if(is_move_to(cmd) && m_vertices > 2)
{
*x = 0;
*y = 0;
m_vertices = 0;
return path_cmd_end_poly | path_flags_close;
}
++m_vertices;
m_ptr += sizeof(vertex_integer_type);
return cmd;
}
private:
const int8u* m_data;
const int8u* m_end;
const int8u* m_ptr;
double m_dx;
double m_dy;
double m_scale;
unsigned m_vertices;
};
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -19,90 +19,104 @@
#include "agg_line_aa_basics.h" #include "agg_line_aa_basics.h"
#include "agg_color_rgba.h" #include "agg_color_rgba.h"
namespace agg {
//=======================================================pattern_filter_nn namespace agg
template<class ColorT>
struct pattern_filter_nn
{ {
typedef ColorT color_type;
static unsigned dilation() { return 0; }
static void AGG_INLINE pixel_low_res(color_type const* const* buf, color_type* p, int x, int y) { *p = buf[y][x]; } //=======================================================pattern_filter_nn
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)
{ {
*p = buf[y >> line_subpixel_shift][x >> line_subpixel_shift]; typedef ColorT color_type;
} static unsigned dilation() { return 0; }
};
typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8; static void AGG_INLINE pixel_low_res(color_type const* const* buf,
typedef pattern_filter_nn<rgba16> pattern_filter_nn_rgba16; color_type* p, int x, int y)
{
*p = buf[y][x];
}
//===========================================pattern_filter_bilinear_rgba static void AGG_INLINE pixel_high_res(color_type const* const* buf,
template<class ColorT> color_type* p, int x, int y)
struct pattern_filter_bilinear_rgba {
{ *p = buf[y >> line_subpixel_shift]
typedef ColorT color_type; [x >> line_subpixel_shift];
typedef typename color_type::value_type value_type; }
typedef typename color_type::calc_type calc_type; };
static unsigned dilation() { return 1; } typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8;
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]; }
static AGG_INLINE void pixel_high_res(color_type const* const* buf, color_type* p, int x, int y) //===========================================pattern_filter_bilinear_rgba
template<class ColorT> struct pattern_filter_bilinear_rgba
{ {
calc_type r, g, b, a; typedef ColorT color_type;
r = g = b = a = line_subpixel_scale * line_subpixel_scale / 2; typedef typename color_type::value_type value_type;
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;
x &= line_subpixel_mask; static unsigned dilation() { return 1; }
y &= line_subpixel_mask;
const color_type* ptr = buf[y_lr] + x_lr;
weight = (line_subpixel_scale - x) * (line_subpixel_scale - y); static AGG_INLINE void pixel_low_res(color_type const* const* buf,
r += weight * ptr->r; color_type* p, int x, int y)
g += weight * ptr->g; {
b += weight * ptr->b; *p = buf[y][x];
a += weight * ptr->a; }
++ptr; static AGG_INLINE void pixel_high_res(color_type const* const* buf,
color_type* p, int x, int y)
{
calc_type r, g, b, a;
r = g = b = a = line_subpixel_scale * line_subpixel_scale / 2;
weight = x * (line_subpixel_scale - y); calc_type weight;
r += weight * ptr->r; int x_lr = x >> line_subpixel_shift;
g += weight * ptr->g; int y_lr = y >> line_subpixel_shift;
b += weight * ptr->b;
a += weight * ptr->a;
ptr = buf[y_lr + 1] + x_lr; x &= line_subpixel_mask;
y &= line_subpixel_mask;
const color_type* ptr = buf[y_lr] + x_lr;
weight = (line_subpixel_scale - x) * y; weight = (line_subpixel_scale - x) *
r += weight * ptr->r; (line_subpixel_scale - y);
g += weight * ptr->g; r += weight * ptr->r;
b += weight * ptr->b; g += weight * ptr->g;
a += weight * ptr->a; b += weight * ptr->b;
a += weight * ptr->a;
++ptr; ++ptr;
weight = x * y; weight = x * (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;
p->r = (value_type)(r >> line_subpixel_shift * 2); ptr = buf[y_lr + 1] + x_lr;
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; weight = (line_subpixel_scale - x) * y;
typedef pattern_filter_bilinear_rgba<rgba16> pattern_filter_bilinear_rgba16; r += weight * ptr->r;
} // namespace agg g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
++ptr;
weight = x * y;
r += weight * ptr->r;
g += weight * ptr->g;
b += weight * ptr->b;
a += weight * ptr->a;
p->r = (value_type)(r >> line_subpixel_shift * 2);
p->g = (value_type)(g >> line_subpixel_shift * 2);
p->b = (value_type)(b >> line_subpixel_shift * 2);
p->a = (value_type)(a >> line_subpixel_shift * 2);
}
};
typedef pattern_filter_bilinear_rgba<rgba8> pattern_filter_bilinear_rgba8;
typedef pattern_filter_bilinear_rgba<rgba16> pattern_filter_bilinear_rgba16;
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -16,196 +16,225 @@
#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 {
//==================================================pixfmt_amask_adaptor namespace agg
template<class PixFmt, class AlphaMask>
class pixfmt_amask_adaptor
{ {
public: //==================================================pixfmt_amask_adaptor
typedef PixFmt pixfmt_type; template<class PixFmt, class AlphaMask> class pixfmt_amask_adaptor
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()) public:
typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::row_data row_data;
typedef AlphaMask amask_type;
typedef typename amask_type::cover_type cover_type;
private:
enum span_extra_tail_e { span_extra_tail = 256 };
void realloc_span(unsigned len)
{ {
m_span.resize(len + span_extra_tail); if(len > m_span.size())
{
m_span.resize(len + span_extra_tail);
}
} }
}
void init_span(unsigned len) void init_span(unsigned len)
{
realloc_span(len);
memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type));
}
void init_span(unsigned len, const cover_type* covers)
{
realloc_span(len);
memcpy(&m_span[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()
{}
void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; }
void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; }
//--------------------------------------------------------------------
template<class PixFmt2>
bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2)
{
return m_pixf->attach(pixf, x1, y1, x2, y2);
}
//--------------------------------------------------------------------
unsigned width() const { return m_pixf->width(); }
unsigned height() const { return m_pixf->height(); }
//--------------------------------------------------------------------
color_type pixel(int x, int y) { return m_pixf->pixel(x, y); }
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c) { m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y)); }
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
{
m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover));
}
//--------------------------------------------------------------------
void copy_hline(int x, int y, unsigned len, const color_type& c)
{
realloc_span(len);
m_mask->fill_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
void blend_hline(int x, int y, unsigned len, const color_type& c, cover_type cover)
{
init_span(len);
m_mask->combine_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
void copy_vline(int x, int y, unsigned len, const color_type& c)
{
realloc_span(len);
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, unsigned len, const color_type& c, 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, int xdst, int ydst, int xsrc, int ysrc, unsigned len)
{
m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len);
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const cover_type* covers)
{
init_span(len, covers);
m_mask->combine_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
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);
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); realloc_span(len);
m_mask->combine_hspan(x, y, &m_span[0], len); memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type));
} }
else
void init_span(unsigned len, const cover_type* covers)
{
realloc_span(len);
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()
{}
void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; }
void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; }
//--------------------------------------------------------------------
template<class PixFmt2>
bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2)
{
return m_pixf->attach(pixf, x1, y1, x2, y2);
}
//--------------------------------------------------------------------
unsigned width() const { return m_pixf->width(); }
unsigned height() const { return m_pixf->height(); }
//--------------------------------------------------------------------
color_type pixel(int x, int y)
{
return m_pixf->pixel(x, y);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y));
}
//--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
{
m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover));
}
//--------------------------------------------------------------------
void copy_hline(int x, int y,
unsigned len,
const color_type& c)
{ {
realloc_span(len); 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_solid_hspan(x, y, len, c, &m_span[0]);
} }
m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_color_vspan(int x, void blend_hline(int x, int y,
int y, unsigned len,
unsigned len, const color_type& c,
const color_type* colors, cover_type cover)
const cover_type* covers,
cover_type cover = cover_full)
{
if (covers)
{ {
init_span(len, covers); init_span(len);
m_mask->combine_vspan(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 copy_vline(int x, int y,
unsigned len,
const color_type& c)
{ {
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_solid_vspan(x, y, len, c, &m_span[0]);
} }
m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover);
}
private: //--------------------------------------------------------------------
pixfmt_type* m_pixf; void blend_vline(int x, int y,
const amask_type* m_mask; unsigned len,
pod_array<cover_type> m_span; const color_type& c,
}; 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]);
}
} // namespace agg //--------------------------------------------------------------------
void copy_from(const rendering_buffer& from,
int xdst, int ydst,
int xsrc, int ysrc,
unsigned len)
{
m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len);
}
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y,
unsigned len,
const color_type& c,
const cover_type* covers)
{
init_span(len, covers);
m_mask->combine_hspan(x, y, &m_span[0], len);
m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]);
}
//--------------------------------------------------------------------
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);
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);
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);
}
//--------------------------------------------------------------------
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,69 +20,78 @@
#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
{ {
typedef ColorT color_type; struct pixfmt_gray_tag
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) };
struct pixfmt_rgb_tag
{
};
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)
{ {
rgba c(color_type::to_double(r), if (cover > cover_none)
color_type::to_double(g),
color_type::to_double(b),
color_type::to_double(a));
if (cover < cover_full)
{ {
double x = static_cast<double>(cover) / static_cast<double>(cover_full); rgba c(
c.r *= x; color_type::to_double(r),
c.g *= x; color_type::to_double(g),
c.b *= x; color_type::to_double(b),
c.a *= x; color_type::to_double(a));
if (cover < cover_full)
{
double x = static_cast<double>(cover) / static_cast<double>(cover_full);
c.r *= x;
c.g *= x;
c.b *= x;
c.a *= x;
}
return c;
} }
else return rgba::no_color();
return c;
} }
else
return rgba::no_color();
}
static rgba get(const value_type* p, cover_type cover = cover_full) static rgba get(const value_type* p, cover_type cover = cover_full)
{ {
return get(p[order_type::R], p[order_type::G], p[order_type::B], p[order_type::A], cover); return get(
} p[order_type::R],
p[order_type::G],
p[order_type::B],
p[order_type::A],
cover);
}
static void set(value_type* p, value_type r, value_type g, value_type b, value_type a) static void set(value_type* p, value_type r, value_type g, value_type b, value_type a)
{ {
p[order_type::R] = r; p[order_type::R] = r;
p[order_type::G] = g; p[order_type::G] = g;
p[order_type::B] = b; p[order_type::B] = b;
p[order_type::A] = a; p[order_type::A] = a;
} }
static void set(value_type* p, const rgba& c) static void set(value_type* p, const rgba& c)
{ {
p[order_type::R] = color_type::from_double(c.r); p[order_type::R] = color_type::from_double(c.r);
p[order_type::G] = color_type::from_double(c.g); p[order_type::G] = color_type::from_double(c.g);
p[order_type::B] = color_type::from_double(c.b); p[order_type::B] = color_type::from_double(c.b);
p[order_type::A] = color_type::from_double(c.a); 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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -18,99 +18,140 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg { namespace agg
//=======================================================pixfmt_transposer
template<class PixFmt>
class pixfmt_transposer
{ {
public: //=======================================================pixfmt_transposer
typedef PixFmt pixfmt_type; template<class PixFmt> class pixfmt_transposer
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)
{ {
m_pixf->blend_vline(y, x, len, c, cover); public:
} typedef PixFmt pixfmt_type;
typedef typename pixfmt_type::color_type color_type;
typedef typename pixfmt_type::row_data row_data;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE void blend_vline(int x, int y, unsigned len, const color_type& c, int8u cover) pixfmt_transposer() : m_pixf(0) {}
{ explicit pixfmt_transposer(pixfmt_type& pixf) : m_pixf(&pixf) {}
m_pixf->blend_hline(y, x, len, c, cover); void attach(pixfmt_type& pixf) { m_pixf = &pixf; }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) AGG_INLINE unsigned width() const { return m_pixf->height(); }
{ AGG_INLINE unsigned height() const { return m_pixf->width(); }
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) AGG_INLINE color_type pixel(int x, int y) const
{ {
m_pixf->blend_solid_hspan(y, x, len, c, covers); return m_pixf->pixel(y, x);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE void copy_color_hspan(int x, int y, unsigned len, const color_type* colors) AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
{ {
m_pixf->copy_color_vspan(y, x, len, colors); m_pixf->copy_pixel(y, x, c);
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) AGG_INLINE void blend_pixel(int x, int y,
{ const color_type& c,
m_pixf->copy_color_hspan(y, x, len, colors); int8u cover)
} {
m_pixf->blend_pixel(y, x, c, cover);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE void AGG_INLINE void copy_hline(int x, int y,
blend_color_hspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) unsigned len,
{ 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 AGG_INLINE void copy_vline(int x, int y,
blend_color_vspan(int x, int y, unsigned len, const color_type* colors, const int8u* covers, int8u cover) unsigned len,
{ const color_type& c)
m_pixf->blend_color_hspan(y, x, len, colors, covers, cover); {
} m_pixf->copy_hline(y, x, len, c);
}
private: //--------------------------------------------------------------------
pixfmt_type* m_pixf; AGG_INLINE void blend_hline(int x, int y,
}; unsigned len,
} // namespace agg const color_type& c,
int8u cover)
{
m_pixf->blend_vline(y, x, len, c, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_vline(int x, int y,
unsigned len,
const color_type& c,
int8u cover)
{
m_pixf->blend_hline(y, x, len, c, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_solid_hspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
m_pixf->blend_solid_vspan(y, x, len, c, covers);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_solid_vspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
m_pixf->blend_solid_hspan(y, x, len, c, covers);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_color_hspan(int x, int y,
unsigned len,
const color_type* colors)
{
m_pixf->copy_color_vspan(y, x, len, colors);
}
//--------------------------------------------------------------------
AGG_INLINE void copy_color_vspan(int x, int y,
unsigned len,
const color_type* colors)
{
m_pixf->copy_color_hspan(y, x, len, colors);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_color_hspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
m_pixf->blend_color_vspan(y, x, len, colors, covers, cover);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_color_vspan(int x, int y,
unsigned len,
const color_type* colors,
const int8u* covers,
int8u cover)
{
m_pixf->blend_color_hspan(y, x, len, colors, covers, cover);
}
private:
pixfmt_type* m_pixf;
};
}
#endif #endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -17,116 +17,131 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg { namespace agg
//======================================================rasterizer_outline
template<class Renderer>
class rasterizer_outline
{ {
public: //======================================================rasterizer_outline
explicit rasterizer_outline(Renderer& ren) template<class Renderer> class rasterizer_outline
: 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)
{ {
m_vertices = 1; public:
m_ren->move_to(m_start_x = x, m_start_y = y); 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 line_to(int x, int y)
{
++m_vertices;
m_ren->line_to(x, y);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void move_to_d(double x, double y) { move_to(m_ren->coord(x), m_ren->coord(y)); } void move_to(int x, int y)
//--------------------------------------------------------------------
void line_to_d(double x, double y) { line_to(m_ren->coord(x), m_ren->coord(y)); }
//--------------------------------------------------------------------
void close()
{
if (m_vertices > 2)
{ {
line_to(m_start_x, m_start_y); m_vertices = 1;
m_ren->move_to(m_start_x = x, m_start_y = y);
} }
m_vertices = 0;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void add_vertex(double x, double y, unsigned cmd) void line_to(int x, int y)
{
if (is_move_to(cmd))
{ {
move_to_d(x, y); ++m_vertices;
m_ren->line_to(x, y);
} }
else
//--------------------------------------------------------------------
void move_to_d(double x, double y)
{ {
if (is_end_poly(cmd)) 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)
{ {
if (is_closed(cmd)) line_to(m_start_x, m_start_y);
close();
} }
else m_vertices = 0;
}
//--------------------------------------------------------------------
void add_vertex(double x, double y, unsigned cmd)
{
if(is_move_to(cmd))
{ {
line_to_d(x, y); move_to_d(x, y);
}
else
{
if(is_end_poly(cmd))
{
if(is_closed(cmd)) close();
}
else
{
line_to_d(x, y);
}
} }
} }
}
//--------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id = 0)
{
double x;
double y;
unsigned cmd; //--------------------------------------------------------------------
vs.rewind(path_id); template<class VertexSource>
while (!is_stop(cmd = vs.vertex(&x, &y))) void add_path(VertexSource& vs, unsigned path_id=0)
{ {
add_vertex(x, y, cmd); double x;
} double y;
}
//-------------------------------------------------------------------- unsigned cmd;
template<class VertexSource, class ColorStorage, class PathId> vs.rewind(path_id);
void render_all_paths(VertexSource& vs, const ColorStorage& colors, const PathId& path_id, unsigned num_paths) while(!is_stop(cmd = vs.vertex(&x, &y)))
{ {
for (unsigned i = 0; i < num_paths; i++) add_vertex(x, y, cmd);
}
}
//--------------------------------------------------------------------
template<class VertexSource, class ColorStorage, class PathId>
void render_all_paths(VertexSource& vs,
const ColorStorage& colors,
const PathId& path_id,
unsigned num_paths)
{ {
m_ren->line_color(colors[i]); for(unsigned i = 0; i < num_paths; i++)
add_path(vs, path_id[i]); {
m_ren->line_color(colors[i]);
add_path(vs, path_id[i]);
}
} }
}
//--------------------------------------------------------------------
template<class Ctrl> //--------------------------------------------------------------------
void render_ctrl(Ctrl& c) template<class Ctrl> void render_ctrl(Ctrl& c)
{
unsigned i;
for (i = 0; i < c.num_paths(); i++)
{ {
m_ren->line_color(c.color(i)); unsigned i;
add_path(c, i); for(i = 0; i < c.num_paths(); i++)
{
m_ren->line_color(c.color(i));
add_path(c, i);
}
} }
}
private:
Renderer* m_ren;
int m_start_x;
int m_start_y;
unsigned m_vertices;
};
} // namespace agg private:
Renderer* m_ren;
int m_start_x;
int m_start_y;
unsigned m_vertices;
};
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -19,254 +19,275 @@
#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 //-------------------------------------------------------------------------
// Vertex (x, y) with the distance to the next one. The last vertex has inline bool cmp_dist_start(int d) { return d > 0; }
// the distance between the last and the first points inline bool cmp_dist_end(int d) { return d <= 0; }
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
{ {
double dx = val.x - x; int x;
double dy = val.y - y; int y;
return (len = uround(sqrt(dx * dx + dy * dy))) > (line_subpixel_scale + line_subpixel_scale / 2); int len;
}
};
//----------------------------------------------------------outline_aa_join_e line_aa_vertex() {}
enum outline_aa_join_e { line_aa_vertex(int x_, int y_) :
outline_no_join, //-----outline_no_join x(x_),
outline_miter_join, //-----outline_miter_join y(y_),
outline_round_join, //-----outline_round_join len(0)
outline_miter_accurate_join //-----outline_accurate_join {
}; }
//=======================================================rasterizer_outline_aa bool operator () (const line_aa_vertex& val)
template<class Renderer, class Coord = line_coord> {
class rasterizer_outline_aa double dx = val.x - x;
{ double dy = val.y - y;
private: return (len = uround(sqrt(dx * dx + dy * dy))) >
//------------------------------------------------------------------------ (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);
public: //----------------------------------------------------------outline_aa_join_e
typedef line_aa_vertex vertex_type; enum outline_aa_join_e
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; outline_no_join, //-----outline_no_join
} outline_miter_join, //-----outline_miter_join
bool line_join() const { return m_line_join; } outline_round_join, //-----outline_round_join
outline_miter_accurate_join //-----outline_accurate_join
};
//------------------------------------------------------------------------ //=======================================================rasterizer_outline_aa
void round_cap(bool v) { m_round_cap = v; } template<class Renderer, class Coord=line_coord> class rasterizer_outline_aa
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)
{ {
if (is_move_to(cmd)) private:
//------------------------------------------------------------------------
struct draw_vars
{ {
render(false); unsigned idx;
move_to_d(x, y); int x1, y1, x2, y2;
line_parameters curr, next;
int lcurr, lnext;
int xb1, yb1, xb2, yb2;
unsigned flags;
};
void draw(draw_vars& dv, unsigned start, unsigned end);
public:
typedef line_aa_vertex vertex_type;
typedef vertex_sequence<vertex_type, 6> vertex_storage_type;
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;
} }
else bool line_join() const { return m_line_join; }
//------------------------------------------------------------------------
void round_cap(bool v) { m_round_cap = v; }
bool round_cap() const { return m_round_cap; }
//------------------------------------------------------------------------
void move_to(int x, int y)
{ {
if (is_end_poly(cmd)) 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)
{
if(is_move_to(cmd))
{ {
render(is_closed(cmd)); render(false);
if (is_closed(cmd)) move_to_d(x, y);
}
else
{
if(is_end_poly(cmd))
{ {
move_to(m_start_x, m_start_y); render(is_closed(cmd));
if(is_closed(cmd))
{
move_to(m_start_x, m_start_y);
}
}
else
{
line_to_d(x, y);
} }
} }
else }
//------------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id=0)
{
double x;
double y;
unsigned cmd;
vs.rewind(path_id);
while(!is_stop(cmd = vs.vertex(&x, &y)))
{ {
line_to_d(x, y); add_vertex(x, y, cmd);
}
render(false);
}
//------------------------------------------------------------------------
template<class VertexSource, class ColorStorage, class PathId>
void render_all_paths(VertexSource& vs,
const ColorStorage& colors,
const PathId& path_id,
unsigned num_paths)
{
for(unsigned i = 0; i < num_paths; i++)
{
m_ren->color(colors[i]);
add_path(vs, path_id[i]);
} }
} }
}
//------------------------------------------------------------------------
template<class VertexSource>
void add_path(VertexSource& vs, unsigned path_id = 0)
{
double x;
double y;
unsigned cmd; //------------------------------------------------------------------------
vs.rewind(path_id); template<class Ctrl> void render_ctrl(Ctrl& c)
while (!is_stop(cmd = vs.vertex(&x, &y)))
{ {
add_vertex(x, y, cmd); unsigned i;
for(i = 0; i < c.num_paths(); i++)
{
m_ren->color(c.color(i));
add_path(c, i);
}
} }
render(false);
}
//------------------------------------------------------------------------ private:
template<class VertexSource, class ColorStorage, class PathId> rasterizer_outline_aa(const rasterizer_outline_aa<Renderer, Coord>&);
void render_all_paths(VertexSource& vs, const ColorStorage& colors, const PathId& path_id, unsigned num_paths) const rasterizer_outline_aa<Renderer, Coord>& operator =
{ (const rasterizer_outline_aa<Renderer, Coord>&);
for (unsigned i = 0; i < num_paths; i++)
{
m_ren->color(colors[i]);
add_path(vs, path_id[i]);
}
}
//------------------------------------------------------------------------ Renderer* m_ren;
template<class Ctrl> vertex_storage_type m_src_vertices;
void render_ctrl(Ctrl& c) 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;
for (i = 0; i < c.num_paths(); i++) const vertex_storage_type::value_type* v;
for(i = start; i < end; i++)
{ {
m_ren->color(c.color(i)); if(m_line_join == outline_round_join)
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);
}
private: switch(dv.flags)
rasterizer_outline_aa(const rasterizer_outline_aa<Renderer, Coord>&); {
const rasterizer_outline_aa<Renderer, Coord>& operator=(const rasterizer_outline_aa<Renderer, Coord>&); 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;
}
Renderer* m_ren; if(m_line_join == outline_round_join && (dv.flags & 2) == 0)
vertex_storage_type m_src_vertices; {
outline_aa_join_e m_line_join; m_ren->pie(dv.curr.x2, dv.curr.y2,
bool m_round_cap; dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
int m_start_x; dv.curr.y2 - (dv.curr.x2 - dv.curr.x1),
int m_start_y; dv.curr.x2 + (dv.next.y2 - dv.next.y1),
}; dv.curr.y2 - (dv.next.x2 - dv.next.x1));
}
//---------------------------------------------------------------------------- dv.x1 = dv.x2;
template<class Renderer, class Coord> dv.y1 = dv.y2;
void rasterizer_outline_aa<Renderer, Coord>::draw(draw_vars& dv, unsigned start, unsigned end) dv.lcurr = dv.lnext;
{ dv.lnext = m_src_vertices[dv.idx].len;
unsigned i;
const vertex_storage_type::value_type* v;
for (i = start; i < end; i++) ++dv.idx;
{ 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);
}
switch (dv.flags) v = &m_src_vertices[dv.idx];
{ dv.x2 = v->x;
case 0: dv.y2 = v->y;
m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2);
break;
case 1:
m_ren->line2(dv.curr, dv.xb2, dv.yb2);
break;
case 2:
m_ren->line1(dv.curr, dv.xb1, dv.yb1);
break;
case 3:
m_ren->line0(dv.curr);
break;
}
if (m_line_join == outline_round_join && (dv.flags & 2) == 0) dv.curr = dv.next;
{ dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
m_ren->pie(dv.curr.x2, dv.xb1 = dv.xb2;
dv.curr.y2, dv.yb1 = dv.yb2;
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1),
dv.curr.x2 + (dv.next.y2 - dv.next.y1),
dv.curr.y2 - (dv.next.x2 - dv.next.x1));
}
dv.x1 = dv.x2; switch(m_line_join)
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.next.diagonal_quadrant()) << 1); dv.flags |= ((dv.curr.diagonal_quadrant() ==
if ((dv.flags & 2) == 0) dv.next.diagonal_quadrant()) << 1);
if((dv.flags & 2) == 0)
{ {
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
} }
@ -274,282 +295,302 @@ void rasterizer_outline_aa<Renderer, Coord>::draw(draw_vars& dv, unsigned start,
case outline_round_join: case outline_round_join:
dv.flags >>= 1; dv.flags >>= 1;
dv.flags |= ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); dv.flags |= ((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;
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)
{ {
dv.idx = 2; 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;
v = &m_src_vertices[m_src_vertices.size() - 1]; if(close_polygon && (m_src_vertices.size() >= 3))
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 = (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | dv.flags =
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
((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) if((dv.flags & 1) == 0 && m_line_join != outline_round_join)
{ {
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
} }
if ((dv.flags & 2) == 0 && m_line_join != outline_round_join) if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
{ {
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
}
draw(dv, 0, m_src_vertices.size());
} }
draw(dv, 0, m_src_vertices.size()); else
}
else
{
switch (m_src_vertices.size())
{ {
case 0: switch(m_src_vertices.size())
case 1: {
case 0:
case 1:
break;
case 2:
{
v = &m_src_vertices[0];
x1 = v->x;
y1 = v->y;
lprev = v->len;
v = &m_src_vertices[1];
x2 = v->x;
y2 = v->y;
line_parameters lp(x1, y1, x2, y2, lprev);
if(m_round_cap)
{
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
}
m_ren->line3(lp,
x1 + (y2 - y1),
y1 - (x2 - x1),
x2 + (y2 - y1),
y2 - (x2 - x1));
if(m_round_cap)
{
m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
}
}
break; break;
case 2: { case 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;
line_parameters lp(x1, y1, x2, y2, lprev);
if (m_round_cap)
{ {
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); int x3, y3;
int lnext;
v = &m_src_vertices[0];
x1 = v->x;
y1 = v->y;
lprev = v->len;
v = &m_src_vertices[1];
x2 = v->x;
y2 = v->y;
lnext = v->len;
v = &m_src_vertices[2];
x3 = v->x;
y3 = v->y;
line_parameters lp1(x1, y1, x2, y2, lprev);
line_parameters lp2(x2, y2, x3, y3, lnext);
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));
}
} }
m_ren->line3(lp, x1 + (y2 - y1), y1 - (x2 - x1), x2 + (y2 - y1), y2 - (x2 - x1)); break;
if (m_round_cap)
default:
{ {
m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1)); dv.idx = 3;
}
}
break;
case 3: { v = &m_src_vertices[0];
int x3, y3; x1 = v->x;
int lnext; y1 = v->y;
v = &m_src_vertices[0]; lprev = v->len;
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) v = &m_src_vertices[1];
{ x2 = v->x;
m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); y2 = v->y;
} dv.lcurr = v->len;
line_parameters prev(x1, y1, x2, y2, lprev);
if (m_line_join == outline_round_join) v = &m_src_vertices[2];
{ dv.x1 = v->x;
m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), x2 + (y2 - y1), y2 - (x2 - x1)); dv.y1 = v->y;
dv.lnext = v->len;
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1), x2 + (y3 - y2), y2 - (x3 - x2)); 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);
m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2), x3 + (y3 - y2), y3 - (x3 - x2)); dv.xb1 = 0;
} dv.yb1 = 0;
else dv.xb2 = 0;
{ dv.yb2 = 0;
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)); switch(m_line_join)
} {
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 = (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | dv.flags =
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
((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->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), x2 + (y2 - y1), y2 - (x2 - x1)); m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
m_ren->pie(prev.x2, }
prev.y2, if((dv.flags & 1) == 0)
x2 + (y2 - y1), {
y2 - (x2 - x1), if(m_line_join == outline_round_join)
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), {
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1)); m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
x2 + (y2 - y1), y2 - (x2 - x1));
m_ren->pie(prev.x2, prev.y2,
x2 + (y2 - y1), y2 - (x2 - x1),
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1));
}
else
{
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1),
dv.xb1, dv.yb1);
}
} }
else else
{ {
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); m_ren->line1(prev,
m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), dv.xb1, dv.yb1); x1 + (y2 - y1),
y1 - (x2 - x1));
} }
} if((dv.flags & 2) == 0 && m_line_join != outline_round_join)
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);
if ((dv.flags & 1) == 0)
{
if (m_line_join == outline_round_join)
{ {
m_ren->line3(dv.curr, bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
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), draw(dv, 1, m_src_vertices.size() - 2);
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
if((dv.flags & 1) == 0)
{
if(m_line_join == outline_round_join)
{
m_ren->line3(dv.curr,
dv.curr.x1 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y1 - (dv.curr.x2 - dv.curr.x1),
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}
else
{
m_ren->line3(dv.curr, dv.xb1, dv.yb1,
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
}
} }
else else
{ {
m_ren->line3(dv.curr, m_ren->line2(dv.curr,
dv.xb1, dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
dv.yb1,
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)
{
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));
}
} }
else break;
{
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,445 +33,477 @@
#include "agg_rasterizer_sl_clip.h" #include "agg_rasterizer_sl_clip.h"
#include "agg_gamma_functions.h" #include "agg_gamma_functions.h"
namespace agg {
//-----------------------------------------------------------------cell_aa namespace agg
// 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
{ {
x = 0x7FFFFFFF; int x;
y = 0x7FFFFFFF; int y;
cover = 0; int cover;
area = 0; int area;
}
void style(const cell_aa&) {} void initial()
{
x = 0x7FFFFFFF;
y = 0x7FFFFFFF;
cover = 0;
area = 0;
}
int not_equal(int ex, int ey, const cell_aa&) const { return (ex - x) | (ey - y); } void style(const cell_aa&) {}
};
//==================================================rasterizer_scanline_aa int not_equal(int ex, int ey, const cell_aa&) const
// Polygon rasterizer that is used to render filled polygons with {
// high-quality Anti-Aliasing. Internally, by default, the class uses return (ex - x) | (ey - y);
// 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()
: m_outline()
, m_clipper()
, m_filling_rule(fill_non_zero)
, m_auto_close(true)
, m_start_x(0)
, m_start_y(0)
, m_status(status_initial)
{
int i;
for (i = 0; i < aa_scale; i++)
m_gamma[i] = i;
}
//-------------------------------------------------------------------- //==================================================rasterizer_scanline_aa
template<class GammaF> // Polygon rasterizer that is used to render filled polygons with
rasterizer_scanline_aa(const GammaF& gamma_function) // high-quality Anti-Aliasing. Internally, by default, the class uses
: m_outline() // integer coordinates in format 24.8, i.e. 24 bits for integer part
, m_clipper(m_outline) // and 8 bits for fractional - see poly_subpixel_shift. This class can be
, m_filling_rule(fill_non_zero) // used in the following way:
, m_auto_close(true) //
, m_start_x(0) // 1. filling_rule(filling_rule_e ft) - optional.
, m_start_y(0) //
, 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
{ {
gamma(gamma_function); enum status
}
//--------------------------------------------------------------------
void reset();
void reset_clipping();
void clip_box(double x1, double y1, double x2, double y2);
void filling_rule(filling_rule_e filling_rule);
void auto_close(bool flag) { m_auto_close = flag; }
//--------------------------------------------------------------------
template<class GammaF>
void gamma(const GammaF& gamma_function)
{
int i;
for (i = 0; i < aa_scale; i++)
{ {
m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask); 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() :
m_outline(),
m_clipper(),
m_filling_rule(fill_non_zero),
m_auto_close(true),
m_start_x(0),
m_start_y(0),
m_status(status_initial)
{
int i;
for(i = 0; i < aa_scale; i++) m_gamma[i] = i;
} }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
unsigned apply_gamma(unsigned cover) const { return m_gamma[cover]; } template<class GammaF>
rasterizer_scanline_aa(const GammaF& gamma_function) :
//-------------------------------------------------------------------- m_outline(),
void move_to(int x, int y); m_clipper(m_outline),
void line_to(int x, int y); m_filling_rule(fill_non_zero),
void move_to_d(double x, double y); m_auto_close(true),
void line_to_d(double x, double y); m_start_x(0),
void close_polygon(); m_start_y(0),
void add_vertex(double x, double y, unsigned cmd); m_status(status_initial)
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); gamma(gamma_function);
} }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
int min_x() const { return m_outline.min_x(); } void reset();
int min_y() const { return m_outline.min_y(); } void reset_clipping();
int max_x() const { return m_outline.max_x(); } void clip_box(double x1, double y1, double x2, double y2);
int max_y() const { return m_outline.max_y(); } void filling_rule(filling_rule_e filling_rule);
void auto_close(bool flag) { m_auto_close = flag; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void sort(); template<class GammaF> void gamma(const GammaF& gamma_function)
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; int i;
if (cover > aa_scale) for(i = 0; i < aa_scale; i++)
{ {
cover = aa_scale2 - cover; m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask);
} }
} }
if (cover > aa_mask)
cover = aa_mask;
return m_gamma[cover];
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
template<class Scanline> unsigned apply_gamma(unsigned cover) const
bool sweep_scanline(Scanline& sl)
{
for (;;)
{ {
if (m_scan_y > m_outline.max_y()) return m_gamma[cover];
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)))
{ {
const cell_aa* cur_cell = *cells; add_vertex(x, y, cmd);
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 //--------------------------------------------------------------------
while (--num_cells) 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)
{
cover &= aa_mask2;
if(cover > aa_scale)
{ {
cur_cell = *++cells; cover = aa_scale2 - cover;
if (cur_cell->x != x) }
break; }
area += cur_cell->area; if(cover > aa_mask) cover = aa_mask;
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;
}
if (area) //accumulate all cells with the same X
{ while(--num_cells)
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
if (alpha)
{ {
sl.add_cell(x, alpha); cur_cell = *++cells;
if(cur_cell->x != x) break;
area += cur_cell->area;
cover += cur_cell->cover;
} }
x++;
}
if (num_cells && cur_cell->x > x) if(area)
{
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
if (alpha)
{ {
sl.add_span(x, cur_cell->x - x, alpha); 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;
++m_scan_y;
} }
if (sl.num_spans()) sl.finalize(m_scan_y);
break;
++m_scan_y; ++m_scan_y;
return true;
} }
sl.finalize(m_scan_y); //--------------------------------------------------------------------
++m_scan_y; bool hit_test(int tx, int ty);
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>
// Disable copying AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y)
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); if(m_auto_close) close_polygon();
m_status = status_closed; 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> template<class Clip>
void rasterizer_scanline_aa<Clip>::move_to(int x, int y) bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty)
{
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); if(!navigate_scanline(ty)) return false;
} scanline_hit_test sl(tx);
else if (is_vertex(cmd)) sweep_scanline(sl);
{ return sl.hit();
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,204 +17,226 @@
#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
{ {
typedef int coord_type; //--------------------------------------------------------poly_max_coord_e
static AGG_INLINE int mul_div(double a, double b, double c) { return iround(a * b / c); } enum poly_max_coord_e
static int xi(int v) { return v; }
static int yi(int v) { return v; }
static int upscale(double v) { return iround(v * static_cast<double>(poly_subpixel_scale)); }
static int downscale(int v) { return v; }
};
//--------------------------------------------------------ras_conv_int_sat
struct ras_conv_int_sat
{
typedef int coord_type;
static AGG_INLINE int mul_div(double a, double b, double c)
{ {
return saturation<poly_max_coord>::iround(a * b / c); poly_max_coord = (1 << 30) - 1 //----poly_max_coord
} };
static int xi(int v) { return v; }
static int yi(int v) { return v; } //------------------------------------------------------------ras_conv_int
static int upscale(double v) struct ras_conv_int
{ {
return saturation<poly_max_coord>::iround(v * static_cast<double>(poly_subpixel_scale)); typedef int coord_type;
} static AGG_INLINE int mul_div(double a, double b, double c)
static int downscale(int v) { return v; }
};
//---------------------------------------------------------ras_conv_int_3x
struct ras_conv_int_3x
{
typedef int coord_type;
static AGG_INLINE int mul_div(double a, double b, double c) { return iround(a * b / c); }
static int xi(int v) { return v * 3; }
static int yi(int v) { return v; }
static int upscale(double v) { return iround(v * static_cast<double>(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 * static_cast<double>(poly_subpixel_scale)); }
static int yi(double v) { return iround(v * static_cast<double>(poly_subpixel_scale)); }
static double upscale(double v) { return v; }
static double downscale(int v) { return v / static_cast<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 * static_cast<double>(poly_subpixel_scale) * 3); }
static int yi(double v) { return iround(v * static_cast<double>(poly_subpixel_scale)); }
static double upscale(double v) { return v; }
static double downscale(int v) { return v / static_cast<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 return iround(a * b / c);
ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2));
} }
else static int xi(int v) { return v; }
{ static int yi(int v) { return v; }
if (f1 == f2) static int upscale(double v) { return iround(v * static_cast<double>(poly_subpixel_scale)); }
{ static int downscale(int v) { return v; }
// Invisible by Y };
return;
}
coord_type tx1 = x1; //--------------------------------------------------------ras_conv_int_sat
coord_type ty1 = y1; struct ras_conv_int_sat
coord_type tx2 = x2;
coord_type ty2 = y2;
if (f1 & 8) // y1 < clip.y1
{
tx1 = x1 + Conv::mul_div(m_clip_box.y1 - y1, x2 - x1, y2 - y1);
ty1 = m_clip_box.y1;
}
if (f1 & 2) // y1 > clip.y2
{
tx1 = x1 + Conv::mul_div(m_clip_box.y2 - y1, x2 - x1, y2 - y1);
ty1 = m_clip_box.y2;
}
if (f2 & 8) // y2 < clip.y1
{
tx2 = x1 + Conv::mul_div(m_clip_box.y1 - y1, x2 - x1, y2 - y1);
ty2 = m_clip_box.y1;
}
if (f2 & 2) // y2 > clip.y2
{
tx2 = x1 + Conv::mul_div(m_clip_box.y2 - y1, x2 - x1, y2 - y1);
ty2 = m_clip_box.y2;
}
ras.line(Conv::xi(tx1), Conv::yi(ty1), Conv::xi(tx2), Conv::yi(ty2));
}
}
public:
//--------------------------------------------------------------------
template<class Rasterizer>
void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
{ {
if (m_clipping) typedef int coord_type;
static AGG_INLINE int mul_div(double a, double b, double c)
{ {
unsigned f2 = clipping_flags(x2, y2, m_clip_box); 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 * static_cast<double>(poly_subpixel_scale));
}
static int downscale(int v) { return v; }
};
if ((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0) //---------------------------------------------------------ras_conv_int_3x
struct ras_conv_int_3x
{
typedef int coord_type;
static AGG_INLINE int mul_div(double a, double b, double c)
{
return iround(a * b / c);
}
static int xi(int v) { return v * 3; }
static int yi(int v) { return v; }
static int upscale(double v) { return iround(v * static_cast<double>(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 * static_cast<double>(poly_subpixel_scale)); }
static int yi(double v) { return iround(v * static_cast<double>(poly_subpixel_scale)); }
static double upscale(double v) { return v; }
static double downscale(int v) { return v / static_cast<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 * static_cast<double>(poly_subpixel_scale) * 3); }
static int yi(double v) { return iround(v * static_cast<double>(poly_subpixel_scale)); }
static double upscale(double v) { return v; }
static double downscale(int v) { return v / static_cast<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)
{ {
// Invisible by Y // Fully visible
m_x1 = x2; ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2));
m_y1 = y2;
m_f1 = f2;
return;
} }
else
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))
{ {
if(f1 == f2)
{
// Invisible by Y
return;
}
coord_type tx1 = x1;
coord_type ty1 = y1;
coord_type tx2 = x2;
coord_type ty2 = y2;
if(f1 & 8) // y1 < clip.y1
{
tx1 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
ty1 = m_clip_box.y1;
}
if(f1 & 2) // y1 > clip.y2
{
tx1 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
ty1 = m_clip_box.y2;
}
if(f2 & 8) // y2 < clip.y1
{
tx2 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1);
ty2 = m_clip_box.y1;
}
if(f2 & 2) // y2 > clip.y2
{
tx2 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1);
ty2 = m_clip_box.y2;
}
ras.line(Conv::xi(tx1), Conv::yi(ty1),
Conv::xi(tx2), Conv::yi(ty2));
}
}
public:
//--------------------------------------------------------------------
template<class Rasterizer>
void line_to(Rasterizer& ras, coord_type x2, coord_type y2)
{
if(m_clipping)
{
unsigned f2 = clipping_flags(x2, y2, m_clip_box);
if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0)
{
// Invisible by Y
m_x1 = x2;
m_y1 = y2;
m_f1 = f2;
return;
}
coord_type x1 = m_x1;
coord_type y1 = m_y1;
unsigned f1 = m_f1;
coord_type y3, y4;
unsigned f3, f4;
switch(((f1 & 5) << 1) | (f2 & 5))
{
case 0: // Visible by X 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);
@ -225,15 +247,15 @@ class rasterizer_sl_clip
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);
@ -242,15 +264,15 @@ class rasterizer_sl_clip
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);
@ -261,69 +283,69 @@ class rasterizer_sl_clip
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;
} }
m_f1 = f2; else
{
ras.line(Conv::xi(m_x1), Conv::yi(m_y1),
Conv::xi(x2), Conv::yi(y2));
}
m_x1 = x2;
m_y1 = y2;
} }
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(Conv::xi(m_x1), Conv::yi(m_y1), Conv::xi(x2), Conv::yi(y2)); ras.line(m_x1, m_y1, x2, y2);
m_x1 = x2;
m_y1 = y2;
} }
m_x1 = x2;
m_y1 = y2;
}
private: private:
rect_type m_clip_box; int m_x1, m_y1;
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() // -----rasterizer_sl_clip_int
: m_x1(0) // -----rasterizer_sl_clip_int_sat
, m_y1(0) // -----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;
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -24,303 +24,326 @@
#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
explicit renderer_mclip(pixfmt_type& pixf) template<class PixelFormat> class renderer_mclip
: m_ren(pixf)
, m_curr_cb(0)
, m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax())
{}
void attach(pixfmt_type& pixf)
{ {
m_ren.attach(pixf); public:
reset_clipping(true); 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;
//-------------------------------------------------------------------- //--------------------------------------------------------------------
const pixfmt_type& ren() const { return m_ren.ren(); } explicit renderer_mclip(pixfmt_type& pixf) :
pixfmt_type& ren() { return m_ren.ren(); } m_ren(pixf),
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(); } {}
unsigned height() const { return m_ren.height(); } void attach(pixfmt_type& pixf)
//--------------------------------------------------------------------
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())
{ {
const rect_i& cb = m_clip[0]; m_ren.attach(pixf);
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); reset_clipping(true);
} }
}
//--------------------------------------------------------------------
const pixfmt_type& ren() const { return m_ren.ren(); }
pixfmt_type& ren() { return m_ren.ren(); }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
bool next_clip_box() unsigned width() const { return m_ren.width(); }
{ unsigned height() const { return m_ren.height(); }
if (++m_curr_cb < m_clip.size())
//--------------------------------------------------------------------
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()
{ {
const rect_i& cb = m_clip[m_curr_cb]; m_curr_cb = 0;
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); if(m_clip.size())
return true; {
const rect_i& cb = m_clip[0];
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
}
} }
return false;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void reset_clipping(bool visibility) bool next_clip_box()
{ {
m_ren.reset_clipping(visibility); if(++m_curr_cb < m_clip.size())
m_clip.remove_all(); {
m_curr_cb = 0; const rect_i& cb = m_clip[m_curr_cb];
m_bounds = m_ren.clip_box(); m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
} return true;
}
//-------------------------------------------------------------------- return false;
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 reset_clipping(bool visibility)
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
first_clip_box();
do
{ {
if (m_ren.inbox(x, y)) 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_ren.ren().copy_pixel(x, y, c); m_clip.add(cb);
break; 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()); }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_pixel(int x, int y, const color_type& c, cover_type cover) void clear(const color_type& c)
{
first_clip_box();
do
{ {
if (m_ren.inbox(x, y)) m_ren.clear(c);
}
//--------------------------------------------------------------------
void copy_pixel(int x, int y, const color_type& c)
{
first_clip_box();
do
{ {
m_ren.ren().blend_pixel(x, y, c, cover); if(m_ren.inbox(x, y))
break; {
m_ren.ren().copy_pixel(x, y, c);
break;
}
} }
} while (next_clip_box()); while(next_clip_box());
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
color_type pixel(int x, int y) const void blend_pixel(int x, int y, const color_type& c, cover_type cover)
{
first_clip_box();
do
{ {
if (m_ren.inbox(x, y)) first_clip_box();
do
{ {
return m_ren.ren().pixel(x, y); if(m_ren.inbox(x, y))
{
m_ren.ren().blend_pixel(x, y, c, cover);
break;
}
} }
} while (next_clip_box()); while(next_clip_box());
return color_type::no_color(); }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_hline(int x1, int y, int x2, const color_type& c) color_type pixel(int x, int y) const
{
first_clip_box();
do
{ {
m_ren.copy_hline(x1, y, x2, c); first_clip_box();
} while (next_clip_box()); do
} {
if(m_ren.inbox(x, y))
{
return m_ren.ren().pixel(x, y);
}
}
while(next_clip_box());
return color_type::no_color();
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_vline(int x, int y1, int y2, const color_type& c) void copy_hline(int x1, int y, int x2, const color_type& c)
{
first_clip_box();
do
{ {
m_ren.copy_vline(x, y1, y2, c); first_clip_box();
} while (next_clip_box()); do
} {
m_ren.copy_hline(x1, y, x2, c);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_hline(int x1, int y, int x2, const color_type& c, cover_type cover) void copy_vline(int x, int y1, int y2, const color_type& c)
{
first_clip_box();
do
{ {
m_ren.blend_hline(x1, y, x2, c, cover); first_clip_box();
} while (next_clip_box()); do
} {
m_ren.copy_vline(x, y1, y2, c);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_vline(int x, int y1, int y2, 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
{ {
m_ren.blend_vline(x, y1, y2, c, cover); first_clip_box();
} while (next_clip_box()); do
} {
m_ren.blend_hline(x1, y, x2, c, cover);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) void blend_vline(int x, int y1, int y2,
{ const color_type& c, cover_type cover)
first_clip_box();
do
{ {
m_ren.copy_bar(x1, y1, x2, y2, c); first_clip_box();
} while (next_clip_box()); do
} {
m_ren.blend_vline(x, y1, y2, c, cover);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_bar(int x1, int y1, int x2, int y2, const color_type& c, cover_type cover) void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
{
first_clip_box();
do
{ {
m_ren.blend_bar(x1, y1, x2, y2, c, cover); first_clip_box();
} while (next_clip_box()); do
} {
m_ren.copy_bar(x1, y1, x2, y2, c);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_solid_hspan(int x, int y, int len, const color_type& c, const cover_type* covers) void blend_bar(int x1, int y1, int x2, int y2,
{ const color_type& c, cover_type cover)
first_clip_box();
do
{ {
m_ren.blend_solid_hspan(x, y, len, c, covers); first_clip_box();
} while (next_clip_box()); do
} {
m_ren.blend_bar(x1, y1, x2, y2, c, cover);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_solid_vspan(int x, int y, int len, const color_type& c, const cover_type* covers) void blend_solid_hspan(int x, int y, int len,
{ const color_type& c, const cover_type* covers)
first_clip_box();
do
{ {
m_ren.blend_solid_vspan(x, y, len, c, covers); first_clip_box();
} while (next_clip_box()); do
} {
m_ren.blend_solid_hspan(x, y, len, c, covers);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_color_hspan(int x, int y, int len, const color_type* colors) void blend_solid_vspan(int x, int y, int len,
{ const color_type& c, const cover_type* covers)
first_clip_box();
do
{ {
m_ren.copy_color_hspan(x, y, len, colors); first_clip_box();
} while (next_clip_box()); do
} {
m_ren.blend_solid_vspan(x, y, len, c, covers);
}
while(next_clip_box());
}
//--------------------------------------------------------------------
void blend_color_hspan(int x, //--------------------------------------------------------------------
int y, void copy_color_hspan(int x, int y, int len, const color_type* colors)
int len,
const color_type* colors,
const cover_type* covers,
cover_type cover = cover_full)
{
first_clip_box();
do
{ {
m_ren.blend_color_hspan(x, y, len, colors, covers, cover); first_clip_box();
} while (next_clip_box()); do
} {
m_ren.copy_color_hspan(x, y, len, colors);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void blend_color_vspan(int x, void blend_color_hspan(int x, int y, int len,
int y, const color_type* colors,
int len, const cover_type* covers,
const color_type* colors, cover_type cover = cover_full)
const cover_type* covers,
cover_type cover = cover_full)
{
first_clip_box();
do
{ {
m_ren.blend_color_vspan(x, y, len, colors, covers, cover); first_clip_box();
} while (next_clip_box()); do
} {
m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void copy_from(const rendering_buffer& from, const rect_i* rc = 0, int x_to = 0, int y_to = 0) void blend_color_vspan(int x, int y, int len,
{ const color_type* colors,
first_clip_box(); const cover_type* covers,
do cover_type cover = cover_full)
{ {
m_ren.copy_from(from, rc, x_to, y_to); first_clip_box();
} while (next_clip_box()); do
} {
m_ren.blend_color_vspan(x, y, len, colors, covers, cover);
}
while(next_clip_box());
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
template<class SrcPixelFormatRenderer> void copy_from(const rendering_buffer& from,
void blend_from(const SrcPixelFormatRenderer& src, const rect_i* rc=0,
const rect_i* rect_src_ptr = 0, int x_to=0,
int dx = 0, int y_to=0)
int dy = 0,
cover_type cover = cover_full)
{
first_clip_box();
do
{ {
m_ren.blend_from(src, rect_src_ptr, dx, dy, cover); first_clip_box();
} while (next_clip_box()); do
} {
m_ren.copy_from(from, rc, x_to, y_to);
}
while(next_clip_box());
}
private: //--------------------------------------------------------------------
renderer_mclip(const renderer_mclip<PixelFormat>&); template<class SrcPixelFormatRenderer>
const renderer_mclip<PixelFormat>& operator=(const renderer_mclip<PixelFormat>&); 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());
}
base_ren_type m_ren;
pod_bvector<rect_i, 4> m_clip; private:
unsigned m_curr_cb; renderer_mclip(const renderer_mclip<PixelFormat>&);
rect_i m_bounds; const renderer_mclip<PixelFormat>&
}; operator = (const renderer_mclip<PixelFormat>&);
} // namespace agg 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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -25,190 +25,200 @@
#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
{ {
public: //-----------------------------------------------------renderer_primitives
typedef BaseRenderer base_ren_type; template<class BaseRenderer> class renderer_primitives
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)
{ {
m_ren->blend_hline(x1, y1, x2 - 1, m_line_color, cover_full); public:
m_ren->blend_vline(x2, y1, y2 - 1, m_line_color, cover_full); typedef BaseRenderer base_ren_type;
m_ren->blend_hline(x1 + 1, y2, x2, m_line_color, cover_full); typedef typename base_ren_type::color_type color_type;
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); } 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; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void outlined_rectangle(int x1, int y1, int x2, int y2) static int coord(double c)
{ {
rectangle(x1, y1, x2, y2); return iround(c * line_bresenham_interpolator::subpixel_scale);
m_ren->blend_bar(x1 + 1, y1 + 1, x2 - 1, y2 - 1, m_fill_color, cover_full);
}
//--------------------------------------------------------------------
void ellipse(int x, int y, int rx, int ry)
{
ellipse_bresenham_interpolator ei(rx, ry);
int dx = 0;
int dy = -ry;
do
{
dx += ei.dx();
dy += ei.dy();
m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
++ei;
} while (dy < 0);
}
//--------------------------------------------------------------------
void solid_ellipse(int x, int y, int rx, int ry)
{
ellipse_bresenham_interpolator ei(rx, ry);
int dx = 0;
int dy = -ry;
int dy0 = dy;
int dx0 = dx;
do
{
dx += ei.dx();
dy += ei.dy();
if (dy != dy0)
{
m_ren->blend_hline(x - dx0, y + dy0, x + dx0, m_fill_color, cover_full);
m_ren->blend_hline(x - dx0, y - dy0, x + dx0, m_fill_color, cover_full);
}
dx0 = dx;
dy0 = dy;
++ei;
} while (dy < 0);
m_ren->blend_hline(x - dx0, y + dy0, x + dx0, m_fill_color, cover_full);
}
//--------------------------------------------------------------------
void outlined_ellipse(int x, int y, int rx, int ry)
{
ellipse_bresenham_interpolator ei(rx, ry);
int dx = 0;
int dy = -ry;
do
{
dx += ei.dx();
dy += ei.dy();
m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
if (ei.dy() && dx)
{
m_ren->blend_hline(x - dx + 1, y + dy, x + dx - 1, m_fill_color, cover_full);
m_ren->blend_hline(x - dx + 1, y - dy, x + dx - 1, m_fill_color, cover_full);
}
++ei;
} while (dy < 0);
}
//--------------------------------------------------------------------
void line(int x1, int y1, int x2, int y2, bool last = false)
{
line_bresenham_interpolator li(x1, y1, x2, y2);
unsigned len = li.len();
if (len == 0)
{
if (last)
{
m_ren->blend_pixel(li.line_lr(x1), li.line_lr(y1), m_line_color, cover_full);
}
return;
} }
if (last) //--------------------------------------------------------------------
++len; 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; }
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
{ {
m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full); dx += ei.dx();
li.vstep(); dy += ei.dy();
} 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);
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
{ {
m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full); dx += ei.dx();
li.hstep(); dy += ei.dy();
} 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 move_to(int x, int y) void outlined_ellipse(int x, int y, int rx, int ry)
{ {
m_curr_x = x; ellipse_bresenham_interpolator ei(rx, ry);
m_curr_y = y; int dx = 0;
} int dy = -ry;
//-------------------------------------------------------------------- do
void line_to(int x, int y, bool last = false) {
{ dx += ei.dx();
line(m_curr_x, m_curr_y, x, y, last); dy += ei.dy();
m_curr_x = x;
m_curr_y = y;
}
//-------------------------------------------------------------------- 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);
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(); } {
rendering_buffer& rbuf() { return m_ren->rbuf(); } 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);
}
private: //--------------------------------------------------------------------
base_ren_type* m_ren; void line(int x1, int y1, int x2, int y2, bool last=false)
color_type m_fill_color; {
color_type m_line_color; line_bresenham_interpolator li(x1, y1, x2, y2);
int m_curr_x;
int m_curr_y;
};
} // namespace agg unsigned len = li.len();
if(len == 0)
{
if(last)
{
m_ren->blend_pixel(li.line_lr(x1), li.line_lr(y1), m_line_color, cover_full);
}
return;
}
if(last) ++len;
if(li.is_ver())
{
do
{
m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full);
li.vstep();
}
while(--len);
}
else
{
do
{
m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full);
li.hstep();
}
while(--len);
}
}
//--------------------------------------------------------------------
void move_to(int x, int y)
{
m_curr_x = x;
m_curr_y = y;
}
//--------------------------------------------------------------------
void line_to(int x, int y, bool last=false)
{
line(m_curr_x, m_curr_y, x, y, last);
m_curr_x = x;
m_curr_y = y;
}
//--------------------------------------------------------------------
const base_ren_type& ren() const { return *m_ren; }
base_ren_type& ren() { return *m_ren; }
//--------------------------------------------------------------------
const rendering_buffer& rbuf() const { return m_ren->rbuf(); }
rendering_buffer& rbuf() { return m_ren->rbuf(); }
private:
base_ren_type* m_ren;
color_type m_fill_color;
color_type m_line_color;
int m_curr_x;
int m_curr_y;
};
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -18,215 +18,247 @@
#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(ren_type& ren, glyph_gen_type& glyph) //==============================================renderer_raster_htext_solid
: m_ren(&ren) template<class BaseRenderer, class GlyphGenerator>
, m_glyph(&glyph) class renderer_raster_htext_solid
{}
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; public:
while (*str) typedef BaseRenderer ren_type;
{ typedef GlyphGenerator glyph_gen_type;
m_glyph->prepare(&r, x, y, *str, flip); typedef typename glyph_gen_type::glyph_rect glyph_rect;
if (r.x2 >= r.x1) typedef typename ren_type::color_type color_type;
{
int i;
if (flip)
{
for (i = r.y1; i <= r.y2; i++)
{
m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1), m_color, m_glyph->span(r.y2 - i));
}
}
else
{
for (i = r.y1; i <= r.y2; i++)
{
m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1), m_color, m_glyph->span(i - r.y1));
}
}
}
x += r.dx;
y += r.dy;
++str;
}
}
private: renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph) :
ren_type* m_ren; m_ren(&ren),
glyph_gen_type* m_glyph; m_glyph(&glyph)
color_type m_color;
};
//=============================================renderer_raster_vtext_solid
template<class BaseRenderer, class GlyphGenerator>
class renderer_raster_vtext_solid
{
public:
typedef BaseRenderer ren_type;
typedef GlyphGenerator glyph_gen_type;
typedef typename glyph_gen_type::glyph_rect glyph_rect;
typedef typename ren_type::color_type color_type;
renderer_raster_vtext_solid(ren_type& ren, glyph_gen_type& glyph)
: m_ren(&ren)
, m_glyph(&glyph)
{}
//--------------------------------------------------------------------
void color(const color_type& c) { m_color = c; }
const color_type& color() const { return m_color; }
//--------------------------------------------------------------------
template<class CharT>
void render_text(double x, double y, const CharT* str, bool flip = false)
{
glyph_rect r;
while (*str)
{
m_glyph->prepare(&r, x, y, *str, !flip);
if (r.x2 >= r.x1)
{
int i;
if (flip)
{
for (i = r.y1; i <= r.y2; i++)
{
m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1), m_color, m_glyph->span(i - r.y1));
}
}
else
{
for (i = r.y1; i <= r.y2; i++)
{
m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1), m_color, m_glyph->span(r.y2 - i));
}
}
}
x += r.dx;
y += r.dy;
++str;
}
}
private:
ren_type* m_ren;
glyph_gen_type* m_glyph;
color_type m_color;
};
//===================================================renderer_raster_htext
template<class ScanlineRenderer, class GlyphGenerator>
class renderer_raster_htext
{
public:
typedef ScanlineRenderer ren_type;
typedef GlyphGenerator glyph_gen_type;
typedef typename glyph_gen_type::glyph_rect glyph_rect;
class scanline_single_span
{
public:
typedef agg::cover_type cover_type;
//----------------------------------------------------------------
struct const_span
{
int x;
unsigned len;
const cover_type* covers;
const_span() {}
const_span(int x_, unsigned len_, const cover_type* covers_)
: x(x_)
, len(len_)
, covers(covers_)
{}
};
typedef const const_span* const_iterator;
//----------------------------------------------------------------
scanline_single_span(int x, int y, unsigned len, const cover_type* covers)
: m_y(y)
, m_span(x, len, covers)
{} {}
void attach(ren_type& ren) { m_ren = &ren; }
//---------------------------------------------------------------- //--------------------------------------------------------------------
int y() const { return m_y; } void color(const color_type& c) { m_color = c; }
unsigned num_spans() const { return 1; } const color_type& color() const { return m_color; }
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)
{
int i;
if(flip)
{
for(i = r.y1; i <= r.y2; i++)
{
m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1),
m_color,
m_glyph->span(r.y2 - i));
}
}
else
{
for(i = r.y1; i <= r.y2; i++)
{
m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1),
m_color,
m_glyph->span(i - r.y1));
}
}
}
x += r.dx;
y += r.dy;
++str;
}
}
private:
ren_type* m_ren;
glyph_gen_type* m_glyph;
color_type m_color;
}; };
//--------------------------------------------------------------------
renderer_raster_htext(ren_type& ren, glyph_gen_type& glyph)
: m_ren(&ren)
, m_glyph(&glyph)
{}
//--------------------------------------------------------------------
template<class CharT> //=============================================renderer_raster_vtext_solid
void render_text(double x, double y, const CharT* str, bool flip = false) template<class BaseRenderer, class GlyphGenerator>
class renderer_raster_vtext_solid
{ {
glyph_rect r; public:
while (*str) 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)
{ {
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; void color(const color_type& c) { m_color = c; }
glyph_gen_type* m_glyph; const color_type& color() const { return m_color; }
};
} // namespace agg //--------------------------------------------------------------------
template<class CharT>
void render_text(double x, double y, const CharT* str, bool flip=false)
{
glyph_rect r;
while(*str)
{
m_glyph->prepare(&r, x, y, *str, !flip);
if(r.x2 >= r.x1)
{
int i;
if(flip)
{
for(i = r.y1; i <= r.y2; i++)
{
m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1),
m_color,
m_glyph->span(i - r.y1));
}
}
else
{
for(i = r.y1; i <= r.y2; i++)
{
m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1),
m_color,
m_glyph->span(r.y2 - i));
}
}
}
x += r.dx;
y += r.dy;
++str;
}
}
private:
ren_type* m_ren;
glyph_gen_type* m_glyph;
color_type m_color;
};
//===================================================renderer_raster_htext
template<class ScanlineRenderer, class GlyphGenerator>
class renderer_raster_htext
{
public:
typedef ScanlineRenderer ren_type;
typedef GlyphGenerator glyph_gen_type;
typedef typename glyph_gen_type::glyph_rect glyph_rect;
class scanline_single_span
{
public:
typedef agg::cover_type cover_type;
//----------------------------------------------------------------
struct const_span
{
int x;
unsigned len;
const cover_type* covers;
const_span() {}
const_span(int x_, unsigned len_, const cover_type* covers_) :
x(x_), len(len_), covers(covers_)
{}
};
typedef const const_span* const_iterator;
//----------------------------------------------------------------
scanline_single_span(int x, int y, unsigned len,
const cover_type* covers) :
m_y(y),
m_span(x, len, covers)
{}
//----------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return 1; }
const_iterator begin() const { return &m_span; }
private:
//----------------------------------------------------------------
int m_y;
const_span m_span;
};
//--------------------------------------------------------------------
renderer_raster_htext(ren_type& ren, glyph_gen_type& glyph) :
m_ren(&ren),
m_glyph(&glyph)
{
}
//--------------------------------------------------------------------
template<class CharT>
void render_text(double x, double y, const CharT* str, bool flip=false)
{
glyph_rect r;
while(*str)
{
m_glyph->prepare(&r, x, y, *str, flip);
if(r.x2 >= r.x1)
{
m_ren->prepare();
int i;
if(flip)
{
for(i = r.y1; i <= r.y2; i++)
{
m_ren->render(
scanline_single_span(r.x1,
i,
(r.x2 - r.x1 + 1),
m_glyph->span(r.y2 - i)));
}
}
else
{
for(i = r.y1; i <= r.y2; i++)
{
m_ren->render(
scanline_single_span(r.x1,
i,
(r.x2 - r.x1 + 1),
m_glyph->span(i - r.y1)));
}
}
}
x += r.dx;
y += r.dy;
++str;
}
}
private:
ren_type* m_ren;
glyph_gen_type* m_glyph;
};
}
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -22,261 +22,284 @@
#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
row_accessor() template<class T> class 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)
{ {
attach(buf, width, height, stride); public:
} typedef const_row_info<T> row_data;
//-------------------------------------------------------------------- //-------------------------------------------------------------------
void attach(T* buf, unsigned width, unsigned height, int stride) row_accessor() :
{ m_buf(0),
m_buf = m_start = buf; m_start(0),
m_width = width; m_width(0),
m_height = height; m_height(0),
m_stride = stride; m_stride(0)
if (stride < 0)
{ {
m_start = m_buf - int(height - 1) * stride;
} }
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
AGG_INLINE T* buf() { return m_buf; } row_accessor(T* buf, unsigned width, unsigned height, int stride) :
AGG_INLINE const T* buf() const { return m_buf; } m_buf(0),
AGG_INLINE unsigned width() const { return m_width; } m_start(0),
AGG_INLINE unsigned height() const { return m_height; } m_width(0),
AGG_INLINE int stride() const { return m_stride; } m_height(0),
AGG_INLINE unsigned stride_abs() const { return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); } m_stride(0)
//--------------------------------------------------------------------
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); attach(buf, width, height, stride);
} }
}
//--------------------------------------------------------------------
void clear(T value) //--------------------------------------------------------------------
{ void attach(T* buf, unsigned width, unsigned height, int stride)
unsigned y;
unsigned w = width();
unsigned stride = stride_abs();
for (y = 0; y < height(); y++)
{ {
T* p = row_ptr(0, y, w); m_buf = m_start = buf;
unsigned x; m_width = width;
for (x = 0; x < stride; x++) m_height = height;
{ m_stride = stride;
*p++ = value; if(stride < 0)
{
m_start = m_buf - int(height - 1) * stride;
} }
} }
}
private: //--------------------------------------------------------------------
//-------------------------------------------------------------------- AGG_INLINE T* buf() { return m_buf; }
T* m_buf; // Pointer to rendering buffer AGG_INLINE const T* buf() const { return m_buf; }
T* m_start; // Pointer to first pixel depending on stride AGG_INLINE unsigned width() const { return m_width; }
unsigned m_width; // Width in pixels AGG_INLINE unsigned height() const { return m_height; }
unsigned m_height; // Height in pixels AGG_INLINE int stride() const { return m_stride; }
int m_stride; // Number of bytes per row. Can be < 0 AGG_INLINE unsigned stride_abs() const
};
//==========================================================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())
{ {
m_rows.resize(height); return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride);
}
else if (height == 0)
{
return;
} }
T* row_ptr = m_buf; //--------------------------------------------------------------------
AGG_INLINE T* row_ptr(int, int y, unsigned)
if (stride < 0) {
{ return m_start + y * m_stride;
row_ptr = m_buf - int(height - 1) * 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));
} }
T** rows = &m_rows[0]; //--------------------------------------------------------------------
template<class RenBuf>
while (height > 0) void copy_from(const RenBuf& src)
{ {
*rows++ = row_ptr; unsigned h = height();
row_ptr += stride; if(src.height() < h) h = src.height();
--height;
} unsigned l = stride_abs();
} if(src.stride_abs() < l) l = src.stride_abs();
l *= sizeof(T);
//-------------------------------------------------------------------- unsigned y;
AGG_INLINE T* buf() { return m_buf; } unsigned w = width();
AGG_INLINE const T* buf() const { return m_buf; } for (y = 0; y < h; y++)
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_rows[y]; }
AGG_INLINE T* row_ptr(int y) { return m_rows[y]; }
AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; }
AGG_INLINE row_data row(int y) const { return row_data(0, m_width - 1, m_rows[y]); }
//--------------------------------------------------------------------
T const* const* rows() const { return &m_rows[0]; }
//--------------------------------------------------------------------
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; memcpy(row_ptr(0, y, w), src.row_ptr(y), l);
} }
} }
}
private: //--------------------------------------------------------------------
//-------------------------------------------------------------------- void clear(T value)
T* m_buf; // Pointer to rendering buffer {
pod_array<T*> m_rows; // Pointers to each row of the buffer unsigned y;
unsigned m_width; // Width in pixels unsigned w = width();
unsigned m_height; // Height in pixels unsigned stride = stride_abs();
int m_stride; // Number of bytes per row. Can be < 0 for(y = 0; y < height(); y++)
}; {
T* p = row_ptr(0, y, w);
unsigned x;
for(x = 0; x < stride; x++)
{
*p++ = value;
}
}
}
//========================================================rendering_buffer private:
// //--------------------------------------------------------------------
// The definition of the main type for accessing the rows in the frame T* m_buf; // Pointer to rendering buffer
// buffer. It provides functionality to navigate to the rows in a T* m_start; // Pointer to first pixel depending on stride
// rectangular matrix, from top to bottom or from bottom to top depending unsigned m_width; // Width in pixels
// on stride. unsigned m_height; // Height in pixels
// 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
// when creating. For example, on typical Intel Pentium hardware //==========================================================row_ptr_cache
// row_ptr_cache speeds span_image_filter_rgb_nn up to 10% template<class T> class row_ptr_cache
// {
// It's used only in short hand typedefs like pixfmt_rgba32 and can be public:
// redefined in agg_config.h typedef const_row_info<T> row_data;
// In real applications you can use both, depending on your needs
//------------------------------------------------------------------------ //-------------------------------------------------------------------
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())
{
m_rows.resize(height);
}
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;
}
}
//--------------------------------------------------------------------
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_rows[y];
}
AGG_INLINE T* row_ptr(int y) { return m_rows[y]; }
AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; }
AGG_INLINE row_data row (int y) const
{
return row_data(0, m_width-1, m_rows[y]);
}
//--------------------------------------------------------------------
T const* const* rows() const { return &m_rows[0]; }
//--------------------------------------------------------------------
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
pod_array<T*> m_rows; // Pointers to each row of the buffer
unsigned m_width; // Width in pixels
unsigned m_height; // Height in pixels
int m_stride; // Number of bytes per row. Can be < 0
};
//========================================================rendering_buffer
//
// The definition of the main type for accessing the rows in the frame
// buffer. It provides functionality to navigate to the rows in a
// rectangular matrix, from top to bottom or from bottom to top depending
// on stride.
//
// row_accessor is cheap to create/destroy, but performs one multiplication
// when calling row_ptr().
//
// row_ptr_cache creates an array of pointers to rows, so, the access
// via row_ptr() may be faster. But it requires memory allocation
// when creating. For example, on typical Intel Pentium hardware
// row_ptr_cache speeds span_image_filter_rgb_nn up to 10%
//
// It's used only in short hand typedefs like pixfmt_rgba32 and can be
// redefined in agg_config.h
// In real applications you can use both, depending on your needs
//------------------------------------------------------------------------
#ifdef AGG_RENDERING_BUFFER #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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -22,114 +22,116 @@
#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_dynarow() { init(0, 0, 0); } // 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.
rendering_buffer_dynarow() // Generally it's more efficient to use this class as a temporary buffer
: m_rows() // for rendering a few lines and then to blend it with another buffer.
, m_width(0) //
, m_height(0) class rendering_buffer_dynarow
, 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)
{ {
memset(&m_rows[0], 0, sizeof(row_data) * height); public:
} 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)
{ {
pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width); init(0,0,0);
} }
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; } //--------------------------------------------------------------------
unsigned height() const { return m_height; } void init(unsigned width, unsigned height, unsigned byte_width)
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)
{ {
if (x < r->x1) unsigned i;
for(i = 0; i < m_height; ++i)
{ {
r->x1 = x; pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width);
} }
if (x2 > r->x2) if(width && height)
{ {
r->x2 = x2; m_width = width;
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)
{ {
int8u* p = pod_allocator<int8u>::allocate(m_byte_width); row_data* r = &m_rows[y];
r->ptr = p; int x2 = x + len - 1;
r->x1 = x; if(r->ptr)
r->x2 = x2; {
memset(p, 0, m_byte_width); if(x < r->x1) { r->x1 = x; }
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -23,47 +23,50 @@
#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
{ {
public: //------------------------------------------------------------rounded_rect
rounded_rect() {} //
rounded_rect(double x1, double y1, double x2, double y2, double r); // See Implemantation agg_rounded_rect.cpp
//
class rounded_rect
{
public:
rounded_rect() {}
rounded_rect(double x1, double y1, double x2, double y2, double r);
void rect(double x1, double y1, double x2, double y2); void 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, double rx3, double ry3, double rx4, double ry4); void radius(double rx1, double ry1, double rx2, double ry2,
void normalize_radius(); double rx3, double ry3, double rx4, double ry4);
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -17,12 +17,12 @@
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
// Adaptation for 32-bit screen coordinates (scanline32_bin) has been sponsored by // Adaptation for 32-bit screen coordinates (scanline32_bin) has been sponsored by
// Liberty Technology Systems, Inc., visit http://lib-sys.com // Liberty Technology Systems, Inc., visit http://lib-sys.com
// //
// Liberty Technology Systems, Inc. is the provider of // Liberty Technology Systems, Inc. is the provider of
// PostScript and PDF technology for software developers. // PostScript and PDF technology for software developers.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
#ifndef AGG_SCANLINE_BIN_INCLUDED #ifndef AGG_SCANLINE_BIN_INCLUDED
@ -30,215 +30,235 @@
#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;
struct span //=============================================================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
{ {
int16 x; public:
int16 len; typedef int32 coord_type;
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
{ {
unsigned max_len = max_x - min_x + 3; public:
if (max_len > m_spans.size()) typedef int32 coord_type;
//--------------------------------------------------------------------
struct span
{ {
m_spans.resize(max_len); span() {}
} span(coord_type x_, coord_type len_) : x(x_), len(len_) {}
m_last_x = 0x7FFFFFF0;
m_cur_span = &m_spans[0];
}
//-------------------------------------------------------------------- coord_type x;
void add_cell(int x, unsigned) coord_type len;
{ };
if (x == m_last_x + 1) typedef pod_bvector<span, 4> span_array_type;
//--------------------------------------------------------------------
class const_iterator
{ {
m_cur_span->len++; public:
} const_iterator(const span_array_type& spans) :
else 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_cur_span; m_last_x = 0x7FFFFFF0;
m_cur_span->x = (int16)x; m_spans.remove_all();
m_cur_span->len = 1;
} }
m_last_x = x;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned) void add_cell(int x, unsigned)
{
if (x == m_last_x + 1)
{ {
m_cur_span->len = (int16)(m_cur_span->len + len); if(x == m_last_x+1)
{
m_spans.last().len++;
}
else
{
m_spans.add(span(coord_type(x), 1));
}
m_last_x = x;
} }
else
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned)
{ {
++m_cur_span; if(x == m_last_x+1)
m_cur_span->x = (int16)x; {
m_cur_span->len = (int16)len; m_spans.last().len += coord_type(len);
}
else
{
m_spans.add(span(coord_type(x), coord_type(len)));
}
m_last_x = x + len - 1;
} }
m_last_x = x + len - 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void add_cells(int x, unsigned len, const void*) { add_span(x, len, 0); } void add_cells(int x, unsigned len, const void*)
{
add_span(x, len, 0);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void finalize(int y) { m_y = y; } void finalize(int y)
{
m_y = y;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void reset_spans() void reset_spans()
{ {
m_last_x = 0x7FFFFFF0; m_last_x = 0x7FFFFFF0;
m_cur_span = &m_spans[0]; m_spans.remove_all();
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
int y() const { return m_y; } int y() const { return m_y; }
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } unsigned num_spans() const { return m_spans.size(); }
const_iterator begin() const { return &m_spans[1]; } const_iterator begin() const { return const_iterator(m_spans); }
private: private:
scanline_bin(const scanline_bin&); scanline32_bin(const scanline32_bin&);
const scanline_bin operator=(const scanline_bin&); const scanline32_bin operator = (const scanline32_bin&);
int m_last_x; unsigned m_max_len;
int m_y; int m_last_x;
pod_array<span> m_spans; int m_y;
span* m_cur_span; span_array_type m_spans;
};
//===========================================================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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -17,291 +17,313 @@
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
// Adaptation for 32-bit screen coordinates (scanline32_p) has been sponsored by // Adaptation for 32-bit screen coordinates (scanline32_p) has been sponsored by
// Liberty Technology Systems, Inc., visit http://lib-sys.com // Liberty Technology Systems, Inc., visit http://lib-sys.com
// //
// Liberty Technology Systems, Inc. is the provider of // Liberty Technology Systems, Inc. is the provider of
// PostScript and PDF technology for software developers. // PostScript and PDF technology for software developers.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
#ifndef AGG_SCANLINE_P_INCLUDED #ifndef AGG_SCANLINE_P_INCLUDED
#define AGG_SCANLINE_P_INCLUDED #define AGG_SCANLINE_P_INCLUDED
#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
{ {
coord_type x; public:
coord_type len; // If negative, it's a solid span, covers is valid typedef scanline_p8 self_type;
const cover_type* covers; typedef int8u cover_type;
}; typedef int16 coord_type;
typedef span* iterator; //--------------------------------------------------------------------
typedef const span* const_iterator; struct span
{
coord_type x;
coord_type len; // If negative, it's a solid span, covers is valid
const cover_type* covers;
};
scanline_p8() typedef span* iterator;
: m_last_x(0x7FFFFFF0) typedef const span* const_iterator;
, m_covers()
, m_cover_ptr(0)
, m_spans()
, m_cur_span(0)
{}
//-------------------------------------------------------------------- scanline_p8() :
void reset(int min_x, int max_x) m_last_x(0x7FFFFFF0),
{ m_covers(),
unsigned max_len = max_x - min_x + 3; m_cover_ptr(0),
if (max_len > m_spans.size()) m_spans(),
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 add_cell(int x, unsigned cover) void reset(int min_x, int max_x)
{
*m_cover_ptr = (cover_type)cover;
if (x == m_last_x + 1 && m_cur_span->len > 0)
{ {
m_cur_span->len++; unsigned max_len = max_x - min_x + 3;
if(max_len > m_spans.size())
{
m_spans.resize(max_len);
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_cur_span = &m_spans[0];
m_cur_span->len = 0;
} }
else
{
m_cur_span++;
m_cur_span->covers = m_cover_ptr;
m_cur_span->x = (int16)x;
m_cur_span->len = 1;
}
m_last_x = x;
m_cover_ptr++;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void add_cells(int x, unsigned len, const cover_type* covers) void add_cell(int x, unsigned cover)
{
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;
m_cur_span++; if(x == m_last_x+1 && m_cur_span->len > 0)
m_cur_span->covers = m_cover_ptr++; {
m_cur_span->x = (int16)x; m_cur_span->len++;
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 finalize(int y) { m_y = y; } 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 reset_spans() void add_span(int x, unsigned len, unsigned cover)
{ {
m_last_x = 0x7FFFFFF0; if(x == m_last_x+1 &&
m_cover_ptr = &m_covers[0]; m_cur_span->len < 0 &&
m_cur_span = &m_spans[0]; cover == *m_cur_span->covers)
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;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
int y() const { return m_y; } void finalize(int y)
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } {
const_iterator begin() const { return &m_spans[1]; } m_y = y;
}
private: //--------------------------------------------------------------------
scanline_p8(const self_type&); void reset_spans()
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 m_y; int y() const { return m_y; }
pod_array<cover_type> m_covers; unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
cover_type* m_cover_ptr; const_iterator begin() const { return &m_spans[1]; }
pod_array<span> m_spans;
span* m_cur_span;
};
//==========================================================scanline32_p8 private:
class scanline32_p8 scanline_p8(const self_type&);
{ const self_type& operator = (const self_type&);
public:
typedef scanline32_p8 self_type;
typedef int8u cover_type;
typedef int32 coord_type;
struct span int m_last_x;
{ int m_y;
span() {} pod_array<cover_type> m_covers;
span(coord_type x_, coord_type len_, const cover_type* covers_) cover_type* m_cover_ptr;
: x(x_) pod_array<span> m_spans;
, len(len_) span* m_cur_span;
, 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)
{
unsigned max_len = max_x - min_x + 3;
if (max_len > m_covers.size())
{
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_spans.remove_all();
}
//--------------------------------------------------------------------
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)
{
m_spans.last().len++;
}
else
{
m_spans.add(span(coord_type(x), 1, m_cover_ptr));
}
m_last_x = x;
m_cover_ptr++;
}
//--------------------------------------------------------------------
void add_cells(int x, unsigned len, const cover_type* covers)
{
memcpy(m_cover_ptr, covers, len * sizeof(cover_type));
if (x == m_last_x + 1 && m_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)
//==========================================================scanline32_p8
class scanline32_p8
{ {
if (x == m_last_x + 1 && m_spans.size() && m_spans.last().len < 0 && cover == *m_spans.last().covers) public:
typedef scanline32_p8 self_type;
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_spans.last().len -= coord_type(len);
} }
else
//--------------------------------------------------------------------
void reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 3;
if(max_len > m_covers.size())
{
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_cover_ptr = &m_covers[0];
m_spans.remove_all();
}
//--------------------------------------------------------------------
void add_cell(int x, unsigned cover)
{ {
*m_cover_ptr = cover_type(cover); *m_cover_ptr = cover_type(cover);
m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++)); if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0)
{
m_spans.last().len++;
}
else
{
m_spans.add(span(coord_type(x), 1, m_cover_ptr));
}
m_last_x = x;
m_cover_ptr++;
} }
m_last_x = x + len - 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void finalize(int y) { m_y = y; } 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 reset_spans() void add_span(int x, unsigned len, unsigned cover)
{ {
m_last_x = 0x7FFFFFF0; if(x == m_last_x+1 &&
m_cover_ptr = &m_covers[0]; m_spans.size() &&
m_spans.remove_all(); m_spans.last().len < 0 &&
} cover == *m_spans.last().covers)
{
m_spans.last().len -= coord_type(len);
}
else
{
*m_cover_ptr = cover_type(cover);
m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++));
}
m_last_x = x + len - 1;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
int y() const { return m_y; } void finalize(int y)
unsigned num_spans() const { return m_spans.size(); } {
const_iterator begin() const { return const_iterator(m_spans); } m_y = y;
}
private: //--------------------------------------------------------------------
scanline32_p8(const self_type&); void reset_spans()
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 m_last_x; int y() const { return m_y; }
int m_y; unsigned num_spans() const { return m_spans.size(); }
pod_array<cover_type> m_covers; const_iterator begin() const { return const_iterator(m_spans); }
cover_type* m_cover_ptr;
span_array_type m_spans; private:
}; 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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -13,12 +13,12 @@
// http://www.antigrain.com // http://www.antigrain.com
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
// Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by // Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by
// Liberty Technology Systems, Inc., visit http://lib-sys.com // Liberty Technology Systems, Inc., visit http://lib-sys.com
// //
// Liberty Technology Systems, Inc. is the provider of // Liberty Technology Systems, Inc. is the provider of
// PostScript and PDF technology for software developers. // PostScript and PDF technology for software developers.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
#ifndef AGG_SCANLINE_U_INCLUDED #ifndef AGG_SCANLINE_U_INCLUDED
@ -26,456 +26,475 @@
#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
{ {
public: //=============================================================scanline_u8
typedef scanline_u8 self_type; //
typedef int8u cover_type; // Unpacked scanline container class
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
struct span // 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
{ {
coord_type x; public:
coord_type len; typedef scanline_u8 self_type;
cover_type* covers; typedef int8u cover_type;
}; typedef int16 coord_type;
typedef span* iterator; //--------------------------------------------------------------------
typedef const span* const_iterator; struct span
//--------------------------------------------------------------------
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())
{ {
m_spans.resize(max_len); coord_type x;
m_covers.resize(max_len); coord_type len;
} cover_type* covers;
m_last_x = 0x7FFFFFF0; };
m_min_x = min_x;
m_cur_span = &m_spans[0];
}
//-------------------------------------------------------------------- typedef span* iterator;
void add_cell(int x, unsigned cover) typedef const span* const_iterator;
{
x -= m_min_x; //--------------------------------------------------------------------
m_covers[x] = (cover_type)cover; scanline_u8() :
if (x == m_last_x + 1) m_min_x(0),
m_last_x(0x7FFFFFF0),
m_cur_span(0)
{}
//--------------------------------------------------------------------
void reset(int min_x, int max_x)
{ {
m_cur_span->len++; unsigned max_len = max_x - min_x + 2;
} if(max_len > m_spans.size())
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;
};
//==========================================================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); m_spans.resize(max_len);
++span; m_covers.resize(max_len);
} while (--count); }
m_last_x = 0x7FFFFFF0;
m_min_x = min_x;
m_cur_span = &m_spans[0];
} }
}
private: //--------------------------------------------------------------------
const AlphaMask* m_alpha_mask; void add_cell(int x, unsigned cover)
};
//===========================================================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()
{}
//--------------------------------------------------------------------
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); x -= m_min_x;
} m_covers[x] = (cover_type)cover;
m_last_x = 0x7FFFFFF0; if(x == m_last_x+1)
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); m_cur_span->len++;
++span; }
} while (--count); 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;
} }
}
private: //--------------------------------------------------------------------
const AlphaMask* m_alpha_mask; 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;
}
} // namespace agg //--------------------------------------------------------------------
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;
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()
{}
//--------------------------------------------------------------------
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;
};
}
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -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;
if (s > 0.0 && vs.size() > 1) //===========================================================shorten_path
template<class VertexSequence>
void shorten_path(VertexSequence& vs, double s, unsigned closed = 0)
{ {
double d; typedef typename VertexSequence::value_type vertex_type;
int n = int(vs.size() - 2);
while (n) if(s > 0.0 && vs.size() > 1)
{ {
d = vs[n].dist; double d;
if (d > s) int n = int(vs.size() - 2);
break; while(n)
vs.remove_last(); {
s -= d; d = vs[n].dist;
--n; if(d > s) break;
}
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();
vs.close(closed != 0); s -= d;
--n;
}
if(vs.size() < 2)
{
vs.remove_all();
}
else
{
n = vs.size() - 1;
vertex_type& prev = vs[n-1];
vertex_type& last = vs[n];
d = (prev.dist - s) / prev.dist;
double x = prev.x + (last.x - prev.x) * d;
double y = prev.y + (last.y - prev.y) * d;
last.x = x;
last.y = y;
if(!prev(last)) vs.remove_last();
vs.close(closed != 0);
}
} }
} }
} }
} // namespace agg
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -22,119 +22,126 @@
#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;
for (i = 0; i < n; i++) //=============================================================swap_arrays
template<class T> void swap_arrays(T* a1, T* a2, unsigned n)
{ {
T tmp = *a1; unsigned i;
*a1++ = *a2; for(i = 0; i < n; i++)
*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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -18,34 +18,37 @@
#include "agg_array.h" #include "agg_array.h"
namespace agg { namespace agg
//----------------------------------------------------------span_allocator
template<class ColorT>
class span_allocator
{ {
public: //----------------------------------------------------------span_allocator
typedef ColorT color_type; template<class ColorT> class span_allocator
//--------------------------------------------------------------------
AGG_INLINE color_type* allocate(unsigned span_len)
{ {
if (span_len > m_span.size()) public:
typedef ColorT color_type;
//--------------------------------------------------------------------
AGG_INLINE color_type* allocate(unsigned span_len)
{ {
// To reduce the number of reallocs we align the if(span_len > m_span.size())
// span_len to 256 color elements. {
// Well, I just like this number and it looks reasonable. // To reduce the number of reallocs we align the
//----------------------- // span_len to 256 color elements.
m_span.resize(((span_len + 255) >> 8) << 8); // Well, I just like this number and it looks reasonable.
//-----------------------
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -18,41 +18,39 @@
#include "agg_basics.h" #include "agg_basics.h"
namespace agg { namespace agg
//----------------------------------------------------------span_converter
template<class SpanGenerator, class SpanConverter>
class span_converter
{ {
public: //----------------------------------------------------------span_converter
typedef typename SpanGenerator::color_type color_type; template<class SpanGenerator, class SpanConverter> class span_converter
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()
{ {
m_span_gen->prepare(); public:
m_span_cnv->prepare(); typedef typename SpanGenerator::color_type color_type;
}
//-------------------------------------------------------------------- span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv) :
void generate(color_type* span, int x, int y, unsigned len) m_span_gen(&span_gen), m_span_cnv(&span_cnv) {}
{
m_span_gen->generate(span, x, y, len);
m_span_cnv->generate(span, x, y, len);
}
private: void attach_generator(SpanGenerator& span_gen) { m_span_gen = &span_gen; }
SpanGenerator* m_span_gen; void attach_converter(SpanConverter& span_cnv) { m_span_cnv = &span_cnv; }
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -19,176 +19,154 @@
#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;
struct coord_type //============================================================span_gouraud
template<class ColorT> class span_gouraud
{ {
double x; public:
double y; typedef ColorT color_type;
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -13,12 +13,12 @@
// http://www.antigrain.com // http://www.antigrain.com
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
// Adaptation for high precision colors has been sponsored by // Adaptation for high precision colors has been sponsored by
// Liberty Technology Systems, Inc., visit http://lib-sys.com // Liberty Technology Systems, Inc., visit http://lib-sys.com
// //
// Liberty Technology Systems, Inc. is the provider of // Liberty Technology Systems, Inc. is the provider of
// PostScript and PDF technology for software developers. // PostScript and PDF technology for software developers.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
#ifndef AGG_SPAN_GOURAUD_GRAY_INCLUDED #ifndef AGG_SPAN_GOURAUD_GRAY_INCLUDED
@ -29,222 +29,213 @@
#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 };
private: //=======================================================span_gouraud_gray
//-------------------------------------------------------------------- template<class ColorT> class span_gouraud_gray : public span_gouraud<ColorT>
struct gray_calc
{ {
void init(const coord_type& c1, const coord_type& c2) 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
};
private:
//--------------------------------------------------------------------
struct gray_calc
{ {
m_x1 = c1.x - 0.5; void init(const coord_type& c1, const coord_type& c2)
m_y1 = c1.y - 0.5; {
m_dx = c2.x - c1.x; m_x1 = c1.x - 0.5;
double dy = c2.y - c1.y; m_y1 = c1.y - 0.5;
m_1dy = (std::fabs(dy) < 1e-10) ? 1e10 : 1.0 / dy; m_dx = c2.x - c1.x;
m_v1 = c1.color.v; double dy = c2.y - c1.y;
m_a1 = c1.color.a; m_1dy = (std::fabs(dy) < 1e-10) ? 1e10 : 1.0 / dy;
m_dv = c2.color.v - m_v1; m_v1 = c1.color.v;
m_da = c2.color.a - m_a1; 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)
{ {
double k = (y - m_y1) * m_1dy; m_c1.calc(y);
if (k < 0.0) const gray_calc* pc1 = &m_c1;
k = 0.0; const gray_calc* pc2 = &m_c2;
if (k > 1.0)
k = 1.0; if(y < m_y2)
m_v = m_v1 + iround(m_dv * k); {
m_a = m_a1 + iround(m_da * k); // Bottom part of the triangle (first subtriangle)
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;
double m_y1; private:
double m_dx; bool m_swap;
double m_1dy; int m_y2;
int m_v1; gray_calc m_c1;
int m_a1; gray_calc m_c2;
int m_dv; gray_calc m_c3;
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -13,12 +13,12 @@
// http://www.antigrain.com // http://www.antigrain.com
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
// Adaptation for high precision colors has been sponsored by // Adaptation for high precision colors has been sponsored by
// Liberty Technology Systems, Inc., visit http://lib-sys.com // Liberty Technology Systems, Inc., visit http://lib-sys.com
// //
// Liberty Technology Systems, Inc. is the provider of // Liberty Technology Systems, Inc. is the provider of
// PostScript and PDF technology for software developers. // PostScript and PDF technology for software developers.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
#ifndef AGG_SPAN_GOURAUD_RGBA_INCLUDED #ifndef AGG_SPAN_GOURAUD_RGBA_INCLUDED
@ -29,271 +29,249 @@
#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 };
private: //=======================================================span_gouraud_rgba
//-------------------------------------------------------------------- template<class ColorT> class span_gouraud_rgba : public span_gouraud<ColorT>
struct rgba_calc
{ {
void init(const coord_type& c1, const coord_type& c2) 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
};
private:
//--------------------------------------------------------------------
struct rgba_calc
{ {
m_x1 = c1.x - 0.5; void init(const coord_type& c1, const coord_type& c2)
m_y1 = c1.y - 0.5; {
m_dx = c2.x - c1.x; m_x1 = c1.x - 0.5;
double dy = c2.y - c1.y; m_y1 = c1.y - 0.5;
m_1dy = (dy < 1e-5) ? 1e5 : 1.0 / dy; m_dx = c2.x - c1.x;
m_r1 = c1.color.r; double dy = c2.y - c1.y;
m_g1 = c1.color.g; m_1dy = (dy < 1e-5) ? 1e5 : 1.0 / dy;
m_b1 = c1.color.b; m_r1 = c1.color.r;
m_a1 = c1.color.a; m_g1 = c1.color.g;
m_dr = c2.color.r - m_r1; m_b1 = c1.color.b;
m_dg = c2.color.g - m_g1; m_a1 = c1.color.a;
m_db = c2.color.b - m_b1; m_dr = c2.color.r - m_r1;
m_da = c2.color.a - m_a1; 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)
{ {
double k = (y - m_y1) * m_1dy; m_rgba1.calc(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y);
if (k < 0.0) const rgba_calc* pc1 = &m_rgba1;
k = 0.0; const rgba_calc* pc2 = &m_rgba2;
if (k > 1.0)
k = 1.0; if(y <= m_y2)
m_r = m_r1 + iround(m_dr * k); {
m_g = m_g1 + iround(m_dg * k); // Bottom part of the triangle (first subtriangle)
m_b = m_b1 + iround(m_db * k); //-------------------------
m_a = m_a1 + iround(m_da * k); m_rgba2.calc(y + m_rgba2.m_1dy);
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;
}
} }
double m_x1; private:
double m_y1; bool m_swap;
double m_dx; int m_y2;
double m_1dy; rgba_calc m_rgba1;
int m_r1; rgba_calc m_rgba2;
int m_g1; rgba_calc m_rgba3;
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -23,326 +23,342 @@
#include "agg_math.h" #include "agg_math.h"
#include "agg_array.h" #include "agg_array.h"
namespace agg {
enum gradient_subpixel_scale_e { namespace agg
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 downscale_shift_e { downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift }; enum gradient_subpixel_scale_e
//--------------------------------------------------------------------
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; gradient_subpixel_shift = 4, //-----gradient_subpixel_shift
if (dd < 1) gradient_subpixel_scale = 1 << gradient_subpixel_shift, //-----gradient_subpixel_scale
dd = 1; gradient_subpixel_mask = gradient_subpixel_scale - 1 //-----gradient_subpixel_mask
m_interpolator->begin(x + 0.5, y + 0.5, len); };
do
//==========================================================span_gradient
template<class ColorT,
class Interpolator,
class GradientF,
class ColorF>
class span_gradient
{
public:
typedef Interpolator interpolator_type;
typedef ColorT color_type;
enum downscale_shift_e
{ {
m_interpolator->coordinates(&x, &y); downscale_shift = interpolator_type::subpixel_shift -
int d = m_gradient_function->calculate(x >> downscale_shift, y >> downscale_shift, m_d2); gradient_subpixel_shift
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; span_gradient() {}
const GradientF* m_gradient_function;
const ColorF* m_color_function;
int m_d1;
int m_d2;
};
//=====================================================gradient_linear_color //--------------------------------------------------------------------
template<class ColorT> span_gradient(interpolator_type& inter,
struct gradient_linear_color const GradientF& gradient_function,
{ const ColorF& color_function,
typedef ColorT color_type; 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))
{}
gradient_linear_color() {} //--------------------------------------------------------------------
gradient_linear_color(const color_type& c1, const color_type& c2, unsigned size = 256) interpolator_type& interpolator() { return *m_interpolator; }
: m_c1(c1) const GradientF& gradient_function() const { return *m_gradient_function; }
, m_c2(c2) const ColorF& color_function() const { return *m_color_function; }
, m_size(size) double d1() const { return double(m_d1) / gradient_subpixel_scale; }
{} double d2() const { return double(m_d2) / gradient_subpixel_scale; }
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 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 colors(const color_type& c1, const color_type& c2, unsigned size = 256) //--------------------------------------------------------------------
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_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
{ {
m_c1 = c1; typedef ColorT color_type;
m_c2 = c2;
m_size = size;
}
color_type m_c1; gradient_linear_color() {}
color_type m_c2; gradient_linear_color(const color_type& c1, const color_type& c2,
unsigned m_size; unsigned size = 256) :
}; m_c1(c1), m_c2(c2), m_size(size) {}
//==========================================================gradient_circle unsigned size() const { return m_size; }
class gradient_circle color_type operator [] (unsigned v) const
{
// 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)
{ {
if (m_fx) return m_c1.gradient(m_c2, double(v) / double(m_size - 1));
{ }
if (m_fx < 0)
++m_fx; void colors(const color_type& c1, const color_type& c2, unsigned size = 256)
else {
--m_fx; m_c1 = c1;
} m_c2 = c2;
if (m_fy) m_size = size;
{ }
if (m_fy < 0)
++m_fy; color_type m_c1;
else color_type m_c2;
--m_fy; 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);
d = (m_r2 - (m_fx2 + m_fy2)); double 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_y //==============================================================gradient_x
class gradient_y class gradient_x
{
public:
static int calculate(int, int y, int) { return y; }
};
//========================================================gradient_diamond
class gradient_diamond
{
public:
static AGG_INLINE int calculate(int x, int y, int)
{ {
int ax = std::abs(x); public:
int ay = std::abs(y); static int calculate(int x, int, int) { return x; }
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_sqrt_xy //==============================================================gradient_y
class gradient_sqrt_xy class gradient_y
{
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)
{ {
return uround(std::fabs(std::atan2(double(y), double(x))) * double(d) / pi); public:
} static int calculate(int, int y, int) { return y; }
}; };
//=================================================gradient_repeat_adaptor //========================================================gradient_diamond
template<class GradientF> class gradient_diamond
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; public:
if (ret < 0) static AGG_INLINE int calculate(int x, int y, int)
ret += d; {
return ret; int ax = std::abs(x);
} int ay = std::abs(y);
return ax > ay ? ax : ay;
}
};
private: //=============================================================gradient_xy
const GradientF* m_gradient; class gradient_xy
};
//================================================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; public:
int ret = m_gradient->calculate(x, y, d) % d2; static AGG_INLINE int calculate(int x, int y, int d)
if (ret < 0) {
ret += d2; return std::abs(x) * std::abs(y) / d;
if (ret >= d) }
ret = d2 - ret; };
return ret;
}
private: //========================================================gradient_sqrt_xy
const GradientF* m_gradient; class gradient_sqrt_xy
}; {
public:
static AGG_INLINE int calculate(int x, int y, int)
{
return fast_sqrt(std::abs(x) * std::abs(y));
}
};
} // namespace agg //==========================================================gradient_conic
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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -18,103 +18,109 @@
#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
{ {
public: //======================================================span_gradient_alpha
typedef Interpolator interpolator_type; template<class ColorT,
typedef ColorT color_type; class Interpolator,
typedef typename color_type::value_type alpha_type; class GradientF,
class AlphaF>
enum downscale_shift_e { downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift }; class span_gradient_alpha
//--------------------------------------------------------------------
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; public:
if (dd < 1) typedef Interpolator interpolator_type;
dd = 1; typedef ColorT color_type;
m_interpolator->begin(x + 0.5, y + 0.5, len); typedef typename color_type::value_type alpha_type;
do
enum downscale_shift_e
{ {
m_interpolator->coordinates(&x, &y); downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift
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> span_gradient_alpha() {}
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 span_gradient_alpha(interpolator_type& inter,
{ const GradientF& gradient_function,
typedef int8u alpha_type; const AlphaF& alpha_function,
alpha_type operator[](alpha_type x) const { return x; } 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))
{}
//==========================================gradient_alpha_one_munus_x_u8 //--------------------------------------------------------------------
struct gradient_alpha_one_munus_x_u8 interpolator_type& interpolator() { return *m_interpolator; }
{ const GradientF& gradient_function() const { return *m_gradient_function; }
typedef int8u alpha_type; const AlphaF& alpha_function() const { return *m_alpha_function; }
alpha_type operator[](alpha_type x) const { return 255 - x; } double d1() const { return double(m_d1) / gradient_subpixel_scale; }
}; 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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -23,216 +23,224 @@
#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
span_image_filter() {} template<class Source, class Interpolator> class 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)
{ {
m_dx_dbl = dx; public:
m_dy_dbl = dy; typedef Source source_type;
m_dx_int = iround(dx * image_subpixel_scale); typedef Interpolator interpolator_type;
m_dy_int = iround(dy * image_subpixel_scale);
}
void filter_offset(double d) { filter_offset(d, d); }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
interpolator_type& interpolator() { return *m_interpolator; } 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; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
void prepare() {} 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; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
private: void interpolator(interpolator_type& v) { m_interpolator = &v; }
source_type* m_src; void filter(const image_filter_lut& v) { m_filter = &v; }
interpolator_type* m_interpolator; void filter_offset(double dx, double dy)
const image_filter_lut* m_filter;
double m_dx_dbl;
double m_dy_dbl;
unsigned m_dx_int;
unsigned m_dy_int;
};
//==============================================span_image_resample_affine
template<class Source>
class span_image_resample_affine : public span_image_filter<Source, span_interpolator_linear<trans_affine>>
{
public:
typedef Source source_type;
typedef span_interpolator_linear<trans_affine> interpolator_type;
typedef span_image_filter<source_type, interpolator_type> base_type;
//--------------------------------------------------------------------
span_image_resample_affine()
: m_scale_limit(200.0)
, m_blur_x(1.0)
, m_blur_y(1.0)
{}
//--------------------------------------------------------------------
span_image_resample_affine(source_type& src, interpolator_type& inter, const image_filter_lut& filter)
: base_type(src, inter, &filter)
, m_scale_limit(200.0)
, m_blur_x(1.0)
, m_blur_y(1.0)
{}
//--------------------------------------------------------------------
int scale_limit() const { return uround(m_scale_limit); }
void scale_limit(int v) { m_scale_limit = v; }
//--------------------------------------------------------------------
double blur_x() const { return m_blur_x; }
double blur_y() const { return m_blur_y; }
void blur_x(double v) { m_blur_x = v; }
void blur_y(double v) { m_blur_y = v; }
void blur(double v) { m_blur_x = m_blur_y = v; }
//--------------------------------------------------------------------
void prepare()
{
double scale_x;
double scale_y;
base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y);
if (scale_x * scale_y > m_scale_limit)
{ {
scale_x = scale_x * m_scale_limit / (scale_x * scale_y); m_dx_dbl = dx;
scale_y = scale_y * m_scale_limit / (scale_x * scale_y); m_dy_dbl = dy;
m_dx_int = iround(dx * image_subpixel_scale);
m_dy_int = iround(dy * image_subpixel_scale);
}
void filter_offset(double d) { filter_offset(d, d); }
//--------------------------------------------------------------------
interpolator_type& interpolator() { return *m_interpolator; }
//--------------------------------------------------------------------
void prepare() {}
//--------------------------------------------------------------------
private:
source_type* m_src;
interpolator_type* m_interpolator;
const image_filter_lut* m_filter;
double m_dx_dbl;
double m_dy_dbl;
unsigned m_dx_int;
unsigned m_dy_int;
};
//==============================================span_image_resample_affine
template<class Source>
class span_image_resample_affine :
public span_image_filter<Source, span_interpolator_linear<trans_affine> >
{
public:
typedef Source source_type;
typedef span_interpolator_linear<trans_affine> interpolator_type;
typedef span_image_filter<source_type, interpolator_type> base_type;
//--------------------------------------------------------------------
span_image_resample_affine() :
m_scale_limit(200.0),
m_blur_x(1.0),
m_blur_y(1.0)
{}
//--------------------------------------------------------------------
span_image_resample_affine(source_type& src,
interpolator_type& inter,
const image_filter_lut& filter) :
base_type(src, inter, &filter),
m_scale_limit(200.0),
m_blur_x(1.0),
m_blur_y(1.0)
{}
//--------------------------------------------------------------------
int scale_limit() const { return uround(m_scale_limit); }
void scale_limit(int v) { m_scale_limit = v; }
//--------------------------------------------------------------------
double blur_x() const { return m_blur_x; }
double blur_y() const { return m_blur_y; }
void blur_x(double v) { m_blur_x = v; }
void blur_y(double v) { m_blur_y = v; }
void blur(double v) { m_blur_x = m_blur_y = v; }
//--------------------------------------------------------------------
void prepare()
{
double scale_x;
double scale_y;
base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y);
if(scale_x * scale_y > m_scale_limit)
{
scale_x = scale_x * m_scale_limit / (scale_x * scale_y);
scale_y = scale_y * m_scale_limit / (scale_x * scale_y);
}
if(scale_x < 1) scale_x = 1;
if(scale_y < 1) scale_y = 1;
if(scale_x > m_scale_limit) scale_x = m_scale_limit;
if(scale_y > m_scale_limit) scale_y = m_scale_limit;
scale_x *= m_blur_x;
scale_y *= m_blur_y;
if(scale_x < 1) scale_x = 1;
if(scale_y < 1) scale_y = 1;
m_rx = uround( scale_x * double(image_subpixel_scale));
m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale));
m_ry = uround( scale_y * double(image_subpixel_scale));
m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale));
} }
if (scale_x < 1) protected:
scale_x = 1; int m_rx;
if (scale_y < 1) int m_ry;
scale_y = 1; int m_rx_inv;
int m_ry_inv;
if (scale_x > m_scale_limit) private:
scale_x = m_scale_limit; double m_scale_limit;
if (scale_y > m_scale_limit) double m_blur_x;
scale_y = m_scale_limit; double m_blur_y;
};
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)); //=====================================================span_image_resample
m_rx_inv = uround(1.0 / scale_x * double(image_subpixel_scale)); template<class Source, class Interpolator>
class span_image_resample :
m_ry = uround(scale_y * double(image_subpixel_scale)); public span_image_filter<Source, Interpolator>
m_ry_inv = uround(1.0 / scale_y * double(image_subpixel_scale));
}
protected:
int m_rx;
int m_ry;
int m_rx_inv;
int m_ry_inv;
private:
double m_scale_limit;
double m_blur_x;
double m_blur_y;
};
//=====================================================span_image_resample
template<class Source, class Interpolator>
class span_image_resample : public span_image_filter<Source, Interpolator>
{
public:
typedef Source source_type;
typedef Interpolator interpolator_type;
typedef span_image_filter<source_type, interpolator_type> base_type;
//--------------------------------------------------------------------
span_image_resample()
: m_scale_limit(20)
, m_blur_x(image_subpixel_scale)
, m_blur_y(image_subpixel_scale)
{}
//--------------------------------------------------------------------
span_image_resample(source_type& src, interpolator_type& inter, const image_filter_lut& filter)
: base_type(src, inter, &filter)
, m_scale_limit(20)
, m_blur_x(image_subpixel_scale)
, m_blur_y(image_subpixel_scale)
{}
//--------------------------------------------------------------------
int scale_limit() const { return m_scale_limit; }
void scale_limit(int v) { m_scale_limit = v; }
//--------------------------------------------------------------------
double blur_x() const { return double(m_blur_x) / double(image_subpixel_scale); }
double blur_y() const { return double(m_blur_y) / double(image_subpixel_scale); }
void blur_x(double v) { m_blur_x = uround(v * double(image_subpixel_scale)); }
void blur_y(double v) { m_blur_y = uround(v * double(image_subpixel_scale)); }
void blur(double v) { m_blur_x = m_blur_y = uround(v * double(image_subpixel_scale)); }
protected:
AGG_INLINE void adjust_scale(int* rx, int* ry)
{ {
if (*rx < image_subpixel_scale) public:
*rx = image_subpixel_scale; typedef Source source_type;
if (*ry < image_subpixel_scale) typedef Interpolator interpolator_type;
*ry = image_subpixel_scale; typedef span_image_filter<source_type, interpolator_type> base_type;
if (*rx > image_subpixel_scale * m_scale_limit)
{
*rx = image_subpixel_scale * m_scale_limit;
}
if (*ry > image_subpixel_scale * m_scale_limit)
{
*ry = image_subpixel_scale * m_scale_limit;
}
*rx = (*rx * m_blur_x) >> image_subpixel_shift;
*ry = (*ry * m_blur_y) >> image_subpixel_shift;
if (*rx < image_subpixel_scale)
*rx = image_subpixel_scale;
if (*ry < image_subpixel_scale)
*ry = image_subpixel_scale;
}
int m_scale_limit; //--------------------------------------------------------------------
int m_blur_x; span_image_resample() :
int m_blur_y; m_scale_limit(20),
}; m_blur_x(image_subpixel_scale),
m_blur_y(image_subpixel_scale)
{}
} // namespace agg //--------------------------------------------------------------------
span_image_resample(source_type& src,
interpolator_type& inter,
const image_filter_lut& filter) :
base_type(src, inter, &filter),
m_scale_limit(20),
m_blur_x(image_subpixel_scale),
m_blur_y(image_subpixel_scale)
{}
//--------------------------------------------------------------------
int scale_limit() const { return m_scale_limit; }
void scale_limit(int v) { m_scale_limit = v; }
//--------------------------------------------------------------------
double blur_x() const { return double(m_blur_x) / double(image_subpixel_scale); }
double blur_y() const { return double(m_blur_y) / double(image_subpixel_scale); }
void blur_x(double v) { m_blur_x = uround(v * double(image_subpixel_scale)); }
void blur_y(double v) { m_blur_y = uround(v * double(image_subpixel_scale)); }
void blur(double v) { m_blur_x =
m_blur_y = uround(v * double(image_subpixel_scale)); }
protected:
AGG_INLINE void adjust_scale(int* rx, int* ry)
{
if(*rx < image_subpixel_scale) *rx = image_subpixel_scale;
if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
if(*rx > image_subpixel_scale * m_scale_limit)
{
*rx = image_subpixel_scale * m_scale_limit;
}
if(*ry > image_subpixel_scale * m_scale_limit)
{
*ry = image_subpixel_scale * m_scale_limit;
}
*rx = (*rx * m_blur_x) >> image_subpixel_shift;
*ry = (*ry * m_blur_y) >> image_subpixel_shift;
if(*rx < image_subpixel_scale) *rx = image_subpixel_scale;
if(*ry < image_subpixel_scale) *ry = image_subpixel_scale;
}
int m_scale_limit;
int m_blur_x;
int m_blur_y;
};
}
#endif #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

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -18,47 +18,60 @@
#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
span_interpolator_adaptor() {} template<class Interpolator, class Distortion>
span_interpolator_adaptor(const trans_type& trans, const distortion_type& dist) class span_interpolator_adaptor : public Interpolator
: 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); public:
m_distortion->calculate(x, y); typedef Interpolator base_type;
} typedef typename base_type::trans_type trans_type;
typedef Distortion distortion_type;
//--------------------------------------------------------------------
span_interpolator_adaptor() {}
span_interpolator_adaptor(const trans_type& trans,
const distortion_type& dist) :
base_type(trans),
m_distortion(&dist)
{
}
//--------------------------------------------------------------------
span_interpolator_adaptor(const trans_type& trans,
const distortion_type& dist,
double x, double y, unsigned len) :
base_type(trans, x, y, len),
m_distortion(&dist)
{
}
//--------------------------------------------------------------------
const distortion_type& distortion() const
{
return *m_distortion;
}
//--------------------------------------------------------------------
void distortion(const distortion_type& dist)
{
m_distortion = dist;
}
//--------------------------------------------------------------------
void coordinates(int* x, int* y) const
{
base_type::coordinates(x, y);
m_distortion->calculate(x, y);
}
private:
//--------------------------------------------------------------------
const distortion_type* m_distortion;
};
}
private:
//--------------------------------------------------------------------
const distortion_type* m_distortion;
};
} // namespace agg
#endif #endif

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -20,199 +20,213 @@
#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;
enum subpixel_scale_e { subpixel_shift = SubpixelShift, subpixel_scale = 1 << subpixel_shift }; //================================================span_interpolator_linear
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)
{ {
begin(x, y, len); public:
} typedef Transformer trans_type;
//---------------------------------------------------------------- enum subpixel_scale_e
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:
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)
{ {
unsigned len = m_len; subpixel_shift = SubpixelShift,
if (len > m_subdiv_size) subpixel_scale = 1 << subpixel_shift
len = m_subdiv_size; };
double tx = double(m_src_x) / double(subpixel_scale) + len;
double ty = m_src_y; //--------------------------------------------------------------------
m_trans->transform(&tx, &ty); span_interpolator_linear() {}
m_li_x = dda2_line_interpolator(m_li_x.y(), iround(tx * subpixel_scale), len); span_interpolator_linear(const trans_type& trans) : m_trans(&trans) {}
m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ty * subpixel_scale), len); span_interpolator_linear(const trans_type& trans,
m_pos = 0; double x, double y, unsigned len) :
m_trans(&trans)
{
begin(x, y, len);
} }
m_src_x += subpixel_scale;
++m_pos;
--m_len;
}
//---------------------------------------------------------------- //----------------------------------------------------------------
void coordinates(int* x, int* y) const 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
{ {
*x = m_li_x.y(); public:
*y = m_li_y.y(); 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)
{
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

View file

@ -2,8 +2,8 @@
// Anti-Grain Geometry - Version 2.4 // Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
// //
// Permission to copy, use, modify, sell and distribute this software // Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies. // is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied // This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose. // warranty, and with no claim as to its suitability for any purpose.
// //
@ -18,393 +18,445 @@
#include "agg_trans_perspective.h" #include "agg_trans_perspective.h"
#include "agg_dda_line.h" #include "agg_dda_line.h"
namespace agg { namespace agg
//===========================================span_interpolator_persp_exact
template<unsigned SubpixelShift = 8>
class span_interpolator_persp_exact
{ {
public:
typedef trans_perspective trans_type;
typedef trans_perspective::iterator_x iterator_type;
enum subpixel_scale_e { subpixel_shift = SubpixelShift, subpixel_scale = 1 << subpixel_shift };
//--------------------------------------------------------------------
span_interpolator_persp_exact() {}
//--------------------------------------------------------------------
// Arbitrary quadrangle transformations
span_interpolator_persp_exact(const double* src, const double* dst) { quad_to_quad(src, dst); }
//-------------------------------------------------------------------- //===========================================span_interpolator_persp_exact
// Direct transformations template<unsigned SubpixelShift = 8>
span_interpolator_persp_exact(double x1, double y1, double x2, double y2, const double* quad) class span_interpolator_persp_exact
{ {
rect_to_quad(x1, y1, x2, y2, quad); public:
} typedef trans_perspective trans_type;
typedef trans_perspective::iterator_x iterator_type;
enum subpixel_scale_e
{
subpixel_shift = SubpixelShift,
subpixel_scale = 1 << subpixel_shift
};
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Reverse transformations span_interpolator_persp_exact() {}
span_interpolator_persp_exact(const double* quad, double x1, double y1, double x2, double y2)
//--------------------------------------------------------------------
// Arbitrary quadrangle transformations
span_interpolator_persp_exact(const double* src, const double* dst)
{
quad_to_quad(src, dst);
}
//--------------------------------------------------------------------
// Direct transformations
span_interpolator_persp_exact(double x1, double y1,
double x2, double y2,
const double* quad)
{
rect_to_quad(x1, y1, x2, y2, quad);
}
//--------------------------------------------------------------------
// Reverse transformations
span_interpolator_persp_exact(const double* quad,
double x1, double y1,
double x2, double y2)
{
quad_to_rect(quad, x1, y1, x2, y2);
}
//--------------------------------------------------------------------
// Set the transformations using two arbitrary quadrangles.
void quad_to_quad(const double* src, const double* dst)
{
m_trans_dir.quad_to_quad(src, dst);
m_trans_inv.quad_to_quad(dst, src);
}
//--------------------------------------------------------------------
// Set the direct transformations, i.e., rectangle -> quadrangle
void rect_to_quad(double x1, double y1, double x2, double y2,
const double* quad)
{
double src[8];
src[0] = src[6] = x1;
src[2] = src[4] = x2;
src[1] = src[3] = y1;
src[5] = src[7] = y2;
quad_to_quad(src, quad);
}
//--------------------------------------------------------------------
// Set the reverse transformations, i.e., quadrangle -> rectangle
void quad_to_rect(const double* quad,
double x1, double y1, double x2, double y2)
{
double dst[8];
dst[0] = dst[6] = x1;
dst[2] = dst[4] = x2;
dst[1] = dst[3] = y1;
dst[5] = dst[7] = y2;
quad_to_quad(quad, dst);
}
//--------------------------------------------------------------------
// Check if the equations were solved successfully
bool is_valid() const { return m_trans_dir.is_valid(); }
//----------------------------------------------------------------
void begin(double x, double y, unsigned len)
{
m_iterator = m_trans_dir.begin(x, y, 1.0);
double xt = m_iterator.x;
double yt = m_iterator.y;
double dx;
double dy;
const double delta = 1/double(subpixel_scale);
dx = xt + delta;
dy = yt;
m_trans_inv.transform(&dx, &dy);
dx -= x;
dy -= y;
int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
dx = xt;
dy = yt + delta;
m_trans_inv.transform(&dx, &dy);
dx -= x;
dy -= y;
int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
x += len;
xt = x;
yt = y;
m_trans_dir.transform(&xt, &yt);
dx = xt + delta;
dy = yt;
m_trans_inv.transform(&dx, &dy);
dx -= x;
dy -= y;
int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
dx = xt;
dy = yt + delta;
m_trans_inv.transform(&dx, &dy);
dx -= x;
dy -= y;
int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
m_scale_x = dda2_line_interpolator(sx1, sx2, len);
m_scale_y = dda2_line_interpolator(sy1, sy2, len);
}
//----------------------------------------------------------------
void resynchronize(double xe, double ye, unsigned len)
{
// Assume x1,y1 are equal to the ones at the previous end point
int sx1 = m_scale_x.y();
int sy1 = m_scale_y.y();
// Calculate transformed coordinates at x2,y2
double xt = xe;
double yt = ye;
m_trans_dir.transform(&xt, &yt);
const double delta = 1/double(subpixel_scale);
double dx;
double dy;
// Calculate scale by X at x2,y2
dx = xt + delta;
dy = yt;
m_trans_inv.transform(&dx, &dy);
dx -= xe;
dy -= ye;
int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
// Calculate scale by Y at x2,y2
dx = xt;
dy = yt + delta;
m_trans_inv.transform(&dx, &dy);
dx -= xe;
dy -= ye;
int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
// Initialize the interpolators
m_scale_x = dda2_line_interpolator(sx1, sx2, len);
m_scale_y = dda2_line_interpolator(sy1, sy2, len);
}
//----------------------------------------------------------------
void operator++()
{
++m_iterator;
++m_scale_x;
++m_scale_y;
}
//----------------------------------------------------------------
void coordinates(int* x, int* y) const
{
*x = iround(m_iterator.x * subpixel_scale);
*y = iround(m_iterator.y * subpixel_scale);
}
//----------------------------------------------------------------
void local_scale(int* x, int* y)
{
*x = m_scale_x.y();
*y = m_scale_y.y();
}
//----------------------------------------------------------------
void transform(double* x, double* y) const
{
m_trans_dir.transform(x, y);
}
private:
trans_type m_trans_dir;
trans_type m_trans_inv;
iterator_type m_iterator;
dda2_line_interpolator m_scale_x;
dda2_line_interpolator m_scale_y;
};
//============================================span_interpolator_persp_lerp
template<unsigned SubpixelShift = 8>
class span_interpolator_persp_lerp
{ {
quad_to_rect(quad, x1, y1, x2, y2); public:
} typedef trans_perspective trans_type;
enum subpixel_scale_e
{
subpixel_shift = SubpixelShift,
subpixel_scale = 1 << subpixel_shift
};
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Set the transformations using two arbitrary quadrangles. span_interpolator_persp_lerp() {}
void quad_to_quad(const double* src, const double* dst)
{
m_trans_dir.quad_to_quad(src, dst);
m_trans_inv.quad_to_quad(dst, src);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Set the direct transformations, i.e., rectangle -> quadrangle // Arbitrary quadrangle transformations
void rect_to_quad(double x1, double y1, double x2, double y2, const double* quad) span_interpolator_persp_lerp(const double* src, const double* dst)
{ {
double src[8]; quad_to_quad(src, dst);
src[0] = src[6] = x1; }
src[2] = src[4] = x2;
src[1] = src[3] = y1;
src[5] = src[7] = y2;
quad_to_quad(src, quad);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Set the reverse transformations, i.e., quadrangle -> rectangle // Direct transformations
void quad_to_rect(const double* quad, double x1, double y1, double x2, double y2) span_interpolator_persp_lerp(double x1, double y1,
{ double x2, double y2,
double dst[8]; const double* quad)
dst[0] = dst[6] = x1; {
dst[2] = dst[4] = x2; rect_to_quad(x1, y1, x2, y2, quad);
dst[1] = dst[3] = y1; }
dst[5] = dst[7] = y2;
quad_to_quad(quad, dst);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Check if the equations were solved successfully // Reverse transformations
bool is_valid() const { return m_trans_dir.is_valid(); } span_interpolator_persp_lerp(const double* quad,
double x1, double y1,
double x2, double y2)
{
quad_to_rect(quad, x1, y1, x2, y2);
}
//---------------------------------------------------------------- //--------------------------------------------------------------------
void begin(double x, double y, unsigned len) // Set the transformations using two arbitrary quadrangles.
{ void quad_to_quad(const double* src, const double* dst)
m_iterator = m_trans_dir.begin(x, y, 1.0); {
double xt = m_iterator.x; m_trans_dir.quad_to_quad(src, dst);
double yt = m_iterator.y; m_trans_inv.quad_to_quad(dst, src);
}
double dx; //--------------------------------------------------------------------
double dy; // Set the direct transformations, i.e., rectangle -> quadrangle
const double delta = 1 / double(subpixel_scale); void rect_to_quad(double x1, double y1, double x2, double y2,
dx = xt + delta; const double* quad)
dy = yt; {
m_trans_inv.transform(&dx, &dy); double src[8];
dx -= x; src[0] = src[6] = x1;
dy -= y; src[2] = src[4] = x2;
int sx1 = uround(subpixel_scale / sqrt(dx * dx + dy * dy)) >> subpixel_shift; src[1] = src[3] = y1;
dx = xt; src[5] = src[7] = y2;
dy = yt + delta; quad_to_quad(src, quad);
m_trans_inv.transform(&dx, &dy); }
dx -= x;
dy -= y;
int sy1 = uround(subpixel_scale / sqrt(dx * dx + dy * dy)) >> subpixel_shift;
x += len;
xt = x;
yt = y;
m_trans_dir.transform(&xt, &yt);
dx = xt + delta; //--------------------------------------------------------------------
dy = yt; // Set the reverse transformations, i.e., quadrangle -> rectangle
m_trans_inv.transform(&dx, &dy); void quad_to_rect(const double* quad,
dx -= x; double x1, double y1, double x2, double y2)
dy -= y; {
int sx2 = uround(subpixel_scale / sqrt(dx * dx + dy * dy)) >> subpixel_shift; double dst[8];
dx = xt; dst[0] = dst[6] = x1;
dy = yt + delta; dst[2] = dst[4] = x2;
m_trans_inv.transform(&dx, &dy); dst[1] = dst[3] = y1;
dx -= x; dst[5] = dst[7] = y2;
dy -= y; quad_to_quad(quad, dst);
int sy2 = uround(subpixel_scale / sqrt(dx * dx + dy * dy)) >> subpixel_shift; }
m_scale_x = dda2_line_interpolator(sx1, sx2, len); //--------------------------------------------------------------------
m_scale_y = dda2_line_interpolator(sy1, sy2, len); // Check if the equations were solved successfully
} bool is_valid() const { return m_trans_dir.is_valid(); }
//---------------------------------------------------------------- //----------------------------------------------------------------
void resynchronize(double xe, double ye, unsigned len) void begin(double x, double y, unsigned len)
{ {
// Assume x1,y1 are equal to the ones at the previous end point // Calculate transformed coordinates at x1,y1
int sx1 = m_scale_x.y(); double xt = x;
int sy1 = m_scale_y.y(); double yt = y;
m_trans_dir.transform(&xt, &yt);
int x1 = iround(xt * subpixel_scale);
int y1 = iround(yt * subpixel_scale);
// Calculate transformed coordinates at x2,y2 double dx;
double xt = xe; double dy;
double yt = ye; const double delta = 1/double(subpixel_scale);
m_trans_dir.transform(&xt, &yt);
const double delta = 1 / double(subpixel_scale); // Calculate scale by X at x1,y1
double dx; dx = xt + delta;
double dy; dy = yt;
m_trans_inv.transform(&dx, &dy);
dx -= x;
dy -= y;
int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
// Calculate scale by X at x2,y2 // Calculate scale by Y at x1,y1
dx = xt + delta; dx = xt;
dy = yt; dy = yt + delta;
m_trans_inv.transform(&dx, &dy); m_trans_inv.transform(&dx, &dy);
dx -= xe; dx -= x;
dy -= ye; dy -= y;
int sx2 = uround(subpixel_scale / sqrt(dx * dx + dy * dy)) >> subpixel_shift; int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
// Calculate scale by Y at x2,y2 // Calculate transformed coordinates at x2,y2
dx = xt; x += len;
dy = yt + delta; xt = x;
m_trans_inv.transform(&dx, &dy); yt = y;
dx -= xe; m_trans_dir.transform(&xt, &yt);
dy -= ye; int x2 = iround(xt * subpixel_scale);
int sy2 = uround(subpixel_scale / sqrt(dx * dx + dy * dy)) >> subpixel_shift; int y2 = iround(yt * subpixel_scale);
// Initialize the interpolators // Calculate scale by X at x2,y2
m_scale_x = dda2_line_interpolator(sx1, sx2, len); dx = xt + delta;
m_scale_y = dda2_line_interpolator(sy1, sy2, len); dy = yt;
} m_trans_inv.transform(&dx, &dy);
dx -= x;
dy -= y;
int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
//---------------------------------------------------------------- // Calculate scale by Y at x2,y2
void operator++() dx = xt;
{ dy = yt + delta;
++m_iterator; m_trans_inv.transform(&dx, &dy);
++m_scale_x; dx -= x;
++m_scale_y; dy -= y;
} int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
//---------------------------------------------------------------- // Initialize the interpolators
void coordinates(int* x, int* y) const m_coord_x = dda2_line_interpolator(x1, x2, len);
{ m_coord_y = dda2_line_interpolator(y1, y2, len);
*x = iround(m_iterator.x * subpixel_scale); m_scale_x = dda2_line_interpolator(sx1, sx2, len);
*y = iround(m_iterator.y * subpixel_scale); m_scale_y = dda2_line_interpolator(sy1, sy2, len);
} }
//----------------------------------------------------------------
void local_scale(int* x, int* y)
{
*x = m_scale_x.y();
*y = m_scale_y.y();
}
//---------------------------------------------------------------- //----------------------------------------------------------------
void transform(double* x, double* y) const { m_trans_dir.transform(x, y); } void resynchronize(double xe, double ye, unsigned len)
{
// Assume x1,y1 are equal to the ones at the previous end point
int x1 = m_coord_x.y();
int y1 = m_coord_y.y();
int sx1 = m_scale_x.y();
int sy1 = m_scale_y.y();
private: // Calculate transformed coordinates at x2,y2
trans_type m_trans_dir; double xt = xe;
trans_type m_trans_inv; double yt = ye;
iterator_type m_iterator; m_trans_dir.transform(&xt, &yt);
dda2_line_interpolator m_scale_x; int x2 = iround(xt * subpixel_scale);
dda2_line_interpolator m_scale_y; int y2 = iround(yt * subpixel_scale);
};
//============================================span_interpolator_persp_lerp const double delta = 1/double(subpixel_scale);
template<unsigned SubpixelShift = 8> double dx;
class span_interpolator_persp_lerp double dy;
{
public:
typedef trans_perspective trans_type;
enum subpixel_scale_e { subpixel_shift = SubpixelShift, subpixel_scale = 1 << subpixel_shift };
//-------------------------------------------------------------------- // Calculate scale by X at x2,y2
span_interpolator_persp_lerp() {} dx = xt + delta;
dy = yt;
m_trans_inv.transform(&dx, &dy);
dx -= xe;
dy -= ye;
int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
//-------------------------------------------------------------------- // Calculate scale by Y at x2,y2
// Arbitrary quadrangle transformations dx = xt;
span_interpolator_persp_lerp(const double* src, const double* dst) { quad_to_quad(src, dst); } dy = yt + delta;
m_trans_inv.transform(&dx, &dy);
dx -= xe;
dy -= ye;
int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift;
//-------------------------------------------------------------------- // Initialize the interpolators
// Direct transformations m_coord_x = dda2_line_interpolator(x1, x2, len);
span_interpolator_persp_lerp(double x1, double y1, double x2, double y2, const double* quad) m_coord_y = dda2_line_interpolator(y1, y2, len);
{ m_scale_x = dda2_line_interpolator(sx1, sx2, len);
rect_to_quad(x1, y1, x2, y2, quad); m_scale_y = dda2_line_interpolator(sy1, sy2, len);
} }
//--------------------------------------------------------------------
// Reverse transformations
span_interpolator_persp_lerp(const double* quad, double x1, double y1, double x2, double y2)
{
quad_to_rect(quad, x1, y1, x2, y2);
}
//-------------------------------------------------------------------- //----------------------------------------------------------------
// Set the transformations using two arbitrary quadrangles. void operator++()
void quad_to_quad(const double* src, const double* dst) {
{ ++m_coord_x;
m_trans_dir.quad_to_quad(src, dst); ++m_coord_y;
m_trans_inv.quad_to_quad(dst, src); ++m_scale_x;
} ++m_scale_y;
}
//-------------------------------------------------------------------- //----------------------------------------------------------------
// Set the direct transformations, i.e., rectangle -> quadrangle void coordinates(int* x, int* y) const
void rect_to_quad(double x1, double y1, double x2, double y2, const double* quad) {
{ *x = m_coord_x.y();
double src[8]; *y = m_coord_y.y();
src[0] = src[6] = x1; }
src[2] = src[4] = x2;
src[1] = src[3] = y1;
src[5] = src[7] = y2;
quad_to_quad(src, quad);
}
//-------------------------------------------------------------------- //----------------------------------------------------------------
// Set the reverse transformations, i.e., quadrangle -> rectangle void local_scale(int* x, int* y)
void quad_to_rect(const double* quad, double x1, double y1, double x2, double y2) {
{ *x = m_scale_x.y();
double dst[8]; *y = m_scale_y.y();
dst[0] = dst[6] = x1; }
dst[2] = dst[4] = x2;
dst[1] = dst[3] = y1;
dst[5] = dst[7] = y2;
quad_to_quad(quad, dst);
}
//-------------------------------------------------------------------- //----------------------------------------------------------------
// Check if the equations were solved successfully void transform(double* x, double* y) const
bool is_valid() const { return m_trans_dir.is_valid(); } {
m_trans_dir.transform(x, y);
}
private:
trans_type m_trans_dir;
trans_type m_trans_inv;
dda2_line_interpolator m_coord_x;
dda2_line_interpolator m_coord_y;
dda2_line_interpolator m_scale_x;
dda2_line_interpolator m_scale_y;
};
//---------------------------------------------------------------- }
void begin(double x, double y, unsigned len)
{
// Calculate transformed coordinates at x1,y1
double xt = x;
double yt = y;
m_trans_dir.transform(&xt, &yt);
int x1 = iround(xt * subpixel_scale);
int y1 = iround(yt * subpixel_scale);
double dx;
double dy;
const double delta = 1 / double(subpixel_scale);
// Calculate scale by X at x1,y1
dx = xt + delta;
dy = yt;
m_trans_inv.transform(&dx, &dy);
dx -= x;
dy -= y;
int sx1 = uround(subpixel_scale / sqrt(dx * dx + dy * dy)) >> subpixel_shift;
// Calculate scale by Y at x1,y1
dx = xt;
dy = yt + delta;
m_trans_inv.transform(&dx, &dy);
dx -= x;
dy -= y;
int sy1 = uround(subpixel_scale / sqrt(dx * dx + dy * dy)) >> subpixel_shift;
// Calculate transformed coordinates at x2,y2
x += len;
xt = x;
yt = y;
m_trans_dir.transform(&xt, &yt);
int x2 = iround(xt * subpixel_scale);
int y2 = iround(yt * subpixel_scale);
// Calculate scale by X at x2,y2
dx = xt + delta;
dy = yt;
m_trans_inv.transform(&dx, &dy);
dx -= x;
dy -= y;
int sx2 = uround(subpixel_scale / sqrt(dx * dx + dy * dy)) >> subpixel_shift;
// Calculate scale by Y at x2,y2
dx = xt;
dy = yt + delta;
m_trans_inv.transform(&dx, &dy);
dx -= x;
dy -= y;
int sy2 = uround(subpixel_scale / sqrt(dx * dx + dy * dy)) >> subpixel_shift;
// Initialize the interpolators
m_coord_x = dda2_line_interpolator(x1, x2, len);
m_coord_y = dda2_line_interpolator(y1, y2, len);
m_scale_x = dda2_line_interpolator(sx1, sx2, len);
m_scale_y = dda2_line_interpolator(sy1, sy2, len);
}
//----------------------------------------------------------------
void resynchronize(double xe, double ye, unsigned len)
{
// Assume x1,y1 are equal to the ones at the previous end point
int x1 = m_coord_x.y();
int y1 = m_coord_y.y();
int sx1 = m_scale_x.y();
int sy1 = m_scale_y.y();
// Calculate transformed coordinates at x2,y2
double xt = xe;
double yt = ye;
m_trans_dir.transform(&xt, &yt);
int x2 = iround(xt * subpixel_scale);
int y2 = iround(yt * subpixel_scale);
const double delta = 1 / double(subpixel_scale);
double dx;
double dy;
// Calculate scale by X at x2,y2
dx = xt + delta;
dy = yt;
m_trans_inv.transform(&dx, &dy);
dx -= xe;
dy -= ye;
int sx2 = uround(subpixel_scale / sqrt(dx * dx + dy * dy)) >> subpixel_shift;
// Calculate scale by Y at x2,y2
dx = xt;
dy = yt + delta;
m_trans_inv.transform(&dx, &dy);
dx -= xe;
dy -= ye;
int sy2 = uround(subpixel_scale / sqrt(dx * dx + dy * dy)) >> subpixel_shift;
// Initialize the interpolators
m_coord_x = dda2_line_interpolator(x1, x2, len);
m_coord_y = dda2_line_interpolator(y1, y2, len);
m_scale_x = dda2_line_interpolator(sx1, sx2, len);
m_scale_y = dda2_line_interpolator(sy1, sy2, len);
}
//----------------------------------------------------------------
void operator++()
{
++m_coord_x;
++m_coord_y;
++m_scale_x;
++m_scale_y;
}
//----------------------------------------------------------------
void coordinates(int* x, int* y) const
{
*x = m_coord_x.y();
*y = m_coord_y.y();
}
//----------------------------------------------------------------
void local_scale(int* x, int* y)
{
*x = m_scale_x.y();
*y = m_scale_y.y();
}
//----------------------------------------------------------------
void transform(double* x, double* y) const { m_trans_dir.transform(x, y); }
private:
trans_type m_trans_dir;
trans_type m_trans_inv;
dda2_line_interpolator m_coord_x;
dda2_line_interpolator m_coord_y;
dda2_line_interpolator m_scale_x;
dda2_line_interpolator m_scale_y;
};
} // namespace agg
#endif #endif

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