Initial checkin
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9933 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Executable
+499
@@ -0,0 +1,499 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// scanline_u8 class
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_ALPHA_MASK_U8_INCLUDED
|
||||||
|
#define AGG_ALPHA_MASK_U8_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//===================================================one_component_mask_u8
|
||||||
|
struct one_component_mask_u8
|
||||||
|
{
|
||||||
|
static unsigned calculate(const int8u* p) { return *p; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//=====================================================rgb_to_gray_mask_u8
|
||||||
|
template<unsigned R, unsigned G, unsigned B>
|
||||||
|
struct rgb_to_gray_mask_u8
|
||||||
|
{
|
||||||
|
static unsigned calculate(const int8u* p)
|
||||||
|
{
|
||||||
|
return (p[R]*77 + p[G]*150 + p[B]*29) >> 8;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//==========================================================alpha_mask_u8
|
||||||
|
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
|
||||||
|
class alpha_mask_u8
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef int8u cover_type;
|
||||||
|
typedef alpha_mask_u8<Step, Offset, MaskF> self_type;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
cover_shift = 8,
|
||||||
|
cover_none = 0,
|
||||||
|
cover_full = 255
|
||||||
|
};
|
||||||
|
|
||||||
|
alpha_mask_u8() : m_rbuf(0) {}
|
||||||
|
alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
|
||||||
|
|
||||||
|
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
|
||||||
|
|
||||||
|
MaskF& mask_function() { return m_mask_function; }
|
||||||
|
const MaskF& mask_function() const { return m_mask_function; }
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
cover_type pixel(int x, int y) const
|
||||||
|
{
|
||||||
|
if(x >= 0 && y >= 0 &&
|
||||||
|
x < (int)m_rbuf->width() &&
|
||||||
|
y <= (int)m_rbuf->height())
|
||||||
|
{
|
||||||
|
return (cover_type)m_mask_function.calculate(
|
||||||
|
m_rbuf->row(y) + x * Step + Offset);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
cover_type combine_pixel(int x, int y, cover_type val) const
|
||||||
|
{
|
||||||
|
if(x >= 0 && y >= 0 &&
|
||||||
|
x < (int)m_rbuf->width() &&
|
||||||
|
y <= (int)m_rbuf->height())
|
||||||
|
{
|
||||||
|
return (cover_type)((val *
|
||||||
|
m_mask_function.calculate(
|
||||||
|
m_rbuf->row(y) + x * Step + Offset)) >>
|
||||||
|
cover_shift);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||||
|
{
|
||||||
|
int xmax = m_rbuf->width() - 1;
|
||||||
|
int ymax = m_rbuf->height() - 1;
|
||||||
|
|
||||||
|
int count = num_pix;
|
||||||
|
cover_type* covers = dst;
|
||||||
|
|
||||||
|
if(y < 0 || y > ymax)
|
||||||
|
{
|
||||||
|
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(x < 0)
|
||||||
|
{
|
||||||
|
count += x;
|
||||||
|
if(count <= 0)
|
||||||
|
{
|
||||||
|
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(covers, 0, -x * sizeof(cover_type));
|
||||||
|
covers -= x;
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(x + count > xmax)
|
||||||
|
{
|
||||||
|
int rest = x + count - xmax - 1;
|
||||||
|
count -= rest;
|
||||||
|
if(count <= 0)
|
||||||
|
{
|
||||||
|
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(covers + count, 0, rest * sizeof(cover_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*covers++ = (cover_type)m_mask_function.calculate(mask);
|
||||||
|
mask += Step;
|
||||||
|
}
|
||||||
|
while(--count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||||
|
{
|
||||||
|
int xmax = m_rbuf->width() - 1;
|
||||||
|
int ymax = m_rbuf->height() - 1;
|
||||||
|
|
||||||
|
int count = num_pix;
|
||||||
|
cover_type* covers = dst;
|
||||||
|
|
||||||
|
if(y < 0 || y > ymax)
|
||||||
|
{
|
||||||
|
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(x < 0)
|
||||||
|
{
|
||||||
|
count += x;
|
||||||
|
if(count <= 0)
|
||||||
|
{
|
||||||
|
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(covers, 0, -x * sizeof(cover_type));
|
||||||
|
covers -= x;
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(x + count > xmax)
|
||||||
|
{
|
||||||
|
int rest = x + count - xmax - 1;
|
||||||
|
count -= rest;
|
||||||
|
if(count <= 0)
|
||||||
|
{
|
||||||
|
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(covers + count, 0, rest * sizeof(cover_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*covers = (cover_type)(((*covers) *
|
||||||
|
m_mask_function.calculate(mask)) >>
|
||||||
|
cover_shift);
|
||||||
|
++covers;
|
||||||
|
mask += Step;
|
||||||
|
}
|
||||||
|
while(--count);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||||
|
{
|
||||||
|
int xmax = m_rbuf->width() - 1;
|
||||||
|
int ymax = m_rbuf->height() - 1;
|
||||||
|
|
||||||
|
int count = num_pix;
|
||||||
|
cover_type* covers = dst;
|
||||||
|
|
||||||
|
if(x < 0 || x > xmax)
|
||||||
|
{
|
||||||
|
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(y < 0)
|
||||||
|
{
|
||||||
|
count += y;
|
||||||
|
if(count <= 0)
|
||||||
|
{
|
||||||
|
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(covers, 0, -y * sizeof(cover_type));
|
||||||
|
covers -= y;
|
||||||
|
y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(y + count > ymax)
|
||||||
|
{
|
||||||
|
int rest = y + count - ymax - 1;
|
||||||
|
count -= rest;
|
||||||
|
if(count <= 0)
|
||||||
|
{
|
||||||
|
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(covers + count, 0, rest * sizeof(cover_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*covers++ = (cover_type)m_mask_function.calculate(mask);
|
||||||
|
mask += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--count);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||||
|
{
|
||||||
|
int xmax = m_rbuf->width() - 1;
|
||||||
|
int ymax = m_rbuf->height() - 1;
|
||||||
|
|
||||||
|
int count = num_pix;
|
||||||
|
cover_type* covers = dst;
|
||||||
|
|
||||||
|
if(x < 0 || x > xmax)
|
||||||
|
{
|
||||||
|
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(y < 0)
|
||||||
|
{
|
||||||
|
count += y;
|
||||||
|
if(count <= 0)
|
||||||
|
{
|
||||||
|
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(covers, 0, -y * sizeof(cover_type));
|
||||||
|
covers -= y;
|
||||||
|
y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(y + count > ymax)
|
||||||
|
{
|
||||||
|
int rest = y + count - ymax - 1;
|
||||||
|
count -= rest;
|
||||||
|
if(count <= 0)
|
||||||
|
{
|
||||||
|
memset(dst, 0, num_pix * sizeof(cover_type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(covers + count, 0, rest * sizeof(cover_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*covers = (cover_type)(((*covers) *
|
||||||
|
m_mask_function.calculate(mask)) >>
|
||||||
|
cover_shift);
|
||||||
|
++covers;
|
||||||
|
mask += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
alpha_mask_u8(const self_type&);
|
||||||
|
const self_type& operator = (const self_type&);
|
||||||
|
|
||||||
|
rendering_buffer* m_rbuf;
|
||||||
|
MaskF m_mask_function;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef alpha_mask_u8<1, 0> alpha_mask_gray8; //----alpha_mask_gray8
|
||||||
|
|
||||||
|
typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r; //----alpha_mask_rgb24r
|
||||||
|
typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g; //----alpha_mask_rgb24g
|
||||||
|
typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b; //----alpha_mask_rgb24b
|
||||||
|
|
||||||
|
typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r; //----alpha_mask_bgr24r
|
||||||
|
typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g; //----alpha_mask_bgr24g
|
||||||
|
typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b; //----alpha_mask_bgr24b
|
||||||
|
|
||||||
|
typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r
|
||||||
|
typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g
|
||||||
|
typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b
|
||||||
|
typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a
|
||||||
|
|
||||||
|
typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r
|
||||||
|
typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g
|
||||||
|
typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b
|
||||||
|
typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a
|
||||||
|
|
||||||
|
typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r
|
||||||
|
typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g
|
||||||
|
typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b
|
||||||
|
typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a
|
||||||
|
|
||||||
|
typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r
|
||||||
|
typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g
|
||||||
|
typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b
|
||||||
|
typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a
|
||||||
|
|
||||||
|
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray; //----alpha_mask_rgb24gray
|
||||||
|
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray; //----alpha_mask_bgr24gray
|
||||||
|
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray
|
||||||
|
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray
|
||||||
|
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray
|
||||||
|
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================amask_no_clip_u8
|
||||||
|
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
|
||||||
|
class amask_no_clip_u8
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef int8u cover_type;
|
||||||
|
typedef amask_no_clip_u8<Step, Offset, MaskF> self_type;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
cover_shift = 8,
|
||||||
|
cover_none = 0,
|
||||||
|
cover_full = 255
|
||||||
|
};
|
||||||
|
|
||||||
|
amask_no_clip_u8() : m_rbuf(0) {}
|
||||||
|
amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
|
||||||
|
|
||||||
|
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
|
||||||
|
|
||||||
|
MaskF& mask_function() { return m_mask_function; }
|
||||||
|
const MaskF& mask_function() const { return m_mask_function; }
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
cover_type pixel(int x, int y) const
|
||||||
|
{
|
||||||
|
return (cover_type)m_mask_function.calculate(
|
||||||
|
m_rbuf->row(y) + x * Step + Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
cover_type combine_pixel(int x, int y, cover_type val) const
|
||||||
|
{
|
||||||
|
return (cover_type)((val *
|
||||||
|
m_mask_function.calculate(
|
||||||
|
m_rbuf->row(y) + x * Step + Offset)) >>
|
||||||
|
cover_shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||||
|
{
|
||||||
|
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*dst++ = (cover_type)m_mask_function.calculate(mask);
|
||||||
|
mask += Step;
|
||||||
|
}
|
||||||
|
while(--num_pix);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||||
|
{
|
||||||
|
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*dst = (cover_type)(((*dst) *
|
||||||
|
m_mask_function.calculate(mask)) >>
|
||||||
|
cover_shift);
|
||||||
|
++dst;
|
||||||
|
mask += Step;
|
||||||
|
}
|
||||||
|
while(--num_pix);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||||
|
{
|
||||||
|
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*dst++ = (cover_type)m_mask_function.calculate(mask);
|
||||||
|
mask += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--num_pix);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||||
|
{
|
||||||
|
const int8u* mask = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*dst = (cover_type)(((*dst) *
|
||||||
|
m_mask_function.calculate(mask)) >>
|
||||||
|
cover_shift);
|
||||||
|
++dst;
|
||||||
|
mask += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--num_pix);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
amask_no_clip_u8(const self_type&);
|
||||||
|
const self_type& operator = (const self_type&);
|
||||||
|
|
||||||
|
rendering_buffer* m_rbuf;
|
||||||
|
MaskF m_mask_function;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8
|
||||||
|
|
||||||
|
typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r
|
||||||
|
typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g; //----amask_no_clip_rgb24g
|
||||||
|
typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b; //----amask_no_clip_rgb24b
|
||||||
|
|
||||||
|
typedef amask_no_clip_u8<3, 2> amask_no_clip_bgr24r; //----amask_no_clip_bgr24r
|
||||||
|
typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g; //----amask_no_clip_bgr24g
|
||||||
|
typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b; //----amask_no_clip_bgr24b
|
||||||
|
|
||||||
|
typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r
|
||||||
|
typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g
|
||||||
|
typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b
|
||||||
|
typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a
|
||||||
|
|
||||||
|
typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r
|
||||||
|
typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g
|
||||||
|
typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b
|
||||||
|
typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a
|
||||||
|
|
||||||
|
typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r
|
||||||
|
typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g
|
||||||
|
typedef amask_no_clip_u8<4, 0> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b
|
||||||
|
typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a
|
||||||
|
|
||||||
|
typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r
|
||||||
|
typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g
|
||||||
|
typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b
|
||||||
|
typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a
|
||||||
|
|
||||||
|
typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgb24gray; //----amask_no_clip_rgb24gray
|
||||||
|
typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray; //----amask_no_clip_bgr24gray
|
||||||
|
typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgba32gray; //----amask_no_clip_rgba32gray
|
||||||
|
typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_argb32gray; //----amask_no_clip_argb32gray
|
||||||
|
typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgra32gray; //----amask_no_clip_bgra32gray
|
||||||
|
typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_abgr32gray; //----amask_no_clip_abgr32gray
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Arc vertex generator
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_ARC_INCLUDED
|
||||||
|
#define AGG_ARC_INCLUDED
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//=====================================================================arc
|
||||||
|
//
|
||||||
|
// See Implementation agg_arc.cpp
|
||||||
|
//
|
||||||
|
class arc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
arc() : m_scale(1.0), m_initialized(false) {}
|
||||||
|
arc(double x, double y,
|
||||||
|
double rx, double ry,
|
||||||
|
double a1, double a2,
|
||||||
|
bool ccw=true);
|
||||||
|
|
||||||
|
void init(double x, double y,
|
||||||
|
double rx, double ry,
|
||||||
|
double a1, double a2,
|
||||||
|
bool ccw=true);
|
||||||
|
|
||||||
|
void approximation_scale(double s);
|
||||||
|
double approximation_scale() const { return m_scale; }
|
||||||
|
|
||||||
|
void rewind(unsigned);
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void normalize(double a1, double a2, bool ccw);
|
||||||
|
|
||||||
|
double m_x;
|
||||||
|
double m_y;
|
||||||
|
double m_rx;
|
||||||
|
double m_ry;
|
||||||
|
double m_angle;
|
||||||
|
double m_start;
|
||||||
|
double m_end;
|
||||||
|
double m_scale;
|
||||||
|
double m_da;
|
||||||
|
bool m_ccw;
|
||||||
|
bool m_initialized;
|
||||||
|
unsigned m_path_cmd;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,734 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_ARRAY_INCLUDED
|
||||||
|
#define AGG_ARRAY_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//---------------------------------------------------------------pod_array
|
||||||
|
// A simple class template to store Plain Old Data, a vector
|
||||||
|
// of a fixed size. The data is continous in memory
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> class pod_array
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T value_type;
|
||||||
|
|
||||||
|
~pod_array() { delete [] m_array; }
|
||||||
|
pod_array() : m_size(0), m_capacity(0), m_array(0) {}
|
||||||
|
pod_array(unsigned cap, unsigned extra_tail=0);
|
||||||
|
|
||||||
|
// Copying
|
||||||
|
pod_array(const pod_array<T>&);
|
||||||
|
const pod_array<T>& operator = (const pod_array<T>&);
|
||||||
|
|
||||||
|
unsigned capacity() const { return m_capacity; }
|
||||||
|
void capacity(unsigned cap, unsigned extra_tail=0);
|
||||||
|
|
||||||
|
void resize(unsigned new_size);
|
||||||
|
|
||||||
|
void add(const T& v) { m_array[m_size++] = v; }
|
||||||
|
void inc_size(unsigned size) { m_size += size; }
|
||||||
|
unsigned size() const { return m_size; }
|
||||||
|
const T& operator [] (unsigned idx) const { return m_array[idx]; }
|
||||||
|
T& operator [] (unsigned idx) { return m_array[idx]; }
|
||||||
|
|
||||||
|
void remove_all() { m_size = 0; }
|
||||||
|
void cut_at(unsigned num) { if(num < m_size) m_size = num; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned m_size;
|
||||||
|
unsigned m_capacity;
|
||||||
|
T* m_array;
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T>
|
||||||
|
void pod_array<T>::capacity(unsigned cap, unsigned extra_tail)
|
||||||
|
{
|
||||||
|
m_size = 0;
|
||||||
|
if(cap > m_capacity)
|
||||||
|
{
|
||||||
|
delete [] m_array;
|
||||||
|
m_capacity = cap + extra_tail;
|
||||||
|
m_array = m_capacity ? new T [m_capacity] : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T>
|
||||||
|
void pod_array<T>::resize(unsigned new_size)
|
||||||
|
{
|
||||||
|
if(new_size > m_size)
|
||||||
|
{
|
||||||
|
if(new_size > m_capacity)
|
||||||
|
{
|
||||||
|
T* data = new T[new_size];
|
||||||
|
memcpy(data, m_array, m_size * sizeof(T));
|
||||||
|
delete [] m_array;
|
||||||
|
m_array = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_size = new_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> pod_array<T>::pod_array(unsigned cap, unsigned extra_tail) :
|
||||||
|
m_size(0), m_capacity(0), m_array(0)
|
||||||
|
{
|
||||||
|
capacity(cap, extra_tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> pod_array<T>::pod_array(const pod_array<T>& v) :
|
||||||
|
m_size(v.m_size),
|
||||||
|
m_capacity(v.m_capacity),
|
||||||
|
m_array(v.m_capacity ? new T [v.m_capacity] : 0)
|
||||||
|
{
|
||||||
|
memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> const pod_array<T>&
|
||||||
|
pod_array<T>::operator = (const pod_array<T>&v)
|
||||||
|
{
|
||||||
|
capacity(v.m_capacity);
|
||||||
|
if(v.m_size) memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> class pod_array_adaptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T value_type;
|
||||||
|
pod_array_adaptor(T* array, unsigned size) :
|
||||||
|
m_array(array), m_size(size) {}
|
||||||
|
|
||||||
|
unsigned size() const { return m_size; }
|
||||||
|
const T& operator [] (unsigned idx) const { return m_array[idx]; }
|
||||||
|
T& operator [] (unsigned idx) { return m_array[idx]; }
|
||||||
|
private:
|
||||||
|
T* m_array;
|
||||||
|
unsigned m_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------pod_deque
|
||||||
|
// A simple class template to store Plain Old Data, similar to std::deque
|
||||||
|
// It doesn't reallocate memory but instead, uses blocks of data of size
|
||||||
|
// of (1 << S), that is, power of two. The data is NOT continuous in memory,
|
||||||
|
// so the only valid access method is operator [] or curr(), prev(), next()
|
||||||
|
//
|
||||||
|
// There reallocs occure only when the pool of pointers to blocks needs
|
||||||
|
// to be extended (it happens very rear). You can control the value
|
||||||
|
// of increment to reallocate the pointer buffer. See the second constructor.
|
||||||
|
// By default, the incremeent value equals (1 << S), i.e., the block size.
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S=6> class pod_deque
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
block_shift = S,
|
||||||
|
block_size = 1 << block_shift,
|
||||||
|
block_mask = block_size - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef T value_type;
|
||||||
|
|
||||||
|
~pod_deque();
|
||||||
|
pod_deque();
|
||||||
|
pod_deque(unsigned block_ptr_inc);
|
||||||
|
|
||||||
|
// Copying
|
||||||
|
pod_deque(const pod_deque<T, S>& v);
|
||||||
|
const pod_deque<T, S>& operator = (const pod_deque<T, S>& v);
|
||||||
|
|
||||||
|
void remove_all() { m_size = 0; }
|
||||||
|
void free_all() { free_tail(0); }
|
||||||
|
void free_tail(unsigned size);
|
||||||
|
void add(const T& val);
|
||||||
|
void modify_last(const T& val);
|
||||||
|
void remove_last();
|
||||||
|
|
||||||
|
int allocate_continuous_block(unsigned num_elements);
|
||||||
|
|
||||||
|
void cut_at(unsigned size)
|
||||||
|
{
|
||||||
|
if(size < m_size) m_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned size() const { return m_size; }
|
||||||
|
|
||||||
|
const T& operator [] (unsigned idx) const
|
||||||
|
{
|
||||||
|
return m_blocks[idx >> block_shift][idx & block_mask];
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator [] (unsigned idx)
|
||||||
|
{
|
||||||
|
return m_blocks[idx >> block_shift][idx & block_mask];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& curr(unsigned idx) const
|
||||||
|
{
|
||||||
|
return (*this)[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
T& curr(unsigned idx)
|
||||||
|
{
|
||||||
|
return (*this)[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& prev(unsigned idx) const
|
||||||
|
{
|
||||||
|
return (*this)[(idx + m_size - 1) % m_size];
|
||||||
|
}
|
||||||
|
|
||||||
|
T& prev(unsigned idx)
|
||||||
|
{
|
||||||
|
return (*this)[(idx + m_size - 1) % m_size];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& next(unsigned idx) const
|
||||||
|
{
|
||||||
|
return (*this)[(idx + 1) % m_size];
|
||||||
|
}
|
||||||
|
|
||||||
|
T& next(unsigned idx)
|
||||||
|
{
|
||||||
|
return (*this)[(idx + 1) % m_size];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& last() const
|
||||||
|
{
|
||||||
|
return (*this)[m_size - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
T& last()
|
||||||
|
{
|
||||||
|
return (*this)[m_size - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned byte_size() const;
|
||||||
|
void serialize(int8u* ptr) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void allocate_block(unsigned nb);
|
||||||
|
T* data_ptr();
|
||||||
|
|
||||||
|
unsigned m_size;
|
||||||
|
unsigned m_num_blocks;
|
||||||
|
unsigned m_max_blocks;
|
||||||
|
T** m_blocks;
|
||||||
|
unsigned m_block_ptr_inc;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S> pod_deque<T, S>::~pod_deque()
|
||||||
|
{
|
||||||
|
if(m_num_blocks)
|
||||||
|
{
|
||||||
|
T** blk = m_blocks + m_num_blocks - 1;
|
||||||
|
while(m_num_blocks--)
|
||||||
|
{
|
||||||
|
delete [] *blk;
|
||||||
|
--blk;
|
||||||
|
}
|
||||||
|
delete [] m_blocks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S>
|
||||||
|
void pod_deque<T, S>::free_tail(unsigned size)
|
||||||
|
{
|
||||||
|
if(size < m_size)
|
||||||
|
{
|
||||||
|
unsigned nb = (size + block_mask) >> block_shift;
|
||||||
|
while(m_num_blocks > nb)
|
||||||
|
{
|
||||||
|
delete [] m_blocks[--m_num_blocks];
|
||||||
|
}
|
||||||
|
m_size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S> pod_deque<T, S>::pod_deque() :
|
||||||
|
m_size(0),
|
||||||
|
m_num_blocks(0),
|
||||||
|
m_max_blocks(0),
|
||||||
|
m_blocks(0),
|
||||||
|
m_block_ptr_inc(block_size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S>
|
||||||
|
pod_deque<T, S>::pod_deque(unsigned block_ptr_inc) :
|
||||||
|
m_size(0),
|
||||||
|
m_num_blocks(0),
|
||||||
|
m_max_blocks(0),
|
||||||
|
m_blocks(0),
|
||||||
|
m_block_ptr_inc(block_ptr_inc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S>
|
||||||
|
pod_deque<T, S>::pod_deque(const pod_deque<T, S>& v) :
|
||||||
|
m_size(v.m_size),
|
||||||
|
m_num_blocks(v.m_num_blocks),
|
||||||
|
m_max_blocks(v.m_max_blocks),
|
||||||
|
m_blocks(v.m_max_blocks ? new T* [v.m_max_blocks] : 0),
|
||||||
|
m_block_ptr_inc(v.m_block_ptr_inc)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < v.m_num_blocks; ++i)
|
||||||
|
{
|
||||||
|
m_blocks[i] = new T [block_size];
|
||||||
|
memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S>
|
||||||
|
const pod_deque<T, S>& pod_deque<T, S>::operator = (const pod_deque<T, S>& v)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for(i = m_num_blocks; i < v.m_num_blocks; ++i)
|
||||||
|
{
|
||||||
|
allocate_block(i);
|
||||||
|
}
|
||||||
|
for(i = 0; i < v.m_num_blocks; ++i)
|
||||||
|
{
|
||||||
|
memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
|
||||||
|
}
|
||||||
|
m_size = v.m_size;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S>
|
||||||
|
void pod_deque<T, S>::allocate_block(unsigned nb)
|
||||||
|
{
|
||||||
|
if(nb >= m_max_blocks)
|
||||||
|
{
|
||||||
|
T** new_blocks = new T* [m_max_blocks + m_block_ptr_inc];
|
||||||
|
|
||||||
|
if(m_blocks)
|
||||||
|
{
|
||||||
|
memcpy(new_blocks,
|
||||||
|
m_blocks,
|
||||||
|
m_num_blocks * sizeof(T*));
|
||||||
|
|
||||||
|
delete [] m_blocks;
|
||||||
|
}
|
||||||
|
m_blocks = new_blocks;
|
||||||
|
m_max_blocks += m_block_ptr_inc;
|
||||||
|
}
|
||||||
|
m_blocks[nb] = new T [block_size];
|
||||||
|
m_num_blocks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S>
|
||||||
|
inline T* pod_deque<T, S>::data_ptr()
|
||||||
|
{
|
||||||
|
unsigned nb = m_size >> block_shift;
|
||||||
|
if(nb >= m_num_blocks)
|
||||||
|
{
|
||||||
|
allocate_block(nb);
|
||||||
|
}
|
||||||
|
return m_blocks[nb] + (m_size & block_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S>
|
||||||
|
inline void pod_deque<T, S>::add(const T& val)
|
||||||
|
{
|
||||||
|
*data_ptr() = val;
|
||||||
|
++m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S>
|
||||||
|
inline void pod_deque<T, S>::remove_last()
|
||||||
|
{
|
||||||
|
if(m_size) --m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S>
|
||||||
|
void pod_deque<T, S>::modify_last(const T& val)
|
||||||
|
{
|
||||||
|
remove_last();
|
||||||
|
add(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S>
|
||||||
|
int pod_deque<T, S>::allocate_continuous_block(unsigned num_elements)
|
||||||
|
{
|
||||||
|
if(num_elements < block_size)
|
||||||
|
{
|
||||||
|
data_ptr(); // Allocate initial block if necessary
|
||||||
|
unsigned rest = block_size - (m_size & block_mask);
|
||||||
|
unsigned index;
|
||||||
|
if(num_elements <= rest)
|
||||||
|
{
|
||||||
|
// The rest of the block is good, we can use it
|
||||||
|
//-----------------
|
||||||
|
index = m_size;
|
||||||
|
m_size += num_elements;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New block
|
||||||
|
//---------------
|
||||||
|
m_size += rest;
|
||||||
|
data_ptr();
|
||||||
|
index = m_size;
|
||||||
|
m_size += num_elements;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
return -1; // Impossible to allocate
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S>
|
||||||
|
unsigned pod_deque<T, S>::byte_size() const
|
||||||
|
{
|
||||||
|
return m_size * sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T, unsigned S>
|
||||||
|
void pod_deque<T, S>::serialize(int8u* ptr) const
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < m_size; i++)
|
||||||
|
{
|
||||||
|
memcpy(ptr, &(*this)[i], sizeof(T));
|
||||||
|
ptr += sizeof(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------pod_allocator
|
||||||
|
// Allocator for arbitrary POD data. Most usable in different cache
|
||||||
|
// systems for efficient memory allocations.
|
||||||
|
// Memory is allocated with blocks of fixed size ("block_size" in
|
||||||
|
// the constructor). If required size exceeds the block size the allocator
|
||||||
|
// creates a new block of the required size. However, the most efficient
|
||||||
|
// use is when the average reqired size is much less than the block size.
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
class pod_allocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void remove_all()
|
||||||
|
{
|
||||||
|
if(m_num_blocks)
|
||||||
|
{
|
||||||
|
int8u** blk = m_blocks + m_num_blocks - 1;
|
||||||
|
while(m_num_blocks--)
|
||||||
|
{
|
||||||
|
delete [] *blk;
|
||||||
|
--blk;
|
||||||
|
}
|
||||||
|
delete [] m_blocks;
|
||||||
|
}
|
||||||
|
m_num_blocks = 0;
|
||||||
|
m_max_blocks = 0;
|
||||||
|
m_blocks = 0;
|
||||||
|
m_buf_ptr = 0;
|
||||||
|
m_rest = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~pod_allocator()
|
||||||
|
{
|
||||||
|
remove_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
pod_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) :
|
||||||
|
m_block_size(block_size),
|
||||||
|
m_block_ptr_inc(block_ptr_inc),
|
||||||
|
m_num_blocks(0),
|
||||||
|
m_max_blocks(0),
|
||||||
|
m_blocks(0),
|
||||||
|
m_buf_ptr(0),
|
||||||
|
m_rest(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int8u* allocate(unsigned size, unsigned alignment=1)
|
||||||
|
{
|
||||||
|
if(size == 0) return 0;
|
||||||
|
if(size <= m_rest)
|
||||||
|
{
|
||||||
|
int8u* ptr = m_buf_ptr;
|
||||||
|
if(alignment > 1)
|
||||||
|
{
|
||||||
|
unsigned align = (alignment - unsigned(ptr) % alignment) % alignment;
|
||||||
|
size += align;
|
||||||
|
ptr += align;
|
||||||
|
if(size <= m_rest)
|
||||||
|
{
|
||||||
|
m_rest -= size;
|
||||||
|
m_buf_ptr += size;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
allocate_block(size);
|
||||||
|
return allocate(size - align, alignment);
|
||||||
|
}
|
||||||
|
m_rest -= size;
|
||||||
|
m_buf_ptr += size;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
allocate_block(size + alignment - 1);
|
||||||
|
return allocate(size, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
void allocate_block(unsigned size)
|
||||||
|
{
|
||||||
|
if(size < m_block_size) size = m_block_size;
|
||||||
|
if(m_num_blocks >= m_max_blocks)
|
||||||
|
{
|
||||||
|
int8u** new_blocks = new int8u* [m_max_blocks + m_block_ptr_inc];
|
||||||
|
|
||||||
|
if(m_blocks)
|
||||||
|
{
|
||||||
|
memcpy(new_blocks,
|
||||||
|
m_blocks,
|
||||||
|
m_num_blocks * sizeof(int8u*));
|
||||||
|
|
||||||
|
delete [] m_blocks;
|
||||||
|
}
|
||||||
|
m_blocks = new_blocks;
|
||||||
|
m_max_blocks += m_block_ptr_inc;
|
||||||
|
}
|
||||||
|
m_blocks[m_num_blocks] = m_buf_ptr = new int8u [size];
|
||||||
|
m_num_blocks++;
|
||||||
|
m_rest = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned m_block_size;
|
||||||
|
unsigned m_block_ptr_inc;
|
||||||
|
unsigned m_num_blocks;
|
||||||
|
unsigned m_max_blocks;
|
||||||
|
int8u** m_blocks;
|
||||||
|
int8u* m_buf_ptr;
|
||||||
|
unsigned m_rest;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
quick_sort_threshold = 9
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------swap_elements
|
||||||
|
template<class T> inline void swap_elements(T& a, T& b)
|
||||||
|
{
|
||||||
|
T temp = a;
|
||||||
|
a = b;
|
||||||
|
b = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------quick_sort
|
||||||
|
template<class Array, class Less>
|
||||||
|
void quick_sort(Array& arr, Less less)
|
||||||
|
{
|
||||||
|
if(arr.size() < 2) return;
|
||||||
|
|
||||||
|
typename Array::value_type* e1;
|
||||||
|
typename Array::value_type* e2;
|
||||||
|
|
||||||
|
int stack[80];
|
||||||
|
int* top = stack;
|
||||||
|
int limit = arr.size();
|
||||||
|
int base = 0;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
int len = limit - base;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
int pivot;
|
||||||
|
|
||||||
|
if(len > quick_sort_threshold)
|
||||||
|
{
|
||||||
|
// we use base + len/2 as the pivot
|
||||||
|
pivot = base + len / 2;
|
||||||
|
swap_elements(arr[base], arr[pivot]);
|
||||||
|
|
||||||
|
i = base + 1;
|
||||||
|
j = limit - 1;
|
||||||
|
|
||||||
|
// now ensure that *i <= *base <= *j
|
||||||
|
e1 = &(arr[j]);
|
||||||
|
e2 = &(arr[i]);
|
||||||
|
if(less(*e1, *e2)) swap_elements(*e1, *e2);
|
||||||
|
|
||||||
|
e1 = &(arr[base]);
|
||||||
|
e2 = &(arr[i]);
|
||||||
|
if(less(*e1, *e2)) swap_elements(*e1, *e2);
|
||||||
|
|
||||||
|
e1 = &(arr[j]);
|
||||||
|
e2 = &(arr[base]);
|
||||||
|
if(less(*e1, *e2)) swap_elements(*e1, *e2);
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
do i++; while( less(arr[i], arr[base]) );
|
||||||
|
do j--; while( less(arr[base], arr[j]) );
|
||||||
|
|
||||||
|
if( i > j )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
swap_elements(arr[i], arr[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
swap_elements(arr[base], arr[j]);
|
||||||
|
|
||||||
|
// now, push the largest sub-array
|
||||||
|
if(j - base > limit - i)
|
||||||
|
{
|
||||||
|
top[0] = base;
|
||||||
|
top[1] = j;
|
||||||
|
base = i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
top[0] = i;
|
||||||
|
top[1] = limit;
|
||||||
|
limit = j;
|
||||||
|
}
|
||||||
|
top += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the sub-array is small, perform insertion sort
|
||||||
|
j = base;
|
||||||
|
i = j + 1;
|
||||||
|
|
||||||
|
for(; i < limit; j = i, i++)
|
||||||
|
{
|
||||||
|
for(; less(*(e1 = &(arr[j + 1])), *(e2 = &(arr[j]))); j--)
|
||||||
|
{
|
||||||
|
swap_elements(*e1, *e2);
|
||||||
|
if(j == base)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(top > stack)
|
||||||
|
{
|
||||||
|
top -= 2;
|
||||||
|
base = top[0];
|
||||||
|
limit = top[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------remove_duplicates
|
||||||
|
// Remove duplicates from a sorted array. It doesn't cut the the
|
||||||
|
// tail of the array, it just returns the number of remaining elements.
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
template<class Array, class Equal>
|
||||||
|
unsigned remove_duplicates(Array& arr, Equal equal)
|
||||||
|
{
|
||||||
|
if(arr.size() < 2) return arr.size();
|
||||||
|
|
||||||
|
unsigned i, j;
|
||||||
|
for(i = 1, j = 1; i < arr.size(); i++)
|
||||||
|
{
|
||||||
|
typename Array::value_type& e = arr[i];
|
||||||
|
if(!equal(e, arr[i - 1]))
|
||||||
|
{
|
||||||
|
arr[j++] = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Simple arrowhead/arrowtail generator
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_ARROWHEAD_INCLUDED
|
||||||
|
#define AGG_ARROWHEAD_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//===============================================================arrowhead
|
||||||
|
//
|
||||||
|
// See implementation agg_arrowhead.cpp
|
||||||
|
//
|
||||||
|
class arrowhead
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
arrowhead();
|
||||||
|
|
||||||
|
void head(double d1, double d2, double d3, double d4)
|
||||||
|
{
|
||||||
|
m_head_d1 = d1;
|
||||||
|
m_head_d2 = d2;
|
||||||
|
m_head_d3 = d3;
|
||||||
|
m_head_d4 = d4;
|
||||||
|
m_head_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void head() { m_head_flag = true; }
|
||||||
|
void no_head() { m_head_flag = false; }
|
||||||
|
|
||||||
|
void tail(double d1, double d2, double d3, double d4)
|
||||||
|
{
|
||||||
|
m_tail_d1 = d1;
|
||||||
|
m_tail_d2 = d2;
|
||||||
|
m_tail_d3 = d3;
|
||||||
|
m_tail_d4 = d4;
|
||||||
|
m_tail_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tail() { m_tail_flag = true; }
|
||||||
|
void no_tail() { m_tail_flag = false; }
|
||||||
|
|
||||||
|
void rewind(unsigned id);
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_head_d1;
|
||||||
|
double m_head_d2;
|
||||||
|
double m_head_d3;
|
||||||
|
double m_head_d4;
|
||||||
|
double m_tail_d1;
|
||||||
|
double m_tail_d2;
|
||||||
|
double m_tail_d3;
|
||||||
|
double m_tail_d4;
|
||||||
|
bool m_head_flag;
|
||||||
|
bool m_tail_flag;
|
||||||
|
double m_coord[16];
|
||||||
|
unsigned m_cmd[8];
|
||||||
|
unsigned m_curr_id;
|
||||||
|
unsigned m_curr_coord;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,283 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_BASICS_INCLUDED
|
||||||
|
#define AGG_BASICS_INCLUDED
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
typedef signed char int8; //----int8
|
||||||
|
typedef unsigned char int8u; //----int8u
|
||||||
|
typedef signed short int16; //----int16
|
||||||
|
typedef unsigned short int16u; //----int16u
|
||||||
|
typedef signed int int32; //----int32
|
||||||
|
typedef unsigned int int32u; //----int32u
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
typedef unsigned char cover_type; //----cover_type
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
cover_shift = 8, //----cover_shift
|
||||||
|
cover_size = 1 << cover_shift, //----cover_size
|
||||||
|
cover_mask = cover_size - 1, //----cover_mask
|
||||||
|
cover_none = 0, //----cover_none
|
||||||
|
cover_full = cover_mask //----cover_full
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------pi
|
||||||
|
const double pi = 3.14159265358979323846;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------deg2rad
|
||||||
|
inline double deg2rad(double deg)
|
||||||
|
{
|
||||||
|
return deg * pi / 180.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------rad2deg
|
||||||
|
inline double rad2deg(double rad)
|
||||||
|
{
|
||||||
|
return rad * 180.0 / pi;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------rect_base
|
||||||
|
template<class T> struct rect_base
|
||||||
|
{
|
||||||
|
typedef rect_base<T> self_type;
|
||||||
|
T x1;
|
||||||
|
T y1;
|
||||||
|
T x2;
|
||||||
|
T y2;
|
||||||
|
|
||||||
|
rect_base() {}
|
||||||
|
rect_base(T x1_, T y1_, T x2_, T y2_) :
|
||||||
|
x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
|
||||||
|
|
||||||
|
const self_type& normalize()
|
||||||
|
{
|
||||||
|
T t;
|
||||||
|
if(x1 > x2) { t = x1; x1 = x2; x2 = t; }
|
||||||
|
if(y1 > y2) { t = y1; y1 = y2; y2 = t; }
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool clip(const self_type& r)
|
||||||
|
{
|
||||||
|
if(x2 > r.x2) x2 = r.x2;
|
||||||
|
if(y2 > r.y2) y2 = r.y2;
|
||||||
|
if(x1 < r.x1) x1 = r.x1;
|
||||||
|
if(y1 < r.y1) y1 = r.y1;
|
||||||
|
return x1 <= x2 && y1 <= y2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_valid() const
|
||||||
|
{
|
||||||
|
return x1 <= x2 && y1 <= y2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------intersect_rectangles
|
||||||
|
template<class Rect>
|
||||||
|
inline Rect intersect_rectangles(const Rect& r1, const Rect& r2)
|
||||||
|
{
|
||||||
|
Rect r = r1;
|
||||||
|
|
||||||
|
// First process x2,y2 because the other order
|
||||||
|
// results in Internal Compiler Error under
|
||||||
|
// Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in
|
||||||
|
// case of "Maximize Speed" optimization option.
|
||||||
|
//-----------------
|
||||||
|
if(r.x2 > r2.x2) r.x2 = r2.x2;
|
||||||
|
if(r.y2 > r2.y2) r.y2 = r2.y2;
|
||||||
|
if(r.x1 < r2.x1) r.x1 = r2.x1;
|
||||||
|
if(r.y1 < r2.y1) r.y1 = r2.y1;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------unite_rectangles
|
||||||
|
template<class Rect>
|
||||||
|
inline Rect unite_rectangles(const Rect& r1, const Rect& r2)
|
||||||
|
{
|
||||||
|
Rect r = r1;
|
||||||
|
if(r.x2 < r2.x2) r.x2 = r2.x2;
|
||||||
|
if(r.y2 < r2.y2) r.y2 = r2.y2;
|
||||||
|
if(r.x1 > r2.x1) r.x1 = r2.x1;
|
||||||
|
if(r.y1 > r2.y1) r.y1 = r2.y1;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef rect_base<int> rect; //----rect
|
||||||
|
typedef rect_base<double> rect_d; //----rect_d
|
||||||
|
|
||||||
|
//---------------------------------------------------------path_commands_e
|
||||||
|
enum path_commands_e
|
||||||
|
{
|
||||||
|
path_cmd_stop = 0, //----path_cmd_stop
|
||||||
|
path_cmd_move_to = 1, //----path_cmd_move_to
|
||||||
|
path_cmd_line_to = 2, //----path_cmd_line_to
|
||||||
|
path_cmd_curve3 = 3, //----path_cmd_curve3
|
||||||
|
path_cmd_curve4 = 4, //----path_cmd_curve4
|
||||||
|
path_cmd_end_poly = 6, //----path_cmd_end_poly
|
||||||
|
path_cmd_mask = 0x0F //----path_cmd_mask
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------path_flags_e
|
||||||
|
enum path_flags_e
|
||||||
|
{
|
||||||
|
path_flags_none = 0, //----path_flags_none
|
||||||
|
path_flags_ccw = 0x10, //----path_flags_ccw
|
||||||
|
path_flags_cw = 0x20, //----path_flags_cw
|
||||||
|
path_flags_close = 0x40, //----path_flags_close
|
||||||
|
path_flags_mask = 0xF0 //----path_flags_mask
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------is_vertex
|
||||||
|
inline bool is_vertex(unsigned c)
|
||||||
|
{
|
||||||
|
return c >= path_cmd_move_to && c < path_cmd_end_poly;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------is_stop
|
||||||
|
inline bool is_stop(unsigned c)
|
||||||
|
{
|
||||||
|
return c == path_cmd_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------is_move_to
|
||||||
|
inline bool is_move_to(unsigned c)
|
||||||
|
{
|
||||||
|
return c == path_cmd_move_to;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------is_line_to
|
||||||
|
inline bool is_line_to(unsigned c)
|
||||||
|
{
|
||||||
|
return c == path_cmd_line_to;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------is_curve
|
||||||
|
inline bool is_curve(unsigned c)
|
||||||
|
{
|
||||||
|
return c == path_cmd_curve3 || c == path_cmd_curve4;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------is_curve3
|
||||||
|
inline bool is_curve3(unsigned c)
|
||||||
|
{
|
||||||
|
return c == path_cmd_curve3;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------is_curve4
|
||||||
|
inline bool is_curve4(unsigned c)
|
||||||
|
{
|
||||||
|
return c == path_cmd_curve4;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------is_end_poly
|
||||||
|
inline bool is_end_poly(unsigned c)
|
||||||
|
{
|
||||||
|
return (c & path_cmd_mask) == path_cmd_end_poly;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------is_close
|
||||||
|
inline bool is_close(unsigned c)
|
||||||
|
{
|
||||||
|
return (c & ~(path_flags_cw | path_flags_ccw)) ==
|
||||||
|
(path_cmd_end_poly | path_flags_close);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------is_next_poly
|
||||||
|
inline bool is_next_poly(unsigned c)
|
||||||
|
{
|
||||||
|
return is_stop(c) || is_move_to(c) || is_end_poly(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------is_cw
|
||||||
|
inline bool is_cw(unsigned c)
|
||||||
|
{
|
||||||
|
return (c & path_flags_cw) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------is_ccw
|
||||||
|
inline bool is_ccw(unsigned c)
|
||||||
|
{
|
||||||
|
return (c & path_flags_ccw) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------is_oriented
|
||||||
|
inline bool is_oriented(unsigned c)
|
||||||
|
{
|
||||||
|
return (c & (path_flags_cw | path_flags_ccw)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------is_closed
|
||||||
|
inline bool is_closed(unsigned c)
|
||||||
|
{
|
||||||
|
return (c & path_flags_close) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------get_close_flag
|
||||||
|
inline unsigned get_close_flag(unsigned c)
|
||||||
|
{
|
||||||
|
return c & path_flags_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------clear_orientation
|
||||||
|
inline unsigned clear_orientation(unsigned c)
|
||||||
|
{
|
||||||
|
return c & ~(path_flags_cw | path_flags_ccw);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------get_orientation
|
||||||
|
inline unsigned get_orientation(unsigned c)
|
||||||
|
{
|
||||||
|
return c & (path_flags_cw | path_flags_ccw);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------set_orientation
|
||||||
|
inline unsigned set_orientation(unsigned c, unsigned o)
|
||||||
|
{
|
||||||
|
return clear_orientation(c) | o;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------point_type
|
||||||
|
struct point_type
|
||||||
|
{
|
||||||
|
double x, y;
|
||||||
|
|
||||||
|
point_type() {}
|
||||||
|
point_type(double x_, double y_) : x(x_), y(y_) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------vertex_type
|
||||||
|
struct vertex_type
|
||||||
|
{
|
||||||
|
double x, y;
|
||||||
|
unsigned cmd;
|
||||||
|
|
||||||
|
vertex_type() {}
|
||||||
|
vertex_type(double x_, double y_, unsigned cmd_) :
|
||||||
|
x(x_), y(y_), cmd(cmd_) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e.,
|
||||||
|
// 4, 7, 10, or 13 vertices.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_BEZIER_ARC_INCLUDED
|
||||||
|
#define AGG_BEZIER_ARC_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_conv_transform.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
void arc_to_bezier(double cx, double cy, double rx, double ry,
|
||||||
|
double start_angle, double sweep_angle,
|
||||||
|
double* curve);
|
||||||
|
|
||||||
|
|
||||||
|
//==============================================================bezier_arc
|
||||||
|
//
|
||||||
|
// See implemantaion agg_bezier_arc.cpp
|
||||||
|
//
|
||||||
|
class bezier_arc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bezier_arc() : m_vertex(26) {}
|
||||||
|
bezier_arc(double x, double y,
|
||||||
|
double rx, double ry,
|
||||||
|
double start_angle,
|
||||||
|
double sweep_angle)
|
||||||
|
{
|
||||||
|
init(x, y, rx, ry, start_angle, sweep_angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(double x, double y,
|
||||||
|
double rx, double ry,
|
||||||
|
double start_angle,
|
||||||
|
double sweep_angle);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void rewind(unsigned)
|
||||||
|
{
|
||||||
|
m_vertex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
if(m_vertex >= m_num_vertices) return path_cmd_stop;
|
||||||
|
*x = m_vertices[m_vertex];
|
||||||
|
*y = m_vertices[m_vertex + 1];
|
||||||
|
m_vertex += 2;
|
||||||
|
return (m_vertex == 2) ? path_cmd_move_to : path_cmd_curve4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supplemantary functions. num_vertices() actually returns doubled
|
||||||
|
// number of vertices. That is, for 1 vertex it returns 2.
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned num_vertices() const { return m_num_vertices; }
|
||||||
|
const double* vertices() const { return m_vertices; }
|
||||||
|
double* vertices() { return m_vertices; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned m_vertex;
|
||||||
|
unsigned m_num_vertices;
|
||||||
|
double m_vertices[26];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================bezier_arc_svg
|
||||||
|
// Compute an SVG-style bezier arc.
|
||||||
|
//
|
||||||
|
// Computes an elliptical arc from (x1, y1) to (x2, y2). The size and
|
||||||
|
// orientation of the ellipse are defined by two radii (rx, ry)
|
||||||
|
// and an x-axis-rotation, which indicates how the ellipse as a whole
|
||||||
|
// is rotated relative to the current coordinate system. The center
|
||||||
|
// (cx, cy) of the ellipse is calculated automatically to satisfy the
|
||||||
|
// constraints imposed by the other parameters.
|
||||||
|
// large-arc-flag and sweep-flag contribute to the automatic calculations
|
||||||
|
// and help determine how the arc is drawn.
|
||||||
|
class bezier_arc_svg
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
bezier_arc_svg() : m_arc(), m_radii_ok(false) {}
|
||||||
|
|
||||||
|
bezier_arc_svg(double x1, double y1,
|
||||||
|
double rx, double ry,
|
||||||
|
double angle,
|
||||||
|
bool large_arc_flag,
|
||||||
|
bool sweep_flag,
|
||||||
|
double x2, double y2) :
|
||||||
|
m_arc(), m_radii_ok(false)
|
||||||
|
{
|
||||||
|
init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void init(double x1, double y1,
|
||||||
|
double rx, double ry,
|
||||||
|
double angle,
|
||||||
|
bool large_arc_flag,
|
||||||
|
bool sweep_flag,
|
||||||
|
double x2, double y2);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
bool radii_ok() const { return m_radii_ok; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void rewind(unsigned)
|
||||||
|
{
|
||||||
|
m_arc.rewind(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
return m_arc.vertex(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supplemantary functions. num_vertices() actually returns doubled
|
||||||
|
// number of vertices. That is, for 1 vertex it returns 2.
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned num_vertices() const { return m_arc.num_vertices(); }
|
||||||
|
const double* vertices() const { return m_arc.vertices(); }
|
||||||
|
double* vertices() { return m_arc.vertices(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bezier_arc m_arc;
|
||||||
|
bool m_radii_ok;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_BITSET_ITERATOR_INCLUDED
|
||||||
|
#define AGG_BITSET_ITERATOR_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
class bitset_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bitset_iterator(const int8u* bits, unsigned offset = 0) :
|
||||||
|
m_bits(bits + (offset >> 3)),
|
||||||
|
m_mask(0x80 >> (offset & 7))
|
||||||
|
{}
|
||||||
|
|
||||||
|
void operator ++ ()
|
||||||
|
{
|
||||||
|
m_mask >>= 1;
|
||||||
|
if(m_mask == 0)
|
||||||
|
{
|
||||||
|
++m_bits;
|
||||||
|
m_mask = 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned bit() const
|
||||||
|
{
|
||||||
|
return (*m_bits) & m_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int8u* m_bits;
|
||||||
|
int8u m_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// bounding_rect function template
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_BOUNDING_RECT_INCLUDED
|
||||||
|
#define AGG_BOUNDING_RECT_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//-----------------------------------------------------------bounding_rect
|
||||||
|
template<class VertexSource, class GetId, class CoordT>
|
||||||
|
bool bounding_rect(VertexSource& vs, GetId& gi,
|
||||||
|
unsigned start, unsigned num,
|
||||||
|
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
for(i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
vs.rewind(gi[start + i]);
|
||||||
|
unsigned cmd;
|
||||||
|
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||||
|
{
|
||||||
|
if(is_vertex(cmd))
|
||||||
|
{
|
||||||
|
if(first)
|
||||||
|
{
|
||||||
|
*x1 = CoordT(x);
|
||||||
|
*y1 = CoordT(y);
|
||||||
|
*x2 = CoordT(x);
|
||||||
|
*y2 = CoordT(y);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(CoordT(x) < *x1) *x1 = CoordT(x);
|
||||||
|
if(CoordT(y) < *y1) *y1 = CoordT(y);
|
||||||
|
if(CoordT(x) > *x2) *x2 = CoordT(x);
|
||||||
|
if(CoordT(y) > *y2) *y2 = CoordT(y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *x1 <= *x2 && *y1 <= *y2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------bounding_rect_single
|
||||||
|
template<class VertexSource, class CoordT>
|
||||||
|
bool bounding_rect_single(VertexSource& vs, unsigned path_id,
|
||||||
|
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
|
||||||
|
{
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
vs.rewind(path_id);
|
||||||
|
unsigned cmd;
|
||||||
|
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||||
|
{
|
||||||
|
if(is_vertex(cmd))
|
||||||
|
{
|
||||||
|
if(first)
|
||||||
|
{
|
||||||
|
*x1 = CoordT(x);
|
||||||
|
*y1 = CoordT(y);
|
||||||
|
*x2 = CoordT(x);
|
||||||
|
*y2 = CoordT(y);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(CoordT(x) < *x1) *x1 = CoordT(x);
|
||||||
|
if(CoordT(y) < *y1) *y1 = CoordT(y);
|
||||||
|
if(CoordT(x) > *x2) *x2 = CoordT(x);
|
||||||
|
if(CoordT(y) > *y2) *y2 = CoordT(y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *x1 <= *x2 && *y1 <= *y2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// class bspline
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_BSPLINE_INCLUDED
|
||||||
|
#define AGG_BSPLINE_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//----------------------------------------------------------------bspline
|
||||||
|
// A very simple class of Bi-cubic Spline interpolation.
|
||||||
|
// First call init(num, x[], y[]) where num - number of source points,
|
||||||
|
// x, y - arrays of X and Y values respectively. Here Y must be a function
|
||||||
|
// of X. It means that all the X-coordinates must be arranged in the ascending
|
||||||
|
// order.
|
||||||
|
// Then call get(x) that calculates a value Y for the respective X.
|
||||||
|
// The class supports extrapolation, i.e. you can call get(x) where x is
|
||||||
|
// outside the given with init() X-range. Extrapolation is a simple linear
|
||||||
|
// function.
|
||||||
|
//
|
||||||
|
// See Implementation agg_bspline.cpp
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
class bspline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~bspline();
|
||||||
|
bspline();
|
||||||
|
bspline(int num);
|
||||||
|
bspline(int num, const double* x, const double* y);
|
||||||
|
|
||||||
|
void init(int num);
|
||||||
|
void add_point(double x, double y);
|
||||||
|
void prepare();
|
||||||
|
|
||||||
|
void init(int num, const double* x, const double* y);
|
||||||
|
|
||||||
|
double get(double x) const;
|
||||||
|
double get_stateful(double x) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bspline(const bspline&);
|
||||||
|
const bspline& operator = (const bspline&);
|
||||||
|
|
||||||
|
static void bsearch(int n, const double *x, double x0, int *i);
|
||||||
|
double extrapolation_left(double x) const;
|
||||||
|
double extrapolation_right(double x) const;
|
||||||
|
double interpolation(double x, int i) const;
|
||||||
|
|
||||||
|
int m_max;
|
||||||
|
int m_num;
|
||||||
|
double* m_x;
|
||||||
|
double* m_y;
|
||||||
|
double* m_am;
|
||||||
|
mutable int m_last_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Liang-Barsky clipping
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED
|
||||||
|
#define AGG_CLIP_LIANG_BARSKY_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//-------------------------------------------------------clip_liang_barsky
|
||||||
|
template<class T>
|
||||||
|
inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2,
|
||||||
|
const rect_base<T>& clip_box,
|
||||||
|
T* x, T* y)
|
||||||
|
{
|
||||||
|
const double nearzero = 1e-30;
|
||||||
|
|
||||||
|
double deltax = x2 - x1;
|
||||||
|
double deltay = y2 - y1;
|
||||||
|
double xin;
|
||||||
|
double xout;
|
||||||
|
double yin;
|
||||||
|
double yout;
|
||||||
|
double tinx;
|
||||||
|
double tiny;
|
||||||
|
double toutx;
|
||||||
|
double touty;
|
||||||
|
double tin1;
|
||||||
|
double tin2;
|
||||||
|
double tout1;
|
||||||
|
unsigned np = 0;
|
||||||
|
|
||||||
|
if(deltax == 0.0)
|
||||||
|
{
|
||||||
|
// bump off of the vertical
|
||||||
|
deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(deltay == 0.0)
|
||||||
|
{
|
||||||
|
// bump off of the horizontal
|
||||||
|
deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(deltax > 0.0)
|
||||||
|
{
|
||||||
|
// points to right
|
||||||
|
xin = clip_box.x1;
|
||||||
|
xout = clip_box.x2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xin = clip_box.x2;
|
||||||
|
xout = clip_box.x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(deltay > 0.0)
|
||||||
|
{
|
||||||
|
// points up
|
||||||
|
yin = clip_box.y1;
|
||||||
|
yout = clip_box.y2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yin = clip_box.y2;
|
||||||
|
yout = clip_box.y1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinx = (xin - x1) / deltax;
|
||||||
|
tiny = (yin - y1) / deltay;
|
||||||
|
|
||||||
|
if (tinx < tiny)
|
||||||
|
{
|
||||||
|
// hits x first
|
||||||
|
tin1 = tinx;
|
||||||
|
tin2 = tiny;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// hits y first
|
||||||
|
tin1 = tiny;
|
||||||
|
tin2 = tinx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tin1 <= 1.0)
|
||||||
|
{
|
||||||
|
if(0.0 < tin1)
|
||||||
|
{
|
||||||
|
*x++ = (T)xin;
|
||||||
|
*y++ = (T)yin;
|
||||||
|
++np;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tin2 <= 1.0)
|
||||||
|
{
|
||||||
|
toutx = (xout - x1) / deltax;
|
||||||
|
touty = (yout - y1) / deltay;
|
||||||
|
|
||||||
|
tout1 = (toutx < touty) ? toutx : touty;
|
||||||
|
|
||||||
|
if(tin2 > 0.0 || tout1 > 0.0)
|
||||||
|
{
|
||||||
|
if(tin2 <= tout1)
|
||||||
|
{
|
||||||
|
if(tin2 > 0.0)
|
||||||
|
{
|
||||||
|
if(tinx > tiny)
|
||||||
|
{
|
||||||
|
*x++ = (T)xin;
|
||||||
|
*y++ = (T)(y1 + tinx * deltay);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*x++ = (T)(x1 + tiny * deltax);
|
||||||
|
*y++ = (T)yin;
|
||||||
|
}
|
||||||
|
++np;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tout1 < 1.0)
|
||||||
|
{
|
||||||
|
if(toutx < touty)
|
||||||
|
{
|
||||||
|
*x++ = (T)xout;
|
||||||
|
*y++ = (T)(y1 + toutx * deltay);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*x++ = (T)(x1 + touty * deltax);
|
||||||
|
*y++ = (T)yout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*x++ = x2;
|
||||||
|
*y++ = y2;
|
||||||
|
}
|
||||||
|
++np;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(tinx > tiny)
|
||||||
|
{
|
||||||
|
*x++ = (T)xin;
|
||||||
|
*y++ = (T)yout;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*x++ = (T)xout;
|
||||||
|
*y++ = (T)yin;
|
||||||
|
}
|
||||||
|
++np;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return np;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// color type rgba
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_COLOR_RGBA_INCLUDED
|
||||||
|
#define AGG_COLOR_RGBA_INCLUDED
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//====================================================================rgba
|
||||||
|
struct rgba
|
||||||
|
{
|
||||||
|
enum premul { pre };
|
||||||
|
|
||||||
|
double r;
|
||||||
|
double g;
|
||||||
|
double b;
|
||||||
|
double a;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba() {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba(double r_, double g_, double b_, double a_=1.0) :
|
||||||
|
r(r_), g(g_), b(b_), a(a_) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba(premul, double r_, double g_, double b_, double a_=1.0) :
|
||||||
|
r(r_), g(g_), b(b_), a(a_)
|
||||||
|
{
|
||||||
|
premultiply();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba(premul, const rgba& c) : r(c.r), g(c.g), b(c.b), a(c.a)
|
||||||
|
{
|
||||||
|
premultiply();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba(premul, const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_)
|
||||||
|
{
|
||||||
|
premultiply();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
r = g = b = a = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba& transparent()
|
||||||
|
{
|
||||||
|
a = 0.0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba& transparent(premul)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba& opacity(double a_)
|
||||||
|
{
|
||||||
|
if(a_ < 0.0) a_ = 0.0;
|
||||||
|
if(a_ > 1.0) a_ = 1.0;
|
||||||
|
a = a_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba& opacity(premul, double a_)
|
||||||
|
{
|
||||||
|
if(a_ < 0.0) a_ = 0.0;
|
||||||
|
if(a_ > 1.0) a_ = 1.0;
|
||||||
|
premultiply(a_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
double opacity() const
|
||||||
|
{
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba& premultiply()
|
||||||
|
{
|
||||||
|
r *= a;
|
||||||
|
g *= a;
|
||||||
|
b *= a;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba& premultiply(double a_)
|
||||||
|
{
|
||||||
|
if(a == 0.0 || a_ == 0.0)
|
||||||
|
{
|
||||||
|
r = g = b = a = 0.0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
a_ /= a;
|
||||||
|
r *= a_;
|
||||||
|
g *= a_;
|
||||||
|
b *= a_;
|
||||||
|
a = a_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba& demultiply()
|
||||||
|
{
|
||||||
|
if(a == 0)
|
||||||
|
{
|
||||||
|
r = g = b = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
double a_ = 1.0 / a;
|
||||||
|
r *= a_;
|
||||||
|
g *= a_;
|
||||||
|
b *= a_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba gradient(rgba c, double k) const
|
||||||
|
{
|
||||||
|
rgba ret;
|
||||||
|
ret.r = r + (c.r - r) * k;
|
||||||
|
ret.g = g + (c.g - g) * k;
|
||||||
|
ret.b = b + (c.b - b) * k;
|
||||||
|
ret.a = a + (c.a - a) * k;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static rgba no_color() { return rgba(0,0,0,0); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static rgba from_wavelength(double wl, double gamma = 1.0);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba(double wavelen, double gamma=1.0)
|
||||||
|
{
|
||||||
|
*this = from_wavelength(wavelen, gamma);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline rgba rgba_pre(double r, double g, double b, double a=1.0)
|
||||||
|
{
|
||||||
|
return rgba(rgba::pre, r, g, b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
inline rgba rgba_pre(const rgba& c)
|
||||||
|
{
|
||||||
|
return rgba(rgba::pre, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
inline rgba rgba_pre(const rgba& c, double a)
|
||||||
|
{
|
||||||
|
return rgba(rgba::pre, c, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline rgba rgba::from_wavelength(double wl, double gamma)
|
||||||
|
{
|
||||||
|
rgba t(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
if(wl >= 380.0 && wl <= 440.0)
|
||||||
|
{
|
||||||
|
t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0);
|
||||||
|
t.b = 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(wl >= 440.0 && wl <= 490.0)
|
||||||
|
{
|
||||||
|
t.g = (wl - 440.0) / (490.0 - 440.0);
|
||||||
|
t.b = 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(wl >= 490.0 && wl <= 510.0)
|
||||||
|
{
|
||||||
|
t.g = 1.0;
|
||||||
|
t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(wl >= 510.0 && wl <= 580.0)
|
||||||
|
{
|
||||||
|
t.r = (wl - 510.0) / (580.0 - 510.0);
|
||||||
|
t.g = 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(wl >= 580.0 && wl <= 645.0)
|
||||||
|
{
|
||||||
|
t.r = 1.0;
|
||||||
|
t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if(wl >= 645.0 && wl <= 780.0)
|
||||||
|
{
|
||||||
|
t.r = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double s = 1.0;
|
||||||
|
if(wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0);
|
||||||
|
else if(wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0);
|
||||||
|
|
||||||
|
t.r = pow(t.r * s, gamma);
|
||||||
|
t.g = pow(t.g * s, gamma);
|
||||||
|
t.b = pow(t.b * s, gamma);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,256 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// color type rgba8
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_COLOR_RGBA8_INCLUDED
|
||||||
|
#define AGG_COLOR_RGBA8_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
// Supported byte orders for RGB and RGBA pixel formats
|
||||||
|
//=======================================================================
|
||||||
|
struct order_rgb24 { enum { R=0, G=1, B=2, rgb24_tag }; }; //----order_rgb24
|
||||||
|
struct order_bgr24 { enum { B=0, G=1, R=2, rgb24_tag }; }; //----order_bgr24
|
||||||
|
struct order_rgba32 { enum { R=0, G=1, B=2, A=3, rgba32_tag }; }; //----order_rgba32
|
||||||
|
struct order_argb32 { enum { A=0, R=1, G=2, B=3, rgba32_tag }; }; //----order_argb32
|
||||||
|
struct order_abgr32 { enum { A=0, B=1, G=2, R=3, rgba32_tag }; }; //----order_abgr32
|
||||||
|
struct order_bgra32 { enum { B=0, G=1, R=2, A=3, rgba32_tag }; }; //----order_bgra32
|
||||||
|
|
||||||
|
//==================================================================rgba8
|
||||||
|
struct rgba8
|
||||||
|
{
|
||||||
|
enum order { rgb, bgr };
|
||||||
|
enum premul { pre };
|
||||||
|
|
||||||
|
int8u r;
|
||||||
|
int8u g;
|
||||||
|
int8u b;
|
||||||
|
int8u a;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba8() {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=255) :
|
||||||
|
r(int8u(r_)), g(int8u(g_)), b(int8u(b_)), a(int8u(a_)) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba8(premul, unsigned r_, unsigned g_, unsigned b_, unsigned a_=255) :
|
||||||
|
r(int8u(r_)), g(int8u(g_)), b(int8u(b_)), a(int8u(a_))
|
||||||
|
{
|
||||||
|
premultiply();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba8(const rgba& c) :
|
||||||
|
r(int8u(c.r * 255.0 + 0.5)),
|
||||||
|
g(int8u(c.g * 255.0 + 0.5)),
|
||||||
|
b(int8u(c.b * 255.0 + 0.5)),
|
||||||
|
a(int8u(c.a * 255.0 + 0.5)) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba8(premul, const rgba8& c) :
|
||||||
|
r(int8u(c.r)), g(int8u(c.g)), b(int8u(c.b)), a(int8u(c.a))
|
||||||
|
{
|
||||||
|
premultiply();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba8(const rgba8& c, unsigned a_) :
|
||||||
|
r(int8u(c.r)), g(int8u(c.g)), b(int8u(c.b)), a(int8u(a_)) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba8(premul, const rgba8& c, unsigned a_) :
|
||||||
|
r(int8u(c.r)), g(int8u(c.g)), b(int8u(c.b)), a(int8u(a_))
|
||||||
|
{
|
||||||
|
premultiply();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba8(unsigned packed, order o) :
|
||||||
|
r(int8u((o == rgb) ? ((packed >> 16) & 0xFF) : (packed & 0xFF))),
|
||||||
|
g(int8u((packed >> 8) & 0xFF)),
|
||||||
|
b(int8u((o == rgb) ? (packed & 0xFF) : ((packed >> 16) & 0xFF))),
|
||||||
|
a(255) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba8(premul, unsigned packed, order o) :
|
||||||
|
r(int8u((o == rgb) ? ((packed >> 16) & 0xFF) : (packed & 0xFF))),
|
||||||
|
g(int8u((packed >> 8) & 0xFF)),
|
||||||
|
b(int8u((o == rgb) ? (packed & 0xFF) : ((packed >> 16) & 0xFF))),
|
||||||
|
a(255)
|
||||||
|
{
|
||||||
|
premultiply();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
r = g = b = a = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba8& transparent()
|
||||||
|
{
|
||||||
|
a = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba8& transparent(premul)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba8& opacity(double a_)
|
||||||
|
{
|
||||||
|
if(a_ < 0.0) a_ = 0.0;
|
||||||
|
if(a_ > 1.0) a_ = 1.0;
|
||||||
|
a = int8u(a_ * 255.0 + 0.5);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba8& opacity(premul, double a_)
|
||||||
|
{
|
||||||
|
if(a_ < 0.0) a_ = 0.0;
|
||||||
|
if(a_ > 1.0) a_ = 1.0;
|
||||||
|
a = int8u(a_ * 255.0 + 0.5);
|
||||||
|
premultiply(int8u(a_ * 255.0));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
double opacity() const
|
||||||
|
{
|
||||||
|
return double(a) / 255.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba8& premultiply()
|
||||||
|
{
|
||||||
|
if(a == 255) return *this;
|
||||||
|
if(a == 0)
|
||||||
|
{
|
||||||
|
r = g = b = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
r = (r * a) >> 8;
|
||||||
|
g = (g * a) >> 8;
|
||||||
|
b = (b * a) >> 8;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba8& premultiply(unsigned a_)
|
||||||
|
{
|
||||||
|
if(a == 255 && a_ >= 255) return *this;
|
||||||
|
if(a == 0 || a_ == 0)
|
||||||
|
{
|
||||||
|
r = g = b = a = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
unsigned r_ = (r * a_) / a;
|
||||||
|
unsigned g_ = (g * a_) / a;
|
||||||
|
unsigned b_ = (b * a_) / a;
|
||||||
|
r = int8u((r_ > a_) ? a_ : r_);
|
||||||
|
g = int8u((g_ > a_) ? a_ : g_);
|
||||||
|
b = int8u((b_ > a_) ? a_ : b_);
|
||||||
|
a = int8u(a_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rgba8& demultiply()
|
||||||
|
{
|
||||||
|
if(a == 255) return *this;
|
||||||
|
if(a == 0)
|
||||||
|
{
|
||||||
|
r = g = b = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
unsigned r_ = (r * 255) / a;
|
||||||
|
unsigned g_ = (g * 255) / a;
|
||||||
|
unsigned b_ = (b * 255) / a;
|
||||||
|
r = (r_ > 255) ? 255 : r_;
|
||||||
|
g = (g_ > 255) ? 255 : g_;
|
||||||
|
b = (b_ > 255) ? 255 : b_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba8 gradient(rgba8 c, double k) const
|
||||||
|
{
|
||||||
|
rgba8 ret;
|
||||||
|
int ik = int(k * 256);
|
||||||
|
ret.r = int8u(int(r) + (((int(c.r) - int(r)) * ik) >> 8));
|
||||||
|
ret.g = int8u(int(g) + (((int(c.g) - int(g)) * ik) >> 8));
|
||||||
|
ret.b = int8u(int(b) + (((int(c.b) - int(b)) * ik) >> 8));
|
||||||
|
ret.a = int8u(int(a) + (((int(c.a) - int(a)) * ik) >> 8));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static rgba8 no_color() { return rgba8(0,0,0,0); }
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static rgba8 from_wavelength(double wl, double gamma = 1.0)
|
||||||
|
{
|
||||||
|
return rgba8(rgba::from_wavelength(wl, gamma));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rgba8(double wavelen, double gamma=1.0)
|
||||||
|
{
|
||||||
|
*this = from_wavelength(wavelen, gamma);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, unsigned a=1.0)
|
||||||
|
{
|
||||||
|
return rgba8(rgba8::pre, r, g, b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
inline rgba8 rgba8_pre(const rgba& c)
|
||||||
|
{
|
||||||
|
return rgba8(rgba8::pre, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
inline rgba8 rgba8_pre(const rgba8& c, unsigned a)
|
||||||
|
{
|
||||||
|
return rgba8(rgba8::pre, c, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+169
@@ -0,0 +1,169 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_CONV_ADAPTOR_VCGEN_INCLUDED
|
||||||
|
#define AGG_CONV_ADAPTOR_VCGEN_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_vertex_iterator.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//------------------------------------------------------------null_markers
|
||||||
|
struct null_markers
|
||||||
|
{
|
||||||
|
void remove_all() {}
|
||||||
|
void add_vertex(double, double, unsigned) {}
|
||||||
|
void prepare_src() {}
|
||||||
|
|
||||||
|
void rewind(unsigned) {}
|
||||||
|
unsigned vertex(double*, double*) { return path_cmd_stop; }
|
||||||
|
|
||||||
|
typedef null_markers source_type;
|
||||||
|
typedef vertex_iterator<source_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------conv_adaptor_vcgen
|
||||||
|
template<class VertexSource,
|
||||||
|
class Generator,
|
||||||
|
class Markers=null_markers> class conv_adaptor_vcgen
|
||||||
|
{
|
||||||
|
enum status
|
||||||
|
{
|
||||||
|
initial,
|
||||||
|
accumulate,
|
||||||
|
generate
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
conv_adaptor_vcgen(VertexSource& source) :
|
||||||
|
m_source(&source),
|
||||||
|
m_status(initial)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void set_source(VertexSource& source) { m_source = &source; }
|
||||||
|
|
||||||
|
Generator& generator() { return m_generator; }
|
||||||
|
const Generator& generator() const { return m_generator; }
|
||||||
|
|
||||||
|
Markers& markers() { return m_markers; }
|
||||||
|
const Markers& markers() const { return m_markers; }
|
||||||
|
|
||||||
|
void rewind(unsigned id)
|
||||||
|
{
|
||||||
|
m_source->rewind(id);
|
||||||
|
m_status = initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
typedef conv_adaptor_vcgen<VertexSource, Generator, Markers> source_type;
|
||||||
|
typedef vertex_iterator<source_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Prohibit copying
|
||||||
|
conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
|
||||||
|
const conv_adaptor_vcgen<VertexSource, Generator, Markers>&
|
||||||
|
operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
|
||||||
|
|
||||||
|
VertexSource* m_source;
|
||||||
|
Generator m_generator;
|
||||||
|
Markers m_markers;
|
||||||
|
status m_status;
|
||||||
|
unsigned m_last_cmd;
|
||||||
|
double m_start_x;
|
||||||
|
double m_start_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VertexSource, class Generator, class Markers>
|
||||||
|
unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
unsigned cmd = path_cmd_stop;
|
||||||
|
bool done = false;
|
||||||
|
while(!done)
|
||||||
|
{
|
||||||
|
switch(m_status)
|
||||||
|
{
|
||||||
|
case initial:
|
||||||
|
m_markers.remove_all();
|
||||||
|
m_last_cmd = m_source->vertex(&m_start_x, &m_start_y);
|
||||||
|
m_status = accumulate;
|
||||||
|
|
||||||
|
case accumulate:
|
||||||
|
if(is_stop(m_last_cmd)) return path_cmd_stop;
|
||||||
|
|
||||||
|
m_generator.remove_all();
|
||||||
|
m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
|
||||||
|
m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
cmd = m_source->vertex(x, y);
|
||||||
|
if(is_vertex(cmd))
|
||||||
|
{
|
||||||
|
m_last_cmd = cmd;
|
||||||
|
if(is_move_to(cmd))
|
||||||
|
{
|
||||||
|
m_start_x = *x;
|
||||||
|
m_start_y = *y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_generator.add_vertex(*x, *y, cmd);
|
||||||
|
m_markers.add_vertex(*x, *y, path_cmd_line_to);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(is_stop(cmd))
|
||||||
|
{
|
||||||
|
m_last_cmd = path_cmd_stop;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(is_end_poly(cmd))
|
||||||
|
{
|
||||||
|
m_generator.add_vertex(*x, *y, cmd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_generator.rewind(0);
|
||||||
|
m_status = generate;
|
||||||
|
|
||||||
|
case generate:
|
||||||
|
cmd = m_generator.vertex(x, y);
|
||||||
|
if(is_stop(cmd))
|
||||||
|
{
|
||||||
|
m_status = accumulate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+127
@@ -0,0 +1,127 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_CONV_ADAPTOR_VPGEN_INCLUDED
|
||||||
|
#define AGG_CONV_ADAPTOR_VPGEN_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_vertex_iterator.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//======================================================conv_adaptor_vpgen
|
||||||
|
template<class VertexSource, class VPGen> class conv_adaptor_vpgen
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
|
||||||
|
|
||||||
|
void set_source(VertexSource& source) { m_source = &source; }
|
||||||
|
|
||||||
|
VPGen& vpgen() { return m_vpgen; }
|
||||||
|
const VPGen& vpgen() const { return m_vpgen; }
|
||||||
|
|
||||||
|
void rewind(unsigned path_id);
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
typedef conv_adaptor_vpgen<VertexSource, VPGen> source_type;
|
||||||
|
typedef vertex_iterator<source_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);
|
||||||
|
const conv_adaptor_vpgen<VertexSource, VPGen>&
|
||||||
|
operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&);
|
||||||
|
|
||||||
|
VertexSource* m_source;
|
||||||
|
VPGen m_vpgen;
|
||||||
|
double m_start_x;
|
||||||
|
double m_start_y;
|
||||||
|
unsigned m_poly_flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VertexSource, class VPGen>
|
||||||
|
void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id)
|
||||||
|
{
|
||||||
|
m_source->rewind(path_id);
|
||||||
|
m_vpgen.reset();
|
||||||
|
m_start_x = 0;
|
||||||
|
m_start_y = 0;
|
||||||
|
m_poly_flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VertexSource, class VPGen>
|
||||||
|
unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
unsigned cmd = path_cmd_stop;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
cmd = m_vpgen.vertex(x, y);
|
||||||
|
if(!is_stop(cmd)) break;
|
||||||
|
|
||||||
|
if(m_poly_flags)
|
||||||
|
{
|
||||||
|
cmd = m_poly_flags;
|
||||||
|
m_poly_flags = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
double tx, ty;
|
||||||
|
cmd = m_source->vertex(&tx, &ty);
|
||||||
|
if(is_vertex(cmd))
|
||||||
|
{
|
||||||
|
if(is_move_to(cmd))
|
||||||
|
{
|
||||||
|
m_vpgen.move_to(tx, ty);
|
||||||
|
m_start_x = tx;
|
||||||
|
m_start_y = ty;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_vpgen.line_to(tx, ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(is_end_poly(cmd))
|
||||||
|
{
|
||||||
|
m_poly_flags = cmd;
|
||||||
|
if(is_closed(cmd))
|
||||||
|
{
|
||||||
|
m_vpgen.line_to(m_start_x, m_start_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The adaptor should be transparent to all unknown commands
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_CONV_BSPLINE_INCLUDED
|
||||||
|
#define AGG_CONV_BSPLINE_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_vcgen_bspline.h"
|
||||||
|
#include "agg_conv_adaptor_vcgen.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//---------------------------------------------------------conv_bspline
|
||||||
|
template<class VertexSource>
|
||||||
|
struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline>
|
||||||
|
{
|
||||||
|
typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type;
|
||||||
|
|
||||||
|
conv_bspline(VertexSource& vs) :
|
||||||
|
conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) {}
|
||||||
|
|
||||||
|
void interpolation_step(double v) { base_type::generator().interpolation_step(v); }
|
||||||
|
double interpolation_step() const { return base_type::generator().interpolation_step(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_bspline(const conv_bspline<VertexSource>&);
|
||||||
|
const conv_bspline<VertexSource>&
|
||||||
|
operator = (const conv_bspline<VertexSource>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Polygon clipping converter
|
||||||
|
// There an optimized Liang-Basky algorithm is used.
|
||||||
|
// The algorithm doesn't optimize the degenerate edges, i.e. it will never
|
||||||
|
// break a closed polygon into two or more ones, instead, there will be
|
||||||
|
// degenerate edges coinciding with the respective clipping boundaries.
|
||||||
|
// This is a sub-optimal solution, because that optimization would require
|
||||||
|
// extra, rather expensive math while the rasterizer tolerates it quite well,
|
||||||
|
// without any considerable overhead.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_CONV_CLIP_POLYGON_INCLUDED
|
||||||
|
#define AGG_CONV_CLIP_POLYGON_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_conv_adaptor_vpgen.h"
|
||||||
|
#include "agg_vpgen_clip_polygon.h"
|
||||||
|
#include "agg_vertex_iterator.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//=======================================================conv_clip_polygon
|
||||||
|
template<class VertexSource>
|
||||||
|
struct conv_clip_polygon : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>
|
||||||
|
{
|
||||||
|
typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> base_type;
|
||||||
|
|
||||||
|
conv_clip_polygon(VertexSource& vs) :
|
||||||
|
conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) {}
|
||||||
|
|
||||||
|
void clip_box(double x1, double y1, double x2, double y2)
|
||||||
|
{
|
||||||
|
base_type::vpgen().clip_box(x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
double x1() const { return base_type::vpgen().x1(); }
|
||||||
|
double y1() const { return base_type::vpgen().y1(); }
|
||||||
|
double x2() const { return base_type::vpgen().x2(); }
|
||||||
|
double y2() const { return base_type::vpgen().y2(); }
|
||||||
|
|
||||||
|
typedef conv_clip_polygon<VertexSource> source_type;
|
||||||
|
typedef vertex_iterator<source_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_clip_polygon(const conv_clip_polygon<VertexSource>&);
|
||||||
|
const conv_clip_polygon<VertexSource>&
|
||||||
|
operator = (const conv_clip_polygon<VertexSource>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_CONV_CLOSE_POLYGON_INCLUDED
|
||||||
|
#define AGG_CONV_CLOSE_POLYGON_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_vertex_iterator.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//======================================================conv_close_polygon
|
||||||
|
template<class VertexSource> class conv_close_polygon
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
|
||||||
|
|
||||||
|
void set_source(VertexSource& source) { m_source = &source; }
|
||||||
|
|
||||||
|
void rewind(unsigned path_id);
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
typedef conv_close_polygon<VertexSource> source_type;
|
||||||
|
typedef vertex_iterator<source_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_close_polygon(const conv_close_polygon<VertexSource>&);
|
||||||
|
const conv_close_polygon<VertexSource>&
|
||||||
|
operator = (const conv_close_polygon<VertexSource>&);
|
||||||
|
|
||||||
|
VertexSource* m_source;
|
||||||
|
unsigned m_cmd[2];
|
||||||
|
double m_x[2];
|
||||||
|
double m_y[2];
|
||||||
|
unsigned m_vertex;
|
||||||
|
bool m_line_to;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VertexSource>
|
||||||
|
void conv_close_polygon<VertexSource>::rewind(unsigned path_id)
|
||||||
|
{
|
||||||
|
m_source->rewind(path_id);
|
||||||
|
m_vertex = 2;
|
||||||
|
m_line_to = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VertexSource>
|
||||||
|
unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
unsigned cmd = path_cmd_stop;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(m_vertex < 2)
|
||||||
|
{
|
||||||
|
*x = m_x[m_vertex];
|
||||||
|
*y = m_y[m_vertex];
|
||||||
|
cmd = m_cmd[m_vertex];
|
||||||
|
++m_vertex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = m_source->vertex(x, y);
|
||||||
|
|
||||||
|
if(is_end_poly(cmd))
|
||||||
|
{
|
||||||
|
cmd |= path_flags_close;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_stop(cmd))
|
||||||
|
{
|
||||||
|
if(m_line_to)
|
||||||
|
{
|
||||||
|
m_cmd[0] = path_cmd_end_poly | path_flags_close;
|
||||||
|
m_cmd[1] = path_cmd_stop;
|
||||||
|
m_vertex = 0;
|
||||||
|
m_line_to = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_move_to(cmd))
|
||||||
|
{
|
||||||
|
if(m_line_to)
|
||||||
|
{
|
||||||
|
m_x[0] = 0.0;
|
||||||
|
m_y[0] = 0.0;
|
||||||
|
m_cmd[0] = path_cmd_end_poly | path_flags_close;
|
||||||
|
m_x[1] = *x;
|
||||||
|
m_y[1] = *y;
|
||||||
|
m_cmd[1] = cmd;
|
||||||
|
m_vertex = 0;
|
||||||
|
m_line_to = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_vertex(cmd))
|
||||||
|
{
|
||||||
|
m_line_to = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_CONV_CONCAT_INCLUDED
|
||||||
|
#define AGG_CONV_CONCAT_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_vertex_iterator.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//=============================================================conv_concat
|
||||||
|
// Concatenation of two paths. Usually used to combine lines or curves
|
||||||
|
// with markers such as arrowheads
|
||||||
|
template<class VS1, class VS2> class conv_concat
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
conv_concat(VS1& source1, VS2& source2) :
|
||||||
|
m_source1(&source1), m_source2(&source2), m_status(2) {}
|
||||||
|
|
||||||
|
void set_source1(VS1& source) { m_source1 = &source; }
|
||||||
|
void set_source2(VS2& source) { m_source2 = &source; }
|
||||||
|
|
||||||
|
|
||||||
|
void rewind(unsigned id)
|
||||||
|
{
|
||||||
|
m_source1->rewind(id);
|
||||||
|
m_source2->rewind(0);
|
||||||
|
m_status = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
unsigned cmd;
|
||||||
|
if(m_status == 0)
|
||||||
|
{
|
||||||
|
cmd = m_source1->vertex(x, y);
|
||||||
|
if(!is_stop(cmd)) return cmd;
|
||||||
|
m_status = 1;
|
||||||
|
}
|
||||||
|
if(m_status == 1)
|
||||||
|
{
|
||||||
|
cmd = m_source2->vertex(x, y);
|
||||||
|
if(!is_stop(cmd)) return cmd;
|
||||||
|
m_status = 2;
|
||||||
|
}
|
||||||
|
return path_cmd_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef conv_concat<VS1, VS2> source_type;
|
||||||
|
typedef vertex_iterator<source_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_concat(const conv_concat<VS1, VS2>&);
|
||||||
|
const conv_concat<VS1, VS2>&
|
||||||
|
operator = (const conv_concat<VS1, VS2>&);
|
||||||
|
|
||||||
|
VS1* m_source1;
|
||||||
|
VS2* m_source2;
|
||||||
|
int m_status;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// conv_stroke
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_CONV_CONTOUR_INCLUDED
|
||||||
|
#define AGG_CONV_CONTOUR_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_vcgen_contour.h"
|
||||||
|
#include "agg_conv_adaptor_vcgen.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//-----------------------------------------------------------conv_contour
|
||||||
|
template<class VertexSource>
|
||||||
|
struct conv_contour : public conv_adaptor_vcgen<VertexSource, vcgen_contour>
|
||||||
|
{
|
||||||
|
typedef conv_adaptor_vcgen<VertexSource, vcgen_contour> base_type;
|
||||||
|
|
||||||
|
conv_contour(VertexSource& vs) :
|
||||||
|
conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void width(double w) { base_type::generator().width(w); }
|
||||||
|
void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
|
||||||
|
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
|
||||||
|
void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); }
|
||||||
|
|
||||||
|
double width() const { return base_type::generator().width(); }
|
||||||
|
double miter_limit() const { return base_type::generator().miter_limit(); }
|
||||||
|
bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_contour(const conv_contour<VertexSource>&);
|
||||||
|
const conv_contour<VertexSource>&
|
||||||
|
operator = (const conv_contour<VertexSource>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// classes conv_curve
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_CONV_CURVE_INCLUDED
|
||||||
|
#define AGG_CONV_CURVE_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_curves.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------conv_curve
|
||||||
|
// Curve converter class. Any path storage can have Bezier curves defined
|
||||||
|
// by their control points. There're two types of curves supported: curve3
|
||||||
|
// and curve4. Curve3 is a conic Bezier curve with 2 endpoints and 1 control
|
||||||
|
// point. Curve4 has 2 control points (4 points in total) and can be used
|
||||||
|
// to interpolate more complicated curves. Curve4, unlike curve3 can be used
|
||||||
|
// to approximate arcs, both curcular and elliptical. Curves are approximated
|
||||||
|
// with straight lines and one of the approaches is just to store the whole
|
||||||
|
// sequence of vertices that approximate our curve. It takes additional
|
||||||
|
// memory, and at the same time the consecutive vertices can be calculated
|
||||||
|
// on demand.
|
||||||
|
//
|
||||||
|
// Initially, path storages are not suppose to keep all the vertices of the
|
||||||
|
// curves (although, nothig prevents us from doing so). Instead, path_storage
|
||||||
|
// keeps only vertices, needed to calculate a curve on demand. Those vertices
|
||||||
|
// are marked with special commands. So, if the path_storage contains curves
|
||||||
|
// (which are not real curves yet), and we render this storage directly,
|
||||||
|
// all we will see is only 2 or 3 straight line segments (for curve3 and
|
||||||
|
// curve4 respectively). If we need to see real curves drawn we need to
|
||||||
|
// include this class into the conversion pipeline.
|
||||||
|
//
|
||||||
|
// Class conv_curve recognizes commands path_cmd_curve3 and path_cmd_curve4
|
||||||
|
// and converts these vertices into a move_to/line_to sequence.
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
template<class VertexSource> class conv_curve
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
conv_curve(VertexSource& source) :
|
||||||
|
m_source(&source), m_last_x(0.0), m_last_y(0.0) {}
|
||||||
|
|
||||||
|
void set_source(VertexSource& source) { m_source = &source; }
|
||||||
|
|
||||||
|
void approximation_scale(double s)
|
||||||
|
{
|
||||||
|
m_curve3.approximation_scale(s);
|
||||||
|
m_curve4.approximation_scale(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
double approximation_scale() const
|
||||||
|
{
|
||||||
|
return m_curve3.approximation_scale();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rewind(unsigned id);
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
typedef conv_curve<VertexSource> source_type;
|
||||||
|
typedef vertex_iterator<source_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_curve(const conv_curve<VertexSource>&);
|
||||||
|
const conv_curve<VertexSource>&
|
||||||
|
operator = (const conv_curve<VertexSource>&);
|
||||||
|
|
||||||
|
VertexSource* m_source;
|
||||||
|
double m_last_x;
|
||||||
|
double m_last_y;
|
||||||
|
curve3 m_curve3;
|
||||||
|
curve4 m_curve4;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VertexSource>
|
||||||
|
void conv_curve<VertexSource>::rewind(unsigned id)
|
||||||
|
{
|
||||||
|
m_source->rewind(id);
|
||||||
|
m_last_x = 0.0;
|
||||||
|
m_last_y = 0.0;
|
||||||
|
m_curve3.reset();
|
||||||
|
m_curve4.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VertexSource>
|
||||||
|
unsigned conv_curve<VertexSource>::vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
if(!is_stop(m_curve3.vertex(x, y)))
|
||||||
|
{
|
||||||
|
m_last_x = *x;
|
||||||
|
m_last_y = *y;
|
||||||
|
return path_cmd_line_to;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!is_stop(m_curve4.vertex(x, y)))
|
||||||
|
{
|
||||||
|
m_last_x = *x;
|
||||||
|
m_last_y = *y;
|
||||||
|
return path_cmd_line_to;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ct2_x;
|
||||||
|
double ct2_y;
|
||||||
|
double end_x;
|
||||||
|
double end_y;
|
||||||
|
|
||||||
|
unsigned cmd = m_source->vertex(x, y);
|
||||||
|
switch(cmd)
|
||||||
|
{
|
||||||
|
case path_cmd_move_to:
|
||||||
|
case path_cmd_line_to:
|
||||||
|
m_last_x = *x;
|
||||||
|
m_last_y = *y;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case path_cmd_curve3:
|
||||||
|
m_source->vertex(&end_x, &end_y);
|
||||||
|
|
||||||
|
m_curve3.init(m_last_x, m_last_y,
|
||||||
|
*x, *y,
|
||||||
|
end_x, end_y);
|
||||||
|
|
||||||
|
m_curve3.vertex(x, y); // First call returns path_cmd_move_to
|
||||||
|
m_curve3.vertex(x, y); // This is the first vertex of the curve
|
||||||
|
cmd = path_cmd_line_to;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case path_cmd_curve4:
|
||||||
|
m_source->vertex(&ct2_x, &ct2_y);
|
||||||
|
m_source->vertex(&end_x, &end_y);
|
||||||
|
|
||||||
|
m_curve4.init(m_last_x, m_last_y,
|
||||||
|
*x, *y,
|
||||||
|
ct2_x, ct2_y,
|
||||||
|
end_x, end_y);
|
||||||
|
|
||||||
|
m_curve4.vertex(x, y); // First call returns path_cmd_move_to
|
||||||
|
m_curve4.vertex(x, y); // This is the first vertex of the curve
|
||||||
|
cmd = path_cmd_line_to;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// conv_dash
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_CONV_DASH_INCLUDED
|
||||||
|
#define AGG_CONV_DASH_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_vcgen_dash.h"
|
||||||
|
#include "agg_conv_adaptor_vcgen.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//---------------------------------------------------------------conv_dash
|
||||||
|
template<class VertexSource, class Markers=null_markers>
|
||||||
|
struct conv_dash : public conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>
|
||||||
|
{
|
||||||
|
typedef Markers marker_type;
|
||||||
|
typedef conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers> base_type;
|
||||||
|
|
||||||
|
conv_dash(VertexSource& vs) :
|
||||||
|
conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_all_dashes()
|
||||||
|
{
|
||||||
|
base_type::generator().remove_all_dashes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_dash(double dash_len, double gap_len)
|
||||||
|
{
|
||||||
|
base_type::generator().add_dash(dash_len, gap_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dash_start(double ds)
|
||||||
|
{
|
||||||
|
base_type::generator().dash_start(ds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shorten(double s) { base_type::generator().shorten(s); }
|
||||||
|
double shorten() const { return base_type::generator().shorten(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_dash(const conv_dash<VertexSource, Markers>&);
|
||||||
|
const conv_dash<VertexSource, Markers>&
|
||||||
|
operator = (const conv_dash<VertexSource, Markers>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,443 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// General Polygon Clipper based on the GPC library by Alan Murta
|
||||||
|
// Union, Intersection, XOR, A-B, B-A
|
||||||
|
// Contact the author if you intend to use it in commercial applications!
|
||||||
|
// http://www.cs.man.ac.uk/aig/staff/alan/software/
|
||||||
|
// Alan Murta (email: [email protected])
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_CONV_GPC_INCLUDED
|
||||||
|
#define AGG_CONV_GPC_INCLUDED
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_array.h"
|
||||||
|
#include "agg_vertex_iterator.h"
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "gpc.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
enum gpc_op_e
|
||||||
|
{
|
||||||
|
gpc_or,
|
||||||
|
gpc_and,
|
||||||
|
gpc_xor,
|
||||||
|
gpc_a_minus_b,
|
||||||
|
gpc_b_minus_a
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//================================================================conv_gpc
|
||||||
|
template<class VSA, class VSB> class conv_gpc
|
||||||
|
{
|
||||||
|
enum status
|
||||||
|
{
|
||||||
|
status_move_to,
|
||||||
|
status_line_to,
|
||||||
|
status_stop
|
||||||
|
};
|
||||||
|
|
||||||
|
struct contour_header_type
|
||||||
|
{
|
||||||
|
int num_vertices;
|
||||||
|
int hole_flag;
|
||||||
|
gpc_vertex* vertices;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef pod_deque<gpc_vertex, 8> vertex_array_type;
|
||||||
|
typedef pod_deque<contour_header_type, 6> contour_header_array_type;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef VSA source_a_type;
|
||||||
|
typedef VSB source_b_type;
|
||||||
|
typedef conv_gpc<source_a_type, source_b_type> self_type;
|
||||||
|
|
||||||
|
~conv_gpc()
|
||||||
|
{
|
||||||
|
free_gpc_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) :
|
||||||
|
m_src_a(&a),
|
||||||
|
m_src_b(&b),
|
||||||
|
m_status(status_move_to),
|
||||||
|
m_vertex(-1),
|
||||||
|
m_contour(-1),
|
||||||
|
m_operation(op)
|
||||||
|
{
|
||||||
|
memset(&m_poly_a, 0, sizeof(m_poly_a));
|
||||||
|
memset(&m_poly_b, 0, sizeof(m_poly_b));
|
||||||
|
memset(&m_result, 0, sizeof(m_result));
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_source1(VSA& source) { m_src_a = &source; }
|
||||||
|
void set_source2(VSB& source) { m_src_b = &source; }
|
||||||
|
|
||||||
|
void operation(gpc_op_e v) { m_operation = v; }
|
||||||
|
|
||||||
|
// Vertex Source Interface
|
||||||
|
void rewind(unsigned id);
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
// Iterator
|
||||||
|
typedef vertex_iterator<self_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_gpc(const conv_gpc<VSA, VSB>&);
|
||||||
|
const conv_gpc<VSA, VSB>& operator = (const conv_gpc<VSA, VSB>&);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void free_polygon(gpc_polygon& p);
|
||||||
|
void free_result();
|
||||||
|
void free_gpc_data();
|
||||||
|
void start_contour();
|
||||||
|
void add_vertex(double x, double y);
|
||||||
|
void end_contour(unsigned orientation);
|
||||||
|
void make_polygon(gpc_polygon& p);
|
||||||
|
void start_extracting();
|
||||||
|
bool next_contour();
|
||||||
|
bool next_vertex(double* x, double* y);
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class VS> void add(VS& src, gpc_polygon& p)
|
||||||
|
{
|
||||||
|
unsigned cmd;
|
||||||
|
double x, y;
|
||||||
|
double start_x = 0.0;
|
||||||
|
double start_y = 0.0;
|
||||||
|
bool line_to = false;
|
||||||
|
unsigned orientation = 0;
|
||||||
|
|
||||||
|
m_contour_accumulator.remove_all();
|
||||||
|
|
||||||
|
while(!is_stop(cmd = src.vertex(&x, &y)))
|
||||||
|
{
|
||||||
|
if(is_vertex(cmd))
|
||||||
|
{
|
||||||
|
if(is_move_to(cmd))
|
||||||
|
{
|
||||||
|
if(line_to)
|
||||||
|
{
|
||||||
|
end_contour(orientation);
|
||||||
|
orientation = 0;
|
||||||
|
}
|
||||||
|
start_contour();
|
||||||
|
start_x = x;
|
||||||
|
start_y = y;
|
||||||
|
}
|
||||||
|
add_vertex(x, y);
|
||||||
|
line_to = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(is_end_poly(cmd))
|
||||||
|
{
|
||||||
|
orientation = get_orientation(cmd);
|
||||||
|
if(line_to && is_closed(cmd))
|
||||||
|
{
|
||||||
|
add_vertex(start_x, start_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(line_to)
|
||||||
|
{
|
||||||
|
end_contour(orientation);
|
||||||
|
}
|
||||||
|
make_polygon(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
source_a_type* m_src_a;
|
||||||
|
source_b_type* m_src_b;
|
||||||
|
status m_status;
|
||||||
|
int m_vertex;
|
||||||
|
int m_contour;
|
||||||
|
gpc_op_e m_operation;
|
||||||
|
vertex_array_type m_vertex_accumulator;
|
||||||
|
contour_header_array_type m_contour_accumulator;
|
||||||
|
gpc_polygon m_poly_a;
|
||||||
|
gpc_polygon m_poly_b;
|
||||||
|
gpc_polygon m_result;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VSA, class VSB>
|
||||||
|
void conv_gpc<VSA, VSB>::free_polygon(gpc_polygon& p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < p.num_contours; i++)
|
||||||
|
{
|
||||||
|
delete [] p.contour[i].vertex;
|
||||||
|
}
|
||||||
|
delete [] p.hole;
|
||||||
|
delete [] p.contour;
|
||||||
|
memset(&p, 0, sizeof(gpc_polygon));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VSA, class VSB>
|
||||||
|
void conv_gpc<VSA, VSB>::free_result()
|
||||||
|
{
|
||||||
|
if(m_result.contour)
|
||||||
|
{
|
||||||
|
gpc_free_polygon(&m_result);
|
||||||
|
}
|
||||||
|
memset(&m_result, 0, sizeof(m_result));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VSA, class VSB>
|
||||||
|
void conv_gpc<VSA, VSB>::free_gpc_data()
|
||||||
|
{
|
||||||
|
free_polygon(m_poly_a);
|
||||||
|
free_polygon(m_poly_b);
|
||||||
|
free_result();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VSA, class VSB>
|
||||||
|
void conv_gpc<VSA, VSB>::start_contour()
|
||||||
|
{
|
||||||
|
contour_header_type h;
|
||||||
|
memset(&h, 0, sizeof(h));
|
||||||
|
m_contour_accumulator.add(h);
|
||||||
|
m_vertex_accumulator.remove_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VSA, class VSB>
|
||||||
|
inline void conv_gpc<VSA, VSB>::add_vertex(double x, double y)
|
||||||
|
{
|
||||||
|
gpc_vertex v;
|
||||||
|
v.x = x;
|
||||||
|
v.y = y;
|
||||||
|
m_vertex_accumulator.add(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VSA, class VSB>
|
||||||
|
void conv_gpc<VSA, VSB>::end_contour(unsigned orientation)
|
||||||
|
{
|
||||||
|
if(m_contour_accumulator.size())
|
||||||
|
{
|
||||||
|
if(m_vertex_accumulator.size() > 2)
|
||||||
|
{
|
||||||
|
contour_header_type& h =
|
||||||
|
m_contour_accumulator[m_contour_accumulator.size() - 1];
|
||||||
|
|
||||||
|
h.num_vertices = m_vertex_accumulator.size();
|
||||||
|
h.hole_flag = 0;
|
||||||
|
|
||||||
|
// TO DO: Clarify the "holes"
|
||||||
|
//if(is_cw(orientation)) h.hole_flag = 1;
|
||||||
|
|
||||||
|
h.vertices = new gpc_vertex [h.num_vertices];
|
||||||
|
gpc_vertex* d = h.vertices;
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < h.num_vertices; i++)
|
||||||
|
{
|
||||||
|
const gpc_vertex& s = m_vertex_accumulator[i];
|
||||||
|
d->x = s.x;
|
||||||
|
d->y = s.y;
|
||||||
|
++d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_vertex_accumulator.remove_last();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VSA, class VSB>
|
||||||
|
void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p)
|
||||||
|
{
|
||||||
|
free_polygon(p);
|
||||||
|
if(m_contour_accumulator.size())
|
||||||
|
{
|
||||||
|
p.num_contours = m_contour_accumulator.size();
|
||||||
|
|
||||||
|
// TO DO: Clarify the "holes"
|
||||||
|
//p.hole = new int[p.num_contours];
|
||||||
|
p.hole = 0;
|
||||||
|
|
||||||
|
p.contour = new gpc_vertex_list[p.num_contours];
|
||||||
|
|
||||||
|
int i;
|
||||||
|
//int* ph = p.hole;
|
||||||
|
gpc_vertex_list* pv = p.contour;
|
||||||
|
for(i = 0; i < p.num_contours; i++)
|
||||||
|
{
|
||||||
|
const contour_header_type& h = m_contour_accumulator[i];
|
||||||
|
// *ph++ = h.hole_flag;
|
||||||
|
pv->num_vertices = h.num_vertices;
|
||||||
|
pv->vertex = h.vertices;
|
||||||
|
++pv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VSA, class VSB>
|
||||||
|
void conv_gpc<VSA, VSB>::start_extracting()
|
||||||
|
{
|
||||||
|
m_status = status_move_to;
|
||||||
|
m_contour = -1;
|
||||||
|
m_vertex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VSA, class VSB>
|
||||||
|
bool conv_gpc<VSA, VSB>::next_contour()
|
||||||
|
{
|
||||||
|
if(++m_contour < m_result.num_contours)
|
||||||
|
{
|
||||||
|
m_vertex = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VSA, class VSB>
|
||||||
|
inline bool conv_gpc<VSA, VSB>::next_vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
const gpc_vertex_list& vlist = m_result.contour[m_contour];
|
||||||
|
if(++m_vertex < vlist.num_vertices)
|
||||||
|
{
|
||||||
|
const gpc_vertex& v = vlist.vertex[m_vertex];
|
||||||
|
*x = v.x;
|
||||||
|
*y = v.y;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VSA, class VSB>
|
||||||
|
void conv_gpc<VSA, VSB>::rewind(unsigned id)
|
||||||
|
{
|
||||||
|
free_result();
|
||||||
|
m_src_a->rewind(id);
|
||||||
|
m_src_b->rewind(id);
|
||||||
|
add(*m_src_a, m_poly_a);
|
||||||
|
add(*m_src_b, m_poly_b);
|
||||||
|
switch(m_operation)
|
||||||
|
{
|
||||||
|
case gpc_or:
|
||||||
|
gpc_polygon_clip(GPC_UNION,
|
||||||
|
&m_poly_a,
|
||||||
|
&m_poly_b,
|
||||||
|
&m_result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case gpc_and:
|
||||||
|
gpc_polygon_clip(GPC_INT,
|
||||||
|
&m_poly_a,
|
||||||
|
&m_poly_b,
|
||||||
|
&m_result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case gpc_xor:
|
||||||
|
gpc_polygon_clip(GPC_XOR,
|
||||||
|
&m_poly_a,
|
||||||
|
&m_poly_b,
|
||||||
|
&m_result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case gpc_a_minus_b:
|
||||||
|
gpc_polygon_clip(GPC_DIFF,
|
||||||
|
&m_poly_a,
|
||||||
|
&m_poly_b,
|
||||||
|
&m_result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case gpc_b_minus_a:
|
||||||
|
gpc_polygon_clip(GPC_DIFF,
|
||||||
|
&m_poly_b,
|
||||||
|
&m_poly_a,
|
||||||
|
&m_result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
start_extracting();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VSA, class VSB>
|
||||||
|
unsigned conv_gpc<VSA, VSB>::vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
if(m_status == status_move_to)
|
||||||
|
{
|
||||||
|
if(next_contour())
|
||||||
|
{
|
||||||
|
if(next_vertex(x, y))
|
||||||
|
{
|
||||||
|
m_status = status_line_to;
|
||||||
|
return path_cmd_move_to;
|
||||||
|
}
|
||||||
|
m_status = status_stop;
|
||||||
|
return path_cmd_end_poly | path_flags_close;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(next_vertex(x, y))
|
||||||
|
{
|
||||||
|
return path_cmd_line_to;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_status = status_move_to;
|
||||||
|
}
|
||||||
|
return path_cmd_end_poly | path_flags_close;
|
||||||
|
}
|
||||||
|
return path_cmd_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// conv_marker
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_CONV_MARKER_INCLUDED
|
||||||
|
#define AGG_CONV_MARKER_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_trans_affine.h"
|
||||||
|
#include "agg_vertex_iterator.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//-------------------------------------------------------------conv_marker
|
||||||
|
template<class MarkerLocator, class MarkerShapes>
|
||||||
|
class conv_marker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
conv_marker(MarkerLocator& ml, MarkerShapes& ms);
|
||||||
|
|
||||||
|
trans_affine& transform() { return m_transform; }
|
||||||
|
const trans_affine& transform() const { return m_transform; }
|
||||||
|
|
||||||
|
void rewind(unsigned id);
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
typedef conv_marker<MarkerLocator, MarkerShapes> source_type;
|
||||||
|
typedef vertex_iterator<source_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_marker(const conv_marker<MarkerLocator, MarkerShapes>&);
|
||||||
|
const conv_marker<MarkerLocator, MarkerShapes>&
|
||||||
|
operator = (const conv_marker<MarkerLocator, MarkerShapes>&);
|
||||||
|
|
||||||
|
enum status_e
|
||||||
|
{
|
||||||
|
initial,
|
||||||
|
markers,
|
||||||
|
polygon,
|
||||||
|
stop
|
||||||
|
};
|
||||||
|
|
||||||
|
MarkerLocator* m_marker_locator;
|
||||||
|
MarkerShapes* m_marker_shapes;
|
||||||
|
trans_affine m_transform;
|
||||||
|
trans_affine m_mtx;
|
||||||
|
status_e m_status;
|
||||||
|
unsigned m_marker;
|
||||||
|
unsigned m_num_markers;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class MarkerLocator, class MarkerShapes>
|
||||||
|
conv_marker<MarkerLocator, MarkerShapes>::conv_marker(MarkerLocator& ml, MarkerShapes& ms) :
|
||||||
|
m_marker_locator(&ml),
|
||||||
|
m_marker_shapes(&ms),
|
||||||
|
m_status(initial),
|
||||||
|
m_marker(0),
|
||||||
|
m_num_markers(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class MarkerLocator, class MarkerShapes>
|
||||||
|
void conv_marker<MarkerLocator, MarkerShapes>::rewind(unsigned)
|
||||||
|
{
|
||||||
|
m_status = initial;
|
||||||
|
m_marker = 0;
|
||||||
|
m_num_markers = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class MarkerLocator, class MarkerShapes>
|
||||||
|
unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
unsigned cmd = path_cmd_move_to;
|
||||||
|
double x1, y1, x2, y2;
|
||||||
|
|
||||||
|
while(!is_stop(cmd))
|
||||||
|
{
|
||||||
|
switch(m_status)
|
||||||
|
{
|
||||||
|
case initial:
|
||||||
|
if(m_num_markers == 0)
|
||||||
|
{
|
||||||
|
cmd = path_cmd_stop;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_marker_locator->rewind(m_marker);
|
||||||
|
++m_marker;
|
||||||
|
m_num_markers = 0;
|
||||||
|
m_status = markers;
|
||||||
|
|
||||||
|
case markers:
|
||||||
|
if(is_stop(m_marker_locator->vertex(&x1, &y1)))
|
||||||
|
{
|
||||||
|
m_status = initial;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(is_stop(m_marker_locator->vertex(&x2, &y2)))
|
||||||
|
{
|
||||||
|
m_status = initial;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++m_num_markers;
|
||||||
|
m_mtx = m_transform;
|
||||||
|
m_mtx *= trans_affine_rotation(atan2(y2 - y1, x2 - x1));
|
||||||
|
m_mtx *= trans_affine_translation(x1, y1);
|
||||||
|
m_marker_shapes->rewind(m_marker - 1);
|
||||||
|
m_status = polygon;
|
||||||
|
|
||||||
|
case polygon:
|
||||||
|
cmd = m_marker_shapes->vertex(x, y);
|
||||||
|
if(is_stop(cmd))
|
||||||
|
{
|
||||||
|
cmd = path_cmd_move_to;
|
||||||
|
m_status = markers;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_mtx.transform(x, y);
|
||||||
|
return cmd;
|
||||||
|
|
||||||
|
case stop:
|
||||||
|
cmd = path_cmd_stop;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_CONV_MARKER_ADAPTOR_INCLUDED
|
||||||
|
#define AGG_CONV_MARKER_ADAPTOR_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_conv_adaptor_vcgen.h"
|
||||||
|
#include "agg_vcgen_vertex_sequence.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//=====================================================conv_marker_adaptor
|
||||||
|
template<class VertexSource, class Markers=null_markers>
|
||||||
|
struct conv_marker_adaptor :
|
||||||
|
public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>
|
||||||
|
{
|
||||||
|
typedef Markers marker_type;
|
||||||
|
typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers> base_type;
|
||||||
|
|
||||||
|
conv_marker_adaptor(VertexSource& vs) :
|
||||||
|
conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>(vs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void shorten(double s) { base_type::generator().shorten(s); }
|
||||||
|
double shorten() const { return base_type::generator().shorten(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_marker_adaptor(const conv_marker_adaptor<VertexSource, Markers>&);
|
||||||
|
const conv_marker_adaptor<VertexSource, Markers>&
|
||||||
|
operator = (const conv_marker_adaptor<VertexSource, Markers>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+48
@@ -0,0 +1,48 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_CONV_SEGMENTATOR_INCLUDED
|
||||||
|
#define AGG_CONV_SEGMENTATOR_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_conv_adaptor_vpgen.h"
|
||||||
|
#include "agg_vpgen_segmentator.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//========================================================conv_segmentator
|
||||||
|
template<class VertexSource>
|
||||||
|
struct conv_segmentator : public conv_adaptor_vpgen<VertexSource, vpgen_segmentator>
|
||||||
|
{
|
||||||
|
typedef conv_adaptor_vpgen<VertexSource, vpgen_segmentator> base_type;
|
||||||
|
|
||||||
|
conv_segmentator(VertexSource& vs) :
|
||||||
|
conv_adaptor_vpgen<VertexSource, vpgen_segmentator>(vs) {}
|
||||||
|
|
||||||
|
void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); }
|
||||||
|
double approximation_scale() const { return base_type::vpgen().approximation_scale(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_segmentator(const conv_segmentator<VertexSource>&);
|
||||||
|
const conv_segmentator<VertexSource>&
|
||||||
|
operator = (const conv_segmentator<VertexSource>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_CONV_SHORTEN_PATH_INCLUDED
|
||||||
|
#define AGG_CONV_SHORTEN_PATH_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_conv_adaptor_vcgen.h"
|
||||||
|
#include "agg_vcgen_vertex_sequence.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//=======================================================conv_shorten_path
|
||||||
|
template<class VertexSource> class conv_shorten_path :
|
||||||
|
public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> base_type;
|
||||||
|
|
||||||
|
conv_shorten_path(VertexSource& vs) :
|
||||||
|
conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>(vs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void shorten(double s) { base_type::generator().shorten(s); }
|
||||||
|
double shorten() const { return base_type::generator().shorten(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_shorten_path(const conv_shorten_path<VertexSource>&);
|
||||||
|
const conv_shorten_path<VertexSource>&
|
||||||
|
operator = (const conv_shorten_path<VertexSource>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Smooth polygon generator
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_CONV_SMOOTH_POLY1_INCLUDED
|
||||||
|
#define AGG_CONV_SMOOTH_POLY1_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_vcgen_smooth_poly1.h"
|
||||||
|
#include "agg_conv_adaptor_vcgen.h"
|
||||||
|
#include "agg_conv_curve.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//-------------------------------------------------------conv_smooth_poly1
|
||||||
|
template<class VertexSource>
|
||||||
|
struct conv_smooth_poly1 :
|
||||||
|
public conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>
|
||||||
|
{
|
||||||
|
typedef conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1> base_type;
|
||||||
|
|
||||||
|
conv_smooth_poly1(VertexSource& vs) :
|
||||||
|
conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>(vs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void smooth_value(double v) { base_type::generator().smooth_value(v); }
|
||||||
|
double smooth_value() const { return base_type::generator().smooth_value(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_smooth_poly1(const conv_smooth_poly1<VertexSource>&);
|
||||||
|
const conv_smooth_poly1<VertexSource>&
|
||||||
|
operator = (const conv_smooth_poly1<VertexSource>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------conv_smooth_poly1_curve
|
||||||
|
template<class VertexSource>
|
||||||
|
struct conv_smooth_poly1_curve :
|
||||||
|
public conv_curve<conv_smooth_poly1<VertexSource> >
|
||||||
|
{
|
||||||
|
conv_smooth_poly1_curve(VertexSource& vs) :
|
||||||
|
conv_curve<conv_smooth_poly1<VertexSource> >(m_smooth),
|
||||||
|
m_smooth(vs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void smooth_value(double v) { m_smooth.generator().smooth_value(v); }
|
||||||
|
double smooth_value() const { return m_smooth.generator().smooth_value(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_smooth_poly1_curve(const conv_smooth_poly1_curve<VertexSource>&);
|
||||||
|
const conv_smooth_poly1_curve<VertexSource>&
|
||||||
|
operator = (const conv_smooth_poly1_curve<VertexSource>&);
|
||||||
|
|
||||||
|
conv_smooth_poly1<VertexSource> m_smooth;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// conv_stroke
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_CONV_STROKE_INCLUDED
|
||||||
|
#define AGG_CONV_STROKE_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_vcgen_stroke.h"
|
||||||
|
#include "agg_conv_adaptor_vcgen.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//-------------------------------------------------------------conv_stroke
|
||||||
|
template<class VertexSource, class Markers=null_markers>
|
||||||
|
struct conv_stroke :
|
||||||
|
public conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>
|
||||||
|
{
|
||||||
|
typedef Markers marker_type;
|
||||||
|
typedef conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers> base_type;
|
||||||
|
|
||||||
|
conv_stroke(VertexSource& vs) :
|
||||||
|
conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void line_cap(vcgen_stroke::line_cap_e lc) { base_type::generator().line_cap(lc); }
|
||||||
|
void line_join(vcgen_stroke::line_join_e lj) { base_type::generator().line_join(lj); }
|
||||||
|
|
||||||
|
vcgen_stroke::line_cap_e line_cap() const { return base_type::generator().line_cap(); }
|
||||||
|
vcgen_stroke::line_join_e line_join() const { return base_type::generator().line_join(); }
|
||||||
|
|
||||||
|
void width(double w) { base_type::generator().width(w); }
|
||||||
|
void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
|
||||||
|
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
|
||||||
|
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
|
||||||
|
|
||||||
|
double width() const { return base_type::generator().width(); }
|
||||||
|
double miter_limit() const { return base_type::generator().miter_limit(); }
|
||||||
|
double approximation_scale() const { return base_type::generator().approximation_scale(); }
|
||||||
|
|
||||||
|
void shorten(double s) { base_type::generator().shorten(s); }
|
||||||
|
double shorten() const { return base_type::generator().shorten(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_stroke(const conv_stroke<VertexSource, Markers>&);
|
||||||
|
const conv_stroke<VertexSource, Markers>&
|
||||||
|
operator = (const conv_stroke<VertexSource, Markers>&);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// class conv_transform
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_CONV_TRANSFORM_INCLUDED
|
||||||
|
#define AGG_CONV_TRANSFORM_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_trans_affine.h"
|
||||||
|
#include "agg_vertex_iterator.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//----------------------------------------------------------conv_transform
|
||||||
|
template<class VertexSource, class Transformer=trans_affine> class conv_transform
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
conv_transform(VertexSource& source, const Transformer& tr) :
|
||||||
|
m_source(&source), m_trans(&tr) {}
|
||||||
|
|
||||||
|
void set_source(VertexSource& source) { m_source = &source; }
|
||||||
|
|
||||||
|
void rewind(unsigned id)
|
||||||
|
{
|
||||||
|
m_source->rewind(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
unsigned cmd = m_source->vertex(x, y);
|
||||||
|
if(is_vertex(cmd))
|
||||||
|
{
|
||||||
|
m_trans->transform(x, y);
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void transformer(const Transformer& tr)
|
||||||
|
{
|
||||||
|
m_trans = &tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef conv_transform<VertexSource, Transformer> source_type;
|
||||||
|
typedef vertex_iterator<source_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_transform(const conv_transform<VertexSource>&);
|
||||||
|
const conv_transform<VertexSource>&
|
||||||
|
operator = (const conv_transform<VertexSource>&);
|
||||||
|
|
||||||
|
VertexSource* m_source;
|
||||||
|
const Transformer* m_trans;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_CONV_UNCLOSE_POLYGON_INCLUDED
|
||||||
|
#define AGG_CONV_UNCLOSE_POLYGON_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_vertex_iterator.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//====================================================conv_unclose_polygon
|
||||||
|
template<class VertexSource> class conv_unclose_polygon
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {}
|
||||||
|
|
||||||
|
void set_source(VertexSource& source) { m_source = &source; }
|
||||||
|
|
||||||
|
void rewind(unsigned path_id)
|
||||||
|
{
|
||||||
|
m_source->rewind(path_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
unsigned cmd = m_source->vertex(x, y);
|
||||||
|
if(is_end_poly(cmd)) cmd &= ~path_flags_close;
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef conv_unclose_polygon<VertexSource> source_type;
|
||||||
|
typedef vertex_iterator<source_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&);
|
||||||
|
const conv_unclose_polygon<VertexSource>&
|
||||||
|
operator = (const conv_unclose_polygon<VertexSource>&);
|
||||||
|
|
||||||
|
VertexSource* m_source;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// classes curve3 and curve4
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_CURVES_INCLUDED
|
||||||
|
#define AGG_CURVES_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_vertex_iterator.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
// See Implemantation agg_curves.cpp
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------curve3
|
||||||
|
class curve3
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
curve3() :
|
||||||
|
m_num_steps(0), m_step(0), m_scale(1.0) { }
|
||||||
|
|
||||||
|
curve3(double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double x3, double y3) :
|
||||||
|
m_num_steps(0), m_step(0), m_scale(1.0)
|
||||||
|
{
|
||||||
|
init(x1, y1, x2, y2, x3, y3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() { m_num_steps = 0; m_step = -1; }
|
||||||
|
void init(double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double x3, double y3);
|
||||||
|
void approximation_scale(double s) { m_scale = s; }
|
||||||
|
double approximation_scale() const { return m_scale; }
|
||||||
|
|
||||||
|
void rewind(unsigned id);
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
typedef curve3 source_type;
|
||||||
|
typedef vertex_iterator<source_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_num_steps;
|
||||||
|
int m_step;
|
||||||
|
double m_scale;
|
||||||
|
double m_start_x;
|
||||||
|
double m_start_y;
|
||||||
|
double m_end_x;
|
||||||
|
double m_end_y;
|
||||||
|
double m_fx;
|
||||||
|
double m_fy;
|
||||||
|
double m_dfx;
|
||||||
|
double m_dfy;
|
||||||
|
double m_ddfx;
|
||||||
|
double m_ddfy;
|
||||||
|
double m_saved_fx;
|
||||||
|
double m_saved_fy;
|
||||||
|
double m_saved_dfx;
|
||||||
|
double m_saved_dfy;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------curve4
|
||||||
|
class curve4
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
curve4() :
|
||||||
|
m_num_steps(0), m_step(0), m_scale(1.0) { }
|
||||||
|
|
||||||
|
curve4(double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double x3, double y3,
|
||||||
|
double x4, double y4) :
|
||||||
|
m_num_steps(0), m_step(0), m_scale(1.0)
|
||||||
|
{
|
||||||
|
init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() { m_num_steps = 0; m_step = -1; }
|
||||||
|
void init(double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double x3, double y3,
|
||||||
|
double x4, double y4);
|
||||||
|
|
||||||
|
void approximation_scale(double s) { m_scale = s; }
|
||||||
|
double approximation_scale() const { return m_scale; }
|
||||||
|
|
||||||
|
void rewind(unsigned id);
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
typedef curve4 source_type;
|
||||||
|
typedef vertex_iterator<source_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_num_steps;
|
||||||
|
int m_step;
|
||||||
|
double m_scale;
|
||||||
|
double m_start_x;
|
||||||
|
double m_start_y;
|
||||||
|
double m_end_x;
|
||||||
|
double m_end_y;
|
||||||
|
double m_fx;
|
||||||
|
double m_fy;
|
||||||
|
double m_dfx;
|
||||||
|
double m_dfy;
|
||||||
|
double m_ddfx;
|
||||||
|
double m_ddfy;
|
||||||
|
double m_dddfx;
|
||||||
|
double m_dddfy;
|
||||||
|
double m_saved_fx;
|
||||||
|
double m_saved_fy;
|
||||||
|
double m_saved_dfx;
|
||||||
|
double m_saved_dfy;
|
||||||
|
double m_saved_ddfx;
|
||||||
|
double m_saved_ddfy;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,290 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// classes dda_line_interpolator, dda2_line_interpolator
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_DDA_LINE_INCLUDED
|
||||||
|
#define AGG_DDA_LINE_INCLUDED
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//===================================================dda_line_interpolator
|
||||||
|
template<int FractionShift, int YShift=0> class dda_line_interpolator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
dda_line_interpolator() {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
dda_line_interpolator(int y1, int y2, unsigned count) :
|
||||||
|
m_y(y1),
|
||||||
|
m_inc(((y2 - y1) << FractionShift) / int(count)),
|
||||||
|
m_dy(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void operator ++ ()
|
||||||
|
{
|
||||||
|
m_dy += m_inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void operator -- ()
|
||||||
|
{
|
||||||
|
m_dy -= m_inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void operator += (unsigned n)
|
||||||
|
{
|
||||||
|
m_dy += m_inc * n;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void operator -= (unsigned n)
|
||||||
|
{
|
||||||
|
m_dy -= m_inc * n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
int y() const { return m_y + (m_dy >> (FractionShift-YShift)); }
|
||||||
|
int dy() const { return m_dy; }
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_y;
|
||||||
|
int m_inc;
|
||||||
|
int m_dy;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=================================================dda2_line_interpolator
|
||||||
|
class dda2_line_interpolator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef int save_data_type;
|
||||||
|
enum { save_size = 2 };
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
dda2_line_interpolator() {}
|
||||||
|
|
||||||
|
//-------------------------------------------- Forward-adjusted line
|
||||||
|
dda2_line_interpolator(int y1, int y2, int count) :
|
||||||
|
m_cnt(count <= 0 ? 1 : count),
|
||||||
|
m_lft((y2 - y1) / m_cnt),
|
||||||
|
m_rem((y2 - y1) % m_cnt),
|
||||||
|
m_mod(m_rem),
|
||||||
|
m_y(y1)
|
||||||
|
{
|
||||||
|
if(m_mod <= 0)
|
||||||
|
{
|
||||||
|
m_mod += count;
|
||||||
|
m_rem += count;
|
||||||
|
m_lft--;
|
||||||
|
}
|
||||||
|
m_mod -= count;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------- Backward-adjusted line
|
||||||
|
dda2_line_interpolator(int y1, int y2, int count, int) :
|
||||||
|
m_cnt(count <= 0 ? 1 : count),
|
||||||
|
m_lft((y2 - y1) / m_cnt),
|
||||||
|
m_rem((y2 - y1) % m_cnt),
|
||||||
|
m_mod(m_rem),
|
||||||
|
m_y(y1)
|
||||||
|
{
|
||||||
|
if(m_mod <= 0)
|
||||||
|
{
|
||||||
|
m_mod += count;
|
||||||
|
m_rem += count;
|
||||||
|
m_lft--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------- Backward-adjusted line
|
||||||
|
dda2_line_interpolator(int y, int count) :
|
||||||
|
m_cnt(count <= 0 ? 1 : count),
|
||||||
|
m_lft(y / m_cnt),
|
||||||
|
m_rem(y % m_cnt),
|
||||||
|
m_mod(m_rem),
|
||||||
|
m_y(0)
|
||||||
|
{
|
||||||
|
if(m_mod <= 0)
|
||||||
|
{
|
||||||
|
m_mod += count;
|
||||||
|
m_rem += count;
|
||||||
|
m_lft--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void save(save_data_type* data) const
|
||||||
|
{
|
||||||
|
data[0] = m_mod;
|
||||||
|
data[1] = m_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void load(const save_data_type* data)
|
||||||
|
{
|
||||||
|
m_mod = data[0];
|
||||||
|
m_y = data[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void operator++()
|
||||||
|
{
|
||||||
|
m_mod += m_rem;
|
||||||
|
m_y += m_lft;
|
||||||
|
if(m_mod > 0)
|
||||||
|
{
|
||||||
|
m_mod -= m_cnt;
|
||||||
|
m_y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void operator--()
|
||||||
|
{
|
||||||
|
if(m_mod <= m_rem)
|
||||||
|
{
|
||||||
|
m_mod += m_cnt;
|
||||||
|
m_y--;
|
||||||
|
}
|
||||||
|
m_mod -= m_rem;
|
||||||
|
m_y -= m_lft;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void adjust_forward()
|
||||||
|
{
|
||||||
|
m_mod -= m_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void adjust_backward()
|
||||||
|
{
|
||||||
|
m_mod += m_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
int mod() const { return m_mod; }
|
||||||
|
int rem() const { return m_rem; }
|
||||||
|
int lft() const { return m_lft; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
int y() const { return m_y; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_cnt;
|
||||||
|
int m_lft;
|
||||||
|
int m_rem;
|
||||||
|
int m_mod;
|
||||||
|
int m_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------line_bresenham_interpolator
|
||||||
|
class line_bresenham_interpolator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
subpixel_shift = 8,
|
||||||
|
subpixel_size = 1 << subpixel_shift,
|
||||||
|
subpixel_mask = subpixel_size - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static int line_lr(int v) { return v >> subpixel_shift; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
line_bresenham_interpolator(int x1, int y1, int x2, int y2) :
|
||||||
|
m_x1_lr(line_lr(x1)),
|
||||||
|
m_y1_lr(line_lr(y1)),
|
||||||
|
m_x2_lr(line_lr(x2)),
|
||||||
|
m_y2_lr(line_lr(y2)),
|
||||||
|
m_ver(abs(m_x2_lr - m_x1_lr) < abs(m_y2_lr - m_y1_lr)),
|
||||||
|
m_len(m_ver ? abs(m_y2_lr - m_y1_lr) :
|
||||||
|
abs(m_x2_lr - m_x1_lr)),
|
||||||
|
m_inc(m_ver ? ((y2 > y1) ? 1 : -1) : ((x2 > x1) ? 1 : -1)),
|
||||||
|
m_interpolator(m_ver ? x1 : y1,
|
||||||
|
m_ver ? x2 : y2,
|
||||||
|
m_len)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
bool is_ver() const { return m_ver; }
|
||||||
|
unsigned len() const { return m_len; }
|
||||||
|
int inc() const { return m_inc; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void hstep()
|
||||||
|
{
|
||||||
|
++m_interpolator;
|
||||||
|
m_x1_lr += m_inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void vstep()
|
||||||
|
{
|
||||||
|
++m_interpolator;
|
||||||
|
m_y1_lr += m_inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
int x1() const { return m_x1_lr; }
|
||||||
|
int y1() const { return m_y1_lr; }
|
||||||
|
int x2() const { return line_lr(m_interpolator.y()); }
|
||||||
|
int y2() const { return line_lr(m_interpolator.y()); }
|
||||||
|
int x2_hr() const { return m_interpolator.y(); }
|
||||||
|
int y2_hr() const { return m_interpolator.y(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_x1_lr;
|
||||||
|
int m_y1_lr;
|
||||||
|
int m_x2_lr;
|
||||||
|
int m_y2_lr;
|
||||||
|
bool m_ver;
|
||||||
|
unsigned m_len;
|
||||||
|
int m_inc;
|
||||||
|
dda2_line_interpolator m_interpolator;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// class ellipse
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_ELLIPSE_INCLUDED
|
||||||
|
#define AGG_ELLIPSE_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//----------------------------------------------------------------ellipse
|
||||||
|
class ellipse
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ellipse() : m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_num(4), m_step(0) {}
|
||||||
|
ellipse(double x, double y, double rx, double ry, unsigned num_steps)
|
||||||
|
: m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_num(num_steps), m_step(0) {}
|
||||||
|
|
||||||
|
void init(double x, double y, double rx, double ry, unsigned num_steps);
|
||||||
|
void approximation_scale(double scale);
|
||||||
|
void rewind(unsigned id);
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_x;
|
||||||
|
double m_y;
|
||||||
|
double m_rx;
|
||||||
|
double m_ry;
|
||||||
|
unsigned m_num;
|
||||||
|
unsigned m_step;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void ellipse::init(double x, double y, double rx, double ry, unsigned num_steps)
|
||||||
|
{
|
||||||
|
m_x = x;
|
||||||
|
m_y = y;
|
||||||
|
m_rx = rx;
|
||||||
|
m_ry = ry;
|
||||||
|
m_num = num_steps;
|
||||||
|
m_step = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void ellipse::approximation_scale(double scale)
|
||||||
|
{
|
||||||
|
m_num = unsigned((fabs(m_rx) + fabs(m_ry) + 6.0) * scale);
|
||||||
|
if(m_num < 6) m_num = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void ellipse::rewind(unsigned)
|
||||||
|
{
|
||||||
|
m_step = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline unsigned ellipse::vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
if(m_step == m_num)
|
||||||
|
{
|
||||||
|
++m_step;
|
||||||
|
return path_cmd_end_poly | path_flags_close | path_flags_ccw;
|
||||||
|
}
|
||||||
|
if(m_step > m_num) return path_cmd_stop;
|
||||||
|
double angle = double(m_step) / double(m_num) * 2.0 * pi;
|
||||||
|
*x = m_x + cos(angle) * m_rx;
|
||||||
|
*y = m_y + sin(angle) * m_ry;
|
||||||
|
m_step++;
|
||||||
|
return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Simple Bresenham interpolator for ellipsees
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_ELLIPSE_BRESENHAM_INCLUDED
|
||||||
|
#define AGG_ELLIPSE_BRESENHAM_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//------------------------------------------ellipse_bresenham_interpolator
|
||||||
|
class ellipse_bresenham_interpolator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ellipse_bresenham_interpolator(int rx, int ry) :
|
||||||
|
m_rx2(rx * rx),
|
||||||
|
m_ry2(ry * ry),
|
||||||
|
m_two_rx2(m_rx2 << 1),
|
||||||
|
m_two_ry2(m_ry2 << 1),
|
||||||
|
m_dx(0),
|
||||||
|
m_dy(0),
|
||||||
|
m_inc_x(0),
|
||||||
|
m_inc_y(-ry * m_two_rx2),
|
||||||
|
m_cur_f(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int dx() const { return m_dx; }
|
||||||
|
int dy() const { return m_dy; }
|
||||||
|
|
||||||
|
void operator++ ()
|
||||||
|
{
|
||||||
|
int mx, my, mxy, min_m;
|
||||||
|
int fx, fy, fxy;
|
||||||
|
|
||||||
|
mx = fx = m_cur_f + m_inc_x + m_ry2;
|
||||||
|
if(mx < 0) mx = -mx;
|
||||||
|
|
||||||
|
my = fy = m_cur_f + m_inc_y + m_rx2;
|
||||||
|
if(my < 0) my = -my;
|
||||||
|
|
||||||
|
mxy = fxy = m_cur_f + m_inc_x + m_ry2 + m_inc_y + m_rx2;
|
||||||
|
if(mxy < 0) mxy = -mxy;
|
||||||
|
|
||||||
|
min_m = mx;
|
||||||
|
bool flag = true;
|
||||||
|
|
||||||
|
if(min_m > my)
|
||||||
|
{
|
||||||
|
min_m = my;
|
||||||
|
flag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dx = m_dy = 0;
|
||||||
|
|
||||||
|
if(min_m > mxy)
|
||||||
|
{
|
||||||
|
m_inc_x += m_two_ry2;
|
||||||
|
m_inc_y += m_two_rx2;
|
||||||
|
m_cur_f = fxy;
|
||||||
|
m_dx = 1;
|
||||||
|
m_dy = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(flag)
|
||||||
|
{
|
||||||
|
m_inc_x += m_two_ry2;
|
||||||
|
m_cur_f = fx;
|
||||||
|
m_dx = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_inc_y += m_two_rx2;
|
||||||
|
m_cur_f = fy;
|
||||||
|
m_dy = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_rx2;
|
||||||
|
int m_ry2;
|
||||||
|
int m_two_rx2;
|
||||||
|
int m_two_ry2;
|
||||||
|
int m_dx;
|
||||||
|
int m_dy;
|
||||||
|
int m_inc_x;
|
||||||
|
int m_inc_y;
|
||||||
|
int m_cur_f;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_EMBEDDED_RASTER_FONTS_INCLUDED
|
||||||
|
#define AGG_EMBEDDED_RASTER_FONTS_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
extern const int8u gse4x6[];
|
||||||
|
extern const int8u gse4x8[];
|
||||||
|
extern const int8u gse5x7[];
|
||||||
|
extern const int8u gse5x9[];
|
||||||
|
extern const int8u gse6x12[];
|
||||||
|
extern const int8u gse6x9[];
|
||||||
|
extern const int8u gse7x11[];
|
||||||
|
extern const int8u gse7x11_bold[];
|
||||||
|
extern const int8u gse7x15[];
|
||||||
|
extern const int8u gse7x15_bold[];
|
||||||
|
extern const int8u gse8x16[];
|
||||||
|
extern const int8u gse8x16_bold[];
|
||||||
|
extern const int8u mcs11_prop[];
|
||||||
|
extern const int8u mcs11_prop_condensed[];
|
||||||
|
extern const int8u mcs12_prop[];
|
||||||
|
extern const int8u mcs13_prop[];
|
||||||
|
extern const int8u mcs5x10_mono[];
|
||||||
|
extern const int8u mcs5x11_mono[];
|
||||||
|
extern const int8u mcs6x10_mono[];
|
||||||
|
extern const int8u mcs6x11_mono[];
|
||||||
|
extern const int8u mcs7x12_mono_high[];
|
||||||
|
extern const int8u mcs7x12_mono_low[];
|
||||||
|
extern const int8u verdana12[];
|
||||||
|
extern const int8u verdana12_bold[];
|
||||||
|
extern const int8u verdana13[];
|
||||||
|
extern const int8u verdana13_bold[];
|
||||||
|
extern const int8u verdana14[];
|
||||||
|
extern const int8u verdana14_bold[];
|
||||||
|
extern const int8u verdana16[];
|
||||||
|
extern const int8u verdana16_bold[];
|
||||||
|
extern const int8u verdana17[];
|
||||||
|
extern const int8u verdana17_bold[];
|
||||||
|
extern const int8u verdana18[];
|
||||||
|
extern const int8u verdana18_bold[];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+394
@@ -0,0 +1,394 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_FONT_CACHE_MANAGER_INCLUDED
|
||||||
|
#define AGG_FONT_CACHE_MANAGER_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_array.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//---------------------------------------------------------glyph_data_type
|
||||||
|
enum glyph_data_type
|
||||||
|
{
|
||||||
|
glyph_data_invalid = 0,
|
||||||
|
glyph_data_mono = 1,
|
||||||
|
glyph_data_gray8 = 2,
|
||||||
|
glyph_data_outline = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------glyph_cache
|
||||||
|
struct glyph_cache
|
||||||
|
{
|
||||||
|
unsigned glyph_index;
|
||||||
|
int8u* data;
|
||||||
|
unsigned data_size;
|
||||||
|
glyph_data_type data_type;
|
||||||
|
rect bounds;
|
||||||
|
double advance_x;
|
||||||
|
double advance_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------font_cache
|
||||||
|
class font_cache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum { block_size = 16384-16 };
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
font_cache(const char* font_signature) :
|
||||||
|
m_allocator(block_size),
|
||||||
|
m_font_signature(0)
|
||||||
|
{
|
||||||
|
m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1);
|
||||||
|
strcpy(m_font_signature, font_signature);
|
||||||
|
memset(m_glyphs, 0, sizeof(m_glyphs));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
bool font_is(const char* font_signature) const
|
||||||
|
{
|
||||||
|
return strcmp(font_signature, m_font_signature) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const glyph_cache* find_glyph(unsigned glyph_code) const
|
||||||
|
{
|
||||||
|
unsigned msb = (glyph_code >> 8) & 0xFF;
|
||||||
|
if(m_glyphs[msb])
|
||||||
|
{
|
||||||
|
return m_glyphs[msb][glyph_code & 0xFF];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
glyph_cache* cache_glyph(unsigned glyph_code,
|
||||||
|
unsigned glyph_index,
|
||||||
|
unsigned data_size,
|
||||||
|
glyph_data_type data_type,
|
||||||
|
const rect& bounds,
|
||||||
|
double advance_x,
|
||||||
|
double advance_y)
|
||||||
|
{
|
||||||
|
unsigned msb = (glyph_code >> 8) & 0xFF;
|
||||||
|
if(m_glyphs[msb] == 0)
|
||||||
|
{
|
||||||
|
m_glyphs[msb] =
|
||||||
|
(glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256,
|
||||||
|
sizeof(glyph_cache*));
|
||||||
|
memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned lsb = glyph_code & 0xFF;
|
||||||
|
if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite
|
||||||
|
|
||||||
|
glyph_cache* glyph =
|
||||||
|
(glyph_cache*)m_allocator.allocate(sizeof(glyph_cache),
|
||||||
|
sizeof(int8u*));
|
||||||
|
|
||||||
|
glyph->glyph_index = glyph_index;
|
||||||
|
glyph->data = m_allocator.allocate(data_size);
|
||||||
|
glyph->data_size = data_size;
|
||||||
|
glyph->data_type = data_type;
|
||||||
|
glyph->bounds = bounds;
|
||||||
|
glyph->advance_x = advance_x;
|
||||||
|
glyph->advance_y = advance_y;
|
||||||
|
return m_glyphs[msb][lsb] = glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
pod_allocator m_allocator;
|
||||||
|
glyph_cache** m_glyphs[256];
|
||||||
|
char* m_font_signature;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------font_cache_pool
|
||||||
|
class font_cache_pool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
~font_cache_pool()
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < m_num_fonts; ++i)
|
||||||
|
{
|
||||||
|
delete m_fonts[i];
|
||||||
|
}
|
||||||
|
delete [] m_fonts;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
font_cache_pool(unsigned max_fonts=32) :
|
||||||
|
m_fonts(new font_cache* [max_fonts]),
|
||||||
|
m_max_fonts(max_fonts),
|
||||||
|
m_num_fonts(0),
|
||||||
|
m_cur_font(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void font(const char* font_signature, bool reset_cache = false)
|
||||||
|
{
|
||||||
|
int idx = find_font(font_signature);
|
||||||
|
if(idx >= 0)
|
||||||
|
{
|
||||||
|
if(reset_cache)
|
||||||
|
{
|
||||||
|
delete m_fonts[idx];
|
||||||
|
m_fonts[idx] = new font_cache(font_signature);
|
||||||
|
}
|
||||||
|
m_cur_font = m_fonts[idx];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(m_num_fonts >= m_max_fonts)
|
||||||
|
{
|
||||||
|
delete m_fonts[0];
|
||||||
|
memcpy(m_fonts,
|
||||||
|
m_fonts + 1,
|
||||||
|
(m_max_fonts - 1) * sizeof(font_cache*));
|
||||||
|
m_num_fonts = m_max_fonts - 1;
|
||||||
|
}
|
||||||
|
m_fonts[m_num_fonts] = new font_cache(font_signature);
|
||||||
|
m_cur_font = m_fonts[m_num_fonts];
|
||||||
|
++m_num_fonts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const font_cache* font() const
|
||||||
|
{
|
||||||
|
return m_cur_font;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const glyph_cache* find_glyph(unsigned glyph_code) const
|
||||||
|
{
|
||||||
|
if(m_cur_font) return m_cur_font->find_glyph(glyph_code);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
glyph_cache* cache_glyph(unsigned glyph_code,
|
||||||
|
unsigned glyph_index,
|
||||||
|
unsigned data_size,
|
||||||
|
glyph_data_type data_type,
|
||||||
|
const rect& bounds,
|
||||||
|
double advance_x,
|
||||||
|
double advance_y)
|
||||||
|
{
|
||||||
|
if(m_cur_font)
|
||||||
|
{
|
||||||
|
return m_cur_font->cache_glyph(glyph_code,
|
||||||
|
glyph_index,
|
||||||
|
data_size,
|
||||||
|
data_type,
|
||||||
|
bounds,
|
||||||
|
advance_x,
|
||||||
|
advance_y);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
int find_font(const char* font_signature)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < m_num_fonts; i++)
|
||||||
|
{
|
||||||
|
if(m_fonts[i]->font_is(font_signature)) return int(i);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
font_cache** m_fonts;
|
||||||
|
unsigned m_max_fonts;
|
||||||
|
unsigned m_num_fonts;
|
||||||
|
font_cache* m_cur_font;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
enum glyph_rendering
|
||||||
|
{
|
||||||
|
glyph_ren_native_mono,
|
||||||
|
glyph_ren_native_gray8,
|
||||||
|
glyph_ren_outline,
|
||||||
|
glyph_ren_agg_mono,
|
||||||
|
glyph_ren_agg_gray8
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------font_cache_manager
|
||||||
|
template<class FontEngine> class font_cache_manager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef FontEngine font_engine_type;
|
||||||
|
typedef font_cache_manager<FontEngine> self_type;
|
||||||
|
typedef typename font_engine_type::path_adaptor_type path_adaptor_type;
|
||||||
|
typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type;
|
||||||
|
typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type;
|
||||||
|
typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type;
|
||||||
|
typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) :
|
||||||
|
m_fonts(max_fonts),
|
||||||
|
m_engine(engine),
|
||||||
|
m_change_stamp(-1),
|
||||||
|
m_prev_glyph(0),
|
||||||
|
m_last_glyph(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const glyph_cache* glyph(unsigned glyph_code)
|
||||||
|
{
|
||||||
|
synchronize();
|
||||||
|
const glyph_cache* gl = m_fonts.find_glyph(glyph_code);
|
||||||
|
if(gl)
|
||||||
|
{
|
||||||
|
m_prev_glyph = m_last_glyph;
|
||||||
|
return m_last_glyph = gl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(m_engine.prepare_glyph(glyph_code))
|
||||||
|
{
|
||||||
|
m_prev_glyph = m_last_glyph;
|
||||||
|
m_last_glyph = m_fonts.cache_glyph(glyph_code,
|
||||||
|
m_engine.glyph_index(),
|
||||||
|
m_engine.data_size(),
|
||||||
|
m_engine.data_type(),
|
||||||
|
m_engine.bounds(),
|
||||||
|
m_engine.advance_x(),
|
||||||
|
m_engine.advance_y());
|
||||||
|
m_engine.write_glyph_to(m_last_glyph->data);
|
||||||
|
return m_last_glyph;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void init_embedded_adaptors(const glyph_cache* gl, double x, double y)
|
||||||
|
{
|
||||||
|
if(gl)
|
||||||
|
{
|
||||||
|
switch(gl->data_type)
|
||||||
|
{
|
||||||
|
case glyph_data_mono:
|
||||||
|
m_mono_adaptor.init(gl->data, gl->data_size, x, y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case glyph_data_gray8:
|
||||||
|
m_gray8_adaptor.init(gl->data, gl->data_size, x, y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case glyph_data_outline:
|
||||||
|
m_path_adaptor.init(gl->data, gl->data_size, x, y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
path_adaptor_type& path_adaptor() { return m_path_adaptor; }
|
||||||
|
gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; }
|
||||||
|
gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; }
|
||||||
|
mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; }
|
||||||
|
mono_scanline_type& mono_scanline() { return m_mono_scanline; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const glyph_cache* perv_glyph() const { return m_prev_glyph; }
|
||||||
|
const glyph_cache* last_glyph() const { return m_last_glyph; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
bool add_kerning(double* x, double* y)
|
||||||
|
{
|
||||||
|
if(m_prev_glyph && m_last_glyph)
|
||||||
|
{
|
||||||
|
return m_engine.add_kerning(m_prev_glyph->glyph_index,
|
||||||
|
m_last_glyph->glyph_index,
|
||||||
|
x, y);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void precache(unsigned from, unsigned to)
|
||||||
|
{
|
||||||
|
for(; from <= to; ++from) glyph(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void reset_cache()
|
||||||
|
{
|
||||||
|
m_fonts.font(m_engine.font_signature(), true);
|
||||||
|
m_change_stamp = m_engine.change_stamp();
|
||||||
|
m_prev_glyph = m_last_glyph = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
font_cache_manager(const self_type&);
|
||||||
|
const self_type& operator = (const self_type&);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void synchronize()
|
||||||
|
{
|
||||||
|
if(m_change_stamp != m_engine.change_stamp())
|
||||||
|
{
|
||||||
|
m_fonts.font(m_engine.font_signature());
|
||||||
|
m_change_stamp = m_engine.change_stamp();
|
||||||
|
m_prev_glyph = m_last_glyph = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
font_cache_pool m_fonts;
|
||||||
|
font_engine_type& m_engine;
|
||||||
|
int m_change_stamp;
|
||||||
|
double m_dx;
|
||||||
|
double m_dy;
|
||||||
|
const glyph_cache* m_prev_glyph;
|
||||||
|
const glyph_cache* m_last_glyph;
|
||||||
|
path_adaptor_type m_path_adaptor;
|
||||||
|
gray8_adaptor_type m_gray8_adaptor;
|
||||||
|
gray8_scanline_type m_gray8_scanline;
|
||||||
|
mono_adaptor_type m_mono_adaptor;
|
||||||
|
mono_scanline_type m_mono_scanline;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_GAMMA_FUNCTIONS_INCLUDED
|
||||||
|
#define AGG_GAMMA_FUNCTIONS_INCLUDED
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//===============================================================gamma_none
|
||||||
|
struct gamma_none
|
||||||
|
{
|
||||||
|
double operator()(double x) const { return x; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//==============================================================gamma_power
|
||||||
|
class gamma_power
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
gamma_power() : m_gamma(1.0) {}
|
||||||
|
gamma_power(double g) : m_gamma(g) {}
|
||||||
|
|
||||||
|
void gamma(double g) { m_gamma = g; }
|
||||||
|
double gamma() const { return m_gamma; }
|
||||||
|
|
||||||
|
double operator() (double x) const
|
||||||
|
{
|
||||||
|
return pow(x, m_gamma);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_gamma;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================gamma_threshold
|
||||||
|
class gamma_threshold
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
gamma_threshold() : m_threshold(0.5) {}
|
||||||
|
gamma_threshold(double t) : m_threshold(t) {}
|
||||||
|
|
||||||
|
void threshold(double t) { m_threshold = t; }
|
||||||
|
double threshold() const { return m_threshold; }
|
||||||
|
|
||||||
|
double operator() (double x) const
|
||||||
|
{
|
||||||
|
return (x < m_threshold) ? 0.0 : 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_threshold;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================gamma_linear
|
||||||
|
class gamma_linear
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
gamma_linear() : m_start(0.0), m_end(1.0) {}
|
||||||
|
gamma_linear(double s, double e) : m_start(s), m_end(e) {}
|
||||||
|
|
||||||
|
void set(double s, double e) { m_start = s; m_end = e; }
|
||||||
|
void start(double s) { m_start = s; }
|
||||||
|
void end(double e) { m_end = e; }
|
||||||
|
double start() const { return m_start; }
|
||||||
|
double end() const { return m_end; }
|
||||||
|
|
||||||
|
double operator() (double x) const
|
||||||
|
{
|
||||||
|
if(x < m_start) return 0.0;
|
||||||
|
if(x > m_end) return 1.0;
|
||||||
|
return (x - m_start) / (m_end - m_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_start;
|
||||||
|
double m_end;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================gamma_multiply
|
||||||
|
class gamma_multiply
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
gamma_multiply() : m_mul(1.0) {}
|
||||||
|
gamma_multiply(double v) : m_mul(v) {}
|
||||||
|
|
||||||
|
void value(double v) { m_mul = v; }
|
||||||
|
double value() const { return m_mul; }
|
||||||
|
|
||||||
|
double operator() (double x) const
|
||||||
|
{
|
||||||
|
double y = x * m_mul;
|
||||||
|
if(y > 1.0) y = 1.0;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_mul;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_GAMMA_LUT_INCLUDED
|
||||||
|
#define AGG_GAMMA_LUT_INCLUDED
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
template<class LoResT=int8u,
|
||||||
|
class HiResT=int8u,
|
||||||
|
unsigned GammaShift=8,
|
||||||
|
unsigned HiResShift=8> class gamma_lut
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
gamma_shift = GammaShift,
|
||||||
|
gamma_size = 1 << gamma_shift,
|
||||||
|
gamma_mask = gamma_size - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
hi_res_shift = HiResShift,
|
||||||
|
hi_res_size = 1 << hi_res_shift,
|
||||||
|
hi_res_mask = hi_res_size - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
~gamma_lut()
|
||||||
|
{
|
||||||
|
delete [] m_inv_gamma;
|
||||||
|
delete [] m_dir_gamma;
|
||||||
|
}
|
||||||
|
|
||||||
|
gamma_lut() :
|
||||||
|
m_gamma(1.0),
|
||||||
|
m_dir_gamma(new HiResT[gamma_size]),
|
||||||
|
m_inv_gamma(new LoResT[hi_res_size])
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < gamma_size; i++)
|
||||||
|
{
|
||||||
|
m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < hi_res_size; i++)
|
||||||
|
{
|
||||||
|
m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gamma_lut(double g) :
|
||||||
|
m_gamma(1.0),
|
||||||
|
m_dir_gamma(new HiResT[gamma_size]),
|
||||||
|
m_inv_gamma(new LoResT[hi_res_size])
|
||||||
|
{
|
||||||
|
gamma(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gamma(double g)
|
||||||
|
{
|
||||||
|
m_gamma = g;
|
||||||
|
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < gamma_size; i++)
|
||||||
|
{
|
||||||
|
m_dir_gamma[i] = (HiResT)(pow(double(i) / double(gamma_mask), m_gamma) * double(hi_res_mask) + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
double inv_g = 1.0 / g;
|
||||||
|
for(i = 0; i < hi_res_size; i++)
|
||||||
|
{
|
||||||
|
m_inv_gamma[i] = (LoResT)(pow(double(i) / double(hi_res_mask), inv_g) * double(gamma_mask) + 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double gamma() const
|
||||||
|
{
|
||||||
|
return m_gamma;
|
||||||
|
}
|
||||||
|
|
||||||
|
HiResT dir(LoResT v) const
|
||||||
|
{
|
||||||
|
return m_dir_gamma[unsigned(v)];
|
||||||
|
}
|
||||||
|
|
||||||
|
LoResT inv(HiResT v) const
|
||||||
|
{
|
||||||
|
return m_inv_gamma[unsigned(v)];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_gamma;
|
||||||
|
HiResT* m_dir_gamma;
|
||||||
|
LoResT* m_inv_gamma;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_GLYPH_RASTER_BIN_INCLUDED
|
||||||
|
#define AGG_GLYPH_RASTER_BIN_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//========================================================glyph_raster_bin
|
||||||
|
template<class ColorT> class glyph_raster_bin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef ColorT color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
struct glyph_rect
|
||||||
|
{
|
||||||
|
int x1,y1,x2,y2;
|
||||||
|
double dx, dy;
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
glyph_raster_bin(const int8u* font) :
|
||||||
|
m_font(font),
|
||||||
|
m_big_endian(false)
|
||||||
|
{
|
||||||
|
int t = 1;
|
||||||
|
if(*(char*)&t == 0) m_big_endian = true;
|
||||||
|
memset(m_span, 0, sizeof(m_span));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const int8u* font() const { return m_font; }
|
||||||
|
void font(const int8u* f) { m_font = f; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
double height() const { return m_font[0]; }
|
||||||
|
double base_line() const { return m_font[1]; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class CharT>
|
||||||
|
double width(const CharT* str) const
|
||||||
|
{
|
||||||
|
unsigned start_char = m_font[2];
|
||||||
|
unsigned num_chars = m_font[3];
|
||||||
|
|
||||||
|
unsigned w = 0;
|
||||||
|
while(*str)
|
||||||
|
{
|
||||||
|
unsigned glyph = *str;
|
||||||
|
const int8u* bits = m_font + 4 + num_chars * 2 +
|
||||||
|
value(m_font + 4 + (glyph - start_char) * 2);
|
||||||
|
w += *bits;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void prepare(glyph_rect* r, double x, double y, unsigned glyph, bool flip)
|
||||||
|
{
|
||||||
|
unsigned start_char = m_font[2];
|
||||||
|
unsigned num_chars = m_font[3];
|
||||||
|
|
||||||
|
m_bits = m_font + 4 + num_chars * 2 +
|
||||||
|
value(m_font + 4 + (glyph - start_char) * 2);
|
||||||
|
|
||||||
|
m_glyph_width = *m_bits++;
|
||||||
|
m_glyph_byte_width = (m_glyph_width + 7) >> 3;
|
||||||
|
|
||||||
|
r->x1 = int(x);
|
||||||
|
r->x2 = r->x1 + m_glyph_width - 1;
|
||||||
|
if(flip)
|
||||||
|
{
|
||||||
|
r->y1 = int(y) - m_font[0] + m_font[1];
|
||||||
|
r->y2 = r->y1 + m_font[0] - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r->y1 = int(y) - m_font[1] + 1;
|
||||||
|
r->y2 = r->y1 + m_font[0] - 1;
|
||||||
|
}
|
||||||
|
r->dx = m_glyph_width;
|
||||||
|
r->dy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const cover_type* span(unsigned i)
|
||||||
|
{
|
||||||
|
i = m_font[0] - i - 1;
|
||||||
|
const int8u* bits = m_bits + i * m_glyph_byte_width;
|
||||||
|
unsigned j;
|
||||||
|
unsigned val = *bits;
|
||||||
|
unsigned nb = 0;
|
||||||
|
for(j = 0; j < m_glyph_width; ++j)
|
||||||
|
{
|
||||||
|
m_span[j] = (cover_type)((val & 0x80) ? cover_full : cover_none);
|
||||||
|
val <<= 1;
|
||||||
|
if(++nb >= 8)
|
||||||
|
{
|
||||||
|
val = *++bits;
|
||||||
|
nb = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_span;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
int16u value(const int8u* p) const
|
||||||
|
{
|
||||||
|
int16u v;
|
||||||
|
if(m_big_endian)
|
||||||
|
{
|
||||||
|
*(int8u*)&v = p[1];
|
||||||
|
*((int8u*)&v + 1) = p[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*(int8u*)&v = p[0];
|
||||||
|
*((int8u*)&v + 1) = p[1];
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const int8u* m_font;
|
||||||
|
bool m_big_endian;
|
||||||
|
cover_type m_span[32];
|
||||||
|
const int8u* m_bits;
|
||||||
|
unsigned m_glyph_width;
|
||||||
|
unsigned m_glyph_byte_width;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+107
@@ -0,0 +1,107 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// color type gray8
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_GRAY8_INCLUDED
|
||||||
|
#define AGG_GRAY8_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//===================================================================gray8
|
||||||
|
struct gray8
|
||||||
|
{
|
||||||
|
int8u v;
|
||||||
|
int8u a;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
gray8() {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
gray8(unsigned v_, unsigned a_=255) :
|
||||||
|
v(int8u(v_)), a(int8u(a_)) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
gray8(const rgba& c) :
|
||||||
|
v(int8u((0.299*c.r + 0.587*c.g + 0.114*c.b) * 255.0 + 0.5)),
|
||||||
|
a(int8u(c.a*255.0)) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
gray8(const rgba8& c) :
|
||||||
|
v((c.r*77 + c.g*150 + c.b*29) >> 8),
|
||||||
|
a(c.a) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
v = a = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const gray8& transparent()
|
||||||
|
{
|
||||||
|
a = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void opacity(double a_)
|
||||||
|
{
|
||||||
|
if(a_ < 0.0) a_ = 0.0;
|
||||||
|
if(a_ > 1.0) a_ = 1.0;
|
||||||
|
a = int8u(a_ * 255.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
double opacity() const
|
||||||
|
{
|
||||||
|
return double(a) / 255.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
gray8 gradient(gray8 c, double k) const
|
||||||
|
{
|
||||||
|
gray8 ret;
|
||||||
|
int ik = int(k * 256);
|
||||||
|
ret.v = int8u(int(v) + (((int(c.v) - int(v)) * ik) >> 8));
|
||||||
|
ret.a = int8u(int(a) + (((int(c.a) - int(a)) * ik) >> 8));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
gray8 pre() const
|
||||||
|
{
|
||||||
|
return gray8((v*a) >> 8, a);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static gray8 no_color() { return gray8(0,0); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Class gsv_text
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_GSV_TEXT_INCLUDED
|
||||||
|
#define AGG_GSV_TEXT_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_conv_stroke.h"
|
||||||
|
#include "agg_conv_transform.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------gsv_text
|
||||||
|
//
|
||||||
|
// See Implementation agg_gsv_text.cpp
|
||||||
|
//
|
||||||
|
class gsv_text
|
||||||
|
{
|
||||||
|
enum status
|
||||||
|
{
|
||||||
|
initial,
|
||||||
|
next_char,
|
||||||
|
start_glyph,
|
||||||
|
glyph
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
~gsv_text();
|
||||||
|
gsv_text();
|
||||||
|
|
||||||
|
void font(const void* font);
|
||||||
|
void flip(bool flip_y) { m_flip = flip_y; }
|
||||||
|
void load_font(const char* file);
|
||||||
|
void size(double height, double width=0.0);
|
||||||
|
void space(double space);
|
||||||
|
void line_space(double line_space);
|
||||||
|
void start_point(double x, double y);
|
||||||
|
void text(const char* text);
|
||||||
|
|
||||||
|
void rewind(unsigned id);
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// not supposed to be copied
|
||||||
|
gsv_text(const gsv_text&);
|
||||||
|
const gsv_text& operator = (const gsv_text&);
|
||||||
|
|
||||||
|
int16u value(const int8u* p) const
|
||||||
|
{
|
||||||
|
int16u v;
|
||||||
|
if(m_big_endian)
|
||||||
|
{
|
||||||
|
*(int8u*)&v = p[1];
|
||||||
|
*((int8u*)&v + 1) = p[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*(int8u*)&v = p[0];
|
||||||
|
*((int8u*)&v + 1) = p[1];
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_x;
|
||||||
|
double m_y;
|
||||||
|
double m_start_x;
|
||||||
|
double m_width;
|
||||||
|
double m_height;
|
||||||
|
double m_space;
|
||||||
|
double m_line_space;
|
||||||
|
char m_chr[2];
|
||||||
|
char* m_text;
|
||||||
|
char* m_text_buf;
|
||||||
|
unsigned m_buf_size;
|
||||||
|
char* m_cur_chr;
|
||||||
|
const void* m_font;
|
||||||
|
char* m_loaded_font;
|
||||||
|
status m_status;
|
||||||
|
bool m_big_endian;
|
||||||
|
bool m_flip;
|
||||||
|
|
||||||
|
int8u* m_indices;
|
||||||
|
int8* m_glyphs;
|
||||||
|
int8* m_bglyph;
|
||||||
|
int8* m_eglyph;
|
||||||
|
double m_w;
|
||||||
|
double m_h;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------gsv_text_outline
|
||||||
|
template<class Transformer = trans_affine> class gsv_text_outline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
gsv_text_outline(gsv_text& text, const Transformer& trans) :
|
||||||
|
m_polyline(text),
|
||||||
|
m_trans(m_polyline, trans)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void width(double w)
|
||||||
|
{
|
||||||
|
m_polyline.width(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
void transformer(const Transformer* trans)
|
||||||
|
{
|
||||||
|
m_trans->transformer(trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rewind(unsigned id)
|
||||||
|
{
|
||||||
|
m_trans.rewind(id);
|
||||||
|
m_polyline.line_join(vcgen_stroke::round_join);
|
||||||
|
m_polyline.line_cap(vcgen_stroke::round_cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
return m_trans.vertex(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
conv_stroke<gsv_text> m_polyline;
|
||||||
|
conv_transform<conv_stroke<gsv_text>, Transformer> m_trans;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,367 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Image transformation filters,
|
||||||
|
// Filtering classes (image_filter_base, image_filter),
|
||||||
|
// Basic filter shape classes:
|
||||||
|
// image_filter_bilinear,
|
||||||
|
// image_filter_bicubic,
|
||||||
|
// image_filter_spline16,
|
||||||
|
// image_filter_spline36,
|
||||||
|
// image_filter_sinc64,
|
||||||
|
// image_filter_sinc144,
|
||||||
|
// image_filter_sinc196,
|
||||||
|
// image_filter_sinc256
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_IMAGE_FILTERS_INCLUDED
|
||||||
|
#define AGG_IMAGE_FILTERS_INCLUDED
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
// See Implementation agg_image_filters.cpp
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
image_filter_shift = 14, //----image_filter_shift
|
||||||
|
image_filter_size = 1 << image_filter_shift, //----image_filter_size
|
||||||
|
image_filter_mask = image_filter_size - 1, //----image_filter_mask
|
||||||
|
|
||||||
|
image_subpixel_shift = 8, //----image_subpixel_shift
|
||||||
|
image_subpixel_size = 1 << image_subpixel_shift, //----image_subpixel_size
|
||||||
|
image_subpixel_mask = image_subpixel_size - 1 //----image_subpixel_mask
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------image_filter_base
|
||||||
|
class image_filter_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~image_filter_base();
|
||||||
|
|
||||||
|
image_filter_base(unsigned dimension);
|
||||||
|
|
||||||
|
unsigned dimension() const { return m_dimension; }
|
||||||
|
int start() const { return m_start; }
|
||||||
|
const double* weight_array_dbl() const { return m_weight_array_dbl; }
|
||||||
|
const int* weight_array_int() const { return m_weight_array_int; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void weight(unsigned idx, double val);
|
||||||
|
double calc_x(unsigned idx) const;
|
||||||
|
void normalize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
image_filter_base(const image_filter_base&);
|
||||||
|
const image_filter_base& operator = (const image_filter_base&);
|
||||||
|
|
||||||
|
unsigned m_dimension;
|
||||||
|
int m_start;
|
||||||
|
double* m_weight_array_dbl;
|
||||||
|
int* m_weight_array_int;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------image_filter
|
||||||
|
template<class FilterF> class image_filter : public image_filter_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
image_filter() :
|
||||||
|
image_filter_base(FilterF::dimension()),
|
||||||
|
m_filter_function()
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
unsigned dim = dimension() << image_subpixel_shift;
|
||||||
|
for(i = 0; i < dim; i++)
|
||||||
|
{
|
||||||
|
weight(i, m_filter_function.calc_weight(calc_x(i)));
|
||||||
|
}
|
||||||
|
normalize();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
FilterF m_filter_function;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------image_filter_bilinear
|
||||||
|
class image_filter_bilinear
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 2; }
|
||||||
|
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
return (x <= 0.0) ? x + 1.0 : 1.0 - x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------image_filter_bicubic
|
||||||
|
class image_filter_bicubic
|
||||||
|
{
|
||||||
|
static double pow3(double x)
|
||||||
|
{
|
||||||
|
return (x <= 0.0) ? 0.0 : x * x * x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 4; }
|
||||||
|
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(1.0/6.0) *
|
||||||
|
(pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------image_filter_spline16
|
||||||
|
class image_filter_spline16
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 4; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x < 0.0) x = -x;
|
||||||
|
if(x < 1.0)
|
||||||
|
{
|
||||||
|
return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0;
|
||||||
|
}
|
||||||
|
return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------image_filter_spline36
|
||||||
|
class image_filter_spline36
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 6; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x < 0.0) x = -x;
|
||||||
|
|
||||||
|
if(x < 1.0)
|
||||||
|
{
|
||||||
|
return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0;
|
||||||
|
}
|
||||||
|
if(x < 2.0)
|
||||||
|
{
|
||||||
|
return ((-6.0/11.0 * (x-1) + 270.0/209.0) * (x-1) - 156.0/ 209.0) * (x-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((1.0/11.0 * (x-2) - 45.0/209.0) * (x-2) + 26.0/209.0) * (x-2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------image_filter_sinc36
|
||||||
|
class image_filter_sinc36
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 6; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x == 0.0) return 1.0;
|
||||||
|
x *= pi;
|
||||||
|
double x3 = x * (1.0/3.0);
|
||||||
|
return (sin(x) / x) * (sin(x3) / x3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------image_filter_sinc64
|
||||||
|
class image_filter_sinc64
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 8; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x == 0.0) return 1.0;
|
||||||
|
x *= pi;
|
||||||
|
double x4 = x * 0.25;
|
||||||
|
return (sin(x) / x) * (sin(x4) / x4);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------image_filter_sinc100
|
||||||
|
class image_filter_sinc100
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 10; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x == 0.0) return 1.0;
|
||||||
|
x *= pi;
|
||||||
|
double x5 = x * 0.2;
|
||||||
|
return (sin(x) / x) * (sin(x5) / x5);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------image_filter_sinc144
|
||||||
|
class image_filter_sinc144
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 12; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x == 0.0) return 1.0;
|
||||||
|
x *= pi;
|
||||||
|
double x6 = x * (1.0/6.0);
|
||||||
|
return (sin(x) / x) * (sin(x6) / x6);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------image_filter_sinc196
|
||||||
|
class image_filter_sinc196
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 14; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x == 0.0) return 1.0;
|
||||||
|
x *= pi;
|
||||||
|
double x7 = x * (1.0/7.0);
|
||||||
|
return (sin(x) / x) * (sin(x7) / x7);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------image_filter_sinc256
|
||||||
|
class image_filter_sinc256
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 16; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x == 0.0) return 1.0;
|
||||||
|
x *= pi;
|
||||||
|
double x8 = x * 0.125;
|
||||||
|
return (sin(x) / x) * (sin(x8) / x8);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------image_filter_blackman36
|
||||||
|
class image_filter_blackman36
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 6; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x == 0.0) return 1.0;
|
||||||
|
x *= pi;
|
||||||
|
double x3 = x * (1.0/3.0);
|
||||||
|
return (sin(x) / x) * (0.42 + 0.5*cos(x3) + 0.08*cos(2*x3));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------image_filter_blackman64
|
||||||
|
class image_filter_blackman64
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 8; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x == 0.0) return 1.0;
|
||||||
|
x *= pi;
|
||||||
|
double x4 = x * 0.25;
|
||||||
|
return (sin(x) / x) * (0.42 + 0.5*cos(x4) + 0.08*cos(2*x4));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------image_filter_blackman100
|
||||||
|
class image_filter_blackman100
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 10; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x == 0.0) return 1.0;
|
||||||
|
x *= pi;
|
||||||
|
double x5 = x * 0.2;
|
||||||
|
return (sin(x) / x) * (0.42 + 0.5*cos(x5) + 0.08*cos(2*x5));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------image_filter_blackman144
|
||||||
|
class image_filter_blackman144
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 12; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x == 0.0) return 1.0;
|
||||||
|
x *= pi;
|
||||||
|
double x6 = x * (1.0/6.0);
|
||||||
|
return (sin(x) / x) * (0.42 + 0.5*cos(x6) + 0.08*cos(2*x6));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------image_filter_blackman196
|
||||||
|
class image_filter_blackman196
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 14; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x == 0.0) return 1.0;
|
||||||
|
x *= pi;
|
||||||
|
double x7 = x * (1.0/7.0);
|
||||||
|
return (sin(x) / x) * (0.42 + 0.5*cos(x7) + 0.08*cos(2*x7));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------image_filter_blackman256
|
||||||
|
class image_filter_blackman256
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static unsigned dimension() { return 16; }
|
||||||
|
static double calc_weight(double x)
|
||||||
|
{
|
||||||
|
if(x == 0.0) return 1.0;
|
||||||
|
x *= pi;
|
||||||
|
double x8 = x * 0.125;
|
||||||
|
return (sin(x) / x) * (0.42 + 0.5*cos(x8) + 0.08*cos(2*x8));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_LINE_AA_BASICS_INCLUDED
|
||||||
|
#define AGG_LINE_AA_BASICS_INCLUDED
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
// See Implementation agg_line_aa_basics.cpp
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
line_subpixel_shift = 8, //----line_subpixel_shift
|
||||||
|
line_subpixel_size = 1 << line_subpixel_shift, //----line_subpixel_size
|
||||||
|
line_subpixel_mask = line_subpixel_size - 1 //----line_subpixel_mask
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
line_mr_subpixel_shift = 4, //----line_mr_subpixel_shift
|
||||||
|
line_mr_subpixel_size = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_size
|
||||||
|
line_mr_subpixel_mask = line_mr_subpixel_size - 1 //----line_mr_subpixel_mask
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------line_mr
|
||||||
|
inline int line_mr(int x)
|
||||||
|
{
|
||||||
|
return x >> (line_subpixel_shift - line_mr_subpixel_shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------line_hr
|
||||||
|
inline int line_hr(int x)
|
||||||
|
{
|
||||||
|
return x << (line_subpixel_shift - line_mr_subpixel_shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------line_dbl_hr
|
||||||
|
inline int line_dbl_hr(int x)
|
||||||
|
{
|
||||||
|
return x << line_subpixel_shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------line_coord
|
||||||
|
inline int line_coord(double x)
|
||||||
|
{
|
||||||
|
return int(x * line_subpixel_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================line_parameters
|
||||||
|
struct line_parameters
|
||||||
|
{
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
line_parameters() {}
|
||||||
|
line_parameters(int x1_, int y1_, int x2_, int y2_, int len_) :
|
||||||
|
x1(x1_), y1(y1_), x2(x2_), y2(y2_),
|
||||||
|
dx(abs(x2_ - x1_)),
|
||||||
|
dy(abs(y2_ - y1_)),
|
||||||
|
sx((x2_ > x1_) ? 1 : -1),
|
||||||
|
sy((y2_ > y1_) ? 1 : -1),
|
||||||
|
vertical(dy >= dx),
|
||||||
|
inc(vertical ? sy : sx),
|
||||||
|
len(len_),
|
||||||
|
octant((sy & 4) | (sx & 2) | int(vertical))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
unsigned orthogonal_quadrant() const { return s_orthogonal_quadrant[octant]; }
|
||||||
|
unsigned diagonal_quadrant() const { return s_diagonal_quadrant[octant]; }
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
bool same_orthogonal_quadrant(const line_parameters& lp) const
|
||||||
|
{
|
||||||
|
return s_orthogonal_quadrant[octant] == s_orthogonal_quadrant[lp.octant];
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
bool same_diagonal_quadrant(const line_parameters& lp) const
|
||||||
|
{
|
||||||
|
return s_diagonal_quadrant[octant] == s_diagonal_quadrant[lp.octant];
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
int x1, y1, x2, y2, dx, dy, sx, sy;
|
||||||
|
bool vertical;
|
||||||
|
int inc;
|
||||||
|
int len;
|
||||||
|
int octant;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
static int8u s_orthogonal_quadrant[8];
|
||||||
|
static int8u s_diagonal_quadrant[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// See Implementation agg_line_aa_basics.cpp
|
||||||
|
|
||||||
|
//----------------------------------------------------------------bisectrix
|
||||||
|
void bisectrix(const line_parameters& l1,
|
||||||
|
const line_parameters& l2,
|
||||||
|
int* x, int* y);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,247 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_MATH_INCLUDED
|
||||||
|
#define AGG_MATH_INCLUDED
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
const double intersection_epsilon = 1.0e-8;
|
||||||
|
|
||||||
|
//------------------------------------------------------calc_point_location
|
||||||
|
inline double calc_point_location(double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double x, double y)
|
||||||
|
{
|
||||||
|
return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------point_in_triangle
|
||||||
|
inline bool point_in_triangle(double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double x3, double y3,
|
||||||
|
double x, double y)
|
||||||
|
{
|
||||||
|
bool cp1 = calc_point_location(x1, y1, x2, y2, x, y) < 0.0;
|
||||||
|
bool cp2 = calc_point_location(x2, y2, x3, y3, x, y) < 0.0;
|
||||||
|
bool cp3 = calc_point_location(x3, y3, x1, y1, x, y) < 0.0;
|
||||||
|
return cp1 == cp2 && cp2 == cp3 && cp3 == cp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------calc_distance
|
||||||
|
inline double calc_distance(double x1, double y1, double x2, double y2)
|
||||||
|
{
|
||||||
|
double dx = x2-x1;
|
||||||
|
double dy = y2-y1;
|
||||||
|
return sqrt(dx * dx + dy * dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------calc_point_line_distance
|
||||||
|
inline double calc_point_line_distance(double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double x, double y)
|
||||||
|
{
|
||||||
|
double dx = x2-x1;
|
||||||
|
double dy = y2-y1;
|
||||||
|
return ((x - x2) * dy - (y - y2) * dx) / sqrt(dx * dx + dy * dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------calc_intersection
|
||||||
|
inline bool calc_intersection(double ax, double ay, double bx, double by,
|
||||||
|
double cx, double cy, double dx, double dy,
|
||||||
|
double* x, double* y)
|
||||||
|
{
|
||||||
|
double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy);
|
||||||
|
double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx);
|
||||||
|
if(fabs(den) < intersection_epsilon) return false;
|
||||||
|
double r = num / den;
|
||||||
|
*x = ax + r * (bx-ax);
|
||||||
|
*y = ay + r * (by-ay);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------calc_orthogonal
|
||||||
|
inline void calc_orthogonal(double thickness,
|
||||||
|
double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double* x, double* y)
|
||||||
|
{
|
||||||
|
double dx = x2 - x1;
|
||||||
|
double dy = y2 - y1;
|
||||||
|
double d = sqrt(dx*dx + dy*dy);
|
||||||
|
*x = thickness * dy / d;
|
||||||
|
*y = thickness * dx / d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------dilate_triangle
|
||||||
|
inline void dilate_triangle(double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double x3, double y3,
|
||||||
|
double *x, double* y,
|
||||||
|
double d)
|
||||||
|
{
|
||||||
|
double dx1=0.0;
|
||||||
|
double dy1=0.0;
|
||||||
|
double dx2=0.0;
|
||||||
|
double dy2=0.0;
|
||||||
|
double dx3=0.0;
|
||||||
|
double dy3=0.0;
|
||||||
|
double loc = calc_point_location(x1, y1, x2, y2, x3, y3);
|
||||||
|
if(fabs(loc) > intersection_epsilon)
|
||||||
|
{
|
||||||
|
if(calc_point_location(x1, y1, x2, y2, x3, y3) > 0.0)
|
||||||
|
{
|
||||||
|
d = -d;
|
||||||
|
}
|
||||||
|
calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1);
|
||||||
|
calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2);
|
||||||
|
calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3);
|
||||||
|
}
|
||||||
|
*x++ = x1 + dx1; *y++ = y1 - dy1;
|
||||||
|
*x++ = x2 + dx1; *y++ = y2 - dy1;
|
||||||
|
*x++ = x2 + dx2; *y++ = y2 - dy2;
|
||||||
|
*x++ = x3 + dx2; *y++ = y3 - dy2;
|
||||||
|
*x++ = x3 + dx3; *y++ = y3 - dy3;
|
||||||
|
*x++ = x1 + dx3; *y++ = y1 - dy3;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------calc_polygon_area
|
||||||
|
template<class Storage> double calc_polygon_area(const Storage& st)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
double sum = 0.0;
|
||||||
|
double x = st[0].x;
|
||||||
|
double y = st[0].y;
|
||||||
|
double xs = x;
|
||||||
|
double ys = y;
|
||||||
|
|
||||||
|
for(i = 1; i < st.size(); i++)
|
||||||
|
{
|
||||||
|
const typename Storage::value_type& v = st[i];
|
||||||
|
sum += x * v.y - y * v.x;
|
||||||
|
x = v.x;
|
||||||
|
y = v.y;
|
||||||
|
}
|
||||||
|
return (sum + x * ys - y * xs) * 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Tables for fast sqrt
|
||||||
|
extern int16u g_sqrt_table[1024];
|
||||||
|
extern int8 g_elder_bit_table[256];
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------fast_sqrt
|
||||||
|
//Fast integer Sqrt - really fast: no cycles, divisions or multiplications
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4035) //Disable warning "no return value"
|
||||||
|
#endif
|
||||||
|
inline unsigned fast_sqrt(unsigned val)
|
||||||
|
{
|
||||||
|
#if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM)
|
||||||
|
//For Ix86 family processors this assembler code is used.
|
||||||
|
//The key command here is bsr - determination the number of the most
|
||||||
|
//significant bit of the value. For other processors
|
||||||
|
//(and maybe compilers) the pure C "#else" section is used.
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
mov ebx, val
|
||||||
|
mov edx, 11
|
||||||
|
bsr ecx, ebx
|
||||||
|
sub ecx, 9
|
||||||
|
jle less_than_9_bits
|
||||||
|
shr ecx, 1
|
||||||
|
adc ecx, 0
|
||||||
|
sub edx, ecx
|
||||||
|
shl ecx, 1
|
||||||
|
shr ebx, cl
|
||||||
|
less_than_9_bits:
|
||||||
|
xor eax, eax
|
||||||
|
mov ax, g_sqrt_table[ebx*2]
|
||||||
|
mov ecx, edx
|
||||||
|
shr eax, cl
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
//This code is actually pure C and portable to most
|
||||||
|
//arcitectures including 64bit ones.
|
||||||
|
unsigned t = val;
|
||||||
|
int bit=0;
|
||||||
|
unsigned shift = 11;
|
||||||
|
|
||||||
|
//The following piece of code is just an emulation of the
|
||||||
|
//Ix86 assembler command "bsr" (see above). However on old
|
||||||
|
//Intels (like Intel MMX 233MHz) this code is about twice
|
||||||
|
//faster (sic!) then just one "bsr". On PIII and PIV the
|
||||||
|
//bsr is optimized quite well.
|
||||||
|
bit = t >> 24;
|
||||||
|
if(bit)
|
||||||
|
{
|
||||||
|
bit = g_elder_bit_table[bit] + 24;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bit = (t >> 16) & 0xFF;
|
||||||
|
if(bit)
|
||||||
|
{
|
||||||
|
bit = g_elder_bit_table[bit] + 16;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bit = (t >> 8) & 0xFF;
|
||||||
|
if(bit)
|
||||||
|
{
|
||||||
|
bit = g_elder_bit_table[bit] + 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bit = g_elder_bit_table[t];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//This is calculation sqrt itself.
|
||||||
|
bit -= 9;
|
||||||
|
if(bit > 0)
|
||||||
|
{
|
||||||
|
bit = (bit >> 1) + (bit & 1);
|
||||||
|
shift -= bit;
|
||||||
|
val >>= (bit << 1);
|
||||||
|
}
|
||||||
|
return g_sqrt_table[val] >> shift;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,369 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_PATH_STORAGE_INCLUDED
|
||||||
|
#define AGG_PATH_STORAGE_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//------------------------------------------------------------path_storage
|
||||||
|
// A container to store vertices with their flags.
|
||||||
|
// A path consists of a number of contours separated with "move_to"
|
||||||
|
// commands. The path storage can keep and maintain more than one
|
||||||
|
// path.
|
||||||
|
// To navigate to the beginning of a particular path, use rewind(path_id);
|
||||||
|
// Where path_id is what start_new_path() returns. So, when you call
|
||||||
|
// start_new_path() you need to store its return value somewhere else
|
||||||
|
// to navigate to the path afterwards.
|
||||||
|
//
|
||||||
|
// See Implementation: agg_path_storage.cpp
|
||||||
|
// See also: vertex_source concept
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
class path_storage
|
||||||
|
{
|
||||||
|
// Allocation parameters
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
block_shift = 8,
|
||||||
|
block_size = 1 << block_shift,
|
||||||
|
block_mask = block_size - 1,
|
||||||
|
block_pool = 256
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
class const_iterator
|
||||||
|
{
|
||||||
|
void vertex()
|
||||||
|
{
|
||||||
|
if(m_vertex_idx < m_path->total_vertices())
|
||||||
|
{
|
||||||
|
m_vertex.cmd = m_path->vertex(m_vertex_idx, &m_vertex.x, &m_vertex.y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_vertex.cmd = path_cmd_stop;
|
||||||
|
m_vertex.x = m_vertex.y = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
const_iterator() {}
|
||||||
|
const_iterator(unsigned cmd) { m_vertex.cmd = cmd; }
|
||||||
|
const_iterator(const const_iterator& i) :
|
||||||
|
m_path(i.m_path),
|
||||||
|
m_vertex_idx(i.m_vertex_idx),
|
||||||
|
m_vertex(i.m_vertex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator(const path_storage& p, unsigned id) :
|
||||||
|
m_path(&p),
|
||||||
|
m_vertex_idx(id)
|
||||||
|
{
|
||||||
|
vertex();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator& operator++()
|
||||||
|
{
|
||||||
|
++m_vertex_idx;
|
||||||
|
vertex();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vertex_type& operator*() const { return m_vertex; }
|
||||||
|
const vertex_type* operator->() const { return &m_vertex; }
|
||||||
|
|
||||||
|
bool operator != (const const_iterator& i)
|
||||||
|
{
|
||||||
|
return m_vertex.cmd != i.m_vertex.cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const path_storage* m_path;
|
||||||
|
unsigned m_vertex_idx;
|
||||||
|
vertex_type m_vertex;
|
||||||
|
};
|
||||||
|
|
||||||
|
~path_storage();
|
||||||
|
path_storage();
|
||||||
|
path_storage(const path_storage& ps);
|
||||||
|
|
||||||
|
void remove_all();
|
||||||
|
|
||||||
|
unsigned last_vertex(double* x, double* y) const;
|
||||||
|
unsigned prev_vertex(double* x, double* y) const;
|
||||||
|
|
||||||
|
void rel_to_abs(double* x, double* y) const;
|
||||||
|
|
||||||
|
void move_to(double x, double y);
|
||||||
|
void move_rel(double dx, double dy);
|
||||||
|
|
||||||
|
void line_to(double x, double y);
|
||||||
|
void line_rel(double dx, double dy);
|
||||||
|
|
||||||
|
void arc_to(double rx, double ry,
|
||||||
|
double angle,
|
||||||
|
bool large_arc_flag,
|
||||||
|
bool sweep_flag,
|
||||||
|
double x, double y);
|
||||||
|
|
||||||
|
void arc_rel(double rx, double ry,
|
||||||
|
double angle,
|
||||||
|
bool large_arc_flag,
|
||||||
|
bool sweep_flag,
|
||||||
|
double dx, double dy);
|
||||||
|
|
||||||
|
void curve3(double x_ctrl, double y_ctrl,
|
||||||
|
double x_to, double y_to);
|
||||||
|
|
||||||
|
void curve3_rel(double dx_ctrl, double dy_ctrl,
|
||||||
|
double dx_to, double dy_to);
|
||||||
|
|
||||||
|
void curve3(double x_to, double y_to);
|
||||||
|
|
||||||
|
void curve3_rel(double dx_to, double dy_to);
|
||||||
|
|
||||||
|
void curve4(double x_ctrl1, double y_ctrl1,
|
||||||
|
double x_ctrl2, double y_ctrl2,
|
||||||
|
double x_to, double y_to);
|
||||||
|
|
||||||
|
void curve4_rel(double dx_ctrl1, double dy_ctrl1,
|
||||||
|
double dx_ctrl2, double dy_ctrl2,
|
||||||
|
double dx_to, double dy_to);
|
||||||
|
|
||||||
|
void curve4(double x_ctrl2, double y_ctrl2,
|
||||||
|
double x_to, double y_to);
|
||||||
|
|
||||||
|
void curve4_rel(double x_ctrl2, double y_ctrl2,
|
||||||
|
double x_to, double y_to);
|
||||||
|
|
||||||
|
|
||||||
|
void end_poly(unsigned flags = path_flags_close);
|
||||||
|
|
||||||
|
void close_polygon(unsigned flags = path_flags_none)
|
||||||
|
{
|
||||||
|
end_poly(path_flags_close | flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_poly(const double* vertices, unsigned num,
|
||||||
|
bool solid_path = false,
|
||||||
|
unsigned end_flags = path_flags_none);
|
||||||
|
|
||||||
|
void add_vertices(const double* vertices, unsigned num)
|
||||||
|
{
|
||||||
|
add_poly(vertices, num, path_flags_none);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class VertexSource>
|
||||||
|
void add_path(VertexSource& vs,
|
||||||
|
unsigned path_id = 0,
|
||||||
|
bool solid_path = true)
|
||||||
|
{
|
||||||
|
double x, y;
|
||||||
|
unsigned cmd;
|
||||||
|
vs.rewind(path_id);
|
||||||
|
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||||
|
{
|
||||||
|
if(is_move_to(cmd) && solid_path && m_total_vertices)
|
||||||
|
{
|
||||||
|
cmd = path_cmd_line_to;
|
||||||
|
}
|
||||||
|
add_vertex(x, y, cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned start_new_path();
|
||||||
|
|
||||||
|
void copy_from(const path_storage& ps);
|
||||||
|
const path_storage& operator = (const path_storage& ps)
|
||||||
|
{
|
||||||
|
copy_from(ps);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned total_vertices() const { return m_total_vertices; }
|
||||||
|
unsigned vertex(unsigned idx, double* x, double* y) const
|
||||||
|
{
|
||||||
|
unsigned nb = idx >> block_shift;
|
||||||
|
const double* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1);
|
||||||
|
*x = *pv++;
|
||||||
|
*y = *pv;
|
||||||
|
return m_cmd_blocks[nb][idx & block_mask];
|
||||||
|
}
|
||||||
|
unsigned command(unsigned idx) const
|
||||||
|
{
|
||||||
|
return m_cmd_blocks[idx >> block_shift][idx & block_mask];
|
||||||
|
}
|
||||||
|
|
||||||
|
void rewind(unsigned path_id);
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
const_iterator begin(unsigned id) const { return const_iterator(*this, id); }
|
||||||
|
const_iterator begin() const { return const_iterator(*this, 0); }
|
||||||
|
const_iterator end() const { return const_iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
// Arrange the orientation of all the polygons. After calling this
|
||||||
|
// method all the polygons will have the same orientation
|
||||||
|
// determined by the new_orientation flag, i.e.,
|
||||||
|
// path_flags_cw or path_flags_ccw
|
||||||
|
unsigned arrange_orientations(unsigned path_id, path_flags_e new_orientation);
|
||||||
|
void arrange_orientations_all_paths(path_flags_e new_orientation);
|
||||||
|
|
||||||
|
// Flip all the vertices horizontally or vertically
|
||||||
|
void flip_x(double x1, double x2);
|
||||||
|
void flip_y(double y1, double y2);
|
||||||
|
|
||||||
|
// This function adds a vertex with its flags directly. Since there's no
|
||||||
|
// checking for errors, keeping proper path integrity is the responsibility
|
||||||
|
// of the caller. It can be said the function is "not very public".
|
||||||
|
void add_vertex(double x, double y, unsigned cmd);
|
||||||
|
|
||||||
|
// Allows you to modify vertex coordinates. The caller must know
|
||||||
|
// the index of the vertex.
|
||||||
|
void modify_vertex(unsigned idx, double x, double y)
|
||||||
|
{
|
||||||
|
double* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1);
|
||||||
|
*pv++ = x;
|
||||||
|
*pv = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allows you to modify vertex command. The caller must know
|
||||||
|
// the index of the vertex.
|
||||||
|
void modify_command(unsigned idx, unsigned cmd)
|
||||||
|
{
|
||||||
|
m_cmd_blocks[idx >> block_shift][idx & block_mask] = (unsigned char)cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
void allocate_block(unsigned nb);
|
||||||
|
unsigned char* storage_ptrs(double** xy_ptr);
|
||||||
|
unsigned perceive_polygon_orientation(unsigned idx,
|
||||||
|
double xs, double ys,
|
||||||
|
unsigned* orientation);
|
||||||
|
void reverse_polygon(unsigned start, unsigned end);
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned m_total_vertices;
|
||||||
|
unsigned m_total_blocks;
|
||||||
|
unsigned m_max_blocks;
|
||||||
|
double** m_coord_blocks;
|
||||||
|
unsigned char** m_cmd_blocks;
|
||||||
|
unsigned m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline unsigned path_storage::vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
if(m_iterator >= m_total_vertices) return path_cmd_stop;
|
||||||
|
return vertex(m_iterator++, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline unsigned path_storage::prev_vertex(double* x, double* y) const
|
||||||
|
{
|
||||||
|
if(m_total_vertices > 1)
|
||||||
|
{
|
||||||
|
return vertex(m_total_vertices - 2, x, y);
|
||||||
|
}
|
||||||
|
return path_cmd_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline unsigned path_storage::last_vertex(double* x, double* y) const
|
||||||
|
{
|
||||||
|
if(m_total_vertices)
|
||||||
|
{
|
||||||
|
return vertex(m_total_vertices - 1, x, y);
|
||||||
|
}
|
||||||
|
return path_cmd_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void path_storage::rel_to_abs(double* x, double* y) const
|
||||||
|
{
|
||||||
|
if(m_total_vertices)
|
||||||
|
{
|
||||||
|
double x2;
|
||||||
|
double y2;
|
||||||
|
if(is_vertex(vertex(m_total_vertices - 1, &x2, &y2)))
|
||||||
|
{
|
||||||
|
*x += x2;
|
||||||
|
*y += y2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline unsigned char* path_storage::storage_ptrs(double** xy_ptr)
|
||||||
|
{
|
||||||
|
unsigned nb = m_total_vertices >> block_shift;
|
||||||
|
if(nb >= m_total_blocks)
|
||||||
|
{
|
||||||
|
allocate_block(nb);
|
||||||
|
}
|
||||||
|
*xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1);
|
||||||
|
return m_cmd_blocks[nb] + (m_total_vertices & block_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void path_storage::add_vertex(double x, double y, unsigned cmd)
|
||||||
|
{
|
||||||
|
double* coord_ptr = 0;
|
||||||
|
unsigned char* cmd_ptr = storage_ptrs(&coord_ptr);
|
||||||
|
*cmd_ptr = (unsigned char)cmd;
|
||||||
|
*coord_ptr++ = x;
|
||||||
|
*coord_ptr = y;
|
||||||
|
m_total_vertices++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void path_storage::move_to(double x, double y)
|
||||||
|
{
|
||||||
|
add_vertex(x, y, path_cmd_move_to);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void path_storage::move_rel(double dx, double dy)
|
||||||
|
{
|
||||||
|
rel_to_abs(&dx, &dy);
|
||||||
|
add_vertex(dx, dy, path_cmd_move_to);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void path_storage::line_to(double x, double y)
|
||||||
|
{
|
||||||
|
add_vertex(x, y, path_cmd_line_to);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void path_storage::line_rel(double dx, double dy)
|
||||||
|
{
|
||||||
|
rel_to_abs(&dx, &dy);
|
||||||
|
add_vertex(dx, dy, path_cmd_line_to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+293
@@ -0,0 +1,293 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_PATH_STORAGE_INTEGER_INCLUDED
|
||||||
|
#define AGG_PATH_STORAGE_INTEGER_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_array.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//---------------------------------------------------------vertex_integer
|
||||||
|
template<class T, unsigned CoordShift=6> struct vertex_integer
|
||||||
|
{
|
||||||
|
enum path_cmd
|
||||||
|
{
|
||||||
|
cmd_move_to = 0,
|
||||||
|
cmd_line_to = 1,
|
||||||
|
cmd_curve3 = 2,
|
||||||
|
cmd_curve4 = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
coord_shift = CoordShift,
|
||||||
|
coord_mult = 1 << coord_shift
|
||||||
|
};
|
||||||
|
|
||||||
|
T x,y;
|
||||||
|
vertex_integer() {}
|
||||||
|
vertex_integer(T x_, T y_, unsigned flag) :
|
||||||
|
x(((x_ << 1) & ~1) | (flag & 1)),
|
||||||
|
y(((y_ << 1) & ~1) | (flag >> 1)) {}
|
||||||
|
|
||||||
|
unsigned vertex(double* x_, double* y_, double dx=0, double dy=0) const
|
||||||
|
{
|
||||||
|
*x_ = dx + (double(x >> 1) / coord_mult);
|
||||||
|
*y_ = dy + (double(y >> 1) / coord_mult);
|
||||||
|
switch(((y & 1) << 1) | (x & 1))
|
||||||
|
{
|
||||||
|
case cmd_move_to: return path_cmd_move_to;
|
||||||
|
case cmd_line_to: return path_cmd_line_to;
|
||||||
|
case cmd_curve3: return path_cmd_curve3;
|
||||||
|
case cmd_curve4: return path_cmd_curve4;
|
||||||
|
}
|
||||||
|
return path_cmd_stop;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------path_storage_integer
|
||||||
|
template<class T, unsigned CoordShift=6> class path_storage_integer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef vertex_integer<T, CoordShift> vertex_integer_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void remove_all() { m_storage.remove_all(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void move_to(T x, T y)
|
||||||
|
{
|
||||||
|
m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void line_to(T x, T y)
|
||||||
|
{
|
||||||
|
m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_line_to));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void curve3(T x_ctrl, T y_ctrl,
|
||||||
|
T x_to, T y_to)
|
||||||
|
{
|
||||||
|
m_storage.add(vertex_integer_type(x_ctrl, y_ctrl, vertex_integer_type::cmd_curve3));
|
||||||
|
m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve3));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void curve4(T x_ctrl1, T y_ctrl1,
|
||||||
|
T x_ctrl2, T y_ctrl2,
|
||||||
|
T x_to, T y_to)
|
||||||
|
{
|
||||||
|
m_storage.add(vertex_integer_type(x_ctrl1, y_ctrl1, vertex_integer_type::cmd_curve4));
|
||||||
|
m_storage.add(vertex_integer_type(x_ctrl2, y_ctrl2, vertex_integer_type::cmd_curve4));
|
||||||
|
m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve4));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void close_polygon() {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned size() const { return m_storage.size(); }
|
||||||
|
unsigned vertex(unsigned idx, T* x, T* y) const
|
||||||
|
{
|
||||||
|
const vertex_integer_type& v = m_storage[idx];
|
||||||
|
*x = v.x >> 1;
|
||||||
|
*y = v.y >> 1;
|
||||||
|
return ((v.y & 1) << 1) | (v.x & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); }
|
||||||
|
void serialize(int8u* ptr) const
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < m_storage.size(); i++)
|
||||||
|
{
|
||||||
|
memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type));
|
||||||
|
ptr += sizeof(vertex_integer_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void rewind(unsigned)
|
||||||
|
{
|
||||||
|
m_vertex_idx = 0;
|
||||||
|
m_closed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
if(m_storage.size() < 2 || m_vertex_idx > m_storage.size())
|
||||||
|
{
|
||||||
|
*x = 0;
|
||||||
|
*y = 0;
|
||||||
|
return path_cmd_stop;
|
||||||
|
}
|
||||||
|
if(m_vertex_idx == m_storage.size())
|
||||||
|
{
|
||||||
|
*x = 0;
|
||||||
|
*y = 0;
|
||||||
|
++m_vertex_idx;
|
||||||
|
return path_cmd_end_poly | path_flags_close;
|
||||||
|
}
|
||||||
|
unsigned cmd = m_storage[m_vertex_idx].vertex(x, y);
|
||||||
|
if(is_move_to(cmd) && !m_closed)
|
||||||
|
{
|
||||||
|
*x = 0;
|
||||||
|
*y = 0;
|
||||||
|
m_closed = true;
|
||||||
|
return path_cmd_end_poly | path_flags_close;
|
||||||
|
}
|
||||||
|
m_closed = false;
|
||||||
|
++m_vertex_idx;
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rect_d bounding_rect() const
|
||||||
|
{
|
||||||
|
rect_d bounds(1e100, 1e100, -1e100, -1e100);
|
||||||
|
if(m_storage.size() == 0)
|
||||||
|
{
|
||||||
|
bounds.x1 = bounds.x1 = bounds.x2 = bounds.y2 = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < m_storage.size(); i++)
|
||||||
|
{
|
||||||
|
double x, y;
|
||||||
|
m_storage[i].vertex(&x, &y);
|
||||||
|
if(x < bounds.x1) bounds.x1 = x;
|
||||||
|
if(y < bounds.y1) bounds.y1 = y;
|
||||||
|
if(x > bounds.x2) bounds.x2 = x;
|
||||||
|
if(y > bounds.y2) bounds.y2 = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
pod_deque<vertex_integer_type, 6> m_storage;
|
||||||
|
unsigned m_vertex_idx;
|
||||||
|
bool m_closed;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------serialized_integer_path_adaptor
|
||||||
|
template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef vertex_integer<T, CoordShift> vertex_integer_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
serialized_integer_path_adaptor() :
|
||||||
|
m_data(0),
|
||||||
|
m_end(0),
|
||||||
|
m_ptr(0),
|
||||||
|
m_dx(0.0),
|
||||||
|
m_dy(0.0),
|
||||||
|
m_closed(true)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
serialized_integer_path_adaptor(const int8u* data, unsigned size,
|
||||||
|
double dx, double dy) :
|
||||||
|
m_data(data),
|
||||||
|
m_end(data + size),
|
||||||
|
m_ptr(data),
|
||||||
|
m_dx(dx),
|
||||||
|
m_dy(dy),
|
||||||
|
m_closed(true)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void init(const int8u* data, unsigned size, double dx, double dy)
|
||||||
|
{
|
||||||
|
m_data = data;
|
||||||
|
m_end = data + size;
|
||||||
|
m_ptr = data;
|
||||||
|
m_dx = dx;
|
||||||
|
m_dy = dy;
|
||||||
|
m_closed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void rewind(unsigned)
|
||||||
|
{
|
||||||
|
m_ptr = m_data;
|
||||||
|
m_closed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
if(m_data == 0 || m_ptr > m_end)
|
||||||
|
{
|
||||||
|
*x = 0;
|
||||||
|
*y = 0;
|
||||||
|
return path_cmd_stop;
|
||||||
|
}
|
||||||
|
if(m_ptr == m_end)
|
||||||
|
{
|
||||||
|
*x = 0;
|
||||||
|
*y = 0;
|
||||||
|
m_ptr += sizeof(vertex_integer_type);
|
||||||
|
return path_cmd_end_poly | path_flags_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex_integer_type v;
|
||||||
|
memcpy(&v, m_ptr, sizeof(vertex_integer_type));
|
||||||
|
unsigned cmd = v.vertex(x, y, m_dx, m_dy);
|
||||||
|
if(is_move_to(cmd) && !m_closed)
|
||||||
|
{
|
||||||
|
*x = 0;
|
||||||
|
*y = 0;
|
||||||
|
m_closed = true;
|
||||||
|
return path_cmd_end_poly | path_flags_close;
|
||||||
|
}
|
||||||
|
m_closed = false;
|
||||||
|
m_ptr += sizeof(vertex_integer_type);
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int8u* m_data;
|
||||||
|
const int8u* m_end;
|
||||||
|
const int8u* m_ptr;
|
||||||
|
double m_dx;
|
||||||
|
double m_dy;
|
||||||
|
bool m_closed;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_PATTERN_FILTERS_RGBA8_INCLUDED
|
||||||
|
#define AGG_PATTERN_FILTERS_RGBA8_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_line_aa_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//=======================================================pattern_filter_nn
|
||||||
|
template<class ColorT> struct pattern_filter_nn
|
||||||
|
{
|
||||||
|
typedef ColorT color_type;
|
||||||
|
static unsigned dilation() { return 0; }
|
||||||
|
|
||||||
|
static void pixel_low_res(color_type const* const* buf,
|
||||||
|
color_type* p, int x, int y)
|
||||||
|
{
|
||||||
|
*p = buf[y][x];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pixel_high_res(color_type const* const* buf,
|
||||||
|
color_type* p, int x, int y)
|
||||||
|
{
|
||||||
|
*p = buf[y >> line_subpixel_shift]
|
||||||
|
[x >> line_subpixel_shift];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========================================pattern_filter_bilinear_rgba8
|
||||||
|
struct pattern_filter_bilinear_rgba8
|
||||||
|
{
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
static unsigned dilation() { return 1; }
|
||||||
|
|
||||||
|
static void pixel_low_res(color_type const* const* buf,
|
||||||
|
color_type* p, int x, int y)
|
||||||
|
{
|
||||||
|
*p = buf[y][x];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pixel_high_res(color_type const* const* buf,
|
||||||
|
color_type* p, int x, int y)
|
||||||
|
{
|
||||||
|
int r, g, b, a;
|
||||||
|
r = g = b = a = line_subpixel_size * line_subpixel_size / 2;
|
||||||
|
|
||||||
|
int weight;
|
||||||
|
int x_lr = x >> line_subpixel_shift;
|
||||||
|
int y_lr = y >> line_subpixel_shift;
|
||||||
|
|
||||||
|
x &= line_subpixel_mask;
|
||||||
|
y &= line_subpixel_mask;
|
||||||
|
const color_type* ptr = buf[y_lr] + x_lr;
|
||||||
|
|
||||||
|
weight = (line_subpixel_size - x) *
|
||||||
|
(line_subpixel_size - y);
|
||||||
|
r += weight * ptr->r;
|
||||||
|
g += weight * ptr->g;
|
||||||
|
b += weight * ptr->b;
|
||||||
|
a += weight * ptr->a;
|
||||||
|
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
weight = x * (line_subpixel_size - y);
|
||||||
|
r += weight * ptr->r;
|
||||||
|
g += weight * ptr->g;
|
||||||
|
b += weight * ptr->b;
|
||||||
|
a += weight * ptr->a;
|
||||||
|
|
||||||
|
ptr = buf[y_lr + 1] + x_lr;
|
||||||
|
|
||||||
|
weight = (line_subpixel_size - x) * y;
|
||||||
|
r += weight * ptr->r;
|
||||||
|
g += weight * ptr->g;
|
||||||
|
b += weight * ptr->b;
|
||||||
|
a += weight * ptr->a;
|
||||||
|
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
weight = x * y;
|
||||||
|
r += weight * ptr->r;
|
||||||
|
g += weight * ptr->g;
|
||||||
|
b += weight * ptr->b;
|
||||||
|
a += weight * ptr->a;
|
||||||
|
|
||||||
|
p->r = (int8u)(r >> line_subpixel_shift * 2);
|
||||||
|
p->g = (int8u)(g >> line_subpixel_shift * 2);
|
||||||
|
p->b = (int8u)(b >> line_subpixel_shift * 2);
|
||||||
|
p->a = (int8u)(a >> line_subpixel_shift * 2);
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
|
||||||
|
#define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//==================================================pixfmt_amask_adaptor
|
||||||
|
template<class PixFmt, class AlphaMask> class pixfmt_amask_adaptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef PixFmt pixfmt_type;
|
||||||
|
typedef typename pixfmt_type::color_type color_type;
|
||||||
|
typedef AlphaMask amask_type;
|
||||||
|
typedef typename amask_type::cover_type cover_type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum { span_extra_tail = 256 };
|
||||||
|
|
||||||
|
void realloc_span(unsigned len)
|
||||||
|
{
|
||||||
|
if(len > m_max_len)
|
||||||
|
{
|
||||||
|
delete [] m_span;
|
||||||
|
m_span = new cover_type[m_max_len = len + span_extra_tail];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_span(unsigned len)
|
||||||
|
{
|
||||||
|
realloc_span(len);
|
||||||
|
|
||||||
|
// ATTN! May work incorrectly if cover_type is more that one byte
|
||||||
|
memset(m_span, amask_type::cover_full, len * sizeof(cover_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_span(unsigned len, const cover_type* covers)
|
||||||
|
{
|
||||||
|
realloc_span(len);
|
||||||
|
memcpy(m_span, covers, len * sizeof(cover_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
~pixfmt_amask_adaptor() { delete [] m_span; }
|
||||||
|
|
||||||
|
pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) :
|
||||||
|
m_pixf(&pixf), m_mask(&mask), m_span(0), m_max_len(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; }
|
||||||
|
void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned width() const { return m_pixf->width(); }
|
||||||
|
unsigned height() const { return m_pixf->height(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type pixel(int x, int y)
|
||||||
|
{
|
||||||
|
return m_pixf->pixel(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_pixel(int x, int y, const color_type& c)
|
||||||
|
{
|
||||||
|
m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
|
||||||
|
{
|
||||||
|
m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_hline(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c)
|
||||||
|
{
|
||||||
|
realloc_span(len);
|
||||||
|
m_mask->fill_hspan(x, y, m_span, len);
|
||||||
|
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_hline(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
cover_type cover)
|
||||||
|
{
|
||||||
|
init_span(len);
|
||||||
|
m_mask->combine_hspan(x, y, m_span, len);
|
||||||
|
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_vline(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c)
|
||||||
|
{
|
||||||
|
realloc_span(len);
|
||||||
|
m_mask->fill_vspan(x, y, m_span, len);
|
||||||
|
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_vline(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
cover_type cover)
|
||||||
|
{
|
||||||
|
init_span(len);
|
||||||
|
m_mask->combine_vspan(x, y, m_span, len);
|
||||||
|
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_from(const rendering_buffer& from,
|
||||||
|
int xdst, int ydst,
|
||||||
|
int xsrc, int ysrc,
|
||||||
|
unsigned len)
|
||||||
|
{
|
||||||
|
m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_hspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
const cover_type* covers)
|
||||||
|
{
|
||||||
|
init_span(len, covers);
|
||||||
|
m_mask->combine_hspan(x, y, m_span, len);
|
||||||
|
m_pixf->blend_solid_hspan(x, y, len, c, m_span);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_vspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
const cover_type* covers)
|
||||||
|
{
|
||||||
|
init_span(len, covers);
|
||||||
|
m_mask->combine_vspan(x, y, m_span, len);
|
||||||
|
m_pixf->blend_solid_vspan(x, y, len, c, m_span);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const cover_type* covers,
|
||||||
|
cover_type cover = cover_full)
|
||||||
|
{
|
||||||
|
if(covers)
|
||||||
|
{
|
||||||
|
init_span(len, covers);
|
||||||
|
m_mask->combine_hspan(x, y, m_span, len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
realloc_span(len);
|
||||||
|
m_mask->fill_hspan(x, y, m_span, len);
|
||||||
|
}
|
||||||
|
m_pixf->blend_color_hspan(x, y, len, colors, m_span, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const cover_type* covers,
|
||||||
|
cover_type cover = cover_full)
|
||||||
|
{
|
||||||
|
if(covers)
|
||||||
|
{
|
||||||
|
init_span(len, covers);
|
||||||
|
m_mask->combine_vspan(x, y, m_span, len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
realloc_span(len);
|
||||||
|
m_mask->fill_vspan(x, y, m_span, len);
|
||||||
|
}
|
||||||
|
m_pixf->blend_color_vspan(x, y, len, colors, m_span, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
pixfmt_type* m_pixf;
|
||||||
|
const amask_type* m_mask;
|
||||||
|
|
||||||
|
cover_type* m_span;
|
||||||
|
unsigned m_max_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,312 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_PIXFMT_GRAY8_INCLUDED
|
||||||
|
#define AGG_PIXFMT_GRAY8_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_gray8.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//======================================================pixfmt_gray8_base
|
||||||
|
template<unsigned Step=1, unsigned Offset=0>
|
||||||
|
class pixfmt_gray8_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef gray8 color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
pixfmt_gray8_base(rendering_buffer& rb)
|
||||||
|
: m_rbuf(&rb)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned width() const { return m_rbuf->width(); }
|
||||||
|
unsigned height() const { return m_rbuf->height(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type pixel(int x, int y)
|
||||||
|
{
|
||||||
|
return color_type(m_rbuf->row(y)[x * Step + Offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_pixel(int x, int y, const color_type& c)
|
||||||
|
{
|
||||||
|
m_rbuf->row(y)[x * Step + Offset] = (int8u)c.v;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
int v = *p;
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
*p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_hline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p = (int8u)c.v;
|
||||||
|
p += Step;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_vline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p = (int8u)c.v;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_hline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p = (int8u)c.v;
|
||||||
|
p += Step;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int v = *p;
|
||||||
|
*p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16);
|
||||||
|
p += Step;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_vline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p = (int8u)c.v;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int v = *p;
|
||||||
|
*p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_from(const rendering_buffer& from,
|
||||||
|
int xdst, int ydst,
|
||||||
|
int xsrc, int ysrc,
|
||||||
|
unsigned len)
|
||||||
|
{
|
||||||
|
memmove(m_rbuf->row(ydst) + xdst * Step + Offset,
|
||||||
|
(const void*)(from.row(ysrc) + xsrc * Step + Offset),
|
||||||
|
len * Step);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = int(*covers++) * c.a;
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*p = (int8u)c.v;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int v = *p;
|
||||||
|
*p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += Step;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = int(*covers++) * c.a;
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*p = (int8u)c.v;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int v = *p;
|
||||||
|
*p = (int8u)((((c.v - v) * alpha) + (v << 16)) >> 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*p = (int8u)colors->v;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int v = *p;
|
||||||
|
*p = (int8u)((((colors->v - v) * alpha) + (v << 16)) >> 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += Step;
|
||||||
|
++colors;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x * Step + Offset;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*p = (int8u)colors->v;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int v = *p;
|
||||||
|
*p = (int8u)((((colors->v - v) * alpha) + (v << 16)) >> 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
++colors;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
rendering_buffer* m_rbuf;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef pixfmt_gray8_base<1, 0> pixfmt_gray8; //----pixfmt_gray8
|
||||||
|
|
||||||
|
typedef pixfmt_gray8_base<3, 0> pixfmt_gray8_rgb24r; //----pixfmt_gray8_rgb24r
|
||||||
|
typedef pixfmt_gray8_base<3, 1> pixfmt_gray8_rgb24g; //----pixfmt_gray8_rgb24g
|
||||||
|
typedef pixfmt_gray8_base<3, 2> pixfmt_gray8_rgb24b; //----pixfmt_gray8_rgb24b
|
||||||
|
|
||||||
|
typedef pixfmt_gray8_base<3, 2> pixfmt_gray8_bgr24r; //----pixfmt_gray8_bgr24r
|
||||||
|
typedef pixfmt_gray8_base<3, 1> pixfmt_gray8_bgr24g; //----pixfmt_gray8_bgr24g
|
||||||
|
typedef pixfmt_gray8_base<3, 0> pixfmt_gray8_bgr24b; //----pixfmt_gray8_bgr24b
|
||||||
|
|
||||||
|
typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_rgba32r; //----pixfmt_gray8_rgba32r
|
||||||
|
typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_rgba32g; //----pixfmt_gray8_rgba32g
|
||||||
|
typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_rgba32b; //----pixfmt_gray8_rgba32b
|
||||||
|
typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_rgba32a; //----pixfmt_gray8_rgba32a
|
||||||
|
|
||||||
|
typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_argb32r; //----pixfmt_gray8_argb32r
|
||||||
|
typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_argb32g; //----pixfmt_gray8_argb32g
|
||||||
|
typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_argb32b; //----pixfmt_gray8_argb32b
|
||||||
|
typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_argb32a; //----pixfmt_gray8_argb32a
|
||||||
|
|
||||||
|
typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_bgra32r; //----pixfmt_gray8_bgra32r
|
||||||
|
typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_bgra32g; //----pixfmt_gray8_bgra32g
|
||||||
|
typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_bgra32b; //----pixfmt_gray8_bgra32b
|
||||||
|
typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_bgra32a; //----pixfmt_gray8_bgra32a
|
||||||
|
|
||||||
|
typedef pixfmt_gray8_base<4, 3> pixfmt_gray8_abgr32r; //----pixfmt_gray8_abgr32r
|
||||||
|
typedef pixfmt_gray8_base<4, 2> pixfmt_gray8_abgr32g; //----pixfmt_gray8_abgr32g
|
||||||
|
typedef pixfmt_gray8_base<4, 1> pixfmt_gray8_abgr32b; //----pixfmt_gray8_abgr32b
|
||||||
|
typedef pixfmt_gray8_base<4, 0> pixfmt_gray8_abgr32a; //----pixfmt_gray8_abgr32a
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,355 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_PIXFMT_RGB24_INCLUDED
|
||||||
|
#define AGG_PIXFMT_RGB24_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//=====================================================pixel_formats_rgb24
|
||||||
|
template<class Order> class pixel_formats_rgb24
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
pixel_formats_rgb24(rendering_buffer& rb)
|
||||||
|
: m_rbuf(&rb)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned width() const { return m_rbuf->width(); }
|
||||||
|
unsigned height() const { return m_rbuf->height(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type pixel(int x, int y)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
return color_type(p[Order::R], p[Order::G], p[Order::B]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_pixel(int x, int y, const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int r = p[Order::R];
|
||||||
|
int g = p[Order::G];
|
||||||
|
int b = p[Order::B];
|
||||||
|
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_hline(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_vline(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_hline(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int r = p[Order::R];
|
||||||
|
int g = p[Order::G];
|
||||||
|
int b = p[Order::B];
|
||||||
|
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_vline(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int r = p[Order::R];
|
||||||
|
int g = p[Order::G];
|
||||||
|
int b = p[Order::B];
|
||||||
|
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_from(const rendering_buffer& from,
|
||||||
|
int xdst, int ydst,
|
||||||
|
int xsrc, int ysrc,
|
||||||
|
unsigned len)
|
||||||
|
{
|
||||||
|
memmove(m_rbuf->row(ydst) + xdst * 3,
|
||||||
|
(const void*)(from.row(ysrc) + xsrc * 3), len * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_hspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = int(*covers++) * c.a;
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int r = (int8u)p[Order::R];
|
||||||
|
int g = (int8u)p[Order::G];
|
||||||
|
int b = (int8u)p[Order::B];
|
||||||
|
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_vspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = int(*covers++) * c.a;
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int r = p[Order::R];
|
||||||
|
int g = p[Order::G];
|
||||||
|
int b = p[Order::B];
|
||||||
|
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
const int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)colors->r;
|
||||||
|
p[Order::G] = (int8u)colors->g;
|
||||||
|
p[Order::B] = (int8u)colors->b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int r = p[Order::R];
|
||||||
|
int g = p[Order::G];
|
||||||
|
int b = p[Order::B];
|
||||||
|
p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += 3;
|
||||||
|
++colors;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
const int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)colors->r;
|
||||||
|
p[Order::G] = (int8u)colors->g;
|
||||||
|
p[Order::B] = (int8u)colors->b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int r = p[Order::R];
|
||||||
|
int g = p[Order::G];
|
||||||
|
int b = p[Order::B];
|
||||||
|
p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
++colors;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
rendering_buffer* m_rbuf;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef pixel_formats_rgb24<order_rgb24> pixfmt_rgb24; //----pixfmt_rgb24
|
||||||
|
typedef pixel_formats_rgb24<order_bgr24> pixfmt_bgr24; //----pixfmt_bgr24
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,331 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_PIXFMT_RGB24_GAMMA_INCLUDED
|
||||||
|
#define AGG_PIXFMT_RGB24_GAMMA_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
#include "agg_gamma_lut.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//================================================pixel_formats_rgb24_gamma
|
||||||
|
template<class Order, class Gamma> class pixel_formats_rgb24_gamma
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
typedef Gamma gamma_type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
inline void blend_pix(int8u* p, const color_type& c, int alpha)
|
||||||
|
{
|
||||||
|
int r = m_gamma->dir(p[Order::R]);
|
||||||
|
int g = m_gamma->dir(p[Order::G]);
|
||||||
|
int b = m_gamma->dir(p[Order::B]);
|
||||||
|
p[Order::R] = m_gamma->inv((((m_gamma->dir(c.r) - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = m_gamma->inv((((m_gamma->dir(c.g) - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = m_gamma->inv((((m_gamma->dir(c.b) - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
inline void copy_or_blend_pix(int8u* p, const color_type& c, int cover)
|
||||||
|
{
|
||||||
|
int alpha = int(c.a) * cover;
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
blend_pix(p, c, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
inline void copy_or_blend_pix(int8u* p, const color_type& c)
|
||||||
|
{
|
||||||
|
if(c.a)
|
||||||
|
{
|
||||||
|
if(c.a == 255)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int r = m_gamma->dir(p[Order::R]);
|
||||||
|
int g = m_gamma->dir(p[Order::G]);
|
||||||
|
int b = m_gamma->dir(p[Order::B]);
|
||||||
|
p[Order::R] = m_gamma->inv((((m_gamma->dir(c.r) - r) * c.a) + (r << 8)) >> 8);
|
||||||
|
p[Order::G] = m_gamma->inv((((m_gamma->dir(c.g) - g) * c.a) + (g << 8)) >> 8);
|
||||||
|
p[Order::B] = m_gamma->inv((((m_gamma->dir(c.b) - b) * c.a) + (b << 8)) >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
pixel_formats_rgb24_gamma(rendering_buffer& rb, const gamma_type& g) :
|
||||||
|
m_rbuf(&rb),
|
||||||
|
m_gamma(&g)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void gamma(const gamma_type& g) { m_gamma = &g; }
|
||||||
|
const gamma_type& gamma() const { return *m_gamma; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned width() const { return m_rbuf->width(); }
|
||||||
|
unsigned height() const { return m_rbuf->height(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type pixel(int x, int y)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
return color_type(p[Order::R], p[Order::G], p[Order::B]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_pixel(int x, int y, const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(m_rbuf->row(y) + x + x + x, c, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_hline(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_vline(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_hline(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
blend_pix(p, c, alpha);
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_vline(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
blend_pix(p, c, alpha);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_from(const rendering_buffer& from,
|
||||||
|
int xdst, int ydst,
|
||||||
|
int xsrc, int ysrc,
|
||||||
|
unsigned len)
|
||||||
|
{
|
||||||
|
memmove(m_rbuf->row(ydst) + xdst * 3,
|
||||||
|
(const void*)(from.row(ysrc) + xsrc * 3), len * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_hspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, c, *covers++);
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_vspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, c, *covers++);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
rendering_buffer* m_rbuf;
|
||||||
|
const gamma_type* m_gamma;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------pixfmt_rgb24_gamma
|
||||||
|
template<class Gamma> class pixfmt_rgb24_gamma :
|
||||||
|
public pixel_formats_rgb24_gamma<order_rgb24, Gamma>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) :
|
||||||
|
pixel_formats_rgb24_gamma<order_rgb24, Gamma>(rb, g) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------pixfmt_bgr24_gamma
|
||||||
|
template<class Gamma> class pixfmt_bgr24_gamma :
|
||||||
|
public pixel_formats_rgb24_gamma<order_bgr24, Gamma>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) :
|
||||||
|
pixel_formats_rgb24_gamma<order_bgr24, Gamma>(rb, g) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,292 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_PIXFMT_RGB24_PRE_INCLUDED
|
||||||
|
#define AGG_PIXFMT_RGB24_PRE_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
//==================================================pixel_formats_rgb24_pre
|
||||||
|
template<class Order> class pixel_formats_rgb24_pre
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static inline void copy_pix(int8u* p, const color_type& c)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static inline void blend_pix(int8u* p, const color_type& c,
|
||||||
|
unsigned cover, unsigned alpha)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)((p[Order::R] * alpha + ((c.r * cover) << 8)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((p[Order::G] * alpha + ((c.g * cover) << 8)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((p[Order::B] * alpha + ((c.b * cover) << 8)) >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static inline void copy_or_blend_pix(int8u* p, const color_type& c, unsigned cover)
|
||||||
|
{
|
||||||
|
unsigned alpha = 65535 - cover * c.a;
|
||||||
|
|
||||||
|
if(alpha < 65535)
|
||||||
|
{
|
||||||
|
if(alpha <= 65535-255*255)
|
||||||
|
{
|
||||||
|
copy_pix(p, c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
blend_pix(p, c, cover, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static inline void copy_or_blend_pix(int8u* p, const color_type& c)
|
||||||
|
{
|
||||||
|
unsigned alpha = 255 - c.a;
|
||||||
|
if(alpha < 255)
|
||||||
|
{
|
||||||
|
if(alpha == 0)
|
||||||
|
{
|
||||||
|
copy_pix(p, c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)((p[Order::R] * alpha + (c.r << 8)) >> 8);
|
||||||
|
p[Order::G] = (int8u)((p[Order::G] * alpha + (c.g << 8)) >> 8);
|
||||||
|
p[Order::B] = (int8u)((p[Order::B] * alpha + (c.b << 8)) >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
pixel_formats_rgb24_pre(rendering_buffer& rb)
|
||||||
|
: m_rbuf(&rb)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned width() const { return m_rbuf->width(); }
|
||||||
|
unsigned height() const { return m_rbuf->height(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type pixel(int x, int y)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
return color_type(p[Order::R], p[Order::G], p[Order::B]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_pixel(int x, int y, const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(m_rbuf->row(y) + x + x + x, c, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_hline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_vline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_hline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
unsigned alpha = unsigned(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alpha = 65535 - alpha;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
blend_pix(p, c, cover, alpha);
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_vline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
unsigned alpha = unsigned(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alpha = 65535 - alpha;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
blend_pix(p, c, cover, alpha);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_from(const rendering_buffer& from,
|
||||||
|
int xdst, int ydst,
|
||||||
|
int xsrc, int ysrc,
|
||||||
|
unsigned len)
|
||||||
|
{
|
||||||
|
memmove(m_rbuf->row(ydst) + xdst * 3,
|
||||||
|
(const void*)(from.row(ysrc) + xsrc * 3), len * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, c, *covers++);
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, c, *covers++);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
rendering_buffer* m_rbuf;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef pixel_formats_rgb24_pre<order_rgb24> pixfmt_rgb24_pre; //----pixfmt_rgb24_pre
|
||||||
|
typedef pixel_formats_rgb24_pre<order_bgr24> pixfmt_bgr24_pre; //----pixfmt_bgr24_pre
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,326 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_PIXFMT_RGB555_INCLUDED
|
||||||
|
#define AGG_PIXFMT_RGB555_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//------------------------------------------------------------------rgb555
|
||||||
|
inline int16u rgb555(unsigned r, unsigned g, unsigned b)
|
||||||
|
{
|
||||||
|
return (int16u)(((r & 0xF8) << 7) | ((g & 0xF8) << 2) | (b >> 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===========================================================pixfmt_rgb555
|
||||||
|
class pixfmt_rgb555
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
pixfmt_rgb555(rendering_buffer& rb)
|
||||||
|
: m_rbuf(&rb)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned width() const { return m_rbuf->width(); }
|
||||||
|
unsigned height() const { return m_rbuf->height(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type pixel(int x, int y)
|
||||||
|
{
|
||||||
|
unsigned rgb = ((int16u*)(m_rbuf->row(y)))[x];
|
||||||
|
return color_type((rgb >> 7) & 0xF8,
|
||||||
|
(rgb >> 2) & 0xF8,
|
||||||
|
(rgb << 3) & 0xF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_pixel(int x, int y, const color_type& c)
|
||||||
|
{
|
||||||
|
((int16u*)(m_rbuf->row(y)))[x] = rgb555(c.r, c.g, c.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*p = rgb555(c.r, c.g, c.b);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int16u rgb = *p;
|
||||||
|
int r = (rgb >> 7) & 0xF8;
|
||||||
|
int g = (rgb >> 2) & 0xF8;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*p = (int16u)
|
||||||
|
((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
|
||||||
|
(((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
|
||||||
|
((((c.b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_hline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
|
||||||
|
int16u v = rgb555(c.r, c.g, c.b);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p++ = v;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_vline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 1);
|
||||||
|
int16u v = rgb555(c.r, c.g, c.b);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*(int16u*)p = v;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_hline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
int16u v = rgb555(c.r, c.g, c.b);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p++ = v;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int16u rgb = *p;
|
||||||
|
int r = (rgb >> 7) & 0xF8;
|
||||||
|
int g = (rgb >> 2) & 0xF8;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*p++ = (int16u)
|
||||||
|
((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
|
||||||
|
(((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
|
||||||
|
((((c.b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_vline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 1);
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
int16u v = rgb555(c.r, c.g, c.b);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*(int16u*)p = v;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int16u rgb = *(int16u*)p;
|
||||||
|
int r = (rgb >> 7) & 0xF8;
|
||||||
|
int g = (rgb >> 2) & 0xF8;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*(int16u*)p = (int16u)
|
||||||
|
((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
|
||||||
|
(((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
|
||||||
|
((((c.b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_from(const rendering_buffer& from,
|
||||||
|
int xdst, int ydst,
|
||||||
|
int xsrc, int ysrc,
|
||||||
|
unsigned len)
|
||||||
|
{
|
||||||
|
memmove(m_rbuf->row(ydst) + xdst * 2,
|
||||||
|
(const void*)(from.row(ysrc) + xsrc * 2), len * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = int(*covers++) * c.a;
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*p = rgb555(c.r, c.g, c.b);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int16u rgb = *p;
|
||||||
|
int r = (rgb >> 7) & 0xF8;
|
||||||
|
int g = (rgb >> 2) & 0xF8;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*p = (int16u)
|
||||||
|
((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
|
||||||
|
(((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
|
||||||
|
((((c.b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 1);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = int(*covers++) * c.a;
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*(int16u*)p = rgb555(c.r, c.g, c.b);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int16u rgb = *(int16u*)p;
|
||||||
|
int r = (rgb >> 7) & 0xF8;
|
||||||
|
int g = (rgb >> 2) & 0xF8;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*(int16u*)p = (int16u)
|
||||||
|
((((((c.r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
|
||||||
|
(((((c.g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
|
||||||
|
((((c.b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*(int16u*)p = rgb555(colors->r, colors->g, colors->b);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int16u rgb = *p;
|
||||||
|
int r = (rgb >> 7) & 0xF8;
|
||||||
|
int g = (rgb >> 2) & 0xF8;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*(int16u*)p = (int16u)
|
||||||
|
((((((colors->r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
|
||||||
|
(((((colors->g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
|
||||||
|
((((colors->b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
++colors;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 1);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*(int16u*)p = rgb555(colors->r, colors->g, colors->b);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int16u rgb = *(int16u*)p;
|
||||||
|
int r = (rgb >> 7) & 0xF8;
|
||||||
|
int g = (rgb >> 2) & 0xF8;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*(int16u*)p = (int16u)
|
||||||
|
((((((colors->r - r) * alpha) + (r << 16)) >> 9) & 0x7C00) |
|
||||||
|
(((((colors->g - g) * alpha) + (g << 16)) >> 14) & 0x3E0) |
|
||||||
|
((((colors->b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
++colors;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
rendering_buffer* m_rbuf;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,326 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_PIXFMT_RGB565_INCLUDED
|
||||||
|
#define AGG_PIXFMT_RGB565_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//------------------------------------------------------------------rgb565
|
||||||
|
inline int16u rgb565(unsigned r, unsigned g, unsigned b)
|
||||||
|
{
|
||||||
|
return (int16u)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===========================================================pixfmt_rgb565
|
||||||
|
class pixfmt_rgb565
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
pixfmt_rgb565(rendering_buffer& rb)
|
||||||
|
: m_rbuf(&rb)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned width() const { return m_rbuf->width(); }
|
||||||
|
unsigned height() const { return m_rbuf->height(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type pixel(int x, int y)
|
||||||
|
{
|
||||||
|
unsigned rgb = ((int16u*)(m_rbuf->row(y)))[x];
|
||||||
|
return color_type((rgb >> 8) & 0xF8,
|
||||||
|
(rgb >> 3) & 0xFC,
|
||||||
|
(rgb << 3) & 0xF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_pixel(int x, int y, const color_type& c)
|
||||||
|
{
|
||||||
|
((int16u*)(m_rbuf->row(y)))[x] = rgb565(c.r, c.g, c.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*p = rgb565(c.r, c.g, c.b);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int16u rgb = *p;
|
||||||
|
int r = (rgb >> 8) & 0xF8;
|
||||||
|
int g = (rgb >> 3) & 0xFC;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*p = (int16u)
|
||||||
|
((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
|
||||||
|
(((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
|
||||||
|
((((c.b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_hline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
|
||||||
|
int16u v = rgb565(c.r, c.g, c.b);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p++ = v;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_vline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 1);
|
||||||
|
int16u v = rgb565(c.r, c.g, c.b);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*(int16u*)p = v;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_hline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
int16u v = rgb565(c.r, c.g, c.b);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p++ = v;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int16u rgb = *p;
|
||||||
|
int r = (rgb >> 8) & 0xF8;
|
||||||
|
int g = (rgb >> 3) & 0xFC;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*p++ = (int16u)
|
||||||
|
((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
|
||||||
|
(((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
|
||||||
|
((((c.b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_vline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 1);
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
int16u v = rgb565(c.r, c.g, c.b);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*(int16u*)p = v;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int16u rgb = *(int16u*)p;
|
||||||
|
int r = (rgb >> 8) & 0xF8;
|
||||||
|
int g = (rgb >> 3) & 0xFC;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*(int16u*)p = (int16u)
|
||||||
|
((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
|
||||||
|
(((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
|
||||||
|
((((c.b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_from(const rendering_buffer& from,
|
||||||
|
int xdst, int ydst,
|
||||||
|
int xsrc, int ysrc,
|
||||||
|
unsigned len)
|
||||||
|
{
|
||||||
|
memmove(m_rbuf->row(ydst) + xdst * 2,
|
||||||
|
(const void*)(from.row(ysrc) + xsrc * 2), len * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = int(*covers++) * c.a;
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*p = rgb565(c.r, c.g, c.b);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int16u rgb = *p;
|
||||||
|
int r = (rgb >> 8) & 0xF8;
|
||||||
|
int g = (rgb >> 3) & 0xFC;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*p = (int16u)
|
||||||
|
((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
|
||||||
|
(((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
|
||||||
|
((((c.b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 1);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = int(*covers++) * c.a;
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*(int16u*)p = rgb565(c.r, c.g, c.b);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int16u rgb = *(int16u*)p;
|
||||||
|
int r = (rgb >> 8) & 0xF8;
|
||||||
|
int g = (rgb >> 3) & 0xFC;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*(int16u*)p = (int16u)
|
||||||
|
((((((c.r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
|
||||||
|
(((((c.g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
|
||||||
|
((((c.b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int16u* p = (int16u*)(m_rbuf->row(y)) + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*(int16u*)p = rgb565(colors->r, colors->g, colors->b);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int16u rgb = *p;
|
||||||
|
int r = (rgb >> 8) & 0xF8;
|
||||||
|
int g = (rgb >> 3) & 0xFC;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*p = (int16u)
|
||||||
|
((((((colors->r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
|
||||||
|
(((((colors->g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
|
||||||
|
((((colors->b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++p;
|
||||||
|
++colors;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 1);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
*(int16u*)p = rgb565(colors->r, colors->g, colors->b);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int16u rgb = *(int16u*)p;
|
||||||
|
int r = (rgb >> 8) & 0xF8;
|
||||||
|
int g = (rgb >> 3) & 0xFC;
|
||||||
|
int b = (rgb << 3) & 0xF8;
|
||||||
|
*(int16u*)p = (int16u)
|
||||||
|
((((((colors->r - r) * alpha) + (r << 16)) >> 8) & 0xF800) |
|
||||||
|
(((((colors->g - g) * alpha) + (g << 16)) >> 13) & 0x7E0) |
|
||||||
|
((((colors->b - b) * alpha) + (b << 16)) >> 19));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
++colors;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
rendering_buffer* m_rbuf;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,371 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_PIXFMT_RGBA32_INCLUDED
|
||||||
|
#define AGG_PIXFMT_RGBA32_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//====================================================pixel_formats_rgba32
|
||||||
|
template<class Order> class pixel_formats_rgba32
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
pixel_formats_rgba32(rendering_buffer& rb)
|
||||||
|
: m_rbuf(&rb)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned width() const { return m_rbuf->width(); }
|
||||||
|
unsigned height() const { return m_rbuf->height(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type pixel(int x, int y)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_pixel(int x, int y, const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p[Order::A] = (int8u)c.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
int alpha = int(cover) * int(c.a);
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p[Order::A] = (int8u)c.a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int r = p[Order::R];
|
||||||
|
int g = p[Order::G];
|
||||||
|
int b = p[Order::B];
|
||||||
|
int a = p[Order::A];
|
||||||
|
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_hline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int32u v;
|
||||||
|
int8u* p8 = (int8u*)&v;
|
||||||
|
p8[Order::R] = (int8u)c.r;
|
||||||
|
p8[Order::G] = (int8u)c.g;
|
||||||
|
p8[Order::B] = (int8u)c.b;
|
||||||
|
p8[Order::A] = (int8u)c.a;
|
||||||
|
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p32++ = v;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_vline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int32u v;
|
||||||
|
int8u* p8 = (int8u*)&v;
|
||||||
|
p8[Order::R] = (int8u)c.r;
|
||||||
|
p8[Order::G] = (int8u)c.g;
|
||||||
|
p8[Order::B] = (int8u)c.b;
|
||||||
|
p8[Order::A] = (int8u)c.a;
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*(int32u*)p = v;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_hline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int alpha = int(cover) * int(c.a);
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
int32u v;
|
||||||
|
int8u* p8 = (int8u*)&v;
|
||||||
|
p8[Order::R] = (int8u)c.r;
|
||||||
|
p8[Order::G] = (int8u)c.g;
|
||||||
|
p8[Order::B] = (int8u)c.b;
|
||||||
|
p8[Order::A] = (int8u)c.a;
|
||||||
|
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p32++ = v;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int r = p[Order::R];
|
||||||
|
int g = p[Order::G];
|
||||||
|
int b = p[Order::B];
|
||||||
|
int a = p[Order::A];
|
||||||
|
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_vline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
int alpha = int(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
int32u v;
|
||||||
|
int8u* p8 = (int8u*)&v;
|
||||||
|
p8[Order::R] = (int8u)c.r;
|
||||||
|
p8[Order::G] = (int8u)c.g;
|
||||||
|
p8[Order::B] = (int8u)c.b;
|
||||||
|
p8[Order::A] = (int8u)c.a;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*(int32u*)p = v;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int r = p[Order::R];
|
||||||
|
int g = p[Order::G];
|
||||||
|
int b = p[Order::B];
|
||||||
|
int a = p[Order::A];
|
||||||
|
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_from(const rendering_buffer& from,
|
||||||
|
int xdst, int ydst,
|
||||||
|
int xsrc, int ysrc,
|
||||||
|
unsigned len)
|
||||||
|
{
|
||||||
|
memmove(m_rbuf->row(ydst) + xdst * 4,
|
||||||
|
(const void*)(from.row(ysrc) + xsrc * 4), len * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = int(*covers++) * c.a;
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p[Order::A] = (int8u)c.a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int r = p[Order::R];
|
||||||
|
int g = p[Order::G];
|
||||||
|
int b = p[Order::B];
|
||||||
|
int a = p[Order::A];
|
||||||
|
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = int(*covers++) * c.a;
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p[Order::A] = (int8u)c.a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int r = p[Order::R];
|
||||||
|
int g = p[Order::G];
|
||||||
|
int b = p[Order::B];
|
||||||
|
int a = p[Order::A];
|
||||||
|
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)colors->r;
|
||||||
|
p[Order::G] = (int8u)colors->g;
|
||||||
|
p[Order::B] = (int8u)colors->b;
|
||||||
|
p[Order::A] = (int8u)colors->a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int r = p[Order::R];
|
||||||
|
int g = p[Order::G];
|
||||||
|
int b = p[Order::B];
|
||||||
|
int a = p[Order::A];
|
||||||
|
p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += 4;
|
||||||
|
++colors;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)colors->r;
|
||||||
|
p[Order::G] = (int8u)colors->g;
|
||||||
|
p[Order::B] = (int8u)colors->b;
|
||||||
|
p[Order::A] = (int8u)colors->a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int r = p[Order::R];
|
||||||
|
int g = p[Order::G];
|
||||||
|
int b = p[Order::B];
|
||||||
|
int a = p[Order::A];
|
||||||
|
p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16);
|
||||||
|
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
++colors;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
rendering_buffer* m_rbuf;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef pixel_formats_rgba32<order_rgba32> pixfmt_rgba32; //----pixfmt_rgba32
|
||||||
|
typedef pixel_formats_rgba32<order_argb32> pixfmt_argb32; //----pixfmt_argb32
|
||||||
|
typedef pixel_formats_rgba32<order_abgr32> pixfmt_abgr32; //----pixfmt_abgr32
|
||||||
|
typedef pixel_formats_rgba32<order_bgra32> pixfmt_bgra32; //----pixfmt_bgra32
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_PIXFMT_RGBA32_PLAIN_INCLUDED
|
||||||
|
#define AGG_PIXFMT_RGBA32_PLAIN_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
//===============================================pixel_formats_rgba32_plain
|
||||||
|
template<class Order> class pixel_formats_rgba32_plain
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static inline void copy_pix(int8u* p, const color_type& c)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p[Order::A] = (int8u)c.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static inline void blend_pix(int8u* p, const color_type& c, unsigned alpha)
|
||||||
|
{
|
||||||
|
int a = p[Order::A];
|
||||||
|
int r = p[Order::R] * a;
|
||||||
|
int g = p[Order::G] * a;
|
||||||
|
int b = p[Order::B] * a;
|
||||||
|
a = ((alpha << 8) + (a << 16)) - alpha * a;
|
||||||
|
p[Order::A] = (int8u)(a >> 16);
|
||||||
|
p[Order::R] = (int8u)((((((c.r << 8) - r) * alpha) + (r << 16)) / a));
|
||||||
|
p[Order::G] = (int8u)((((((c.g << 8) - g) * alpha) + (g << 16)) / a));
|
||||||
|
p[Order::B] = (int8u)((((((c.b << 8) - b) * alpha) + (b << 16)) / a));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static inline void copy_or_blend_pix(int8u* p, const color_type& c, unsigned cover)
|
||||||
|
{
|
||||||
|
unsigned alpha = cover * c.a;
|
||||||
|
// For testing
|
||||||
|
//color_type c2 = c;
|
||||||
|
//c2.a = alpha >> 8;
|
||||||
|
//copy_or_blend_pix(p, c2);
|
||||||
|
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
copy_pix(p, c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
blend_pix(p, c, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static inline void copy_or_blend_pix(int8u* p, const color_type& c)
|
||||||
|
{
|
||||||
|
unsigned alpha = c.a;
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255)
|
||||||
|
{
|
||||||
|
copy_pix(p, c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int a = p[Order::A];
|
||||||
|
int r = p[Order::R] * a;
|
||||||
|
int g = p[Order::G] * a;
|
||||||
|
int b = p[Order::B] * a;
|
||||||
|
a = ((alpha + a) << 8) - alpha * a;
|
||||||
|
p[Order::A] = (int8u)(a >> 8);
|
||||||
|
p[Order::R] = (int8u)((((((c.r << 8) - r) * alpha) + (r << 8)) / a));
|
||||||
|
p[Order::G] = (int8u)((((((c.g << 8) - g) * alpha) + (g << 8)) / a));
|
||||||
|
p[Order::B] = (int8u)((((((c.b << 8) - b) * alpha) + (b << 8)) / a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
pixel_formats_rgba32_plain(rendering_buffer& rb)
|
||||||
|
: m_rbuf(&rb)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned width() const { return m_rbuf->width(); }
|
||||||
|
unsigned height() const { return m_rbuf->height(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type pixel(int x, int y)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_pixel(int x, int y, const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p[Order::A] = (int8u)c.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(m_rbuf->row(y) + (x << 2), c, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_hline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int32u v;
|
||||||
|
copy_pix((int8u*)&v, c);
|
||||||
|
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p32++ = v;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_vline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int32u v;
|
||||||
|
copy_pix((int8u*)&v, c);
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*(int32u*)p = v;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_hline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
unsigned alpha = unsigned(cover) * c.a;
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
int32u v;
|
||||||
|
copy_pix((int8u*)&v, c);
|
||||||
|
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p32++ = v;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
blend_pix(p, c, alpha);
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_vline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
unsigned alpha = unsigned(cover) * c.a;
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
unsigned alpha = unsigned(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
int32u v;
|
||||||
|
copy_pix((int8u*)&v, c);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*(int32u*)p = v;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
blend_pix(p, c, alpha);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_from(const rendering_buffer& from,
|
||||||
|
int xdst, int ydst,
|
||||||
|
int xsrc, int ysrc,
|
||||||
|
unsigned len)
|
||||||
|
{
|
||||||
|
memmove(m_rbuf->row(ydst) + xdst * 4,
|
||||||
|
(const void*)(from.row(ysrc) + xsrc * 4), len * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, c, *covers++);
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, c, *covers++);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
rendering_buffer* m_rbuf;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef pixel_formats_rgba32_plain<order_rgba32> pixfmt_rgba32_plain; //----pixfmt_rgba32_plain
|
||||||
|
typedef pixel_formats_rgba32_plain<order_argb32> pixfmt_argb32_plain; //----pixfmt_argb32_plain
|
||||||
|
typedef pixel_formats_rgba32_plain<order_abgr32> pixfmt_abgr32_plain; //----pixfmt_abgr32_plain
|
||||||
|
typedef pixel_formats_rgba32_plain<order_bgra32> pixfmt_bgra32_plain; //----pixfmt_bgra32_plain
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,297 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_PIXFMT_RGBA32_PRE_INCLUDED
|
||||||
|
#define AGG_PIXFMT_RGBA32_PRE_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
//=================================================pixel_formats_rgba32_pre
|
||||||
|
template<class Order> class pixel_formats_rgba32_pre
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static inline void copy_pix(int8u* p, const color_type& c)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p[Order::A] = (int8u)c.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static inline void blend_pix(int8u* p, const color_type& c,
|
||||||
|
unsigned cover, unsigned alpha)
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)((p[Order::R] * alpha + ((c.r * cover) << 8)) >> 16);
|
||||||
|
p[Order::G] = (int8u)((p[Order::G] * alpha + ((c.g * cover) << 8)) >> 16);
|
||||||
|
p[Order::B] = (int8u)((p[Order::B] * alpha + ((c.b * cover) << 8)) >> 16);
|
||||||
|
p[Order::A] = (int8u)(255 - ((alpha * (255 - p[Order::A])) >> 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static inline void copy_or_blend_pix(int8u* p, const color_type& c, unsigned cover)
|
||||||
|
{
|
||||||
|
unsigned alpha = 65535 - cover * c.a;
|
||||||
|
|
||||||
|
if(alpha < 65535)
|
||||||
|
{
|
||||||
|
if(alpha <= 65535-255*255)
|
||||||
|
{
|
||||||
|
copy_pix(p, c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
blend_pix(p, c, cover, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static inline void copy_or_blend_pix(int8u* p, const color_type& c)
|
||||||
|
{
|
||||||
|
unsigned alpha = 255 - c.a;
|
||||||
|
if(alpha < 255)
|
||||||
|
{
|
||||||
|
if(alpha == 0)
|
||||||
|
{
|
||||||
|
copy_pix(p, c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p[Order::R] = (int8u)((p[Order::R] * alpha + (c.r << 8)) >> 8);
|
||||||
|
p[Order::G] = (int8u)((p[Order::G] * alpha + (c.g << 8)) >> 8);
|
||||||
|
p[Order::B] = (int8u)((p[Order::B] * alpha + (c.b << 8)) >> 8);
|
||||||
|
p[Order::A] = (int8u)(255 - ((alpha * (255 - p[Order::A])) >> 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
pixel_formats_rgba32_pre(rendering_buffer& rb)
|
||||||
|
: m_rbuf(&rb)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned width() const { return m_rbuf->width(); }
|
||||||
|
unsigned height() const { return m_rbuf->height(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type pixel(int x, int y)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_pixel(int x, int y, const color_type& c)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
p[Order::R] = (int8u)c.r;
|
||||||
|
p[Order::G] = (int8u)c.g;
|
||||||
|
p[Order::B] = (int8u)c.b;
|
||||||
|
p[Order::A] = (int8u)c.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(m_rbuf->row(y) + (x << 2), c, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_hline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int32u v;
|
||||||
|
copy_pix((int8u*)&v, c);
|
||||||
|
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p32++ = v;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_vline(int x, int y, unsigned len, const color_type& c)
|
||||||
|
{
|
||||||
|
int32u v;
|
||||||
|
copy_pix((int8u*)&v, c);
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*(int32u*)p = v;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_hline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
unsigned alpha = unsigned(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
int32u v;
|
||||||
|
copy_pix((int8u*)&v, c);
|
||||||
|
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*p32++ = v;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
alpha = 65535 - alpha;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
blend_pix(p, c, cover, alpha);
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_vline(int x, int y, unsigned len,
|
||||||
|
const color_type& c, int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
unsigned alpha = unsigned(cover) * c.a;
|
||||||
|
if(alpha == 255*255)
|
||||||
|
{
|
||||||
|
int32u v;
|
||||||
|
copy_pix((int8u*)&v, c);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*(int32u*)p = v;
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alpha = 65535 - alpha;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
blend_pix(p, c, cover, alpha);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_from(const rendering_buffer& from,
|
||||||
|
int xdst, int ydst,
|
||||||
|
int xsrc, int ysrc,
|
||||||
|
unsigned len)
|
||||||
|
{
|
||||||
|
memmove(m_rbuf->row(ydst) + xdst * 4,
|
||||||
|
(const void*)(from.row(ysrc) + xsrc * 4), len * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, c, *covers++);
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type& c, const int8u* covers)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, c, *covers++);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan(int x, int y, unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const int8u* covers,
|
||||||
|
int8u cover)
|
||||||
|
{
|
||||||
|
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover);
|
||||||
|
p += m_rbuf->stride();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
rendering_buffer* m_rbuf;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef pixel_formats_rgba32_pre<order_rgba32> pixfmt_rgba32_pre; //----pixfmt_rgba32_pre
|
||||||
|
typedef pixel_formats_rgba32_pre<order_argb32> pixfmt_argb32_pre; //----pixfmt_argb32_pre
|
||||||
|
typedef pixel_formats_rgba32_pre<order_abgr32> pixfmt_abgr32_pre; //----pixfmt_abgr32_pre
|
||||||
|
typedef pixel_formats_rgba32_pre<order_bgra32> pixfmt_bgra32_pre; //----pixfmt_bgra32_pre
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_RASTERIZER_OUTLINE_INCLUDED
|
||||||
|
#define AGG_RASTERIZER_OUTLINE_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//======================================================rasterizer_outline
|
||||||
|
template<class Renderer> class rasterizer_outline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
rasterizer_outline(Renderer& ren) : m_ren(&ren), m_start_x(0), m_start_y(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void move_to(int x, int y)
|
||||||
|
{
|
||||||
|
m_ren->move_to(m_start_x = x, m_start_y = y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void line_to(int x, int y)
|
||||||
|
{
|
||||||
|
m_ren->line_to(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void move_to_d(double x, double y)
|
||||||
|
{
|
||||||
|
move_to(m_ren->coord(x), m_ren->coord(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void line_to_d(double x, double y)
|
||||||
|
{
|
||||||
|
line_to(m_ren->coord(x), m_ren->coord(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
line_to(m_start_x, m_start_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void add_vertex(double x, double y, unsigned cmd)
|
||||||
|
{
|
||||||
|
if(is_move_to(cmd))
|
||||||
|
{
|
||||||
|
move_to_d(x, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(is_end_poly(cmd))
|
||||||
|
{
|
||||||
|
if(is_closed(cmd)) close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line_to_d(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class VertexSource>
|
||||||
|
void add_path(VertexSource& vs, unsigned id=0)
|
||||||
|
{
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
|
||||||
|
unsigned cmd;
|
||||||
|
vs.rewind(id);
|
||||||
|
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||||
|
{
|
||||||
|
add_vertex(x, y, cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class VertexSource, class ColorStorage, class PathId>
|
||||||
|
void render_all_paths(VertexSource& vs,
|
||||||
|
const ColorStorage& colors,
|
||||||
|
const PathId& id,
|
||||||
|
unsigned num_paths)
|
||||||
|
{
|
||||||
|
for(unsigned i = 0; i < num_paths; i++)
|
||||||
|
{
|
||||||
|
m_ren->line_color(colors[i]);
|
||||||
|
add_path(vs, id[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class Ctrl> void render_ctrl(Ctrl& c)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < c.num_paths(); i++)
|
||||||
|
{
|
||||||
|
m_ren->line_color(c.color(i));
|
||||||
|
add_path(c, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
Renderer* m_ren;
|
||||||
|
int m_start_x;
|
||||||
|
int m_start_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,513 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_RASTERIZER_OUTLINE_AA_INCLUDED
|
||||||
|
#define AGG_RASTERIZER_OUTLINE_AA_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_line_aa_basics.h"
|
||||||
|
#include "agg_vertex_sequence.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
inline bool cmp_dist_start(int d) { return d > 0; }
|
||||||
|
inline bool cmp_dist_end(int d) { return d <= 0; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------line_aa_vertex
|
||||||
|
// Vertex (x, y) with the distance to the next one. The last vertex has
|
||||||
|
// the distance between the last and the first points
|
||||||
|
struct line_aa_vertex
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
line_aa_vertex() {}
|
||||||
|
line_aa_vertex(int x_, int y_) :
|
||||||
|
x(x_),
|
||||||
|
y(y_),
|
||||||
|
len(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator () (const line_aa_vertex& val)
|
||||||
|
{
|
||||||
|
double dx = val.x - x;
|
||||||
|
double dy = val.y - y;
|
||||||
|
return (len = int(sqrt(dx * dx + dy * dy))) >
|
||||||
|
(line_subpixel_size + line_subpixel_size / 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=======================================================rasterizer_outline_aa
|
||||||
|
template<class Renderer> class rasterizer_outline_aa
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
struct draw_vars
|
||||||
|
{
|
||||||
|
unsigned idx;
|
||||||
|
int x1, y1, x2, y2;
|
||||||
|
line_parameters curr, next;
|
||||||
|
int lcurr, lnext;
|
||||||
|
int xb1, yb1, xb2, yb2;
|
||||||
|
unsigned flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
void draw(draw_vars& dv, unsigned start, unsigned end);
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef line_aa_vertex vertex_type;
|
||||||
|
typedef vertex_sequence<vertex_type, 6> vertex_storage_type;
|
||||||
|
|
||||||
|
rasterizer_outline_aa(Renderer& ren) :
|
||||||
|
m_ren(ren),
|
||||||
|
m_accurate_join(m_ren.accurate_join_only()),
|
||||||
|
m_round_cap(false),
|
||||||
|
m_start_x(0),
|
||||||
|
m_start_y(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
void accurate_join(bool v)
|
||||||
|
{
|
||||||
|
m_accurate_join = m_ren.accurate_join_only() ? true : v;
|
||||||
|
}
|
||||||
|
bool accurate_join() const { return m_accurate_join; }
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
void round_cap(bool v) { m_round_cap = v; }
|
||||||
|
bool round_cap() const { return m_round_cap; }
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
void move_to(int x, int y)
|
||||||
|
{
|
||||||
|
m_src_vertices.modify_last(vertex_type(m_start_x = x, m_start_y = y));
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
void line_to(int x, int y)
|
||||||
|
{
|
||||||
|
m_src_vertices.add(vertex_type(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
void move_to_d(double x, double y)
|
||||||
|
{
|
||||||
|
move_to(line_coord(x), line_coord(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
void line_to_d(double x, double y)
|
||||||
|
{
|
||||||
|
line_to(line_coord(x), line_coord(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
void render(bool close_polygon);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
void add_vertex(double x, double y, unsigned cmd)
|
||||||
|
{
|
||||||
|
if(is_move_to(cmd))
|
||||||
|
{
|
||||||
|
render(false);
|
||||||
|
move_to_d(x, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(is_end_poly(cmd))
|
||||||
|
{
|
||||||
|
render(is_closed(cmd));
|
||||||
|
if(is_closed(cmd)) move_to(m_start_x, m_start_y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line_to_d(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VertexSource>
|
||||||
|
void add_path(VertexSource& vs, unsigned id=0)
|
||||||
|
{
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
|
||||||
|
unsigned cmd;
|
||||||
|
vs.rewind(id);
|
||||||
|
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||||
|
{
|
||||||
|
add_vertex(x, y, cmd);
|
||||||
|
}
|
||||||
|
render(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class VertexSource, class ColorStorage, class PathId>
|
||||||
|
void render_all_paths(VertexSource& vs,
|
||||||
|
const ColorStorage& colors,
|
||||||
|
const PathId& id,
|
||||||
|
unsigned num_paths)
|
||||||
|
{
|
||||||
|
for(unsigned i = 0; i < num_paths; i++)
|
||||||
|
{
|
||||||
|
m_ren.color(colors[i]);
|
||||||
|
add_path(vs, id[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class Ctrl> void render_ctrl(Ctrl& c)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < c.num_paths(); i++)
|
||||||
|
{
|
||||||
|
m_ren.color(c.color(i));
|
||||||
|
add_path(c, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
rasterizer_outline_aa(const rasterizer_outline_aa<Renderer>&);
|
||||||
|
const rasterizer_outline_aa<Renderer>& operator =
|
||||||
|
(const rasterizer_outline_aa<Renderer>&);
|
||||||
|
|
||||||
|
Renderer& m_ren;
|
||||||
|
vertex_storage_type m_src_vertices;
|
||||||
|
bool m_accurate_join;
|
||||||
|
bool m_round_cap;
|
||||||
|
int m_start_x;
|
||||||
|
int m_start_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
template<class Renderer>
|
||||||
|
void rasterizer_outline_aa<Renderer>::draw(draw_vars& dv, unsigned start, unsigned end)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
const vertex_storage_type::value_type* v;
|
||||||
|
|
||||||
|
for(i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
switch(dv.flags)
|
||||||
|
{
|
||||||
|
case 0: m_ren.line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break;
|
||||||
|
case 1: m_ren.line2(dv.curr, dv.xb2, dv.yb2); break;
|
||||||
|
case 2: m_ren.line1(dv.curr, dv.xb1, dv.yb1); break;
|
||||||
|
case 3: m_ren.line0(dv.curr); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dv.x1 = dv.x2;
|
||||||
|
dv.y1 = dv.y2;
|
||||||
|
dv.lcurr = dv.lnext;
|
||||||
|
dv.lnext = m_src_vertices[dv.idx].len;
|
||||||
|
|
||||||
|
++dv.idx;
|
||||||
|
if(dv.idx >= m_src_vertices.size()) dv.idx = 0;
|
||||||
|
|
||||||
|
v = &m_src_vertices[dv.idx];
|
||||||
|
dv.x2 = v->x;
|
||||||
|
dv.y2 = v->y;
|
||||||
|
|
||||||
|
dv.curr = dv.next;
|
||||||
|
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
|
||||||
|
dv.xb1 = dv.xb2;
|
||||||
|
dv.yb1 = dv.yb2;
|
||||||
|
|
||||||
|
if(m_accurate_join)
|
||||||
|
{
|
||||||
|
dv.flags = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dv.flags >>= 1;
|
||||||
|
dv.flags |= ((dv.curr.diagonal_quadrant() ==
|
||||||
|
dv.next.diagonal_quadrant()) << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((dv.flags & 2) == 0)
|
||||||
|
{
|
||||||
|
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
template<class Renderer>
|
||||||
|
void rasterizer_outline_aa<Renderer>::render(bool close_polygon)
|
||||||
|
{
|
||||||
|
m_src_vertices.close(close_polygon);
|
||||||
|
draw_vars dv;
|
||||||
|
const vertex_storage_type::value_type* v;
|
||||||
|
int x1;
|
||||||
|
int y1;
|
||||||
|
int x2;
|
||||||
|
int y2;
|
||||||
|
int lprev;
|
||||||
|
|
||||||
|
if(close_polygon)
|
||||||
|
{
|
||||||
|
if(m_src_vertices.size() >= 3)
|
||||||
|
{
|
||||||
|
dv.idx = 2;
|
||||||
|
|
||||||
|
v = &m_src_vertices[m_src_vertices.size() - 1];
|
||||||
|
x1 = v->x;
|
||||||
|
y1 = v->y;
|
||||||
|
lprev = v->len;
|
||||||
|
|
||||||
|
v = &m_src_vertices[0];
|
||||||
|
x2 = v->x;
|
||||||
|
y2 = v->y;
|
||||||
|
dv.lcurr = v->len;
|
||||||
|
line_parameters prev(x1, y1, x2, y2, lprev);
|
||||||
|
|
||||||
|
v = &m_src_vertices[1];
|
||||||
|
dv.x1 = v->x;
|
||||||
|
dv.y1 = v->y;
|
||||||
|
dv.lnext = v->len;
|
||||||
|
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
|
||||||
|
|
||||||
|
v = &m_src_vertices[dv.idx];
|
||||||
|
dv.x2 = v->x;
|
||||||
|
dv.y2 = v->y;
|
||||||
|
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
|
||||||
|
|
||||||
|
dv.xb1 = 0;
|
||||||
|
dv.yb1 = 0;
|
||||||
|
dv.xb2 = 0;
|
||||||
|
dv.yb2 = 0;
|
||||||
|
|
||||||
|
if(m_accurate_join)
|
||||||
|
{
|
||||||
|
dv.flags = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dv.flags =
|
||||||
|
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
|
||||||
|
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((dv.flags & 1) == 0)
|
||||||
|
{
|
||||||
|
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((dv.flags & 2) == 0)
|
||||||
|
{
|
||||||
|
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
|
||||||
|
}
|
||||||
|
draw(dv, 0, m_src_vertices.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(m_src_vertices.size())
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
v = &m_src_vertices[0];
|
||||||
|
x1 = v->x;
|
||||||
|
y1 = v->y;
|
||||||
|
lprev = v->len;
|
||||||
|
v = &m_src_vertices[1];
|
||||||
|
x2 = v->x;
|
||||||
|
y2 = v->y;
|
||||||
|
line_parameters lp(x1, y1, x2, y2, lprev);
|
||||||
|
if(m_round_cap)
|
||||||
|
{
|
||||||
|
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||||
|
}
|
||||||
|
m_ren.line3(lp,
|
||||||
|
x1 + (y2 - y1),
|
||||||
|
y1 - (x2 - x1),
|
||||||
|
x2 + (y2 - y1),
|
||||||
|
y2 - (x2 - x1));
|
||||||
|
if(m_round_cap)
|
||||||
|
{
|
||||||
|
m_ren.semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
int x3, y3;
|
||||||
|
int lnext;
|
||||||
|
v = &m_src_vertices[0];
|
||||||
|
x1 = v->x;
|
||||||
|
y1 = v->y;
|
||||||
|
lprev = v->len;
|
||||||
|
v = &m_src_vertices[1];
|
||||||
|
x2 = v->x;
|
||||||
|
y2 = v->y;
|
||||||
|
lnext = v->len;
|
||||||
|
v = &m_src_vertices[2];
|
||||||
|
x3 = v->x;
|
||||||
|
y3 = v->y;
|
||||||
|
line_parameters lp1(x1, y1, x2, y2, lprev);
|
||||||
|
line_parameters lp2(x2, y2, x3, y3, lnext);
|
||||||
|
bisectrix(lp1, lp2, &dv.xb1, &dv.yb1);
|
||||||
|
|
||||||
|
if(m_round_cap)
|
||||||
|
{
|
||||||
|
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||||
|
}
|
||||||
|
m_ren.line3(lp1,
|
||||||
|
x1 + (y2 - y1),
|
||||||
|
y1 - (x2 - x1),
|
||||||
|
dv.xb1,
|
||||||
|
dv.yb1);
|
||||||
|
|
||||||
|
m_ren.line3(lp2,
|
||||||
|
dv.xb1,
|
||||||
|
dv.yb1,
|
||||||
|
x3 + (y3 - y2),
|
||||||
|
y3 - (x3 - x2));
|
||||||
|
if(m_round_cap)
|
||||||
|
{
|
||||||
|
m_ren.semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
dv.idx = 3;
|
||||||
|
|
||||||
|
v = &m_src_vertices[0];
|
||||||
|
x1 = v->x;
|
||||||
|
y1 = v->y;
|
||||||
|
lprev = v->len;
|
||||||
|
|
||||||
|
v = &m_src_vertices[1];
|
||||||
|
x2 = v->x;
|
||||||
|
y2 = v->y;
|
||||||
|
dv.lcurr = v->len;
|
||||||
|
line_parameters prev(x1, y1, x2, y2, lprev);
|
||||||
|
|
||||||
|
v = &m_src_vertices[2];
|
||||||
|
dv.x1 = v->x;
|
||||||
|
dv.y1 = v->y;
|
||||||
|
dv.lnext = v->len;
|
||||||
|
dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr);
|
||||||
|
|
||||||
|
v = &m_src_vertices[dv.idx];
|
||||||
|
dv.x2 = v->x;
|
||||||
|
dv.y2 = v->y;
|
||||||
|
dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext);
|
||||||
|
|
||||||
|
dv.xb1 = 0;
|
||||||
|
dv.yb1 = 0;
|
||||||
|
dv.xb2 = 0;
|
||||||
|
dv.yb2 = 0;
|
||||||
|
|
||||||
|
if(m_accurate_join)
|
||||||
|
{
|
||||||
|
dv.flags = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dv.flags =
|
||||||
|
(prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) |
|
||||||
|
((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((dv.flags & 1) == 0)
|
||||||
|
{
|
||||||
|
bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1);
|
||||||
|
m_ren.line3(prev,
|
||||||
|
x1 + (y2 - y1),
|
||||||
|
y1 - (x2 - x1),
|
||||||
|
dv.xb1,
|
||||||
|
dv.yb1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ren.line1(prev,
|
||||||
|
x1 + (y2 - y1),
|
||||||
|
y1 - (x2 - x1));
|
||||||
|
}
|
||||||
|
if(m_round_cap)
|
||||||
|
{
|
||||||
|
m_ren.semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1));
|
||||||
|
}
|
||||||
|
if((dv.flags & 2) == 0)
|
||||||
|
{
|
||||||
|
bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(dv, 1, m_src_vertices.size() - 2);
|
||||||
|
|
||||||
|
if((dv.flags & 1) == 0)
|
||||||
|
{
|
||||||
|
m_ren.line3(dv.curr,
|
||||||
|
dv.xb1,
|
||||||
|
dv.yb1,
|
||||||
|
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||||
|
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ren.line2(dv.curr,
|
||||||
|
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||||
|
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||||
|
}
|
||||||
|
if(m_round_cap)
|
||||||
|
{
|
||||||
|
m_ren.semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2,
|
||||||
|
dv.curr.x2 + (dv.curr.y2 - dv.curr.y1),
|
||||||
|
dv.curr.y2 - (dv.curr.x2 - dv.curr.x1));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_src_vertices.remove_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,771 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
// The author gratefully acknowleges the support of David Turner,
|
||||||
|
// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
|
||||||
|
// libray - in producing this work. See http://www.freetype.org for details.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Class rasterizer_scanline_aa
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED
|
||||||
|
#define AGG_RASTERIZER_SCANLINE_AA_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_math.h"
|
||||||
|
#include "agg_gamma_functions.h"
|
||||||
|
#include "agg_clip_liang_barsky.h"
|
||||||
|
#include "agg_render_scanlines.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// These constants determine the subpixel accuracy, to be more precise,
|
||||||
|
// the number of bits of the fractional part of the coordinates.
|
||||||
|
// The possible coordinate capacity in bits can be calculated by formula:
|
||||||
|
// sizeof(int) * 8 - poly_base_shift * 2, i.e, for 32-bit integers and
|
||||||
|
// 8-bits fractional part the capacity is 16 bits or [-32768...32767].
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
poly_base_shift = 8, //----poly_base_shift
|
||||||
|
poly_base_size = 1 << poly_base_shift, //----poly_base_size
|
||||||
|
poly_base_mask = poly_base_size - 1 //----poly_base_mask
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------------------------------------poly_coord
|
||||||
|
inline int poly_coord(double c)
|
||||||
|
{
|
||||||
|
return int(c * poly_base_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------cell_aa
|
||||||
|
// A pixel cell. There're no constructors defined and it was done
|
||||||
|
// intentionally in order to avoid extra overhead when allocating an
|
||||||
|
// array of cells.
|
||||||
|
struct cell_aa
|
||||||
|
{
|
||||||
|
int16 x;
|
||||||
|
int16 y;
|
||||||
|
int packed_coord;
|
||||||
|
int cover;
|
||||||
|
int area;
|
||||||
|
|
||||||
|
void set(int x, int y, int c, int a);
|
||||||
|
void set_coord(int x, int y);
|
||||||
|
void set_cover(int c, int a);
|
||||||
|
void add_cover(int c, int a);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------outline_aa
|
||||||
|
// An internal class that implements the main rasterization algorithm.
|
||||||
|
// Used in the rasterizer. Should not be used direcly.
|
||||||
|
class outline_aa
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
cell_block_shift = 12,
|
||||||
|
cell_block_size = 1 << cell_block_shift,
|
||||||
|
cell_block_mask = cell_block_size - 1,
|
||||||
|
cell_block_pool = 256,
|
||||||
|
cell_block_limit = 1024
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
~outline_aa();
|
||||||
|
outline_aa();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void move_to(int x, int y);
|
||||||
|
void line_to(int x, int y);
|
||||||
|
|
||||||
|
int min_x() const { return m_min_x; }
|
||||||
|
int min_y() const { return m_min_y; }
|
||||||
|
int max_x() const { return m_max_x; }
|
||||||
|
int max_y() const { return m_max_y; }
|
||||||
|
|
||||||
|
const cell_aa* const* cells();
|
||||||
|
unsigned num_cells() { cells(); return m_num_cells; }
|
||||||
|
bool sorted() const { return m_sorted; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
outline_aa(const outline_aa&);
|
||||||
|
const outline_aa& operator = (const outline_aa&);
|
||||||
|
|
||||||
|
void set_cur_cell(int x, int y);
|
||||||
|
void add_cur_cell();
|
||||||
|
void sort_cells();
|
||||||
|
void render_hline(int ey, int x1, int y1, int x2, int y2);
|
||||||
|
void render_line(int x1, int y1, int x2, int y2);
|
||||||
|
void allocate_block();
|
||||||
|
|
||||||
|
static void qsort_cells(cell_aa** start, unsigned num);
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned m_num_blocks;
|
||||||
|
unsigned m_max_blocks;
|
||||||
|
unsigned m_cur_block;
|
||||||
|
unsigned m_num_cells;
|
||||||
|
cell_aa** m_cells;
|
||||||
|
cell_aa* m_cur_cell_ptr;
|
||||||
|
cell_aa** m_sorted_cells;
|
||||||
|
unsigned m_sorted_size;
|
||||||
|
cell_aa m_cur_cell;
|
||||||
|
int m_cur_x;
|
||||||
|
int m_cur_y;
|
||||||
|
int m_min_x;
|
||||||
|
int m_min_y;
|
||||||
|
int m_max_x;
|
||||||
|
int m_max_y;
|
||||||
|
bool m_sorted;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------filling_rule_e
|
||||||
|
enum filling_rule_e
|
||||||
|
{
|
||||||
|
fill_non_zero,
|
||||||
|
fill_even_odd
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------clipping_flags
|
||||||
|
// Determine the clipping code of the vertex according to the
|
||||||
|
// Cyrus-Beck line clipping algorithm
|
||||||
|
//
|
||||||
|
// | |
|
||||||
|
// 0110 | 0010 | 0011
|
||||||
|
// | |
|
||||||
|
// -------+--------+-------- clip_box.y2
|
||||||
|
// | |
|
||||||
|
// 0100 | 0000 | 0001
|
||||||
|
// | |
|
||||||
|
// -------+--------+-------- clip_box.y1
|
||||||
|
// | |
|
||||||
|
// 1100 | 1000 | 1001
|
||||||
|
// | |
|
||||||
|
// clip_box.x1 clip_box.x2
|
||||||
|
//
|
||||||
|
//
|
||||||
|
inline unsigned clipping_flags(int x, int y, const rect& clip_box)
|
||||||
|
{
|
||||||
|
return (x > clip_box.x2) |
|
||||||
|
((y > clip_box.y2) << 1) |
|
||||||
|
((x < clip_box.x1) << 2) |
|
||||||
|
((y < clip_box.y1) << 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==================================================rasterizer_scanline_aa
|
||||||
|
// Polygon rasterizer that is used to render filled polygons with
|
||||||
|
// high-quality Anti-Aliasing. Internally, by default, the class uses
|
||||||
|
// integer coordinates in format 24.8, i.e. 24 bits for integer part
|
||||||
|
// and 8 bits for fractional - see poly_base_shift. This class can be
|
||||||
|
// used in the following way:
|
||||||
|
//
|
||||||
|
// 1. filling_rule(filling_rule_e ft) - optional.
|
||||||
|
//
|
||||||
|
// 2. gamma() - optional.
|
||||||
|
//
|
||||||
|
// 3. reset()
|
||||||
|
//
|
||||||
|
// 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create
|
||||||
|
// more than one contour, but each contour must consist of at least 3
|
||||||
|
// vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3);
|
||||||
|
// is the absolute minimum of vertices that define a triangle.
|
||||||
|
// The algorithm does not check either the number of vertices nor
|
||||||
|
// coincidence of their coordinates, but in the worst case it just
|
||||||
|
// won't draw anything.
|
||||||
|
// The orger of the vertices (clockwise or counterclockwise)
|
||||||
|
// is important when using the non-zero filling rule (fill_non_zero).
|
||||||
|
// In this case the vertex order of all the contours must be the same
|
||||||
|
// if you want your intersecting polygons to be without "holes".
|
||||||
|
// You actually can use different vertices order. If the contours do not
|
||||||
|
// intersect each other the order is not important anyway. If they do,
|
||||||
|
// contours with the same vertex order will be rendered without "holes"
|
||||||
|
// while the intersecting contours with different orders will have "holes".
|
||||||
|
//
|
||||||
|
// filling_rule() and gamma() can be called anytime before "sweeping".
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift=8> class rasterizer_scanline_aa
|
||||||
|
{
|
||||||
|
enum status
|
||||||
|
{
|
||||||
|
status_initial,
|
||||||
|
status_line_to,
|
||||||
|
status_closed
|
||||||
|
};
|
||||||
|
|
||||||
|
struct iterator
|
||||||
|
{
|
||||||
|
const cell_aa* const* cells;
|
||||||
|
int cover;
|
||||||
|
int last_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
aa_shift = AA_Shift,
|
||||||
|
aa_num = 1 << aa_shift,
|
||||||
|
aa_mask = aa_num - 1,
|
||||||
|
aa_2num = aa_num * 2,
|
||||||
|
aa_2mask = aa_2num - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
rasterizer_scanline_aa() :
|
||||||
|
m_filling_rule(fill_non_zero),
|
||||||
|
m_clipped_start_x(0),
|
||||||
|
m_clipped_start_y(0),
|
||||||
|
m_start_x(0),
|
||||||
|
m_start_y(0),
|
||||||
|
m_prev_x(0),
|
||||||
|
m_prev_y(0),
|
||||||
|
m_prev_flags(0),
|
||||||
|
m_status(status_initial),
|
||||||
|
m_clipping(false)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < aa_num; i++) m_gamma[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class GammaF>
|
||||||
|
rasterizer_scanline_aa(const GammaF& gamma_function) :
|
||||||
|
m_filling_rule(fill_non_zero),
|
||||||
|
m_clipped_start_x(0),
|
||||||
|
m_clipped_start_y(0),
|
||||||
|
m_start_x(0),
|
||||||
|
m_start_y(0),
|
||||||
|
m_prev_x(0),
|
||||||
|
m_prev_y(0),
|
||||||
|
m_prev_flags(0),
|
||||||
|
m_status(status_initial),
|
||||||
|
m_clipping(false)
|
||||||
|
{
|
||||||
|
gamma(gamma_function);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void reset();
|
||||||
|
void filling_rule(filling_rule_e filling_rule);
|
||||||
|
void clip_box(double x1, double y1, double x2, double y2);
|
||||||
|
void reset_clipping();
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class GammaF> void gamma(const GammaF& gamma_function)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < aa_num; i++)
|
||||||
|
{
|
||||||
|
m_gamma[i] = int(floor(gamma_function(double(i) / aa_mask) * aa_mask + 0.5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned apply_gamma(unsigned cover) const
|
||||||
|
{
|
||||||
|
return m_gamma[cover];
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void add_vertex(double x, double y, unsigned cmd);
|
||||||
|
void move_to(int x, int y);
|
||||||
|
void line_to(int x, int y);
|
||||||
|
void close_polygon();
|
||||||
|
void move_to_d(double x, double y);
|
||||||
|
void line_to_d(double x, double y);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
int min_x() const { return m_outline.min_x(); }
|
||||||
|
int min_y() const { return m_outline.min_y(); }
|
||||||
|
int max_x() const { return m_outline.max_x(); }
|
||||||
|
int max_y() const { return m_outline.max_y(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned calculate_alpha(int area) const
|
||||||
|
{
|
||||||
|
int cover = area >> (poly_base_shift*2 + 1 - aa_shift);
|
||||||
|
|
||||||
|
if(cover < 0) cover = -cover;
|
||||||
|
if(m_filling_rule == fill_even_odd)
|
||||||
|
{
|
||||||
|
cover &= aa_2mask;
|
||||||
|
if(cover > aa_num)
|
||||||
|
{
|
||||||
|
cover = aa_2num - cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(cover > aa_mask) cover = aa_mask;
|
||||||
|
return m_gamma[cover];
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void sort()
|
||||||
|
{
|
||||||
|
m_outline.cells();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
bool rewind_scanlines()
|
||||||
|
{
|
||||||
|
close_polygon();
|
||||||
|
m_iterator.cells = m_outline.cells();
|
||||||
|
if(m_outline.num_cells() == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_iterator.cover = 0;
|
||||||
|
m_iterator.last_y = (*m_iterator.cells)->y;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||||
|
{
|
||||||
|
sl.reset_spans();
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
const cell_aa* cur_cell = *m_iterator.cells;
|
||||||
|
if(cur_cell == 0) return false;
|
||||||
|
++m_iterator.cells;
|
||||||
|
m_iterator.last_y = cur_cell->y;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
int coord = cur_cell->packed_coord;
|
||||||
|
int area = cur_cell->area;
|
||||||
|
int last_x = cur_cell->x;
|
||||||
|
|
||||||
|
m_iterator.cover += cur_cell->cover;
|
||||||
|
|
||||||
|
//accumulate all cells with the same coordinates
|
||||||
|
for(; (cur_cell = *m_iterator.cells) != 0; ++m_iterator.cells)
|
||||||
|
{
|
||||||
|
if(cur_cell->packed_coord != coord) break;
|
||||||
|
area += cur_cell->area;
|
||||||
|
m_iterator.cover += cur_cell->cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
int alpha;
|
||||||
|
if(cur_cell == 0 || cur_cell->y != m_iterator.last_y)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(area)
|
||||||
|
{
|
||||||
|
alpha = calculate_alpha((m_iterator.cover << (poly_base_shift + 1)) - area);
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
sl.add_cell(last_x, alpha);
|
||||||
|
}
|
||||||
|
++last_x;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++m_iterator.cells;
|
||||||
|
|
||||||
|
if(area)
|
||||||
|
{
|
||||||
|
alpha = calculate_alpha((m_iterator.cover << (poly_base_shift + 1)) - area);
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
sl.add_cell(last_x, alpha);
|
||||||
|
}
|
||||||
|
++last_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cur_cell->x > last_x)
|
||||||
|
{
|
||||||
|
alpha = calculate_alpha(m_iterator.cover << (poly_base_shift + 1));
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
sl.add_span(last_x, cur_cell->x - last_x, alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(sl.num_spans())
|
||||||
|
{
|
||||||
|
sl.finalize(m_iterator.last_y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
bool hit_test(int tx, int ty);
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void add_xy(const double* x, const double* y, unsigned n)
|
||||||
|
{
|
||||||
|
if(n > 2)
|
||||||
|
{
|
||||||
|
move_to_d(*x++, *y++);
|
||||||
|
--n;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
line_to_d(*x++, *y++);
|
||||||
|
}
|
||||||
|
while(--n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
template<class VertexSource>
|
||||||
|
void add_path(VertexSource& vs, unsigned id=0)
|
||||||
|
{
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
|
||||||
|
unsigned cmd;
|
||||||
|
vs.rewind(id);
|
||||||
|
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||||
|
{
|
||||||
|
add_vertex(x, y, cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Disable copying
|
||||||
|
rasterizer_scanline_aa(const rasterizer_scanline_aa<AA_Shift>&);
|
||||||
|
const rasterizer_scanline_aa<AA_Shift>&
|
||||||
|
operator = (const rasterizer_scanline_aa<AA_Shift>&);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void move_to_no_clip(int x, int y);
|
||||||
|
void line_to_no_clip(int x, int y);
|
||||||
|
void close_polygon_no_clip();
|
||||||
|
void clip_segment(int x, int y);
|
||||||
|
|
||||||
|
private:
|
||||||
|
outline_aa m_outline;
|
||||||
|
int m_gamma[aa_num];
|
||||||
|
filling_rule_e m_filling_rule;
|
||||||
|
int m_clipped_start_x;
|
||||||
|
int m_clipped_start_y;
|
||||||
|
int m_start_x;
|
||||||
|
int m_start_y;
|
||||||
|
int m_prev_x;
|
||||||
|
int m_prev_y;
|
||||||
|
unsigned m_prev_flags;
|
||||||
|
unsigned m_status;
|
||||||
|
rect m_clip_box;
|
||||||
|
bool m_clipping;
|
||||||
|
iterator m_iterator;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::reset()
|
||||||
|
{
|
||||||
|
m_outline.reset();
|
||||||
|
m_status = status_initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::filling_rule(filling_rule_e filling_rule)
|
||||||
|
{
|
||||||
|
m_filling_rule = filling_rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::clip_box(double x1, double y1, double x2, double y2)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
m_clip_box = rect(poly_coord(x1), poly_coord(y1),
|
||||||
|
poly_coord(x2), poly_coord(y2));
|
||||||
|
m_clip_box.normalize();
|
||||||
|
m_clipping = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::reset_clipping()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
m_clipping = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::move_to_no_clip(int x, int y)
|
||||||
|
{
|
||||||
|
if(m_status == status_line_to)
|
||||||
|
{
|
||||||
|
close_polygon_no_clip();
|
||||||
|
}
|
||||||
|
m_outline.move_to(x, y);
|
||||||
|
m_clipped_start_x = x;
|
||||||
|
m_clipped_start_y = y;
|
||||||
|
m_status = status_line_to;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::line_to_no_clip(int x, int y)
|
||||||
|
{
|
||||||
|
if(m_status != status_initial)
|
||||||
|
{
|
||||||
|
m_outline.line_to(x, y);
|
||||||
|
m_status = status_line_to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::close_polygon_no_clip()
|
||||||
|
{
|
||||||
|
if(m_status == status_line_to)
|
||||||
|
{
|
||||||
|
m_outline.line_to(m_clipped_start_x, m_clipped_start_y);
|
||||||
|
m_status = status_closed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::clip_segment(int x, int y)
|
||||||
|
{
|
||||||
|
unsigned flags = clipping_flags(x, y, m_clip_box);
|
||||||
|
if(m_prev_flags == flags)
|
||||||
|
{
|
||||||
|
if(flags == 0)
|
||||||
|
{
|
||||||
|
if(m_status == status_initial)
|
||||||
|
{
|
||||||
|
move_to_no_clip(x, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line_to_no_clip(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int cx[4];
|
||||||
|
int cy[4];
|
||||||
|
unsigned n = clip_liang_barsky(m_prev_x, m_prev_y,
|
||||||
|
x, y,
|
||||||
|
m_clip_box,
|
||||||
|
cx, cy);
|
||||||
|
const int* px = cx;
|
||||||
|
const int* py = cy;
|
||||||
|
while(n--)
|
||||||
|
{
|
||||||
|
if(m_status == status_initial)
|
||||||
|
{
|
||||||
|
move_to_no_clip(*px++, *py++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line_to_no_clip(*px++, *py++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_prev_flags = flags;
|
||||||
|
m_prev_x = x;
|
||||||
|
m_prev_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::add_vertex(double x, double y, unsigned cmd)
|
||||||
|
{
|
||||||
|
if(is_close(cmd))
|
||||||
|
{
|
||||||
|
close_polygon();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(is_move_to(cmd))
|
||||||
|
{
|
||||||
|
move_to(poly_coord(x), poly_coord(y));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(is_vertex(cmd))
|
||||||
|
{
|
||||||
|
line_to(poly_coord(x), poly_coord(y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::move_to(int x, int y)
|
||||||
|
{
|
||||||
|
if(m_clipping)
|
||||||
|
{
|
||||||
|
if(m_outline.sorted())
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
if(m_status == status_line_to)
|
||||||
|
{
|
||||||
|
close_polygon();
|
||||||
|
}
|
||||||
|
m_prev_x = m_start_x = x;
|
||||||
|
m_prev_y = m_start_y = y;
|
||||||
|
m_status = status_initial;
|
||||||
|
m_prev_flags = clipping_flags(x, y, m_clip_box);
|
||||||
|
if(m_prev_flags == 0)
|
||||||
|
{
|
||||||
|
move_to_no_clip(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
move_to_no_clip(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::line_to(int x, int y)
|
||||||
|
{
|
||||||
|
if(m_clipping)
|
||||||
|
{
|
||||||
|
clip_segment(x, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line_to_no_clip(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::close_polygon()
|
||||||
|
{
|
||||||
|
if(m_clipping)
|
||||||
|
{
|
||||||
|
clip_segment(m_start_x, m_start_y);
|
||||||
|
}
|
||||||
|
close_polygon_no_clip();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::move_to_d(double x, double y)
|
||||||
|
{
|
||||||
|
move_to(poly_coord(x), poly_coord(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
void rasterizer_scanline_aa<AA_Shift>::line_to_d(double x, double y)
|
||||||
|
{
|
||||||
|
line_to(poly_coord(x), poly_coord(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<unsigned AA_Shift>
|
||||||
|
bool rasterizer_scanline_aa<AA_Shift>::hit_test(int tx, int ty)
|
||||||
|
{
|
||||||
|
close_polygon();
|
||||||
|
const cell_aa* const* cells = m_outline.cells();
|
||||||
|
if(m_outline.num_cells() == 0) return false;
|
||||||
|
|
||||||
|
int cover = 0;
|
||||||
|
|
||||||
|
const cell_aa* cur_cell = *cells++;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
int alpha;
|
||||||
|
int coord = cur_cell->packed_coord;
|
||||||
|
int x = cur_cell->x;
|
||||||
|
int y = cur_cell->y;
|
||||||
|
|
||||||
|
if(y > ty) return false;
|
||||||
|
|
||||||
|
int area = cur_cell->area;
|
||||||
|
cover += cur_cell->cover;
|
||||||
|
|
||||||
|
while((cur_cell = *cells++) != 0)
|
||||||
|
{
|
||||||
|
if(cur_cell->packed_coord != coord) break;
|
||||||
|
area += cur_cell->area;
|
||||||
|
cover += cur_cell->cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(area)
|
||||||
|
{
|
||||||
|
alpha = calculate_alpha((cover << (poly_base_shift + 1)) - area);
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(tx == x && ty == y) return true;
|
||||||
|
}
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!cur_cell) break;
|
||||||
|
|
||||||
|
if(cur_cell->x > x)
|
||||||
|
{
|
||||||
|
alpha = calculate_alpha(cover << (poly_base_shift + 1));
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(ty == y && tx >= x && tx <= cur_cell->x) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_RENDER_SCANLINES_INCLUDED
|
||||||
|
#define AGG_RENDER_SCANLINES_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//========================================================render_scanlines
|
||||||
|
template<class Rasterizer, class Scanline, class Renderer>
|
||||||
|
void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren)
|
||||||
|
{
|
||||||
|
if(ras.rewind_scanlines())
|
||||||
|
{
|
||||||
|
sl.reset(ras.min_x(), ras.max_x());
|
||||||
|
ren.prepare(unsigned(ras.max_x() - ras.min_x() + 2));
|
||||||
|
|
||||||
|
while(ras.sweep_scanline(sl))
|
||||||
|
{
|
||||||
|
ren.render(sl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//========================================================render_all_paths
|
||||||
|
template<class Rasterizer, class Scanline, class Renderer,
|
||||||
|
class VertexSource, class ColorStorage, class PathId>
|
||||||
|
void render_all_paths(Rasterizer& ras,
|
||||||
|
Scanline& sl,
|
||||||
|
Renderer& r,
|
||||||
|
VertexSource& vs,
|
||||||
|
const ColorStorage& as,
|
||||||
|
const PathId& id,
|
||||||
|
unsigned num_paths)
|
||||||
|
{
|
||||||
|
for(unsigned i = 0; i < num_paths; i++)
|
||||||
|
{
|
||||||
|
ras.reset();
|
||||||
|
ras.add_path(vs, id[i]);
|
||||||
|
r.color(as[i]);
|
||||||
|
render_scanlines(ras, sl, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,420 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// class renderer_base
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_RENDERER_BASE_INCLUDED
|
||||||
|
#define AGG_RENDERER_BASE_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//-----------------------------------------------------------renderer_base
|
||||||
|
template<class PixelFormat> class renderer_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef PixelFormat pixfmt_type;
|
||||||
|
typedef typename pixfmt_type::color_type color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
renderer_base(pixfmt_type& ren) :
|
||||||
|
m_ren(&ren),
|
||||||
|
m_clip_box(0, 0, ren.width() - 1, ren.height() - 1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const pixfmt_type& ren() const { return *m_ren; }
|
||||||
|
pixfmt_type& ren() { return *m_ren; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned width() const { return m_ren->width(); }
|
||||||
|
unsigned height() const { return m_ren->height(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
bool clip_box(int x1, int y1, int x2, int y2)
|
||||||
|
{
|
||||||
|
rect cb(x1, y1, x2, y2);
|
||||||
|
cb.normalize();
|
||||||
|
if(cb.clip(rect(0, 0, width() - 1, height() - 1)))
|
||||||
|
{
|
||||||
|
m_clip_box = cb;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
m_clip_box.x1 = 1;
|
||||||
|
m_clip_box.y1 = 1;
|
||||||
|
m_clip_box.x2 = 0;
|
||||||
|
m_clip_box.y2 = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void reset_clipping(bool visibility)
|
||||||
|
{
|
||||||
|
if(visibility)
|
||||||
|
{
|
||||||
|
m_clip_box.x1 = 0;
|
||||||
|
m_clip_box.y1 = 0;
|
||||||
|
m_clip_box.x2 = width() - 1;
|
||||||
|
m_clip_box.y2 = height() - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_clip_box.x1 = 1;
|
||||||
|
m_clip_box.y1 = 1;
|
||||||
|
m_clip_box.x2 = 0;
|
||||||
|
m_clip_box.y2 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void clip_box_naked(int x1, int y1, int x2, int y2)
|
||||||
|
{
|
||||||
|
m_clip_box.x1 = x1;
|
||||||
|
m_clip_box.y1 = y1;
|
||||||
|
m_clip_box.x2 = x2;
|
||||||
|
m_clip_box.y2 = y2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
bool inbox(int x, int y) const
|
||||||
|
{
|
||||||
|
return x >= m_clip_box.x1 && y >= m_clip_box.y1 &&
|
||||||
|
x <= m_clip_box.x2 && y <= m_clip_box.y2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void first_clip_box() {}
|
||||||
|
bool next_clip_box() { return false; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rect& clip_box() const { return m_clip_box; }
|
||||||
|
int xmin() const { return m_clip_box.x1; }
|
||||||
|
int ymin() const { return m_clip_box.y1; }
|
||||||
|
int xmax() const { return m_clip_box.x2; }
|
||||||
|
int ymax() const { return m_clip_box.y2; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rect& bounding_clip_box() const { return m_clip_box; }
|
||||||
|
int bounding_xmin() const { return m_clip_box.x1; }
|
||||||
|
int bounding_ymin() const { return m_clip_box.y1; }
|
||||||
|
int bounding_xmax() const { return m_clip_box.x2; }
|
||||||
|
int bounding_ymax() const { return m_clip_box.y2; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void clear(const color_type& c)
|
||||||
|
{
|
||||||
|
unsigned y;
|
||||||
|
if(width())
|
||||||
|
{
|
||||||
|
for(y = 0; y < height(); y++)
|
||||||
|
{
|
||||||
|
m_ren->copy_hline(0, y, width(), c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_pixel(int x, int y, const color_type& c)
|
||||||
|
{
|
||||||
|
if(inbox(x, y))
|
||||||
|
{
|
||||||
|
m_ren->copy_pixel(x, y, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
|
||||||
|
{
|
||||||
|
if(inbox(x, y))
|
||||||
|
{
|
||||||
|
m_ren->blend_pixel(x, y, c, cover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type pixel(int x, int y) const
|
||||||
|
{
|
||||||
|
return inbox(x, y) ?
|
||||||
|
m_ren->pixel(x, y) :
|
||||||
|
color_type::no_color();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_hline(int x1, int y, int x2, const color_type& c)
|
||||||
|
{
|
||||||
|
if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
|
||||||
|
if(y > ymax()) return;
|
||||||
|
if(y < ymin()) return;
|
||||||
|
if(x1 > xmax()) return;
|
||||||
|
if(x2 < xmin()) return;
|
||||||
|
|
||||||
|
if(x1 < xmin()) x1 = xmin();
|
||||||
|
if(x2 > xmax()) x2 = xmax();
|
||||||
|
|
||||||
|
m_ren->copy_hline(x1, y, x2 - x1 + 1, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_vline(int x, int y1, int y2, const color_type& c)
|
||||||
|
{
|
||||||
|
if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
|
||||||
|
if(x > xmax()) return;
|
||||||
|
if(x < xmin()) return;
|
||||||
|
if(y1 > ymax()) return;
|
||||||
|
if(y2 < ymin()) return;
|
||||||
|
|
||||||
|
if(y1 < ymin()) y1 = ymin();
|
||||||
|
if(y2 > ymax()) y2 = ymax();
|
||||||
|
|
||||||
|
m_ren->copy_vline(x, y1, y2 - y1 + 1, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_hline(int x1, int y, int x2,
|
||||||
|
const color_type& c, cover_type cover)
|
||||||
|
{
|
||||||
|
if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
|
||||||
|
if(y > ymax()) return;
|
||||||
|
if(y < ymin()) return;
|
||||||
|
if(x1 > xmax()) return;
|
||||||
|
if(x2 < xmin()) return;
|
||||||
|
|
||||||
|
if(x1 < xmin()) x1 = xmin();
|
||||||
|
if(x2 > xmax()) x2 = xmax();
|
||||||
|
|
||||||
|
m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_vline(int x, int y1, int y2,
|
||||||
|
const color_type& c, cover_type cover)
|
||||||
|
{
|
||||||
|
if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
|
||||||
|
if(x > xmax()) return;
|
||||||
|
if(x < xmin()) return;
|
||||||
|
if(y1 > ymax()) return;
|
||||||
|
if(y2 < ymin()) return;
|
||||||
|
|
||||||
|
if(y1 < ymin()) y1 = ymin();
|
||||||
|
if(y2 > ymax()) y2 = ymax();
|
||||||
|
|
||||||
|
m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
|
||||||
|
{
|
||||||
|
rect rc(x1, y1, x2, y2);
|
||||||
|
rc.normalize();
|
||||||
|
if(rc.clip(clip_box()))
|
||||||
|
{
|
||||||
|
int y;
|
||||||
|
for(y = rc.y1; y <= rc.y2; y++)
|
||||||
|
{
|
||||||
|
m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_bar(int x1, int y1, int x2, int y2,
|
||||||
|
const color_type& c, cover_type cover)
|
||||||
|
{
|
||||||
|
rect rc(x1, y1, x2, y2);
|
||||||
|
rc.normalize();
|
||||||
|
if(rc.clip(clip_box()))
|
||||||
|
{
|
||||||
|
int y;
|
||||||
|
for(y = rc.y1; y <= rc.y2; y++)
|
||||||
|
{
|
||||||
|
m_ren->blend_hline(rc.x1,
|
||||||
|
y,
|
||||||
|
unsigned(rc.x2 - rc.x1 + 1),
|
||||||
|
c,
|
||||||
|
cover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_hspan(int x, int y, int len,
|
||||||
|
const color_type& c,
|
||||||
|
const cover_type* covers)
|
||||||
|
{
|
||||||
|
if(y > ymax()) return;
|
||||||
|
if(y < ymin()) return;
|
||||||
|
|
||||||
|
if(x < xmin())
|
||||||
|
{
|
||||||
|
len -= xmin() - x;
|
||||||
|
if(len <= 0) return;
|
||||||
|
covers += xmin() - x;
|
||||||
|
x = xmin();
|
||||||
|
}
|
||||||
|
if(x + len > xmax())
|
||||||
|
{
|
||||||
|
len = xmax() - x + 1;
|
||||||
|
if(len <= 0) return;
|
||||||
|
}
|
||||||
|
m_ren->blend_solid_hspan(x, y, len, c, covers);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_vspan(int x, int y, int len,
|
||||||
|
const color_type& c,
|
||||||
|
const cover_type* covers)
|
||||||
|
{
|
||||||
|
if(x > xmax()) return;
|
||||||
|
if(x < xmin()) return;
|
||||||
|
|
||||||
|
if(y < ymin())
|
||||||
|
{
|
||||||
|
len -= ymin() - y;
|
||||||
|
if(len <= 0) return;
|
||||||
|
covers += ymin() - y;
|
||||||
|
y = ymin();
|
||||||
|
}
|
||||||
|
if(y + len > ymax())
|
||||||
|
{
|
||||||
|
len = ymax() - y + 1;
|
||||||
|
if(len <= 0) return;
|
||||||
|
}
|
||||||
|
m_ren->blend_solid_vspan(x, y, len, c, covers);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan(int x, int y, int len,
|
||||||
|
const color_type* colors,
|
||||||
|
const cover_type* covers,
|
||||||
|
cover_type cover = cover_full)
|
||||||
|
{
|
||||||
|
if(y > ymax()) return;
|
||||||
|
if(y < ymin()) return;
|
||||||
|
|
||||||
|
if(x < xmin())
|
||||||
|
{
|
||||||
|
int d = xmin() - x;
|
||||||
|
len -= d;
|
||||||
|
if(len <= 0) return;
|
||||||
|
if(covers) covers += d;
|
||||||
|
colors += d;
|
||||||
|
x = xmin();
|
||||||
|
}
|
||||||
|
if(x + len > xmax())
|
||||||
|
{
|
||||||
|
len = xmax() - x + 1;
|
||||||
|
if(len <= 0) return;
|
||||||
|
}
|
||||||
|
m_ren->blend_color_hspan(x, y, len, colors, covers, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan(int x, int y, int len,
|
||||||
|
const color_type* colors,
|
||||||
|
const cover_type* covers,
|
||||||
|
cover_type cover = cover_full)
|
||||||
|
{
|
||||||
|
if(x > xmax()) return;
|
||||||
|
if(x < xmin()) return;
|
||||||
|
|
||||||
|
if(y < ymin())
|
||||||
|
{
|
||||||
|
int d = ymin() - y;
|
||||||
|
len -= d;
|
||||||
|
if(len <= 0) return;
|
||||||
|
if(covers) covers += d;
|
||||||
|
colors += d;
|
||||||
|
y = ymin();
|
||||||
|
}
|
||||||
|
if(y + len > ymax())
|
||||||
|
{
|
||||||
|
len = ymax() - y + 1;
|
||||||
|
if(len <= 0) return;
|
||||||
|
}
|
||||||
|
m_ren->blend_color_vspan(x, y, len, colors, covers, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan_no_clip(int x, int y, int len,
|
||||||
|
const color_type* colors,
|
||||||
|
const cover_type* covers,
|
||||||
|
cover_type cover = cover_full)
|
||||||
|
{
|
||||||
|
m_ren->blend_color_hspan(x, y, len, colors, covers, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan_no_clip(int x, int y, int len,
|
||||||
|
const color_type* colors,
|
||||||
|
const cover_type* covers,
|
||||||
|
cover_type cover = cover_full)
|
||||||
|
{
|
||||||
|
m_ren->blend_color_vspan(x, y, len, colors, covers, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_from(const rendering_buffer& from,
|
||||||
|
const rect* rc=0,
|
||||||
|
int x_to=0,
|
||||||
|
int y_to=0)
|
||||||
|
{
|
||||||
|
rect tmp_rect(0, 0, from.width(), from.height());
|
||||||
|
if(rc == 0)
|
||||||
|
{
|
||||||
|
rc = &tmp_rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
rect rc2(*rc);
|
||||||
|
rc2.normalize();
|
||||||
|
if(rc2.clip(rect(0, 0, from.width() - 1, from.height() - 1)))
|
||||||
|
{
|
||||||
|
rect rc3(x_to + rc2.x1 - rc->x1,
|
||||||
|
y_to + rc2.y1 - rc->y1,
|
||||||
|
x_to + rc2.x2 - rc->x1,
|
||||||
|
y_to + rc2.y2 - rc->y1);
|
||||||
|
rc3.normalize();
|
||||||
|
|
||||||
|
if(rc3.clip(clip_box()))
|
||||||
|
{
|
||||||
|
while(rc3.y1 <= rc3.y2)
|
||||||
|
{
|
||||||
|
m_ren->copy_from(from,
|
||||||
|
rc3.x1, rc3.y1,
|
||||||
|
rc2.x1, rc2.y1,
|
||||||
|
rc3.x2 - rc3.x1 + 1);
|
||||||
|
++rc2.y1;
|
||||||
|
++rc3.y1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
pixfmt_type* m_ren;
|
||||||
|
rect m_clip_box;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,707 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// class renderer_markers
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_RENDERER_MARKERS_INCLUDED
|
||||||
|
#define AGG_RENDERER_MARKERS_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_renderer_primitives.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//---------------------------------------------------------------marker_e
|
||||||
|
enum marker_e
|
||||||
|
{
|
||||||
|
marker_square,
|
||||||
|
marker_diamond,
|
||||||
|
marker_circle,
|
||||||
|
marker_crossed_circle,
|
||||||
|
marker_semiellipse_left,
|
||||||
|
marker_semiellipse_right,
|
||||||
|
marker_semiellipse_up,
|
||||||
|
marker_semiellipse_down,
|
||||||
|
marker_triangle_left,
|
||||||
|
marker_triangle_right,
|
||||||
|
marker_triangle_up,
|
||||||
|
marker_triangle_down,
|
||||||
|
marker_four_rays,
|
||||||
|
marker_cross,
|
||||||
|
marker_x,
|
||||||
|
marker_dash,
|
||||||
|
marker_dot,
|
||||||
|
marker_pixel,
|
||||||
|
|
||||||
|
end_of_markers
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------renderer_markers
|
||||||
|
template<class BaseRenderer> class renderer_markers :
|
||||||
|
public renderer_primitives<BaseRenderer>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef renderer_primitives<BaseRenderer> base_type;
|
||||||
|
typedef BaseRenderer base_ren_type;
|
||||||
|
typedef typename base_ren_type::color_type color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
renderer_markers(base_ren_type& rbuf) :
|
||||||
|
base_type(rbuf)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
bool visible(int x, int y, int r) const
|
||||||
|
{
|
||||||
|
rect rc(x-r, y-r, x+y, y+r);
|
||||||
|
return rc.clip(base_type::ren().bounding_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void square(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r) base_type::outlined_rectangle(x-r, y-r, x+r, y+r);
|
||||||
|
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void diamond(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
int dy = -r;
|
||||||
|
int dx = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
|
||||||
|
|
||||||
|
if(dx)
|
||||||
|
{
|
||||||
|
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
++dy;
|
||||||
|
++dx;
|
||||||
|
}
|
||||||
|
while(dy <= 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void circle(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r) base_type::outlined_ellipse(x, y, r, r);
|
||||||
|
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void crossed_circle(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
base_type::outlined_ellipse(x, y, r, r);
|
||||||
|
int r6 = r + (r >> 1);
|
||||||
|
if(r <= 2) r6++;
|
||||||
|
r >>= 1;
|
||||||
|
base_type::ren().blend_hline(x-r6, y, x-r, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_hline(x+r, y, x+r6, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_vline(x, y-r6, y-r, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_vline(x, y+r, y+r6, base_type::line_color(), cover_full);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
void semiellipse_left(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
int r8 = r * 4 / 5;
|
||||||
|
int dy = -r;
|
||||||
|
int dx = 0;
|
||||||
|
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dx += ei.dx();
|
||||||
|
dy += ei.dy();
|
||||||
|
|
||||||
|
base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
|
||||||
|
|
||||||
|
if(ei.dy() && dx)
|
||||||
|
{
|
||||||
|
base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
++ei;
|
||||||
|
}
|
||||||
|
while(dy < r8);
|
||||||
|
base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void semiellipse_right(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
int r8 = r * 4 / 5;
|
||||||
|
int dy = -r;
|
||||||
|
int dx = 0;
|
||||||
|
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dx += ei.dx();
|
||||||
|
dy += ei.dy();
|
||||||
|
|
||||||
|
base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
|
||||||
|
|
||||||
|
if(ei.dy() && dx)
|
||||||
|
{
|
||||||
|
base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
++ei;
|
||||||
|
}
|
||||||
|
while(dy < r8);
|
||||||
|
base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void semiellipse_up(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
int r8 = r * 4 / 5;
|
||||||
|
int dy = -r;
|
||||||
|
int dx = 0;
|
||||||
|
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dx += ei.dx();
|
||||||
|
dy += ei.dy();
|
||||||
|
|
||||||
|
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
|
||||||
|
|
||||||
|
if(ei.dy() && dx)
|
||||||
|
{
|
||||||
|
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
++ei;
|
||||||
|
}
|
||||||
|
while(dy < r8);
|
||||||
|
base_type::ren().blend_hline(x-dx, y-dy-1, x+dx, base_type::line_color(), cover_full);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void semiellipse_down(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
int r8 = r * 4 / 5;
|
||||||
|
int dy = -r;
|
||||||
|
int dx = 0;
|
||||||
|
ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dx += ei.dx();
|
||||||
|
dy += ei.dy();
|
||||||
|
|
||||||
|
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
|
||||||
|
|
||||||
|
if(ei.dy() && dx)
|
||||||
|
{
|
||||||
|
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
++ei;
|
||||||
|
}
|
||||||
|
while(dy < r8);
|
||||||
|
base_type::ren().blend_hline(x-dx, y+dy+1, x+dx, base_type::line_color(), cover_full);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void triangle_left(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
int dy = -r;
|
||||||
|
int dx = 0;
|
||||||
|
int flip = 0;
|
||||||
|
int r6 = r * 3 / 5;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
|
||||||
|
|
||||||
|
if(dx)
|
||||||
|
{
|
||||||
|
base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
++dy;
|
||||||
|
dx += flip;
|
||||||
|
flip ^= 1;
|
||||||
|
}
|
||||||
|
while(dy < r6);
|
||||||
|
base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void triangle_right(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
int dy = -r;
|
||||||
|
int dx = 0;
|
||||||
|
int flip = 0;
|
||||||
|
int r6 = r * 3 / 5;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
|
||||||
|
|
||||||
|
if(dx)
|
||||||
|
{
|
||||||
|
base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
++dy;
|
||||||
|
dx += flip;
|
||||||
|
flip ^= 1;
|
||||||
|
}
|
||||||
|
while(dy < r6);
|
||||||
|
base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void triangle_up(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
int dy = -r;
|
||||||
|
int dx = 0;
|
||||||
|
int flip = 0;
|
||||||
|
int r6 = r * 3 / 5;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
|
||||||
|
|
||||||
|
if(dx)
|
||||||
|
{
|
||||||
|
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
++dy;
|
||||||
|
dx += flip;
|
||||||
|
flip ^= 1;
|
||||||
|
}
|
||||||
|
while(dy < r6);
|
||||||
|
base_type::ren().blend_hline(x-dx, y-dy, x+dx, base_type::line_color(), cover_full);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void triangle_down(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
int dy = -r;
|
||||||
|
int dx = 0;
|
||||||
|
int flip = 0;
|
||||||
|
int r6 = r * 3 / 5;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
|
||||||
|
|
||||||
|
if(dx)
|
||||||
|
{
|
||||||
|
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
++dy;
|
||||||
|
dx += flip;
|
||||||
|
flip ^= 1;
|
||||||
|
}
|
||||||
|
while(dy < r6);
|
||||||
|
base_type::ren().blend_hline(x-dx, y+dy, x+dx, base_type::line_color(), cover_full);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void four_rays(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
int dy = -r;
|
||||||
|
int dx = 0;
|
||||||
|
int flip = 0;
|
||||||
|
int r3 = -(r / 3);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full);
|
||||||
|
|
||||||
|
if(dx)
|
||||||
|
{
|
||||||
|
base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
++dy;
|
||||||
|
dx += flip;
|
||||||
|
flip ^= 1;
|
||||||
|
}
|
||||||
|
while(dy <= r3);
|
||||||
|
base_type::solid_rectangle(x+r3+1, y+r3+1, x-r3-1, y-r3-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void cross(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
base_type::ren().blend_vline(x, y-r, y+r, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void xing(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r)
|
||||||
|
{
|
||||||
|
int dy = -r * 7 / 10;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x + dy, y + dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x - dy, y + dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x + dy, y - dy, base_type::line_color(), cover_full);
|
||||||
|
base_type::ren().blend_pixel(x - dy, y - dy, base_type::line_color(), cover_full);
|
||||||
|
++dy;
|
||||||
|
}
|
||||||
|
while(dy < 0);
|
||||||
|
}
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void dash(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r) base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full);
|
||||||
|
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void dot(int x, int y, int r)
|
||||||
|
{
|
||||||
|
if(visible(x, y, r))
|
||||||
|
{
|
||||||
|
if(r) base_type::solid_ellipse(x, y, r, r);
|
||||||
|
else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void pixel(int x, int y, int)
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void marker(int x, int y, int r, marker_e type)
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case marker_square: square(x, y, r); break;
|
||||||
|
case marker_diamond: diamond(x, y, r); break;
|
||||||
|
case marker_circle: circle(x, y, r); break;
|
||||||
|
case marker_crossed_circle: crossed_circle(x, y, r); break;
|
||||||
|
case marker_semiellipse_left: semiellipse_left(x, y, r); break;
|
||||||
|
case marker_semiellipse_right: semiellipse_right(x, y, r); break;
|
||||||
|
case marker_semiellipse_up: semiellipse_up(x, y, r); break;
|
||||||
|
case marker_semiellipse_down: semiellipse_down(x, y, r); break;
|
||||||
|
case marker_triangle_left: triangle_left(x, y, r); break;
|
||||||
|
case marker_triangle_right: triangle_right(x, y, r); break;
|
||||||
|
case marker_triangle_up: triangle_up(x, y, r); break;
|
||||||
|
case marker_triangle_down: triangle_down(x, y, r); break;
|
||||||
|
case marker_four_rays: four_rays(x, y, r); break;
|
||||||
|
case marker_cross: cross(x, y, r); break;
|
||||||
|
case marker_x: xing(x, y, r); break;
|
||||||
|
case marker_dash: dash(x, y, r); break;
|
||||||
|
case marker_dot: dot(x, y, r); break;
|
||||||
|
case marker_pixel: pixel(x, y, r); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class T>
|
||||||
|
void markers(int n, const T* x, const T* y, T r, marker_e type)
|
||||||
|
{
|
||||||
|
if(n <= 0) return;
|
||||||
|
if(r == 0)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::ren().blend_pixel(int(*x), int(*y), base_type::fill_color(), cover_full);
|
||||||
|
++x;
|
||||||
|
++y;
|
||||||
|
}
|
||||||
|
while(--n);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case marker_square: do { square (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_diamond: do { diamond (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_circle: do { circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_four_rays: do { four_rays (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_cross: do { cross (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_x: do { xing (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_dash: do { dash (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_dot: do { dot (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
case marker_pixel: do { pixel (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class T>
|
||||||
|
void markers(int n, const T* x, const T* y, const T* r, marker_e type)
|
||||||
|
{
|
||||||
|
if(n <= 0) return;
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case marker_square: do { square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_diamond: do { diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_circle: do { circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_four_rays: do { four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_cross: do { cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_x: do { xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_dash: do { dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_dot: do { dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
case marker_pixel: do { pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class T>
|
||||||
|
void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, marker_e type)
|
||||||
|
{
|
||||||
|
if(n <= 0) return;
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case marker_square: do { base_type::fill_color(*fc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_diamond: do { base_type::fill_color(*fc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_circle: do { base_type::fill_color(*fc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_crossed_circle: do { base_type::fill_color(*fc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_semiellipse_left: do { base_type::fill_color(*fc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_semiellipse_right: do { base_type::fill_color(*fc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_semiellipse_up: do { base_type::fill_color(*fc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_semiellipse_down: do { base_type::fill_color(*fc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_triangle_left: do { base_type::fill_color(*fc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_triangle_right: do { base_type::fill_color(*fc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_triangle_up: do { base_type::fill_color(*fc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_triangle_down: do { base_type::fill_color(*fc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_four_rays: do { base_type::fill_color(*fc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_cross: do { base_type::fill_color(*fc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_x: do { base_type::fill_color(*fc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_dash: do { base_type::fill_color(*fc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_dot: do { base_type::fill_color(*fc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
case marker_pixel: do { base_type::fill_color(*fc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class T>
|
||||||
|
void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, const color_type* lc, marker_e type)
|
||||||
|
{
|
||||||
|
if(n <= 0) return;
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case marker_square: do { base_type::fill_color(*fc); base_type::line_color(*lc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_diamond: do { base_type::fill_color(*fc); base_type::line_color(*lc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_crossed_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_semiellipse_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_semiellipse_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_semiellipse_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_semiellipse_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_triangle_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_triangle_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_triangle_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_triangle_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_four_rays: do { base_type::fill_color(*fc); base_type::line_color(*lc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_cross: do { base_type::fill_color(*fc); base_type::line_color(*lc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_x: do { base_type::fill_color(*fc); base_type::line_color(*lc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_dash: do { base_type::fill_color(*fc); base_type::line_color(*lc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_dot: do { base_type::fill_color(*fc); base_type::line_color(*lc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
case marker_pixel: do { base_type::fill_color(*fc); base_type::line_color(*lc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,334 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// class renderer_mclip
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_RENDERER_MCLIP_INCLUDED
|
||||||
|
#define AGG_RENDERER_MCLIP_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_array.h"
|
||||||
|
#include "agg_renderer_base.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//----------------------------------------------------------renderer_mclip
|
||||||
|
template<class PixelFormat> class renderer_mclip
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef PixelFormat pixfmt_type;
|
||||||
|
typedef typename pixfmt_type::color_type color_type;
|
||||||
|
typedef renderer_base<pixfmt_type> base_ren_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
renderer_mclip(pixfmt_type& ren) :
|
||||||
|
m_ren(ren),
|
||||||
|
m_curr_cb(0),
|
||||||
|
m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const pixfmt_type& ren() const { return m_ren.ren(); }
|
||||||
|
pixfmt_type& ren() { return m_ren.ren(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned width() const { return m_ren.width(); }
|
||||||
|
unsigned height() const { return m_ren.height(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rect& clip_box() const { return m_ren.clip_box(); }
|
||||||
|
int xmin() const { return m_ren.xmin(); }
|
||||||
|
int ymin() const { return m_ren.ymin(); }
|
||||||
|
int xmax() const { return m_ren.xmax(); }
|
||||||
|
int ymax() const { return m_ren.ymax(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rect& bounding_clip_box() const { return m_bounds; }
|
||||||
|
int bounding_xmin() const { return m_bounds.x1; }
|
||||||
|
int bounding_ymin() const { return m_bounds.y1; }
|
||||||
|
int bounding_xmax() const { return m_bounds.x2; }
|
||||||
|
int bounding_ymax() const { return m_bounds.y2; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void first_clip_box()
|
||||||
|
{
|
||||||
|
m_curr_cb = 0;
|
||||||
|
if(m_clip.size())
|
||||||
|
{
|
||||||
|
const rect& cb = m_clip[0];
|
||||||
|
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
bool next_clip_box()
|
||||||
|
{
|
||||||
|
if(++m_curr_cb < m_clip.size())
|
||||||
|
{
|
||||||
|
const rect& cb = m_clip[m_curr_cb];
|
||||||
|
m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void reset_clipping(bool visibility)
|
||||||
|
{
|
||||||
|
m_ren.reset_clipping(visibility);
|
||||||
|
m_clip.remove_all();
|
||||||
|
m_curr_cb = 0;
|
||||||
|
m_bounds = m_ren.clip_box();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void add_clip_box(int x1, int y1, int x2, int y2)
|
||||||
|
{
|
||||||
|
rect cb(x1, y1, x2, y2);
|
||||||
|
cb.normalize();
|
||||||
|
if(cb.clip(rect(0, 0, width() - 1, height() - 1)))
|
||||||
|
{
|
||||||
|
m_clip.add(cb);
|
||||||
|
if(cb.x1 < m_bounds.x1) m_bounds.x1 = cb.x1;
|
||||||
|
if(cb.y1 < m_bounds.y1) m_bounds.y1 = cb.y1;
|
||||||
|
if(cb.x2 > m_bounds.x2) m_bounds.x2 = cb.x2;
|
||||||
|
if(cb.y2 > m_bounds.y2) m_bounds.y2 = cb.y2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void clear(const color_type& c)
|
||||||
|
{
|
||||||
|
m_ren.clear(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_pixel(int x, int y, const color_type& c)
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(m_ren.inbox(x, y))
|
||||||
|
{
|
||||||
|
m_ren.ren().copy_pixel(x, y, c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_pixel(int x, int y, const color_type& c, cover_type cover)
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(m_ren.inbox(x, y))
|
||||||
|
{
|
||||||
|
m_ren.ren().blend_pixel(x, y, c, cover);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type pixel(int x, int y) const
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(m_ren.inbox(x, y))
|
||||||
|
{
|
||||||
|
return m_ren.ren().pixel(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
return color_type::no_color();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_hline(int x1, int y, int x2, const color_type& c)
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren.copy_hline(x1, y, x2, c);
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_vline(int x, int y1, int y2, const color_type& c)
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren.copy_vline(x, y1, y2, c);
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_hline(int x1, int y, int x2,
|
||||||
|
const color_type& c, cover_type cover)
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren.blend_hline(x1, y, x2, c, cover);
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_vline(int x, int y1, int y2,
|
||||||
|
const color_type& c, cover_type cover)
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren.blend_vline(x, y1, y2, c, cover);
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren.copy_bar(x1, y1, x2, y2, c);
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_bar(int x1, int y1, int x2, int y2,
|
||||||
|
const color_type& c, cover_type cover)
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren.blend_bar(x1, y1, x2, y2, c, cover);
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_hspan(int x, int y, int len,
|
||||||
|
const color_type& c, const cover_type* covers)
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren.blend_solid_hspan(x, y, len, c, covers);
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_solid_vspan(int x, int y, int len,
|
||||||
|
const color_type& c, const cover_type* covers)
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren.blend_solid_vspan(x, y, len, c, covers);
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan(int x, int y, int len,
|
||||||
|
const color_type* colors,
|
||||||
|
const cover_type* covers,
|
||||||
|
cover_type cover = cover_full)
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan(int x, int y, int len,
|
||||||
|
const color_type* colors,
|
||||||
|
const cover_type* covers,
|
||||||
|
cover_type cover = cover_full)
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren.blend_color_hspan(x, y, len, colors, covers, cover);
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_hspan_no_clip(int x, int y, int len,
|
||||||
|
const color_type* colors,
|
||||||
|
const cover_type* covers,
|
||||||
|
cover_type cover = cover_full)
|
||||||
|
{
|
||||||
|
m_ren.blend_color_hspan_no_clip(x, y, len, colors, covers, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void blend_color_vspan_no_clip(int x, int y, int len,
|
||||||
|
const color_type* colors,
|
||||||
|
const cover_type* covers,
|
||||||
|
cover_type cover = cover_full)
|
||||||
|
{
|
||||||
|
m_ren.blend_color_vspan_no_clip(x, y, len, colors, covers, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_from(const rendering_buffer& from,
|
||||||
|
const rect* rc=0,
|
||||||
|
int x_to=0,
|
||||||
|
int y_to=0)
|
||||||
|
{
|
||||||
|
first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren.copy_from(from, rc, x_to, y_to);
|
||||||
|
}
|
||||||
|
while(next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
renderer_mclip(const renderer_mclip<PixelFormat>&);
|
||||||
|
const renderer_mclip<PixelFormat>&
|
||||||
|
operator = (const renderer_mclip<PixelFormat>&);
|
||||||
|
|
||||||
|
base_ren_type m_ren;
|
||||||
|
pod_deque<rect, 4> m_clip;
|
||||||
|
unsigned m_curr_cb;
|
||||||
|
rect m_bounds;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,916 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED
|
||||||
|
#define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "agg_line_aa_basics.h"
|
||||||
|
#include "agg_dda_line.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//========================================================line_image_scale
|
||||||
|
template<class Source> class line_image_scale
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename Source::color_type color_type;
|
||||||
|
|
||||||
|
line_image_scale(const Source& src, double height) :
|
||||||
|
m_source(src),
|
||||||
|
m_height(height),
|
||||||
|
m_scale(src.height() / height)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
double width() const { return m_source.width(); }
|
||||||
|
double height() const { return m_height; }
|
||||||
|
|
||||||
|
color_type pixel(int x, int y) const
|
||||||
|
{
|
||||||
|
double src_y = y * m_scale;
|
||||||
|
int h = int(m_source.height()) - 1;
|
||||||
|
int y1 = int(floor(src_y));
|
||||||
|
int y2 = y1 + 1;
|
||||||
|
color_type pix1 = (y1 < 0) ? m_source.pixel(x, 0).transparent() : m_source.pixel(x, y1);
|
||||||
|
color_type pix2 = (y2 > h) ? m_source.pixel(x, h).transparent() : m_source.pixel(x, y2);
|
||||||
|
return pix1.gradient(pix2, src_y - y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
line_image_scale(const line_image_scale<Source>&);
|
||||||
|
const line_image_scale<Source>& operator = (const line_image_scale<Source>&);
|
||||||
|
|
||||||
|
const Source& m_source;
|
||||||
|
double m_height;
|
||||||
|
double m_scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//======================================================line_image_pattern
|
||||||
|
template<class Filter> class line_image_pattern
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Filter filter_type;
|
||||||
|
typedef typename filter_type::color_type color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
~line_image_pattern()
|
||||||
|
{
|
||||||
|
delete [] m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
line_image_pattern(const Filter& filter) :
|
||||||
|
m_filter(&filter),
|
||||||
|
m_dilation(filter.dilation() + 1),
|
||||||
|
m_dilation_hr(m_dilation << line_subpixel_shift),
|
||||||
|
m_data(0),
|
||||||
|
m_width(0),
|
||||||
|
m_height(0),
|
||||||
|
m_width_hr(0),
|
||||||
|
m_half_height_hr(0),
|
||||||
|
m_offset_y_hr(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class Source>
|
||||||
|
line_image_pattern(const Filter& filter, const Source& src) :
|
||||||
|
m_filter(&filter),
|
||||||
|
m_dilation(filter.dilation() + 1),
|
||||||
|
m_dilation_hr(m_dilation << line_subpixel_shift),
|
||||||
|
m_data(0),
|
||||||
|
m_width(0),
|
||||||
|
m_height(0),
|
||||||
|
m_width_hr(0),
|
||||||
|
m_half_height_hr(0),
|
||||||
|
m_offset_y_hr(0)
|
||||||
|
{
|
||||||
|
create(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class Source> void create(const Source& src)
|
||||||
|
{
|
||||||
|
m_height = unsigned(ceil((double)src.height()));
|
||||||
|
m_width = unsigned(ceil((double)src.width()));
|
||||||
|
m_width_hr = int(src.width() * line_subpixel_size);
|
||||||
|
m_half_height_hr = int(src.height() * line_subpixel_size/2);
|
||||||
|
m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_size/2;
|
||||||
|
m_half_height_hr += line_subpixel_size/2;
|
||||||
|
|
||||||
|
delete [] m_data;
|
||||||
|
m_data = new color_type [(m_width + m_dilation * 2) * (m_height + m_dilation * 2)];
|
||||||
|
|
||||||
|
m_buf.attach(m_data, m_width + m_dilation * 2,
|
||||||
|
m_height + m_dilation * 2,
|
||||||
|
m_width + m_dilation * 2);
|
||||||
|
unsigned x, y;
|
||||||
|
color_type* d1;
|
||||||
|
color_type* d2;
|
||||||
|
for(y = 0; y < m_height; y++)
|
||||||
|
{
|
||||||
|
d1 = m_buf.row(y + m_dilation) + m_dilation;
|
||||||
|
for(x = 0; x < m_width; x++)
|
||||||
|
{
|
||||||
|
*d1++ = src.pixel(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const color_type* s1;
|
||||||
|
const color_type* s2;
|
||||||
|
for(y = 0; y < m_dilation; y++)
|
||||||
|
{
|
||||||
|
s1 = m_buf.row(m_height + m_dilation - 1) + m_dilation;
|
||||||
|
s2 = m_buf.row(m_dilation) + m_dilation;
|
||||||
|
d1 = m_buf.row(m_dilation + m_height + y) + m_dilation;
|
||||||
|
d2 = m_buf.row(m_dilation - y - 1) + m_dilation;
|
||||||
|
for(x = 0; x < m_width; x++)
|
||||||
|
{
|
||||||
|
*d1++ = color_type(*s1++, 0);
|
||||||
|
*d2++ = color_type(*s2++, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned h = m_height + m_dilation * 2;
|
||||||
|
for(y = 0; y < h; y++)
|
||||||
|
{
|
||||||
|
s1 = m_buf.row(y) + m_dilation;
|
||||||
|
s2 = m_buf.row(y) + m_dilation + m_width;
|
||||||
|
d1 = m_buf.row(y) + m_dilation + m_width;
|
||||||
|
d2 = m_buf.row(y) + m_dilation;
|
||||||
|
|
||||||
|
for(x = 0; x < m_dilation; x++)
|
||||||
|
{
|
||||||
|
*d1++ = *s1++;
|
||||||
|
*--d2 = *--s2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
int pattern_width() const { return m_width_hr; }
|
||||||
|
int line_width() const { return m_half_height_hr; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type pixel(int x, int y) const
|
||||||
|
{
|
||||||
|
return m_filter->pixel_high_res(m_buf.rows(),
|
||||||
|
x % m_width_hr + m_dilation_hr,
|
||||||
|
y + m_offset_y_hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const filter_type& filter() const { return m_filter; }
|
||||||
|
filter_type& filter() { return m_filter; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
line_image_pattern(const line_image_pattern<filter_type>&);
|
||||||
|
const line_image_pattern<filter_type>&
|
||||||
|
operator = (const line_image_pattern<filter_type>&);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
row_ptr_cache<color_type> m_buf;
|
||||||
|
const filter_type* m_filter;
|
||||||
|
unsigned m_dilation;
|
||||||
|
int m_dilation_hr;
|
||||||
|
color_type* m_data;
|
||||||
|
unsigned m_width;
|
||||||
|
unsigned m_height;
|
||||||
|
int m_width_hr;
|
||||||
|
int m_half_height_hr;
|
||||||
|
int m_offset_y_hr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=================================================line_image_pattern_pow2
|
||||||
|
template<class Filter> class line_image_pattern_pow2 :
|
||||||
|
public line_image_pattern<Filter>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Filter filter_type;
|
||||||
|
typedef typename filter_type::color_type color_type;
|
||||||
|
typedef line_image_pattern<Filter> base_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
line_image_pattern_pow2(const Filter& filter) :
|
||||||
|
line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class Source>
|
||||||
|
line_image_pattern_pow2(const Filter& filter, const Source& src) :
|
||||||
|
line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask)
|
||||||
|
{
|
||||||
|
create(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class Source> void create(const Source& src)
|
||||||
|
{
|
||||||
|
line_image_pattern<Filter>::create(src);
|
||||||
|
m_mask = 1;
|
||||||
|
while(m_mask < base_type::m_width)
|
||||||
|
{
|
||||||
|
m_mask <<= 1;
|
||||||
|
m_mask |= 1;
|
||||||
|
}
|
||||||
|
m_mask <<= line_subpixel_shift - 1;
|
||||||
|
m_mask |= line_subpixel_mask;
|
||||||
|
base_type::m_width_hr = m_mask + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void pixel(color_type* p, int x, int y) const
|
||||||
|
{
|
||||||
|
base_type::m_filter->pixel_high_res(
|
||||||
|
base_type::m_buf.rows(),
|
||||||
|
p,
|
||||||
|
(x & m_mask) + base_type::m_dilation_hr,
|
||||||
|
y + base_type::m_offset_y_hr);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
unsigned m_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================================================distance_interpolator4
|
||||||
|
class distance_interpolator4
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
distance_interpolator4() {}
|
||||||
|
distance_interpolator4(int x1, int y1, int x2, int y2,
|
||||||
|
int sx, int sy, int ex, int ey,
|
||||||
|
int len, double scale, int x, int y) :
|
||||||
|
m_dx(x2 - x1),
|
||||||
|
m_dy(y2 - y1),
|
||||||
|
m_dx_start(line_mr(sx) - line_mr(x1)),
|
||||||
|
m_dy_start(line_mr(sy) - line_mr(y1)),
|
||||||
|
m_dx_end(line_mr(ex) - line_mr(x2)),
|
||||||
|
m_dy_end(line_mr(ey) - line_mr(y2)),
|
||||||
|
|
||||||
|
m_dist(int(double(x + line_subpixel_size/2 - x2) * double(m_dy) -
|
||||||
|
double(y + line_subpixel_size/2 - y2) * double(m_dx))),
|
||||||
|
|
||||||
|
m_dist_start((line_mr(x + line_subpixel_size/2) - line_mr(sx)) * m_dy_start -
|
||||||
|
(line_mr(y + line_subpixel_size/2) - line_mr(sy)) * m_dx_start),
|
||||||
|
|
||||||
|
m_dist_end((line_mr(x + line_subpixel_size/2) - line_mr(ex)) * m_dy_end -
|
||||||
|
(line_mr(y + line_subpixel_size/2) - line_mr(ey)) * m_dx_end),
|
||||||
|
m_len(int(len / scale))
|
||||||
|
{
|
||||||
|
double d = len * scale;
|
||||||
|
int dx = int(((x2 - x1) << line_subpixel_shift) / d);
|
||||||
|
int dy = int(((y2 - y1) << line_subpixel_shift) / d);
|
||||||
|
m_dx_pict = -dy;
|
||||||
|
m_dy_pict = dx;
|
||||||
|
m_dist_pict = ((x + line_subpixel_size/2 - (x1 - dy)) * m_dy_pict -
|
||||||
|
(y + line_subpixel_size/2 - (y1 + dx)) * m_dx_pict) >>
|
||||||
|
line_subpixel_shift;
|
||||||
|
|
||||||
|
m_dx <<= line_subpixel_shift;
|
||||||
|
m_dy <<= line_subpixel_shift;
|
||||||
|
m_dx_start <<= line_mr_subpixel_shift;
|
||||||
|
m_dy_start <<= line_mr_subpixel_shift;
|
||||||
|
m_dx_end <<= line_mr_subpixel_shift;
|
||||||
|
m_dy_end <<= line_mr_subpixel_shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
void inc_x()
|
||||||
|
{
|
||||||
|
m_dist += m_dy;
|
||||||
|
m_dist_start += m_dy_start;
|
||||||
|
m_dist_pict += m_dy_pict;
|
||||||
|
m_dist_end += m_dy_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
void dec_x()
|
||||||
|
{
|
||||||
|
m_dist -= m_dy;
|
||||||
|
m_dist_start -= m_dy_start;
|
||||||
|
m_dist_pict -= m_dy_pict;
|
||||||
|
m_dist_end -= m_dy_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
void inc_y()
|
||||||
|
{
|
||||||
|
m_dist -= m_dx;
|
||||||
|
m_dist_start -= m_dx_start;
|
||||||
|
m_dist_pict -= m_dx_pict;
|
||||||
|
m_dist_end -= m_dx_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
void dec_y()
|
||||||
|
{
|
||||||
|
m_dist += m_dx;
|
||||||
|
m_dist_start += m_dx_start;
|
||||||
|
m_dist_pict += m_dx_pict;
|
||||||
|
m_dist_end += m_dx_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
void inc_x(int dy)
|
||||||
|
{
|
||||||
|
m_dist += m_dy;
|
||||||
|
m_dist_start += m_dy_start;
|
||||||
|
m_dist_pict += m_dy_pict;
|
||||||
|
m_dist_end += m_dy_end;
|
||||||
|
if(dy > 0)
|
||||||
|
{
|
||||||
|
m_dist -= m_dx;
|
||||||
|
m_dist_start -= m_dx_start;
|
||||||
|
m_dist_pict -= m_dx_pict;
|
||||||
|
m_dist_end -= m_dx_end;
|
||||||
|
}
|
||||||
|
if(dy < 0)
|
||||||
|
{
|
||||||
|
m_dist += m_dx;
|
||||||
|
m_dist_start += m_dx_start;
|
||||||
|
m_dist_pict += m_dx_pict;
|
||||||
|
m_dist_end += m_dx_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
void dec_x(int dy)
|
||||||
|
{
|
||||||
|
m_dist -= m_dy;
|
||||||
|
m_dist_start -= m_dy_start;
|
||||||
|
m_dist_pict -= m_dy_pict;
|
||||||
|
m_dist_end -= m_dy_end;
|
||||||
|
if(dy > 0)
|
||||||
|
{
|
||||||
|
m_dist -= m_dx;
|
||||||
|
m_dist_start -= m_dx_start;
|
||||||
|
m_dist_pict -= m_dx_pict;
|
||||||
|
m_dist_end -= m_dx_end;
|
||||||
|
}
|
||||||
|
if(dy < 0)
|
||||||
|
{
|
||||||
|
m_dist += m_dx;
|
||||||
|
m_dist_start += m_dx_start;
|
||||||
|
m_dist_pict += m_dx_pict;
|
||||||
|
m_dist_end += m_dx_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
void inc_y(int dx)
|
||||||
|
{
|
||||||
|
m_dist -= m_dx;
|
||||||
|
m_dist_start -= m_dx_start;
|
||||||
|
m_dist_pict -= m_dx_pict;
|
||||||
|
m_dist_end -= m_dx_end;
|
||||||
|
if(dx > 0)
|
||||||
|
{
|
||||||
|
m_dist += m_dy;
|
||||||
|
m_dist_start += m_dy_start;
|
||||||
|
m_dist_pict += m_dy_pict;
|
||||||
|
m_dist_end += m_dy_end;
|
||||||
|
}
|
||||||
|
if(dx < 0)
|
||||||
|
{
|
||||||
|
m_dist -= m_dy;
|
||||||
|
m_dist_start -= m_dy_start;
|
||||||
|
m_dist_pict -= m_dy_pict;
|
||||||
|
m_dist_end -= m_dy_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
void dec_y(int dx)
|
||||||
|
{
|
||||||
|
m_dist += m_dx;
|
||||||
|
m_dist_start += m_dx_start;
|
||||||
|
m_dist_pict += m_dx_pict;
|
||||||
|
m_dist_end += m_dx_end;
|
||||||
|
if(dx > 0)
|
||||||
|
{
|
||||||
|
m_dist += m_dy;
|
||||||
|
m_dist_start += m_dy_start;
|
||||||
|
m_dist_pict += m_dy_pict;
|
||||||
|
m_dist_end += m_dy_end;
|
||||||
|
}
|
||||||
|
if(dx < 0)
|
||||||
|
{
|
||||||
|
m_dist -= m_dy;
|
||||||
|
m_dist_start -= m_dy_start;
|
||||||
|
m_dist_pict -= m_dy_pict;
|
||||||
|
m_dist_end -= m_dy_end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
int dist() const { return m_dist; }
|
||||||
|
int dist_start() const { return m_dist_start; }
|
||||||
|
int dist_pict() const { return m_dist_pict; }
|
||||||
|
int dist_end() const { return m_dist_end; }
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
int dx() const { return m_dx; }
|
||||||
|
int dy() const { return m_dy; }
|
||||||
|
int dx_start() const { return m_dx_start; }
|
||||||
|
int dy_start() const { return m_dy_start; }
|
||||||
|
int dx_pict() const { return m_dx_pict; }
|
||||||
|
int dy_pict() const { return m_dy_pict; }
|
||||||
|
int dx_end() const { return m_dx_end; }
|
||||||
|
int dy_end() const { return m_dy_end; }
|
||||||
|
int len() const { return m_len; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
int m_dx;
|
||||||
|
int m_dy;
|
||||||
|
int m_dx_start;
|
||||||
|
int m_dy_start;
|
||||||
|
int m_dx_pict;
|
||||||
|
int m_dy_pict;
|
||||||
|
int m_dx_end;
|
||||||
|
int m_dy_end;
|
||||||
|
|
||||||
|
int m_dist;
|
||||||
|
int m_dist_start;
|
||||||
|
int m_dist_pict;
|
||||||
|
int m_dist_end;
|
||||||
|
int m_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==================================================line_interpolator_image
|
||||||
|
template<class Renderer> class line_interpolator_image
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Renderer renderer_type;
|
||||||
|
typedef typename Renderer::color_type color_type;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
max_half_width = 64
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
line_interpolator_image(renderer_type& ren, const line_parameters& lp,
|
||||||
|
int sx, int sy, int ex, int ey,
|
||||||
|
int pattern_start,
|
||||||
|
double scale_x) :
|
||||||
|
m_lp(lp),
|
||||||
|
m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) :
|
||||||
|
line_dbl_hr(lp.y2 - lp.y1),
|
||||||
|
lp.vertical ? abs(lp.y2 - lp.y1) :
|
||||||
|
abs(lp.x2 - lp.x1) + 1),
|
||||||
|
m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x,
|
||||||
|
lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask),
|
||||||
|
m_ren(ren),
|
||||||
|
m_x(lp.x1 >> line_subpixel_shift),
|
||||||
|
m_y(lp.y1 >> line_subpixel_shift),
|
||||||
|
m_old_x(m_x),
|
||||||
|
m_old_y(m_y),
|
||||||
|
m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) :
|
||||||
|
abs((lp.x2 >> line_subpixel_shift) - m_x))),
|
||||||
|
m_width(ren.subpixel_width()),
|
||||||
|
m_max_extent(m_width >> (line_subpixel_shift - 2)),
|
||||||
|
m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()),
|
||||||
|
m_step(0)
|
||||||
|
{
|
||||||
|
agg::dda2_line_interpolator li(0, lp.vertical ?
|
||||||
|
(lp.dy << agg::line_subpixel_shift) :
|
||||||
|
(lp.dx << agg::line_subpixel_shift),
|
||||||
|
lp.len);
|
||||||
|
|
||||||
|
unsigned i;
|
||||||
|
int stop = m_width + line_subpixel_size * 2;
|
||||||
|
for(i = 0; i < max_half_width; ++i)
|
||||||
|
{
|
||||||
|
m_dist_pos[i] = li.y();
|
||||||
|
if(m_dist_pos[i] >= stop) break;
|
||||||
|
++li;
|
||||||
|
}
|
||||||
|
m_dist_pos[i] = 0x7FFF0000;
|
||||||
|
|
||||||
|
int dist1_start;
|
||||||
|
int dist2_start;
|
||||||
|
int npix = 1;
|
||||||
|
|
||||||
|
if(lp.vertical)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
--m_li;
|
||||||
|
m_y -= lp.inc;
|
||||||
|
m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
|
||||||
|
|
||||||
|
if(lp.inc > 0) m_di.dec_y(m_x - m_old_x);
|
||||||
|
else m_di.inc_y(m_x - m_old_x);
|
||||||
|
|
||||||
|
m_old_x = m_x;
|
||||||
|
|
||||||
|
dist1_start = dist2_start = m_di.dist_start();
|
||||||
|
|
||||||
|
int dx = 0;
|
||||||
|
if(dist1_start < 0) ++npix;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dist1_start += m_di.dy_start();
|
||||||
|
dist2_start -= m_di.dy_start();
|
||||||
|
if(dist1_start < 0) ++npix;
|
||||||
|
if(dist2_start < 0) ++npix;
|
||||||
|
++dx;
|
||||||
|
}
|
||||||
|
while(m_dist_pos[dx] <= m_width);
|
||||||
|
if(npix == 0) break;
|
||||||
|
|
||||||
|
npix = 0;
|
||||||
|
}
|
||||||
|
while(--m_step >= -m_max_extent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
--m_li;
|
||||||
|
|
||||||
|
m_x -= lp.inc;
|
||||||
|
m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
|
||||||
|
|
||||||
|
if(lp.inc > 0) m_di.dec_x(m_y - m_old_y);
|
||||||
|
else m_di.inc_x(m_y - m_old_y);
|
||||||
|
|
||||||
|
m_old_y = m_y;
|
||||||
|
|
||||||
|
dist1_start = dist2_start = m_di.dist_start();
|
||||||
|
|
||||||
|
int dy = 0;
|
||||||
|
if(dist1_start < 0) ++npix;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dist1_start -= m_di.dx_start();
|
||||||
|
dist2_start += m_di.dx_start();
|
||||||
|
if(dist1_start < 0) ++npix;
|
||||||
|
if(dist2_start < 0) ++npix;
|
||||||
|
++dy;
|
||||||
|
}
|
||||||
|
while(m_dist_pos[dy] <= m_width);
|
||||||
|
if(npix == 0) break;
|
||||||
|
|
||||||
|
npix = 0;
|
||||||
|
}
|
||||||
|
while(--m_step >= -m_max_extent);
|
||||||
|
}
|
||||||
|
m_li.adjust_forward();
|
||||||
|
m_step -= m_max_extent;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
bool step_hor()
|
||||||
|
{
|
||||||
|
++m_li;
|
||||||
|
m_x += m_lp.inc;
|
||||||
|
m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift;
|
||||||
|
|
||||||
|
if(m_lp.inc > 0) m_di.inc_x(m_y - m_old_y);
|
||||||
|
else m_di.dec_x(m_y - m_old_y);
|
||||||
|
|
||||||
|
m_old_y = m_y;
|
||||||
|
|
||||||
|
int s1 = m_di.dist() / m_lp.len;
|
||||||
|
int s2 = -s1;
|
||||||
|
|
||||||
|
if(m_lp.inc < 0) s1 = -s1;
|
||||||
|
|
||||||
|
int dist_start;
|
||||||
|
int dist_pict;
|
||||||
|
int dist_end;
|
||||||
|
int dy;
|
||||||
|
int dist;
|
||||||
|
|
||||||
|
dist_start = m_di.dist_start();
|
||||||
|
dist_pict = m_di.dist_pict() + m_start;
|
||||||
|
dist_end = m_di.dist_end();
|
||||||
|
color_type* p0 = m_colors + max_half_width + 2;
|
||||||
|
color_type* p1 = p0;
|
||||||
|
|
||||||
|
int npix = 0;
|
||||||
|
p1->clear();
|
||||||
|
if(dist_end > 0)
|
||||||
|
{
|
||||||
|
if(dist_start <= 0)
|
||||||
|
{
|
||||||
|
m_ren.pixel(p1, dist_pict, s2);
|
||||||
|
}
|
||||||
|
++npix;
|
||||||
|
}
|
||||||
|
++p1;
|
||||||
|
|
||||||
|
dy = 1;
|
||||||
|
while((dist = m_dist_pos[dy]) - s1 <= m_width)
|
||||||
|
{
|
||||||
|
dist_start -= m_di.dx_start();
|
||||||
|
dist_pict -= m_di.dx_pict();
|
||||||
|
dist_end -= m_di.dx_end();
|
||||||
|
p1->clear();
|
||||||
|
if(dist_end > 0 && dist_start <= 0)
|
||||||
|
{
|
||||||
|
if(m_lp.inc > 0) dist = -dist;
|
||||||
|
m_ren.pixel(p1, dist_pict, s2 - dist);
|
||||||
|
++npix;
|
||||||
|
}
|
||||||
|
++p1;
|
||||||
|
++dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
dy = 1;
|
||||||
|
dist_start = m_di.dist_start();
|
||||||
|
dist_pict = m_di.dist_pict() + m_start;
|
||||||
|
dist_end = m_di.dist_end();
|
||||||
|
while((dist = m_dist_pos[dy]) + s1 <= m_width)
|
||||||
|
{
|
||||||
|
dist_start += m_di.dx_start();
|
||||||
|
dist_pict += m_di.dx_pict();
|
||||||
|
dist_end += m_di.dx_end();
|
||||||
|
--p0;
|
||||||
|
p0->clear();
|
||||||
|
if(dist_end > 0 && dist_start <= 0)
|
||||||
|
{
|
||||||
|
if(m_lp.inc > 0) dist = -dist;
|
||||||
|
m_ren.pixel(p0, dist_pict, s2 + dist);
|
||||||
|
++npix;
|
||||||
|
}
|
||||||
|
++dy;
|
||||||
|
}
|
||||||
|
m_ren.blend_color_vspan(m_x,
|
||||||
|
m_y - dy + 1,
|
||||||
|
unsigned(p1 - p0),
|
||||||
|
p0);
|
||||||
|
return npix && ++m_step < m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
bool step_ver()
|
||||||
|
{
|
||||||
|
++m_li;
|
||||||
|
m_y += m_lp.inc;
|
||||||
|
m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift;
|
||||||
|
|
||||||
|
if(m_lp.inc > 0) m_di.inc_y(m_x - m_old_x);
|
||||||
|
else m_di.dec_y(m_x - m_old_x);
|
||||||
|
|
||||||
|
m_old_x = m_x;
|
||||||
|
|
||||||
|
int s1 = m_di.dist() / m_lp.len;
|
||||||
|
int s2 = -s1;
|
||||||
|
|
||||||
|
if(m_lp.inc > 0) s1 = -s1;
|
||||||
|
|
||||||
|
int dist_start;
|
||||||
|
int dist_pict;
|
||||||
|
int dist_end;
|
||||||
|
int dist;
|
||||||
|
int dx;
|
||||||
|
|
||||||
|
dist_start = m_di.dist_start();
|
||||||
|
dist_pict = m_di.dist_pict() + m_start;
|
||||||
|
dist_end = m_di.dist_end();
|
||||||
|
color_type* p0 = m_colors + max_half_width + 2;
|
||||||
|
color_type* p1 = p0;
|
||||||
|
|
||||||
|
int npix = 0;
|
||||||
|
p1->clear();
|
||||||
|
if(dist_end > 0)
|
||||||
|
{
|
||||||
|
if(dist_start <= 0)
|
||||||
|
{
|
||||||
|
m_ren.pixel(p1, dist_pict, s2);
|
||||||
|
}
|
||||||
|
++npix;
|
||||||
|
}
|
||||||
|
++p1;
|
||||||
|
|
||||||
|
dx = 1;
|
||||||
|
while((dist = m_dist_pos[dx]) - s1 <= m_width)
|
||||||
|
{
|
||||||
|
dist_start += m_di.dy_start();
|
||||||
|
dist_pict += m_di.dy_pict();
|
||||||
|
dist_end += m_di.dy_end();
|
||||||
|
p1->clear();
|
||||||
|
if(dist_end > 0 && dist_start <= 0)
|
||||||
|
{
|
||||||
|
if(m_lp.inc > 0) dist = -dist;
|
||||||
|
m_ren.pixel(p1, dist_pict, s2 + dist);
|
||||||
|
++npix;
|
||||||
|
}
|
||||||
|
++p1;
|
||||||
|
++dx;
|
||||||
|
}
|
||||||
|
|
||||||
|
dx = 1;
|
||||||
|
dist_start = m_di.dist_start();
|
||||||
|
dist_pict = m_di.dist_pict() + m_start;
|
||||||
|
dist_end = m_di.dist_end();
|
||||||
|
while((dist = m_dist_pos[dx]) + s1 <= m_width)
|
||||||
|
{
|
||||||
|
dist_start -= m_di.dy_start();
|
||||||
|
dist_pict -= m_di.dy_pict();
|
||||||
|
dist_end -= m_di.dy_end();
|
||||||
|
--p0;
|
||||||
|
p0->clear();
|
||||||
|
if(dist_end > 0 && dist_start <= 0)
|
||||||
|
{
|
||||||
|
if(m_lp.inc > 0) dist = -dist;
|
||||||
|
m_ren.pixel(p0, dist_pict, s2 - dist);
|
||||||
|
++npix;
|
||||||
|
}
|
||||||
|
++dx;
|
||||||
|
}
|
||||||
|
m_ren.blend_color_hspan(m_x - dx + 1,
|
||||||
|
m_y,
|
||||||
|
unsigned(p1 - p0),
|
||||||
|
p0);
|
||||||
|
return npix && ++m_step < m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
int pattern_end() const { return m_start + m_di.len(); }
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
bool vertical() const { return m_lp.vertical; }
|
||||||
|
int width() const { return m_width; }
|
||||||
|
int count() const { return m_count; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
line_interpolator_image(const line_interpolator_image<Renderer>&);
|
||||||
|
const line_interpolator_image<Renderer>&
|
||||||
|
operator = (const line_interpolator_image<Renderer>&);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const line_parameters& m_lp;
|
||||||
|
dda2_line_interpolator m_li;
|
||||||
|
distance_interpolator4 m_di;
|
||||||
|
renderer_type& m_ren;
|
||||||
|
int m_plen;
|
||||||
|
int m_x;
|
||||||
|
int m_y;
|
||||||
|
int m_old_x;
|
||||||
|
int m_old_y;
|
||||||
|
int m_count;
|
||||||
|
int m_width;
|
||||||
|
int m_max_extent;
|
||||||
|
int m_start;
|
||||||
|
int m_step;
|
||||||
|
int m_dist_pos[max_half_width + 1];
|
||||||
|
color_type m_colors[max_half_width * 2 + 4];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================================================renderer_outline_image
|
||||||
|
template<class BaseRenderer, class ImagePattern>
|
||||||
|
class renderer_outline_image
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
typedef BaseRenderer base_ren_type;
|
||||||
|
typedef renderer_outline_image<BaseRenderer, ImagePattern> self_type;
|
||||||
|
typedef typename base_ren_type::color_type color_type;
|
||||||
|
typedef ImagePattern pattern_type;
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
renderer_outline_image(base_ren_type& ren, const pattern_type& patt) :
|
||||||
|
m_ren(&ren),
|
||||||
|
m_pattern(&patt),
|
||||||
|
m_start(0),
|
||||||
|
m_scale_x(1.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
void pattern(const pattern_type& p) { m_pattern = &p; }
|
||||||
|
const pattern_type& pattern() const { return *m_pattern; }
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
void scale_x(double s) { m_scale_x = s; }
|
||||||
|
double scale_x() const { return m_scale_x; }
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
int subpixel_width() const { return m_pattern->line_width(); }
|
||||||
|
int pattern_width() const { return m_pattern->pattern_width(); }
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
void pixel(color_type* p, int x, int y) const
|
||||||
|
{
|
||||||
|
m_pattern->pixel(p, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
void blend_color_hspan(int x, int y, unsigned len, const color_type* colors)
|
||||||
|
{
|
||||||
|
m_ren->blend_color_hspan(x, y, len, colors, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
void blend_color_vspan(int x, int y, unsigned len, const color_type* colors)
|
||||||
|
{
|
||||||
|
m_ren->blend_color_vspan(x, y, len, colors, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static bool accurate_join_only() { return true; }
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
template<class Cmp>
|
||||||
|
void semidot(Cmp, int, int, int, int)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
void line0(const line_parameters&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
void line1(const line_parameters&, int, int)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
void line2(const line_parameters&, int, int)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
void line3(const line_parameters& lp,
|
||||||
|
int sx, int sy, int ex, int ey)
|
||||||
|
{
|
||||||
|
line_interpolator_image<self_type> li(*this, lp,
|
||||||
|
sx, sy,
|
||||||
|
ex, ey,
|
||||||
|
m_start, m_scale_x);
|
||||||
|
if(li.vertical())
|
||||||
|
{
|
||||||
|
while(li.step_ver());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while(li.step_hor());
|
||||||
|
}
|
||||||
|
m_start = li.pattern_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
base_ren_type* m_ren;
|
||||||
|
const pattern_type* m_pattern;
|
||||||
|
int m_start;
|
||||||
|
double m_scale_x;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// class renderer_primitives
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_RENDERER_PRIMITIVES_INCLUDED
|
||||||
|
#define AGG_RENDERER_PRIMITIVES_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_renderer_base.h"
|
||||||
|
#include "agg_dda_line.h"
|
||||||
|
#include "agg_ellipse_bresenham.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//-----------------------------------------------------renderer_primitives
|
||||||
|
template<class BaseRenderer> class renderer_primitives
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef BaseRenderer base_ren_type;
|
||||||
|
typedef typename base_ren_type::color_type color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
renderer_primitives(base_ren_type& ren) :
|
||||||
|
m_ren(&ren),
|
||||||
|
m_fill_color(),
|
||||||
|
m_line_color(),
|
||||||
|
m_curr_x(0),
|
||||||
|
m_curr_y(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
static int coord(double c)
|
||||||
|
{
|
||||||
|
return int(c * line_bresenham_interpolator::subpixel_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void fill_color(const color_type& c) { m_fill_color = c; }
|
||||||
|
void line_color(const color_type& c) { m_line_color = c; }
|
||||||
|
const color_type& fill_color() const { return m_fill_color; }
|
||||||
|
const color_type& line_color() const { return m_line_color; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void rectangle(int x1, int y1, int x2, int y2)
|
||||||
|
{
|
||||||
|
m_ren->blend_hline(x1, y1, x2-1, m_line_color, cover_full);
|
||||||
|
m_ren->blend_vline(x2, y1, y2-1, m_line_color, cover_full);
|
||||||
|
m_ren->blend_hline(x1+1, y2, x2, m_line_color, cover_full);
|
||||||
|
m_ren->blend_vline(x1, y1+1, y2, m_line_color, cover_full);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void solid_rectangle(int x1, int y1, int x2, int y2)
|
||||||
|
{
|
||||||
|
m_ren->blend_bar(x1, y1, x2, y2, m_fill_color, cover_full);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void outlined_rectangle(int x1, int y1, int x2, int y2)
|
||||||
|
{
|
||||||
|
rectangle(x1, y1, x2, y2);
|
||||||
|
m_ren->blend_bar(x1+1, y1+1, x2-1, y2-1, m_fill_color, cover_full);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void ellipse(int x, int y, int rx, int ry)
|
||||||
|
{
|
||||||
|
ellipse_bresenham_interpolator ei(rx, ry);
|
||||||
|
int dx = 0;
|
||||||
|
int dy = -ry;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dx += ei.dx();
|
||||||
|
dy += ei.dy();
|
||||||
|
m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
|
||||||
|
m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
|
||||||
|
m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
|
||||||
|
m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
|
||||||
|
++ei;
|
||||||
|
}
|
||||||
|
while(dy < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void solid_ellipse(int x, int y, int rx, int ry)
|
||||||
|
{
|
||||||
|
ellipse_bresenham_interpolator ei(rx, ry);
|
||||||
|
int dx = 0;
|
||||||
|
int dy = -ry;
|
||||||
|
int dy0 = dy;
|
||||||
|
int dx0 = dx;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dx += ei.dx();
|
||||||
|
dy += ei.dy();
|
||||||
|
|
||||||
|
if(dy != dy0)
|
||||||
|
{
|
||||||
|
m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full);
|
||||||
|
m_ren->blend_hline(x-dx0, y-dy0, x+dx0, m_fill_color, cover_full);
|
||||||
|
}
|
||||||
|
dx0 = dx;
|
||||||
|
dy0 = dy;
|
||||||
|
++ei;
|
||||||
|
}
|
||||||
|
while(dy < 0);
|
||||||
|
m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void outlined_ellipse(int x, int y, int rx, int ry)
|
||||||
|
{
|
||||||
|
ellipse_bresenham_interpolator ei(rx, ry);
|
||||||
|
int dx = 0;
|
||||||
|
int dy = -ry;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dx += ei.dx();
|
||||||
|
dy += ei.dy();
|
||||||
|
|
||||||
|
m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full);
|
||||||
|
m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full);
|
||||||
|
m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full);
|
||||||
|
m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full);
|
||||||
|
|
||||||
|
if(ei.dy() && dx)
|
||||||
|
{
|
||||||
|
m_ren->blend_hline(x-dx+1, y+dy, x+dx-1, m_fill_color, cover_full);
|
||||||
|
m_ren->blend_hline(x-dx+1, y-dy, x+dx-1, m_fill_color, cover_full);
|
||||||
|
}
|
||||||
|
++ei;
|
||||||
|
}
|
||||||
|
while(dy < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void line(int x1, int y1, int x2, int y2, bool last=false)
|
||||||
|
{
|
||||||
|
line_bresenham_interpolator li(x1, y1, x2, y2);
|
||||||
|
|
||||||
|
unsigned len = li.len();
|
||||||
|
if(len == 0)
|
||||||
|
{
|
||||||
|
if(last)
|
||||||
|
{
|
||||||
|
m_ren->blend_pixel(li.line_lr(x1), li.line_lr(y1), m_line_color, cover_full);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(last) ++len;
|
||||||
|
|
||||||
|
if(li.is_ver())
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full);
|
||||||
|
li.vstep();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full);
|
||||||
|
li.hstep();
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void move_to(int x, int y)
|
||||||
|
{
|
||||||
|
m_curr_x = x;
|
||||||
|
m_curr_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void line_to(int x, int y, bool last=false)
|
||||||
|
{
|
||||||
|
line(m_curr_x, m_curr_y, x, y, last);
|
||||||
|
m_curr_x = x;
|
||||||
|
m_curr_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const base_ren_type& ren() const { return *m_ren; }
|
||||||
|
base_ren_type& ren() { return *m_ren; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const rendering_buffer& rbuf() const { return m_ren->rbuf(); }
|
||||||
|
rendering_buffer& rbuf() { return m_ren->rbuf(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
base_ren_type* m_ren;
|
||||||
|
color_type m_fill_color;
|
||||||
|
color_type m_line_color;
|
||||||
|
int m_curr_x;
|
||||||
|
int m_curr_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,264 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_RENDERER_RASTER_TEXT_INCLUDED
|
||||||
|
#define AGG_RENDERER_RASTER_TEXT_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//==============================================renderer_raster_htext_solid
|
||||||
|
template<class BaseRenderer, class GlyphGenerator>
|
||||||
|
class renderer_raster_htext_solid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef BaseRenderer ren_type;
|
||||||
|
typedef GlyphGenerator glyph_gen_type;
|
||||||
|
typedef typename glyph_gen_type::glyph_rect glyph_rect;
|
||||||
|
typedef typename ren_type::color_type color_type;
|
||||||
|
|
||||||
|
renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph) :
|
||||||
|
m_ren(&ren),
|
||||||
|
m_glyph(&glyph)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void color(const color_type& c) { m_color = c; }
|
||||||
|
const color_type& color() const { return m_color; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class CharT>
|
||||||
|
void render_text(double x, double y, const CharT* str, bool flip=false)
|
||||||
|
{
|
||||||
|
glyph_rect r;
|
||||||
|
while(*str)
|
||||||
|
{
|
||||||
|
m_glyph->prepare(&r, x, y, *str, flip);
|
||||||
|
if(r.x2 >= r.x1)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if(flip)
|
||||||
|
{
|
||||||
|
for(i = r.y1; i <= r.y2; i++)
|
||||||
|
{
|
||||||
|
m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1),
|
||||||
|
m_color,
|
||||||
|
m_glyph->span(r.y2 - i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(i = r.y1; i <= r.y2; i++)
|
||||||
|
{
|
||||||
|
m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1),
|
||||||
|
m_color,
|
||||||
|
m_glyph->span(i - r.y1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x += r.dx;
|
||||||
|
y += r.dy;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ren_type* m_ren;
|
||||||
|
glyph_gen_type* m_glyph;
|
||||||
|
color_type m_color;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================renderer_raster_vtext_solid
|
||||||
|
template<class BaseRenderer, class GlyphGenerator>
|
||||||
|
class renderer_raster_vtext_solid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef BaseRenderer ren_type;
|
||||||
|
typedef GlyphGenerator glyph_gen_type;
|
||||||
|
typedef typename glyph_gen_type::glyph_rect glyph_rect;
|
||||||
|
typedef typename ren_type::color_type color_type;
|
||||||
|
|
||||||
|
renderer_raster_vtext_solid(ren_type& ren, glyph_gen_type& glyph) :
|
||||||
|
m_ren(&ren),
|
||||||
|
m_glyph(&glyph)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void color(const color_type& c) { m_color = c; }
|
||||||
|
const color_type& color() const { return m_color; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class CharT>
|
||||||
|
void render_text(double x, double y, const CharT* str, bool flip=false)
|
||||||
|
{
|
||||||
|
glyph_rect r;
|
||||||
|
while(*str)
|
||||||
|
{
|
||||||
|
m_glyph->prepare(&r, x, y, *str, !flip);
|
||||||
|
if(r.x2 >= r.x1)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if(flip)
|
||||||
|
{
|
||||||
|
for(i = r.y1; i <= r.y2; i++)
|
||||||
|
{
|
||||||
|
m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1),
|
||||||
|
m_color,
|
||||||
|
m_glyph->span(i - r.y1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(i = r.y1; i <= r.y2; i++)
|
||||||
|
{
|
||||||
|
m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1),
|
||||||
|
m_color,
|
||||||
|
m_glyph->span(r.y2 - i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x += r.dx;
|
||||||
|
y += r.dy;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ren_type* m_ren;
|
||||||
|
glyph_gen_type* m_glyph;
|
||||||
|
color_type m_color;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================================================renderer_raster_htext
|
||||||
|
template<class ScanlineRenderer, class GlyphGenerator>
|
||||||
|
class renderer_raster_htext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef ScanlineRenderer ren_type;
|
||||||
|
typedef GlyphGenerator glyph_gen_type;
|
||||||
|
typedef typename glyph_gen_type::glyph_rect glyph_rect;
|
||||||
|
|
||||||
|
class scanline_single_span
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef agg::cover_type cover_type;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
struct const_span
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
unsigned len;
|
||||||
|
const cover_type* covers;
|
||||||
|
|
||||||
|
const_span() {}
|
||||||
|
const_span(int x_, unsigned len_, const cover_type* covers_) :
|
||||||
|
x(x_), len(len_), covers(covers_)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef const const_span* const_iterator;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
scanline_single_span(int x, int y, unsigned len,
|
||||||
|
const cover_type* covers) :
|
||||||
|
m_y(y),
|
||||||
|
m_span(x, len, covers)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
int y() const { return m_y; }
|
||||||
|
unsigned num_spans() const { return 1; }
|
||||||
|
const_iterator begin() const { return &m_span; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
int m_y;
|
||||||
|
const_span m_span;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
renderer_raster_htext(ren_type& ren, glyph_gen_type& glyph) :
|
||||||
|
m_ren(&ren),
|
||||||
|
m_glyph(&glyph)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class CharT>
|
||||||
|
void render_text(double x, double y, const CharT* str, bool flip=false)
|
||||||
|
{
|
||||||
|
glyph_rect r;
|
||||||
|
while(*str)
|
||||||
|
{
|
||||||
|
m_glyph->prepare(&r, x, y, *str, flip);
|
||||||
|
if(r.x2 >= r.x1)
|
||||||
|
{
|
||||||
|
m_ren->prepare(r.x2 - r.x1 + 1);
|
||||||
|
int i;
|
||||||
|
if(flip)
|
||||||
|
{
|
||||||
|
for(i = r.y1; i <= r.y2; i++)
|
||||||
|
{
|
||||||
|
m_ren->render(
|
||||||
|
scanline_single_span(r.x1,
|
||||||
|
i,
|
||||||
|
(r.x2 - r.x1 + 1),
|
||||||
|
m_glyph->span(r.y2 - i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(i = r.y1; i <= r.y2; i++)
|
||||||
|
{
|
||||||
|
m_ren->render(
|
||||||
|
scanline_single_span(r.x1,
|
||||||
|
i,
|
||||||
|
(r.x2 - r.x1 + 1),
|
||||||
|
m_glyph->span(i - r.y1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x += r.dx;
|
||||||
|
y += r.dy;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ren_type* m_ren;
|
||||||
|
glyph_gen_type* m_glyph;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,285 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_RENDERER_SCANLINE_INCLUDED
|
||||||
|
#define AGG_RENDERER_SCANLINE_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_renderer_base.h"
|
||||||
|
#include "agg_render_scanlines.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//====================================================renderer_scanline_aa
|
||||||
|
template<class BaseRenderer, class SpanGenerator> class renderer_scanline_aa
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef BaseRenderer base_ren_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
renderer_scanline_aa(base_ren_type& ren, SpanGenerator& span_gen) :
|
||||||
|
m_ren(&ren),
|
||||||
|
m_span_gen(&span_gen)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void prepare(unsigned max_span_len)
|
||||||
|
{
|
||||||
|
m_span_gen->prepare(max_span_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class Scanline> void render(const Scanline& sl)
|
||||||
|
{
|
||||||
|
int y = sl.y();
|
||||||
|
m_ren->first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int xmin = m_ren->xmin();
|
||||||
|
int xmax = m_ren->xmax();
|
||||||
|
|
||||||
|
if(y >= m_ren->ymin() && y <= m_ren->ymax())
|
||||||
|
{
|
||||||
|
unsigned num_spans = sl.num_spans();
|
||||||
|
typename Scanline::const_iterator span = sl.begin();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int x = span->x;
|
||||||
|
int len = span->len;
|
||||||
|
bool solid = false;
|
||||||
|
const typename Scanline::cover_type* covers = span->covers;
|
||||||
|
|
||||||
|
if(len < 0)
|
||||||
|
{
|
||||||
|
solid = true;
|
||||||
|
len = -len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(x < xmin)
|
||||||
|
{
|
||||||
|
len -= xmin - x;
|
||||||
|
covers += xmin - x;
|
||||||
|
x = xmin;
|
||||||
|
}
|
||||||
|
if(len > 0)
|
||||||
|
{
|
||||||
|
if(x + len > xmax)
|
||||||
|
{
|
||||||
|
len = xmax - x + 1;
|
||||||
|
}
|
||||||
|
if(len > 0)
|
||||||
|
{
|
||||||
|
m_ren->blend_color_hspan_no_clip(
|
||||||
|
x, y, len,
|
||||||
|
m_span_gen->generate(x, y, len),
|
||||||
|
solid ? 0 : covers,
|
||||||
|
*covers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++span;
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(m_ren->next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
base_ren_type* m_ren;
|
||||||
|
SpanGenerator* m_span_gen;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============================================renderer_scanline_aa_solid
|
||||||
|
template<class BaseRenderer> class renderer_scanline_aa_solid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef BaseRenderer base_ren_type;
|
||||||
|
typedef typename base_ren_type::color_type color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
renderer_scanline_aa_solid(base_ren_type& ren) :
|
||||||
|
m_ren(&ren)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void color(const color_type& c) { m_color = c; }
|
||||||
|
const color_type& color() const { return m_color; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void prepare(unsigned) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class Scanline> void render(const Scanline& sl)
|
||||||
|
{
|
||||||
|
int y = sl.y();
|
||||||
|
unsigned num_spans = sl.num_spans();
|
||||||
|
typename Scanline::const_iterator span = sl.begin();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int x = span->x;
|
||||||
|
if(span->len > 0)
|
||||||
|
{
|
||||||
|
m_ren->blend_solid_hspan(x, y, (unsigned)span->len,
|
||||||
|
m_color,
|
||||||
|
span->covers);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ren->blend_hline(x, y, (unsigned)(x - span->len - 1),
|
||||||
|
m_color,
|
||||||
|
*(span->covers));
|
||||||
|
}
|
||||||
|
++span;
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
base_ren_type* m_ren;
|
||||||
|
color_type m_color;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================================================renderer_scanline_bin
|
||||||
|
template<class BaseRenderer, class SpanGenerator> class renderer_scanline_bin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef BaseRenderer base_ren_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
renderer_scanline_bin(base_ren_type& ren, SpanGenerator& span_gen) :
|
||||||
|
m_ren(&ren),
|
||||||
|
m_span_gen(&span_gen)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void prepare(unsigned max_span_len)
|
||||||
|
{
|
||||||
|
m_span_gen->prepare(max_span_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class Scanline> void render(const Scanline& sl)
|
||||||
|
{
|
||||||
|
int y = sl.y();
|
||||||
|
m_ren->first_clip_box();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int xmin = m_ren->xmin();
|
||||||
|
int xmax = m_ren->xmax();
|
||||||
|
|
||||||
|
if(y >= m_ren->ymin() && y <= m_ren->ymax())
|
||||||
|
{
|
||||||
|
unsigned num_spans = sl.num_spans();
|
||||||
|
typename Scanline::const_iterator span = sl.begin();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int x = span->x;
|
||||||
|
int len = span->len;
|
||||||
|
|
||||||
|
if(len < 0) len = -len;
|
||||||
|
if(x < xmin)
|
||||||
|
{
|
||||||
|
len -= xmin - x;
|
||||||
|
x = xmin;
|
||||||
|
}
|
||||||
|
if(len > 0)
|
||||||
|
{
|
||||||
|
if(x + len > xmax)
|
||||||
|
{
|
||||||
|
len = xmax - x + 1;
|
||||||
|
}
|
||||||
|
if(len > 0)
|
||||||
|
{
|
||||||
|
m_ren->blend_color_hspan_no_clip(
|
||||||
|
x, y, len,
|
||||||
|
m_span_gen->generate(x, y, len),
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++span;
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(m_ren->next_clip_box());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
base_ren_type* m_ren;
|
||||||
|
SpanGenerator* m_span_gen;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================renderer_scanline_bin_solid
|
||||||
|
template<class BaseRenderer> class renderer_scanline_bin_solid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef BaseRenderer base_ren_type;
|
||||||
|
typedef typename base_ren_type::color_type color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
renderer_scanline_bin_solid(base_ren_type& ren) :
|
||||||
|
m_ren(&ren)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void color(const color_type& c) { m_color = c; }
|
||||||
|
const color_type& color() const { return m_color; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void prepare(unsigned) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class Scanline> void render(const Scanline& sl)
|
||||||
|
{
|
||||||
|
unsigned num_spans = sl.num_spans();
|
||||||
|
typename Scanline::const_iterator span = sl.begin();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_ren->blend_hline(span->x,
|
||||||
|
sl.y(),
|
||||||
|
span->x - 1 + ((span->len < 0) ?
|
||||||
|
-span->len :
|
||||||
|
span->len),
|
||||||
|
m_color,
|
||||||
|
cover_full);
|
||||||
|
++span;
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
base_ren_type* m_ren;
|
||||||
|
color_type m_color;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// class rendering_buffer
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_RENDERING_BUFFER_INCLUDED
|
||||||
|
#define AGG_RENDERING_BUFFER_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//==========================================================row_ptr_cache
|
||||||
|
template<class T> class row_ptr_cache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
~row_ptr_cache()
|
||||||
|
{
|
||||||
|
delete [] m_rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
row_ptr_cache() :
|
||||||
|
m_buf(0),
|
||||||
|
m_rows(0),
|
||||||
|
m_width(0),
|
||||||
|
m_height(0),
|
||||||
|
m_stride(0),
|
||||||
|
m_max_height(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) :
|
||||||
|
m_buf(0),
|
||||||
|
m_rows(0),
|
||||||
|
m_width(0),
|
||||||
|
m_height(0),
|
||||||
|
m_stride(0),
|
||||||
|
m_max_height(0)
|
||||||
|
{
|
||||||
|
attach(buf, width, height, stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void attach(T* buf, unsigned width, unsigned height, int stride)
|
||||||
|
{
|
||||||
|
m_buf = buf;
|
||||||
|
m_width = width;
|
||||||
|
m_height = height;
|
||||||
|
m_stride = stride;
|
||||||
|
if(height > m_max_height)
|
||||||
|
{
|
||||||
|
delete [] m_rows;
|
||||||
|
m_rows = new T* [m_max_height = height];
|
||||||
|
}
|
||||||
|
|
||||||
|
T* row_ptr = m_buf;
|
||||||
|
|
||||||
|
if(stride < 0)
|
||||||
|
{
|
||||||
|
row_ptr = m_buf - int(height - 1) * stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
T** rows = m_rows;
|
||||||
|
|
||||||
|
while(height--)
|
||||||
|
{
|
||||||
|
*rows++ = row_ptr;
|
||||||
|
row_ptr += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const T* buf() const { return m_buf; }
|
||||||
|
unsigned width() const { return m_width; }
|
||||||
|
unsigned height() const { return m_height; }
|
||||||
|
int stride() const { return m_stride; }
|
||||||
|
unsigned stride_abs() const
|
||||||
|
{
|
||||||
|
return (m_stride < 0) ?
|
||||||
|
unsigned(-m_stride) :
|
||||||
|
unsigned(m_stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
T* row(unsigned y) { return m_rows[y]; }
|
||||||
|
const T* row(unsigned y) const { return m_rows[y]; }
|
||||||
|
T const* const* rows() const { return m_rows; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void copy_from(const row_ptr_cache<T>& mtx)
|
||||||
|
{
|
||||||
|
unsigned h = height();
|
||||||
|
if(mtx.height() < h) h = mtx.height();
|
||||||
|
|
||||||
|
unsigned l = stride_abs();
|
||||||
|
if(mtx.stride_abs() < l) l = mtx.stride_abs();
|
||||||
|
|
||||||
|
l *= sizeof(T);
|
||||||
|
|
||||||
|
unsigned y;
|
||||||
|
for (y = 0; y < h; y++)
|
||||||
|
{
|
||||||
|
memcpy(row(y), mtx.row(y), l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Prohibit copying
|
||||||
|
row_ptr_cache(const row_ptr_cache<T>&);
|
||||||
|
const row_ptr_cache<T>& operator = (const row_ptr_cache<T>&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
T* m_buf; // Pointer to renrdering buffer
|
||||||
|
T** m_rows; // Pointers to each row of the buffer
|
||||||
|
unsigned m_width; // Width in pixels
|
||||||
|
unsigned m_height; // Height in pixels
|
||||||
|
int m_stride; // Number of bytes per row. Can be < 0
|
||||||
|
unsigned m_max_height; // The maximal height (currently allocated)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========================================================rendering_buffer
|
||||||
|
typedef row_ptr_cache<int8u> rendering_buffer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Rounded rectangle vertex generator
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_ROUNDED_RECT_INCLUDED
|
||||||
|
#define AGG_ROUNDED_RECT_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_arc.h"
|
||||||
|
#include "agg_vertex_iterator.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//------------------------------------------------------------rounded_rect
|
||||||
|
//
|
||||||
|
// See Implemantation agg_rounded_rect.cpp
|
||||||
|
//
|
||||||
|
class rounded_rect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
rounded_rect() {}
|
||||||
|
rounded_rect(double x1, double y1, double x2, double y2, double r);
|
||||||
|
|
||||||
|
void rect(double x1, double y1, double x2, double y2);
|
||||||
|
void radius(double r);
|
||||||
|
void radius(double rx, double ry);
|
||||||
|
void radius(double rx_bottom, double ry_bottom, double rx_top, double ry_top);
|
||||||
|
void radius(double rx1, double ry1, double rx2, double ry2,
|
||||||
|
double rx3, double ry3, double rx4, double ry4);
|
||||||
|
void normalize_radius();
|
||||||
|
|
||||||
|
void approximation_scale(double s) { m_arc.approximation_scale(s); }
|
||||||
|
double approximation_scale() const { return m_arc.approximation_scale(); }
|
||||||
|
|
||||||
|
void rewind(unsigned);
|
||||||
|
unsigned vertex(double* x, double* y);
|
||||||
|
|
||||||
|
typedef rounded_rect source_type;
|
||||||
|
typedef vertex_iterator<source_type> iterator;
|
||||||
|
iterator begin(unsigned id) { return iterator(*this, id); }
|
||||||
|
iterator end() { return iterator(path_cmd_stop); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_x1;
|
||||||
|
double m_y1;
|
||||||
|
double m_x2;
|
||||||
|
double m_y2;
|
||||||
|
double m_rx1;
|
||||||
|
double m_ry1;
|
||||||
|
double m_rx2;
|
||||||
|
double m_ry2;
|
||||||
|
double m_rx3;
|
||||||
|
double m_ry3;
|
||||||
|
double m_rx4;
|
||||||
|
double m_ry4;
|
||||||
|
unsigned m_status;
|
||||||
|
arc m_arc;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Class scanline_bin - binary scanline.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_SCANLINE_BIN_INCLUDED
|
||||||
|
#define AGG_SCANLINE_BIN_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//=============================================================scanline_bin
|
||||||
|
//
|
||||||
|
// This is binary scaline container which supports the interface
|
||||||
|
// used in the rasterizer::render(). See description of agg_scanline_u8
|
||||||
|
// for details.
|
||||||
|
//
|
||||||
|
// Rendering:
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// int y = sl.y();
|
||||||
|
//
|
||||||
|
// ************************************
|
||||||
|
// ...Perform vertical clipping here...
|
||||||
|
// ************************************
|
||||||
|
//
|
||||||
|
// unsigned num_spans = sl.num_spans();
|
||||||
|
// const agg::scanline_bin::span* cur_span = sl.spans();
|
||||||
|
//
|
||||||
|
// do
|
||||||
|
// {
|
||||||
|
// x = cur_span->x;
|
||||||
|
// len = cur_span->len;
|
||||||
|
//
|
||||||
|
// **************************************
|
||||||
|
// ...Perform horizontal clipping here...
|
||||||
|
// **************************************
|
||||||
|
//
|
||||||
|
// hor_line(x, y, len)
|
||||||
|
// ++cur_span;
|
||||||
|
// }
|
||||||
|
// while(--num_spans);
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
class scanline_bin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct span
|
||||||
|
{
|
||||||
|
int16 x;
|
||||||
|
int16 len;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef const span* const_iterator;
|
||||||
|
|
||||||
|
~scanline_bin()
|
||||||
|
{
|
||||||
|
delete [] m_spans;
|
||||||
|
}
|
||||||
|
|
||||||
|
scanline_bin() :
|
||||||
|
m_max_len(0),
|
||||||
|
m_last_x(0x7FFF),
|
||||||
|
m_spans(0),
|
||||||
|
m_cur_span(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(int min_x, int max_x);
|
||||||
|
void add_cell(int x, unsigned);
|
||||||
|
void add_cells(int x, unsigned len, const void*);
|
||||||
|
void add_span(int x, unsigned len, unsigned);
|
||||||
|
void finalize(int y) { m_y = y; }
|
||||||
|
void reset_spans();
|
||||||
|
|
||||||
|
int y() const { return m_y; }
|
||||||
|
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
|
||||||
|
const_iterator begin() const { return m_spans + 1; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
scanline_bin(const scanline_bin&);
|
||||||
|
const scanline_bin operator = (const scanline_bin&);
|
||||||
|
|
||||||
|
unsigned m_max_len;
|
||||||
|
int m_last_x;
|
||||||
|
int m_y;
|
||||||
|
span* m_spans;
|
||||||
|
span* m_cur_span;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void scanline_bin::reset(int min_x, int max_x)
|
||||||
|
{
|
||||||
|
unsigned max_len = max_x - min_x + 3;
|
||||||
|
if(max_len > m_max_len)
|
||||||
|
{
|
||||||
|
delete [] m_spans;
|
||||||
|
m_spans = new span [max_len];
|
||||||
|
m_max_len = max_len;
|
||||||
|
}
|
||||||
|
m_last_x = 0x7FFF;
|
||||||
|
m_cur_span = m_spans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void scanline_bin::reset_spans()
|
||||||
|
{
|
||||||
|
m_last_x = 0x7FFF;
|
||||||
|
m_cur_span = m_spans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void scanline_bin::add_cell(int x, unsigned)
|
||||||
|
{
|
||||||
|
if(x == m_last_x+1)
|
||||||
|
{
|
||||||
|
m_cur_span->len++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++m_cur_span;
|
||||||
|
m_cur_span->x = (int16)x;
|
||||||
|
m_cur_span->len = 1;
|
||||||
|
}
|
||||||
|
m_last_x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void scanline_bin::add_span(int x, unsigned len, unsigned)
|
||||||
|
{
|
||||||
|
if(x == m_last_x+1)
|
||||||
|
{
|
||||||
|
m_cur_span->len = (int16)(m_cur_span->len + len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++m_cur_span;
|
||||||
|
m_cur_span->x = (int16)x;
|
||||||
|
m_cur_span->len = (int16)len;
|
||||||
|
}
|
||||||
|
m_last_x = x + len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void scanline_bin::add_cells(int x, unsigned len, const void*)
|
||||||
|
{
|
||||||
|
add_span(x, len, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
File diff suppressed because it is too large
Load Diff
Executable
+197
@@ -0,0 +1,197 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Class scanline_p - a general purpose scanline container with packed spans.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_SCANLINE_P_INCLUDED
|
||||||
|
#define AGG_SCANLINE_P_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//==============================================================scanline_p
|
||||||
|
//
|
||||||
|
// This is a general purpose scaline container which supports the interface
|
||||||
|
// used in the rasterizer::render(). See description of agg_scanline_u
|
||||||
|
// for details.
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> class scanline_p
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T cover_type;
|
||||||
|
|
||||||
|
struct span
|
||||||
|
{
|
||||||
|
int16 x;
|
||||||
|
int16 len; // If negative, it's a solid span, covers is valid
|
||||||
|
const T* covers;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef span* iterator;
|
||||||
|
typedef const span* const_iterator;
|
||||||
|
|
||||||
|
~scanline_p()
|
||||||
|
{
|
||||||
|
delete [] m_spans;
|
||||||
|
delete [] m_covers;
|
||||||
|
}
|
||||||
|
|
||||||
|
scanline_p() :
|
||||||
|
m_max_len(0),
|
||||||
|
m_last_x(0x7FFFFFF0),
|
||||||
|
m_covers(0),
|
||||||
|
m_cover_ptr(0),
|
||||||
|
m_spans(0),
|
||||||
|
m_cur_span(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(int min_x, int max_x);
|
||||||
|
void add_cell(int x, unsigned cover);
|
||||||
|
void add_cells(int x, unsigned len, const T* covers);
|
||||||
|
void add_span(int x, unsigned len, unsigned cover);
|
||||||
|
void finalize(int y) { m_y = y; }
|
||||||
|
void reset_spans();
|
||||||
|
|
||||||
|
int y() const { return m_y; }
|
||||||
|
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
|
||||||
|
const_iterator begin() const { return m_spans + 1; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
scanline_p(const scanline_p<T>&);
|
||||||
|
const scanline_p<T>& operator = (const scanline_p<T>&);
|
||||||
|
|
||||||
|
unsigned m_max_len;
|
||||||
|
int m_last_x;
|
||||||
|
int m_y;
|
||||||
|
T* m_covers;
|
||||||
|
T* m_cover_ptr;
|
||||||
|
span* m_spans;
|
||||||
|
span* m_cur_span;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T>
|
||||||
|
void scanline_p<T>::reset(int min_x, int max_x)
|
||||||
|
{
|
||||||
|
unsigned max_len = max_x - min_x + 3;
|
||||||
|
if(max_len > m_max_len)
|
||||||
|
{
|
||||||
|
delete [] m_spans;
|
||||||
|
delete [] m_covers;
|
||||||
|
m_covers = new T [max_len];
|
||||||
|
m_spans = new span [max_len];
|
||||||
|
m_max_len = max_len;
|
||||||
|
}
|
||||||
|
m_last_x = 0x7FFFFFF0;
|
||||||
|
m_cover_ptr = m_covers;
|
||||||
|
m_cur_span = m_spans;
|
||||||
|
m_cur_span->len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T>
|
||||||
|
void scanline_p<T>::reset_spans()
|
||||||
|
{
|
||||||
|
m_last_x = 0x7FFFFFF0;
|
||||||
|
m_cover_ptr = m_covers;
|
||||||
|
m_cur_span = m_spans;
|
||||||
|
m_cur_span->len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T>
|
||||||
|
void scanline_p<T>::add_cell(int x, unsigned cover)
|
||||||
|
{
|
||||||
|
*m_cover_ptr = (T)cover;
|
||||||
|
if(x == m_last_x+1 && m_cur_span->len > 0)
|
||||||
|
{
|
||||||
|
m_cur_span->len++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_cur_span++;
|
||||||
|
m_cur_span->covers = m_cover_ptr;
|
||||||
|
m_cur_span->x = (int16)x;
|
||||||
|
m_cur_span->len = 1;
|
||||||
|
}
|
||||||
|
m_last_x = x;
|
||||||
|
m_cover_ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T>
|
||||||
|
void scanline_p<T>::add_cells(int x, unsigned len, const T* covers)
|
||||||
|
{
|
||||||
|
memcpy(m_cover_ptr, covers, len * sizeof(T));
|
||||||
|
if(x == m_last_x+1 && m_cur_span->len > 0)
|
||||||
|
{
|
||||||
|
m_cur_span->len += (int16)len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_cur_span++;
|
||||||
|
m_cur_span->covers = m_cover_ptr;
|
||||||
|
m_cur_span->x = (int16)x;
|
||||||
|
m_cur_span->len = (int16)len;
|
||||||
|
}
|
||||||
|
m_cover_ptr += len;
|
||||||
|
m_last_x = x + len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T>
|
||||||
|
void scanline_p<T>::add_span(int x, unsigned len, unsigned cover)
|
||||||
|
{
|
||||||
|
if(x == m_last_x+1 &&
|
||||||
|
m_cur_span->len < 0 &&
|
||||||
|
cover == *m_cur_span->covers)
|
||||||
|
{
|
||||||
|
m_cur_span->len -= (int16)len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*m_cover_ptr = (T)cover;
|
||||||
|
m_cur_span++;
|
||||||
|
m_cur_span->covers = m_cover_ptr++;
|
||||||
|
m_cur_span->x = (int16)x;
|
||||||
|
m_cur_span->len = -((int16)len);
|
||||||
|
}
|
||||||
|
m_last_x = x + len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================scanline_p8
|
||||||
|
typedef scanline_p<int8u> scanline_p8;
|
||||||
|
|
||||||
|
//============================================================scanline_p16
|
||||||
|
typedef scanline_p<int16u> scanline_p16;
|
||||||
|
|
||||||
|
//============================================================scanline_p32
|
||||||
|
typedef scanline_p<int32u> scanline_p32;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,795 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SCANLINE_STORAGE_AA_INCLUDED
|
||||||
|
#define AGG_SCANLINE_STORAGE_AA_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "agg_array.h"
|
||||||
|
#include "agg_render_scanlines.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//----------------------------------------------scanline_cell_storage
|
||||||
|
template<class T> class scanline_cell_storage
|
||||||
|
{
|
||||||
|
struct extra_span
|
||||||
|
{
|
||||||
|
unsigned len;
|
||||||
|
T* ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef T value_type;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
~scanline_cell_storage()
|
||||||
|
{
|
||||||
|
remove_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
scanline_cell_storage() :
|
||||||
|
m_cells(128-2),
|
||||||
|
m_extra_storage()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// Copying
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
scanline_cell_storage(const scanline_cell_storage<T>& v) :
|
||||||
|
m_cells(v.m_cells),
|
||||||
|
m_extra_storage()
|
||||||
|
{
|
||||||
|
copy_extra_storage(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
const scanline_cell_storage<T>&
|
||||||
|
operator = (const scanline_cell_storage<T>& v)
|
||||||
|
{
|
||||||
|
remove_all();
|
||||||
|
m_cells = v.m_cells;
|
||||||
|
copy_extra_storage(v);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
void remove_all()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = m_extra_storage.size()-1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
delete [] m_extra_storage[(unsigned)i].ptr;
|
||||||
|
}
|
||||||
|
m_extra_storage.remove_all();
|
||||||
|
m_cells.remove_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
int add_cells(const T* cells, unsigned num_cells)
|
||||||
|
{
|
||||||
|
int idx = m_cells.allocate_continuous_block(num_cells);
|
||||||
|
if(idx >= 0)
|
||||||
|
{
|
||||||
|
T* ptr = &m_cells[idx];
|
||||||
|
memcpy(ptr, cells, sizeof(T) * num_cells);
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
extra_span s;
|
||||||
|
s.len = num_cells;
|
||||||
|
s.ptr = new T [num_cells];
|
||||||
|
memcpy(s.ptr, cells, sizeof(T) * num_cells);
|
||||||
|
m_extra_storage.add(s);
|
||||||
|
return -int(m_extra_storage.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
const T* operator [] (int idx) const
|
||||||
|
{
|
||||||
|
if(idx >= 0)
|
||||||
|
{
|
||||||
|
if((unsigned)idx >= m_cells.size()) return 0;
|
||||||
|
return &m_cells[(unsigned)idx];
|
||||||
|
}
|
||||||
|
unsigned i = unsigned(-idx - 1);
|
||||||
|
if(i >= m_extra_storage.size()) return 0;
|
||||||
|
return m_extra_storage[i].ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
T* operator [] (int idx)
|
||||||
|
{
|
||||||
|
if(idx >= 0)
|
||||||
|
{
|
||||||
|
if((unsigned)idx >= m_cells.size()) return 0;
|
||||||
|
return &m_cells[(unsigned)idx];
|
||||||
|
}
|
||||||
|
unsigned i = unsigned(-idx - 1);
|
||||||
|
if(i >= m_extra_storage.size()) return 0;
|
||||||
|
return m_extra_storage[i].ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void copy_extra_storage(const scanline_cell_storage<T>& v)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < v.m_extra_storage.size(); ++i)
|
||||||
|
{
|
||||||
|
const extra_span& src = v.m_extra_storage[i];
|
||||||
|
extra_span dst;
|
||||||
|
dst.len = src.len;
|
||||||
|
dst.ptr = new T [dst.len];
|
||||||
|
memcpy(dst.ptr, src.ptr, dst.len * sizeof(T));
|
||||||
|
m_extra_storage.add(dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pod_deque<T, 12> m_cells;
|
||||||
|
pod_deque<extra_span, 6> m_extra_storage;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------scanline_storage_aa
|
||||||
|
template<class T> class scanline_storage_aa
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T cover_type;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
struct span_data
|
||||||
|
{
|
||||||
|
int16 x;
|
||||||
|
int16 len; // If negative, it's a solid span, covers is valid
|
||||||
|
int covers_id; // The index of the cells in the scanline_cell_storage
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
struct scanline_data
|
||||||
|
{
|
||||||
|
int y;
|
||||||
|
unsigned num_spans;
|
||||||
|
unsigned start_span;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
class embedded_scanline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
class const_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct span
|
||||||
|
{
|
||||||
|
int16 x;
|
||||||
|
int16 len; // If negative, it's a solid span, covers is valid
|
||||||
|
const T* covers;
|
||||||
|
};
|
||||||
|
|
||||||
|
const_iterator(const embedded_scanline& sl) :
|
||||||
|
m_storage(sl.m_storage),
|
||||||
|
m_span_idx(sl.m_scanline.start_span)
|
||||||
|
{
|
||||||
|
init_span();
|
||||||
|
}
|
||||||
|
|
||||||
|
const span& operator*() const { return m_span; }
|
||||||
|
const span* operator->() const { return &m_span; }
|
||||||
|
|
||||||
|
void operator ++ ()
|
||||||
|
{
|
||||||
|
++m_span_idx;
|
||||||
|
init_span();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init_span()
|
||||||
|
{
|
||||||
|
const span_data& s = m_storage->span_by_index(m_span_idx);
|
||||||
|
m_span.x = s.x;
|
||||||
|
m_span.len = s.len;
|
||||||
|
m_span.covers = m_storage->covers_by_index(s.covers_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const scanline_storage_aa* m_storage;
|
||||||
|
unsigned m_span_idx;
|
||||||
|
span m_span;
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class const_iterator;
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
embedded_scanline(const scanline_storage_aa& storage) :
|
||||||
|
m_storage(&storage)
|
||||||
|
{
|
||||||
|
init(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
void reset(int, int) {}
|
||||||
|
unsigned num_spans() const { return m_scanline.num_spans; }
|
||||||
|
int y() const { return m_scanline.y; }
|
||||||
|
const_iterator begin() const { return const_iterator(*this); }
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
void init(unsigned scanline_idx)
|
||||||
|
{
|
||||||
|
m_scanline_idx = scanline_idx;
|
||||||
|
m_scanline = m_storage->scanline_by_index(m_scanline_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const scanline_storage_aa* m_storage;
|
||||||
|
scanline_data m_scanline;
|
||||||
|
unsigned m_scanline_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
scanline_storage_aa() :
|
||||||
|
m_covers(),
|
||||||
|
m_spans(256-2), // Block increment size
|
||||||
|
m_scanlines(),
|
||||||
|
m_min_x( 0x7FFFFFFF),
|
||||||
|
m_min_y( 0x7FFFFFFF),
|
||||||
|
m_max_x(-0x7FFFFFFF),
|
||||||
|
m_max_y(-0x7FFFFFFF),
|
||||||
|
m_cur_scanline(0)
|
||||||
|
{
|
||||||
|
m_fake_scanline.y = 0;
|
||||||
|
m_fake_scanline.num_spans = 0;
|
||||||
|
m_fake_scanline.start_span = 0;
|
||||||
|
m_fake_span.x = 0;
|
||||||
|
m_fake_span.len = 0;
|
||||||
|
m_fake_span.covers_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renderer Interface
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
void prepare(unsigned)
|
||||||
|
{
|
||||||
|
m_covers.remove_all();
|
||||||
|
m_scanlines.remove_all();
|
||||||
|
m_spans.remove_all();
|
||||||
|
m_min_x = 0x7FFFFFFF;
|
||||||
|
m_min_y = 0x7FFFFFFF;
|
||||||
|
m_max_x = -0x7FFFFFFF;
|
||||||
|
m_max_y = -0x7FFFFFFF;
|
||||||
|
m_cur_scanline = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
template<class Scanline> void render(const Scanline& sl)
|
||||||
|
{
|
||||||
|
scanline_data sl_this;
|
||||||
|
|
||||||
|
int y = sl.y();
|
||||||
|
if(y < m_min_y) m_min_y = y;
|
||||||
|
if(y > m_max_y) m_max_y = y;
|
||||||
|
|
||||||
|
sl_this.y = y;
|
||||||
|
sl_this.num_spans = sl.num_spans();
|
||||||
|
sl_this.start_span = m_spans.size();
|
||||||
|
typename Scanline::const_iterator span_iterator = sl.begin();
|
||||||
|
|
||||||
|
unsigned num_spans = sl_this.num_spans;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
span_data sp;
|
||||||
|
|
||||||
|
sp.x = span_iterator->x;
|
||||||
|
sp.len = span_iterator->len;
|
||||||
|
sp.covers_id =
|
||||||
|
m_covers.add_cells(span_iterator->covers,
|
||||||
|
unsigned(abs(int(sp.len))));
|
||||||
|
m_spans.add(sp);
|
||||||
|
int x1 = sp.x;
|
||||||
|
int x2 = sp.x + sp.len - 1;
|
||||||
|
if(x1 < m_min_x) m_min_x = x1;
|
||||||
|
if(x2 > m_max_x) m_max_x = x2;
|
||||||
|
++span_iterator;
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
m_scanlines.add(sl_this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Iterate scanlines interface
|
||||||
|
int min_x() const { return m_min_x; }
|
||||||
|
int min_y() const { return m_min_y; }
|
||||||
|
int max_x() const { return m_max_x; }
|
||||||
|
int max_y() const { return m_max_y; }
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
bool rewind_scanlines()
|
||||||
|
{
|
||||||
|
m_cur_scanline = 0;
|
||||||
|
return m_scanlines.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||||
|
{
|
||||||
|
sl.reset_spans();
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(m_cur_scanline >= m_scanlines.size()) return false;
|
||||||
|
const scanline_data& sl_this = m_scanlines[m_cur_scanline];
|
||||||
|
|
||||||
|
unsigned num_spans = sl_this.num_spans;
|
||||||
|
unsigned span_idx = sl_this.start_span;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const span_data& sp = m_spans[span_idx++];
|
||||||
|
const T* covers = covers_by_index(sp.covers_id);
|
||||||
|
if(sp.len < 0)
|
||||||
|
{
|
||||||
|
sl.add_span(sp.x, unsigned(-sp.len), *covers);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sl.add_cells(sp.x, sp.len, covers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
++m_cur_scanline;
|
||||||
|
if(sl.num_spans())
|
||||||
|
{
|
||||||
|
sl.finalize(sl_this.y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Specialization for embedded_scanline
|
||||||
|
bool sweep_scanline(embedded_scanline& sl)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(m_cur_scanline >= m_scanlines.size()) return false;
|
||||||
|
sl.init(m_cur_scanline);
|
||||||
|
++m_cur_scanline;
|
||||||
|
}
|
||||||
|
while(sl.num_spans() == 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
unsigned byte_size() const
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
unsigned size = sizeof(int16) * 4; // min_x, min_y, max_x, max_y
|
||||||
|
|
||||||
|
for(i = 0; i < m_scanlines.size(); ++i)
|
||||||
|
{
|
||||||
|
size += sizeof(int16) * 3; // scanline size in bytes, Y, num_spans
|
||||||
|
|
||||||
|
const scanline_data& sl_this = m_scanlines[i];
|
||||||
|
|
||||||
|
unsigned num_spans = sl_this.num_spans;
|
||||||
|
unsigned span_idx = sl_this.start_span;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const span_data& sp = m_spans[span_idx++];
|
||||||
|
|
||||||
|
size += sizeof(int16) * 2; // X, span_len
|
||||||
|
if(sp.len < 0)
|
||||||
|
{
|
||||||
|
size += sizeof(T); // cover
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size += sizeof(T) * unsigned(sp.len); // covers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
static void write_int16(int8u* dst, int16 val)
|
||||||
|
{
|
||||||
|
dst[0] = ((const int8u*)&val)[0];
|
||||||
|
dst[1] = ((const int8u*)&val)[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
void serialize(int8u* data) const
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
write_int16(data, int16u(min_x())); // min_x
|
||||||
|
data += sizeof(int16u);
|
||||||
|
write_int16(data, int16u(min_y())); // min_y
|
||||||
|
data += sizeof(int16u);
|
||||||
|
write_int16(data, int16u(max_x())); // max_x
|
||||||
|
data += sizeof(int16u);
|
||||||
|
write_int16(data, int16u(max_y())); // max_y
|
||||||
|
data += sizeof(int16u);
|
||||||
|
|
||||||
|
for(i = 0; i < m_scanlines.size(); ++i)
|
||||||
|
{
|
||||||
|
const scanline_data& sl_this = m_scanlines[i];
|
||||||
|
|
||||||
|
int8u* size_ptr = data;
|
||||||
|
data += sizeof(int16); // Reserve space for scanline size in bytes
|
||||||
|
|
||||||
|
write_int16(data, int16(sl_this.y)); // Y
|
||||||
|
data += sizeof(int16);
|
||||||
|
|
||||||
|
write_int16(data, int16(sl_this.num_spans)); // num_spans
|
||||||
|
data += sizeof(int16);
|
||||||
|
|
||||||
|
unsigned num_spans = sl_this.num_spans;
|
||||||
|
unsigned span_idx = sl_this.start_span;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const span_data& sp = m_spans[span_idx++];
|
||||||
|
const T* covers = covers_by_index(sp.covers_id);
|
||||||
|
|
||||||
|
write_int16(data, int16(sp.x)); // X
|
||||||
|
data += sizeof(int16);
|
||||||
|
|
||||||
|
write_int16(data, int16(sp.len)); // span_len
|
||||||
|
data += sizeof(int16);
|
||||||
|
|
||||||
|
if(sp.len < 0)
|
||||||
|
{
|
||||||
|
memcpy(data, covers, sizeof(T));
|
||||||
|
data += sizeof(T);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(data, covers, unsigned(sp.len) * sizeof(T));
|
||||||
|
data += sizeof(T) * unsigned(sp.len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
write_int16(size_ptr, int16(unsigned(data - size_ptr)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
const scanline_data& scanline_by_index(unsigned i) const
|
||||||
|
{
|
||||||
|
return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
const span_data& span_by_index(unsigned i) const
|
||||||
|
{
|
||||||
|
return (i < m_spans.size()) ? m_spans[i] : m_fake_span;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
const T* covers_by_index(int i) const
|
||||||
|
{
|
||||||
|
return m_covers[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
scanline_cell_storage<T> m_covers;
|
||||||
|
pod_deque<span_data, 10> m_spans;
|
||||||
|
pod_deque<scanline_data, 8> m_scanlines;
|
||||||
|
span_data m_fake_span;
|
||||||
|
scanline_data m_fake_scanline;
|
||||||
|
int m_min_x;
|
||||||
|
int m_min_y;
|
||||||
|
int m_max_x;
|
||||||
|
int m_max_y;
|
||||||
|
unsigned m_cur_scanline;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef scanline_storage_aa<int8u> scanline_storage_aa8; //--------scanline_storage_aa8
|
||||||
|
typedef scanline_storage_aa<int16u> scanline_storage_aa16; //--------scanline_storage_aa16
|
||||||
|
typedef scanline_storage_aa<int32u> scanline_storage_aa32; //--------scanline_storage_aa32
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------serialized_scanlines_adaptor_aa
|
||||||
|
template<class T> class serialized_scanlines_adaptor_aa
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T cover_type;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
class embedded_scanline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T cover_type;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
class const_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct span
|
||||||
|
{
|
||||||
|
int16 x;
|
||||||
|
int16 len; // If negative, it's a solid span, "covers" is valid
|
||||||
|
const T* covers;
|
||||||
|
};
|
||||||
|
|
||||||
|
const_iterator(const embedded_scanline& sl) :
|
||||||
|
m_ptr(sl.m_ptr),
|
||||||
|
m_dx(sl.m_dx)
|
||||||
|
{
|
||||||
|
init_span();
|
||||||
|
}
|
||||||
|
|
||||||
|
const span& operator*() const { return m_span; }
|
||||||
|
const span* operator->() const { return &m_span; }
|
||||||
|
|
||||||
|
void operator ++ ()
|
||||||
|
{
|
||||||
|
if(m_span.len < 0)
|
||||||
|
{
|
||||||
|
m_ptr += sizeof(T);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ptr += m_span.len * sizeof(T);
|
||||||
|
}
|
||||||
|
init_span();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int read_int16()
|
||||||
|
{
|
||||||
|
int16 val;
|
||||||
|
((int8u*)&val)[0] = *m_ptr++;
|
||||||
|
((int8u*)&val)[1] = *m_ptr++;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_span()
|
||||||
|
{
|
||||||
|
m_span.x = read_int16() + m_dx;
|
||||||
|
m_span.len = read_int16();
|
||||||
|
m_span.covers = m_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int8u* m_ptr;
|
||||||
|
span m_span;
|
||||||
|
int m_dx;
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class const_iterator;
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
void reset(int, int) {}
|
||||||
|
unsigned num_spans() const { return m_num_spans; }
|
||||||
|
int y() const { return m_y; }
|
||||||
|
const_iterator begin() const { return const_iterator(*this); }
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
int read_int16()
|
||||||
|
{
|
||||||
|
int16 val;
|
||||||
|
((int8u*)&val)[0] = *m_ptr++;
|
||||||
|
((int8u*)&val)[1] = *m_ptr++;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
void init(const int8u* ptr, int dx, int dy)
|
||||||
|
{
|
||||||
|
m_ptr = ptr;
|
||||||
|
m_y = read_int16() + dy;
|
||||||
|
m_num_spans = unsigned(read_int16());
|
||||||
|
m_dx = dx;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int8u* m_ptr;
|
||||||
|
int m_y;
|
||||||
|
unsigned m_num_spans;
|
||||||
|
int m_dx;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
serialized_scanlines_adaptor_aa() :
|
||||||
|
m_data(0),
|
||||||
|
m_end(0),
|
||||||
|
m_ptr(0),
|
||||||
|
m_dx(0),
|
||||||
|
m_dy(0),
|
||||||
|
m_min_x(0x7FFFFFFF),
|
||||||
|
m_min_y(0x7FFFFFFF),
|
||||||
|
m_max_x(-0x7FFFFFFF),
|
||||||
|
m_max_y(-0x7FFFFFFF)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
serialized_scanlines_adaptor_aa(const int8u* data, unsigned size,
|
||||||
|
double dx, double dy) :
|
||||||
|
m_data(data),
|
||||||
|
m_end(data + size),
|
||||||
|
m_ptr(data),
|
||||||
|
m_dx(int(floor(dx + 0.5))),
|
||||||
|
m_dy(int(floor(dy + 0.5))),
|
||||||
|
m_min_x(0x7FFFFFFF),
|
||||||
|
m_min_y(0x7FFFFFFF),
|
||||||
|
m_max_x(-0x7FFFFFFF),
|
||||||
|
m_max_y(-0x7FFFFFFF)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void init(const int8u* data, unsigned size, double dx, double dy)
|
||||||
|
{
|
||||||
|
m_data = data;
|
||||||
|
m_end = data + size;
|
||||||
|
m_ptr = data;
|
||||||
|
m_dx = int(floor(dx + 0.5));
|
||||||
|
m_dy = int(floor(dy + 0.5));
|
||||||
|
m_min_x = 0x7FFFFFFF;
|
||||||
|
m_min_y = 0x7FFFFFFF;
|
||||||
|
m_max_x = -0x7FFFFFFF;
|
||||||
|
m_max_y = -0x7FFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
int read_int16()
|
||||||
|
{
|
||||||
|
int16 val;
|
||||||
|
((int8u*)&val)[0] = *m_ptr++;
|
||||||
|
((int8u*)&val)[1] = *m_ptr++;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned read_int16u()
|
||||||
|
{
|
||||||
|
int16u val;
|
||||||
|
((int8u*)&val)[0] = *m_ptr++;
|
||||||
|
((int8u*)&val)[1] = *m_ptr++;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Iterate scanlines interface
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
bool rewind_scanlines()
|
||||||
|
{
|
||||||
|
m_ptr = m_data;
|
||||||
|
if(m_ptr < m_end)
|
||||||
|
{
|
||||||
|
m_min_x = read_int16() + m_dx;
|
||||||
|
m_min_y = read_int16() + m_dy;
|
||||||
|
m_max_x = read_int16() + m_dx;
|
||||||
|
m_max_y = read_int16() + m_dy;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
int min_x() const { return m_min_x; }
|
||||||
|
int min_y() const { return m_min_y; }
|
||||||
|
int max_x() const { return m_max_x; }
|
||||||
|
int max_y() const { return m_max_y; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||||
|
{
|
||||||
|
sl.reset_spans();
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(m_ptr >= m_end) return false;
|
||||||
|
|
||||||
|
read_int16(); // Skip scanline size in bytes
|
||||||
|
int y = read_int16() + m_dy;
|
||||||
|
unsigned num_spans = read_int16();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int x = read_int16() + m_dx;
|
||||||
|
int len = read_int16();
|
||||||
|
|
||||||
|
if(len < 0)
|
||||||
|
{
|
||||||
|
sl.add_span(x, unsigned(-len), *m_ptr);
|
||||||
|
m_ptr += sizeof(T);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sl.add_cells(x, len, m_ptr);
|
||||||
|
m_ptr += len * sizeof(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
|
||||||
|
if(sl.num_spans())
|
||||||
|
{
|
||||||
|
sl.finalize(y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Specialization for embedded_scanline
|
||||||
|
bool sweep_scanline(embedded_scanline& sl)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(m_ptr >= m_end) return false;
|
||||||
|
|
||||||
|
unsigned byte_size = read_int16u();
|
||||||
|
sl.init(m_ptr, m_dx, m_dy);
|
||||||
|
m_ptr += byte_size - sizeof(int16);
|
||||||
|
}
|
||||||
|
while(sl.num_spans() == 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int8u* m_data;
|
||||||
|
const int8u* m_end;
|
||||||
|
const int8u* m_ptr;
|
||||||
|
int m_dx;
|
||||||
|
int m_dy;
|
||||||
|
int m_min_x;
|
||||||
|
int m_min_y;
|
||||||
|
int m_max_x;
|
||||||
|
int m_max_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef serialized_scanlines_adaptor_aa<int8u> serialized_scanlines_adaptor_aa8; //----serialized_scanlines_adaptor_aa8
|
||||||
|
typedef serialized_scanlines_adaptor_aa<int16u> serialized_scanlines_adaptor_aa16; //----serialized_scanlines_adaptor_aa16
|
||||||
|
typedef serialized_scanlines_adaptor_aa<int32u> serialized_scanlines_adaptor_aa32; //----serialized_scanlines_adaptor_aa32
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,579 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SCANLINE_STORAGE_BIN_INCLUDED
|
||||||
|
#define AGG_SCANLINE_STORAGE_BIN_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "agg_array.h"
|
||||||
|
#include "agg_render_scanlines.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//-----------------------------------------------scanline_storage_bin
|
||||||
|
class scanline_storage_bin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
struct span_data
|
||||||
|
{
|
||||||
|
int16 x;
|
||||||
|
int16 len;
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
struct scanline_data
|
||||||
|
{
|
||||||
|
int y;
|
||||||
|
unsigned num_spans;
|
||||||
|
unsigned start_span;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
class embedded_scanline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
class const_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const_iterator(const embedded_scanline& sl) :
|
||||||
|
m_storage(sl.m_storage),
|
||||||
|
m_span_idx(sl.m_scanline.start_span)
|
||||||
|
{
|
||||||
|
m_span = m_storage->span_by_index(m_span_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
const span_data& operator*() const { return m_span; }
|
||||||
|
const span_data* operator->() const { return &m_span; }
|
||||||
|
|
||||||
|
void operator ++ ()
|
||||||
|
{
|
||||||
|
++m_span_idx;
|
||||||
|
m_span = m_storage->span_by_index(m_span_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const scanline_storage_bin* m_storage;
|
||||||
|
unsigned m_span_idx;
|
||||||
|
span_data m_span;
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class const_iterator;
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
embedded_scanline(const scanline_storage_bin& storage) :
|
||||||
|
m_storage(&storage)
|
||||||
|
{
|
||||||
|
setup(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
void reset(int, int) {}
|
||||||
|
unsigned num_spans() const { return m_scanline.num_spans; }
|
||||||
|
int y() const { return m_scanline.y; }
|
||||||
|
const_iterator begin() const { return const_iterator(*this); }
|
||||||
|
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
void setup(unsigned scanline_idx)
|
||||||
|
{
|
||||||
|
m_scanline_idx = scanline_idx;
|
||||||
|
m_scanline = m_storage->scanline_by_index(m_scanline_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const scanline_storage_bin* m_storage;
|
||||||
|
scanline_data m_scanline;
|
||||||
|
unsigned m_scanline_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
scanline_storage_bin() :
|
||||||
|
m_spans(256-2), // Block increment size
|
||||||
|
m_scanlines(),
|
||||||
|
m_min_x( 0x7FFFFFFF),
|
||||||
|
m_min_y( 0x7FFFFFFF),
|
||||||
|
m_max_x(-0x7FFFFFFF),
|
||||||
|
m_max_y(-0x7FFFFFFF),
|
||||||
|
m_cur_scanline(0)
|
||||||
|
{
|
||||||
|
m_fake_scanline.y = 0;
|
||||||
|
m_fake_scanline.num_spans = 0;
|
||||||
|
m_fake_scanline.start_span = 0;
|
||||||
|
m_fake_span.x = 0;
|
||||||
|
m_fake_span.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renderer Interface
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
void prepare(unsigned)
|
||||||
|
{
|
||||||
|
m_scanlines.remove_all();
|
||||||
|
m_spans.remove_all();
|
||||||
|
m_min_x = 0x7FFFFFFF;
|
||||||
|
m_min_y = 0x7FFFFFFF;
|
||||||
|
m_max_x = -0x7FFFFFFF;
|
||||||
|
m_max_y = -0x7FFFFFFF;
|
||||||
|
m_cur_scanline = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
template<class Scanline> void render(const Scanline& sl)
|
||||||
|
{
|
||||||
|
scanline_data sl_this;
|
||||||
|
|
||||||
|
int y = sl.y();
|
||||||
|
if(y < m_min_y) m_min_y = y;
|
||||||
|
if(y > m_max_y) m_max_y = y;
|
||||||
|
|
||||||
|
sl_this.y = y;
|
||||||
|
sl_this.num_spans = sl.num_spans();
|
||||||
|
sl_this.start_span = m_spans.size();
|
||||||
|
typename Scanline::const_iterator span_iterator = sl.begin();
|
||||||
|
|
||||||
|
unsigned num_spans = sl_this.num_spans;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
span_data sp;
|
||||||
|
sp.x = span_iterator->x;
|
||||||
|
sp.len = (int16)abs((int)(span_iterator->len));
|
||||||
|
m_spans.add(sp);
|
||||||
|
int x1 = sp.x;
|
||||||
|
int x2 = sp.x + sp.len - 1;
|
||||||
|
if(x1 < m_min_x) m_min_x = x1;
|
||||||
|
if(x2 > m_max_x) m_max_x = x2;
|
||||||
|
++span_iterator;
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
m_scanlines.add(sl_this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Iterate scanlines interface
|
||||||
|
int min_x() const { return m_min_x; }
|
||||||
|
int min_y() const { return m_min_y; }
|
||||||
|
int max_x() const { return m_max_x; }
|
||||||
|
int max_y() const { return m_max_y; }
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
bool rewind_scanlines()
|
||||||
|
{
|
||||||
|
m_cur_scanline = 0;
|
||||||
|
return m_scanlines.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||||
|
{
|
||||||
|
sl.reset_spans();
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(m_cur_scanline >= m_scanlines.size()) return false;
|
||||||
|
const scanline_data& sl_this = m_scanlines[m_cur_scanline];
|
||||||
|
|
||||||
|
unsigned num_spans = sl_this.num_spans;
|
||||||
|
unsigned span_idx = sl_this.start_span;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const span_data& sp = m_spans[span_idx++];
|
||||||
|
sl.add_span(sp.x, sp.len, cover_full);
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
|
||||||
|
++m_cur_scanline;
|
||||||
|
if(sl.num_spans())
|
||||||
|
{
|
||||||
|
sl.finalize(sl_this.y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Specialization for embedded_scanline
|
||||||
|
bool sweep_scanline(embedded_scanline& sl)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(m_cur_scanline >= m_scanlines.size()) return false;
|
||||||
|
sl.setup(m_cur_scanline);
|
||||||
|
++m_cur_scanline;
|
||||||
|
}
|
||||||
|
while(sl.num_spans() == 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
unsigned byte_size() const
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
unsigned size = sizeof(int16) * 4; // min_x, min_y, max_x, max_y
|
||||||
|
|
||||||
|
for(i = 0; i < m_scanlines.size(); ++i)
|
||||||
|
{
|
||||||
|
size += sizeof(int16) * 2; // Y, num_spans
|
||||||
|
|
||||||
|
const scanline_data& sl_this = m_scanlines[i];
|
||||||
|
|
||||||
|
unsigned num_spans = sl_this.num_spans;
|
||||||
|
unsigned span_idx = sl_this.start_span;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const span_data& sp = m_spans[span_idx++];
|
||||||
|
size += sizeof(int16) * 2; // X, span_len
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
static void write_int16(int8u* dst, int16 val)
|
||||||
|
{
|
||||||
|
dst[0] = ((const int8u*)&val)[0];
|
||||||
|
dst[1] = ((const int8u*)&val)[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
void serialize(int8u* data) const
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
write_int16(data, int16u(min_x())); // min_x
|
||||||
|
data += sizeof(int16u);
|
||||||
|
write_int16(data, int16u(min_y())); // min_y
|
||||||
|
data += sizeof(int16u);
|
||||||
|
write_int16(data, int16u(max_x())); // max_x
|
||||||
|
data += sizeof(int16u);
|
||||||
|
write_int16(data, int16u(max_y())); // max_y
|
||||||
|
data += sizeof(int16u);
|
||||||
|
|
||||||
|
for(i = 0; i < m_scanlines.size(); ++i)
|
||||||
|
{
|
||||||
|
const scanline_data& sl_this = m_scanlines[i];
|
||||||
|
|
||||||
|
write_int16(data, int16(sl_this.y)); // Y
|
||||||
|
data += sizeof(int16);
|
||||||
|
|
||||||
|
write_int16(data, int16(sl_this.num_spans)); // num_spans
|
||||||
|
data += sizeof(int16);
|
||||||
|
|
||||||
|
unsigned num_spans = sl_this.num_spans;
|
||||||
|
unsigned span_idx = sl_this.start_span;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const span_data& sp = m_spans[span_idx++];
|
||||||
|
|
||||||
|
write_int16(data, int16(sp.x)); // X
|
||||||
|
data += sizeof(int16);
|
||||||
|
|
||||||
|
write_int16(data, int16(sp.len)); // len
|
||||||
|
data += sizeof(int16);
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
const scanline_data& scanline_by_index(unsigned i) const
|
||||||
|
{
|
||||||
|
return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
const span_data& span_by_index(unsigned i) const
|
||||||
|
{
|
||||||
|
return (i < m_spans.size()) ? m_spans[i] : m_fake_span;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
pod_deque<span_data, 10> m_spans;
|
||||||
|
pod_deque<scanline_data, 8> m_scanlines;
|
||||||
|
span_data m_fake_span;
|
||||||
|
scanline_data m_fake_scanline;
|
||||||
|
int m_min_x;
|
||||||
|
int m_min_y;
|
||||||
|
int m_max_x;
|
||||||
|
int m_max_y;
|
||||||
|
unsigned m_cur_scanline;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------serialized_scanlines_adaptor_bin
|
||||||
|
class serialized_scanlines_adaptor_bin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef bool cover_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
class embedded_scanline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
class const_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct span
|
||||||
|
{
|
||||||
|
int16 x;
|
||||||
|
int16 len;
|
||||||
|
};
|
||||||
|
|
||||||
|
const_iterator(const embedded_scanline& sl) :
|
||||||
|
m_ptr(sl.m_ptr),
|
||||||
|
m_dx(sl.m_dx)
|
||||||
|
{
|
||||||
|
m_span.x = read_int16() + m_dx;
|
||||||
|
m_span.len = read_int16();
|
||||||
|
}
|
||||||
|
|
||||||
|
const span& operator*() const { return m_span; }
|
||||||
|
const span* operator->() const { return &m_span; }
|
||||||
|
|
||||||
|
void operator ++ ()
|
||||||
|
{
|
||||||
|
m_span.x = read_int16() + m_dx;
|
||||||
|
m_span.len = read_int16();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int read_int16()
|
||||||
|
{
|
||||||
|
int16 val;
|
||||||
|
((int8u*)&val)[0] = *m_ptr++;
|
||||||
|
((int8u*)&val)[1] = *m_ptr++;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int8u* m_ptr;
|
||||||
|
span m_span;
|
||||||
|
int m_dx;
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class const_iterator;
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
void reset(int, int) {}
|
||||||
|
unsigned num_spans() const { return m_num_spans; }
|
||||||
|
int y() const { return m_y; }
|
||||||
|
const_iterator begin() const { return const_iterator(*this); }
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
int read_int16()
|
||||||
|
{
|
||||||
|
int16 val;
|
||||||
|
((int8u*)&val)[0] = *m_ptr++;
|
||||||
|
((int8u*)&val)[1] = *m_ptr++;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
void init(const int8u* ptr, int dx, int dy)
|
||||||
|
{
|
||||||
|
m_ptr = ptr;
|
||||||
|
m_y = read_int16() + dy;
|
||||||
|
m_num_spans = unsigned(read_int16());
|
||||||
|
m_dx = dx;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int8u* m_ptr;
|
||||||
|
int m_y;
|
||||||
|
unsigned m_num_spans;
|
||||||
|
int m_dx;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
serialized_scanlines_adaptor_bin() :
|
||||||
|
m_data(0),
|
||||||
|
m_end(0),
|
||||||
|
m_ptr(0),
|
||||||
|
m_dx(0),
|
||||||
|
m_dy(0),
|
||||||
|
m_min_x(0x7FFFFFFF),
|
||||||
|
m_min_y(0x7FFFFFFF),
|
||||||
|
m_max_x(-0x7FFFFFFF),
|
||||||
|
m_max_y(-0x7FFFFFFF)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
serialized_scanlines_adaptor_bin(const int8u* data, unsigned size,
|
||||||
|
double dx, double dy) :
|
||||||
|
m_data(data),
|
||||||
|
m_end(data + size),
|
||||||
|
m_ptr(data),
|
||||||
|
m_dx(int(floor(dx + 0.5))),
|
||||||
|
m_dy(int(floor(dy + 0.5))),
|
||||||
|
m_min_x(0x7FFFFFFF),
|
||||||
|
m_min_y(0x7FFFFFFF),
|
||||||
|
m_max_x(-0x7FFFFFFF),
|
||||||
|
m_max_y(-0x7FFFFFFF)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void init(const int8u* data, unsigned size, double dx, double dy)
|
||||||
|
{
|
||||||
|
m_data = data;
|
||||||
|
m_end = data + size;
|
||||||
|
m_ptr = data;
|
||||||
|
m_dx = int(floor(dx + 0.5));
|
||||||
|
m_dy = int(floor(dy + 0.5));
|
||||||
|
m_min_x = 0x7FFFFFFF;
|
||||||
|
m_min_y = 0x7FFFFFFF;
|
||||||
|
m_max_x = -0x7FFFFFFF;
|
||||||
|
m_max_y = -0x7FFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
int read_int16()
|
||||||
|
{
|
||||||
|
int16 val;
|
||||||
|
((int8u*)&val)[0] = *m_ptr++;
|
||||||
|
((int8u*)&val)[1] = *m_ptr++;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Iterate scanlines interface
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
bool rewind_scanlines()
|
||||||
|
{
|
||||||
|
m_ptr = m_data;
|
||||||
|
if(m_ptr < m_end)
|
||||||
|
{
|
||||||
|
m_min_x = read_int16() + m_dx;
|
||||||
|
m_min_y = read_int16() + m_dy;
|
||||||
|
m_max_x = read_int16() + m_dx;
|
||||||
|
m_max_y = read_int16() + m_dy;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
int min_x() const { return m_min_x; }
|
||||||
|
int min_y() const { return m_min_y; }
|
||||||
|
int max_x() const { return m_max_x; }
|
||||||
|
int max_y() const { return m_max_y; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||||
|
{
|
||||||
|
sl.reset_spans();
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(m_ptr >= m_end) return false;
|
||||||
|
|
||||||
|
int y = read_int16() + m_dy;
|
||||||
|
unsigned num_spans = read_int16();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int x = read_int16() + m_dx;
|
||||||
|
int len = read_int16();
|
||||||
|
|
||||||
|
if(len < 0) len = -len;
|
||||||
|
sl.add_span(x, unsigned(len), cover_full);
|
||||||
|
}
|
||||||
|
while(--num_spans);
|
||||||
|
|
||||||
|
if(sl.num_spans())
|
||||||
|
{
|
||||||
|
sl.finalize(y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Specialization for embedded_scanline
|
||||||
|
bool sweep_scanline(embedded_scanline& sl)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(m_ptr >= m_end) return false;
|
||||||
|
|
||||||
|
sl.init(m_ptr, m_dx, m_dy);
|
||||||
|
|
||||||
|
// Jump to the next scanline
|
||||||
|
//--------------------------
|
||||||
|
read_int16(); // Y
|
||||||
|
int num_spans = read_int16(); // num_spans
|
||||||
|
m_ptr += num_spans * sizeof(int16) * 2;
|
||||||
|
}
|
||||||
|
while(sl.num_spans() == 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int8u* m_data;
|
||||||
|
const int8u* m_end;
|
||||||
|
const int8u* m_ptr;
|
||||||
|
int m_dx;
|
||||||
|
int m_dy;
|
||||||
|
int m_min_x;
|
||||||
|
int m_min_y;
|
||||||
|
int m_max_x;
|
||||||
|
int m_max_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
Executable
+323
@@ -0,0 +1,323 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SCANLINE_U_INCLUDED
|
||||||
|
#define AGG_SCANLINE_U_INCLUDED
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//==============================================================scanline_u
|
||||||
|
//
|
||||||
|
// Unpacked scanline container class
|
||||||
|
//
|
||||||
|
// This class is used to transfer data from a scanline rastyerizer
|
||||||
|
// to the rendering buffer. It's organized very simple. The class stores
|
||||||
|
// information of horizontal spans to render it into a pixel-map buffer.
|
||||||
|
// Each span has staring X, length, and an array of bytes that determine the
|
||||||
|
// cover-values for each pixel.
|
||||||
|
// Before using this class you should know the minimal and maximal pixel
|
||||||
|
// coordinates of your scanline. The protocol of using is:
|
||||||
|
// 1. reset(min_x, max_x)
|
||||||
|
// 2. add_cell() / add_span() - accumulate scanline.
|
||||||
|
// When forming one scanline the next X coordinate must be always greater
|
||||||
|
// than the last stored one, i.e. it works only with ordered coordinates.
|
||||||
|
// 3. Call finalize(y) and render the scanline.
|
||||||
|
// 3. Call reset_spans() to prepare for the new scanline.
|
||||||
|
//
|
||||||
|
// 4. Rendering:
|
||||||
|
//
|
||||||
|
// Scanline provides an iterator class that allows you to extract
|
||||||
|
// the spans and the cover values for each pixel. Be aware that clipping
|
||||||
|
// has not been done yet, so you should perform it yourself.
|
||||||
|
// Use scanline_u8::iterator to render spans:
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// int y = sl.y(); // Y-coordinate of the scanline
|
||||||
|
//
|
||||||
|
// ************************************
|
||||||
|
// ...Perform vertical clipping here...
|
||||||
|
// ************************************
|
||||||
|
//
|
||||||
|
// scanline_u8::const_iterator span = sl.begin();
|
||||||
|
//
|
||||||
|
// unsigned char* row = m_rbuf->row(y); // The the address of the beginning
|
||||||
|
// // of the current row
|
||||||
|
//
|
||||||
|
// unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
|
||||||
|
// // num_spans is always greater than 0.
|
||||||
|
//
|
||||||
|
// do
|
||||||
|
// {
|
||||||
|
// const scanline_u8::cover_type* covers =
|
||||||
|
// span->covers; // The array of the cover values
|
||||||
|
//
|
||||||
|
// int num_pix = span->len; // Number of pixels of the span.
|
||||||
|
// // Always greater than 0, still it's
|
||||||
|
// // better to use "int" instead of
|
||||||
|
// // "unsigned" because it's more
|
||||||
|
// // convenient for clipping
|
||||||
|
// int x = span->x;
|
||||||
|
//
|
||||||
|
// **************************************
|
||||||
|
// ...Perform horizontal clipping here...
|
||||||
|
// ...you have x, covers, and pix_count..
|
||||||
|
// **************************************
|
||||||
|
//
|
||||||
|
// unsigned char* dst = row + x; // Calculate the start address of the row.
|
||||||
|
// // In this case we assume a simple
|
||||||
|
// // grayscale image 1-byte per pixel.
|
||||||
|
// do
|
||||||
|
// {
|
||||||
|
// *dst++ = *covers++; // Hypotetical rendering.
|
||||||
|
// }
|
||||||
|
// while(--num_pix);
|
||||||
|
//
|
||||||
|
// ++span;
|
||||||
|
// }
|
||||||
|
// while(--num_spans); // num_spans cannot be 0, so this loop is quite safe
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// The question is: why should we accumulate the whole scanline when we
|
||||||
|
// could render just separate spans when they're ready?
|
||||||
|
// That's because using the scaline is generally faster. When is consists
|
||||||
|
// of more than one span the conditions for the processor cash system
|
||||||
|
// are better, because switching between two different areas of memory
|
||||||
|
// (that can be very large) occures less frequently.
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> class scanline_u
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T cover_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
struct span
|
||||||
|
{
|
||||||
|
int16 x;
|
||||||
|
int16 len;
|
||||||
|
cover_type* covers;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef span* iterator;
|
||||||
|
typedef const span* const_iterator;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
~scanline_u();
|
||||||
|
scanline_u();
|
||||||
|
|
||||||
|
void reset(int min_x, int max_x);
|
||||||
|
void add_cell(int x, unsigned cover);
|
||||||
|
void add_cells(int x, unsigned len, const T* covers);
|
||||||
|
void add_span(int x, unsigned len, unsigned cover);
|
||||||
|
void finalize(int y) { m_y = y; }
|
||||||
|
void reset_spans();
|
||||||
|
|
||||||
|
int y() const { return m_y; }
|
||||||
|
unsigned num_spans() const { return unsigned(m_cur_span - m_spans); }
|
||||||
|
const_iterator begin() const { return m_spans + 1; }
|
||||||
|
iterator begin() { return m_spans + 1; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
scanline_u<T>(const scanline_u<T>&);
|
||||||
|
const scanline_u<T>& operator = (const scanline_u<T>&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_min_x;
|
||||||
|
unsigned m_max_len;
|
||||||
|
int m_last_x;
|
||||||
|
int m_y;
|
||||||
|
cover_type* m_covers;
|
||||||
|
span* m_spans;
|
||||||
|
span* m_cur_span;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> scanline_u<T>::~scanline_u()
|
||||||
|
{
|
||||||
|
delete [] m_spans;
|
||||||
|
delete [] m_covers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> scanline_u<T>::scanline_u() :
|
||||||
|
m_min_x(0),
|
||||||
|
m_max_len(0),
|
||||||
|
m_last_x(0x7FFFFFF0),
|
||||||
|
m_covers(0),
|
||||||
|
m_spans(0),
|
||||||
|
m_cur_span(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> void scanline_u<T>::reset(int min_x, int max_x)
|
||||||
|
{
|
||||||
|
unsigned max_len = max_x - min_x + 2;
|
||||||
|
if(max_len > m_max_len)
|
||||||
|
{
|
||||||
|
delete [] m_spans;
|
||||||
|
delete [] m_covers;
|
||||||
|
m_covers = new cover_type [max_len];
|
||||||
|
m_spans = new span [max_len];
|
||||||
|
m_max_len = max_len;
|
||||||
|
}
|
||||||
|
m_last_x = 0x7FFFFFF0;
|
||||||
|
m_min_x = min_x;
|
||||||
|
m_cur_span = m_spans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> inline void scanline_u<T>::reset_spans()
|
||||||
|
{
|
||||||
|
m_last_x = 0x7FFFFFF0;
|
||||||
|
m_cur_span = m_spans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> inline void scanline_u<T>::add_cell(int x, unsigned cover)
|
||||||
|
{
|
||||||
|
x -= m_min_x;
|
||||||
|
m_covers[x] = (unsigned char)cover;
|
||||||
|
if(x == m_last_x+1)
|
||||||
|
{
|
||||||
|
m_cur_span->len++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_cur_span++;
|
||||||
|
m_cur_span->x = (int16)(x + m_min_x);
|
||||||
|
m_cur_span->len = 1;
|
||||||
|
m_cur_span->covers = m_covers + x;
|
||||||
|
}
|
||||||
|
m_last_x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> void scanline_u<T>::add_cells(int x, unsigned len, const T* covers)
|
||||||
|
{
|
||||||
|
x -= m_min_x;
|
||||||
|
memcpy(m_covers + x, covers, len * sizeof(T));
|
||||||
|
if(x == m_last_x+1)
|
||||||
|
{
|
||||||
|
m_cur_span->len += (int16)len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_cur_span++;
|
||||||
|
m_cur_span->x = (int16)(x + m_min_x);
|
||||||
|
m_cur_span->len = (int16)len;
|
||||||
|
m_cur_span->covers = m_covers + x;
|
||||||
|
}
|
||||||
|
m_last_x = x + len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class T> void scanline_u<T>::add_span(int x, unsigned len, unsigned cover)
|
||||||
|
{
|
||||||
|
x -= m_min_x;
|
||||||
|
memset(m_covers + x, cover, len);
|
||||||
|
if(x == m_last_x+1)
|
||||||
|
{
|
||||||
|
m_cur_span->len += (int16)len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_cur_span++;
|
||||||
|
m_cur_span->x = (int16)(x + m_min_x);
|
||||||
|
m_cur_span->len = (int16)len;
|
||||||
|
m_cur_span->covers = m_covers + x;
|
||||||
|
}
|
||||||
|
m_last_x = x + len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================scanline_u8
|
||||||
|
typedef scanline_u<int8u> scanline_u8;
|
||||||
|
|
||||||
|
//============================================================scanline_u16
|
||||||
|
typedef scanline_u<int16u> scanline_u16;
|
||||||
|
|
||||||
|
//============================================================scanline_u32
|
||||||
|
typedef scanline_u<int32u> scanline_u32;
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================scanline_am
|
||||||
|
//
|
||||||
|
// The scanline container with alpha-masking
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
template<class AlphaMask, class CoverT>
|
||||||
|
class scanline_am : public scanline_u<CoverT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef AlphaMask alpha_mask_type;
|
||||||
|
typedef CoverT cover_type;
|
||||||
|
typedef scanline_u<CoverT> scanline_type;
|
||||||
|
|
||||||
|
scanline_am() : scanline_type(), m_alpha_mask(0) {}
|
||||||
|
scanline_am(const AlphaMask& am) : scanline_type(), m_alpha_mask(&am) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void finalize(int span_y)
|
||||||
|
{
|
||||||
|
scanline_u<CoverT>::finalize(span_y);
|
||||||
|
if(m_alpha_mask)
|
||||||
|
{
|
||||||
|
typename scanline_type::iterator span = scanline_type::begin();
|
||||||
|
unsigned count = scanline_type::num_spans();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_alpha_mask->combine_hspan(span->x,
|
||||||
|
scanline_type::y(),
|
||||||
|
span->covers,
|
||||||
|
span->len);
|
||||||
|
++span;
|
||||||
|
}
|
||||||
|
while(--count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const AlphaMask* m_alpha_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================scanline_u8_am
|
||||||
|
template<class AlphaMask>
|
||||||
|
class scanline_u8_am : public scanline_am<AlphaMask, int8u>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef AlphaMask alpha_mask_type;
|
||||||
|
typedef int8u cover_type;
|
||||||
|
typedef scanline_am<alpha_mask_type, cover_type> self_type;
|
||||||
|
|
||||||
|
scanline_u8_am() : self_type() {}
|
||||||
|
scanline_u8_am(const AlphaMask& am) : self_type(am) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SHORTEN_PATH_INCLUDED
|
||||||
|
#define AGG_SHORTEN_PATH_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_vertex_sequence.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//===========================================================shorten_path
|
||||||
|
template<class VertexSequence>
|
||||||
|
void shorten_path(VertexSequence& vs, double s, unsigned closed = 0)
|
||||||
|
{
|
||||||
|
typedef typename VertexSequence::value_type vertex_type;
|
||||||
|
|
||||||
|
if(s > 0.0 && vs.size() > 1)
|
||||||
|
{
|
||||||
|
double d;
|
||||||
|
int n = int(vs.size() - 2);
|
||||||
|
while(n)
|
||||||
|
{
|
||||||
|
d = vs[n].dist;
|
||||||
|
if(d > s) break;
|
||||||
|
vs.remove_last();
|
||||||
|
s -= d;
|
||||||
|
--n;
|
||||||
|
}
|
||||||
|
if(vs.size() < 2)
|
||||||
|
{
|
||||||
|
vs.remove_all();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = vs.size() - 1;
|
||||||
|
vertex_type& prev = vs[n-1];
|
||||||
|
vertex_type& last = vs[n];
|
||||||
|
d = (prev.dist - s) / prev.dist;
|
||||||
|
double x = prev.x + (last.x - prev.x) * d;
|
||||||
|
double y = prev.y + (last.y - prev.y) * d;
|
||||||
|
last.x = x;
|
||||||
|
last.y = y;
|
||||||
|
if(!prev(last)) vs.remove_last();
|
||||||
|
vs.close(closed != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Solving simultaneous equations
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_SIMUL_EQ_INCLUDED
|
||||||
|
#define AGG_SIMUL_EQ_INCLUDED
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//=============================================================swap_arrays
|
||||||
|
template<class T> void swap_arrays(T* a1, T* a2, unsigned n)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
T tmp = *a1;
|
||||||
|
*a1++ = *a2;
|
||||||
|
*a2++ = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================matrix_pivot
|
||||||
|
template<unsigned Rows, unsigned Cols>
|
||||||
|
struct matrix_pivot
|
||||||
|
{
|
||||||
|
static int pivot(double m[Rows][Cols], unsigned row)
|
||||||
|
{
|
||||||
|
int k = int(row);
|
||||||
|
double max_val, tmp;
|
||||||
|
|
||||||
|
max_val = -1.0;
|
||||||
|
unsigned i;
|
||||||
|
for(i = row; i < Rows; i++)
|
||||||
|
{
|
||||||
|
if((tmp = fabs(m[i][row])) > max_val && tmp != 0.0)
|
||||||
|
{
|
||||||
|
max_val = tmp;
|
||||||
|
k = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m[k][row] == 0.0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(k != int(row))
|
||||||
|
{
|
||||||
|
swap_arrays(m[k], m[row], Cols);
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===============================================================simul_eq
|
||||||
|
template<unsigned Size, unsigned RightCols>
|
||||||
|
struct simul_eq
|
||||||
|
{
|
||||||
|
static bool solve(const double left[Size][Size],
|
||||||
|
const double right[Size][RightCols],
|
||||||
|
double result[Size][RightCols])
|
||||||
|
{
|
||||||
|
unsigned i, j, k;
|
||||||
|
double a1;
|
||||||
|
|
||||||
|
double tmp[Size][Size + RightCols];
|
||||||
|
|
||||||
|
for(i = 0; i < Size; i++)
|
||||||
|
{
|
||||||
|
for(j = 0; j < Size; j++)
|
||||||
|
{
|
||||||
|
tmp[i][j] = left[i][j];
|
||||||
|
}
|
||||||
|
for(j = 0; j < RightCols; j++)
|
||||||
|
{
|
||||||
|
tmp[i][Size + j] = right[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(k = 0; k < Size; k++)
|
||||||
|
{
|
||||||
|
if(matrix_pivot<Size, Size + RightCols>::pivot(tmp, k) < 0)
|
||||||
|
{
|
||||||
|
return false; // Singularity....
|
||||||
|
}
|
||||||
|
|
||||||
|
a1 = tmp[k][k];
|
||||||
|
|
||||||
|
for(j = k; j < Size + RightCols; j++)
|
||||||
|
{
|
||||||
|
tmp[k][j] /= a1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = k + 1; i < Size; i++)
|
||||||
|
{
|
||||||
|
a1 = tmp[i][k];
|
||||||
|
for (j = k; j < Size + RightCols; j++)
|
||||||
|
{
|
||||||
|
tmp[i][j] -= a1 * tmp[k][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for(k = 0; k < RightCols; k++)
|
||||||
|
{
|
||||||
|
int m;
|
||||||
|
for(m = int(Size - 1); m >= 0; m--)
|
||||||
|
{
|
||||||
|
result[m][k] = tmp[m][Size + k];
|
||||||
|
for(j = m + 1; j < Size; j++)
|
||||||
|
{
|
||||||
|
result[m][k] -= tmp[m][j] * result[j][k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_ALLOCATOR_INCLUDED
|
||||||
|
#define AGG_SPAN_ALLOCATOR_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//----------------------------------------------------------span_allocator
|
||||||
|
template<class ColorT> class span_allocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef ColorT color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
~span_allocator()
|
||||||
|
{
|
||||||
|
delete [] m_span;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_allocator() :
|
||||||
|
m_max_span_len(0),
|
||||||
|
m_span(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* allocate(unsigned max_span_len)
|
||||||
|
{
|
||||||
|
if(max_span_len > m_max_span_len)
|
||||||
|
{
|
||||||
|
delete [] m_span;
|
||||||
|
m_span = new color_type[m_max_span_len = max_span_len];
|
||||||
|
}
|
||||||
|
return m_span;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* span()
|
||||||
|
{
|
||||||
|
return m_span;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_allocator(const span_allocator<ColorT>&);
|
||||||
|
const span_allocator<ColorT>& operator = (const span_allocator<ColorT>&);
|
||||||
|
|
||||||
|
unsigned m_max_span_len;
|
||||||
|
color_type* m_span;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_CONVERTER_INCLUDED
|
||||||
|
#define AGG_SPAN_CONVERTER_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//----------------------------------------------------------span_converter
|
||||||
|
template<class SpanGenerator, class Conv> class span_converter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename SpanGenerator::color_type color_type;
|
||||||
|
|
||||||
|
span_converter(SpanGenerator& span_gen, Conv& conv) :
|
||||||
|
m_span_gen(&span_gen), m_conv(&conv) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void prepare(unsigned max_span_len)
|
||||||
|
{
|
||||||
|
m_span_gen->prepare(max_span_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
color_type* span = m_span_gen->generate(x, y, len);
|
||||||
|
m_conv->convert(span, len);
|
||||||
|
return span;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SpanGenerator* m_span_gen;
|
||||||
|
Conv* m_conv;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_GENERATOR_INCLUDED
|
||||||
|
#define AGG_SPAN_GENERATOR_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_span_allocator.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//==========================================================span_generator
|
||||||
|
template<class ColorT, class Allocator> class span_generator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef ColorT color_type;
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_generator(alloc_type& alloc) : m_alloc(&alloc) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void allocator(alloc_type& alloc) { m_alloc = &alloc; }
|
||||||
|
alloc_type& allocator() { return *m_alloc; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void prepare(unsigned max_span_len)
|
||||||
|
{
|
||||||
|
m_alloc->allocate(max_span_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
alloc_type* m_alloc;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_GOURAUD_INCLUDED
|
||||||
|
#define AGG_SPAN_GOURAUD_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_math.h"
|
||||||
|
#include "agg_span_generator.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//============================================================span_gouraud
|
||||||
|
template<class ColorT, class Allocator>
|
||||||
|
class span_gouraud : public span_generator<ColorT, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef ColorT color_type;
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
|
||||||
|
struct coord_type
|
||||||
|
{
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
color_type color;
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_gouraud(alloc_type& alloc) :
|
||||||
|
span_generator<color_type, alloc_type>(alloc),
|
||||||
|
m_vertex(0)
|
||||||
|
{
|
||||||
|
m_cmd[0] = path_cmd_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_gouraud(alloc_type& alloc,
|
||||||
|
const color_type& c1,
|
||||||
|
const color_type& c2,
|
||||||
|
const color_type& c3,
|
||||||
|
double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double x3, double y3,
|
||||||
|
double d) :
|
||||||
|
span_generator<color_type, alloc_type>(alloc)
|
||||||
|
{
|
||||||
|
colors(c1, c2, c3);
|
||||||
|
triangle(x1, y1, x2, y2, x3, y3, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void colors(ColorT c1, ColorT c2, ColorT c3)
|
||||||
|
{
|
||||||
|
m_coord[0].color = c1;
|
||||||
|
m_coord[1].color = c2;
|
||||||
|
m_coord[2].color = c3;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Sets the triangle and dilates it if needed.
|
||||||
|
// The trick here is to calculate beveled joins in the vertices of the
|
||||||
|
// triangle and render it as a 6-vertex polygon.
|
||||||
|
// It's necessary to achieve numerical stability.
|
||||||
|
// However, the coordinates to interpolate colors are calculated
|
||||||
|
// as miter joins (calc_intersection).
|
||||||
|
void triangle(double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double x3, double y3,
|
||||||
|
double d)
|
||||||
|
{
|
||||||
|
m_coord[0].x = m_x[0] = x1;
|
||||||
|
m_coord[0].y = m_y[0] = y1;
|
||||||
|
m_coord[1].x = m_x[1] = x2;
|
||||||
|
m_coord[1].y = m_y[1] = y2;
|
||||||
|
m_coord[2].x = m_x[2] = x3;
|
||||||
|
m_coord[2].y = m_y[2] = y3;
|
||||||
|
m_cmd[0] = path_cmd_move_to;
|
||||||
|
m_cmd[1] = path_cmd_line_to;
|
||||||
|
m_cmd[2] = path_cmd_line_to;
|
||||||
|
m_cmd[3] = path_cmd_stop;
|
||||||
|
|
||||||
|
if(d != 0.0)
|
||||||
|
{
|
||||||
|
dilate_triangle(m_coord[0].x, m_coord[0].y,
|
||||||
|
m_coord[1].x, m_coord[1].y,
|
||||||
|
m_coord[2].x, m_coord[2].y,
|
||||||
|
m_x, m_y, d);
|
||||||
|
|
||||||
|
calc_intersection(m_x[4], m_y[4], m_x[5], m_y[5],
|
||||||
|
m_x[0], m_y[0], m_x[1], m_y[1],
|
||||||
|
&m_coord[0].x, &m_coord[0].y);
|
||||||
|
|
||||||
|
calc_intersection(m_x[0], m_y[0], m_x[1], m_y[1],
|
||||||
|
m_x[2], m_y[2], m_x[3], m_y[3],
|
||||||
|
&m_coord[1].x, &m_coord[1].y);
|
||||||
|
|
||||||
|
calc_intersection(m_x[2], m_y[2], m_x[3], m_y[3],
|
||||||
|
m_x[4], m_y[4], m_x[5], m_y[5],
|
||||||
|
&m_coord[2].x, &m_coord[2].y);
|
||||||
|
m_cmd[3] = path_cmd_line_to;
|
||||||
|
m_cmd[4] = path_cmd_line_to;
|
||||||
|
m_cmd[5] = path_cmd_line_to;
|
||||||
|
m_cmd[6] = path_cmd_stop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Vertex Source Interface to feed the coordinates to the rasterizer
|
||||||
|
void rewind(unsigned)
|
||||||
|
{
|
||||||
|
m_vertex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
unsigned vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
*x = m_x[m_vertex];
|
||||||
|
*y = m_y[m_vertex];
|
||||||
|
return m_cmd[m_vertex++];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void arrange_vertices(coord_type* coord) const
|
||||||
|
{
|
||||||
|
coord[0] = m_coord[0];
|
||||||
|
coord[1] = m_coord[1];
|
||||||
|
coord[2] = m_coord[2];
|
||||||
|
|
||||||
|
if(m_coord[0].y > m_coord[2].y)
|
||||||
|
{
|
||||||
|
coord[0] = m_coord[2];
|
||||||
|
coord[2] = m_coord[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
coord_type tmp;
|
||||||
|
if(coord[0].y > coord[1].y)
|
||||||
|
{
|
||||||
|
tmp = coord[1];
|
||||||
|
coord[1] = coord[0];
|
||||||
|
coord[0] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(coord[1].y > coord[2].y)
|
||||||
|
{
|
||||||
|
tmp = coord[2];
|
||||||
|
coord[2] = coord[1];
|
||||||
|
coord[1] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
coord_type m_coord[3];
|
||||||
|
double m_x[8];
|
||||||
|
double m_y[8];
|
||||||
|
unsigned m_cmd[8];
|
||||||
|
unsigned m_vertex;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_GOURAUD_GRAY8_INCLUDED
|
||||||
|
#define AGG_SPAN_GOURAUD_GRAY8_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_gray8.h"
|
||||||
|
#include "agg_dda_line.h"
|
||||||
|
#include "agg_span_gouraud.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//======================================================span_gouraud_gray8
|
||||||
|
template<class Allocator = span_allocator<gray8> >
|
||||||
|
class span_gouraud_gray8 : public span_gouraud<gray8, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef gray8 color_type;
|
||||||
|
typedef span_gouraud<color_type, alloc_type> base_type;
|
||||||
|
typedef typename base_type::coord_type coord_type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
struct gray_calc
|
||||||
|
{
|
||||||
|
void init(const coord_type& c1, const coord_type& c2)
|
||||||
|
{
|
||||||
|
m_x1 = c1.x;
|
||||||
|
m_y1 = c1.y;
|
||||||
|
m_dx = c2.x - c1.x;
|
||||||
|
m_dy = 1.0 / (c2.y - c1.y);
|
||||||
|
m_v1 = c1.color.v;
|
||||||
|
m_a1 = c1.color.a;
|
||||||
|
m_dv = c2.color.v - m_v1;
|
||||||
|
m_da = c2.color.a - m_a1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void calc(int y)
|
||||||
|
{
|
||||||
|
double k = 0.0;
|
||||||
|
if(y > m_y1) k = (y - m_y1) * m_dy;
|
||||||
|
gray8 c;
|
||||||
|
m_v = m_v1 + int(m_dv * k);
|
||||||
|
m_a = m_a1 + int(m_da * k);
|
||||||
|
m_x = int(m_x1 + m_dx * k);
|
||||||
|
}
|
||||||
|
|
||||||
|
double m_x1;
|
||||||
|
double m_y1;
|
||||||
|
double m_dx;
|
||||||
|
double m_dy;
|
||||||
|
int m_v1;
|
||||||
|
int m_a1;
|
||||||
|
int m_dv;
|
||||||
|
int m_da;
|
||||||
|
int m_v;
|
||||||
|
int m_a;
|
||||||
|
int m_x;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_gouraud_gray8(alloc_type& alloc) : base_type(alloc) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_gouraud_gray8(alloc_type& alloc,
|
||||||
|
const color_type& c1,
|
||||||
|
const color_type& c2,
|
||||||
|
const color_type& c3,
|
||||||
|
double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double x3, double y3,
|
||||||
|
double d = 0) :
|
||||||
|
base_type(alloc, c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void prepare(unsigned max_span_len)
|
||||||
|
{
|
||||||
|
base_type::prepare(max_span_len);
|
||||||
|
|
||||||
|
coord_type coord[3];
|
||||||
|
arrange_vertices(coord);
|
||||||
|
|
||||||
|
m_y2 = int(coord[1].y);
|
||||||
|
|
||||||
|
m_swap = calc_point_location(coord[0].x, coord[0].y,
|
||||||
|
coord[2].x, coord[2].y,
|
||||||
|
coord[1].x, coord[1].y) < 0.0;
|
||||||
|
|
||||||
|
m_c1.init(coord[0], coord[2]);
|
||||||
|
m_c2.init(coord[0], coord[1]);
|
||||||
|
m_c3.init(coord[1], coord[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
m_c1.calc(y);
|
||||||
|
const gray_calc* pc1 = &m_c1;
|
||||||
|
const gray_calc* pc2 = &m_c2;
|
||||||
|
|
||||||
|
if(y < m_y2)
|
||||||
|
{
|
||||||
|
m_c2.calc(y+1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_c3.calc(y);
|
||||||
|
pc2 = &m_c3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_swap)
|
||||||
|
{
|
||||||
|
const gray_calc* t = pc2;
|
||||||
|
pc2 = pc1;
|
||||||
|
pc1 = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nx = pc1->m_x;
|
||||||
|
unsigned nlen = pc2->m_x - pc1->m_x + 1;
|
||||||
|
|
||||||
|
if(nlen < len) nlen = len;
|
||||||
|
|
||||||
|
dda_line_interpolator<16> v(pc1->m_v, pc2->m_v, nlen);
|
||||||
|
dda_line_interpolator<16> a(pc1->m_a, pc2->m_a, nlen);
|
||||||
|
|
||||||
|
if(nx < x)
|
||||||
|
{
|
||||||
|
unsigned d = unsigned(x - nx);
|
||||||
|
v += d;
|
||||||
|
a += d;
|
||||||
|
}
|
||||||
|
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
span->v = v.y();
|
||||||
|
span->a = a.y();
|
||||||
|
++v;
|
||||||
|
++a;
|
||||||
|
++span;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_swap;
|
||||||
|
int m_y2;
|
||||||
|
gray_calc m_c1;
|
||||||
|
gray_calc m_c2;
|
||||||
|
gray_calc m_c3;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_GOURAUD_RGBA8_INCLUDED
|
||||||
|
#define AGG_SPAN_GOURAUD_RGBA8_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
#include "agg_dda_line.h"
|
||||||
|
#include "agg_span_gouraud.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//======================================================span_gouraud_rgba8
|
||||||
|
template<class Allocator = span_allocator<rgba8> >
|
||||||
|
class span_gouraud_rgba8 : public span_gouraud<rgba8, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
typedef span_gouraud<color_type, alloc_type> base_type;
|
||||||
|
typedef typename base_type::coord_type coord_type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
struct rgba_calc
|
||||||
|
{
|
||||||
|
void init(const coord_type& c1, const coord_type& c2)
|
||||||
|
{
|
||||||
|
m_x1 = c1.x;
|
||||||
|
m_y1 = c1.y;
|
||||||
|
m_dx = c2.x - c1.x;
|
||||||
|
m_dy = 1.0 / (c2.y - c1.y);
|
||||||
|
m_r1 = c1.color.r;
|
||||||
|
m_g1 = c1.color.g;
|
||||||
|
m_b1 = c1.color.b;
|
||||||
|
m_a1 = c1.color.a;
|
||||||
|
m_dr = c2.color.r - m_r1;
|
||||||
|
m_dg = c2.color.g - m_g1;
|
||||||
|
m_db = c2.color.b - m_b1;
|
||||||
|
m_da = c2.color.a - m_a1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void calc(int y)
|
||||||
|
{
|
||||||
|
double k = 0.0;
|
||||||
|
if(y > m_y1) k = (y - m_y1) * m_dy;
|
||||||
|
rgba8 rgba;
|
||||||
|
m_r = m_r1 + int(m_dr * k);
|
||||||
|
m_g = m_g1 + int(m_dg * k);
|
||||||
|
m_b = m_b1 + int(m_db * k);
|
||||||
|
m_a = m_a1 + int(m_da * k);
|
||||||
|
m_x = int(m_x1 + m_dx * k);
|
||||||
|
}
|
||||||
|
|
||||||
|
double m_x1;
|
||||||
|
double m_y1;
|
||||||
|
double m_dx;
|
||||||
|
double m_dy;
|
||||||
|
int m_r1;
|
||||||
|
int m_g1;
|
||||||
|
int m_b1;
|
||||||
|
int m_a1;
|
||||||
|
int m_dr;
|
||||||
|
int m_dg;
|
||||||
|
int m_db;
|
||||||
|
int m_da;
|
||||||
|
int m_r;
|
||||||
|
int m_g;
|
||||||
|
int m_b;
|
||||||
|
int m_a;
|
||||||
|
int m_x;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_gouraud_rgba8(alloc_type& alloc) : base_type(alloc) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_gouraud_rgba8(alloc_type& alloc,
|
||||||
|
const color_type& c1,
|
||||||
|
const color_type& c2,
|
||||||
|
const color_type& c3,
|
||||||
|
double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double x3, double y3,
|
||||||
|
double d = 0) :
|
||||||
|
base_type(alloc, c1, c2, c3, x1, y1, x2, y2, x3, y3, d)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void prepare(unsigned max_span_len)
|
||||||
|
{
|
||||||
|
base_type::prepare(max_span_len);
|
||||||
|
|
||||||
|
coord_type coord[3];
|
||||||
|
arrange_vertices(coord);
|
||||||
|
|
||||||
|
m_y2 = int(coord[1].y);
|
||||||
|
|
||||||
|
m_swap = calc_point_location(coord[0].x, coord[0].y,
|
||||||
|
coord[2].x, coord[2].y,
|
||||||
|
coord[1].x, coord[1].y) < 0.0;
|
||||||
|
|
||||||
|
m_rgba1.init(coord[0], coord[2]);
|
||||||
|
m_rgba2.init(coord[0], coord[1]);
|
||||||
|
m_rgba3.init(coord[1], coord[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
m_rgba1.calc(y);
|
||||||
|
const rgba_calc* pc1 = &m_rgba1;
|
||||||
|
const rgba_calc* pc2 = &m_rgba2;
|
||||||
|
|
||||||
|
if(y < m_y2)
|
||||||
|
{
|
||||||
|
m_rgba2.calc(y+1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_rgba3.calc(y);
|
||||||
|
pc2 = &m_rgba3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_swap)
|
||||||
|
{
|
||||||
|
const rgba_calc* t = pc2;
|
||||||
|
pc2 = pc1;
|
||||||
|
pc1 = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nx = pc1->m_x;
|
||||||
|
unsigned nlen = pc2->m_x - pc1->m_x + 1;
|
||||||
|
|
||||||
|
if(nlen < len) nlen = len;
|
||||||
|
|
||||||
|
dda_line_interpolator<16> r(pc1->m_r, pc2->m_r, nlen);
|
||||||
|
dda_line_interpolator<16> g(pc1->m_g, pc2->m_g, nlen);
|
||||||
|
dda_line_interpolator<16> b(pc1->m_b, pc2->m_b, nlen);
|
||||||
|
dda_line_interpolator<16> a(pc1->m_a, pc2->m_a, nlen);
|
||||||
|
|
||||||
|
if(nx < x)
|
||||||
|
{
|
||||||
|
unsigned d = unsigned(x - nx);
|
||||||
|
r += d;
|
||||||
|
g += d;
|
||||||
|
b += d;
|
||||||
|
a += d;
|
||||||
|
}
|
||||||
|
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
span->r = (int8u)r.y();
|
||||||
|
span->g = (int8u)g.y();
|
||||||
|
span->b = (int8u)b.y();
|
||||||
|
span->a = (int8u)a.y();
|
||||||
|
++r;
|
||||||
|
++g;
|
||||||
|
++b;
|
||||||
|
++a;
|
||||||
|
++span;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_swap;
|
||||||
|
int m_y2;
|
||||||
|
rgba_calc m_rgba1;
|
||||||
|
rgba_calc m_rgba2;
|
||||||
|
rgba_calc m_rgba3;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_GOURAUD_RGBA8_GAMMA_INCLUDED
|
||||||
|
#define AGG_SPAN_GOURAUD_RGBA8_GAMMA_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
#include "agg_dda_line.h"
|
||||||
|
#include "agg_span_gouraud.h"
|
||||||
|
#include "agg_gamma_lut.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//======================================================span_gouraud_rgba8
|
||||||
|
template<class Allocator = span_allocator<rgba8>,
|
||||||
|
class Gamma = gamma_lut<int8u, int16u, 8, 16> >
|
||||||
|
class span_gouraud_rgba8_gamma : public span_gouraud<rgba8, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
typedef span_gouraud<color_type, alloc_type> base_type;
|
||||||
|
typedef typename base_type::coord_type coord_type;
|
||||||
|
typedef Gamma gamma_type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
struct rgba_calc
|
||||||
|
{
|
||||||
|
void init(const coord_type& c1, const coord_type& c2, const gamma_type& gamma)
|
||||||
|
{
|
||||||
|
m_x1 = c1.x;
|
||||||
|
m_y1 = c1.y;
|
||||||
|
m_dx = c2.x - c1.x;
|
||||||
|
m_dy = 1.0 / (c2.y - c1.y);
|
||||||
|
m_r1 = gamma.dir(c1.color.r);
|
||||||
|
m_g1 = gamma.dir(c1.color.g);
|
||||||
|
m_b1 = gamma.dir(c1.color.b);
|
||||||
|
m_a1 = c1.color.a;
|
||||||
|
m_dr = gamma.dir(c2.color.r) - m_r1;
|
||||||
|
m_dg = gamma.dir(c2.color.g) - m_g1;
|
||||||
|
m_db = gamma.dir(c2.color.b) - m_b1;
|
||||||
|
m_da = c2.color.a - m_a1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void calc(int y)
|
||||||
|
{
|
||||||
|
double k = 0.0;
|
||||||
|
if(y > m_y1) k = (y - m_y1) * m_dy;
|
||||||
|
m_r = m_r1 + int(m_dr * k);
|
||||||
|
m_g = m_g1 + int(m_dg * k);
|
||||||
|
m_b = m_b1 + int(m_db * k);
|
||||||
|
m_a = m_a1 + int(m_da * k);
|
||||||
|
m_x = int(m_x1 + m_dx * k);
|
||||||
|
}
|
||||||
|
|
||||||
|
double m_x1;
|
||||||
|
double m_y1;
|
||||||
|
double m_dx;
|
||||||
|
double m_dy;
|
||||||
|
int m_r1;
|
||||||
|
int m_g1;
|
||||||
|
int m_b1;
|
||||||
|
int m_a1;
|
||||||
|
int m_dr;
|
||||||
|
int m_dg;
|
||||||
|
int m_db;
|
||||||
|
int m_da;
|
||||||
|
int m_r;
|
||||||
|
int m_g;
|
||||||
|
int m_b;
|
||||||
|
int m_a;
|
||||||
|
int m_x;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_gouraud_rgba8_gamma(alloc_type& alloc, const gamma_type& g) :
|
||||||
|
base_type(alloc), m_gamma(&g) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_gouraud_rgba8_gamma(alloc_type& alloc,
|
||||||
|
const gamma_type& g,
|
||||||
|
const color_type& c1,
|
||||||
|
const color_type& c2,
|
||||||
|
const color_type& c3,
|
||||||
|
double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
double x3, double y3,
|
||||||
|
double d = 0) :
|
||||||
|
base_type(alloc, c1, c2, c3, x1, y1, x2, y2, x3, y3, d),
|
||||||
|
m_gamma(&g)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void gamma(const gamma_type& g) { m_gamma = &g; }
|
||||||
|
const gamma_type& gamma() const { return *m_gamma; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void prepare(unsigned max_span_len)
|
||||||
|
{
|
||||||
|
base_type::prepare(max_span_len);
|
||||||
|
|
||||||
|
coord_type coord[3];
|
||||||
|
arrange_vertices(coord);
|
||||||
|
|
||||||
|
m_y2 = int(coord[1].y);
|
||||||
|
|
||||||
|
m_swap = calc_point_location(coord[0].x, coord[0].y,
|
||||||
|
coord[2].x, coord[2].y,
|
||||||
|
coord[1].x, coord[1].y) < 0.0;
|
||||||
|
|
||||||
|
m_rgba1.init(coord[0], coord[2], *m_gamma);
|
||||||
|
m_rgba2.init(coord[0], coord[1], *m_gamma);
|
||||||
|
m_rgba3.init(coord[1], coord[2], *m_gamma);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
m_rgba1.calc(y);
|
||||||
|
const rgba_calc* pc1 = &m_rgba1;
|
||||||
|
const rgba_calc* pc2 = &m_rgba2;
|
||||||
|
|
||||||
|
if(y < m_y2)
|
||||||
|
{
|
||||||
|
m_rgba2.calc(y+1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_rgba3.calc(y);
|
||||||
|
pc2 = &m_rgba3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_swap)
|
||||||
|
{
|
||||||
|
const rgba_calc* t = pc2;
|
||||||
|
pc2 = pc1;
|
||||||
|
pc1 = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nx = pc1->m_x;
|
||||||
|
unsigned nlen = pc2->m_x - pc1->m_x + 1;
|
||||||
|
|
||||||
|
if(nlen < len) nlen = len;
|
||||||
|
|
||||||
|
dda_line_interpolator<8> r(pc1->m_r, pc2->m_r, nlen);
|
||||||
|
dda_line_interpolator<8> g(pc1->m_g, pc2->m_g, nlen);
|
||||||
|
dda_line_interpolator<8> b(pc1->m_b, pc2->m_b, nlen);
|
||||||
|
dda_line_interpolator<16> a(pc1->m_a, pc2->m_a, nlen);
|
||||||
|
|
||||||
|
if(nx < x)
|
||||||
|
{
|
||||||
|
unsigned d = unsigned(x - nx);
|
||||||
|
r += d;
|
||||||
|
g += d;
|
||||||
|
b += d;
|
||||||
|
a += d;
|
||||||
|
}
|
||||||
|
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
span->r = m_gamma->inv(r.y());
|
||||||
|
span->g = m_gamma->inv(g.y());
|
||||||
|
span->b = m_gamma->inv(b.y());
|
||||||
|
span->a = a.y();
|
||||||
|
++r;
|
||||||
|
++g;
|
||||||
|
++b;
|
||||||
|
++a;
|
||||||
|
++span;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
const gamma_type* m_gamma;
|
||||||
|
bool m_swap;
|
||||||
|
int m_y2;
|
||||||
|
rgba_calc m_rgba1;
|
||||||
|
rgba_calc m_rgba2;
|
||||||
|
rgba_calc m_rgba3;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_GRADIENT_INCLUDED
|
||||||
|
#define AGG_SPAN_GRADIENT_INCLUDED
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_span_generator.h"
|
||||||
|
#include "agg_math.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//==========================================================span_gradient
|
||||||
|
template<class ColorT,
|
||||||
|
class Interpolator,
|
||||||
|
class GradientF,
|
||||||
|
class ColorF,
|
||||||
|
class Allocator = span_allocator<ColorT> >
|
||||||
|
class span_gradient : public span_generator<ColorT, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Interpolator interpolator_type;
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef ColorT color_type;
|
||||||
|
typedef span_generator<color_type, alloc_type> base_type;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
base_shift = 8,
|
||||||
|
base_size = 1 << base_shift,
|
||||||
|
base_mask = base_size - 1,
|
||||||
|
|
||||||
|
gradient_shift = 4,
|
||||||
|
gradient_size = 1 << gradient_shift,
|
||||||
|
gradient_mask = gradient_size - 1,
|
||||||
|
|
||||||
|
downscale_shift = interpolator_type::subpixel_shift - gradient_shift
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_gradient(alloc_type& alloc) : base_type(alloc) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_gradient(alloc_type& alloc,
|
||||||
|
interpolator_type& inter,
|
||||||
|
const GradientF& gradient_function,
|
||||||
|
ColorF color_function,
|
||||||
|
double d1, double d2) :
|
||||||
|
base_type(alloc),
|
||||||
|
m_interpolator(&inter),
|
||||||
|
m_gradient_function(&gradient_function),
|
||||||
|
m_color_function(color_function),
|
||||||
|
m_d1(int(d1 * gradient_size)),
|
||||||
|
m_d2(int(d2 * gradient_size))
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
interpolator_type& interpolator() { return *m_interpolator; }
|
||||||
|
const GradientF& gradient_function() const { return *m_gradient_function; }
|
||||||
|
const ColorF color_function() const { return m_color_function; }
|
||||||
|
double d1() const { return double(m_d1) / gradient_size; }
|
||||||
|
double d2() const { return double(m_d2) / gradient_size; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void interpolator(interpolator_type& i) { m_interpolator = &i; }
|
||||||
|
void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
|
||||||
|
void color_function(ColorF cf) { m_color_function = cf; }
|
||||||
|
void d1(double v) { m_d1 = int(v * gradient_size); }
|
||||||
|
void d2(double v) { m_d2 = int(v * gradient_size); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
int dd = m_d2 - m_d1;
|
||||||
|
if(dd < 1) dd = 1;
|
||||||
|
m_interpolator->begin(x+0.5, y+0.5, len);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
m_interpolator->coordinates(&x, &y);
|
||||||
|
int d = m_gradient_function->calculate(x >> downscale_shift,
|
||||||
|
y >> downscale_shift, dd);
|
||||||
|
d = ((d - m_d1) << base_shift) / dd;
|
||||||
|
if(d < 0) d = 0;
|
||||||
|
if(d > base_mask) d = base_mask;
|
||||||
|
*span++ = m_color_function[d];
|
||||||
|
++(*m_interpolator);
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
interpolator_type* m_interpolator;
|
||||||
|
const GradientF* m_gradient_function;
|
||||||
|
ColorF m_color_function;
|
||||||
|
int m_d1;
|
||||||
|
int m_d2;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=====================================================gradient_linear_color
|
||||||
|
template<class ColorT, unsigned BaseShift=8>
|
||||||
|
struct gradient_linear_color
|
||||||
|
{
|
||||||
|
typedef ColorT color_type;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
base_shift = BaseShift,
|
||||||
|
base_size = 1 << base_shift,
|
||||||
|
base_mask = base_size - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
gradient_linear_color() {}
|
||||||
|
gradient_linear_color(const color_type& c1, const color_type& c2) :
|
||||||
|
m_c1(c1), m_c2(c2) {}
|
||||||
|
|
||||||
|
color_type operator [] (unsigned v) const
|
||||||
|
{
|
||||||
|
return m_c1.gradient(m_c2, double(v) / double(base_mask));
|
||||||
|
}
|
||||||
|
|
||||||
|
void colors(const color_type& c1, const color_type& c2)
|
||||||
|
{
|
||||||
|
m_c1 = c1;
|
||||||
|
m_c2 = c2;
|
||||||
|
}
|
||||||
|
|
||||||
|
color_type m_c1;
|
||||||
|
color_type m_c2;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------gradient_circle
|
||||||
|
class gradient_circle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static int calculate(int x, int y, int)
|
||||||
|
{
|
||||||
|
return int(fast_sqrt(x*x + y*y));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------gradient_x
|
||||||
|
class gradient_x
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static int calculate(int x, int, int) { return x; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------gradient_y
|
||||||
|
class gradient_y
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static int calculate(int, int y, int) { return y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------gradient_diamond
|
||||||
|
class gradient_diamond
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static int calculate(int x, int y, int)
|
||||||
|
{
|
||||||
|
int ax = abs(x);
|
||||||
|
int ay = abs(y);
|
||||||
|
return ax > ay ? ax : ay;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------gradient_xy
|
||||||
|
class gradient_xy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static int calculate(int x, int y, int d)
|
||||||
|
{
|
||||||
|
return abs(x) * abs(y) / d;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------gradient_sqrt_xy
|
||||||
|
class gradient_sqrt_xy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static int calculate(int x, int y, int)
|
||||||
|
{
|
||||||
|
return fast_sqrt(abs(x) * abs(y));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------gradient_conic
|
||||||
|
class gradient_conic
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static int calculate(int x, int y, int d)
|
||||||
|
{
|
||||||
|
return int(fabs(atan2(double(y), double(x))) * double(d) / pi);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Image transformations with filtering. Span generator base class
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_SPAN_IMAGE_FILTER_INCLUDED
|
||||||
|
#define AGG_SPAN_IMAGE_FILTER_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_image_filters.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
#include "agg_span_generator.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//--------------------------------------------------span_image_filter
|
||||||
|
template<class ColorT, class Interpolator, class Allocator>
|
||||||
|
class span_image_filter : public span_generator<ColorT, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef ColorT color_type;
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef Interpolator interpolator_type;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
span_image_filter(alloc_type& alloc) :
|
||||||
|
span_generator<color_type, alloc_type>(alloc)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
span_image_filter(alloc_type& alloc,
|
||||||
|
const rendering_buffer& src,
|
||||||
|
const color_type& back_color,
|
||||||
|
interpolator_type& interpolator,
|
||||||
|
const image_filter_base* filter) :
|
||||||
|
span_generator<color_type, alloc_type>(alloc),
|
||||||
|
m_src(&src),
|
||||||
|
m_back_color(back_color),
|
||||||
|
m_interpolator(&interpolator),
|
||||||
|
m_filter(filter)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
const rendering_buffer& source_image() const { return *m_src; }
|
||||||
|
const color_type& background_color() const { return m_back_color; }
|
||||||
|
const image_filter_base& filter() const { return *m_filter; }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
void source_image(const rendering_buffer& v) { m_src = &v; }
|
||||||
|
void background_color(const color_type& v) { m_back_color = v; }
|
||||||
|
void interpolator(interpolator_type& v) { m_interpolator = &v; }
|
||||||
|
void filter(const image_filter_base& v) { m_filter = &v; }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
interpolator_type& interpolator() { return *m_interpolator; }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
const rendering_buffer* m_src;
|
||||||
|
color_type m_back_color;
|
||||||
|
interpolator_type* m_interpolator;
|
||||||
|
const image_filter_base* m_filter;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,531 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_IMAGE_FILTER_RGB24_INCLUDED
|
||||||
|
#define AGG_SPAN_IMAGE_FILTER_RGB24_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
#include "agg_span_image_filter.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
//==============================================span_image_filter_rgb24_nn
|
||||||
|
template<class Order,
|
||||||
|
class Interpolator,
|
||||||
|
class Allocator = span_allocator<rgba8> >
|
||||||
|
class span_image_filter_rgb24_nn :
|
||||||
|
public span_image_filter<rgba8, Interpolator, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Interpolator interpolator_type;
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgb24_nn(alloc_type& alloc) : base_type(alloc) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgb24_nn(alloc_type& alloc,
|
||||||
|
const rendering_buffer& src,
|
||||||
|
const color_type& back_color,
|
||||||
|
interpolator_type& inter) :
|
||||||
|
base_type(alloc, src, back_color, inter, 0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
base_type::interpolator().begin(x, y, len);
|
||||||
|
|
||||||
|
int fg[3];
|
||||||
|
int src_alpha;
|
||||||
|
|
||||||
|
const unsigned char *fg_ptr;
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
|
||||||
|
int maxx = base_type::source_image().width() - 1;
|
||||||
|
int maxy = base_type::source_image().height() - 1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::interpolator().coordinates(&x, &y);
|
||||||
|
|
||||||
|
x >>= image_subpixel_shift;
|
||||||
|
y >>= image_subpixel_shift;
|
||||||
|
|
||||||
|
if(x >= 0 && y >= 0 &&
|
||||||
|
x <= maxx && y <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y) + x + x + x;
|
||||||
|
fg[0] = *fg_ptr++;
|
||||||
|
fg[1] = *fg_ptr++;
|
||||||
|
fg[2] = *fg_ptr++;
|
||||||
|
src_alpha = 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] = base_type::background_color().r;
|
||||||
|
fg[Order::G] = base_type::background_color().g;
|
||||||
|
fg[Order::B] = base_type::background_color().b;
|
||||||
|
src_alpha = base_type::background_color().a;
|
||||||
|
}
|
||||||
|
|
||||||
|
span->r = (int8u)fg[Order::R];
|
||||||
|
span->g = (int8u)fg[Order::G];
|
||||||
|
span->b = (int8u)fg[Order::B];
|
||||||
|
span->a = (int8u)src_alpha;
|
||||||
|
++span;
|
||||||
|
++base_type::interpolator();
|
||||||
|
|
||||||
|
} while(--len);
|
||||||
|
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========================================span_image_filter_rgb24_bilinear
|
||||||
|
template<class Order,
|
||||||
|
class Interpolator,
|
||||||
|
class Allocator = span_allocator<rgba8> >
|
||||||
|
class span_image_filter_rgb24_bilinear :
|
||||||
|
public span_image_filter<rgba8, Interpolator, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Interpolator interpolator_type;
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef span_image_filter<rgba8, Interpolator, Allocator> base_type;
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgb24_bilinear(alloc_type& alloc) : base_type(alloc) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgb24_bilinear(alloc_type& alloc,
|
||||||
|
const rendering_buffer& src,
|
||||||
|
const color_type& back_color,
|
||||||
|
interpolator_type& inter) :
|
||||||
|
base_type(alloc, src, back_color, inter, 0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
base_type::interpolator().begin(x, y, len);
|
||||||
|
|
||||||
|
int fg[3];
|
||||||
|
int src_alpha;
|
||||||
|
int back_r = base_type::background_color().r;
|
||||||
|
int back_g = base_type::background_color().g;
|
||||||
|
int back_b = base_type::background_color().b;
|
||||||
|
int back_a = base_type::background_color().a;
|
||||||
|
|
||||||
|
const unsigned char *fg_ptr;
|
||||||
|
|
||||||
|
int stride = base_type::source_image().stride() - 2 * 3;
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
|
||||||
|
int maxx = base_type::source_image().width() - 1;
|
||||||
|
int maxy = base_type::source_image().height() - 1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int x_hr;
|
||||||
|
int y_hr;
|
||||||
|
|
||||||
|
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||||
|
|
||||||
|
int x_lr = x_hr >> image_subpixel_shift;
|
||||||
|
int y_lr = y_hr >> image_subpixel_shift;
|
||||||
|
int weight;
|
||||||
|
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr < maxx && y_lr < maxy)
|
||||||
|
{
|
||||||
|
fg[0] =
|
||||||
|
fg[1] =
|
||||||
|
fg[2] = image_subpixel_size * image_subpixel_size / 2;
|
||||||
|
|
||||||
|
x_hr &= image_subpixel_mask;
|
||||||
|
y_hr &= image_subpixel_mask;
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
|
||||||
|
|
||||||
|
weight = (image_subpixel_size - x_hr) *
|
||||||
|
(image_subpixel_size - y_hr);
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
|
||||||
|
weight = x_hr * (image_subpixel_size - y_hr);
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
|
||||||
|
fg_ptr += stride;
|
||||||
|
|
||||||
|
weight = (image_subpixel_size - x_hr) * y_hr;
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
|
||||||
|
weight = x_hr * y_hr;
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
|
||||||
|
fg[0] >>= image_subpixel_shift * 2;
|
||||||
|
fg[1] >>= image_subpixel_shift * 2;
|
||||||
|
fg[2] >>= image_subpixel_shift * 2;
|
||||||
|
src_alpha = 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(x_lr < -1 || y_lr < -1 ||
|
||||||
|
x_lr > maxx || y_lr > maxy)
|
||||||
|
{
|
||||||
|
fg[Order::R] = back_r;
|
||||||
|
fg[Order::G] = back_g;
|
||||||
|
fg[Order::B] = back_b;
|
||||||
|
src_alpha = back_a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[0] =
|
||||||
|
fg[1] =
|
||||||
|
fg[2] =
|
||||||
|
src_alpha = image_subpixel_size * image_subpixel_size / 2;
|
||||||
|
|
||||||
|
x_hr &= image_subpixel_mask;
|
||||||
|
y_hr &= image_subpixel_mask;
|
||||||
|
|
||||||
|
weight = (image_subpixel_size - x_hr) *
|
||||||
|
(image_subpixel_size - y_hr);
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
src_alpha += weight * 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
src_alpha += back_a * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
x_lr++;
|
||||||
|
|
||||||
|
weight = x_hr * (image_subpixel_size - y_hr);
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
src_alpha += weight * 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
src_alpha += back_a * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
x_lr--;
|
||||||
|
y_lr++;
|
||||||
|
|
||||||
|
weight = (image_subpixel_size - x_hr) * y_hr;
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
src_alpha += weight * 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
src_alpha += back_a * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
x_lr++;
|
||||||
|
|
||||||
|
weight = x_hr * y_hr;
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
src_alpha += weight * 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
src_alpha += back_a * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
fg[0] >>= image_subpixel_shift * 2;
|
||||||
|
fg[1] >>= image_subpixel_shift * 2;
|
||||||
|
fg[2] >>= image_subpixel_shift * 2;
|
||||||
|
src_alpha >>= image_subpixel_shift * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span->r = (int8u)fg[Order::R];
|
||||||
|
span->g = (int8u)fg[Order::G];
|
||||||
|
span->b = (int8u)fg[Order::B];
|
||||||
|
span->a = (int8u)src_alpha;
|
||||||
|
++span;
|
||||||
|
++base_type::interpolator();
|
||||||
|
|
||||||
|
} while(--len);
|
||||||
|
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=================================================span_image_filter_rgb24
|
||||||
|
template<class Order,
|
||||||
|
class Interpolator,
|
||||||
|
class Allocator = span_allocator<rgba8> >
|
||||||
|
class span_image_filter_rgb24 :
|
||||||
|
public span_image_filter<rgba8, Interpolator, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Interpolator interpolator_type;
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgb24(alloc_type& alloc) : base_type(alloc) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgb24(alloc_type& alloc,
|
||||||
|
const rendering_buffer& src,
|
||||||
|
const color_type& back_color,
|
||||||
|
interpolator_type& inter,
|
||||||
|
const image_filter_base& filter) :
|
||||||
|
base_type(alloc, src, back_color, inter, &filter)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
base_type::interpolator().begin(x, y, len);
|
||||||
|
|
||||||
|
int fg[3];
|
||||||
|
int src_alpha;
|
||||||
|
int back_r = base_type::background_color().r;
|
||||||
|
int back_g = base_type::background_color().g;
|
||||||
|
int back_b = base_type::background_color().b;
|
||||||
|
int back_a = base_type::background_color().a;
|
||||||
|
|
||||||
|
const unsigned char *fg_ptr;
|
||||||
|
|
||||||
|
unsigned dimension = base_type::filter().dimension();
|
||||||
|
int start = base_type::filter().start();
|
||||||
|
int start1 = start - 1;
|
||||||
|
const int* weight_array = base_type::filter().weight_array_int();
|
||||||
|
|
||||||
|
int stride = base_type::source_image().stride() - dimension * 3;
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
|
||||||
|
int maxx = base_type::source_image().width() + start - 2;
|
||||||
|
int maxy = base_type::source_image().height() + start - 2;
|
||||||
|
|
||||||
|
int maxx2 = base_type::source_image().width() - start - 1;
|
||||||
|
int maxy2 = base_type::source_image().height() - start - 1;
|
||||||
|
|
||||||
|
int x_count;
|
||||||
|
int weight_y;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::interpolator().coordinates(&x, &y);
|
||||||
|
|
||||||
|
int x_hr = x;
|
||||||
|
int y_hr = y;
|
||||||
|
|
||||||
|
int x_lr = x_hr >> image_subpixel_shift;
|
||||||
|
int y_lr = y_hr >> image_subpixel_shift;
|
||||||
|
|
||||||
|
fg[0] = fg[1] = fg[2] = image_filter_size / 2;
|
||||||
|
|
||||||
|
int x_fract = x_hr & image_subpixel_mask;
|
||||||
|
unsigned y_count = dimension;
|
||||||
|
|
||||||
|
if(x_lr >= -start && y_lr >= -start &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr + start) + (x_lr + start) * 3;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
x_count = dimension;
|
||||||
|
weight_y = weight_array[y_hr];
|
||||||
|
x_hr = image_subpixel_mask - x_fract;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int weight = (weight_y * weight_array[x_hr] +
|
||||||
|
image_filter_size / 2) >>
|
||||||
|
image_filter_shift;
|
||||||
|
|
||||||
|
fg[0] += *fg_ptr++ * weight;
|
||||||
|
fg[1] += *fg_ptr++ * weight;
|
||||||
|
fg[2] += *fg_ptr++ * weight;
|
||||||
|
|
||||||
|
x_hr += image_subpixel_size;
|
||||||
|
|
||||||
|
} while(--x_count);
|
||||||
|
|
||||||
|
y_hr += image_subpixel_size;
|
||||||
|
fg_ptr += stride;
|
||||||
|
|
||||||
|
} while(--y_count);
|
||||||
|
|
||||||
|
fg[0] >>= image_filter_shift;
|
||||||
|
fg[1] >>= image_filter_shift;
|
||||||
|
fg[2] >>= image_filter_shift;
|
||||||
|
|
||||||
|
if(fg[0] < 0) fg[0] = 0;
|
||||||
|
if(fg[1] < 0) fg[1] = 0;
|
||||||
|
if(fg[2] < 0) fg[2] = 0;
|
||||||
|
|
||||||
|
if(fg[0] > 255) fg[0] = 255;
|
||||||
|
if(fg[1] > 255) fg[1] = 255;
|
||||||
|
if(fg[2] > 255) fg[2] = 255;
|
||||||
|
src_alpha = 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(x_lr < start1 || y_lr < start1 ||
|
||||||
|
x_lr > maxx2 || y_lr > maxy2)
|
||||||
|
{
|
||||||
|
fg[Order::R] = back_r;
|
||||||
|
fg[Order::G] = back_g;
|
||||||
|
fg[Order::B] = back_b;
|
||||||
|
src_alpha = back_a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
src_alpha = image_filter_size / 2;
|
||||||
|
y_lr = (y >> image_subpixel_shift) + start;
|
||||||
|
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
x_count = dimension;
|
||||||
|
weight_y = weight_array[y_hr];
|
||||||
|
x_lr = (x >> image_subpixel_shift) + start;
|
||||||
|
x_hr = image_subpixel_mask - x_fract;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int weight = (weight_y * weight_array[x_hr] +
|
||||||
|
image_filter_size / 2) >>
|
||||||
|
image_filter_shift;
|
||||||
|
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr < int(base_type::source_image().width()) &&
|
||||||
|
y_lr < int(base_type::source_image().height()))
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + x_lr * 3;
|
||||||
|
fg[0] += *fg_ptr++ * weight;
|
||||||
|
fg[1] += *fg_ptr++ * weight;
|
||||||
|
fg[2] += *fg_ptr++ * weight;
|
||||||
|
src_alpha += 255 * weight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
src_alpha += back_a * weight;
|
||||||
|
}
|
||||||
|
x_hr += image_subpixel_size;
|
||||||
|
x_lr++;
|
||||||
|
|
||||||
|
} while(--x_count);
|
||||||
|
|
||||||
|
y_hr += image_subpixel_size;
|
||||||
|
y_lr++;
|
||||||
|
|
||||||
|
} while(--y_count);
|
||||||
|
|
||||||
|
|
||||||
|
fg[0] >>= image_filter_shift;
|
||||||
|
fg[1] >>= image_filter_shift;
|
||||||
|
fg[2] >>= image_filter_shift;
|
||||||
|
src_alpha >>= image_filter_shift;
|
||||||
|
|
||||||
|
if(fg[0] < 0) fg[0] = 0;
|
||||||
|
if(fg[1] < 0) fg[1] = 0;
|
||||||
|
if(fg[2] < 0) fg[2] = 0;
|
||||||
|
if(src_alpha < 0) src_alpha = 0;
|
||||||
|
|
||||||
|
if(fg[0] > 255) fg[0] = 255;
|
||||||
|
if(fg[1] > 255) fg[1] = 255;
|
||||||
|
if(fg[2] > 255) fg[2] = 255;
|
||||||
|
if(src_alpha > 255) src_alpha = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span->r = (int8u)fg[Order::R];
|
||||||
|
span->g = (int8u)fg[Order::G];
|
||||||
|
span->b = (int8u)fg[Order::B];
|
||||||
|
span->a = (int8u)src_alpha;
|
||||||
|
++span;
|
||||||
|
++base_type::interpolator();
|
||||||
|
|
||||||
|
} while(--len);
|
||||||
|
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,475 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_IMAGE_FILTER_RGB24_GAMMA_INCLUDED
|
||||||
|
#define AGG_SPAN_IMAGE_FILTER_RGB24_GAMMA_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
#include "agg_span_image_filter.h"
|
||||||
|
#include "agg_gamma_lut.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
//===================================span_image_filter_rgb24_gamma_bilinear
|
||||||
|
template<class Order,
|
||||||
|
class Interpolator,
|
||||||
|
class Allocator = span_allocator<rgba8>,
|
||||||
|
class Gamma = gamma_lut<int8u, int8u, 8, 8> >
|
||||||
|
class span_image_filter_rgb24_gamma_bilinear :
|
||||||
|
public span_image_filter<rgba8, Interpolator, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Interpolator interpolator_type;
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef span_image_filter<rgba8, Interpolator, Allocator> base_type;
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
typedef Gamma gamma_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgb24_gamma_bilinear(alloc_type& alloc,
|
||||||
|
const gamma_type& g) :
|
||||||
|
base_type(alloc),
|
||||||
|
m_gamma(&g)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgb24_gamma_bilinear(alloc_type& alloc,
|
||||||
|
const rendering_buffer& src,
|
||||||
|
const color_type& back_color,
|
||||||
|
interpolator_type& inter,
|
||||||
|
const gamma_type& g) :
|
||||||
|
base_type(alloc, src, back_color, inter, 0),
|
||||||
|
m_gamma(&g)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
base_type::interpolator().begin(x, y, len);
|
||||||
|
|
||||||
|
int fg[3];
|
||||||
|
int src_alpha;
|
||||||
|
int back_r = m_gamma->dir(base_type::background_color().r);
|
||||||
|
int back_g = m_gamma->dir(base_type::background_color().g);
|
||||||
|
int back_b = m_gamma->dir(base_type::background_color().b);
|
||||||
|
int back_a = base_type::background_color().a;
|
||||||
|
|
||||||
|
const unsigned char *fg_ptr;
|
||||||
|
|
||||||
|
int stride = base_type::source_image().stride() - 2 * 3;
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
|
||||||
|
int maxx = base_type::source_image().width() - 1;
|
||||||
|
int maxy = base_type::source_image().height() - 1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int x_hr;
|
||||||
|
int y_hr;
|
||||||
|
|
||||||
|
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||||
|
|
||||||
|
int x_lr = x_hr >> image_subpixel_shift;
|
||||||
|
int y_lr = y_hr >> image_subpixel_shift;
|
||||||
|
int weight;
|
||||||
|
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr < maxx && y_lr < maxy)
|
||||||
|
{
|
||||||
|
fg[0] =
|
||||||
|
fg[1] =
|
||||||
|
fg[2] = image_subpixel_size * image_subpixel_size / 2;
|
||||||
|
|
||||||
|
x_hr &= image_subpixel_mask;
|
||||||
|
y_hr &= image_subpixel_mask;
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
|
||||||
|
|
||||||
|
weight = (image_subpixel_size - x_hr) *
|
||||||
|
(image_subpixel_size - y_hr);
|
||||||
|
fg[0] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[1] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[2] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
|
||||||
|
weight = x_hr * (image_subpixel_size - y_hr);
|
||||||
|
fg[0] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[1] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[2] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
|
||||||
|
fg_ptr += stride;
|
||||||
|
|
||||||
|
weight = (image_subpixel_size - x_hr) * y_hr;
|
||||||
|
fg[0] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[1] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[2] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
|
||||||
|
weight = x_hr * y_hr;
|
||||||
|
fg[0] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[1] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[2] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
|
||||||
|
fg[0] >>= image_subpixel_shift * 2;
|
||||||
|
fg[1] >>= image_subpixel_shift * 2;
|
||||||
|
fg[2] >>= image_subpixel_shift * 2;
|
||||||
|
src_alpha = 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(x_lr < -1 || y_lr < -1 ||
|
||||||
|
x_lr > maxx || y_lr > maxy)
|
||||||
|
{
|
||||||
|
fg[Order::R] = back_r;
|
||||||
|
fg[Order::G] = back_g;
|
||||||
|
fg[Order::B] = back_b;
|
||||||
|
src_alpha = back_a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[0] =
|
||||||
|
fg[1] =
|
||||||
|
fg[2] =
|
||||||
|
src_alpha = image_subpixel_size * image_subpixel_size / 2;
|
||||||
|
|
||||||
|
x_hr &= image_subpixel_mask;
|
||||||
|
y_hr &= image_subpixel_mask;
|
||||||
|
|
||||||
|
weight = (image_subpixel_size - x_hr) *
|
||||||
|
(image_subpixel_size - y_hr);
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
|
||||||
|
fg[0] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[1] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[2] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
src_alpha += weight * 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
src_alpha += back_a * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
x_lr++;
|
||||||
|
|
||||||
|
weight = x_hr * (image_subpixel_size - y_hr);
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
|
||||||
|
fg[0] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[1] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[2] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
src_alpha += weight * 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
src_alpha += back_a * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
x_lr--;
|
||||||
|
y_lr++;
|
||||||
|
|
||||||
|
weight = (image_subpixel_size - x_hr) * y_hr;
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
|
||||||
|
fg[0] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[1] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[2] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
src_alpha += weight * 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
src_alpha += back_a * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
x_lr++;
|
||||||
|
|
||||||
|
weight = x_hr * y_hr;
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + x_lr + x_lr + x_lr;
|
||||||
|
fg[0] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[1] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
fg[2] += weight * m_gamma->dir(*fg_ptr++);
|
||||||
|
src_alpha += weight * 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
src_alpha += back_a * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
fg[0] >>= image_subpixel_shift * 2;
|
||||||
|
fg[1] >>= image_subpixel_shift * 2;
|
||||||
|
fg[2] >>= image_subpixel_shift * 2;
|
||||||
|
src_alpha >>= image_subpixel_shift * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span->r = (int8u)m_gamma->inv(fg[Order::R]);
|
||||||
|
span->g = (int8u)m_gamma->inv(fg[Order::G]);
|
||||||
|
span->b = (int8u)m_gamma->inv(fg[Order::B]);
|
||||||
|
span->a = (int8u)src_alpha;
|
||||||
|
++span;
|
||||||
|
++base_type::interpolator();
|
||||||
|
|
||||||
|
} while(--len);
|
||||||
|
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const gamma_type* m_gamma;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============================================span_image_filter_rgb24_gamma
|
||||||
|
template<class Order,
|
||||||
|
class Interpolator,
|
||||||
|
class Allocator = span_allocator<rgba8>,
|
||||||
|
class Gamma = gamma_lut<int8u, int8u, 8, 8> >
|
||||||
|
class span_image_filter_rgb24_gamma :
|
||||||
|
public span_image_filter<rgba8, Interpolator, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Interpolator interpolator_type;
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
typedef Gamma gamma_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgb24_gamma(alloc_type& alloc, const gamma_type& g) :
|
||||||
|
base_type(alloc),
|
||||||
|
m_gamma(&g)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgb24_gamma(alloc_type& alloc,
|
||||||
|
const rendering_buffer& src,
|
||||||
|
const color_type& back_color,
|
||||||
|
interpolator_type& inter,
|
||||||
|
const image_filter_base& filter,
|
||||||
|
const gamma_type& g) :
|
||||||
|
base_type(alloc, src, back_color, inter, &filter),
|
||||||
|
m_gamma(&g)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
base_type::interpolator().begin(x, y, len);
|
||||||
|
|
||||||
|
int fg[3];
|
||||||
|
int src_alpha;
|
||||||
|
int back_r = m_gamma->dir(base_type::background_color().r);
|
||||||
|
int back_g = m_gamma->dir(base_type::background_color().g);
|
||||||
|
int back_b = m_gamma->dir(base_type::background_color().b);
|
||||||
|
int back_a = base_type::background_color().a;
|
||||||
|
|
||||||
|
const unsigned char *fg_ptr;
|
||||||
|
|
||||||
|
unsigned dimension = base_type::filter().dimension();
|
||||||
|
int start = base_type::filter().start();
|
||||||
|
int start1 = start - 1;
|
||||||
|
const int* weight_array = base_type::filter().weight_array_int();
|
||||||
|
|
||||||
|
int stride = base_type::source_image().stride() - dimension * 3;
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
|
||||||
|
int maxx = base_type::source_image().width() + start - 2;
|
||||||
|
int maxy = base_type::source_image().height() + start - 2;
|
||||||
|
|
||||||
|
int maxx2 = base_type::source_image().width() - start - 1;
|
||||||
|
int maxy2 = base_type::source_image().height() - start - 1;
|
||||||
|
|
||||||
|
int x_count;
|
||||||
|
int weight_y;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::interpolator().coordinates(&x, &y);
|
||||||
|
|
||||||
|
int x_hr = x;
|
||||||
|
int y_hr = y;
|
||||||
|
|
||||||
|
int x_lr = x_hr >> image_subpixel_shift;
|
||||||
|
int y_lr = y_hr >> image_subpixel_shift;
|
||||||
|
|
||||||
|
fg[0] = fg[1] = fg[2] = image_filter_size / 2;
|
||||||
|
|
||||||
|
int x_fract = x_hr & image_subpixel_mask;
|
||||||
|
unsigned y_count = dimension;
|
||||||
|
|
||||||
|
if(x_lr >= -start && y_lr >= -start &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr + start) + (x_lr + start) * 3;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
x_count = dimension;
|
||||||
|
weight_y = weight_array[y_hr];
|
||||||
|
x_hr = image_subpixel_mask - x_fract;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int weight = (weight_y * weight_array[x_hr] +
|
||||||
|
image_filter_size / 2) >>
|
||||||
|
image_filter_shift;
|
||||||
|
|
||||||
|
fg[0] += m_gamma->dir(*fg_ptr++) * weight;
|
||||||
|
fg[1] += m_gamma->dir(*fg_ptr++) * weight;
|
||||||
|
fg[2] += m_gamma->dir(*fg_ptr++) * weight;
|
||||||
|
|
||||||
|
x_hr += image_subpixel_size;
|
||||||
|
|
||||||
|
} while(--x_count);
|
||||||
|
|
||||||
|
y_hr += image_subpixel_size;
|
||||||
|
fg_ptr += stride;
|
||||||
|
|
||||||
|
} while(--y_count);
|
||||||
|
|
||||||
|
fg[0] >>= image_filter_shift;
|
||||||
|
fg[1] >>= image_filter_shift;
|
||||||
|
fg[2] >>= image_filter_shift;
|
||||||
|
|
||||||
|
if(fg[0] < 0) fg[0] = 0;
|
||||||
|
if(fg[1] < 0) fg[1] = 0;
|
||||||
|
if(fg[2] < 0) fg[2] = 0;
|
||||||
|
|
||||||
|
if(fg[0] > 255) fg[0] = 255;
|
||||||
|
if(fg[1] > 255) fg[1] = 255;
|
||||||
|
if(fg[2] > 255) fg[2] = 255;
|
||||||
|
src_alpha = 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(x_lr < start1 || y_lr < start1 ||
|
||||||
|
x_lr > maxx2 || y_lr > maxy2)
|
||||||
|
{
|
||||||
|
fg[Order::R] = back_r;
|
||||||
|
fg[Order::G] = back_g;
|
||||||
|
fg[Order::B] = back_b;
|
||||||
|
src_alpha = back_a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
src_alpha = image_filter_size / 2;
|
||||||
|
y_lr = (y >> image_subpixel_shift) + start;
|
||||||
|
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
x_count = dimension;
|
||||||
|
weight_y = weight_array[y_hr];
|
||||||
|
x_lr = (x >> image_subpixel_shift) + start;
|
||||||
|
x_hr = image_subpixel_mask - x_fract;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int weight = (weight_y * weight_array[x_hr] +
|
||||||
|
image_filter_size / 2) >>
|
||||||
|
image_filter_shift;
|
||||||
|
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr < int(base_type::source_image().width()) &&
|
||||||
|
y_lr < int(base_type::source_image().height()))
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + x_lr * 3;
|
||||||
|
fg[0] += m_gamma->dir(*fg_ptr++) * weight;
|
||||||
|
fg[1] += m_gamma->dir(*fg_ptr++) * weight;
|
||||||
|
fg[2] += m_gamma->dir(*fg_ptr++) * weight;
|
||||||
|
src_alpha += 255 * weight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
src_alpha += back_a * weight;
|
||||||
|
}
|
||||||
|
x_hr += image_subpixel_size;
|
||||||
|
x_lr++;
|
||||||
|
|
||||||
|
} while(--x_count);
|
||||||
|
|
||||||
|
y_hr += image_subpixel_size;
|
||||||
|
y_lr++;
|
||||||
|
|
||||||
|
} while(--y_count);
|
||||||
|
|
||||||
|
|
||||||
|
fg[0] >>= image_filter_shift;
|
||||||
|
fg[1] >>= image_filter_shift;
|
||||||
|
fg[2] >>= image_filter_shift;
|
||||||
|
src_alpha >>= image_filter_shift;
|
||||||
|
|
||||||
|
if(fg[0] < 0) fg[0] = 0;
|
||||||
|
if(fg[1] < 0) fg[1] = 0;
|
||||||
|
if(fg[2] < 0) fg[2] = 0;
|
||||||
|
if(src_alpha < 0) src_alpha = 0;
|
||||||
|
|
||||||
|
if(fg[0] > 255) fg[0] = 255;
|
||||||
|
if(fg[1] > 255) fg[1] = 255;
|
||||||
|
if(fg[2] > 255) fg[2] = 255;
|
||||||
|
if(src_alpha > 255) src_alpha = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span->r = (int8u)m_gamma->inv(fg[Order::R]);
|
||||||
|
span->g = (int8u)m_gamma->inv(fg[Order::G]);
|
||||||
|
span->b = (int8u)m_gamma->inv(fg[Order::B]);
|
||||||
|
span->a = (int8u)src_alpha;
|
||||||
|
++span;
|
||||||
|
++base_type::interpolator();
|
||||||
|
|
||||||
|
} while(--len);
|
||||||
|
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const gamma_type* m_gamma;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,548 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// classes span_image_filter_rgba32*
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_SPAN_IMAGE_FILTER_RGBA32_INCLUDED
|
||||||
|
#define AGG_SPAN_IMAGE_FILTER_RGBA32_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_color_rgba8.h"
|
||||||
|
#include "agg_span_image_filter.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//=============================================span_image_filter_rgba32_nn
|
||||||
|
template<class Order,
|
||||||
|
class Interpolator,
|
||||||
|
class Allocator = span_allocator<rgba8> >
|
||||||
|
class span_image_filter_rgba32_nn :
|
||||||
|
public span_image_filter<rgba8, Interpolator, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Interpolator interpolator_type;
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgba32_nn(alloc_type& alloc) : base_type(alloc) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgba32_nn(alloc_type& alloc,
|
||||||
|
const rendering_buffer& src,
|
||||||
|
const color_type& back_color,
|
||||||
|
interpolator_type& inter) :
|
||||||
|
base_type(alloc, src, back_color, inter, 0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
base_type::interpolator().begin(x, y, len);
|
||||||
|
|
||||||
|
int fg[4];
|
||||||
|
|
||||||
|
const unsigned char *fg_ptr;
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
|
||||||
|
int maxx = base_type::source_image().width() - 1;
|
||||||
|
int maxy = base_type::source_image().height() - 1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::interpolator().coordinates(&x, &y);
|
||||||
|
|
||||||
|
x >>= image_subpixel_shift;
|
||||||
|
y >>= image_subpixel_shift;
|
||||||
|
|
||||||
|
if(x >= 0 && y >= 0 &&
|
||||||
|
x <= maxx && y <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y) + (x << 2);
|
||||||
|
fg[0] = *fg_ptr++;
|
||||||
|
fg[1] = *fg_ptr++;
|
||||||
|
fg[2] = *fg_ptr++;
|
||||||
|
fg[3] = *fg_ptr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] = base_type::background_color().r;
|
||||||
|
fg[Order::G] = base_type::background_color().g;
|
||||||
|
fg[Order::B] = base_type::background_color().b;
|
||||||
|
fg[Order::A] = base_type::background_color().a;
|
||||||
|
}
|
||||||
|
|
||||||
|
span->r = fg[Order::R];
|
||||||
|
span->g = fg[Order::G];
|
||||||
|
span->b = fg[Order::B];
|
||||||
|
span->a = fg[Order::A];
|
||||||
|
++span;
|
||||||
|
++base_type::interpolator();
|
||||||
|
|
||||||
|
} while(--len);
|
||||||
|
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=======================================span_image_filter_rgba32_bilinear
|
||||||
|
template<class Order,
|
||||||
|
class Interpolator,
|
||||||
|
class Allocator = span_allocator<rgba8> >
|
||||||
|
class span_image_filter_rgba32_bilinear :
|
||||||
|
public span_image_filter<rgba8, Interpolator, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Interpolator interpolator_type;
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgba32_bilinear(alloc_type& alloc) : base_type(alloc) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgba32_bilinear(alloc_type& alloc,
|
||||||
|
const rendering_buffer& src,
|
||||||
|
const color_type& back_color,
|
||||||
|
interpolator_type& inter) :
|
||||||
|
base_type(alloc, src, back_color, inter, 0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
base_type::interpolator().begin(x, y, len);
|
||||||
|
|
||||||
|
int fg[4];
|
||||||
|
int back_r = base_type::background_color().r;
|
||||||
|
int back_g = base_type::background_color().g;
|
||||||
|
int back_b = base_type::background_color().b;
|
||||||
|
int back_a = base_type::background_color().a;
|
||||||
|
|
||||||
|
const unsigned char *fg_ptr;
|
||||||
|
|
||||||
|
int stride = base_type::source_image().stride() - 2 * 4;
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
|
||||||
|
int maxx = base_type::source_image().width() - 1;
|
||||||
|
int maxy = base_type::source_image().height() - 1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int x_hr;
|
||||||
|
int y_hr;
|
||||||
|
|
||||||
|
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||||
|
|
||||||
|
int x_lr = x_hr >> image_subpixel_shift;
|
||||||
|
int y_lr = y_hr >> image_subpixel_shift;
|
||||||
|
int weight;
|
||||||
|
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr < maxx && y_lr < maxy)
|
||||||
|
{
|
||||||
|
fg[0] =
|
||||||
|
fg[1] =
|
||||||
|
fg[2] =
|
||||||
|
fg[3] = image_subpixel_size * image_subpixel_size / 2;
|
||||||
|
|
||||||
|
x_hr &= image_subpixel_mask;
|
||||||
|
y_hr &= image_subpixel_mask;
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2);
|
||||||
|
|
||||||
|
weight = (image_subpixel_size - x_hr) *
|
||||||
|
(image_subpixel_size - y_hr);
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
fg[3] += weight * *fg_ptr++;
|
||||||
|
|
||||||
|
weight = x_hr * (image_subpixel_size - y_hr);
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
fg[3] += weight * *fg_ptr++;
|
||||||
|
|
||||||
|
fg_ptr += stride;
|
||||||
|
|
||||||
|
weight = (image_subpixel_size - x_hr) * y_hr;
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
fg[3] += weight * *fg_ptr++;
|
||||||
|
|
||||||
|
weight = x_hr * y_hr;
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
fg[3] += weight * *fg_ptr++;
|
||||||
|
|
||||||
|
fg[0] >>= image_subpixel_shift * 2;
|
||||||
|
fg[1] >>= image_subpixel_shift * 2;
|
||||||
|
fg[2] >>= image_subpixel_shift * 2;
|
||||||
|
fg[3] >>= image_subpixel_shift * 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(x_lr < -1 || y_lr < -1 ||
|
||||||
|
x_lr > maxx || y_lr > maxy)
|
||||||
|
{
|
||||||
|
fg[Order::R] = back_r;
|
||||||
|
fg[Order::G] = back_g;
|
||||||
|
fg[Order::B] = back_b;
|
||||||
|
fg[Order::A] = back_a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[0] =
|
||||||
|
fg[1] =
|
||||||
|
fg[2] =
|
||||||
|
fg[3] = image_subpixel_size * image_subpixel_size / 2;
|
||||||
|
|
||||||
|
x_hr &= image_subpixel_mask;
|
||||||
|
y_hr &= image_subpixel_mask;
|
||||||
|
|
||||||
|
weight = (image_subpixel_size - x_hr) *
|
||||||
|
(image_subpixel_size - y_hr);
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2);
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
fg[3] += weight * *fg_ptr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
fg[Order::A] += back_a * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
x_lr++;
|
||||||
|
|
||||||
|
weight = x_hr * (image_subpixel_size - y_hr);
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2);
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
fg[3] += weight * *fg_ptr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
fg[Order::A] += back_a * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
x_lr--;
|
||||||
|
y_lr++;
|
||||||
|
|
||||||
|
weight = (image_subpixel_size - x_hr) * y_hr;
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2);
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
fg[3] += weight * *fg_ptr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
fg[Order::A] += back_a * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
x_lr++;
|
||||||
|
|
||||||
|
weight = x_hr * y_hr;
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2);
|
||||||
|
fg[0] += weight * *fg_ptr++;
|
||||||
|
fg[1] += weight * *fg_ptr++;
|
||||||
|
fg[2] += weight * *fg_ptr++;
|
||||||
|
fg[3] += weight * *fg_ptr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
fg[Order::A] += back_a * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
fg[0] >>= image_subpixel_shift * 2;
|
||||||
|
fg[1] >>= image_subpixel_shift * 2;
|
||||||
|
fg[2] >>= image_subpixel_shift * 2;
|
||||||
|
fg[3] >>= image_subpixel_shift * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span->r = (int8u)fg[Order::R];
|
||||||
|
span->g = (int8u)fg[Order::G];
|
||||||
|
span->b = (int8u)fg[Order::B];
|
||||||
|
span->a = (int8u)fg[Order::A];
|
||||||
|
++span;
|
||||||
|
++base_type::interpolator();
|
||||||
|
|
||||||
|
} while(--len);
|
||||||
|
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================================================span_image_filter_rgba32
|
||||||
|
template<class Order,
|
||||||
|
class Interpolator,
|
||||||
|
class Allocator = span_allocator<rgba8> >
|
||||||
|
class span_image_filter_rgba32 :
|
||||||
|
public span_image_filter<rgba8, Interpolator, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Interpolator interpolator_type;
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef span_image_filter<rgba8, Interpolator, alloc_type> base_type;
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgba32(alloc_type& alloc) : base_type(alloc) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_image_filter_rgba32(alloc_type& alloc,
|
||||||
|
const rendering_buffer& src,
|
||||||
|
const color_type& back_color,
|
||||||
|
interpolator_type& inter,
|
||||||
|
const image_filter_base& filter) :
|
||||||
|
base_type(alloc, src, back_color, inter, &filter)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
base_type::interpolator().begin(x, y, len);
|
||||||
|
|
||||||
|
int fg[4];
|
||||||
|
|
||||||
|
int back_r = base_type::background_color().r;
|
||||||
|
int back_g = base_type::background_color().g;
|
||||||
|
int back_b = base_type::background_color().b;
|
||||||
|
int back_a = base_type::background_color().a;
|
||||||
|
|
||||||
|
const unsigned char *fg_ptr;
|
||||||
|
|
||||||
|
unsigned dimension = base_type::filter().dimension();
|
||||||
|
int start = base_type::filter().start();
|
||||||
|
int start1 = start - 1;
|
||||||
|
const int* weight_array = base_type::filter().weight_array_int();
|
||||||
|
|
||||||
|
int stride = base_type::source_image().stride() - (dimension << 2);
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
|
||||||
|
int maxx = base_type::source_image().width() + start - 2;
|
||||||
|
int maxy = base_type::source_image().height() + start - 2;
|
||||||
|
|
||||||
|
int maxx2 = base_type::source_image().width() - start - 1;
|
||||||
|
int maxy2 = base_type::source_image().height() - start - 1;
|
||||||
|
|
||||||
|
int x_count;
|
||||||
|
int weight_y;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
base_type::interpolator().coordinates(&x, &y);
|
||||||
|
|
||||||
|
int x_hr = x;
|
||||||
|
int y_hr = y;
|
||||||
|
|
||||||
|
int x_lr = x_hr >> image_subpixel_shift;
|
||||||
|
int y_lr = y_hr >> image_subpixel_shift;
|
||||||
|
|
||||||
|
fg[0] = fg[1] = fg[2] = fg[3] = image_filter_size / 2;
|
||||||
|
|
||||||
|
int x_fract = x_hr & image_subpixel_mask;
|
||||||
|
unsigned y_count = dimension;
|
||||||
|
|
||||||
|
if(x_lr >= -start && y_lr >= -start &&
|
||||||
|
x_lr <= maxx && y_lr <= maxy)
|
||||||
|
{
|
||||||
|
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr + start) + ((x_lr + start) << 2);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
x_count = dimension;
|
||||||
|
weight_y = weight_array[y_hr];
|
||||||
|
x_hr = image_subpixel_mask - x_fract;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int weight = (weight_y * weight_array[x_hr] +
|
||||||
|
image_filter_size / 2) >>
|
||||||
|
image_filter_shift;
|
||||||
|
|
||||||
|
fg[0] += *fg_ptr++ * weight;
|
||||||
|
fg[1] += *fg_ptr++ * weight;
|
||||||
|
fg[2] += *fg_ptr++ * weight;
|
||||||
|
fg[3] += *fg_ptr++ * weight;
|
||||||
|
|
||||||
|
x_hr += image_subpixel_size;
|
||||||
|
|
||||||
|
} while(--x_count);
|
||||||
|
|
||||||
|
y_hr += image_subpixel_size;
|
||||||
|
fg_ptr += stride;
|
||||||
|
|
||||||
|
} while(--y_count);
|
||||||
|
|
||||||
|
fg[0] >>= image_filter_shift;
|
||||||
|
fg[1] >>= image_filter_shift;
|
||||||
|
fg[2] >>= image_filter_shift;
|
||||||
|
fg[3] >>= image_filter_shift;
|
||||||
|
|
||||||
|
if(fg[0] < 0) fg[0] = 0;
|
||||||
|
if(fg[1] < 0) fg[1] = 0;
|
||||||
|
if(fg[2] < 0) fg[2] = 0;
|
||||||
|
if(fg[3] < 0) fg[3] = 0;
|
||||||
|
|
||||||
|
if(fg[0] > 255) fg[0] = 255;
|
||||||
|
if(fg[1] > 255) fg[1] = 255;
|
||||||
|
if(fg[2] > 255) fg[2] = 255;
|
||||||
|
if(fg[3] > 255) fg[3] = 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(x_lr < start1 || y_lr < start1 ||
|
||||||
|
x_lr > maxx2 || y_lr > maxy2)
|
||||||
|
{
|
||||||
|
fg[Order::R] = back_r;
|
||||||
|
fg[Order::G] = back_g;
|
||||||
|
fg[Order::B] = back_b;
|
||||||
|
fg[Order::A] = back_a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
y_lr = (y >> image_subpixel_shift) + start;
|
||||||
|
y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
x_count = dimension;
|
||||||
|
weight_y = weight_array[y_hr];
|
||||||
|
x_lr = (x >> image_subpixel_shift) + start;
|
||||||
|
x_hr = image_subpixel_mask - x_fract;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int weight = (weight_y * weight_array[x_hr] +
|
||||||
|
image_filter_size / 2) >>
|
||||||
|
image_filter_shift;
|
||||||
|
|
||||||
|
if(x_lr >= 0 && y_lr >= 0 &&
|
||||||
|
x_lr < int(base_type::source_image().width()) &&
|
||||||
|
y_lr < int(base_type::source_image().height()))
|
||||||
|
{
|
||||||
|
fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2);
|
||||||
|
fg[0] += *fg_ptr++ * weight;
|
||||||
|
fg[1] += *fg_ptr++ * weight;
|
||||||
|
fg[2] += *fg_ptr++ * weight;
|
||||||
|
fg[3] += *fg_ptr++ * weight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fg[Order::R] += back_r * weight;
|
||||||
|
fg[Order::G] += back_g * weight;
|
||||||
|
fg[Order::B] += back_b * weight;
|
||||||
|
fg[Order::A] += back_a * weight;
|
||||||
|
}
|
||||||
|
x_hr += image_subpixel_size;
|
||||||
|
x_lr++;
|
||||||
|
|
||||||
|
} while(--x_count);
|
||||||
|
|
||||||
|
y_hr += image_subpixel_size;
|
||||||
|
y_lr++;
|
||||||
|
|
||||||
|
} while(--y_count);
|
||||||
|
|
||||||
|
|
||||||
|
fg[0] >>= image_filter_shift;
|
||||||
|
fg[1] >>= image_filter_shift;
|
||||||
|
fg[2] >>= image_filter_shift;
|
||||||
|
fg[3] >>= image_filter_shift;
|
||||||
|
|
||||||
|
if(fg[0] < 0) fg[0] = 0;
|
||||||
|
if(fg[1] < 0) fg[1] = 0;
|
||||||
|
if(fg[2] < 0) fg[2] = 0;
|
||||||
|
if(fg[3] < 0) fg[3] = 0;
|
||||||
|
|
||||||
|
if(fg[0] > 255) fg[0] = 255;
|
||||||
|
if(fg[1] > 255) fg[1] = 255;
|
||||||
|
if(fg[2] > 255) fg[2] = 255;
|
||||||
|
if(fg[3] > 255) fg[3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span->r = fg[Order::R];
|
||||||
|
span->g = fg[Order::G];
|
||||||
|
span->b = fg[Order::B];
|
||||||
|
span->a = fg[Order::A];
|
||||||
|
++span;
|
||||||
|
++base_type::interpolator();
|
||||||
|
|
||||||
|
} while(--len);
|
||||||
|
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED
|
||||||
|
#define AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//===============================================span_interpolator_adaptor
|
||||||
|
template<class Interpolator, class Distortion>
|
||||||
|
class span_interpolator_adaptor : public Interpolator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Interpolator base_type;
|
||||||
|
typedef typename base_type::trans_type trans_type;
|
||||||
|
typedef Distortion distortion_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_interpolator_adaptor() {}
|
||||||
|
span_interpolator_adaptor(const trans_type& trans,
|
||||||
|
const distortion_type& dist) :
|
||||||
|
base_type(trans),
|
||||||
|
m_distortion(&dist)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_interpolator_adaptor(const trans_type& trans,
|
||||||
|
const distortion_type& dist,
|
||||||
|
double x, double y, unsigned len) :
|
||||||
|
base_type(trans, x, y, len),
|
||||||
|
m_distortion(&dist)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const distortion_type& distortion() const
|
||||||
|
{
|
||||||
|
return *m_distortion;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void distortion(const distortion_type& dist)
|
||||||
|
{
|
||||||
|
m_distortion = dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void coordinates(int* x, int* y) const
|
||||||
|
{
|
||||||
|
base_type::coordinates(x, y);
|
||||||
|
m_distortion->calculate(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
const distortion_type* m_distortion;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED
|
||||||
|
#define AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_dda_line.h"
|
||||||
|
#include "agg_trans_affine.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//================================================span_interpolator_linear
|
||||||
|
template<class Transformer = trans_affine, unsigned SubpixelShift = 8>
|
||||||
|
class span_interpolator_linear
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Transformer trans_type;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
subpixel_shift = SubpixelShift,
|
||||||
|
subpixel_size = 1 << subpixel_shift
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_interpolator_linear() {}
|
||||||
|
span_interpolator_linear(const trans_type& trans) : m_trans(&trans) {}
|
||||||
|
span_interpolator_linear(const trans_type& trans,
|
||||||
|
double x, double y, unsigned len) :
|
||||||
|
m_trans(&trans)
|
||||||
|
{
|
||||||
|
begin(x, y, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
const trans_type& transformer() const { return *m_trans; }
|
||||||
|
void transformer(const trans_type& trans) { m_trans = &trans; }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
void begin(double x, double y, unsigned len)
|
||||||
|
{
|
||||||
|
double tx;
|
||||||
|
double ty;
|
||||||
|
|
||||||
|
tx = x;
|
||||||
|
ty = y;
|
||||||
|
m_trans->transform(&tx, &ty);
|
||||||
|
int x1 = int(tx * subpixel_size);
|
||||||
|
int y1 = int(ty * subpixel_size);
|
||||||
|
|
||||||
|
tx = x + len;
|
||||||
|
ty = y;
|
||||||
|
m_trans->transform(&tx, &ty);
|
||||||
|
int x2 = int(tx * subpixel_size);
|
||||||
|
int y2 = int(ty * subpixel_size);
|
||||||
|
|
||||||
|
m_li_x = dda2_line_interpolator(x1, x2, len);
|
||||||
|
m_li_y = dda2_line_interpolator(y1, y2, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
void operator++()
|
||||||
|
{
|
||||||
|
++m_li_x;
|
||||||
|
++m_li_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
void coordinates(int* x, int* y) const
|
||||||
|
{
|
||||||
|
*x = m_li_x.y();
|
||||||
|
*y = m_li_y.y();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const trans_type* m_trans;
|
||||||
|
dda2_line_interpolator m_li_x;
|
||||||
|
dda2_line_interpolator m_li_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Horizontal span interpolator for use with an arbitrary transformer
|
||||||
|
// The efficiency highly depends on the operations done in the transformer
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED
|
||||||
|
#define AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//=================================================span_interpolator_trans
|
||||||
|
template<class Transformer, unsigned SubpixelShift = 8>
|
||||||
|
class span_interpolator_trans
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Transformer trans_type;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
subpixel_shift = SubpixelShift,
|
||||||
|
subpixel_size = 1 << subpixel_shift
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_interpolator_trans() {}
|
||||||
|
span_interpolator_trans(const trans_type& trans) : m_trans(&trans) {}
|
||||||
|
span_interpolator_trans(const trans_type& trans,
|
||||||
|
double x, double y, unsigned) :
|
||||||
|
m_trans(&trans)
|
||||||
|
{
|
||||||
|
begin(x, y, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
const trans_type& transformer() const { return *m_trans; }
|
||||||
|
void transformer(const trans_type& trans) { m_trans = &trans; }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
void begin(double x, double y, unsigned)
|
||||||
|
{
|
||||||
|
m_x = x;
|
||||||
|
m_y = y;
|
||||||
|
transform();
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
void operator++()
|
||||||
|
{
|
||||||
|
m_x += 1.0;
|
||||||
|
transform();
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
void coordinates(int* x, int* y) const
|
||||||
|
{
|
||||||
|
*x = m_ix;
|
||||||
|
*y = m_iy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
void transform()
|
||||||
|
{
|
||||||
|
double x = m_x;
|
||||||
|
double y = m_y;
|
||||||
|
m_trans->transform(&x, &y);
|
||||||
|
m_ix = int(x * subpixel_size);
|
||||||
|
m_iy = int(y * subpixel_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const trans_type* m_trans;
|
||||||
|
double m_x;
|
||||||
|
double m_y;
|
||||||
|
int m_ix;
|
||||||
|
int m_iy;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_PATTERN_INCLUDED
|
||||||
|
#define AGG_SPAN_PATTERN_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
#include "agg_span_generator.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//--------------------------------------------------------span_pattern
|
||||||
|
template<class ColorT, class AlphaT, class Allocator>
|
||||||
|
class span_pattern : public span_generator<ColorT, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef ColorT color_type;
|
||||||
|
typedef AlphaT alpha_type;
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
span_pattern(alloc_type& alloc) :
|
||||||
|
span_generator<color_type, alloc_type>(alloc)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
span_pattern(alloc_type& alloc,
|
||||||
|
const rendering_buffer& src,
|
||||||
|
unsigned offset_x, unsigned offset_y,
|
||||||
|
alpha_type alpha) :
|
||||||
|
span_generator<color_type, alloc_type>(alloc),
|
||||||
|
m_src(&src),
|
||||||
|
m_offset_x(offset_x),
|
||||||
|
m_offset_y(offset_y),
|
||||||
|
m_alpha(alpha)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
const rendering_buffer& source_image() const { return *m_src; }
|
||||||
|
unsigned offset_x() const { return m_offset_x; }
|
||||||
|
unsigned offset_y() const { return m_offset_y; }
|
||||||
|
alpha_type alpha() const { return m_alpha; }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
void source_image(const rendering_buffer& v) { m_src = &v; }
|
||||||
|
void offset_x(unsigned v) { m_offset_x = v; }
|
||||||
|
void offset_y(unsigned v) { m_offset_y = v; }
|
||||||
|
void alpha(alpha_type v) { m_alpha = v; }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
const rendering_buffer* m_src;
|
||||||
|
unsigned m_offset_x;
|
||||||
|
unsigned m_offset_y;
|
||||||
|
alpha_type m_alpha;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_PATTERN_RGB24_INCLUDED
|
||||||
|
#define AGG_SPAN_PATTERN_RGB24_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_pixfmt_rgb24.h"
|
||||||
|
#include "agg_span_pattern.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//=======================================================span_pattern_rgb24
|
||||||
|
template<class Order, class Allocator = span_allocator<rgba8> >
|
||||||
|
class span_pattern_rgb24 : public span_pattern<rgba8, int8u, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
typedef span_pattern<color_type, int8u, alloc_type> base_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_pattern_rgb24(alloc_type& alloc) : base_type(alloc) {}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
span_pattern_rgb24(alloc_type& alloc,
|
||||||
|
const rendering_buffer& src,
|
||||||
|
unsigned offset_x, unsigned offset_y,
|
||||||
|
int8u alpha = 255) :
|
||||||
|
base_type(alloc, src, offset_x, offset_y, alpha)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
unsigned sx = (base_type::offset_x() + x) % base_type::source_image().width();
|
||||||
|
unsigned wp = base_type::source_image().width() * 3;
|
||||||
|
const int8u* p = base_type::source_image().row((base_type::offset_y() + y) % base_type::source_image().height());
|
||||||
|
p += sx * 3;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
span->r = p[Order::R];
|
||||||
|
span->g = p[Order::G];
|
||||||
|
span->b = p[Order::B];
|
||||||
|
span->a = base_type::alpha();
|
||||||
|
p += 3;
|
||||||
|
++sx;
|
||||||
|
++span;
|
||||||
|
if(sx >= base_type::source_image().width())
|
||||||
|
{
|
||||||
|
sx -= base_type::source_image().width();
|
||||||
|
p -= wp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_PATTERN_RGBA32_INCLUDED
|
||||||
|
#define AGG_SPAN_PATTERN_RGBA32_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_pixfmt_rgba32.h"
|
||||||
|
#include "agg_span_pattern.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//======================================================span_pattern_rgba32
|
||||||
|
template<class Order, class Allocator = span_allocator<rgba8> >
|
||||||
|
class span_pattern_rgba32 : public span_pattern<rgba8, int8u, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef rgba8 color_type;
|
||||||
|
typedef span_pattern<color_type, int8u, alloc_type> base_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_pattern_rgba32(alloc_type& alloc) : base_type(alloc) {}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
span_pattern_rgba32(alloc_type& alloc,
|
||||||
|
const rendering_buffer& src,
|
||||||
|
unsigned offset_x, unsigned offset_y) :
|
||||||
|
base_type(alloc, src, offset_x, offset_y, 0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
unsigned sx = (base_type::offset_x() + x) % base_type::source_image().width();
|
||||||
|
unsigned wp = base_type::source_image().width() << 2;
|
||||||
|
const int8u* p = base_type::source_image().row((base_type::offset_y() + y) % base_type::source_image().height());
|
||||||
|
p += sx << 2;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
span->r = p[Order::R];
|
||||||
|
span->g = p[Order::G];
|
||||||
|
span->b = p[Order::B];
|
||||||
|
span->a = p[Order::A];
|
||||||
|
p += 4;
|
||||||
|
++sx;
|
||||||
|
++span;
|
||||||
|
if(sx >= base_type::source_image().width())
|
||||||
|
{
|
||||||
|
sx -= base_type::source_image().width();
|
||||||
|
p -= wp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// span_solid_rgba8
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef AGG_SPAN_SOLID_INCLUDED
|
||||||
|
#define AGG_SPAN_SOLID_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_span_generator.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
//--------------------------------------------------------------span_solid
|
||||||
|
template<class ColorT, class Allocator = span_allocator<ColorT> >
|
||||||
|
class span_solid : public span_generator<ColorT, Allocator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Allocator alloc_type;
|
||||||
|
typedef ColorT color_type;
|
||||||
|
typedef span_generator<color_type, alloc_type> base_type;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
span_solid(alloc_type& alloc) : base_type(alloc) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void color(const color_type& c) { m_color = c; }
|
||||||
|
const color_type& color() const { return m_color; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
color_type* generate(int x, int y, unsigned len)
|
||||||
|
{
|
||||||
|
color_type* span = base_type::allocator().span();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*span++ = m_color;
|
||||||
|
}
|
||||||
|
while(--len);
|
||||||
|
return base_type::allocator().span();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
color_type m_color;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+339
@@ -0,0 +1,339 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Affine transformation classes.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_TRANS_AFFINE_INCLUDED
|
||||||
|
#define AGG_TRANS_AFFINE_INCLUDED
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "agg_basics.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
const double affine_epsilon = 1e-14; // About of precision of doubles
|
||||||
|
|
||||||
|
//============================================================trans_affine
|
||||||
|
//
|
||||||
|
// See Implementation agg_trans_affine.cpp
|
||||||
|
//
|
||||||
|
// Affine transformation are linear transformations in Cartesian coordinates
|
||||||
|
// (strictly speaking not only in Cartesian, but for the beginning we will
|
||||||
|
// think so). They are rotation, scaling, translation and skewing.
|
||||||
|
// After any affine transformation a line segment remains a line segment
|
||||||
|
// and it will never become a curve.
|
||||||
|
//
|
||||||
|
// There will be no math about matrix calculations, since it has been
|
||||||
|
// described many times. Ask yourself a very simple question:
|
||||||
|
// "why do we need to understand and use some matrix stuff instead of just
|
||||||
|
// rotating, scaling and so on". The answers are:
|
||||||
|
//
|
||||||
|
// 1. Any combination of transformations can be done by only 4 multiplications
|
||||||
|
// and 4 additions in floating point.
|
||||||
|
// 2. One matrix transformation is equivalent to the number of consecutive
|
||||||
|
// discrete transformations, i.e. the matrix "accumulates" all transformations
|
||||||
|
// in the order of their settings. Suppose we have 4 transformations:
|
||||||
|
// * rotate by 30 degrees,
|
||||||
|
// * scale X to 2.0,
|
||||||
|
// * scale Y to 1.5,
|
||||||
|
// * move to (100, 100).
|
||||||
|
// The result will depend on the order of these transformations,
|
||||||
|
// and the advantage of matrix is that the sequence of discret calls:
|
||||||
|
// rotate(30), scaleX(2.0), scaleY(1.5), move(100,100)
|
||||||
|
// will have exactly the same result as the following matrix transformations:
|
||||||
|
//
|
||||||
|
// affine_matrix m;
|
||||||
|
// m *= rotate_matrix(30);
|
||||||
|
// m *= scaleX_matrix(2.0);
|
||||||
|
// m *= scaleY_matrix(1.5);
|
||||||
|
// m *= move_matrix(100,100);
|
||||||
|
//
|
||||||
|
// m.transform_my_point_at_last(x, y);
|
||||||
|
//
|
||||||
|
// What is the good of it? In real life we will set-up the matrix only once
|
||||||
|
// and then transform many points, let alone the convenience to set any
|
||||||
|
// combination of transformations.
|
||||||
|
//
|
||||||
|
// So, how to use it? Very easy - literally as it's shown above. Not quite,
|
||||||
|
// let us write a correct example:
|
||||||
|
//
|
||||||
|
// agg::trans_affine m;
|
||||||
|
// m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0);
|
||||||
|
// m *= agg::trans_affine_scaling(2.0, 1.5);
|
||||||
|
// m *= agg::trans_affine_translation(100.0, 100.0);
|
||||||
|
// m.transform(&x, &y);
|
||||||
|
//
|
||||||
|
// The affine matrix is all you need to perform any linear transformation,
|
||||||
|
// but all transformations have origin point (0,0). It means that we need to
|
||||||
|
// use 2 translations if we want to rotate someting around (100,100):
|
||||||
|
//
|
||||||
|
// m *= agg::trans_affine_translation(-100.0, -100.0); // move to (0,0)
|
||||||
|
// m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate
|
||||||
|
// m *= agg::trans_affine_translation(100.0, 100.0); // move back to (100,100)
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
class trans_affine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//------------------------------------------ Construction
|
||||||
|
// Construct an identity matrix - it does not transform anything
|
||||||
|
trans_affine() :
|
||||||
|
m0(1.0), m1(0.0), m2(0.0), m3(1.0), m4(0.0), m5(0.0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Construct a custom matrix. Usually used in derived classes
|
||||||
|
trans_affine(double v0, double v1, double v2, double v3, double v4, double v5) :
|
||||||
|
m0(v0), m1(v1), m2(v2), m3(v3), m4(v4), m5(v5)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Construct a matrix to transform a parallelogram to another one.
|
||||||
|
trans_affine(const double* rect, const double* parl)
|
||||||
|
{
|
||||||
|
parl_to_parl(rect, parl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct a matrix to transform a rectangle to a parallelogram.
|
||||||
|
trans_affine(double x1, double y1, double x2, double y2,
|
||||||
|
const double* parl)
|
||||||
|
{
|
||||||
|
rect_to_parl(x1, y1, x2, y2, parl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct a matrix to transform a parallelogram to a rectangle.
|
||||||
|
trans_affine(const double* parl,
|
||||||
|
double x1, double y1, double x2, double y2)
|
||||||
|
{
|
||||||
|
parl_to_rect(parl, x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------- Parellelogram transformations
|
||||||
|
// Calculate a matrix to transform a parallelogram to another one.
|
||||||
|
// src and dst are pointers to arrays of three points
|
||||||
|
// (double[6], x,y,...) that identify three corners of the
|
||||||
|
// parallelograms assuming implicit fourth points.
|
||||||
|
// There are also transformations rectangtle to parallelogram and
|
||||||
|
// parellelogram to rectangle
|
||||||
|
const trans_affine& parl_to_parl(const double* src,
|
||||||
|
const double* dst);
|
||||||
|
|
||||||
|
const trans_affine& rect_to_parl(double x1, double y1,
|
||||||
|
double x2, double y2,
|
||||||
|
const double* parl);
|
||||||
|
|
||||||
|
const trans_affine& parl_to_rect(const double* parl,
|
||||||
|
double x1, double y1,
|
||||||
|
double x2, double y2);
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------ Operations
|
||||||
|
// Reset - actually load an identity matrix
|
||||||
|
const trans_affine& reset();
|
||||||
|
|
||||||
|
// Multiply matrix to another one
|
||||||
|
const trans_affine& multiply(const trans_affine& m);
|
||||||
|
|
||||||
|
// Multiply "m" to "this" and assign the result to "this"
|
||||||
|
const trans_affine& premultiply(const trans_affine& m);
|
||||||
|
|
||||||
|
// Invert matrix. Do not try to invert degenerate matrices,
|
||||||
|
// there's no check for validity. If you set scale to 0 and
|
||||||
|
// then try to invert matrix, expect unpredictable result.
|
||||||
|
const trans_affine& invert();
|
||||||
|
|
||||||
|
// Mirroring around X
|
||||||
|
const trans_affine& flip_x();
|
||||||
|
|
||||||
|
// Mirroring around Y
|
||||||
|
const trans_affine& flip_y();
|
||||||
|
|
||||||
|
//------------------------------------------- Load/Store
|
||||||
|
// Store matrix to an array [6] of double
|
||||||
|
void store_to(double* m) const
|
||||||
|
{
|
||||||
|
*m++ = m0; *m++ = m1; *m++ = m2; *m++ = m3; *m++ = m4; *m++ = m5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load matrix from an array [6] of double
|
||||||
|
const trans_affine& load_from(const double* m)
|
||||||
|
{
|
||||||
|
m0 = *m++; m1 = *m++; m2 = *m++; m3 = *m++; m4 = *m++; m5 = *m++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------- Operators
|
||||||
|
|
||||||
|
// Multiply current matrix to another one
|
||||||
|
const trans_affine& operator *= (const trans_affine& m)
|
||||||
|
{
|
||||||
|
return multiply(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiply current matrix to another one and return
|
||||||
|
// the result in a separete matrix.
|
||||||
|
trans_affine operator * (const trans_affine& m)
|
||||||
|
{
|
||||||
|
return trans_affine(*this).multiply(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate and return the inverse matrix
|
||||||
|
trans_affine operator ~ () const
|
||||||
|
{
|
||||||
|
trans_affine ret = *this;
|
||||||
|
return ret.invert();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal operator with default epsilon
|
||||||
|
bool operator == (const trans_affine& m) const
|
||||||
|
{
|
||||||
|
return is_equal(m, affine_epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not Equal operator with default epsilon
|
||||||
|
bool operator != (const trans_affine& m) const
|
||||||
|
{
|
||||||
|
return !is_equal(m, affine_epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------- Transformations
|
||||||
|
// Direct transformation x and y
|
||||||
|
void transform(double* x, double* y) const;
|
||||||
|
|
||||||
|
// Inverse transformation x and y. It works slower than the
|
||||||
|
// direct transformation, so if the performance is critical
|
||||||
|
// it's better to invert() the matrix and then use transform()
|
||||||
|
void inverse_transform(double* x, double* y) const;
|
||||||
|
|
||||||
|
//-------------------------------------------- Auxiliary
|
||||||
|
// Calculate the determinant of matrix
|
||||||
|
double determinant() const
|
||||||
|
{
|
||||||
|
return 1.0 / (m0 * m3 - m1 * m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the average scale (by X and Y).
|
||||||
|
// Basically used to calculate the approximation_scale when
|
||||||
|
// decomposinting curves into line segments.
|
||||||
|
double scale() const;
|
||||||
|
|
||||||
|
// Check to see if it's an identity matrix
|
||||||
|
bool is_identity(double epsilon = affine_epsilon) const;
|
||||||
|
|
||||||
|
// Check to see if two matrices are equal
|
||||||
|
bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const;
|
||||||
|
|
||||||
|
// Determine the major parameters. Use carefully considering degenerate matrices
|
||||||
|
double rotation() const;
|
||||||
|
void translation(double* dx, double* dy) const;
|
||||||
|
void scaling(double* sx, double* sy) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m0;
|
||||||
|
double m1;
|
||||||
|
double m2;
|
||||||
|
double m3;
|
||||||
|
double m4;
|
||||||
|
double m5;
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void trans_affine::transform(double* x, double* y) const
|
||||||
|
{
|
||||||
|
register double tx = *x;
|
||||||
|
*x = tx * m0 + *y * m2 + m4;
|
||||||
|
*y = tx * m1 + *y * m3 + m5;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline void trans_affine::inverse_transform(double* x, double* y) const
|
||||||
|
{
|
||||||
|
register double d = determinant();
|
||||||
|
register double a = (*x - m4) * d;
|
||||||
|
register double b = (*y - m5) * d;
|
||||||
|
*x = a * m3 - b * m2;
|
||||||
|
*y = b * m0 - a * m1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline double trans_affine::scale() const
|
||||||
|
{
|
||||||
|
double x = 0.707106781 * m0 + 0.707106781 * m2;
|
||||||
|
double y = 0.707106781 * m1 + 0.707106781 * m3;
|
||||||
|
return sqrt(x*x + y*y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
inline const trans_affine& trans_affine::premultiply(const trans_affine& m)
|
||||||
|
{
|
||||||
|
trans_affine t = m;
|
||||||
|
return *this = t.multiply(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//====================================================trans_affine_rotation
|
||||||
|
// Rotation matrix. sin() and cos() are calculated twice for the same angle.
|
||||||
|
// There's no harm because the performance of sin()/cos() is very good on all
|
||||||
|
// modern processors. Besides, this operation is not going to be invoked too
|
||||||
|
// often.
|
||||||
|
class trans_affine_rotation : public trans_affine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
trans_affine_rotation(double a) :
|
||||||
|
trans_affine(cos(a), sin(a), -sin(a), cos(a), 0.0, 0.0)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
//====================================================trans_affine_scaling
|
||||||
|
// Scaling matrix. sx, sy - scale coefficients by X and Y respectively
|
||||||
|
class trans_affine_scaling : public trans_affine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
trans_affine_scaling(double sx, double sy) :
|
||||||
|
trans_affine(sx, 0.0, 0.0, sy, 0.0, 0.0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
trans_affine_scaling(double s) :
|
||||||
|
trans_affine(s, 0.0, 0.0, s, 0.0, 0.0)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
//================================================trans_affine_translation
|
||||||
|
// Translation matrix
|
||||||
|
class trans_affine_translation : public trans_affine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
trans_affine_translation(double tx, double ty) :
|
||||||
|
trans_affine(1.0, 0.0, 0.0, 1.0, tx, ty)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
//====================================================trans_affine_skewing
|
||||||
|
// Sckewing (shear) matrix
|
||||||
|
class trans_affine_skewing : public trans_affine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
trans_affine_skewing(double sx, double sy) :
|
||||||
|
trans_affine(1.0, tan(sy), tan(sx), 1.0, 0.0, 0.0)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.2
|
||||||
|
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Bilinear 2D transformations
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
#ifndef AGG_TRANS_BILINEAR_INCLUDED
|
||||||
|
#define AGG_TRANS_BILINEAR_INCLUDED
|
||||||
|
|
||||||
|
#include "agg_basics.h"
|
||||||
|
#include "agg_simul_eq.h"
|
||||||
|
|
||||||
|
namespace agg
|
||||||
|
{
|
||||||
|
|
||||||
|
//==========================================================trans_bilinear
|
||||||
|
class trans_bilinear
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
trans_bilinear() : m_valid(false) {}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Arbitrary quadrangle transformations
|
||||||
|
trans_bilinear(const double* src, const double* dst)
|
||||||
|
{
|
||||||
|
quad_to_quad(src, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Direct transformations
|
||||||
|
trans_bilinear(double x1, double y1, double x2, double y2,
|
||||||
|
const double* quad)
|
||||||
|
{
|
||||||
|
rect_to_quad(x1, y1, x2, y2, quad);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Reverse transformations
|
||||||
|
trans_bilinear(const double* quad,
|
||||||
|
double x1, double y1, double x2, double y2)
|
||||||
|
{
|
||||||
|
quad_to_rect(quad, x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Set the transformations using two arbitrary quadrangles.
|
||||||
|
void quad_to_quad(const double* src, const double* dst)
|
||||||
|
{
|
||||||
|
double left[4][4];
|
||||||
|
double right[4][2];
|
||||||
|
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
unsigned ix = i * 2;
|
||||||
|
unsigned iy = ix + 1;
|
||||||
|
left[i][0] = 1.0;
|
||||||
|
left[i][1] = src[ix] * src[iy];
|
||||||
|
left[i][2] = src[ix];
|
||||||
|
left[i][3] = src[iy];
|
||||||
|
|
||||||
|
right[i][0] = dst[ix];
|
||||||
|
right[i][1] = dst[iy];
|
||||||
|
}
|
||||||
|
m_valid = simul_eq<4, 2>::solve(left, right, m_mtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Set the direct transformations, i.e., rectangle -> quadrangle
|
||||||
|
void rect_to_quad(double x1, double y1, double x2, double y2,
|
||||||
|
const double* quad)
|
||||||
|
{
|
||||||
|
double src[8];
|
||||||
|
src[0] = src[6] = x1;
|
||||||
|
src[2] = src[4] = x2;
|
||||||
|
src[1] = src[3] = y1;
|
||||||
|
src[5] = src[7] = y2;
|
||||||
|
quad_to_quad(src, quad);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Set the reverse transformations, i.e., quadrangle -> rectangle
|
||||||
|
void quad_to_rect(const double* quad,
|
||||||
|
double x1, double y1, double x2, double y2)
|
||||||
|
{
|
||||||
|
double dst[8];
|
||||||
|
dst[0] = dst[6] = x1;
|
||||||
|
dst[2] = dst[4] = x2;
|
||||||
|
dst[1] = dst[3] = y1;
|
||||||
|
dst[5] = dst[7] = y2;
|
||||||
|
quad_to_quad(quad, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Check if the equations were solved successfully
|
||||||
|
bool is_valid() const { return m_valid; }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Transform a point (x, y)
|
||||||
|
void transform(double* x, double* y) const
|
||||||
|
{
|
||||||
|
double tx = *x;
|
||||||
|
double ty = *y;
|
||||||
|
double xy = tx * ty;
|
||||||
|
*x = m_mtx[0][0] + m_mtx[1][0] * xy + m_mtx[2][0] * tx + m_mtx[3][0] * ty;
|
||||||
|
*y = m_mtx[0][1] + m_mtx[1][1] * xy + m_mtx[2][1] * tx + m_mtx[3][1] * ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_mtx[4][2];
|
||||||
|
bool m_valid;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user