Sync to AGG tree to support stippi's Painter classes
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10693 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#ifndef AGG_ARRAY_INCLUDED
|
||||
#define AGG_ARRAY_INCLUDED
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
|
||||
@@ -45,7 +46,10 @@ namespace agg
|
||||
|
||||
void add(const T& v) { m_array[m_size++] = v; }
|
||||
void inc_size(unsigned size) { m_size += size; }
|
||||
unsigned size() const { return m_size; }
|
||||
unsigned size() const { return m_size; }
|
||||
unsigned byte_size() const { return m_size * sizeof(T); }
|
||||
void serialize(int8u* ptr) const;
|
||||
void deserialize(const int8u* data, unsigned byte_size);
|
||||
const T& operator [] (unsigned idx) const { return m_array[idx]; }
|
||||
T& operator [] (unsigned idx) { return m_array[idx]; }
|
||||
|
||||
@@ -116,9 +120,20 @@ namespace agg
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T> void pod_array<T>::serialize(int8u* ptr) const
|
||||
{
|
||||
if(m_size) memcpy(ptr, m_array, m_size * sizeof(T));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T>
|
||||
void pod_array<T>::deserialize(const int8u* data, unsigned byte_size)
|
||||
{
|
||||
byte_size /= sizeof(T);
|
||||
capacity(byte_size);
|
||||
if(byte_size) memcpy(m_array, data, byte_size * sizeof(T));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T> class pod_array_adaptor
|
||||
@@ -154,6 +169,7 @@ namespace agg
|
||||
//------------------------------------------------------------------------
|
||||
template<class T, unsigned S=6> class pod_deque
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
block_shift = S,
|
||||
@@ -161,7 +177,6 @@ namespace agg
|
||||
block_mask = block_size - 1
|
||||
};
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
~pod_deque();
|
||||
@@ -181,6 +196,23 @@ namespace agg
|
||||
|
||||
int allocate_continuous_block(unsigned num_elements);
|
||||
|
||||
void add_array(const T* ptr, unsigned num_elem)
|
||||
{
|
||||
while(num_elem--)
|
||||
{
|
||||
add(*ptr++);
|
||||
}
|
||||
}
|
||||
|
||||
template<class DataAccessor> void add_data(DataAccessor& data)
|
||||
{
|
||||
while(data.size())
|
||||
{
|
||||
add(*data);
|
||||
++data;
|
||||
}
|
||||
}
|
||||
|
||||
void cut_at(unsigned size)
|
||||
{
|
||||
if(size < m_size) m_size = size;
|
||||
@@ -240,6 +272,58 @@ namespace agg
|
||||
|
||||
unsigned byte_size() const;
|
||||
void serialize(int8u* ptr) const;
|
||||
void deserialize(const int8u* data, unsigned byte_size);
|
||||
void deserialize(unsigned start, const T& empty_val,
|
||||
const int8u* data, unsigned byte_size);
|
||||
|
||||
template<class ByteAccessor>
|
||||
void deserialize(ByteAccessor data)
|
||||
{
|
||||
remove_all();
|
||||
unsigned elem_size = data.size() / sizeof(T);
|
||||
|
||||
for(unsigned i = 0; i < elem_size; ++i)
|
||||
{
|
||||
int8u* ptr = (int8u*)data_ptr();
|
||||
for(unsigned j = 0; j < sizeof(T); ++j)
|
||||
{
|
||||
*ptr++ = *data;
|
||||
++data;
|
||||
}
|
||||
++m_size;
|
||||
}
|
||||
}
|
||||
|
||||
template<class ByteAccessor>
|
||||
void deserialize(unsigned start, const T& empty_val, ByteAccessor data)
|
||||
{
|
||||
while(m_size < start)
|
||||
{
|
||||
add(empty_val);
|
||||
}
|
||||
|
||||
unsigned elem_size = data.size() / sizeof(T);
|
||||
for(unsigned i = 0; i < elem_size; ++i)
|
||||
{
|
||||
int8u* ptr;
|
||||
if(start + i < m_size)
|
||||
{
|
||||
ptr = (int8u*)(&((*this)[start + i]));
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = (int8u*)data_ptr();
|
||||
++m_size;
|
||||
}
|
||||
for(unsigned j = 0; j < sizeof(T); ++j)
|
||||
{
|
||||
*ptr++ = *data;
|
||||
++data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const T* block(unsigned nb) const { return m_blocks[nb]; }
|
||||
|
||||
private:
|
||||
void allocate_block(unsigned nb);
|
||||
@@ -253,8 +337,6 @@ namespace agg
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T, unsigned S> pod_deque<T, S>::~pod_deque()
|
||||
{
|
||||
@@ -461,8 +543,49 @@ namespace agg
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T, unsigned S>
|
||||
void pod_deque<T, S>::deserialize(const int8u* data, unsigned byte_size)
|
||||
{
|
||||
remove_all();
|
||||
byte_size /= sizeof(T);
|
||||
for(unsigned i = 0; i < byte_size; ++i)
|
||||
{
|
||||
T* ptr = data_ptr();
|
||||
memcpy(ptr, data, sizeof(T));
|
||||
++m_size;
|
||||
data += sizeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Replace or add a number of elements starting from "start" position
|
||||
//------------------------------------------------------------------------
|
||||
template<class T, unsigned S>
|
||||
void pod_deque<T, S>::deserialize(unsigned start, const T& empty_val,
|
||||
const int8u* data, unsigned byte_size)
|
||||
{
|
||||
while(m_size < start)
|
||||
{
|
||||
add(empty_val);
|
||||
}
|
||||
|
||||
byte_size /= sizeof(T);
|
||||
for(unsigned i = 0; i < byte_size; ++i)
|
||||
{
|
||||
if(start + i < m_size)
|
||||
{
|
||||
memcpy(&((*this)[start + i]), data, sizeof(T));
|
||||
}
|
||||
else
|
||||
{
|
||||
T* ptr = data_ptr();
|
||||
memcpy(ptr, data, sizeof(T));
|
||||
++m_size;
|
||||
}
|
||||
data += sizeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------pod_allocator
|
||||
@@ -520,7 +643,7 @@ namespace agg
|
||||
int8u* ptr = m_buf_ptr;
|
||||
if(alignment > 1)
|
||||
{
|
||||
unsigned align = (alignment - unsigned(ptr) % alignment) % alignment;
|
||||
unsigned align = (alignment - unsigned((size_t)ptr) % alignment) % alignment;
|
||||
size += align;
|
||||
ptr += align;
|
||||
if(size <= m_rest)
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace agg
|
||||
class bezier_arc
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
bezier_arc() : m_vertex(26) {}
|
||||
bezier_arc(double x, double y,
|
||||
double rx, double ry,
|
||||
@@ -48,6 +49,7 @@ namespace agg
|
||||
init(x, y, rx, ry, start_angle, sweep_angle);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(double x, double y,
|
||||
double rx, double ry,
|
||||
double start_angle,
|
||||
|
||||
@@ -35,6 +35,11 @@ namespace agg
|
||||
double y;
|
||||
bool first = true;
|
||||
|
||||
*x1 = CoordT(1);
|
||||
*y1 = CoordT(1);
|
||||
*x2 = CoordT(0);
|
||||
*y2 = CoordT(0);
|
||||
|
||||
for(i = 0; i < num; i++)
|
||||
{
|
||||
vs.rewind(gi[start + i]);
|
||||
@@ -74,6 +79,11 @@ namespace agg
|
||||
double y;
|
||||
bool first = true;
|
||||
|
||||
*x1 = CoordT(1);
|
||||
*y1 = CoordT(1);
|
||||
*x2 = CoordT(0);
|
||||
*y2 = CoordT(0);
|
||||
|
||||
vs.rewind(path_id);
|
||||
unsigned cmd;
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
|
||||
@@ -24,6 +24,35 @@
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//----------------------------------------------------------clipping_flags
|
||||
// Determine the clipping code of the vertex according to the
|
||||
// Cyrus-Beck line clipping algorithm
|
||||
//
|
||||
// | |
|
||||
// 0110 | 0010 | 0011
|
||||
// | |
|
||||
// -------+--------+-------- clip_box.y2
|
||||
// | |
|
||||
// 0100 | 0000 | 0001
|
||||
// | |
|
||||
// -------+--------+-------- clip_box.y1
|
||||
// | |
|
||||
// 1100 | 1000 | 1001
|
||||
// | |
|
||||
// clip_box.x1 clip_box.x2
|
||||
//
|
||||
//
|
||||
template<class T>
|
||||
inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box)
|
||||
{
|
||||
return (x > clip_box.x2) |
|
||||
((y > clip_box.y2) << 1) |
|
||||
((x < clip_box.x1) << 2) |
|
||||
((y < clip_box.y1) << 3);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------clip_liang_barsky
|
||||
template<class T>
|
||||
inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2,
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace agg
|
||||
//====================================================================rgba
|
||||
struct rgba
|
||||
{
|
||||
typedef double alpha_type;
|
||||
enum premul { pre };
|
||||
|
||||
double r;
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace agg
|
||||
//==================================================================rgba8
|
||||
struct rgba8
|
||||
{
|
||||
typedef int8u alpha_type;
|
||||
enum order { rgb, bgr };
|
||||
enum premul { pre };
|
||||
|
||||
@@ -230,7 +231,7 @@ namespace agg
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, unsigned a=1.0)
|
||||
inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, unsigned a=255)
|
||||
{
|
||||
return rgba8(rgba8::pre, r, g, b, a);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace agg
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
unsigned m_poly_flags;
|
||||
int m_vertices;
|
||||
};
|
||||
|
||||
|
||||
@@ -64,6 +65,7 @@ namespace agg
|
||||
m_start_x = 0;
|
||||
m_start_y = 0;
|
||||
m_poly_flags = 0;
|
||||
m_vertices = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,26 +79,51 @@ namespace agg
|
||||
cmd = m_vpgen.vertex(x, y);
|
||||
if(!is_stop(cmd)) break;
|
||||
|
||||
if(m_poly_flags)
|
||||
if(m_poly_flags && !m_vpgen.auto_unclose())
|
||||
{
|
||||
*x = 0.0;
|
||||
*y = 0.0;
|
||||
cmd = m_poly_flags;
|
||||
m_poly_flags = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_vertices < 0)
|
||||
{
|
||||
if(m_vertices < -1)
|
||||
{
|
||||
m_vertices = 0;
|
||||
return path_cmd_stop;
|
||||
}
|
||||
m_vpgen.move_to(m_start_x, m_start_y);
|
||||
m_vertices = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
double tx, ty;
|
||||
cmd = m_source->vertex(&tx, &ty);
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
if(m_vpgen.auto_close() && m_vertices > 2)
|
||||
{
|
||||
m_vpgen.line_to(m_start_x, m_start_y);
|
||||
m_poly_flags = path_cmd_end_poly | path_flags_close;
|
||||
m_start_x = tx;
|
||||
m_start_y = ty;
|
||||
m_vertices = -1;
|
||||
continue;
|
||||
}
|
||||
m_vpgen.move_to(tx, ty);
|
||||
m_start_x = tx;
|
||||
m_start_y = ty;
|
||||
m_start_x = tx;
|
||||
m_start_y = ty;
|
||||
m_vertices = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vpgen.line_to(tx, ty);
|
||||
++m_vertices;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -104,14 +131,26 @@ namespace agg
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
m_poly_flags = cmd;
|
||||
if(is_closed(cmd))
|
||||
if(is_closed(cmd) || m_vpgen.auto_close())
|
||||
{
|
||||
m_vpgen.line_to(m_start_x, m_start_y);
|
||||
if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close;
|
||||
if(m_vertices > 2)
|
||||
{
|
||||
m_vpgen.line_to(m_start_x, m_start_y);
|
||||
}
|
||||
m_vertices = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The adaptor should be transparent to all unknown commands
|
||||
// path_cmd_stop
|
||||
if(m_vpgen.auto_close() && m_vertices > 2)
|
||||
{
|
||||
m_vpgen.line_to(m_start_x, m_start_y);
|
||||
m_poly_flags = path_cmd_end_poly | path_flags_close;
|
||||
m_vertices = -2;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// polyline 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 polyline 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_polyline_INCLUDED
|
||||
#define AGG_CONV_CLIP_polyline_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_adaptor_vpgen.h"
|
||||
#include "agg_vpgen_clip_polyline.h"
|
||||
#include "agg_vertex_iterator.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================conv_clip_polyline
|
||||
template<class VertexSource>
|
||||
struct conv_clip_polyline : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>
|
||||
{
|
||||
typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> base_type;
|
||||
|
||||
conv_clip_polyline(VertexSource& vs) :
|
||||
conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(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_polyline<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_polyline(const conv_clip_polyline<VertexSource>&);
|
||||
const conv_clip_polyline<VertexSource>&
|
||||
operator = (const conv_clip_polyline<VertexSource>&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -37,13 +37,21 @@ namespace agg
|
||||
{
|
||||
}
|
||||
|
||||
void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
|
||||
void inner_line_join(line_join_e lj) { base_type::generator().inner_line_join(lj); }
|
||||
void width(double w) { base_type::generator().width(w); }
|
||||
void miter_limit(double ml) { base_type::generator().miter_limit(ml); }
|
||||
void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); }
|
||||
void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
|
||||
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
|
||||
void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); }
|
||||
|
||||
line_join_e line_join() const { return base_type::generator().line_join(); }
|
||||
line_join_e inner_line_join() const { return base_type::generator().inner_line_join(); }
|
||||
double width() const { return base_type::generator().width(); }
|
||||
double miter_limit() const { return base_type::generator().miter_limit(); }
|
||||
double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
|
||||
double approximation_scale() const { return base_type::generator().approximation_scale(); }
|
||||
bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); }
|
||||
|
||||
private:
|
||||
|
||||
@@ -39,19 +39,23 @@ namespace agg
|
||||
{
|
||||
}
|
||||
|
||||
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); }
|
||||
void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); }
|
||||
void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
|
||||
void inner_line_join(line_join_e lj) { base_type::generator().inner_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(); }
|
||||
line_cap_e line_cap() const { return base_type::generator().line_cap(); }
|
||||
line_join_e line_join() const { return base_type::generator().line_join(); }
|
||||
line_join_e inner_line_join() const { return base_type::generator().inner_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 inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); }
|
||||
void approximation_scale(double as) { base_type::generator().approximation_scale(as); }
|
||||
|
||||
double width() const { return base_type::generator().width(); }
|
||||
double miter_limit() const { return base_type::generator().miter_limit(); }
|
||||
double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); }
|
||||
double approximation_scale() const { return base_type::generator().approximation_scale(); }
|
||||
|
||||
void shorten(double s) { base_type::generator().shorten(s); }
|
||||
|
||||
@@ -299,12 +299,15 @@ namespace agg
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init_embedded_adaptors(const glyph_cache* gl, double x, double y)
|
||||
void init_embedded_adaptors(const glyph_cache* gl,
|
||||
double x, double y,
|
||||
double scale=1.0)
|
||||
{
|
||||
if(gl)
|
||||
{
|
||||
switch(gl->data_type)
|
||||
{
|
||||
default: return;
|
||||
case glyph_data_mono:
|
||||
m_mono_adaptor.init(gl->data, gl->data_size, x, y);
|
||||
break;
|
||||
@@ -314,7 +317,7 @@ namespace agg
|
||||
break;
|
||||
|
||||
case glyph_data_outline:
|
||||
m_path_adaptor.init(gl->data, gl->data_size, x, y);
|
||||
m_path_adaptor.init(gl->data, gl->data_size, x, y, scale);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace agg
|
||||
//===================================================================gray8
|
||||
struct gray8
|
||||
{
|
||||
typedef int8u alpha_type;
|
||||
int8u v;
|
||||
int8u a;
|
||||
|
||||
|
||||
@@ -132,8 +132,8 @@ namespace agg
|
||||
void rewind(unsigned id)
|
||||
{
|
||||
m_trans.rewind(id);
|
||||
m_polyline.line_join(vcgen_stroke::round_join);
|
||||
m_polyline.line_cap(vcgen_stroke::round_cap);
|
||||
m_polyline.line_join(round_join);
|
||||
m_polyline.line_cap(round_cap);
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Stroke math
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_STROKE_MATH_INCLUDED
|
||||
#define AGG_STROKE_MATH_INCLUDED
|
||||
|
||||
#include "agg_math.h"
|
||||
#include "agg_vertex_sequence.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//-------------------------------------------------------------line_cap_e
|
||||
enum line_cap_e
|
||||
{
|
||||
butt_cap,
|
||||
square_cap,
|
||||
round_cap
|
||||
};
|
||||
|
||||
//------------------------------------------------------------line_join_e
|
||||
enum line_join_e
|
||||
{
|
||||
miter_join,
|
||||
miter_join_revert,
|
||||
round_join,
|
||||
bevel_join
|
||||
};
|
||||
|
||||
// Minimal angle to calculate round joins, less than 0.1 degree.
|
||||
const double stroke_theta = 0.001; //----stroke_theta
|
||||
|
||||
|
||||
//--------------------------------------------------------stroke_calc_arc
|
||||
template<class VertexConsumer>
|
||||
void stroke_calc_arc(VertexConsumer& out_vertices,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double width,
|
||||
double approximation_scale)
|
||||
{
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
|
||||
// Check if we actually need the arc
|
||||
//-----------------
|
||||
double dd = calc_distance(dx1, dy1, dx2, dy2);
|
||||
if(dd < approximation_scale)
|
||||
{
|
||||
out_vertices.add(coord_type(x + dx1, y + dy1));
|
||||
if(dd > approximation_scale * 0.25)
|
||||
{
|
||||
out_vertices.add(coord_type(x + dx2, y + dy2));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
double a1 = atan2(dy1, dx1);
|
||||
double a2 = atan2(dy2, dx2);
|
||||
double da = a1 - a2;
|
||||
|
||||
//if(fabs(da) < stroke_theta)
|
||||
//{
|
||||
// out_vertices.add(coord_type(x + dx1, y + dy1));
|
||||
// //out_vertices.add(coord_type(x + dx2, y + dy2));
|
||||
// return;
|
||||
//}
|
||||
|
||||
bool ccw = da > 0.0 && da < pi;
|
||||
|
||||
if(width < 0) width = -width;
|
||||
da = fabs(1.0 / (width * approximation_scale));
|
||||
if(!ccw)
|
||||
{
|
||||
if(a1 > a2) a2 += 2 * pi;
|
||||
while(a1 < a2)
|
||||
{
|
||||
out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width));
|
||||
a1 += da;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(a1 < a2) a2 -= 2 * pi;
|
||||
while(a1 > a2)
|
||||
{
|
||||
out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width));
|
||||
a1 -= da;
|
||||
}
|
||||
}
|
||||
out_vertices.add(coord_type(x + dx2, y + dy2));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------stroke_calc_miter
|
||||
template<class VertexConsumer>
|
||||
void stroke_calc_miter(VertexConsumer& out_vertices,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double width,
|
||||
bool revert_flag,
|
||||
double miter_limit)
|
||||
{
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
|
||||
double xi = v1.x;
|
||||
double yi = v1.y;
|
||||
|
||||
if(!calc_intersection(v0.x + dx1, v0.y - dy1,
|
||||
v1.x + dx1, v1.y - dy1,
|
||||
v1.x + dx2, v1.y - dy2,
|
||||
v2.x + dx2, v2.y - dy2,
|
||||
&xi, &yi))
|
||||
{
|
||||
// The calculation didn't succeed, most probaly
|
||||
// the three points lie one straight line
|
||||
//----------------
|
||||
if(calc_distance(dx1, -dy1, dx2, -dy2) < width * 0.025)
|
||||
{
|
||||
// This case means that the next segment continues
|
||||
// the previous one (straight line)
|
||||
//-----------------
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
}
|
||||
else
|
||||
{
|
||||
// This case means that the next segment goes back
|
||||
//-----------------
|
||||
if(revert_flag)
|
||||
{
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no miter-revert, calcuate new dx1, dy1, dx2, dy2
|
||||
out_vertices.add(coord_type(v1.x + dx1 + dy1 * miter_limit,
|
||||
v1.y - dy1 + dx1 * miter_limit));
|
||||
out_vertices.add(coord_type(v1.x + dx2 - dy2 * miter_limit,
|
||||
v1.y - dy2 - dx2 * miter_limit));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double d1 = calc_distance(v1.x, v1.y, xi, yi);
|
||||
double lim = width * miter_limit;
|
||||
if(d1 > lim)
|
||||
{
|
||||
// Miter limit exceeded
|
||||
//------------------------
|
||||
if(revert_flag)
|
||||
{
|
||||
// For the compatibility with SVG, PDF, etc,
|
||||
// we use a simple bevel join instead of
|
||||
// "smart" bevel
|
||||
//-------------------
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Smart bevel that cuts the miter at the limit point
|
||||
//-------------------
|
||||
d1 = lim / d1;
|
||||
double x1 = v1.x + dx1;
|
||||
double y1 = v1.y - dy1;
|
||||
double x2 = v1.x + dx2;
|
||||
double y2 = v1.y - dy2;
|
||||
|
||||
x1 += (xi - x1) * d1;
|
||||
y1 += (yi - y1) * d1;
|
||||
x2 += (xi - x2) * d1;
|
||||
y2 += (yi - y2) * d1;
|
||||
out_vertices.add(coord_type(x1, y1));
|
||||
out_vertices.add(coord_type(x2, y2));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inside the miter limit
|
||||
//---------------------
|
||||
out_vertices.add(coord_type(xi, yi));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------stroke_calc_cap
|
||||
template<class VertexConsumer>
|
||||
void stroke_calc_cap(VertexConsumer& out_vertices,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
double len,
|
||||
line_cap_e line_cap,
|
||||
double width,
|
||||
double approximation_scale)
|
||||
{
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
|
||||
out_vertices.remove_all();
|
||||
|
||||
double dx1 = width * (v1.y - v0.y) / len;
|
||||
double dy1 = width * (v1.x - v0.x) / len;
|
||||
double dx2 = 0;
|
||||
double dy2 = 0;
|
||||
|
||||
if(line_cap == square_cap)
|
||||
{
|
||||
dx2 = dy1;
|
||||
dy2 = dx1;
|
||||
}
|
||||
|
||||
if(line_cap == round_cap)
|
||||
{
|
||||
double a1 = atan2(dy1, -dx1);
|
||||
double a2 = a1 + pi;
|
||||
double da = fabs(1.0 / (width * approximation_scale));
|
||||
while(a1 < a2)
|
||||
{
|
||||
out_vertices.add(coord_type(v0.x + cos(a1) * width,
|
||||
v0.y + sin(a1) * width));
|
||||
a1 += da;
|
||||
}
|
||||
out_vertices.add(coord_type(v0.x + dx1, v0.y - dy1));
|
||||
}
|
||||
else
|
||||
{
|
||||
out_vertices.add(coord_type(v0.x - dx1 - dx2, v0.y + dy1 - dy2));
|
||||
out_vertices.add(coord_type(v0.x + dx1 - dx2, v0.y - dy1 - dy2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------stroke_calc_join
|
||||
template<class VertexConsumer>
|
||||
void stroke_calc_join(VertexConsumer& out_vertices,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double len1,
|
||||
double len2,
|
||||
double width,
|
||||
line_join_e line_join,
|
||||
line_join_e inner_line_join,
|
||||
double miter_limit,
|
||||
double inner_miter_limit,
|
||||
double approximation_scale)
|
||||
{
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
|
||||
double dx1, dy1, dx2, dy2;
|
||||
|
||||
dx1 = width * (v1.y - v0.y) / len1;
|
||||
dy1 = width * (v1.x - v0.x) / len1;
|
||||
|
||||
dx2 = width * (v2.y - v1.y) / len2;
|
||||
dy2 = width * (v2.x - v1.x) / len2;
|
||||
|
||||
out_vertices.remove_all();
|
||||
|
||||
if(calc_point_location(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y) > 0.0)
|
||||
{
|
||||
// Inner join
|
||||
//---------------
|
||||
stroke_calc_miter(out_vertices,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
width,
|
||||
inner_line_join == miter_join_revert,
|
||||
inner_miter_limit);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Outer join
|
||||
//---------------
|
||||
switch(line_join)
|
||||
{
|
||||
case miter_join:
|
||||
stroke_calc_miter(out_vertices,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
width,
|
||||
false,
|
||||
miter_limit);
|
||||
break;
|
||||
|
||||
case miter_join_revert:
|
||||
stroke_calc_miter(out_vertices,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
width,
|
||||
true,
|
||||
miter_limit);
|
||||
break;
|
||||
|
||||
case round_join:
|
||||
stroke_calc_arc(out_vertices,
|
||||
v1.x, v1.y, dx1, -dy1, dx2, -dy2,
|
||||
width, approximation_scale);
|
||||
break;
|
||||
|
||||
default: // Bevel join
|
||||
out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1));
|
||||
if(calc_distance(dx1, dy1, dx2, dy2) > approximation_scale * 0.25)
|
||||
{
|
||||
out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -166,11 +166,6 @@ namespace agg
|
||||
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,
|
||||
|
||||
@@ -45,10 +45,12 @@ namespace agg
|
||||
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
|
||||
unsigned vertex(double* x_, double* y_,
|
||||
double dx=0, double dy=0,
|
||||
double scale=1.0) const
|
||||
{
|
||||
*x_ = dx + (double(x >> 1) / coord_mult);
|
||||
*y_ = dy + (double(y >> 1) / coord_mult);
|
||||
*x_ = dx + (double(x >> 1) / coord_mult) * scale;
|
||||
*y_ = dy + (double(y >> 1) / coord_mult) * scale;
|
||||
switch(((y & 1) << 1) | (x & 1))
|
||||
{
|
||||
case cmd_move_to: return path_cmd_move_to;
|
||||
@@ -171,7 +173,7 @@ namespace agg
|
||||
rect_d bounds(1e100, 1e100, -1e100, -1e100);
|
||||
if(m_storage.size() == 0)
|
||||
{
|
||||
bounds.x1 = bounds.x1 = bounds.x2 = bounds.y2 = 0.0;
|
||||
bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -212,7 +214,8 @@ namespace agg
|
||||
m_ptr(0),
|
||||
m_dx(0.0),
|
||||
m_dy(0.0),
|
||||
m_closed(true)
|
||||
m_scale(1.0),
|
||||
m_vertices(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
@@ -223,26 +226,28 @@ namespace agg
|
||||
m_ptr(data),
|
||||
m_dx(dx),
|
||||
m_dy(dy),
|
||||
m_closed(true)
|
||||
m_vertices(0)
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(const int8u* data, unsigned size, double dx, double dy)
|
||||
void init(const int8u* data, unsigned size,
|
||||
double dx, double dy, double scale=1.0)
|
||||
{
|
||||
m_data = data;
|
||||
m_end = data + size;
|
||||
m_ptr = data;
|
||||
m_dx = dx;
|
||||
m_dy = dy;
|
||||
m_closed = true;
|
||||
m_data = data;
|
||||
m_end = data + size;
|
||||
m_ptr = data;
|
||||
m_dx = dx;
|
||||
m_dy = dy;
|
||||
m_scale = scale;
|
||||
m_vertices = 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_ptr = m_data;
|
||||
m_closed = true;
|
||||
m_ptr = m_data;
|
||||
m_vertices = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
@@ -254,6 +259,7 @@ namespace agg
|
||||
*y = 0;
|
||||
return path_cmd_stop;
|
||||
}
|
||||
|
||||
if(m_ptr == m_end)
|
||||
{
|
||||
*x = 0;
|
||||
@@ -264,15 +270,15 @@ namespace agg
|
||||
|
||||
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)
|
||||
unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale);
|
||||
if(is_move_to(cmd) && m_vertices > 2)
|
||||
{
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
m_closed = true;
|
||||
m_vertices = 0;
|
||||
return path_cmd_end_poly | path_flags_close;
|
||||
}
|
||||
m_closed = false;
|
||||
++m_vertices;
|
||||
m_ptr += sizeof(vertex_integer_type);
|
||||
return cmd;
|
||||
}
|
||||
@@ -283,7 +289,8 @@ namespace agg
|
||||
const int8u* m_ptr;
|
||||
double m_dx;
|
||||
double m_dy;
|
||||
bool m_closed;
|
||||
double m_scale;
|
||||
unsigned m_vertices;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,429 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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_CRB_RGBA32_INCLUDED
|
||||
#define AGG_PIXFMT_CRB_RGBA32_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_rgba8.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//================================================pixel_formats_crb_rgba32
|
||||
template<class RenBuf, class Order> class pixel_formats_crb_rgba32
|
||||
{
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
typedef RenBuf buffer_type;
|
||||
typedef Order order_type;
|
||||
|
||||
typedef typename RenBuf::row_data row_data;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
pixel_formats_crb_rgba32(RenBuf& 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) const
|
||||
{
|
||||
const int8u* p = m_rbuf->span_ptr(x, y, 1);
|
||||
return p ? color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]) :
|
||||
color_type::no_color();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
return m_rbuf->span(x, y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
int8u* p = m_rbuf->span_ptr(x, y, 1);
|
||||
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->span_ptr(x, y, 1);
|
||||
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->span_ptr(x, y, len));
|
||||
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;
|
||||
do
|
||||
{
|
||||
*(int32u*)(m_rbuf->span_ptr(x, y, 1)) = v;
|
||||
++y;
|
||||
}
|
||||
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->span_ptr(x, y, len));
|
||||
do
|
||||
{
|
||||
*p32++ = v;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
int8u* p = m_rbuf->span_ptr(x, y, len);
|
||||
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)
|
||||
{
|
||||
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*)(m_rbuf->span_ptr(x, y, 1)) = v;
|
||||
++y;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
int8u* p = m_rbuf->span_ptr(x, y, 1);
|
||||
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);
|
||||
++y;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf2> void copy_from(const RenBuf2& from,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
const int8u* p = from.row(ysrc);
|
||||
if(p)
|
||||
{
|
||||
p += xsrc << 2;
|
||||
memmove(m_rbuf->span_ptr(xdst, ydst, len), p, len * 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from(const SrcPixelFormatRenderer& from,
|
||||
const int8u* psrc,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::order_type src_order;
|
||||
int8u* pdst = m_rbuf->span_ptr(xdst, ydst, len);
|
||||
int incp = 4;
|
||||
if(xdst > xsrc)
|
||||
{
|
||||
psrc += (len-1) << 2;
|
||||
pdst += (len-1) << 2;
|
||||
incp = -4;
|
||||
}
|
||||
do
|
||||
{
|
||||
int alpha = psrc[src_order::A];
|
||||
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255)
|
||||
{
|
||||
pdst[Order::R] = psrc[src_order::R];
|
||||
pdst[Order::G] = psrc[src_order::G];
|
||||
pdst[Order::B] = psrc[src_order::B];
|
||||
pdst[Order::A] = psrc[src_order::A];
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = pdst[Order::R];
|
||||
int g = pdst[Order::G];
|
||||
int b = pdst[Order::B];
|
||||
int a = pdst[Order::A];
|
||||
pdst[Order::R] = (int8u)((((psrc[src_order::R] - r) * alpha) + (r << 8)) >> 8);
|
||||
pdst[Order::G] = (int8u)((((psrc[src_order::G] - g) * alpha) + (g << 8)) >> 8);
|
||||
pdst[Order::B] = (int8u)((((psrc[src_order::B] - b) * alpha) + (b << 8)) >> 8);
|
||||
pdst[Order::A] = (int8u)((alpha + a) - ((alpha * a) >> 8));
|
||||
}
|
||||
}
|
||||
psrc += incp;
|
||||
pdst += incp;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
int8u* p = m_rbuf->span_ptr(x, y, len);
|
||||
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)
|
||||
{
|
||||
do
|
||||
{
|
||||
int8u* p = m_rbuf->span_ptr(x, y, 1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
++y;
|
||||
}
|
||||
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->span_ptr(x, y, len);
|
||||
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)
|
||||
{
|
||||
do
|
||||
{
|
||||
int8u* p = m_rbuf->span_ptr(x, y, 1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
++y;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
private:
|
||||
RenBuf* m_rbuf;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,345 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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_CRB_RGBA32_PRE_INCLUDED
|
||||
#define AGG_PIXFMT_CRB_RGBA32_PRE_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_rgba8.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//============================================pixel_formats_crb_rgba32_pre
|
||||
template<class RenBuf, class Order> class pixel_formats_crb_rgba32_pre
|
||||
{
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
typedef RenBuf buffer_type;
|
||||
typedef Order order_type;
|
||||
|
||||
typedef typename RenBuf::row_data row_data;
|
||||
|
||||
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_crb_rgba32_pre(RenBuf& 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) const
|
||||
{
|
||||
const int8u* p = m_rbuf->span_ptr(x, y, 1);
|
||||
return p ? color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]) :
|
||||
color_type::no_color();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
return m_rbuf->span(x, y);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
int8u* p = m_rbuf->span_ptr(x, y, 1);
|
||||
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->span_ptr(x, y, 1), 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->span_ptr(x, y, len));
|
||||
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);
|
||||
do
|
||||
{
|
||||
*(int32u*)(m_rbuf->span_ptr(x, y, 1)) = v;
|
||||
++y;
|
||||
}
|
||||
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;
|
||||
copy_pix((int8u*)&v, c);
|
||||
int32u* p32 = (int32u*)(m_rbuf->span_ptr(x, y, len));
|
||||
do
|
||||
{
|
||||
*p32++ = v;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
int8u* p = m_rbuf->span_ptr(x, y, len);
|
||||
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)
|
||||
{
|
||||
int alpha = int(cover) * c.a;
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
int32u v;
|
||||
copy_pix((int8u*)&v, c);
|
||||
do
|
||||
{
|
||||
*(int32u*)(m_rbuf->span_ptr(x, y, 1)) = v;
|
||||
++y;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = 65535 - alpha;
|
||||
do
|
||||
{
|
||||
blend_pix(m_rbuf->span_ptr(x, y, 1), c, cover, alpha);
|
||||
++y;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf2> void copy_from(const RenBuf2& from,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
const int8u* p = from.row(ysrc);
|
||||
if(p)
|
||||
{
|
||||
p += xsrc << 2;
|
||||
memmove(m_rbuf->span_ptr(xdst, ydst, len), p, len * 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from(const SrcPixelFormatRenderer& from,
|
||||
const int8u* psrc,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::order_type src_order;
|
||||
int8u* pdst = m_rbuf->span_ptr(xdst, ydst, len);
|
||||
int incp = 4;
|
||||
if(xdst > xsrc)
|
||||
{
|
||||
psrc += (len-1) << 2;
|
||||
pdst += (len-1) << 2;
|
||||
incp = -4;
|
||||
}
|
||||
do
|
||||
{
|
||||
unsigned alpha = 255 - psrc[src_order::A];
|
||||
if(alpha < 255)
|
||||
{
|
||||
if(alpha == 0)
|
||||
{
|
||||
pdst[Order::R] = psrc[src_order::R];
|
||||
pdst[Order::G] = psrc[src_order::G];
|
||||
pdst[Order::B] = psrc[src_order::B];
|
||||
pdst[Order::A] = psrc[src_order::A];
|
||||
}
|
||||
else
|
||||
{
|
||||
pdst[Order::R] = (int8u)((pdst[Order::R] * alpha + (psrc[src_order::R] << 8)) >> 8);
|
||||
pdst[Order::G] = (int8u)((pdst[Order::G] * alpha + (psrc[src_order::G] << 8)) >> 8);
|
||||
pdst[Order::B] = (int8u)((pdst[Order::B] * alpha + (psrc[src_order::B] << 8)) >> 8);
|
||||
pdst[Order::A] = (int8u)(255 - ((alpha * (255 - pdst[Order::A])) >> 8));
|
||||
}
|
||||
}
|
||||
psrc += incp;
|
||||
pdst += incp;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
int8u* p = m_rbuf->span_ptr(x, y, len);
|
||||
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)
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(m_rbuf->span_ptr(x, y, 1), c, *covers++);
|
||||
++y;
|
||||
}
|
||||
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->span_ptr(x, y, len);
|
||||
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)
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(m_rbuf->span_ptr(x, y, 1),
|
||||
*colors++,
|
||||
covers ? *covers++ : cover);
|
||||
++y;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
private:
|
||||
RenBuf* m_rbuf;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,6 +30,9 @@ namespace agg
|
||||
{
|
||||
public:
|
||||
typedef gray8 color_type;
|
||||
typedef bool order_type;
|
||||
typedef rendering_buffer::row_data row_data;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
pixfmt_gray8_base(rendering_buffer& rb)
|
||||
@@ -42,11 +45,17 @@ namespace agg
|
||||
unsigned height() const { return m_rbuf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y)
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
return color_type(m_rbuf->row(y)[x * Step + Offset]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
return row_data(x, width() - 1, m_rbuf->row(y) + x);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace agg
|
||||
{
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
typedef Order order_type;
|
||||
typedef rendering_buffer::row_data row_data;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
pixel_formats_rgb24(rendering_buffer& rb)
|
||||
@@ -41,12 +43,18 @@ namespace agg
|
||||
unsigned height() const { return m_rbuf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y)
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||
return color_type(p[Order::R], p[Order::G], p[Order::B]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
return row_data(x, width() - 1, m_rbuf->row(y) + x * 3);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
|
||||
@@ -32,6 +32,8 @@ namespace agg
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
typedef Gamma gamma_type;
|
||||
typedef Order order_type;
|
||||
typedef rendering_buffer::row_data row_data;
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
@@ -105,12 +107,18 @@ namespace agg
|
||||
unsigned height() const { return m_rbuf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y)
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||
return color_type(p[Order::R], p[Order::G], p[Order::B]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
return row_data(x, width() - 1, m_rbuf->row(y) + x * 3);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
|
||||
@@ -30,7 +30,8 @@ namespace agg
|
||||
{
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
|
||||
typedef Order order_type;
|
||||
typedef rendering_buffer::row_data row_data;
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
@@ -101,12 +102,18 @@ namespace agg
|
||||
unsigned height() const { return m_rbuf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y)
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
int8u* p = m_rbuf->row(y) + x + x + x;
|
||||
return color_type(p[Order::R], p[Order::G], p[Order::B]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
return row_data(x, width() - 1, m_rbuf->row(y) + x * 3);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
|
||||
@@ -36,6 +36,8 @@ namespace agg
|
||||
{
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
typedef bool order_type;
|
||||
typedef rendering_buffer::row_data row_data;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
pixfmt_rgb555(rendering_buffer& rb)
|
||||
@@ -48,7 +50,7 @@ namespace agg
|
||||
unsigned height() const { return m_rbuf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y)
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
unsigned rgb = ((int16u*)(m_rbuf->row(y)))[x];
|
||||
return color_type((rgb >> 7) & 0xF8,
|
||||
@@ -56,6 +58,12 @@ namespace agg
|
||||
(rgb << 3) & 0xF8);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
return row_data(x, width() - 1, m_rbuf->row(y) + x * 2);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
|
||||
@@ -36,6 +36,8 @@ namespace agg
|
||||
{
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
typedef bool order_type;
|
||||
typedef rendering_buffer::row_data row_data;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
pixfmt_rgb565(rendering_buffer& rb)
|
||||
@@ -48,7 +50,7 @@ namespace agg
|
||||
unsigned height() const { return m_rbuf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y)
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
unsigned rgb = ((int16u*)(m_rbuf->row(y)))[x];
|
||||
return color_type((rgb >> 8) & 0xF8,
|
||||
@@ -56,6 +58,12 @@ namespace agg
|
||||
(rgb << 3) & 0xF8);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
return row_data(x, width() - 1, m_rbuf->row(y) + x * 2);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace agg
|
||||
{
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
typedef Order order_type;
|
||||
typedef rendering_buffer::row_data row_data;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
pixel_formats_rgba32(rendering_buffer& rb)
|
||||
@@ -41,12 +43,18 @@ namespace agg
|
||||
unsigned height() const { return m_rbuf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y)
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
return row_data(x, width() - 1, m_rbuf->row(y) + (x << 2));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
@@ -207,6 +215,59 @@ namespace agg
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from(const SrcPixelFormatRenderer& from,
|
||||
const int8u* psrc,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::order_type src_order;
|
||||
|
||||
int8u* pdst = m_rbuf->row(ydst) + (xdst << 2);
|
||||
int incp = 4;
|
||||
if(xdst > xsrc)
|
||||
{
|
||||
psrc += (len-1) << 2;
|
||||
pdst += (len-1) << 2;
|
||||
incp = -4;
|
||||
}
|
||||
do
|
||||
{
|
||||
int alpha = psrc[src_order::A];
|
||||
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255)
|
||||
{
|
||||
pdst[Order::R] = psrc[src_order::R];
|
||||
pdst[Order::G] = psrc[src_order::G];
|
||||
pdst[Order::B] = psrc[src_order::B];
|
||||
pdst[Order::A] = psrc[src_order::A];
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = pdst[Order::R];
|
||||
int g = pdst[Order::G];
|
||||
int b = pdst[Order::B];
|
||||
int a = pdst[Order::A];
|
||||
pdst[Order::R] = (int8u)((((psrc[src_order::R] - r) * alpha) + (r << 8)) >> 8);
|
||||
pdst[Order::G] = (int8u)((((psrc[src_order::G] - g) * alpha) + (g << 8)) >> 8);
|
||||
pdst[Order::B] = (int8u)((((psrc[src_order::B] - b) * alpha) + (b << 8)) >> 8);
|
||||
pdst[Order::A] = (int8u)((alpha + a) - ((alpha * a) >> 8));
|
||||
}
|
||||
}
|
||||
psrc += incp;
|
||||
pdst += incp;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
|
||||
@@ -30,7 +30,8 @@ namespace agg
|
||||
{
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
|
||||
typedef Order order_type;
|
||||
typedef rendering_buffer::row_data row_data;
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
@@ -117,12 +118,18 @@ namespace agg
|
||||
unsigned height() const { return m_rbuf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y)
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
return row_data(x, width() - 1, m_rbuf->row(y) + (x << 2));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
|
||||
@@ -30,6 +30,8 @@ namespace agg
|
||||
{
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
typedef Order order_type;
|
||||
typedef rendering_buffer::row_data row_data;
|
||||
|
||||
|
||||
private:
|
||||
@@ -104,12 +106,18 @@ namespace agg
|
||||
unsigned height() const { return m_rbuf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y)
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
return row_data(x, width() - 1, m_rbuf->row(y) + (x << 2));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
@@ -223,6 +231,52 @@ namespace agg
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from(const SrcPixelFormatRenderer& from,
|
||||
const int8u* psrc,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::order_type src_order;
|
||||
|
||||
int8u* pdst = m_rbuf->row(ydst) + (xdst << 2);
|
||||
int incp = 4;
|
||||
if(xdst > xsrc)
|
||||
{
|
||||
psrc += (len-1) << 2;
|
||||
pdst += (len-1) << 2;
|
||||
incp = -4;
|
||||
}
|
||||
do
|
||||
{
|
||||
unsigned alpha = 255 - psrc[src_order::A];
|
||||
if(alpha < 255)
|
||||
{
|
||||
if(alpha == 0)
|
||||
{
|
||||
pdst[Order::R] = psrc[src_order::R];
|
||||
pdst[Order::G] = psrc[src_order::G];
|
||||
pdst[Order::B] = psrc[src_order::B];
|
||||
pdst[Order::A] = psrc[src_order::A];
|
||||
}
|
||||
else
|
||||
{
|
||||
pdst[Order::R] = (int8u)((pdst[Order::R] * alpha + (psrc[src_order::R] << 8)) >> 8);
|
||||
pdst[Order::G] = (int8u)((pdst[Order::G] * alpha + (psrc[src_order::G] << 8)) >> 8);
|
||||
pdst[Order::B] = (int8u)((pdst[Order::B] * alpha + (psrc[src_order::B] << 8)) >> 8);
|
||||
pdst[Order::A] = (int8u)(255 - ((alpha * (255 - pdst[Order::A])) >> 8));
|
||||
}
|
||||
}
|
||||
psrc += incp;
|
||||
pdst += incp;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
|
||||
@@ -148,34 +148,6 @@ namespace agg
|
||||
};
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------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
|
||||
@@ -207,7 +179,7 @@ namespace agg
|
||||
//
|
||||
// filling_rule() and gamma() can be called anytime before "sweeping".
|
||||
//------------------------------------------------------------------------
|
||||
template<unsigned AA_Shift=8> class rasterizer_scanline_aa
|
||||
template<unsigned XScale=1, unsigned AA_Shift=8> class rasterizer_scanline_aa
|
||||
{
|
||||
enum status
|
||||
{
|
||||
@@ -455,9 +427,9 @@ namespace agg
|
||||
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>&);
|
||||
rasterizer_scanline_aa(const rasterizer_scanline_aa<XScale, AA_Shift>&);
|
||||
const rasterizer_scanline_aa<XScale, AA_Shift>&
|
||||
operator = (const rasterizer_scanline_aa<XScale, AA_Shift>&);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to_no_clip(int x, int y);
|
||||
@@ -492,23 +464,23 @@ namespace agg
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<AA_Shift>::reset()
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, 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)
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, 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)
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, AA_Shift>::clip_box(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
reset();
|
||||
m_clip_box = rect(poly_coord(x1), poly_coord(y1),
|
||||
@@ -518,8 +490,8 @@ namespace agg
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<AA_Shift>::reset_clipping()
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, AA_Shift>::reset_clipping()
|
||||
{
|
||||
reset();
|
||||
m_clipping = false;
|
||||
@@ -528,14 +500,14 @@ namespace agg
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<AA_Shift>::move_to_no_clip(int x, int y)
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, 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_outline.move_to(x * XScale, y);
|
||||
m_clipped_start_x = x;
|
||||
m_clipped_start_y = y;
|
||||
m_status = status_line_to;
|
||||
@@ -543,32 +515,32 @@ namespace agg
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<AA_Shift>::line_to_no_clip(int x, int y)
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, AA_Shift>::line_to_no_clip(int x, int y)
|
||||
{
|
||||
if(m_status != status_initial)
|
||||
{
|
||||
m_outline.line_to(x, y);
|
||||
m_outline.line_to(x * XScale, y);
|
||||
m_status = status_line_to;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<AA_Shift>::close_polygon_no_clip()
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, 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_outline.line_to(m_clipped_start_x * XScale, m_clipped_start_y);
|
||||
m_status = status_closed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<AA_Shift>::clip_segment(int x, int y)
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, AA_Shift>::clip_segment(int x, int y)
|
||||
{
|
||||
unsigned flags = clipping_flags(x, y, m_clip_box);
|
||||
if(m_prev_flags == flags)
|
||||
@@ -615,8 +587,8 @@ namespace agg
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<AA_Shift>::add_vertex(double x, double y, unsigned cmd)
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, AA_Shift>::add_vertex(double x, double y, unsigned cmd)
|
||||
{
|
||||
if(is_close(cmd))
|
||||
{
|
||||
@@ -641,8 +613,8 @@ namespace agg
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<AA_Shift>::move_to(int x, int y)
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, AA_Shift>::move_to(int x, int y)
|
||||
{
|
||||
if(m_clipping)
|
||||
{
|
||||
@@ -670,8 +642,8 @@ namespace agg
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<AA_Shift>::line_to(int x, int y)
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, AA_Shift>::line_to(int x, int y)
|
||||
{
|
||||
if(m_clipping)
|
||||
{
|
||||
@@ -684,8 +656,8 @@ namespace agg
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<AA_Shift>::close_polygon()
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, AA_Shift>::close_polygon()
|
||||
{
|
||||
if(m_clipping)
|
||||
{
|
||||
@@ -695,23 +667,23 @@ namespace agg
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<AA_Shift>::move_to_d(double x, double y)
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, 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)
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
void rasterizer_scanline_aa<XScale, 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)
|
||||
template<unsigned XScale, unsigned AA_Shift>
|
||||
bool rasterizer_scanline_aa<XScale, AA_Shift>::hit_test(int tx, int ty)
|
||||
{
|
||||
close_polygon();
|
||||
const cell_aa* const* cells = m_outline.cells();
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------renderer_base
|
||||
template<class PixelFormat> class renderer_base
|
||||
{
|
||||
@@ -371,43 +372,169 @@ namespace agg
|
||||
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 clip_rect_area(rect& dst, rect& src, int wsrc, int hsrc) const
|
||||
{
|
||||
rect tmp_rect(0, 0, from.width(), from.height());
|
||||
if(rc == 0)
|
||||
rect rc(0,0,0,0);
|
||||
rect cb = clip_box();
|
||||
++cb.x2;
|
||||
++cb.y2;
|
||||
|
||||
if(src.x1 < 0)
|
||||
{
|
||||
rc = &tmp_rect;
|
||||
dst.x1 -= src.x1;
|
||||
src.x1 = 0;
|
||||
}
|
||||
if(src.y1 < 0)
|
||||
{
|
||||
dst.y1 -= src.y1;
|
||||
src.y1 = 0;
|
||||
}
|
||||
|
||||
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(src.x2 > wsrc) src.x2 = wsrc;
|
||||
if(src.y2 > hsrc) src.y2 = hsrc;
|
||||
|
||||
if(rc3.clip(clip_box()))
|
||||
if(dst.x1 < cb.x1)
|
||||
{
|
||||
src.x1 += cb.x1 - dst.x1;
|
||||
dst.x1 = cb.x1;
|
||||
}
|
||||
if(dst.y1 < cb.y1)
|
||||
{
|
||||
src.y1 += cb.y1 - dst.y1;
|
||||
dst.y1 = cb.y1;
|
||||
}
|
||||
|
||||
if(dst.x2 > cb.x2) dst.x2 = cb.x2;
|
||||
if(dst.y2 > cb.y2) dst.y2 = cb.y2;
|
||||
|
||||
rc.x2 = dst.x2 - dst.x1;
|
||||
rc.y2 = dst.y2 - dst.y1;
|
||||
|
||||
if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1;
|
||||
if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_from(const rendering_buffer& src,
|
||||
const rect* rect_src_ptr = 0,
|
||||
int dx = 0,
|
||||
int dy = 0)
|
||||
{
|
||||
rect rsrc(0, 0, src.width(), src.height());
|
||||
if(rect_src_ptr)
|
||||
{
|
||||
rsrc.x1 = rect_src_ptr->x1;
|
||||
rsrc.y1 = rect_src_ptr->y1;
|
||||
rsrc.x2 = rect_src_ptr->x2 + 1;
|
||||
rsrc.y2 = rect_src_ptr->y2 + 1;
|
||||
}
|
||||
|
||||
// Version with xdst, ydst (absolute positioning)
|
||||
//rect rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
|
||||
|
||||
// Version with dx, dy (relative positioning)
|
||||
rect rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
|
||||
|
||||
rect rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
|
||||
|
||||
if(rc.x2 > 0)
|
||||
{
|
||||
int incy = 1;
|
||||
if(rdst.y1 > rsrc.y1)
|
||||
{
|
||||
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;
|
||||
}
|
||||
rsrc.y1 += rc.y2 - 1;
|
||||
rdst.y1 += rc.y2 - 1;
|
||||
incy = -1;
|
||||
}
|
||||
while(rc.y2 > 0)
|
||||
{
|
||||
m_ren->copy_from(src,
|
||||
rdst.x1, rdst.y1,
|
||||
rsrc.x1, rsrc.y1,
|
||||
rc.x2);
|
||||
rdst.y1 += incy;
|
||||
rsrc.y1 += incy;
|
||||
--rc.y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from(const SrcPixelFormatRenderer& src,
|
||||
const rect* rect_src_ptr = 0,
|
||||
int dx = 0,
|
||||
int dy = 0)
|
||||
{
|
||||
rect rsrc(0, 0, src.width(), src.height());
|
||||
if(rect_src_ptr)
|
||||
{
|
||||
rsrc.x1 = rect_src_ptr->x1;
|
||||
rsrc.y1 = rect_src_ptr->y1;
|
||||
rsrc.x2 = rect_src_ptr->x2 + 1;
|
||||
rsrc.y2 = rect_src_ptr->y2 + 1;
|
||||
}
|
||||
|
||||
// Version with xdst, ydst (absolute positioning)
|
||||
//rect rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1);
|
||||
|
||||
// Version with dx, dy (relative positioning)
|
||||
rect rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
|
||||
|
||||
rect rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
|
||||
|
||||
if(rc.x2 > 0)
|
||||
{
|
||||
int incy = 1;
|
||||
if(rdst.y1 > rsrc.y1)
|
||||
{
|
||||
rsrc.y1 += rc.y2 - 1;
|
||||
rdst.y1 += rc.y2 - 1;
|
||||
incy = -1;
|
||||
}
|
||||
while(rc.y2 > 0)
|
||||
{
|
||||
typename SrcPixelFormatRenderer::row_data span = src.span(rsrc.x1, rsrc.y1);
|
||||
if(span.ptr)
|
||||
{
|
||||
int x1src = rsrc.x1;
|
||||
int x1dst = rdst.x1;
|
||||
int len = rc.x2;
|
||||
if(span.x1 > x1src)
|
||||
{
|
||||
x1dst += span.x1 - x1src;
|
||||
len -= span.x1 - x1src;
|
||||
x1src = span.x1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
if(x1src + len-1 > span.x2)
|
||||
{
|
||||
len -= x1src + len - span.x2 - 1;
|
||||
}
|
||||
if(len > 0)
|
||||
{
|
||||
m_ren->blend_from(src, span.ptr,
|
||||
x1dst, rdst.y1,
|
||||
x1src, rsrc.y1,
|
||||
len);
|
||||
}
|
||||
}
|
||||
}
|
||||
rdst.y1 += incy;
|
||||
rsrc.y1 += incy;
|
||||
--rc.y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
pixfmt_type* m_ren;
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace agg
|
||||
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
//double src_y = (y + 0.5) * m_scale - 0.5;
|
||||
double src_y = y * m_scale;
|
||||
int h = int(m_source.height()) - 1;
|
||||
int y1 = int(floor(src_y));
|
||||
@@ -170,16 +171,16 @@ namespace agg
|
||||
int line_width() const { return m_half_height_hr; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y) const
|
||||
void pixel(color_type* p, 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);
|
||||
m_filter->pixel_high_res(m_buf.rows(),
|
||||
p,
|
||||
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; }
|
||||
const filter_type& filter() const { return *m_filter; }
|
||||
|
||||
private:
|
||||
line_image_pattern(const line_image_pattern<filter_type>&);
|
||||
@@ -830,8 +831,12 @@ namespace agg
|
||||
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; }
|
||||
void scale_x(double s) { m_scale_x = s; }
|
||||
double scale_x() const { return m_scale_x; }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
void start_x(double s) { m_start = int(s * line_subpixel_size); }
|
||||
double start_x() const { return double(m_start) / line_subpixel_size; }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
int subpixel_width() const { return m_pattern->line_width(); }
|
||||
|
||||
@@ -72,9 +72,13 @@ namespace agg
|
||||
if(x < xmin)
|
||||
{
|
||||
len -= xmin - x;
|
||||
covers += xmin - x;
|
||||
if(!solid)
|
||||
{
|
||||
covers += xmin - x;
|
||||
}
|
||||
x = xmin;
|
||||
}
|
||||
|
||||
if(len > 0)
|
||||
{
|
||||
if(x + len > xmax)
|
||||
|
||||
@@ -29,6 +29,16 @@ namespace agg
|
||||
template<class T> class row_ptr_cache
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
struct row_data
|
||||
{
|
||||
int x1, x2;
|
||||
const int8u* ptr;
|
||||
row_data() {}
|
||||
row_data(int x1_, int x2_, const int8u* ptr_) :
|
||||
x1(x1_), x2(x2_), ptr(ptr_) {}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
~row_ptr_cache()
|
||||
{
|
||||
@@ -122,6 +132,22 @@ namespace agg
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear(T value)
|
||||
{
|
||||
unsigned y;
|
||||
for(y = 0; y < height(); y++)
|
||||
{
|
||||
T* p = row(y);
|
||||
unsigned x;
|
||||
for(x = 0; x < stride_abs(); x++)
|
||||
{
|
||||
*p++ = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
// Prohibit copying
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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_dynarow
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
|
||||
#define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===============================================rendering_buffer_dynarow
|
||||
// Rendering buffer class with dynamic allocation of the rows.
|
||||
// The rows are allocated as needed when requesting for span_ptr().
|
||||
// The class automatically calculates min_x and max_x for each row.
|
||||
// Generally it's more efficient to use this class as a temporary buffer
|
||||
// for rendering a few lines and then to blend it with another buffer.
|
||||
//
|
||||
template<unsigned PixWidth> class rendering_buffer_dynarow
|
||||
{
|
||||
public:
|
||||
//-------------------------------------------------------------------
|
||||
struct row_data
|
||||
{
|
||||
int8u* ptr;
|
||||
int x1;
|
||||
int x2;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
~rendering_buffer_dynarow()
|
||||
{
|
||||
init(0,0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
rendering_buffer_dynarow() :
|
||||
m_rows(0),
|
||||
m_width(0),
|
||||
m_height(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Allocate and clear the buffer
|
||||
//--------------------------------------------------------------------
|
||||
rendering_buffer_dynarow(unsigned width, unsigned height) :
|
||||
m_rows(new row_data[height]),
|
||||
m_width(width),
|
||||
m_height(height)
|
||||
{
|
||||
memset(m_rows, 0, sizeof(row_data) * height);
|
||||
}
|
||||
|
||||
// Allocate and clear the buffer
|
||||
//--------------------------------------------------------------------
|
||||
void init(unsigned width, unsigned height)
|
||||
{
|
||||
unsigned i;
|
||||
for(i = 0; i < m_height; ++i) delete [] m_rows[i].ptr;
|
||||
delete [] m_rows;
|
||||
m_rows = 0;
|
||||
if(width && height)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_rows = new row_data[height];
|
||||
memset(m_rows, 0, sizeof(row_data) * height);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned width() const { return m_width; }
|
||||
unsigned height() const { return m_height; }
|
||||
|
||||
// Get pointer to the beginning of the row. Memory for the row
|
||||
// is allocated as needed.
|
||||
//--------------------------------------------------------------------
|
||||
int8u* row(int y)
|
||||
{
|
||||
row_data* r = m_rows + y;
|
||||
if(r->ptr == 0)
|
||||
{
|
||||
r->ptr = new int8u [m_width * PixWidth];
|
||||
memset(r->ptr, 0, m_width * PixWidth);
|
||||
}
|
||||
return r->ptr;
|
||||
}
|
||||
|
||||
// Get const pointer to the row. The caller must check it for null.
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* row(int y) const
|
||||
{
|
||||
return m_rows[y].ptr;
|
||||
}
|
||||
|
||||
// Get the Y-th span. The pointer r.ptr is automatically adjusted
|
||||
// to the actual beginning of the span. Use this function as follows:
|
||||
//
|
||||
// rendering_buffer_dynarow::row_data r = rbuf.span(x, y);
|
||||
// if(r.ptr)
|
||||
// {
|
||||
// do { blend(r.ptr); r.ptr += PixWidth } while(++r.x1 < r.x2);
|
||||
// }
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
row_data r = m_rows[y];
|
||||
if(r.ptr)
|
||||
{
|
||||
if(x < r.x1) x = r.x1;
|
||||
r.ptr += x * PixWidth;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
// The main function used for rendering. Returns pointer to the
|
||||
// pre-allocated span. Memory for the row is allocated as needed.
|
||||
//--------------------------------------------------------------------
|
||||
int8u* span_ptr(int x, int y, unsigned len)
|
||||
{
|
||||
row_data* r = m_rows + y;
|
||||
int x2 = x + len - 1;
|
||||
if(r->ptr)
|
||||
{
|
||||
if(x < r->x1) { r->x1 = x; }
|
||||
if(x2 > r->x2) { r->x2 = x2; }
|
||||
}
|
||||
else
|
||||
{
|
||||
r->ptr = new int8u [m_width * PixWidth];
|
||||
r->x1 = x;
|
||||
r->x2 = x2;
|
||||
memset(r->ptr, 0, m_width * PixWidth);
|
||||
}
|
||||
return r->ptr + x * PixWidth;
|
||||
}
|
||||
|
||||
// Get const pointer to the span. Used mostly in GetPixel function
|
||||
// The caller must check the returned pointer for null.
|
||||
//--------------------------------------------------------------------
|
||||
const int8u* span_ptr(int x, int y, unsigned) const
|
||||
{
|
||||
row_data* r = m_rows + y;
|
||||
return r->ptr ? r->ptr + x * PixWidth : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
// Prohibit copying
|
||||
rendering_buffer_dynarow(const rendering_buffer_dynarow<PixWidth>&);
|
||||
const rendering_buffer_dynarow<PixWidth>&
|
||||
operator = (const rendering_buffer_dynarow<PixWidth>&);
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
row_data* m_rows; // Pointers to each row of the buffer
|
||||
unsigned m_width; // Width in pixels
|
||||
unsigned m_height; // Height in pixels
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -303,12 +303,13 @@ namespace agg
|
||||
|
||||
sp.x = span_iterator->x;
|
||||
sp.len = span_iterator->len;
|
||||
int len = abs(int(sp.len));
|
||||
sp.covers_id =
|
||||
m_covers.add_cells(span_iterator->covers,
|
||||
unsigned(abs(int(sp.len))));
|
||||
unsigned(len));
|
||||
m_spans.add(sp);
|
||||
int x1 = sp.x;
|
||||
int x2 = sp.x + sp.len - 1;
|
||||
int x2 = sp.x + len - 1;
|
||||
if(x1 < m_min_x) m_min_x = x1;
|
||||
if(x2 > m_max_x) m_max_x = x2;
|
||||
++span_iterator;
|
||||
|
||||
@@ -236,18 +236,8 @@ namespace agg
|
||||
|
||||
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);
|
||||
size += sizeof(int16) * 2 + // Y, num_spans
|
||||
unsigned(m_scanlines[i].num_spans) * sizeof(int16) * 2; // X, span_len
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace agg
|
||||
color_type* generate(int x, int y, unsigned len)
|
||||
{
|
||||
color_type* span = m_span_gen->generate(x, y, len);
|
||||
m_conv->convert(span, len);
|
||||
m_conv->convert(span, x, y, len);
|
||||
return span;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,14 @@
|
||||
namespace agg
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
gradient_subpixel_shift = 4,
|
||||
gradient_subpixel_size = 1 << gradient_subpixel_shift,
|
||||
gradient_subpixel_mask = gradient_subpixel_size - 1
|
||||
};
|
||||
|
||||
|
||||
//==========================================================span_gradient
|
||||
template<class ColorT,
|
||||
class Interpolator,
|
||||
@@ -45,12 +53,7 @@ namespace agg
|
||||
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
|
||||
downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift
|
||||
};
|
||||
|
||||
|
||||
@@ -67,23 +70,23 @@ namespace agg
|
||||
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))
|
||||
m_d1(int(d1 * gradient_subpixel_size)),
|
||||
m_d2(int(d2 * gradient_subpixel_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; }
|
||||
double d1() const { return double(m_d1) / gradient_subpixel_size; }
|
||||
double d2() const { return double(m_d2) / gradient_subpixel_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); }
|
||||
void d1(double v) { m_d1 = int(v * gradient_subpixel_size); }
|
||||
void d2(double v) { m_d2 = int(v * gradient_subpixel_size); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type* generate(int x, int y, unsigned len)
|
||||
@@ -150,9 +153,20 @@ namespace agg
|
||||
};
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------gradient_circle
|
||||
//==========================================================gradient_circle
|
||||
class gradient_circle
|
||||
{
|
||||
// Actually the same as radial. Just for compatibility
|
||||
public:
|
||||
static int calculate(int x, int y, int)
|
||||
{
|
||||
return int(fast_sqrt(x*x + y*y));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==========================================================gradient_radial
|
||||
class gradient_radial
|
||||
{
|
||||
public:
|
||||
static int calculate(int x, int y, int)
|
||||
@@ -162,7 +176,148 @@ namespace agg
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------gradient_x
|
||||
//========================================================gradient_radial_d
|
||||
class gradient_radial_d
|
||||
{
|
||||
public:
|
||||
static int calculate(int x, int y, int)
|
||||
{
|
||||
return int(sqrt(double(x)*double(x) + double(y)*double(y)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//====================================================gradient_radial_focus
|
||||
class gradient_radial_focus
|
||||
{
|
||||
public:
|
||||
//---------------------------------------------------------------------
|
||||
gradient_radial_focus() :
|
||||
m_radius(100 * gradient_subpixel_size),
|
||||
m_focus_x(0),
|
||||
m_focus_y(0)
|
||||
{
|
||||
update_values();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
gradient_radial_focus(double r, double fx, double fy) :
|
||||
m_radius (int(r * gradient_subpixel_size)),
|
||||
m_focus_x(int(fx * gradient_subpixel_size)),
|
||||
m_focus_y(int(fy * gradient_subpixel_size))
|
||||
{
|
||||
update_values();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
void init(double r, double fx, double fy)
|
||||
{
|
||||
m_radius = int(r * gradient_subpixel_size);
|
||||
m_focus_x = int(fx * gradient_subpixel_size);
|
||||
m_focus_y = int(fy * gradient_subpixel_size);
|
||||
update_values();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
double radius() const { return double(m_radius) / gradient_subpixel_size; }
|
||||
double focus_x() const { return double(m_focus_x) / gradient_subpixel_size; }
|
||||
double focus_y() const { return double(m_focus_y) / gradient_subpixel_size; }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
int calculate(int x, int y, int d) const
|
||||
{
|
||||
double solution_x;
|
||||
double solution_y;
|
||||
|
||||
// Special case to avoid divide by zero or very near zero
|
||||
//---------------------------------
|
||||
if(x == int(m_focus_x))
|
||||
{
|
||||
solution_x = m_focus_x;
|
||||
solution_y = 0.0;
|
||||
solution_y += (y > m_focus_y) ? m_trivial : -m_trivial;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Slope of the focus-current line
|
||||
//-------------------------------
|
||||
double slope = double(y - m_focus_y) / double(x - m_focus_x);
|
||||
|
||||
// y-intercept of that same line
|
||||
//--------------------------------
|
||||
double yint = double(y) - (slope * x);
|
||||
|
||||
// Use the classical quadratic formula to calculate
|
||||
// the intersection point
|
||||
//--------------------------------
|
||||
double a = (slope * slope) + 1;
|
||||
double b = 2 * slope * yint;
|
||||
double c = yint * yint - m_radius2;
|
||||
double det = sqrt((b * b) - (4.0 * a * c));
|
||||
solution_x = -b;
|
||||
|
||||
// Choose the positive or negative root depending
|
||||
// on where the X coord lies with respect to the focus.
|
||||
solution_x += (x < m_focus_x) ? -det : det;
|
||||
solution_x /= 2.0 * a;
|
||||
|
||||
// Calculating of Y is trivial
|
||||
solution_y = (slope * solution_x) + yint;
|
||||
}
|
||||
|
||||
// Calculate the percentage (0...1) of the current point along the
|
||||
// focus-circumference line and return the normalized (0...d) value
|
||||
//-------------------------------
|
||||
solution_x -= double(m_focus_x);
|
||||
solution_y -= double(m_focus_y);
|
||||
double int_to_focus = solution_x * solution_x + solution_y * solution_y;
|
||||
double cur_to_focus = double(x - m_focus_x) * double(x - m_focus_x) +
|
||||
double(y - m_focus_y) * double(y - m_focus_y);
|
||||
|
||||
return int(sqrt(cur_to_focus / int_to_focus) * d);
|
||||
}
|
||||
|
||||
private:
|
||||
//---------------------------------------------------------------------
|
||||
void update_values()
|
||||
{
|
||||
// For use in the quadractic equation
|
||||
//-------------------------------
|
||||
m_radius2 = double(m_radius) * double(m_radius);
|
||||
|
||||
double dist = sqrt(double(m_focus_x) * double(m_focus_x) +
|
||||
double(m_focus_y) * double(m_focus_y));
|
||||
|
||||
// Test if distance from focus to center is greater than the radius
|
||||
// For the sake of assurance factor restrict the point to be
|
||||
// no further than 99% of the radius.
|
||||
//-------------------------------
|
||||
double r = m_radius * 0.99;
|
||||
if(dist > r)
|
||||
{
|
||||
// clamp focus to radius
|
||||
// x = r cos theta, y = r sin theta
|
||||
//------------------------
|
||||
double a = atan2(double(m_focus_y), double(m_focus_x));
|
||||
m_focus_x = int(r * cos(a));
|
||||
m_focus_y = int(r * sin(a));
|
||||
}
|
||||
|
||||
// Calculate the solution to be used in the case where x == focus_x
|
||||
//------------------------------
|
||||
m_trivial = sqrt(m_radius2 - (m_focus_x * m_focus_x));
|
||||
}
|
||||
|
||||
int m_radius;
|
||||
int m_focus_x;
|
||||
int m_focus_y;
|
||||
double m_radius2;
|
||||
double m_trivial;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==============================================================gradient_x
|
||||
class gradient_x
|
||||
{
|
||||
public:
|
||||
@@ -170,7 +325,7 @@ namespace agg
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------gradient_y
|
||||
//==============================================================gradient_y
|
||||
class gradient_y
|
||||
{
|
||||
public:
|
||||
@@ -178,7 +333,7 @@ namespace agg
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------gradient_diamond
|
||||
//========================================================gradient_diamond
|
||||
class gradient_diamond
|
||||
{
|
||||
public:
|
||||
@@ -191,7 +346,7 @@ namespace agg
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------gradient_xy
|
||||
//=============================================================gradient_xy
|
||||
class gradient_xy
|
||||
{
|
||||
public:
|
||||
@@ -202,7 +357,7 @@ namespace agg
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------gradient_sqrt_xy
|
||||
//========================================================gradient_sqrt_xy
|
||||
class gradient_sqrt_xy
|
||||
{
|
||||
public:
|
||||
@@ -213,7 +368,7 @@ namespace agg
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------gradient_conic
|
||||
//==========================================================gradient_conic
|
||||
class gradient_conic
|
||||
{
|
||||
public:
|
||||
@@ -224,6 +379,44 @@ namespace agg
|
||||
};
|
||||
|
||||
|
||||
//=================================================gradient_repeat_adaptor
|
||||
template<class GradientF> class gradient_repeat_adaptor
|
||||
{
|
||||
public:
|
||||
gradient_repeat_adaptor(const GradientF& gradient) :
|
||||
m_gradient(&gradient) {}
|
||||
|
||||
int calculate(int x, int y, int d) const
|
||||
{
|
||||
int ret = m_gradient->calculate(x, y, d) % d;
|
||||
if(ret < 0) ret += d;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
const GradientF* m_gradient;
|
||||
};
|
||||
|
||||
|
||||
//================================================gradient_reflect_adaptor
|
||||
template<class GradientF> class gradient_reflect_adaptor
|
||||
{
|
||||
public:
|
||||
gradient_reflect_adaptor(const GradientF& gradient) :
|
||||
m_gradient(&gradient) {}
|
||||
|
||||
int calculate(int x, int y, int d) const
|
||||
{
|
||||
int d2 = d << 1;
|
||||
int ret = m_gradient->calculate(x, y, d) % d2;
|
||||
if(ret < 0) ret += d2;
|
||||
if(ret >= d) ret = d2 - ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
const GradientF* m_gradient;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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_ALPHA_INCLUDED
|
||||
#define AGG_SPAN_GRADIENT_ALPHA_INCLUDED
|
||||
|
||||
#include "agg_span_gradient.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//======================================================span_gradient_alpha
|
||||
template<class ColorT,
|
||||
class Interpolator,
|
||||
class GradientF,
|
||||
class AlphaF>
|
||||
class span_gradient_alpha
|
||||
{
|
||||
public:
|
||||
typedef Interpolator interpolator_type;
|
||||
typedef ColorT color_type;
|
||||
typedef typename color_type::alpha_type alpha_type;
|
||||
|
||||
enum
|
||||
{
|
||||
base_shift = 8,
|
||||
base_size = 1 << base_shift,
|
||||
base_mask = base_size - 1,
|
||||
downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_gradient_alpha() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
span_gradient_alpha(interpolator_type& inter,
|
||||
const GradientF& gradient_function,
|
||||
AlphaF alpha_function,
|
||||
double d1, double d2) :
|
||||
m_interpolator(&inter),
|
||||
m_gradient_function(&gradient_function),
|
||||
m_alpha_function(alpha_function),
|
||||
m_d1(int(d1 * gradient_subpixel_size)),
|
||||
m_d2(int(d2 * gradient_subpixel_size))
|
||||
{}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
interpolator_type& interpolator() { return *m_interpolator; }
|
||||
const GradientF& gradient_function() const { return *m_gradient_function; }
|
||||
const AlphaF alpha_function() const { return m_alpha_function; }
|
||||
double d1() const { return double(m_d1) / gradient_subpixel_size; }
|
||||
double d2() const { return double(m_d2) / gradient_subpixel_size; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void interpolator(interpolator_type& i) { m_interpolator = &i; }
|
||||
void gradient_function(const GradientF& gf) { m_gradient_function = &gf; }
|
||||
void alpha_function(AlphaF af) { m_alpha_function = af; }
|
||||
void d1(double v) { m_d1 = int(v * gradient_subpixel_size); }
|
||||
void d2(double v) { m_d2 = int(v * gradient_subpixel_size); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void convert(color_type* span, int x, int y, unsigned len)
|
||||
{
|
||||
int dd = m_d2 - m_d1;
|
||||
if(dd < 1) dd = 1;
|
||||
m_interpolator->begin(x+0.5, y+0.5, len);
|
||||
do
|
||||
{
|
||||
m_interpolator->coordinates(&x, &y);
|
||||
int d = m_gradient_function->calculate(x >> downscale_shift,
|
||||
y >> downscale_shift, dd);
|
||||
d = ((d - m_d1) << base_shift) / dd;
|
||||
if(d < 0) d = 0;
|
||||
if(d > base_mask) d = base_mask;
|
||||
span->a = m_alpha_function[d];
|
||||
++span;
|
||||
++(*m_interpolator);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
private:
|
||||
interpolator_type* m_interpolator;
|
||||
const GradientF* m_gradient_function;
|
||||
AlphaF m_alpha_function;
|
||||
int m_d1;
|
||||
int m_d2;
|
||||
};
|
||||
|
||||
|
||||
//=======================================================gradient_alpha_x
|
||||
template<class ColorT> struct gradient_alpha_x
|
||||
{
|
||||
typedef typename ColorT::alpha_type alpha_type;
|
||||
alpha_type operator [] (alpha_type x) const { return x; }
|
||||
};
|
||||
|
||||
//====================================================gradient_alpha_x_u8
|
||||
struct gradient_alpha_x_u8
|
||||
{
|
||||
typedef int8u alpha_type;
|
||||
alpha_type operator [] (alpha_type x) const { return x; }
|
||||
};
|
||||
|
||||
//==========================================gradient_alpha_one_munus_x_u8
|
||||
struct gradient_alpha_one_munus_x_u8
|
||||
{
|
||||
typedef int8u alpha_type;
|
||||
alpha_type operator [] (alpha_type x) const { return 255-x; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -52,19 +52,35 @@ namespace agg
|
||||
m_src(&src),
|
||||
m_back_color(back_color),
|
||||
m_interpolator(&interpolator),
|
||||
m_filter(filter)
|
||||
m_filter(filter),
|
||||
m_dx_dbl(0.5),
|
||||
m_dy_dbl(0.5),
|
||||
m_dx_int(image_subpixel_size / 2),
|
||||
m_dy_int(image_subpixel_size / 2)
|
||||
{}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
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; }
|
||||
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; }
|
||||
int filter_dx_int() const { return m_dx_int; }
|
||||
int filter_dy_int() const { return m_dy_int; }
|
||||
double filter_dx_dbl() const { return m_dx_dbl; }
|
||||
double filter_dy_dbl() const { return m_dy_dbl; }
|
||||
|
||||
//----------------------------------------------------------------
|
||||
void 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; }
|
||||
void filter_offset(double dx, double dy)
|
||||
{
|
||||
m_dx_dbl = dx;
|
||||
m_dy_dbl = dy;
|
||||
m_dx_int = int(dx * image_subpixel_size);
|
||||
m_dy_int = int(dy * image_subpixel_size);
|
||||
}
|
||||
void filter_offset(double d) { filter_offset(d, d); }
|
||||
|
||||
//----------------------------------------------------------------
|
||||
interpolator_type& interpolator() { return *m_interpolator; }
|
||||
@@ -75,6 +91,69 @@ namespace agg
|
||||
color_type m_back_color;
|
||||
interpolator_type* m_interpolator;
|
||||
const image_filter_base* m_filter;
|
||||
double m_dx_dbl;
|
||||
double m_dy_dbl;
|
||||
unsigned m_dx_int;
|
||||
unsigned m_dy_int;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------remainder_unsigned
|
||||
class remainder_unsigned
|
||||
{
|
||||
public:
|
||||
remainder_unsigned(unsigned size) :
|
||||
m_size(size),
|
||||
m_add(size * (0x3FFFFFFF / size))
|
||||
{}
|
||||
|
||||
unsigned operator () (int v) const
|
||||
{
|
||||
return (unsigned(v) + m_add) % m_size;
|
||||
}
|
||||
private:
|
||||
unsigned m_size;
|
||||
unsigned m_add;
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------remainder_pow2
|
||||
class remainder_pow2
|
||||
{
|
||||
public:
|
||||
remainder_pow2(unsigned size)
|
||||
{
|
||||
m_mask = 1;
|
||||
while(m_mask < size) m_mask = (m_mask << 1) | 1;
|
||||
m_mask >>= 1;
|
||||
}
|
||||
unsigned operator () (int v) const { return unsigned(v) & m_mask; }
|
||||
private:
|
||||
unsigned m_mask;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------remainder_auto_pow2
|
||||
class remainder_auto_pow2
|
||||
{
|
||||
public:
|
||||
remainder_auto_pow2(unsigned size) :
|
||||
m_size(size),
|
||||
m_add(size * (0x3FFFFFFF / size)),
|
||||
m_mask((m_size & (m_size-1)) ? 0 : m_size-1)
|
||||
{}
|
||||
|
||||
unsigned operator () (int v) const
|
||||
{
|
||||
if(m_mask) return unsigned(v) & m_mask;
|
||||
return (unsigned(v) + m_add) % m_size;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned m_size;
|
||||
unsigned m_add;
|
||||
unsigned m_mask;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -52,7 +52,8 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
color_type* generate(int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x, y, len);
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
int fg[3];
|
||||
int src_alpha;
|
||||
@@ -130,8 +131,8 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
color_type* generate(int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x, y, len);
|
||||
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
int fg[3];
|
||||
int src_alpha;
|
||||
int back_r = base_type::background_color().r;
|
||||
@@ -154,6 +155,9 @@ namespace agg
|
||||
|
||||
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||
|
||||
x_hr -= base_type::filter_dx_int();
|
||||
y_hr -= base_type::filter_dy_int();
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
int weight;
|
||||
@@ -349,7 +353,8 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
color_type* generate(int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x, y, len);
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
int fg[3];
|
||||
int src_alpha;
|
||||
@@ -381,6 +386,9 @@ namespace agg
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
|
||||
x -= base_type::filter_dx_int();
|
||||
y -= base_type::filter_dy_int();
|
||||
|
||||
int x_hr = x;
|
||||
int y_hr = y;
|
||||
|
||||
@@ -502,10 +510,10 @@ namespace agg
|
||||
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;
|
||||
if(fg[0] > src_alpha) fg[0] = src_alpha;
|
||||
if(fg[1] > src_alpha) fg[1] = src_alpha;
|
||||
if(fg[2] > src_alpha) fg[2] = src_alpha;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,8 +61,8 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
color_type* generate(int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x, y, len);
|
||||
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
int fg[3];
|
||||
int src_alpha;
|
||||
int back_r = m_gamma->dir(base_type::background_color().r);
|
||||
@@ -85,6 +85,9 @@ namespace agg
|
||||
|
||||
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||
|
||||
x_hr -= base_type::filter_dx_int();
|
||||
y_hr -= base_type::filter_dy_int();
|
||||
|
||||
int x_lr = x_hr >> image_subpixel_shift;
|
||||
int y_lr = y_hr >> image_subpixel_shift;
|
||||
int weight;
|
||||
@@ -290,8 +293,8 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
color_type* generate(int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x, y, len);
|
||||
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
int fg[3];
|
||||
int src_alpha;
|
||||
int back_r = m_gamma->dir(base_type::background_color().r);
|
||||
@@ -322,6 +325,9 @@ namespace agg
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
|
||||
x -= base_type::filter_dx_int();
|
||||
y -= base_type::filter_dy_int();
|
||||
|
||||
int x_hr = x;
|
||||
int y_hr = y;
|
||||
|
||||
|
||||
@@ -54,7 +54,8 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
color_type* generate(int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x, y, len);
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
int fg[4];
|
||||
|
||||
@@ -139,7 +140,8 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
color_type* generate(int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x, y, len);
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
int fg[4];
|
||||
int back_r = base_type::background_color().r;
|
||||
@@ -162,8 +164,12 @@ namespace agg
|
||||
|
||||
base_type::interpolator().coordinates(&x_hr, &y_hr);
|
||||
|
||||
x_hr -= base_type::filter_dx_int();
|
||||
y_hr -= base_type::filter_dy_int();
|
||||
|
||||
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 &&
|
||||
@@ -176,6 +182,7 @@ namespace agg
|
||||
|
||||
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) *
|
||||
@@ -362,7 +369,8 @@ namespace agg
|
||||
//--------------------------------------------------------------------
|
||||
color_type* generate(int x, int y, unsigned len)
|
||||
{
|
||||
base_type::interpolator().begin(x, y, len);
|
||||
base_type::interpolator().begin(x + base_type::filter_dx_dbl(),
|
||||
y + base_type::filter_dy_dbl(), len);
|
||||
|
||||
int fg[4];
|
||||
|
||||
@@ -394,6 +402,9 @@ namespace agg
|
||||
{
|
||||
base_type::interpolator().coordinates(&x, &y);
|
||||
|
||||
x -= base_type::filter_dx_int();
|
||||
y -= base_type::filter_dy_int();
|
||||
|
||||
int x_hr = x;
|
||||
int y_hr = y;
|
||||
|
||||
@@ -446,10 +457,10 @@ namespace agg
|
||||
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;
|
||||
if(fg[Order::A] > 255) fg[Order::A] = 255;
|
||||
if(fg[Order::R] > fg[Order::A]) fg[Order::R] = fg[Order::A];
|
||||
if(fg[Order::G] > fg[Order::A]) fg[Order::G] = fg[Order::A];
|
||||
if(fg[Order::B] > fg[Order::A]) fg[Order::B] = fg[Order::A];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -517,10 +528,10 @@ namespace agg
|
||||
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;
|
||||
if(fg[Order::A] > 255) fg[Order::A] = 255;
|
||||
if(fg[Order::R] > fg[Order::A]) fg[Order::R] = fg[Order::A];
|
||||
if(fg[Order::G] > fg[Order::A]) fg[Order::G] = fg[Order::A];
|
||||
if(fg[Order::B] > fg[Order::A]) fg[Order::B] = fg[Order::A];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,12 +141,25 @@ namespace agg
|
||||
*y = (*y - m_dy1) / m_ky + m_wy1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
double scale_x() const
|
||||
{
|
||||
return m_kx;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
double scale_y() const
|
||||
{
|
||||
return m_ky;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
double scale() const
|
||||
{
|
||||
return (m_kx + m_ky) * 0.5;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
unsigned byte_size() const
|
||||
{
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
#ifndef AGG_VCGEN_CONTOUR_INCLUDED
|
||||
#define AGG_VCGEN_CONTOUR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vertex_sequence.h"
|
||||
#include "agg_math_stroke.h"
|
||||
#include "agg_vertex_iterator.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
@@ -33,22 +33,32 @@ namespace agg
|
||||
initial,
|
||||
ready,
|
||||
outline,
|
||||
add_point,
|
||||
end_poly
|
||||
out_vertices,
|
||||
end_poly,
|
||||
stop
|
||||
};
|
||||
|
||||
public:
|
||||
typedef vertex_sequence<vertex_dist, 6> vertex_storage;
|
||||
typedef pod_deque<point_type, 6> coord_storage;
|
||||
|
||||
vcgen_contour();
|
||||
|
||||
void line_join(line_join_e lj) { m_line_join = lj; }
|
||||
void inner_line_join(line_join_e lj) { m_inner_line_join = lj; }
|
||||
void width(double w) { m_width = w * 0.5; }
|
||||
void miter_limit(double ml) { m_miter_limit = ml; }
|
||||
void miter_limit_theta(double t);
|
||||
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
|
||||
void approximation_scale(double as) { m_approx_scale = as; }
|
||||
void auto_detect_orientation(bool v) { m_auto_detect = v; }
|
||||
|
||||
line_join_e line_join() const { return m_line_join; }
|
||||
line_join_e inner_line_join() const { return m_inner_line_join; }
|
||||
double width() const { return m_width * 2.0; }
|
||||
double miter_limit() const { return m_miter_limit; }
|
||||
double inner_miter_limit() const { return m_inner_miter_limit; }
|
||||
double approximation_scale() const { return m_approx_scale; }
|
||||
bool auto_detect_orientation() const { return m_auto_detect; }
|
||||
|
||||
// Generator interface
|
||||
@@ -63,24 +73,22 @@ namespace agg
|
||||
vcgen_contour(const vcgen_contour&);
|
||||
const vcgen_contour& operator = (const vcgen_contour&);
|
||||
|
||||
bool calc_miter(const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2);
|
||||
|
||||
vertex_storage m_src_vertices;
|
||||
coord_storage m_out_vertices;
|
||||
double m_width;
|
||||
line_join_e m_line_join;
|
||||
line_join_e m_inner_line_join;
|
||||
double m_approx_scale;
|
||||
double m_abs_width;
|
||||
double m_signed_width;
|
||||
double m_miter_limit;
|
||||
double m_inner_miter_limit;
|
||||
status_e m_status;
|
||||
unsigned m_src_vertex;
|
||||
unsigned m_out_vertex;
|
||||
unsigned m_closed;
|
||||
unsigned m_orientation;
|
||||
bool m_auto_detect;
|
||||
double m_x1;
|
||||
double m_y1;
|
||||
double m_x2;
|
||||
double m_y2;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -16,16 +16,13 @@
|
||||
#ifndef AGG_VCGEN_STROKE_INCLUDED
|
||||
#define AGG_VCGEN_STROKE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vertex_sequence.h"
|
||||
#include "agg_math_stroke.h"
|
||||
#include "agg_vertex_iterator.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
// Minimal angle to calculate round joins
|
||||
const double vcgen_stroke_theta = 1e-10; //----vcgen_stroke_theta
|
||||
|
||||
//============================================================vcgen_stroke
|
||||
//
|
||||
// See Implementation agg_vcgen_stroke.cpp
|
||||
@@ -50,48 +47,28 @@ namespace agg
|
||||
};
|
||||
|
||||
public:
|
||||
enum line_cap_e
|
||||
{
|
||||
butt_cap,
|
||||
square_cap,
|
||||
round_cap
|
||||
};
|
||||
|
||||
enum line_join_e
|
||||
{
|
||||
miter_join,
|
||||
miter_join_revert,
|
||||
round_join,
|
||||
bevel_join
|
||||
};
|
||||
|
||||
struct coord_type
|
||||
{
|
||||
double x, y;
|
||||
|
||||
coord_type() {}
|
||||
coord_type(double x_, double y_) : x(x_), y(y_) {}
|
||||
};
|
||||
|
||||
|
||||
typedef vertex_sequence<vertex_dist, 6> vertex_storage;
|
||||
typedef pod_deque<coord_type, 6> coord_storage;
|
||||
typedef pod_deque<point_type, 6> coord_storage;
|
||||
|
||||
vcgen_stroke();
|
||||
|
||||
void line_cap(line_cap_e lc) { m_line_cap = lc; }
|
||||
void line_join(line_join_e lj) { m_line_join = lj; }
|
||||
void inner_line_join(line_join_e lj) { m_inner_line_join = lj; }
|
||||
|
||||
line_cap_e line_cap() const { return m_line_cap; }
|
||||
line_join_e line_join() const { return m_line_join; }
|
||||
line_join_e inner_line_join() const { return m_inner_line_join; }
|
||||
|
||||
void width(double w) { m_width = w * 0.5; }
|
||||
void miter_limit(double ml) { m_miter_limit = ml; }
|
||||
void miter_limit_theta(double t);
|
||||
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
|
||||
void approximation_scale(double as) { m_approx_scale = as; }
|
||||
|
||||
double width() const { return m_width * 2.0; }
|
||||
double miter_limit() const { return m_miter_limit; }
|
||||
double inner_miter_limit() const { return m_inner_miter_limit; }
|
||||
double approximation_scale() const { return m_approx_scale; }
|
||||
|
||||
void shorten(double s) { m_shorten = s; }
|
||||
@@ -114,34 +91,16 @@ namespace agg
|
||||
vcgen_stroke(const vcgen_stroke&);
|
||||
const vcgen_stroke& operator = (const vcgen_stroke&);
|
||||
|
||||
void calc_join(const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double len1, double len2);
|
||||
|
||||
void calc_miter(const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
bool revert_flag);
|
||||
|
||||
void calc_arc(double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2);
|
||||
|
||||
void calc_cap(const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
double len);
|
||||
|
||||
vertex_storage m_src_vertices;
|
||||
coord_storage m_out_vertices;
|
||||
double m_width;
|
||||
double m_miter_limit;
|
||||
double m_inner_miter_limit;
|
||||
double m_approx_scale;
|
||||
double m_shorten;
|
||||
line_cap_e m_line_cap;
|
||||
line_join_e m_line_join;
|
||||
line_join_e m_inner_line_join;
|
||||
unsigned m_closed;
|
||||
status_e m_status;
|
||||
status_e m_prev_status;
|
||||
|
||||
@@ -54,6 +54,9 @@ namespace agg
|
||||
double x2() const { return m_clip_box.x2; }
|
||||
double y2() const { return m_clip_box.y2; }
|
||||
|
||||
static bool auto_close() { return true; }
|
||||
static bool auto_unclose() { return false; }
|
||||
|
||||
void reset();
|
||||
void move_to(double x, double y);
|
||||
void line_to(double x, double y);
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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_VPGEN_CLIP_POLYLINE_INCLUDED
|
||||
#define AGG_VPGEN_CLIP_POLYLINE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//======================================================vpgen_clip_polyline
|
||||
//
|
||||
// See Implementation agg_vpgen_clip_polyline.cpp
|
||||
//
|
||||
class vpgen_clip_polyline
|
||||
{
|
||||
public:
|
||||
vpgen_clip_polyline() :
|
||||
m_clip_box(0, 0, 1, 1),
|
||||
m_x1(0),
|
||||
m_y1(0),
|
||||
m_f1(0),
|
||||
m_x2(0),
|
||||
m_y2(0),
|
||||
m_f2(0),
|
||||
m_num_vertices(0),
|
||||
m_vertex(0)
|
||||
{
|
||||
}
|
||||
|
||||
void clip_box(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
m_clip_box.x1 = x1;
|
||||
m_clip_box.y1 = y1;
|
||||
m_clip_box.x2 = x2;
|
||||
m_clip_box.y2 = y2;
|
||||
m_clip_box.normalize();
|
||||
}
|
||||
|
||||
|
||||
double x1() const { return m_clip_box.x1; }
|
||||
double y1() const { return m_clip_box.y1; }
|
||||
double x2() const { return m_clip_box.x2; }
|
||||
double y2() const { return m_clip_box.y2; }
|
||||
|
||||
static bool auto_close() { return false; }
|
||||
static bool auto_unclose() { return true; }
|
||||
|
||||
void reset();
|
||||
void move_to(double x, double y);
|
||||
void line_to(double x, double y);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
enum clipping_flags_def
|
||||
{
|
||||
clip_x1 = 1,
|
||||
clip_x2 = 2,
|
||||
clip_y1 = 4,
|
||||
clip_y2 = 8
|
||||
};
|
||||
|
||||
// Determine the clipping code of the vertex according to the
|
||||
// Cyrus-Beck line clipping algorithm
|
||||
//--------------------------------------------------------------------
|
||||
unsigned clipping_flags_x(double x)
|
||||
{
|
||||
unsigned f = 0;
|
||||
if(x < m_clip_box.x1) f |= clip_x1;
|
||||
if(x > m_clip_box.x2) f |= clip_x2;
|
||||
return f;
|
||||
}
|
||||
|
||||
unsigned clipping_flags_y(double y)
|
||||
{
|
||||
unsigned f = 0;
|
||||
if(y < m_clip_box.y1) f |= clip_y1;
|
||||
if(y > m_clip_box.y2) f |= clip_y2;
|
||||
return f;
|
||||
}
|
||||
|
||||
unsigned clipping_flags(double x, double y)
|
||||
{
|
||||
return clipping_flags_x(x) | clipping_flags_y(y);
|
||||
}
|
||||
|
||||
bool move_point(double& x, double& y, unsigned& flags);
|
||||
void clip_line_segment();
|
||||
|
||||
private:
|
||||
rect_d m_clip_box;
|
||||
double m_x1;
|
||||
double m_y1;
|
||||
unsigned m_f1;
|
||||
double m_x2;
|
||||
double m_y2;
|
||||
unsigned m_f2;
|
||||
double m_x[2];
|
||||
double m_y[2];
|
||||
unsigned m_cmd[2];
|
||||
unsigned m_num_vertices;
|
||||
unsigned m_vertex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -34,11 +34,12 @@ namespace agg
|
||||
void approximation_scale(double s) { m_approximation_scale = s; }
|
||||
double approximation_scale() const { return m_approximation_scale; }
|
||||
|
||||
void reset() { m_cmd = path_cmd_stop; }
|
||||
static bool auto_close() { return false; }
|
||||
static bool auto_unclose() { return false; }
|
||||
|
||||
void reset() { m_cmd = path_cmd_stop; }
|
||||
void move_to(double x, double y);
|
||||
void line_to(double x, double y);
|
||||
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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 bezier_ctrl_impl, bezier_ctrl
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BEZIER_CTRL_INCLUDED
|
||||
#define AGG_BEZIER_CTRL_INCLUDED
|
||||
|
||||
#include "agg_math.h"
|
||||
#include "agg_ellipse.h"
|
||||
#include "agg_trans_affine.h"
|
||||
#include "agg_color_rgba.h"
|
||||
#include "agg_conv_stroke.h"
|
||||
#include "agg_conv_curve.h"
|
||||
#include "agg_polygon_ctrl.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//--------------------------------------------------------bezier_ctrl_impl
|
||||
class bezier_ctrl_impl : public ctrl
|
||||
{
|
||||
public:
|
||||
bezier_ctrl_impl();
|
||||
|
||||
void curve(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4);
|
||||
curve4& curve();
|
||||
|
||||
double x1() const { return m_poly.xn(0); }
|
||||
double y1() const { return m_poly.yn(0); }
|
||||
double x2() const { return m_poly.xn(1); }
|
||||
double y2() const { return m_poly.yn(1); }
|
||||
double x3() const { return m_poly.xn(2); }
|
||||
double y3() const { return m_poly.yn(2); }
|
||||
double x4() const { return m_poly.xn(3); }
|
||||
double y4() const { return m_poly.yn(3); }
|
||||
|
||||
void line_width(double w) { m_stroke.width(w); }
|
||||
double line_width() const { return m_stroke.width(); }
|
||||
|
||||
void point_radius(double r) { m_poly.point_radius(r); }
|
||||
double point_radius() const { return m_poly.point_radius(); }
|
||||
|
||||
virtual bool in_rect(double x, double y) const;
|
||||
virtual bool on_mouse_button_down(double x, double y);
|
||||
virtual bool on_mouse_button_up(double x, double y);
|
||||
virtual bool on_mouse_move(double x, double y, bool button_flag);
|
||||
virtual bool on_arrow_keys(bool left, bool right, bool down, bool up);
|
||||
|
||||
// Vertex source interface
|
||||
unsigned num_paths() { return 7; };
|
||||
void rewind(unsigned id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
|
||||
private:
|
||||
curve4 m_curve;
|
||||
ellipse m_ellipse;
|
||||
conv_stroke<curve4> m_stroke;
|
||||
polygon_ctrl_impl m_poly;
|
||||
unsigned m_idx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------bezier_ctrl
|
||||
template<class ColorT> class bezier_ctrl : public bezier_ctrl_impl
|
||||
{
|
||||
public:
|
||||
bezier_ctrl() :
|
||||
m_color(rgba(0.0, 0.0, 0.0))
|
||||
{
|
||||
}
|
||||
|
||||
void line_color(const ColorT& c) { m_color = c; }
|
||||
const ColorT& color(unsigned i) const { return m_color; }
|
||||
|
||||
private:
|
||||
bezier_ctrl(const bezier_ctrl<ColorT>&);
|
||||
const bezier_ctrl<ColorT>& operator = (const bezier_ctrl<ColorT>&);
|
||||
|
||||
ColorT m_color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace agg
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
virtual ~ctrl() {}
|
||||
ctrl(double x1, double y1, double x2, double y2, bool flip_y) :
|
||||
m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2),
|
||||
m_flip_y(flip_y),
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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 polygon_ctrl_impl, polygon_ctrl
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef POLYGON_CTRL_INCLUDED
|
||||
#define POLYGON_CTRL_INCLUDED
|
||||
|
||||
#include "agg_conv_stroke.h"
|
||||
#include "agg_ellipse.h"
|
||||
#include "agg_color_rgba.h"
|
||||
#include "agg_ctrl.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
class simple_polygon_vertex_source
|
||||
{
|
||||
public:
|
||||
simple_polygon_vertex_source(const double* polygon, unsigned np,
|
||||
bool roundoff = false,
|
||||
bool close = true) :
|
||||
m_polygon(polygon),
|
||||
m_num_points(np),
|
||||
m_vertex(0),
|
||||
m_roundoff(roundoff),
|
||||
m_close(close)
|
||||
{
|
||||
}
|
||||
|
||||
void close(bool f) { m_close = f; }
|
||||
bool close() const { return m_close; }
|
||||
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_vertex = 0;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_vertex > m_num_points) return path_cmd_stop;
|
||||
if(m_vertex == m_num_points)
|
||||
{
|
||||
++m_vertex;
|
||||
return path_cmd_end_poly | (m_close ? path_flags_close : 0);
|
||||
}
|
||||
*x = m_polygon[m_vertex * 2];
|
||||
*y = m_polygon[m_vertex * 2 + 1];
|
||||
if(m_roundoff)
|
||||
{
|
||||
*x = floor(*x) + 0.5;
|
||||
*y = floor(*y) + 0.5;
|
||||
}
|
||||
++m_vertex;
|
||||
return (m_vertex == 1) ? path_cmd_move_to : path_cmd_line_to;
|
||||
}
|
||||
|
||||
private:
|
||||
const double* m_polygon;
|
||||
unsigned m_num_points;
|
||||
unsigned m_vertex;
|
||||
bool m_roundoff;
|
||||
bool m_close;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class polygon_ctrl_impl : public ctrl
|
||||
{
|
||||
public:
|
||||
~polygon_ctrl_impl();
|
||||
polygon_ctrl_impl(unsigned np, double point_radius=5);
|
||||
|
||||
unsigned num_points() const { return m_num_points; }
|
||||
double xn(unsigned n) const { return m_polygon[n * 2]; }
|
||||
double yn(unsigned n) const { return m_polygon[n * 2 + 1]; }
|
||||
double& xn(unsigned n) { return m_polygon[n * 2]; }
|
||||
double& yn(unsigned n) { return m_polygon[n * 2 + 1]; }
|
||||
|
||||
const double* polygon() const { return m_polygon; }
|
||||
|
||||
void line_width(double w) { m_stroke.width(w); }
|
||||
double line_width() const { return m_stroke.width(); }
|
||||
|
||||
void point_radius(double r) { m_point_radius = r; }
|
||||
double point_radius() const { return m_point_radius; }
|
||||
|
||||
void in_polygon_check(bool f) { m_in_polygon_check = f; }
|
||||
bool in_polygon_check() const { return m_in_polygon_check; }
|
||||
|
||||
void close(bool f) { m_vs.close(f); }
|
||||
bool close() const { return m_vs.close(); }
|
||||
|
||||
// Vertex source interface
|
||||
unsigned num_paths() { return 1; }
|
||||
void rewind(unsigned id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
virtual bool in_rect(double x, double y) const;
|
||||
virtual bool on_mouse_button_down(double x, double y);
|
||||
virtual bool on_mouse_button_up(double x, double y);
|
||||
virtual bool on_mouse_move(double x, double y, bool button_flag);
|
||||
virtual bool on_arrow_keys(bool left, bool right, bool down, bool up);
|
||||
|
||||
|
||||
private:
|
||||
bool check_edge(unsigned i, double x, double y) const;
|
||||
bool point_in_polygon(double x, double y) const;
|
||||
|
||||
double* m_polygon;
|
||||
unsigned m_num_points;
|
||||
int m_node;
|
||||
int m_edge;
|
||||
simple_polygon_vertex_source m_vs;
|
||||
conv_stroke<simple_polygon_vertex_source> m_stroke;
|
||||
ellipse m_ellipse;
|
||||
double m_point_radius;
|
||||
unsigned m_status;
|
||||
double m_dx;
|
||||
double m_dy;
|
||||
bool m_in_polygon_check;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------polygon_ctrl
|
||||
template<class ColorT> class polygon_ctrl : public polygon_ctrl_impl
|
||||
{
|
||||
public:
|
||||
polygon_ctrl(unsigned np, double point_radius=5) :
|
||||
polygon_ctrl_impl(np, point_radius),
|
||||
m_color(rgba(0.0, 0.0, 0.0))
|
||||
{
|
||||
}
|
||||
|
||||
void line_color(const ColorT& c) { m_color = c; }
|
||||
const ColorT& color(unsigned i) const { return m_color; }
|
||||
|
||||
private:
|
||||
polygon_ctrl(const polygon_ctrl<ColorT>&);
|
||||
const polygon_ctrl<ColorT>& operator = (const polygon_ctrl<ColorT>&);
|
||||
|
||||
ColorT m_color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -58,8 +58,8 @@ namespace agg
|
||||
|
||||
void active_point(int i);
|
||||
|
||||
const double* spline() const { return m_spline_values; }
|
||||
const unsigned char* spline8() const { return m_spline_values8; }
|
||||
const double* spline() const { return m_spline_values; }
|
||||
const int8u* spline8() const { return m_spline_values8; }
|
||||
double value(double x) const;
|
||||
void value(unsigned idx, double y);
|
||||
void point(unsigned idx, double x, double y);
|
||||
@@ -87,7 +87,7 @@ namespace agg
|
||||
double m_yp[32];
|
||||
bspline m_spline;
|
||||
double m_spline_values[256];
|
||||
unsigned char m_spline_values8[256];
|
||||
int8u m_spline_values8[256];
|
||||
double m_border_width;
|
||||
double m_border_extra;
|
||||
double m_curve_width;
|
||||
|
||||
Reference in New Issue
Block a user