WIP: SVG import & rasterization
Updated AntiGrain (agg) library to 2.5 Added agg_svg library from AntiGrain 2.5 added src/slic3r/Utils/SVGImport.cpp/hpp
This commit is contained in:
parent
a2478b7faa
commit
9b15908a47
59 changed files with 10646 additions and 3586 deletions
|
@ -1,6 +1,7 @@
|
|||
project(Slic3r-native)
|
||||
|
||||
add_subdirectory(admesh)
|
||||
add_subdirectory(agg_svg)
|
||||
add_subdirectory(avrdude)
|
||||
# boost/nowide
|
||||
add_subdirectory(boost)
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
Anti-Grain Geometry - Version 2.4
|
||||
Copyright (C) 2002-2005 Maxim Shemanarev (McSeem)
|
||||
Anti-Grain Geometry (AGG) - Version 2.5
|
||||
A high quality rendering engine for C++
|
||||
Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
|
|
21
src/agg/README
Normal file
21
src/agg/README
Normal file
|
@ -0,0 +1,21 @@
|
|||
Anti-Grain Geometry (AGG) - Version 2.5
|
||||
A high quality rendering engine for C++
|
||||
Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
Contact: mcseem@antigrain.com
|
||||
mcseemagg@yahoo.com
|
||||
http://antigrain.com
|
||||
|
||||
AGG is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
AGG is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with AGG; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
|
@ -1,2 +0,0 @@
|
|||
2.4
|
||||
svn revision 128
|
|
@ -1,17 +1,27 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_ARRAY_INCLUDED
|
||||
#define AGG_ARRAY_INCLUDED
|
||||
|
||||
|
|
|
@ -1,22 +1,31 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BASICS_INCLUDED
|
||||
#define AGG_BASICS_INCLUDED
|
||||
|
||||
#include <cmath>
|
||||
#include <math.h>
|
||||
#include "agg_config.h"
|
||||
|
||||
//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR
|
||||
|
@ -143,18 +152,10 @@ namespace agg
|
|||
__asm mov eax, dword ptr [t]
|
||||
}
|
||||
#pragma warning(pop)
|
||||
AGG_INLINE int ifloor(double v)
|
||||
{
|
||||
return int(floor(v));
|
||||
}
|
||||
AGG_INLINE unsigned ufloor(double v) //-------ufloor
|
||||
{
|
||||
return unsigned(floor(v));
|
||||
}
|
||||
AGG_INLINE int iceil(double v)
|
||||
{
|
||||
return int(ceil(v));
|
||||
}
|
||||
AGG_INLINE unsigned uceil(double v) //--------uceil
|
||||
{
|
||||
return unsigned(ceil(v));
|
||||
|
@ -168,18 +169,10 @@ namespace agg
|
|||
{
|
||||
return unsigned(v);
|
||||
}
|
||||
AGG_INLINE int ifloor(double v)
|
||||
{
|
||||
return int(floor(v));
|
||||
}
|
||||
AGG_INLINE unsigned ufloor(double v)
|
||||
{
|
||||
return unsigned(floor(v));
|
||||
}
|
||||
AGG_INLINE int iceil(double v)
|
||||
{
|
||||
return int(ceil(v));
|
||||
}
|
||||
AGG_INLINE unsigned uceil(double v)
|
||||
{
|
||||
return unsigned(ceil(v));
|
||||
|
@ -193,19 +186,10 @@ namespace agg
|
|||
{
|
||||
return unsigned(v + 0.5);
|
||||
}
|
||||
AGG_INLINE int ifloor(double v)
|
||||
{
|
||||
int i = int(v);
|
||||
return i - (i > v);
|
||||
}
|
||||
AGG_INLINE unsigned ufloor(double v)
|
||||
{
|
||||
return unsigned(v);
|
||||
}
|
||||
AGG_INLINE int iceil(double v)
|
||||
{
|
||||
return int(ceil(v));
|
||||
}
|
||||
AGG_INLINE unsigned uceil(double v)
|
||||
{
|
||||
return unsigned(ceil(v));
|
||||
|
@ -228,7 +212,7 @@ namespace agg
|
|||
{
|
||||
AGG_INLINE static unsigned mul(unsigned a, unsigned b)
|
||||
{
|
||||
unsigned q = a * b + (1 << (Shift-1));
|
||||
register unsigned q = a * b + (1 << (Shift-1));
|
||||
return (q + (q >> Shift)) >> Shift;
|
||||
}
|
||||
};
|
||||
|
@ -254,7 +238,7 @@ namespace agg
|
|||
{
|
||||
poly_subpixel_shift = 8, //----poly_subpixel_shift
|
||||
poly_subpixel_scale = 1<<poly_subpixel_shift, //----poly_subpixel_scale
|
||||
poly_subpixel_mask = poly_subpixel_scale-1 //----poly_subpixel_mask
|
||||
poly_subpixel_mask = poly_subpixel_scale-1, //----poly_subpixel_mask
|
||||
};
|
||||
|
||||
//----------------------------------------------------------filling_rule_e
|
||||
|
@ -321,12 +305,6 @@ namespace agg
|
|||
{
|
||||
return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
|
||||
}
|
||||
|
||||
bool overlaps(const self_type& r) const
|
||||
{
|
||||
return !(r.x1 > x2 || r.x2 < x1
|
||||
|| r.y1 > y2 || r.y2 < y1);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------intersect_rectangles
|
||||
|
@ -551,22 +529,9 @@ namespace agg
|
|||
//------------------------------------------------------------is_equal_eps
|
||||
template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon)
|
||||
{
|
||||
bool neg1 = v1 < 0.0;
|
||||
bool neg2 = v2 < 0.0;
|
||||
|
||||
if (neg1 != neg2)
|
||||
return std::fabs(v1) < epsilon && std::fabs(v2) < epsilon;
|
||||
|
||||
int int1, int2;
|
||||
std::frexp(v1, &int1);
|
||||
std::frexp(v2, &int2);
|
||||
int min12 = int1 < int2 ? int1 : int2;
|
||||
|
||||
v1 = std::ldexp(v1, -min12);
|
||||
v2 = std::ldexp(v2, -min12);
|
||||
|
||||
return std::fabs(v1 - v2) < epsilon;
|
||||
return fabs(v1 - v2) <= double(epsilon);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,21 +1,25 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e.,
|
||||
// 4, 7, 10, or 13 vertices.
|
||||
//
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BEZIER_ARC_INCLUDED
|
||||
|
@ -68,7 +72,7 @@ namespace agg
|
|||
*x = m_vertices[m_vertex];
|
||||
*y = m_vertices[m_vertex + 1];
|
||||
m_vertex += 2;
|
||||
return (m_vertex == 2) ? unsigned(path_cmd_move_to) : m_cmd;
|
||||
return (m_vertex == 2) ? path_cmd_move_to : m_cmd;
|
||||
}
|
||||
|
||||
// Supplemantary functions. num_vertices() actually returns doubled
|
||||
|
|
122
src/agg/agg_bounding_rect.h
Normal file
122
src/agg/agg_bounding_rect.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BOUNDING_RECT_INCLUDED
|
||||
#define AGG_BOUNDING_RECT_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------bounding_rect
|
||||
template<class VertexSource, class GetId, class CoordT>
|
||||
bool bounding_rect(VertexSource& vs, GetId& gi,
|
||||
unsigned start, unsigned num,
|
||||
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
|
||||
{
|
||||
unsigned i;
|
||||
double x;
|
||||
double y;
|
||||
bool first = true;
|
||||
|
||||
*x1 = CoordT(1);
|
||||
*y1 = CoordT(1);
|
||||
*x2 = CoordT(0);
|
||||
*y2 = CoordT(0);
|
||||
|
||||
for(i = 0; i < num; i++)
|
||||
{
|
||||
vs.rewind(gi[start + i]);
|
||||
unsigned cmd;
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(first)
|
||||
{
|
||||
*x1 = CoordT(x);
|
||||
*y1 = CoordT(y);
|
||||
*x2 = CoordT(x);
|
||||
*y2 = CoordT(y);
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(CoordT(x) < *x1) *x1 = CoordT(x);
|
||||
if(CoordT(y) < *y1) *y1 = CoordT(y);
|
||||
if(CoordT(x) > *x2) *x2 = CoordT(x);
|
||||
if(CoordT(y) > *y2) *y2 = CoordT(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return *x1 <= *x2 && *y1 <= *y2;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------bounding_rect_single
|
||||
template<class VertexSource, class CoordT>
|
||||
bool bounding_rect_single(VertexSource& vs, unsigned path_id,
|
||||
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
bool first = true;
|
||||
|
||||
*x1 = CoordT(1);
|
||||
*y1 = CoordT(1);
|
||||
*x2 = CoordT(0);
|
||||
*y2 = CoordT(0);
|
||||
|
||||
vs.rewind(path_id);
|
||||
unsigned cmd;
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(first)
|
||||
{
|
||||
*x1 = CoordT(x);
|
||||
*y1 = CoordT(y);
|
||||
*x2 = CoordT(x);
|
||||
*y2 = CoordT(y);
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(CoordT(x) < *x1) *x1 = CoordT(x);
|
||||
if(CoordT(y) < *y1) *y1 = CoordT(y);
|
||||
if(CoordT(x) > *x2) *x2 = CoordT(x);
|
||||
if(CoordT(y) > *y2) *y2 = CoordT(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
return *x1 <= *x2 && *y1 <= *y2;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,21 +1,27 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Liang-Barsky clipping
|
||||
//
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED
|
||||
#define AGG_CLIP_LIANG_BARSKY_INCLUDED
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -37,7 +37,7 @@
|
|||
// Provides cheaper creation and destruction (no mem allocs):
|
||||
// #define AGG_RENDERING_BUFFER row_accessor<int8u>
|
||||
//
|
||||
// You can still use both of them simultaneously in your applications
|
||||
// You can still use both of them simultaneouslyin your applications
|
||||
// This #define is used only for default rendering_buffer type,
|
||||
// in short hand typedefs like pixfmt_rgba32.
|
||||
|
||||
|
|
166
src/agg/agg_conv_adaptor_vcgen.h
Normal file
166
src/agg/agg_conv_adaptor_vcgen.h
Normal file
|
@ -0,0 +1,166 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_ADAPTOR_VCGEN_INCLUDED
|
||||
#define AGG_CONV_ADAPTOR_VCGEN_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//------------------------------------------------------------null_markers
|
||||
struct null_markers
|
||||
{
|
||||
void remove_all() {}
|
||||
void add_vertex(double, double, unsigned) {}
|
||||
void prepare_src() {}
|
||||
|
||||
void rewind(unsigned) {}
|
||||
unsigned vertex(double*, double*) { return path_cmd_stop; }
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------conv_adaptor_vcgen
|
||||
template<class VertexSource,
|
||||
class Generator,
|
||||
class Markers=null_markers> class conv_adaptor_vcgen
|
||||
{
|
||||
enum status
|
||||
{
|
||||
initial,
|
||||
accumulate,
|
||||
generate
|
||||
};
|
||||
|
||||
public:
|
||||
explicit conv_adaptor_vcgen(VertexSource& source) :
|
||||
m_source(&source),
|
||||
m_status(initial)
|
||||
{}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
Generator& generator() { return m_generator; }
|
||||
const Generator& generator() const { return m_generator; }
|
||||
|
||||
Markers& markers() { return m_markers; }
|
||||
const Markers& markers() const { return m_markers; }
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
m_status = initial;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
// Prohibit copying
|
||||
conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
|
||||
const conv_adaptor_vcgen<VertexSource, Generator, Markers>&
|
||||
operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
Generator m_generator;
|
||||
Markers m_markers;
|
||||
status m_status;
|
||||
unsigned m_last_cmd;
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class Generator, class Markers>
|
||||
unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_stop;
|
||||
bool done = false;
|
||||
while(!done)
|
||||
{
|
||||
switch(m_status)
|
||||
{
|
||||
case initial:
|
||||
m_markers.remove_all();
|
||||
m_last_cmd = m_source->vertex(&m_start_x, &m_start_y);
|
||||
m_status = accumulate;
|
||||
|
||||
case accumulate:
|
||||
if(is_stop(m_last_cmd)) return path_cmd_stop;
|
||||
|
||||
m_generator.remove_all();
|
||||
m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
|
||||
m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
cmd = m_source->vertex(x, y);
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
m_last_cmd = cmd;
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
m_start_x = *x;
|
||||
m_start_y = *y;
|
||||
break;
|
||||
}
|
||||
m_generator.add_vertex(*x, *y, cmd);
|
||||
m_markers.add_vertex(*x, *y, path_cmd_line_to);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_stop(cmd))
|
||||
{
|
||||
m_last_cmd = path_cmd_stop;
|
||||
break;
|
||||
}
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
m_generator.add_vertex(*x, *y, cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_generator.rewind(0);
|
||||
m_status = generate;
|
||||
|
||||
case generate:
|
||||
cmd = m_generator.vertex(x, y);
|
||||
if(is_stop(cmd))
|
||||
{
|
||||
m_status = accumulate;
|
||||
break;
|
||||
}
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
71
src/agg/agg_conv_contour.h
Normal file
71
src/agg/agg_conv_contour.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_CONTOUR_INCLUDED
|
||||
#define AGG_CONV_CONTOUR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vcgen_contour.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------conv_contour
|
||||
template<class VertexSource>
|
||||
struct conv_contour : public conv_adaptor_vcgen<VertexSource, vcgen_contour>
|
||||
{
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_contour> base_type;
|
||||
|
||||
conv_contour(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void line_join(line_join_e lj) { base_type::generator().line_join(lj); }
|
||||
void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
|
||||
void 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(); }
|
||||
inner_join_e inner_join() const { return base_type::generator().inner_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:
|
||||
conv_contour(const conv_contour<VertexSource>&);
|
||||
const conv_contour<VertexSource>&
|
||||
operator = (const conv_contour<VertexSource>&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
206
src/agg/agg_conv_curve.h
Normal file
206
src/agg/agg_conv_curve.h
Normal file
|
@ -0,0 +1,206 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_CURVE_INCLUDED
|
||||
#define AGG_CONV_CURVE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_curves.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
|
||||
//---------------------------------------------------------------conv_curve
|
||||
// Curve converter class. Any path storage can have Bezier curves defined
|
||||
// by their control points. There're two types of curves supported: curve3
|
||||
// and curve4. Curve3 is a conic Bezier curve with 2 endpoints and 1 control
|
||||
// point. Curve4 has 2 control points (4 points in total) and can be used
|
||||
// to interpolate more complicated curves. Curve4, unlike curve3 can be used
|
||||
// to approximate arcs, both circular and elliptical. Curves are approximated
|
||||
// with straight lines and one of the approaches is just to store the whole
|
||||
// sequence of vertices that approximate our curve. It takes additional
|
||||
// memory, and at the same time the consecutive vertices can be calculated
|
||||
// on demand.
|
||||
//
|
||||
// Initially, path storages are not suppose to keep all the vertices of the
|
||||
// curves (although, nothing prevents us from doing so). Instead, path_storage
|
||||
// keeps only vertices, needed to calculate a curve on demand. Those vertices
|
||||
// are marked with special commands. So, if the path_storage contains curves
|
||||
// (which are not real curves yet), and we render this storage directly,
|
||||
// all we will see is only 2 or 3 straight line segments (for curve3 and
|
||||
// curve4 respectively). If we need to see real curves drawn we need to
|
||||
// include this class into the conversion pipeline.
|
||||
//
|
||||
// Class conv_curve recognizes commands path_cmd_curve3 and path_cmd_curve4
|
||||
// and converts these vertices into a move_to/line_to sequence.
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VertexSource,
|
||||
class Curve3=curve3,
|
||||
class Curve4=curve4> class conv_curve
|
||||
{
|
||||
public:
|
||||
typedef Curve3 curve3_type;
|
||||
typedef Curve4 curve4_type;
|
||||
typedef conv_curve<VertexSource, Curve3, Curve4> self_type;
|
||||
|
||||
explicit conv_curve(VertexSource& source) :
|
||||
m_source(&source), m_last_x(0.0), m_last_y(0.0) {}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void approximation_method(curve_approximation_method_e v)
|
||||
{
|
||||
m_curve3.approximation_method(v);
|
||||
m_curve4.approximation_method(v);
|
||||
}
|
||||
|
||||
curve_approximation_method_e approximation_method() const
|
||||
{
|
||||
return m_curve4.approximation_method();
|
||||
}
|
||||
|
||||
void approximation_scale(double s)
|
||||
{
|
||||
m_curve3.approximation_scale(s);
|
||||
m_curve4.approximation_scale(s);
|
||||
}
|
||||
|
||||
double approximation_scale() const
|
||||
{
|
||||
return m_curve4.approximation_scale();
|
||||
}
|
||||
|
||||
void angle_tolerance(double v)
|
||||
{
|
||||
m_curve3.angle_tolerance(v);
|
||||
m_curve4.angle_tolerance(v);
|
||||
}
|
||||
|
||||
double angle_tolerance() const
|
||||
{
|
||||
return m_curve4.angle_tolerance();
|
||||
}
|
||||
|
||||
void cusp_limit(double v)
|
||||
{
|
||||
m_curve3.cusp_limit(v);
|
||||
m_curve4.cusp_limit(v);
|
||||
}
|
||||
|
||||
double cusp_limit() const
|
||||
{
|
||||
return m_curve4.cusp_limit();
|
||||
}
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
conv_curve(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
VertexSource* m_source;
|
||||
double m_last_x;
|
||||
double m_last_y;
|
||||
curve3_type m_curve3;
|
||||
curve4_type m_curve4;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class Curve3, class Curve4>
|
||||
void conv_curve<VertexSource, Curve3, Curve4>::rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
m_last_x = 0.0;
|
||||
m_last_y = 0.0;
|
||||
m_curve3.reset();
|
||||
m_curve4.reset();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class Curve3, class Curve4>
|
||||
unsigned conv_curve<VertexSource, Curve3, Curve4>::vertex(double* x, double* y)
|
||||
{
|
||||
if(!is_stop(m_curve3.vertex(x, y)))
|
||||
{
|
||||
m_last_x = *x;
|
||||
m_last_y = *y;
|
||||
return path_cmd_line_to;
|
||||
}
|
||||
|
||||
if(!is_stop(m_curve4.vertex(x, y)))
|
||||
{
|
||||
m_last_x = *x;
|
||||
m_last_y = *y;
|
||||
return path_cmd_line_to;
|
||||
}
|
||||
|
||||
double ct2_x;
|
||||
double ct2_y;
|
||||
double end_x;
|
||||
double end_y;
|
||||
|
||||
unsigned cmd = m_source->vertex(x, y);
|
||||
switch(cmd)
|
||||
{
|
||||
case path_cmd_curve3:
|
||||
m_source->vertex(&end_x, &end_y);
|
||||
|
||||
m_curve3.init(m_last_x, m_last_y,
|
||||
*x, *y,
|
||||
end_x, end_y);
|
||||
|
||||
m_curve3.vertex(x, y); // First call returns path_cmd_move_to
|
||||
m_curve3.vertex(x, y); // This is the first vertex of the curve
|
||||
cmd = path_cmd_line_to;
|
||||
break;
|
||||
|
||||
case path_cmd_curve4:
|
||||
m_source->vertex(&ct2_x, &ct2_y);
|
||||
m_source->vertex(&end_x, &end_y);
|
||||
|
||||
m_curve4.init(m_last_x, m_last_y,
|
||||
*x, *y,
|
||||
ct2_x, ct2_y,
|
||||
end_x, end_y);
|
||||
|
||||
m_curve4.vertex(x, y); // First call returns path_cmd_move_to
|
||||
m_curve4.vertex(x, y); // This is the first vertex of the curve
|
||||
cmd = path_cmd_line_to;
|
||||
break;
|
||||
}
|
||||
m_last_x = *x;
|
||||
m_last_y = *y;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
79
src/agg/agg_conv_stroke.h
Normal file
79
src/agg/agg_conv_stroke.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_STROKE_INCLUDED
|
||||
#define AGG_CONV_STROKE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vcgen_stroke.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-------------------------------------------------------------conv_stroke
|
||||
template<class VertexSource, class Markers=null_markers>
|
||||
struct conv_stroke :
|
||||
public conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>
|
||||
{
|
||||
typedef Markers marker_type;
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers> base_type;
|
||||
|
||||
conv_stroke(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs)
|
||||
{
|
||||
}
|
||||
|
||||
void line_cap(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_join(inner_join_e ij) { base_type::generator().inner_join(ij); }
|
||||
|
||||
line_cap_e line_cap() const { return base_type::generator().line_cap(); }
|
||||
line_join_e line_join() const { return base_type::generator().line_join(); }
|
||||
inner_join_e inner_join() const { return base_type::generator().inner_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); }
|
||||
double shorten() const { return base_type::generator().shorten(); }
|
||||
|
||||
private:
|
||||
conv_stroke(const conv_stroke<VertexSource, Markers>&);
|
||||
const conv_stroke<VertexSource, Markers>&
|
||||
operator = (const conv_stroke<VertexSource, Markers>&);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,21 +1,27 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// class conv_transform
|
||||
//
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_TRANSFORM_INCLUDED
|
||||
#define AGG_CONV_TRANSFORM_INCLUDED
|
||||
|
||||
|
@ -29,7 +35,7 @@ namespace agg
|
|||
template<class VertexSource, class Transformer=trans_affine> class conv_transform
|
||||
{
|
||||
public:
|
||||
conv_transform(VertexSource& source, Transformer& tr) :
|
||||
conv_transform(VertexSource& source, const Transformer& tr) :
|
||||
m_source(&source), m_trans(&tr) {}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
|
@ -48,7 +54,7 @@ namespace agg
|
|||
return cmd;
|
||||
}
|
||||
|
||||
void transformer(Transformer& tr)
|
||||
void transformer(const Transformer& tr)
|
||||
{
|
||||
m_trans = &tr;
|
||||
}
|
||||
|
@ -59,7 +65,7 @@ namespace agg
|
|||
operator = (const conv_transform<VertexSource>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
Transformer* m_trans;
|
||||
const Transformer* m_trans;
|
||||
};
|
||||
|
||||
|
||||
|
|
701
src/agg/agg_curves.h
Normal file
701
src/agg/agg_curves.h
Normal file
|
@ -0,0 +1,701 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CURVES_INCLUDED
|
||||
#define AGG_CURVES_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
// See Implementation agg_curves.cpp
|
||||
|
||||
//--------------------------------------------curve_approximation_method_e
|
||||
enum curve_approximation_method_e
|
||||
{
|
||||
curve_inc,
|
||||
curve_div
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------curve3_inc
|
||||
class curve3_inc
|
||||
{
|
||||
public:
|
||||
curve3_inc() :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0) { }
|
||||
|
||||
curve3_inc(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3) :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
void reset() { m_num_steps = 0; m_step = -1; }
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3);
|
||||
|
||||
void approximation_method(curve_approximation_method_e) {}
|
||||
curve_approximation_method_e approximation_method() const { return curve_inc; }
|
||||
|
||||
void approximation_scale(double s);
|
||||
double approximation_scale() const;
|
||||
|
||||
void angle_tolerance(double) {}
|
||||
double angle_tolerance() const { return 0.0; }
|
||||
|
||||
void cusp_limit(double) {}
|
||||
double cusp_limit() const { return 0.0; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
int m_num_steps;
|
||||
int m_step;
|
||||
double m_scale;
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
double m_end_x;
|
||||
double m_end_y;
|
||||
double m_fx;
|
||||
double m_fy;
|
||||
double m_dfx;
|
||||
double m_dfy;
|
||||
double m_ddfx;
|
||||
double m_ddfy;
|
||||
double m_saved_fx;
|
||||
double m_saved_fy;
|
||||
double m_saved_dfx;
|
||||
double m_saved_dfy;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------curve3_div
|
||||
class curve3_div
|
||||
{
|
||||
public:
|
||||
curve3_div() :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_count(0)
|
||||
{}
|
||||
|
||||
curve3_div(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3) :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_count(0)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
void reset() { m_points.remove_all(); m_count = 0; }
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3);
|
||||
|
||||
void approximation_method(curve_approximation_method_e) {}
|
||||
curve_approximation_method_e approximation_method() const { return curve_div; }
|
||||
|
||||
void approximation_scale(double s) { m_approximation_scale = s; }
|
||||
double approximation_scale() const { return m_approximation_scale; }
|
||||
|
||||
void angle_tolerance(double a) { m_angle_tolerance = a; }
|
||||
double angle_tolerance() const { return m_angle_tolerance; }
|
||||
|
||||
void cusp_limit(double) {}
|
||||
double cusp_limit() const { return 0.0; }
|
||||
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_count >= m_points.size()) return path_cmd_stop;
|
||||
const point_d& p = m_points[m_count++];
|
||||
*x = p.x;
|
||||
*y = p.y;
|
||||
return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
|
||||
}
|
||||
|
||||
private:
|
||||
void bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3);
|
||||
void recursive_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
unsigned level);
|
||||
|
||||
double m_approximation_scale;
|
||||
double m_distance_tolerance_square;
|
||||
double m_angle_tolerance;
|
||||
unsigned m_count;
|
||||
pod_bvector<point_d> m_points;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------curve4_points
|
||||
struct curve4_points
|
||||
{
|
||||
double cp[8];
|
||||
curve4_points() {}
|
||||
curve4_points(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
|
||||
cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
|
||||
}
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
|
||||
cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
|
||||
}
|
||||
double operator [] (unsigned i) const { return cp[i]; }
|
||||
double& operator [] (unsigned i) { return cp[i]; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------curve4_inc
|
||||
class curve4_inc
|
||||
{
|
||||
public:
|
||||
curve4_inc() :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0) { }
|
||||
|
||||
curve4_inc(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4) :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
|
||||
curve4_inc(const curve4_points& cp) :
|
||||
m_num_steps(0), m_step(0), m_scale(1.0)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void reset() { m_num_steps = 0; m_step = -1; }
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4);
|
||||
|
||||
void init(const curve4_points& cp)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void approximation_method(curve_approximation_method_e) {}
|
||||
curve_approximation_method_e approximation_method() const { return curve_inc; }
|
||||
|
||||
void approximation_scale(double s);
|
||||
double approximation_scale() const;
|
||||
|
||||
void angle_tolerance(double) {}
|
||||
double angle_tolerance() const { return 0.0; }
|
||||
|
||||
void cusp_limit(double) {}
|
||||
double cusp_limit() const { return 0.0; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
int m_num_steps;
|
||||
int m_step;
|
||||
double m_scale;
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
double m_end_x;
|
||||
double m_end_y;
|
||||
double m_fx;
|
||||
double m_fy;
|
||||
double m_dfx;
|
||||
double m_dfy;
|
||||
double m_ddfx;
|
||||
double m_ddfy;
|
||||
double m_dddfx;
|
||||
double m_dddfy;
|
||||
double m_saved_fx;
|
||||
double m_saved_fy;
|
||||
double m_saved_dfx;
|
||||
double m_saved_dfy;
|
||||
double m_saved_ddfx;
|
||||
double m_saved_ddfy;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------catrom_to_bezier
|
||||
inline curve4_points catrom_to_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
// Trans. matrix Catmull-Rom to Bezier
|
||||
//
|
||||
// 0 1 0 0
|
||||
// -1/6 1 1/6 0
|
||||
// 0 1/6 1 -1/6
|
||||
// 0 0 1 0
|
||||
//
|
||||
return curve4_points(
|
||||
x2,
|
||||
y2,
|
||||
(-x1 + 6*x2 + x3) / 6,
|
||||
(-y1 + 6*y2 + y3) / 6,
|
||||
( x2 + 6*x3 - x4) / 6,
|
||||
( y2 + 6*y3 - y4) / 6,
|
||||
x3,
|
||||
y3);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
inline curve4_points
|
||||
catrom_to_bezier(const curve4_points& cp)
|
||||
{
|
||||
return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3],
|
||||
cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------ubspline_to_bezier
|
||||
inline curve4_points ubspline_to_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
// Trans. matrix Uniform BSpline to Bezier
|
||||
//
|
||||
// 1/6 4/6 1/6 0
|
||||
// 0 4/6 2/6 0
|
||||
// 0 2/6 4/6 0
|
||||
// 0 1/6 4/6 1/6
|
||||
//
|
||||
return curve4_points(
|
||||
(x1 + 4*x2 + x3) / 6,
|
||||
(y1 + 4*y2 + y3) / 6,
|
||||
(4*x2 + 2*x3) / 6,
|
||||
(4*y2 + 2*y3) / 6,
|
||||
(2*x2 + 4*x3) / 6,
|
||||
(2*y2 + 4*y3) / 6,
|
||||
(x2 + 4*x3 + x4) / 6,
|
||||
(y2 + 4*y3 + y4) / 6);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
inline curve4_points
|
||||
ubspline_to_bezier(const curve4_points& cp)
|
||||
{
|
||||
return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3],
|
||||
cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------hermite_to_bezier
|
||||
inline curve4_points hermite_to_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
// Trans. matrix Hermite to Bezier
|
||||
//
|
||||
// 1 0 0 0
|
||||
// 1 0 1/3 0
|
||||
// 0 1 0 -1/3
|
||||
// 0 1 0 0
|
||||
//
|
||||
return curve4_points(
|
||||
x1,
|
||||
y1,
|
||||
(3*x1 + x3) / 3,
|
||||
(3*y1 + y3) / 3,
|
||||
(3*x2 - x4) / 3,
|
||||
(3*y2 - y4) / 3,
|
||||
x2,
|
||||
y2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
inline curve4_points
|
||||
hermite_to_bezier(const curve4_points& cp)
|
||||
{
|
||||
return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3],
|
||||
cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------curve4_div
|
||||
class curve4_div
|
||||
{
|
||||
public:
|
||||
curve4_div() :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_cusp_limit(0.0),
|
||||
m_count(0)
|
||||
{}
|
||||
|
||||
curve4_div(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4) :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_cusp_limit(0.0),
|
||||
m_count(0)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
|
||||
curve4_div(const curve4_points& cp) :
|
||||
m_approximation_scale(1.0),
|
||||
m_angle_tolerance(0.0),
|
||||
m_count(0)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void reset() { m_points.remove_all(); m_count = 0; }
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4);
|
||||
|
||||
void init(const curve4_points& cp)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void approximation_method(curve_approximation_method_e) {}
|
||||
|
||||
curve_approximation_method_e approximation_method() const
|
||||
{
|
||||
return curve_div;
|
||||
}
|
||||
|
||||
void approximation_scale(double s) { m_approximation_scale = s; }
|
||||
double approximation_scale() const { return m_approximation_scale; }
|
||||
|
||||
void angle_tolerance(double a) { m_angle_tolerance = a; }
|
||||
double angle_tolerance() const { return m_angle_tolerance; }
|
||||
|
||||
void cusp_limit(double v)
|
||||
{
|
||||
m_cusp_limit = (v == 0.0) ? 0.0 : pi - v;
|
||||
}
|
||||
|
||||
double cusp_limit() const
|
||||
{
|
||||
return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit;
|
||||
}
|
||||
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_count >= m_points.size()) return path_cmd_stop;
|
||||
const point_d& p = m_points[m_count++];
|
||||
*x = p.x;
|
||||
*y = p.y;
|
||||
return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
|
||||
}
|
||||
|
||||
private:
|
||||
void bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4);
|
||||
|
||||
void recursive_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4,
|
||||
unsigned level);
|
||||
|
||||
double m_approximation_scale;
|
||||
double m_distance_tolerance_square;
|
||||
double m_angle_tolerance;
|
||||
double m_cusp_limit;
|
||||
unsigned m_count;
|
||||
pod_bvector<point_d> m_points;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------curve3
|
||||
class curve3
|
||||
{
|
||||
public:
|
||||
curve3() : m_approximation_method(curve_div) {}
|
||||
curve3(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3) :
|
||||
m_approximation_method(curve_div)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_curve_inc.reset();
|
||||
m_curve_div.reset();
|
||||
}
|
||||
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
m_curve_inc.init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curve_div.init(x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
}
|
||||
|
||||
void approximation_method(curve_approximation_method_e v)
|
||||
{
|
||||
m_approximation_method = v;
|
||||
}
|
||||
|
||||
curve_approximation_method_e approximation_method() const
|
||||
{
|
||||
return m_approximation_method;
|
||||
}
|
||||
|
||||
void approximation_scale(double s)
|
||||
{
|
||||
m_curve_inc.approximation_scale(s);
|
||||
m_curve_div.approximation_scale(s);
|
||||
}
|
||||
|
||||
double approximation_scale() const
|
||||
{
|
||||
return m_curve_inc.approximation_scale();
|
||||
}
|
||||
|
||||
void angle_tolerance(double a)
|
||||
{
|
||||
m_curve_div.angle_tolerance(a);
|
||||
}
|
||||
|
||||
double angle_tolerance() const
|
||||
{
|
||||
return m_curve_div.angle_tolerance();
|
||||
}
|
||||
|
||||
void cusp_limit(double v)
|
||||
{
|
||||
m_curve_div.cusp_limit(v);
|
||||
}
|
||||
|
||||
double cusp_limit() const
|
||||
{
|
||||
return m_curve_div.cusp_limit();
|
||||
}
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
m_curve_inc.rewind(path_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curve_div.rewind(path_id);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
return m_curve_inc.vertex(x, y);
|
||||
}
|
||||
return m_curve_div.vertex(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
curve3_inc m_curve_inc;
|
||||
curve3_div m_curve_div;
|
||||
curve_approximation_method_e m_approximation_method;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------curve4
|
||||
class curve4
|
||||
{
|
||||
public:
|
||||
curve4() : m_approximation_method(curve_div) {}
|
||||
curve4(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4) :
|
||||
m_approximation_method(curve_div)
|
||||
{
|
||||
init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
|
||||
curve4(const curve4_points& cp) :
|
||||
m_approximation_method(curve_div)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_curve_inc.reset();
|
||||
m_curve_div.reset();
|
||||
}
|
||||
|
||||
void init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
}
|
||||
|
||||
void init(const curve4_points& cp)
|
||||
{
|
||||
init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
|
||||
}
|
||||
|
||||
void approximation_method(curve_approximation_method_e v)
|
||||
{
|
||||
m_approximation_method = v;
|
||||
}
|
||||
|
||||
curve_approximation_method_e approximation_method() const
|
||||
{
|
||||
return m_approximation_method;
|
||||
}
|
||||
|
||||
void approximation_scale(double s)
|
||||
{
|
||||
m_curve_inc.approximation_scale(s);
|
||||
m_curve_div.approximation_scale(s);
|
||||
}
|
||||
double approximation_scale() const { return m_curve_inc.approximation_scale(); }
|
||||
|
||||
void angle_tolerance(double v)
|
||||
{
|
||||
m_curve_div.angle_tolerance(v);
|
||||
}
|
||||
|
||||
double angle_tolerance() const
|
||||
{
|
||||
return m_curve_div.angle_tolerance();
|
||||
}
|
||||
|
||||
void cusp_limit(double v)
|
||||
{
|
||||
m_curve_div.cusp_limit(v);
|
||||
}
|
||||
|
||||
double cusp_limit() const
|
||||
{
|
||||
return m_curve_div.cusp_limit();
|
||||
}
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
m_curve_inc.rewind(path_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curve_div.rewind(path_id);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_approximation_method == curve_inc)
|
||||
{
|
||||
return m_curve_inc.vertex(x, y);
|
||||
}
|
||||
return m_curve_div.vertex(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
curve4_inc m_curve_inc;
|
||||
curve4_div m_curve_div;
|
||||
curve_approximation_method_e m_approximation_method;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,16 +1,25 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_GAMMA_FUNCTIONS_INCLUDED
|
||||
|
@ -115,15 +124,6 @@ namespace agg
|
|||
double m_mul;
|
||||
};
|
||||
|
||||
inline double sRGB_to_linear(double x)
|
||||
{
|
||||
return (x <= 0.04045) ? (x / 12.92) : pow((x + 0.055) / (1.055), 2.4);
|
||||
}
|
||||
|
||||
inline double linear_to_sRGB(double x)
|
||||
{
|
||||
return (x <= 0.0031308) ? (x * 12.92) : (1.055 * pow(x, 1 / 2.4) - 0.055);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,16 +1,25 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_GAMMA_LUT_INCLUDED
|
||||
|
@ -18,7 +27,6 @@
|
|||
|
||||
#include <math.h>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_gamma_functions.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
@ -117,184 +125,6 @@ namespace agg
|
|||
HiResT* m_dir_gamma;
|
||||
LoResT* m_inv_gamma;
|
||||
};
|
||||
|
||||
//
|
||||
// sRGB support classes
|
||||
//
|
||||
|
||||
// sRGB_lut - implements sRGB conversion for the various types.
|
||||
// Base template is undefined, specializations are provided below.
|
||||
template<class LinearType>
|
||||
class sRGB_lut;
|
||||
|
||||
template<>
|
||||
class sRGB_lut<float>
|
||||
{
|
||||
public:
|
||||
sRGB_lut()
|
||||
{
|
||||
// Generate lookup tables.
|
||||
for (int i = 0; i <= 255; ++i)
|
||||
{
|
||||
m_dir_table[i] = float(sRGB_to_linear(i / 255.0));
|
||||
}
|
||||
for (int i = 0; i <= 65535; ++i)
|
||||
{
|
||||
m_inv_table[i] = uround(255.0 * linear_to_sRGB(i / 65535.0));
|
||||
}
|
||||
}
|
||||
|
||||
float dir(int8u v) const
|
||||
{
|
||||
return m_dir_table[v];
|
||||
}
|
||||
|
||||
int8u inv(float v) const
|
||||
{
|
||||
return m_inv_table[int16u(0.5 + v * 65535)];
|
||||
}
|
||||
|
||||
private:
|
||||
float m_dir_table[256];
|
||||
int8u m_inv_table[65536];
|
||||
};
|
||||
|
||||
template<>
|
||||
class sRGB_lut<int16u>
|
||||
{
|
||||
public:
|
||||
sRGB_lut()
|
||||
{
|
||||
// Generate lookup tables.
|
||||
for (int i = 0; i <= 255; ++i)
|
||||
{
|
||||
m_dir_table[i] = uround(65535.0 * sRGB_to_linear(i / 255.0));
|
||||
}
|
||||
for (int i = 0; i <= 65535; ++i)
|
||||
{
|
||||
m_inv_table[i] = uround(255.0 * linear_to_sRGB(i / 65535.0));
|
||||
}
|
||||
}
|
||||
|
||||
int16u dir(int8u v) const
|
||||
{
|
||||
return m_dir_table[v];
|
||||
}
|
||||
|
||||
int8u inv(int16u v) const
|
||||
{
|
||||
return m_inv_table[v];
|
||||
}
|
||||
|
||||
private:
|
||||
int16u m_dir_table[256];
|
||||
int8u m_inv_table[65536];
|
||||
};
|
||||
|
||||
template<>
|
||||
class sRGB_lut<int8u>
|
||||
{
|
||||
public:
|
||||
sRGB_lut()
|
||||
{
|
||||
// Generate lookup tables.
|
||||
for (int i = 0; i <= 255; ++i)
|
||||
{
|
||||
m_dir_table[i] = uround(255.0 * sRGB_to_linear(i / 255.0));
|
||||
m_inv_table[i] = uround(255.0 * linear_to_sRGB(i / 255.0));
|
||||
}
|
||||
}
|
||||
|
||||
int8u dir(int8u v) const
|
||||
{
|
||||
return m_dir_table[v];
|
||||
}
|
||||
|
||||
int8u inv(int8u v) const
|
||||
{
|
||||
return m_inv_table[v];
|
||||
}
|
||||
|
||||
private:
|
||||
int8u m_dir_table[256];
|
||||
int8u m_inv_table[256];
|
||||
};
|
||||
|
||||
// Common base class for sRGB_conv objects. Defines an internal
|
||||
// sRGB_lut object so that users don't have to.
|
||||
template<class T>
|
||||
class sRGB_conv_base
|
||||
{
|
||||
public:
|
||||
static T rgb_from_sRGB(int8u x)
|
||||
{
|
||||
return lut.dir(x);
|
||||
}
|
||||
|
||||
static int8u rgb_to_sRGB(T x)
|
||||
{
|
||||
return lut.inv(x);
|
||||
}
|
||||
|
||||
private:
|
||||
static sRGB_lut<T> lut;
|
||||
};
|
||||
|
||||
// Definition of sRGB_conv_base::lut. Due to the fact that this a template,
|
||||
// we don't need to place the definition in a cpp file. Hurrah.
|
||||
template<class T>
|
||||
sRGB_lut<T> sRGB_conv_base<T>::lut;
|
||||
|
||||
// Wrapper for sRGB-linear conversion.
|
||||
// Base template is undefined, specializations are provided below.
|
||||
template<class T>
|
||||
class sRGB_conv;
|
||||
|
||||
template<>
|
||||
class sRGB_conv<float> : public sRGB_conv_base<float>
|
||||
{
|
||||
public:
|
||||
static float alpha_from_sRGB(int8u x)
|
||||
{
|
||||
static const double y = 1 / 255.0;
|
||||
return float(x * y);
|
||||
}
|
||||
|
||||
static int8u alpha_to_sRGB(float x)
|
||||
{
|
||||
return int8u(0.5 + x * 255);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class sRGB_conv<int16u> : public sRGB_conv_base<int16u>
|
||||
{
|
||||
public:
|
||||
static int16u alpha_from_sRGB(int8u x)
|
||||
{
|
||||
return (x << 8) | x;
|
||||
}
|
||||
|
||||
static int8u alpha_to_sRGB(int16u x)
|
||||
{
|
||||
return x >> 8;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class sRGB_conv<int8u> : public sRGB_conv_base<int8u>
|
||||
{
|
||||
public:
|
||||
static int8u alpha_from_sRGB(int8u x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
static int8u alpha_to_sRGB(int8u x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,16 +1,25 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
// Bessel function (besj) was adapted for use in AGG library by Andy Wilk
|
||||
// Contact: castor.vulgaris@gmail.com
|
||||
|
|
531
src/agg/agg_math_stroke.h
Normal file
531
src/agg/agg_math_stroke.h
Normal file
|
@ -0,0 +1,531 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#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 = 0,
|
||||
miter_join_revert = 1,
|
||||
round_join = 2,
|
||||
bevel_join = 3,
|
||||
miter_join_round = 4
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------inner_join_e
|
||||
enum inner_join_e
|
||||
{
|
||||
inner_bevel,
|
||||
inner_miter,
|
||||
inner_jag,
|
||||
inner_round
|
||||
};
|
||||
|
||||
//------------------------------------------------------------math_stroke
|
||||
template<class VertexConsumer> class math_stroke
|
||||
{
|
||||
public:
|
||||
typedef typename VertexConsumer::value_type coord_type;
|
||||
|
||||
math_stroke();
|
||||
|
||||
void line_cap(line_cap_e lc) { m_line_cap = lc; }
|
||||
void line_join(line_join_e lj) { m_line_join = lj; }
|
||||
void inner_join(inner_join_e ij) { m_inner_join = ij; }
|
||||
|
||||
line_cap_e line_cap() const { return m_line_cap; }
|
||||
line_join_e line_join() const { return m_line_join; }
|
||||
inner_join_e inner_join() const { return m_inner_join; }
|
||||
|
||||
void width(double w);
|
||||
void miter_limit(double ml) { m_miter_limit = ml; }
|
||||
void miter_limit_theta(double t);
|
||||
void inner_miter_limit(double ml) { m_inner_miter_limit = ml; }
|
||||
void approximation_scale(double as) { m_approx_scale = as; }
|
||||
|
||||
double width() const { return m_width * 2.0; }
|
||||
double miter_limit() const { return m_miter_limit; }
|
||||
double inner_miter_limit() const { return m_inner_miter_limit; }
|
||||
double approximation_scale() const { return m_approx_scale; }
|
||||
|
||||
void calc_cap(VertexConsumer& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
double len);
|
||||
|
||||
void calc_join(VertexConsumer& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double len1,
|
||||
double len2);
|
||||
|
||||
private:
|
||||
AGG_INLINE void add_vertex(VertexConsumer& vc, double x, double y)
|
||||
{
|
||||
vc.add(coord_type(x, y));
|
||||
}
|
||||
|
||||
void calc_arc(VertexConsumer& vc,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2);
|
||||
|
||||
void calc_miter(VertexConsumer& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
line_join_e lj,
|
||||
double mlimit,
|
||||
double dbevel);
|
||||
|
||||
double m_width;
|
||||
double m_width_abs;
|
||||
double m_width_eps;
|
||||
int m_width_sign;
|
||||
double m_miter_limit;
|
||||
double m_inner_miter_limit;
|
||||
double m_approx_scale;
|
||||
line_cap_e m_line_cap;
|
||||
line_join_e m_line_join;
|
||||
inner_join_e m_inner_join;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC> math_stroke<VC>::math_stroke() :
|
||||
m_width(0.5),
|
||||
m_width_abs(0.5),
|
||||
m_width_eps(0.5/1024.0),
|
||||
m_width_sign(1),
|
||||
m_miter_limit(4.0),
|
||||
m_inner_miter_limit(1.01),
|
||||
m_approx_scale(1.0),
|
||||
m_line_cap(butt_cap),
|
||||
m_line_join(miter_join),
|
||||
m_inner_join(inner_miter)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC> void math_stroke<VC>::width(double w)
|
||||
{
|
||||
m_width = w * 0.5;
|
||||
if(m_width < 0)
|
||||
{
|
||||
m_width_abs = -m_width;
|
||||
m_width_sign = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_width_abs = m_width;
|
||||
m_width_sign = 1;
|
||||
}
|
||||
m_width_eps = m_width / 1024.0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC> void math_stroke<VC>::miter_limit_theta(double t)
|
||||
{
|
||||
m_miter_limit = 1.0 / sin(t * 0.5) ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void math_stroke<VC>::calc_arc(VC& vc,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
double a1 = atan2(dy1 * m_width_sign, dx1 * m_width_sign);
|
||||
double a2 = atan2(dy2 * m_width_sign, dx2 * m_width_sign);
|
||||
double da = a1 - a2;
|
||||
int i, n;
|
||||
|
||||
da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
|
||||
|
||||
add_vertex(vc, x + dx1, y + dy1);
|
||||
if(m_width_sign > 0)
|
||||
{
|
||||
if(a1 > a2) a2 += 2 * pi;
|
||||
n = int((a2 - a1) / da);
|
||||
da = (a2 - a1) / (n + 1);
|
||||
a1 += da;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width);
|
||||
a1 += da;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(a1 < a2) a2 -= 2 * pi;
|
||||
n = int((a1 - a2) / da);
|
||||
da = (a1 - a2) / (n + 1);
|
||||
a1 -= da;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width);
|
||||
a1 -= da;
|
||||
}
|
||||
}
|
||||
add_vertex(vc, x + dx2, y + dy2);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void math_stroke<VC>::calc_miter(VC& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
line_join_e lj,
|
||||
double mlimit,
|
||||
double dbevel)
|
||||
{
|
||||
double xi = v1.x;
|
||||
double yi = v1.y;
|
||||
double di = 1;
|
||||
double lim = m_width_abs * mlimit;
|
||||
bool miter_limit_exceeded = true; // Assume the worst
|
||||
bool intersection_failed = true; // Assume the worst
|
||||
|
||||
if(calc_intersection(v0.x + dx1, v0.y - dy1,
|
||||
v1.x + dx1, v1.y - dy1,
|
||||
v1.x + dx2, v1.y - dy2,
|
||||
v2.x + dx2, v2.y - dy2,
|
||||
&xi, &yi))
|
||||
{
|
||||
// Calculation of the intersection succeeded
|
||||
//---------------------
|
||||
di = calc_distance(v1.x, v1.y, xi, yi);
|
||||
if(di <= lim)
|
||||
{
|
||||
// Inside the miter limit
|
||||
//---------------------
|
||||
add_vertex(vc, xi, yi);
|
||||
miter_limit_exceeded = false;
|
||||
}
|
||||
intersection_failed = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Calculation of the intersection failed, most probably
|
||||
// the three points lie one straight line.
|
||||
// First check if v0 and v2 lie on the opposite sides of vector:
|
||||
// (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular
|
||||
// to the line determined by vertices v0 and v1.
|
||||
// This condition determines whether the next line segments continues
|
||||
// the previous one or goes back.
|
||||
//----------------
|
||||
double x2 = v1.x + dx1;
|
||||
double y2 = v1.y - dy1;
|
||||
if((cross_product(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) ==
|
||||
(cross_product(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0))
|
||||
{
|
||||
// This case means that the next segment continues
|
||||
// the previous one (straight line)
|
||||
//-----------------
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
miter_limit_exceeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(miter_limit_exceeded)
|
||||
{
|
||||
// Miter limit exceeded
|
||||
//------------------------
|
||||
switch(lj)
|
||||
{
|
||||
case miter_join_revert:
|
||||
// For the compatibility with SVG, PDF, etc,
|
||||
// we use a simple bevel join instead of
|
||||
// "smart" bevel
|
||||
//-------------------
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
break;
|
||||
|
||||
case miter_join_round:
|
||||
calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
|
||||
break;
|
||||
|
||||
default:
|
||||
// If no miter-revert, calculate new dx1, dy1, dx2, dy2
|
||||
//----------------
|
||||
if(intersection_failed)
|
||||
{
|
||||
mlimit *= m_width_sign;
|
||||
add_vertex(vc, v1.x + dx1 + dy1 * mlimit,
|
||||
v1.y - dy1 + dx1 * mlimit);
|
||||
add_vertex(vc, v1.x + dx2 - dy2 * mlimit,
|
||||
v1.y - dy2 - dx2 * mlimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
double x1 = v1.x + dx1;
|
||||
double y1 = v1.y - dy1;
|
||||
double x2 = v1.x + dx2;
|
||||
double y2 = v1.y - dy2;
|
||||
di = (lim - dbevel) / (di - dbevel);
|
||||
add_vertex(vc, x1 + (xi - x1) * di,
|
||||
y1 + (yi - y1) * di);
|
||||
add_vertex(vc, x2 + (xi - x2) * di,
|
||||
y2 + (yi - y2) * di);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------stroke_calc_cap
|
||||
template<class VC>
|
||||
void math_stroke<VC>::calc_cap(VC& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
double len)
|
||||
{
|
||||
vc.remove_all();
|
||||
|
||||
double dx1 = (v1.y - v0.y) / len;
|
||||
double dy1 = (v1.x - v0.x) / len;
|
||||
double dx2 = 0;
|
||||
double dy2 = 0;
|
||||
|
||||
dx1 *= m_width;
|
||||
dy1 *= m_width;
|
||||
|
||||
if(m_line_cap != round_cap)
|
||||
{
|
||||
if(m_line_cap == square_cap)
|
||||
{
|
||||
dx2 = dy1 * m_width_sign;
|
||||
dy2 = dx1 * m_width_sign;
|
||||
}
|
||||
add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2);
|
||||
add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2);
|
||||
}
|
||||
else
|
||||
{
|
||||
double da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2;
|
||||
double a1;
|
||||
int i;
|
||||
int n = int(pi / da);
|
||||
|
||||
da = pi / (n + 1);
|
||||
add_vertex(vc, v0.x - dx1, v0.y + dy1);
|
||||
if(m_width_sign > 0)
|
||||
{
|
||||
a1 = atan2(dy1, -dx1);
|
||||
a1 += da;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
add_vertex(vc, v0.x + cos(a1) * m_width,
|
||||
v0.y + sin(a1) * m_width);
|
||||
a1 += da;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a1 = atan2(-dy1, dx1);
|
||||
a1 -= da;
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
add_vertex(vc, v0.x + cos(a1) * m_width,
|
||||
v0.y + sin(a1) * m_width);
|
||||
a1 -= da;
|
||||
}
|
||||
}
|
||||
add_vertex(vc, v0.x + dx1, v0.y - dy1);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
template<class VC>
|
||||
void math_stroke<VC>::calc_join(VC& vc,
|
||||
const vertex_dist& v0,
|
||||
const vertex_dist& v1,
|
||||
const vertex_dist& v2,
|
||||
double len1,
|
||||
double len2)
|
||||
{
|
||||
double dx1 = m_width * (v1.y - v0.y) / len1;
|
||||
double dy1 = m_width * (v1.x - v0.x) / len1;
|
||||
double dx2 = m_width * (v2.y - v1.y) / len2;
|
||||
double dy2 = m_width * (v2.x - v1.x) / len2;
|
||||
|
||||
vc.remove_all();
|
||||
|
||||
double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y);
|
||||
if(cp != 0 && (cp > 0) == (m_width > 0))
|
||||
{
|
||||
// Inner join
|
||||
//---------------
|
||||
double limit = ((len1 < len2) ? len1 : len2) / m_width_abs;
|
||||
if(limit < m_inner_miter_limit)
|
||||
{
|
||||
limit = m_inner_miter_limit;
|
||||
}
|
||||
|
||||
switch(m_inner_join)
|
||||
{
|
||||
default: // inner_bevel
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
break;
|
||||
|
||||
case inner_miter:
|
||||
calc_miter(vc,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
miter_join_revert,
|
||||
limit, 0);
|
||||
break;
|
||||
|
||||
case inner_jag:
|
||||
case inner_round:
|
||||
cp = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2);
|
||||
if(cp < len1 * len1 && cp < len2 * len2)
|
||||
{
|
||||
calc_miter(vc,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
miter_join_revert,
|
||||
limit, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_inner_join == inner_jag)
|
||||
{
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x, v1.y );
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x, v1.y );
|
||||
calc_arc(vc, v1.x, v1.y, dx2, -dy2, dx1, -dy1);
|
||||
add_vertex(vc, v1.x, v1.y );
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Outer join
|
||||
//---------------
|
||||
|
||||
// Calculate the distance between v1 and
|
||||
// the central point of the bevel line segment
|
||||
//---------------
|
||||
double dx = (dx1 + dx2) / 2;
|
||||
double dy = (dy1 + dy2) / 2;
|
||||
double dbevel = sqrt(dx * dx + dy * dy);
|
||||
|
||||
if(m_line_join == round_join || m_line_join == bevel_join)
|
||||
{
|
||||
// This is an optimization that reduces the number of points
|
||||
// in cases of almost collinear segments. If there's no
|
||||
// visible difference between bevel and miter joins we'd rather
|
||||
// use miter join because it adds only one point instead of two.
|
||||
//
|
||||
// Here we calculate the middle point between the bevel points
|
||||
// and then, the distance between v1 and this middle point.
|
||||
// At outer joins this distance always less than stroke width,
|
||||
// because it's actually the height of an isosceles triangle of
|
||||
// v1 and its two bevel points. If the difference between this
|
||||
// width and this value is small (no visible bevel) we can
|
||||
// add just one point.
|
||||
//
|
||||
// The constant in the expression makes the result approximately
|
||||
// the same as in round joins and caps. You can safely comment
|
||||
// out this entire "if".
|
||||
//-------------------
|
||||
if(m_approx_scale * (m_width_abs - dbevel) < m_width_eps)
|
||||
{
|
||||
if(calc_intersection(v0.x + dx1, v0.y - dy1,
|
||||
v1.x + dx1, v1.y - dy1,
|
||||
v1.x + dx2, v1.y - dy2,
|
||||
v2.x + dx2, v2.y - dy2,
|
||||
&dx, &dy))
|
||||
{
|
||||
add_vertex(vc, dx, dy);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch(m_line_join)
|
||||
{
|
||||
case miter_join:
|
||||
case miter_join_revert:
|
||||
case miter_join_round:
|
||||
calc_miter(vc,
|
||||
v0, v1, v2, dx1, dy1, dx2, dy2,
|
||||
m_line_join,
|
||||
m_miter_limit,
|
||||
dbevel);
|
||||
break;
|
||||
|
||||
case round_join:
|
||||
calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2);
|
||||
break;
|
||||
|
||||
default: // Bevel join
|
||||
add_vertex(vc, v1.x + dx1, v1.y - dy1);
|
||||
add_vertex(vc, v1.x + dx2, v1.y - dy2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,16 +1,25 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_PATH_STORAGE_INCLUDED
|
||||
|
@ -490,14 +499,14 @@ namespace agg
|
|||
m_stop(false)
|
||||
{}
|
||||
|
||||
poly_container_reverse_adaptor(Container& data, bool closed) :
|
||||
poly_container_reverse_adaptor(const Container& data, bool closed) :
|
||||
m_container(&data),
|
||||
m_index(-1),
|
||||
m_closed(closed),
|
||||
m_stop(false)
|
||||
{}
|
||||
|
||||
void init(Container& data, bool closed)
|
||||
void init(const Container& data, bool closed)
|
||||
{
|
||||
m_container = &data;
|
||||
m_index = m_container->size() - 1;
|
||||
|
@ -531,7 +540,7 @@ namespace agg
|
|||
}
|
||||
|
||||
private:
|
||||
Container* m_container;
|
||||
const Container* m_container;
|
||||
int m_index;
|
||||
bool m_closed;
|
||||
bool m_stop;
|
||||
|
@ -835,43 +844,6 @@ namespace agg
|
|||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// If the end points of a path are very, very close then make them
|
||||
// exactly equal so that the stroke converter is not confused.
|
||||
//--------------------------------------------------------------------
|
||||
unsigned align_path(unsigned idx = 0)
|
||||
{
|
||||
if (idx >= total_vertices() || !is_move_to(command(idx)))
|
||||
{
|
||||
return total_vertices();
|
||||
}
|
||||
|
||||
double start_x, start_y;
|
||||
for (; idx < total_vertices() && is_move_to(command(idx)); ++idx)
|
||||
{
|
||||
vertex(idx, &start_x, &start_y);
|
||||
}
|
||||
while (idx < total_vertices() && is_drawing(command(idx)))
|
||||
++idx;
|
||||
|
||||
double x, y;
|
||||
if (is_drawing(vertex(idx - 1, &x, &y)) &&
|
||||
is_equal_eps(x, start_x, 1e-8) &&
|
||||
is_equal_eps(y, start_y, 1e-8))
|
||||
{
|
||||
modify_vertex(idx - 1, start_x, start_y);
|
||||
}
|
||||
|
||||
while (idx < total_vertices() && !is_move_to(command(idx)))
|
||||
++idx;
|
||||
return idx;
|
||||
}
|
||||
|
||||
void align_all_paths()
|
||||
{
|
||||
for (unsigned i = 0; i < total_vertices(); i = align_path(i));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
unsigned perceive_polygon_orientation(unsigned start, unsigned end);
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_PIXFMT_BASE_INCLUDED
|
||||
#define AGG_PIXFMT_BASE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_gray.h"
|
||||
#include "agg_color_rgba.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
struct pixfmt_gray_tag
|
||||
{
|
||||
};
|
||||
|
||||
struct pixfmt_rgb_tag
|
||||
{
|
||||
};
|
||||
|
||||
struct pixfmt_rgba_tag
|
||||
{
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------blender_base
|
||||
template<class ColorT, class Order = void>
|
||||
struct blender_base
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef Order order_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
|
||||
static rgba get(value_type r, value_type g, value_type b, value_type a, cover_type cover = cover_full)
|
||||
{
|
||||
if (cover > cover_none)
|
||||
{
|
||||
rgba c(
|
||||
color_type::to_double(r),
|
||||
color_type::to_double(g),
|
||||
color_type::to_double(b),
|
||||
color_type::to_double(a));
|
||||
|
||||
if (cover < cover_full)
|
||||
{
|
||||
double x = double(cover) / cover_full;
|
||||
c.r *= x;
|
||||
c.g *= x;
|
||||
c.b *= x;
|
||||
c.a *= x;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
else return rgba::no_color();
|
||||
}
|
||||
|
||||
static rgba get(const value_type* p, cover_type cover = cover_full)
|
||||
{
|
||||
return get(
|
||||
p[order_type::R],
|
||||
p[order_type::G],
|
||||
p[order_type::B],
|
||||
p[order_type::A],
|
||||
cover);
|
||||
}
|
||||
|
||||
static void set(value_type* p, value_type r, value_type g, value_type b, value_type a)
|
||||
{
|
||||
p[order_type::R] = r;
|
||||
p[order_type::G] = g;
|
||||
p[order_type::B] = b;
|
||||
p[order_type::A] = a;
|
||||
}
|
||||
|
||||
static void set(value_type* p, const rgba& c)
|
||||
{
|
||||
p[order_type::R] = color_type::from_double(c.r);
|
||||
p[order_type::G] = color_type::from_double(c.g);
|
||||
p[order_type::B] = color_type::from_double(c.b);
|
||||
p[order_type::A] = color_type::from_double(c.a);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,16 +1,25 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for high precision colors has been sponsored by
|
||||
|
@ -25,7 +34,8 @@
|
|||
#define AGG_PIXFMT_GRAY_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_pixfmt_base.h"
|
||||
#include "agg_basics.h"
|
||||
#include "agg_color_gray.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
namespace agg
|
||||
|
@ -37,22 +47,12 @@ namespace agg
|
|||
typedef ColorT color_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
typedef typename color_type::long_type long_type;
|
||||
enum base_scale_e { base_shift = color_type::base_shift };
|
||||
|
||||
// Blend pixels using the non-premultiplied form of Alvy-Ray Smith's
|
||||
// compositing function. Since the render buffer is opaque we skip the
|
||||
// initial premultiply and final demultiply.
|
||||
|
||||
static AGG_INLINE void blend_pix(value_type* p,
|
||||
value_type cv, value_type alpha, cover_type cover)
|
||||
static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
|
||||
unsigned alpha, unsigned cover=0)
|
||||
{
|
||||
blend_pix(p, cv, color_type::mult_cover(alpha, cover));
|
||||
}
|
||||
|
||||
static AGG_INLINE void blend_pix(value_type* p,
|
||||
value_type cv, value_type alpha)
|
||||
{
|
||||
*p = color_type::lerp(*p, cv, alpha);
|
||||
*p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -63,21 +63,20 @@ namespace agg
|
|||
typedef ColorT color_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
typedef typename color_type::long_type long_type;
|
||||
enum base_scale_e { base_shift = color_type::base_shift };
|
||||
|
||||
// Blend pixels using the premultiplied form of Alvy-Ray Smith's
|
||||
// compositing function.
|
||||
|
||||
static AGG_INLINE void blend_pix(value_type* p,
|
||||
value_type cv, value_type alpha, cover_type cover)
|
||||
static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
|
||||
unsigned alpha, unsigned cover)
|
||||
{
|
||||
blend_pix(p, color_type::mult_cover(cv, cover), color_type::mult_cover(alpha, cover));
|
||||
alpha = color_type::base_mask - alpha;
|
||||
cover = (cover + 1) << (base_shift - 8);
|
||||
*p = (value_type)((*p * alpha + cv * cover) >> base_shift);
|
||||
}
|
||||
|
||||
static AGG_INLINE void blend_pix(value_type* p,
|
||||
value_type cv, value_type alpha)
|
||||
static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
|
||||
unsigned alpha)
|
||||
{
|
||||
*p = color_type::prelerp(*p, cv, alpha);
|
||||
*p = (value_type)(((*p * (color_type::base_mask - alpha)) >> base_shift) + cv);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -122,11 +121,10 @@ namespace agg
|
|||
|
||||
|
||||
//=================================================pixfmt_alpha_blend_gray
|
||||
template<class Blender, class RenBuf, unsigned Step = 1, unsigned Offset = 0>
|
||||
template<class Blender, class RenBuf, unsigned Step=1, unsigned Offset=0>
|
||||
class pixfmt_alpha_blend_gray
|
||||
{
|
||||
public:
|
||||
typedef pixfmt_gray_tag pixfmt_category;
|
||||
typedef RenBuf rbuf_type;
|
||||
typedef typename rbuf_type::row_data row_data;
|
||||
typedef Blender blender_type;
|
||||
|
@ -134,117 +132,54 @@ namespace agg
|
|||
typedef int order_type; // A fake one
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum
|
||||
enum base_scale_e
|
||||
{
|
||||
num_components = 1,
|
||||
pix_width = sizeof(value_type) * Step,
|
||||
pix_step = Step,
|
||||
pix_offset = Offset,
|
||||
};
|
||||
struct pixel_type
|
||||
{
|
||||
value_type c[num_components];
|
||||
|
||||
void set(value_type v)
|
||||
{
|
||||
c[0] = v;
|
||||
}
|
||||
|
||||
void set(const color_type& color)
|
||||
{
|
||||
set(color.v);
|
||||
}
|
||||
|
||||
void get(value_type& v) const
|
||||
{
|
||||
v = c[0];
|
||||
}
|
||||
|
||||
color_type get() const
|
||||
{
|
||||
return color_type(c[0]);
|
||||
}
|
||||
|
||||
pixel_type* next()
|
||||
{
|
||||
return (pixel_type*)(c + pix_step);
|
||||
}
|
||||
|
||||
const pixel_type* next() const
|
||||
{
|
||||
return (const pixel_type*)(c + pix_step);
|
||||
}
|
||||
|
||||
pixel_type* advance(int n)
|
||||
{
|
||||
return (pixel_type*)(c + n * pix_step);
|
||||
}
|
||||
|
||||
const pixel_type* advance(int n) const
|
||||
{
|
||||
return (const pixel_type*)(c + n * pix_step);
|
||||
}
|
||||
base_shift = color_type::base_shift,
|
||||
base_scale = color_type::base_scale,
|
||||
base_mask = color_type::base_mask,
|
||||
pix_width = sizeof(value_type),
|
||||
pix_step = Step,
|
||||
pix_offset = Offset
|
||||
};
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_pix(pixel_type* p,
|
||||
value_type v, value_type a,
|
||||
unsigned cover)
|
||||
static AGG_INLINE void copy_or_blend_pix(value_type* p,
|
||||
const color_type& c,
|
||||
unsigned cover)
|
||||
{
|
||||
blender_type::blend_pix(p->c, v, a, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_pix(pixel_type* p, value_type v, value_type a)
|
||||
{
|
||||
blender_type::blend_pix(p->c, v, a);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover)
|
||||
{
|
||||
blender_type::blend_pix(p->c, c.v, c.a, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_pix(pixel_type* p, const color_type& c)
|
||||
{
|
||||
blender_type::blend_pix(p->c, c.v, c.a);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover)
|
||||
{
|
||||
if (!c.is_transparent())
|
||||
if (c.a)
|
||||
{
|
||||
if (c.is_opaque() && cover == cover_mask)
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
p->set(c);
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
blend_pix(p, c, cover);
|
||||
Blender::blend_pix(p, c.v, alpha, cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c)
|
||||
|
||||
static AGG_INLINE void copy_or_blend_pix(value_type* p,
|
||||
const color_type& c)
|
||||
{
|
||||
if (!c.is_transparent())
|
||||
if (c.a)
|
||||
{
|
||||
if (c.is_opaque())
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
p->set(c);
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
blend_pix(p, c);
|
||||
Blender::blend_pix(p, c.v, c.a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
explicit pixfmt_alpha_blend_gray(rbuf_type& rb) :
|
||||
|
@ -257,7 +192,7 @@ namespace agg
|
|||
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
rect_i r(x1, y1, x2, y2);
|
||||
if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
|
||||
if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
|
||||
{
|
||||
int stride = pixf.stride();
|
||||
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
|
||||
|
@ -275,98 +210,61 @@ namespace agg
|
|||
AGG_INLINE int stride() const { return m_rbuf->stride(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
|
||||
int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
|
||||
const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
|
||||
row_data row(int y) const { return m_rbuf->row(y); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE int8u* pix_ptr(int x, int y)
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset);
|
||||
}
|
||||
|
||||
AGG_INLINE const int8u* pix_ptr(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset);
|
||||
}
|
||||
|
||||
// Return pointer to pixel value, forcing row to be allocated.
|
||||
AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len)
|
||||
const int8u* pix_ptr(int x, int y) const
|
||||
{
|
||||
return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step + pix_offset));
|
||||
return m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
}
|
||||
|
||||
// Return pointer to pixel value, or null if row not allocated.
|
||||
AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const
|
||||
int8u* pix_ptr(int x, int y)
|
||||
{
|
||||
int8u* p = m_rbuf->row_ptr(y);
|
||||
return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step + pix_offset)) : 0;
|
||||
}
|
||||
|
||||
// Get pixel pointer from raw buffer pointer.
|
||||
AGG_INLINE static pixel_type* pix_value_ptr(void* p)
|
||||
{
|
||||
return (pixel_type*)((value_type*)p + pix_offset);
|
||||
}
|
||||
|
||||
// Get pixel pointer from raw buffer pointer.
|
||||
AGG_INLINE static const pixel_type* pix_value_ptr(const void* p)
|
||||
{
|
||||
return (const pixel_type*)((const value_type*)p + pix_offset);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE static void write_plain_color(void* p, color_type c)
|
||||
{
|
||||
// Grayscale formats are implicitly premultiplied.
|
||||
c.premultiply();
|
||||
pix_value_ptr(p)->set(c);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE static color_type read_plain_color(const void* p)
|
||||
{
|
||||
return pix_value_ptr(p)->get();
|
||||
return m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE static void make_pix(int8u* p, const color_type& c)
|
||||
{
|
||||
((pixel_type*)p)->set(c);
|
||||
*(value_type*)p = c.v;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE color_type pixel(int x, int y) const
|
||||
{
|
||||
if (const pixel_type* p = pix_value_ptr(x, y))
|
||||
{
|
||||
return p->get();
|
||||
}
|
||||
return color_type::no_color();
|
||||
value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
return color_type(*p);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
pix_value_ptr(x, y, 1)->set(c);
|
||||
*((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||
{
|
||||
copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover);
|
||||
copy_or_blend_pix((value_type*)
|
||||
m_rbuf->row_ptr(x, y, 1) + x * Step + Offset,
|
||||
c,
|
||||
cover);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
pixel_type* p = pix_value_ptr(x, y, len);
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
p->set(c);
|
||||
p = p->next();
|
||||
*p = c.v;
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
@ -379,9 +277,12 @@ namespace agg
|
|||
{
|
||||
do
|
||||
{
|
||||
pix_value_ptr(x, y++, 1)->set(c);
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
*p = c.v;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
|
@ -391,27 +292,29 @@ namespace agg
|
|||
const color_type& c,
|
||||
int8u cover)
|
||||
{
|
||||
if (!c.is_transparent())
|
||||
if (c.a)
|
||||
{
|
||||
pixel_type* p = pix_value_ptr(x, y, len);
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
if (c.is_opaque() && cover == cover_mask)
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
p->set(c);
|
||||
p = p->next();
|
||||
*p = c.v;
|
||||
p += Step;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
blend_pix(p, c, cover);
|
||||
p = p->next();
|
||||
Blender::blend_pix(p, c.v, alpha, cover);
|
||||
p += Step;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -423,23 +326,31 @@ namespace agg
|
|||
const color_type& c,
|
||||
int8u cover)
|
||||
{
|
||||
if (!c.is_transparent())
|
||||
if (c.a)
|
||||
{
|
||||
if (c.is_opaque() && cover == cover_mask)
|
||||
value_type* p;
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
pix_value_ptr(x, y++, 1)->set(c);
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
*p = c.v;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
blend_pix(pix_value_ptr(x, y++, 1), c, cover);
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
Blender::blend_pix(p, c.v, alpha, cover);
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -451,24 +362,26 @@ namespace agg
|
|||
const color_type& c,
|
||||
const int8u* covers)
|
||||
{
|
||||
if (!c.is_transparent())
|
||||
if (c.a)
|
||||
{
|
||||
pixel_type* p = pix_value_ptr(x, y, len);
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
if (c.is_opaque() && *covers == cover_mask)
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
p->set(c);
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
blend_pix(p, c, *covers);
|
||||
Blender::blend_pix(p, c.v, alpha, *covers);
|
||||
}
|
||||
p = p->next();
|
||||
p += Step;
|
||||
++covers;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -479,23 +392,26 @@ namespace agg
|
|||
const color_type& c,
|
||||
const int8u* covers)
|
||||
{
|
||||
if (!c.is_transparent())
|
||||
if (c.a)
|
||||
{
|
||||
do
|
||||
{
|
||||
pixel_type* p = pix_value_ptr(x, y++, 1);
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
|
||||
|
||||
if (c.is_opaque() && *covers == cover_mask)
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
p->set(c);
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
blend_pix(p, c, *covers);
|
||||
Blender::blend_pix(p, c.v, alpha, *covers);
|
||||
}
|
||||
++covers;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -505,14 +421,16 @@ namespace agg
|
|||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
pixel_type* p = pix_value_ptr(x, y, len);
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
p->set(*colors++);
|
||||
p = p->next();
|
||||
*p = colors->v;
|
||||
p += Step;
|
||||
++colors;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
|
@ -523,9 +441,12 @@ namespace agg
|
|||
{
|
||||
do
|
||||
{
|
||||
pix_value_ptr(x, y++, 1)->set(*colors++);
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
*p = colors->v;
|
||||
++colors;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
|
@ -536,40 +457,50 @@ namespace agg
|
|||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
pixel_type* p = pix_value_ptr(x, y, len);
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
if (covers)
|
||||
if(covers)
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++, *covers++);
|
||||
p = p->next();
|
||||
p += Step;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cover == cover_mask)
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++);
|
||||
p = p->next();
|
||||
if(colors->a == base_mask)
|
||||
{
|
||||
*p = colors->v;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_or_blend_pix(p, *colors);
|
||||
}
|
||||
p += Step;
|
||||
++colors;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++, cover);
|
||||
p = p->next();
|
||||
p += Step;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y,
|
||||
|
@ -578,31 +509,49 @@ namespace agg
|
|||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
if (covers)
|
||||
value_type* p;
|
||||
if(covers)
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++);
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
copy_or_blend_pix(p, *colors++, *covers++);
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cover == cover_mask)
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++);
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
if(colors->a == base_mask)
|
||||
{
|
||||
*p = colors->v;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_or_blend_pix(p, *colors);
|
||||
}
|
||||
++colors;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover);
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
copy_or_blend_pix(p, *colors++, cover);
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -611,19 +560,22 @@ namespace agg
|
|||
template<class Function> void for_each_pixel(Function f)
|
||||
{
|
||||
unsigned y;
|
||||
for (y = 0; y < height(); ++y)
|
||||
for(y = 0; y < height(); ++y)
|
||||
{
|
||||
row_data r = m_rbuf->row(y);
|
||||
if (r.ptr)
|
||||
if(r.ptr)
|
||||
{
|
||||
unsigned len = r.x2 - r.x1 + 1;
|
||||
pixel_type* p = pix_value_ptr(r.x1, y, len);
|
||||
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(r.x1, y, len) + r.x1 * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
f(p->c);
|
||||
p = p->next();
|
||||
f(p);
|
||||
p += Step;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -647,7 +599,8 @@ namespace agg
|
|||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
if (const int8u* p = from.row_ptr(ysrc))
|
||||
const int8u* p = from.row_ptr(ysrc);
|
||||
if(p)
|
||||
{
|
||||
memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
|
||||
p + xsrc * pix_width,
|
||||
|
@ -656,7 +609,6 @@ namespace agg
|
|||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Blend from single color, using grayscale surface as alpha channel.
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_color(const SrcPixelFormatRenderer& from,
|
||||
const color_type& color,
|
||||
|
@ -665,26 +617,25 @@ namespace agg
|
|||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
|
||||
typedef typename SrcPixelFormatRenderer::color_type src_color_type;
|
||||
|
||||
if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
|
||||
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0]));
|
||||
psrc = psrc->next();
|
||||
pdst = pdst->next();
|
||||
copy_or_blend_pix(pdst,
|
||||
color,
|
||||
(*psrc * cover + base_mask) >> base_shift);
|
||||
++psrc;
|
||||
++pdst;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Blend from color table, using grayscale surface as indexes into table.
|
||||
// Obviously, this only works for integer value types.
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_lut(const SrcPixelFormatRenderer& from,
|
||||
const color_type* color_lut,
|
||||
|
@ -693,19 +644,19 @@ namespace agg
|
|||
unsigned len,
|
||||
int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
|
||||
|
||||
if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
|
||||
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover);
|
||||
psrc = psrc->next();
|
||||
pdst = pdst->next();
|
||||
copy_or_blend_pix(pdst, color_lut[*psrc], cover);
|
||||
++psrc;
|
||||
++pdst;
|
||||
}
|
||||
while (--len);
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -713,25 +664,15 @@ namespace agg
|
|||
rbuf_type* m_rbuf;
|
||||
};
|
||||
|
||||
typedef blender_gray<gray8> blender_gray8;
|
||||
typedef blender_gray<sgray8> blender_sgray8;
|
||||
typedef blender_gray<gray16> blender_gray16;
|
||||
typedef blender_gray<gray32> blender_gray32;
|
||||
|
||||
typedef blender_gray_pre<gray8> blender_gray8_pre;
|
||||
typedef blender_gray_pre<sgray8> blender_sgray8_pre;
|
||||
typedef blender_gray<gray8> blender_gray8;
|
||||
typedef blender_gray_pre<gray8> blender_gray8_pre;
|
||||
typedef blender_gray<gray16> blender_gray16;
|
||||
typedef blender_gray_pre<gray16> blender_gray16_pre;
|
||||
typedef blender_gray_pre<gray32> blender_gray32_pre;
|
||||
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray8, rendering_buffer> pixfmt_gray8;
|
||||
typedef pixfmt_alpha_blend_gray<blender_sgray8, rendering_buffer> pixfmt_sgray8;
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray16, rendering_buffer> pixfmt_gray16;
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray32, rendering_buffer> pixfmt_gray32;
|
||||
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray8_pre, rendering_buffer> pixfmt_gray8_pre;
|
||||
typedef pixfmt_alpha_blend_gray<blender_sgray8_pre, rendering_buffer> pixfmt_sgray8_pre;
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray16_pre, rendering_buffer> pixfmt_gray16_pre;
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray32_pre, rendering_buffer> pixfmt_gray32_pre;
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray8, rendering_buffer> pixfmt_gray8; //----pixfmt_gray8
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray8_pre, rendering_buffer> pixfmt_gray8_pre; //----pixfmt_gray8_pre
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray16, rendering_buffer> pixfmt_gray16; //----pixfmt_gray16
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray16_pre, rendering_buffer> pixfmt_gray16_pre; //----pixfmt_gray16_pre
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
2911
src/agg/agg_pixfmt_rgba.h
Normal file
2911
src/agg/agg_pixfmt_rgba.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,12 +1,25 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// The author gratefully acknowleges the support of David Turner,
|
||||
|
@ -14,10 +27,6 @@
|
|||
// libray - in producing this work. See http://www.freetype.org for details.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
|
@ -26,12 +35,12 @@
|
|||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RASTERIZER_CELLS_AA_INCLUDED
|
||||
#define AGG_RASTERIZER_CELLS_AA_INCLUDED
|
||||
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <math.h>
|
||||
#include "agg_math.h"
|
||||
#include "agg_array.h"
|
||||
|
||||
|
@ -151,10 +160,10 @@ namespace agg
|
|||
m_curr_cell_ptr(0),
|
||||
m_sorted_cells(),
|
||||
m_sorted_y(),
|
||||
m_min_x(std::numeric_limits<int>::max()),
|
||||
m_min_y(std::numeric_limits<int>::max()),
|
||||
m_max_x(std::numeric_limits<int>::min()),
|
||||
m_max_y(std::numeric_limits<int>::min()),
|
||||
m_min_x(0x7FFFFFFF),
|
||||
m_min_y(0x7FFFFFFF),
|
||||
m_max_x(-0x7FFFFFFF),
|
||||
m_max_y(-0x7FFFFFFF),
|
||||
m_sorted(false)
|
||||
{
|
||||
m_style_cell.initial();
|
||||
|
@ -170,10 +179,10 @@ namespace agg
|
|||
m_curr_cell.initial();
|
||||
m_style_cell.initial();
|
||||
m_sorted = false;
|
||||
m_min_x = std::numeric_limits<int>::max();
|
||||
m_min_y = std::numeric_limits<int>::max();
|
||||
m_max_x = std::numeric_limits<int>::min();
|
||||
m_max_y = std::numeric_limits<int>::min();
|
||||
m_min_x = 0x7FFFFFFF;
|
||||
m_min_y = 0x7FFFFFFF;
|
||||
m_max_x = -0x7FFFFFFF;
|
||||
m_max_y = -0x7FFFFFFF;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
@ -218,8 +227,7 @@ namespace agg
|
|||
int fx1 = x1 & poly_subpixel_mask;
|
||||
int fx2 = x2 & poly_subpixel_mask;
|
||||
|
||||
int delta, p, first;
|
||||
long long dx;
|
||||
int delta, p, first, dx;
|
||||
int incr, lift, mod, rem;
|
||||
|
||||
//trivial case. Happens often
|
||||
|
@ -244,7 +252,7 @@ namespace agg
|
|||
first = poly_subpixel_scale;
|
||||
incr = 1;
|
||||
|
||||
dx = (long long)x2 - (long long)x1;
|
||||
dx = x2 - x1;
|
||||
|
||||
if(dx < 0)
|
||||
{
|
||||
|
@ -254,13 +262,13 @@ namespace agg
|
|||
dx = -dx;
|
||||
}
|
||||
|
||||
delta = (int)(p / dx);
|
||||
mod = (int)(p % dx);
|
||||
delta = p / dx;
|
||||
mod = p % dx;
|
||||
|
||||
if(mod < 0)
|
||||
{
|
||||
delta--;
|
||||
mod += static_cast<int>(dx);
|
||||
mod += dx;
|
||||
}
|
||||
|
||||
m_curr_cell.cover += delta;
|
||||
|
@ -273,16 +281,16 @@ namespace agg
|
|||
if(ex1 != ex2)
|
||||
{
|
||||
p = poly_subpixel_scale * (y2 - y1 + delta);
|
||||
lift = (int)(p / dx);
|
||||
rem = (int)(p % dx);
|
||||
lift = p / dx;
|
||||
rem = p % dx;
|
||||
|
||||
if (rem < 0)
|
||||
{
|
||||
lift--;
|
||||
rem += static_cast<int>(dx);
|
||||
rem += dx;
|
||||
}
|
||||
|
||||
mod -= static_cast<int>(dx);
|
||||
mod -= dx;
|
||||
|
||||
while (ex1 != ex2)
|
||||
{
|
||||
|
@ -290,7 +298,7 @@ namespace agg
|
|||
mod += rem;
|
||||
if(mod >= 0)
|
||||
{
|
||||
mod -= static_cast<int>(dx);
|
||||
mod -= dx;
|
||||
delta++;
|
||||
}
|
||||
|
||||
|
@ -319,17 +327,17 @@ namespace agg
|
|||
{
|
||||
enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift };
|
||||
|
||||
long long dx = (long long)x2 - (long long)x1;
|
||||
int dx = x2 - x1;
|
||||
|
||||
if(dx >= dx_limit || dx <= -dx_limit)
|
||||
{
|
||||
int cx = (int)(((long long)x1 + (long long)x2) >> 1);
|
||||
int cy = (int)(((long long)y1 + (long long)y2) >> 1);
|
||||
int cx = (x1 + x2) >> 1;
|
||||
int cy = (y1 + y2) >> 1;
|
||||
line(x1, y1, cx, cy);
|
||||
line(cx, cy, x2, y2);
|
||||
}
|
||||
|
||||
long long dy = (long long)y2 - (long long)y1;
|
||||
int dy = y2 - y1;
|
||||
int ex1 = x1 >> poly_subpixel_shift;
|
||||
int ex2 = x2 >> poly_subpixel_shift;
|
||||
int ey1 = y1 >> poly_subpixel_shift;
|
||||
|
@ -338,8 +346,7 @@ namespace agg
|
|||
int fy2 = y2 & poly_subpixel_mask;
|
||||
|
||||
int x_from, x_to;
|
||||
int rem, mod, lift, delta, first, incr;
|
||||
long long p;
|
||||
int p, rem, mod, lift, delta, first, incr;
|
||||
|
||||
if(ex1 < m_min_x) m_min_x = ex1;
|
||||
if(ex1 > m_max_x) m_max_x = ex1;
|
||||
|
@ -416,13 +423,13 @@ namespace agg
|
|||
dy = -dy;
|
||||
}
|
||||
|
||||
delta = (int)(p / dy);
|
||||
mod = (int)(p % dy);
|
||||
delta = p / dy;
|
||||
mod = p % dy;
|
||||
|
||||
if(mod < 0)
|
||||
{
|
||||
delta--;
|
||||
mod += static_cast<int>(dy);
|
||||
mod += dy;
|
||||
}
|
||||
|
||||
x_from = x1 + delta;
|
||||
|
@ -434,15 +441,15 @@ namespace agg
|
|||
if(ey1 != ey2)
|
||||
{
|
||||
p = poly_subpixel_scale * dx;
|
||||
lift = (int)(p / dy);
|
||||
rem = (int)(p % dy);
|
||||
lift = p / dy;
|
||||
rem = p % dy;
|
||||
|
||||
if(rem < 0)
|
||||
{
|
||||
lift--;
|
||||
rem += static_cast<int>(dy);
|
||||
rem += dy;
|
||||
}
|
||||
mod -= static_cast<int>(dy);
|
||||
mod -= dy;
|
||||
|
||||
while(ey1 != ey2)
|
||||
{
|
||||
|
@ -450,7 +457,7 @@ namespace agg
|
|||
mod += rem;
|
||||
if (mod >= 0)
|
||||
{
|
||||
mod -= static_cast<int>(dy);
|
||||
mod -= dy;
|
||||
delta++;
|
||||
}
|
||||
|
||||
|
@ -628,8 +635,8 @@ namespace agg
|
|||
if(m_sorted) return; //Perform sort only the first time.
|
||||
|
||||
add_curr_cell();
|
||||
m_curr_cell.x = std::numeric_limits<int>::max();
|
||||
m_curr_cell.y = std::numeric_limits<int>::max();
|
||||
m_curr_cell.x = 0x7FFFFFFF;
|
||||
m_curr_cell.y = 0x7FFFFFFF;
|
||||
m_curr_cell.cover = 0;
|
||||
m_curr_cell.area = 0;
|
||||
|
||||
|
@ -657,13 +664,12 @@ namespace agg
|
|||
// Create the Y-histogram (count the numbers of cells for each Y)
|
||||
cell_type** block_ptr = m_cells;
|
||||
cell_type* cell_ptr;
|
||||
unsigned nb = m_num_cells;
|
||||
unsigned nb = m_num_cells >> cell_block_shift;
|
||||
unsigned i;
|
||||
while(nb)
|
||||
while(nb--)
|
||||
{
|
||||
cell_ptr = *block_ptr++;
|
||||
i = (nb > cell_block_size) ? unsigned(cell_block_size) : nb;
|
||||
nb -= i;
|
||||
i = cell_block_size;
|
||||
while(i--)
|
||||
{
|
||||
m_sorted_y[cell_ptr->y - m_min_y].start++;
|
||||
|
@ -671,6 +677,14 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
cell_ptr = *block_ptr++;
|
||||
i = m_num_cells & cell_block_mask;
|
||||
while(i--)
|
||||
{
|
||||
m_sorted_y[cell_ptr->y - m_min_y].start++;
|
||||
++cell_ptr;
|
||||
}
|
||||
|
||||
// Convert the Y-histogram into the array of starting indexes
|
||||
unsigned start = 0;
|
||||
for(i = 0; i < m_sorted_y.size(); i++)
|
||||
|
@ -682,13 +696,12 @@ namespace agg
|
|||
|
||||
// Fill the cell pointer array sorted by Y
|
||||
block_ptr = m_cells;
|
||||
nb = m_num_cells;
|
||||
while(nb)
|
||||
nb = m_num_cells >> cell_block_shift;
|
||||
while(nb--)
|
||||
{
|
||||
cell_ptr = *block_ptr++;
|
||||
i = (nb > cell_block_size) ? unsigned(cell_block_size) : nb;
|
||||
nb -= i;
|
||||
while(i--)
|
||||
i = cell_block_size;
|
||||
while(i--)
|
||||
{
|
||||
sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
|
||||
m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
|
||||
|
@ -697,6 +710,16 @@ namespace agg
|
|||
}
|
||||
}
|
||||
|
||||
cell_ptr = *block_ptr++;
|
||||
i = m_num_cells & cell_block_mask;
|
||||
while(i--)
|
||||
{
|
||||
sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y];
|
||||
m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr;
|
||||
++curr_y.num;
|
||||
++cell_ptr;
|
||||
}
|
||||
|
||||
// Finally arrange the X-arrays
|
||||
for(i = 0; i < m_sorted_y.size(); i++)
|
||||
{
|
||||
|
|
|
@ -1,12 +1,25 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// The author gratefully acknowleges the support of David Turner,
|
||||
|
@ -14,10 +27,6 @@
|
|||
// libray - in producing this work. See http://www.freetype.org for details.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
|
@ -26,17 +35,47 @@
|
|||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED
|
||||
#define AGG_RASTERIZER_SCANLINE_AA_INCLUDED
|
||||
|
||||
#include "agg_rasterizer_cells_aa.h"
|
||||
#include "agg_rasterizer_sl_clip.h"
|
||||
#include "agg_rasterizer_scanline_aa_nogamma.h"
|
||||
#include "agg_gamma_functions.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
|
||||
//-----------------------------------------------------------------cell_aa
|
||||
// A pixel cell. There're no constructors defined and it was done
|
||||
// intentionally in order to avoid extra overhead when allocating an
|
||||
// array of cells.
|
||||
struct cell_aa
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int cover;
|
||||
int area;
|
||||
|
||||
void initial()
|
||||
{
|
||||
x = 0x7FFFFFFF;
|
||||
y = 0x7FFFFFFF;
|
||||
cover = 0;
|
||||
area = 0;
|
||||
}
|
||||
|
||||
void style(const cell_aa&) {}
|
||||
|
||||
int not_equal(int ex, int ey, const cell_aa&) const
|
||||
{
|
||||
return (ex - x) | (ey - y);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==================================================rasterizer_scanline_aa
|
||||
// Polygon rasterizer that is used to render filled polygons with
|
||||
// high-quality Anti-Aliasing. Internally, by default, the class uses
|
||||
|
|
|
@ -1,483 +0,0 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// The author gratefully acknowleges the support of David Turner,
|
||||
// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
|
||||
// libray - in producing this work. See http://www.freetype.org for details.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates has been sponsored by
|
||||
// Liberty Technology Systems, Inc., visit http://lib-sys.com
|
||||
//
|
||||
// Liberty Technology Systems, Inc. is the provider of
|
||||
// PostScript and PDF technology for software developers.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_RASTERIZER_SCANLINE_AA_NOGAMMA_INCLUDED
|
||||
#define AGG_RASTERIZER_SCANLINE_AA_NOGAMMA_INCLUDED
|
||||
|
||||
#include <limits>
|
||||
#include "agg_rasterizer_cells_aa.h"
|
||||
#include "agg_rasterizer_sl_clip.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
|
||||
//-----------------------------------------------------------------cell_aa
|
||||
// A pixel cell. There're no constructors defined and it was done
|
||||
// intentionally in order to avoid extra overhead when allocating an
|
||||
// array of cells.
|
||||
struct cell_aa
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int cover;
|
||||
int area;
|
||||
|
||||
void initial()
|
||||
{
|
||||
x = std::numeric_limits<int>::max();
|
||||
y = std::numeric_limits<int>::max();
|
||||
cover = 0;
|
||||
area = 0;
|
||||
}
|
||||
|
||||
void style(const cell_aa&) {}
|
||||
|
||||
int not_equal(int ex, int ey, const cell_aa&) const
|
||||
{
|
||||
return ((unsigned)ex - (unsigned)x) | ((unsigned)ey - (unsigned)y);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==================================================rasterizer_scanline_aa_nogamma
|
||||
// Polygon rasterizer that is used to render filled polygons with
|
||||
// high-quality Anti-Aliasing. Internally, by default, the class uses
|
||||
// integer coordinates in format 24.8, i.e. 24 bits for integer part
|
||||
// and 8 bits for fractional - see poly_subpixel_shift. This class can be
|
||||
// used in the following way:
|
||||
//
|
||||
// 1. filling_rule(filling_rule_e ft) - optional.
|
||||
//
|
||||
// 2. gamma() - optional.
|
||||
//
|
||||
// 3. reset()
|
||||
//
|
||||
// 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create
|
||||
// more than one contour, but each contour must consist of at least 3
|
||||
// vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3);
|
||||
// is the absolute minimum of vertices that define a triangle.
|
||||
// The algorithm does not check either the number of vertices nor
|
||||
// coincidence of their coordinates, but in the worst case it just
|
||||
// won't draw anything.
|
||||
// The orger of the vertices (clockwise or counterclockwise)
|
||||
// is important when using the non-zero filling rule (fill_non_zero).
|
||||
// In this case the vertex order of all the contours must be the same
|
||||
// if you want your intersecting polygons to be without "holes".
|
||||
// You actually can use different vertices order. If the contours do not
|
||||
// intersect each other the order is not important anyway. If they do,
|
||||
// contours with the same vertex order will be rendered without "holes"
|
||||
// while the intersecting contours with different orders will have "holes".
|
||||
//
|
||||
// filling_rule() and gamma() can be called anytime before "sweeping".
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa_nogamma
|
||||
{
|
||||
enum status
|
||||
{
|
||||
status_initial,
|
||||
status_move_to,
|
||||
status_line_to,
|
||||
status_closed
|
||||
};
|
||||
|
||||
public:
|
||||
typedef Clip clip_type;
|
||||
typedef typename Clip::conv_type conv_type;
|
||||
typedef typename Clip::coord_type coord_type;
|
||||
|
||||
enum aa_scale_e
|
||||
{
|
||||
aa_shift = 8,
|
||||
aa_scale = 1 << aa_shift,
|
||||
aa_mask = aa_scale - 1,
|
||||
aa_scale2 = aa_scale * 2,
|
||||
aa_mask2 = aa_scale2 - 1
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
rasterizer_scanline_aa_nogamma() :
|
||||
m_outline(),
|
||||
m_clipper(),
|
||||
m_filling_rule(fill_non_zero),
|
||||
m_auto_close(true),
|
||||
m_start_x(0),
|
||||
m_start_y(0),
|
||||
m_status(status_initial)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void reset();
|
||||
void reset_clipping();
|
||||
void clip_box(double x1, double y1, double x2, double y2);
|
||||
void filling_rule(filling_rule_e filling_rule);
|
||||
void auto_close(bool flag) { m_auto_close = flag; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned apply_gamma(unsigned cover) const
|
||||
{
|
||||
return cover;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void move_to(int x, int y);
|
||||
void line_to(int x, int y);
|
||||
void move_to_d(double x, double y);
|
||||
void line_to_d(double x, double y);
|
||||
void close_polygon();
|
||||
void add_vertex(double x, double y, unsigned cmd);
|
||||
|
||||
void edge(int x1, int y1, int x2, int y2);
|
||||
void edge_d(double x1, double y1, double x2, double y2);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
void add_path(VertexSource& vs, unsigned path_id=0)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
|
||||
unsigned cmd;
|
||||
vs.rewind(path_id);
|
||||
if(m_outline.sorted()) reset();
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
add_vertex(x, y, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
int min_x() const { return m_outline.min_x(); }
|
||||
int min_y() const { return m_outline.min_y(); }
|
||||
int max_x() const { return m_outline.max_x(); }
|
||||
int max_y() const { return m_outline.max_y(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void sort();
|
||||
bool rewind_scanlines();
|
||||
bool navigate_scanline(int y);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned calculate_alpha(int area) const
|
||||
{
|
||||
int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift);
|
||||
|
||||
if(cover < 0) cover = -cover;
|
||||
if(m_filling_rule == fill_even_odd)
|
||||
{
|
||||
cover &= aa_mask2;
|
||||
if(cover > aa_scale)
|
||||
{
|
||||
cover = aa_scale2 - cover;
|
||||
}
|
||||
}
|
||||
if(cover > aa_mask) cover = aa_mask;
|
||||
return cover;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Scanline> bool sweep_scanline(Scanline& sl)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(m_scan_y > m_outline.max_y()) return false;
|
||||
sl.reset_spans();
|
||||
unsigned num_cells = m_outline.scanline_num_cells(m_scan_y);
|
||||
const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y);
|
||||
int cover = 0;
|
||||
|
||||
while(num_cells)
|
||||
{
|
||||
const cell_aa* cur_cell = *cells;
|
||||
int x = cur_cell->x;
|
||||
int area = cur_cell->area;
|
||||
unsigned alpha;
|
||||
|
||||
cover += cur_cell->cover;
|
||||
|
||||
//accumulate all cells with the same X
|
||||
while(--num_cells)
|
||||
{
|
||||
cur_cell = *++cells;
|
||||
if(cur_cell->x != x) break;
|
||||
area += cur_cell->area;
|
||||
cover += cur_cell->cover;
|
||||
}
|
||||
|
||||
if(area)
|
||||
{
|
||||
alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area);
|
||||
if(alpha)
|
||||
{
|
||||
sl.add_cell(x, alpha);
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
if(num_cells && cur_cell->x > x)
|
||||
{
|
||||
alpha = calculate_alpha(cover << (poly_subpixel_shift + 1));
|
||||
if(alpha)
|
||||
{
|
||||
sl.add_span(x, cur_cell->x - x, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(sl.num_spans()) break;
|
||||
++m_scan_y;
|
||||
}
|
||||
|
||||
sl.finalize(m_scan_y);
|
||||
++m_scan_y;
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool hit_test(int tx, int ty);
|
||||
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
// Disable copying
|
||||
rasterizer_scanline_aa_nogamma(const rasterizer_scanline_aa_nogamma<Clip>&);
|
||||
const rasterizer_scanline_aa_nogamma<Clip>&
|
||||
operator = (const rasterizer_scanline_aa_nogamma<Clip>&);
|
||||
|
||||
private:
|
||||
rasterizer_cells_aa<cell_aa> m_outline;
|
||||
clip_type m_clipper;
|
||||
filling_rule_e m_filling_rule;
|
||||
bool m_auto_close;
|
||||
coord_type m_start_x;
|
||||
coord_type m_start_y;
|
||||
unsigned m_status;
|
||||
int m_scan_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa_nogamma<Clip>::reset()
|
||||
{
|
||||
m_outline.reset();
|
||||
m_status = status_initial;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa_nogamma<Clip>::filling_rule(filling_rule_e filling_rule)
|
||||
{
|
||||
m_filling_rule = filling_rule;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa_nogamma<Clip>::clip_box(double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
reset();
|
||||
m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1),
|
||||
conv_type::upscale(x2), conv_type::upscale(y2));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa_nogamma<Clip>::reset_clipping()
|
||||
{
|
||||
reset();
|
||||
m_clipper.reset_clipping();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa_nogamma<Clip>::close_polygon()
|
||||
{
|
||||
if(m_status == status_line_to)
|
||||
{
|
||||
m_clipper.line_to(m_outline, m_start_x, m_start_y);
|
||||
m_status = status_closed;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa_nogamma<Clip>::move_to(int x, int y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
if(m_auto_close) close_polygon();
|
||||
m_clipper.move_to(m_start_x = conv_type::downscale(x),
|
||||
m_start_y = conv_type::downscale(y));
|
||||
m_status = status_move_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa_nogamma<Clip>::line_to(int x, int y)
|
||||
{
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::downscale(x),
|
||||
conv_type::downscale(y));
|
||||
m_status = status_line_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa_nogamma<Clip>::move_to_d(double x, double y)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
if(m_auto_close) close_polygon();
|
||||
m_clipper.move_to(m_start_x = conv_type::upscale(x),
|
||||
m_start_y = conv_type::upscale(y));
|
||||
m_status = status_move_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa_nogamma<Clip>::line_to_d(double x, double y)
|
||||
{
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::upscale(x),
|
||||
conv_type::upscale(y));
|
||||
m_status = status_line_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa_nogamma<Clip>::add_vertex(double x, double y, unsigned cmd)
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
move_to_d(x, y);
|
||||
}
|
||||
else
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
line_to_d(x, y);
|
||||
}
|
||||
else
|
||||
if(is_close(cmd))
|
||||
{
|
||||
close_polygon();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa_nogamma<Clip>::edge(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1));
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::downscale(x2),
|
||||
conv_type::downscale(y2));
|
||||
m_status = status_move_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa_nogamma<Clip>::edge_d(double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
if(m_outline.sorted()) reset();
|
||||
m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1));
|
||||
m_clipper.line_to(m_outline,
|
||||
conv_type::upscale(x2),
|
||||
conv_type::upscale(y2));
|
||||
m_status = status_move_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
void rasterizer_scanline_aa_nogamma<Clip>::sort()
|
||||
{
|
||||
if(m_auto_close) close_polygon();
|
||||
m_outline.sort_cells();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE bool rasterizer_scanline_aa_nogamma<Clip>::rewind_scanlines()
|
||||
{
|
||||
if(m_auto_close) close_polygon();
|
||||
m_outline.sort_cells();
|
||||
if(m_outline.total_cells() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_scan_y = m_outline.min_y();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
AGG_INLINE bool rasterizer_scanline_aa_nogamma<Clip>::navigate_scanline(int y)
|
||||
{
|
||||
if(m_auto_close) close_polygon();
|
||||
m_outline.sort_cells();
|
||||
if(m_outline.total_cells() == 0 ||
|
||||
y < m_outline.min_y() ||
|
||||
y > m_outline.max_y())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_scan_y = y;
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class Clip>
|
||||
bool rasterizer_scanline_aa_nogamma<Clip>::hit_test(int tx, int ty)
|
||||
{
|
||||
if(!navigate_scanline(ty)) return false;
|
||||
scanline_hit_test sl(tx);
|
||||
sweep_scanline(sl);
|
||||
return sl.hit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,17 +1,27 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RASTERIZER_SL_CLIP_INCLUDED
|
||||
#define AGG_RASTERIZER_SL_CLIP_INCLUDED
|
||||
|
||||
|
@ -317,7 +327,7 @@ namespace agg
|
|||
rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {}
|
||||
|
||||
void reset_clipping() {}
|
||||
void clip_box(coord_type, coord_type, coord_type, coord_type) {}
|
||||
void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) {}
|
||||
void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; }
|
||||
|
||||
template<class Rasterizer>
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// class renderer_base
|
||||
//
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_BASE_INCLUDED
|
||||
|
@ -134,19 +139,6 @@ namespace agg
|
|||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill(const color_type& c)
|
||||
{
|
||||
unsigned y;
|
||||
if(width())
|
||||
{
|
||||
for(y = 0; y < height(); y++)
|
||||
{
|
||||
m_ren->blend_hline(0, y, width(), c, cover_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
|
|
|
@ -1,23 +1,30 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERER_SCANLINE_INCLUDED
|
||||
#define AGG_RENDERER_SCANLINE_INCLUDED
|
||||
|
||||
#include <limits>
|
||||
#include <cstdlib>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_renderer_base.h"
|
||||
|
||||
|
@ -67,7 +74,7 @@ namespace agg
|
|||
// "rgba8" is needed. Otherwise it will be implicitly
|
||||
// converted in the loop many times.
|
||||
//----------------------
|
||||
typename BaseRenderer::color_type ren_color = color;
|
||||
typename BaseRenderer::color_type ren_color(color);
|
||||
|
||||
sl.reset(ras.min_x(), ras.max_x());
|
||||
while(ras.sweep_scanline(sl))
|
||||
|
@ -747,7 +754,7 @@ namespace agg
|
|||
0,
|
||||
sl_len * sizeof(cover_type));
|
||||
|
||||
int sl_y = std::numeric_limits<int>::max();
|
||||
int sl_y = 0x7FFFFFFF;
|
||||
unsigned i;
|
||||
for(i = 0; i < num_styles; i++)
|
||||
{
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// class rendering_buffer
|
||||
//
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_RENDERING_BUFFER_INCLUDED
|
||||
|
@ -56,14 +61,14 @@ namespace agg
|
|||
//--------------------------------------------------------------------
|
||||
void attach(T* buf, unsigned width, unsigned height, int stride)
|
||||
{
|
||||
m_buf = m_start = buf;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_stride = stride;
|
||||
if(stride < 0)
|
||||
m_buf = m_start = buf;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_stride = stride;
|
||||
if(stride < 0)
|
||||
{
|
||||
m_start = m_buf - int(height - 1) * stride;
|
||||
}
|
||||
m_start = m_buf - int(height - 1) * stride;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -78,13 +83,13 @@ namespace agg
|
|||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE T* row_ptr(int, int y, unsigned)
|
||||
AGG_INLINE T* row_ptr(int, int y, unsigned)
|
||||
{
|
||||
return m_start + y * m_stride;
|
||||
}
|
||||
AGG_INLINE T* row_ptr(int y) { return m_start + y * m_stride; }
|
||||
AGG_INLINE const T* row_ptr(int y) const { return m_start + y * m_stride; }
|
||||
AGG_INLINE row_data row (int y) const
|
||||
AGG_INLINE T* row_ptr(int y) { return m_start + y * m_stride; }
|
||||
AGG_INLINE const T* row_ptr(int y) const { return m_start + y * m_stride; }
|
||||
AGG_INLINE row_data row (int y) const
|
||||
{
|
||||
return row_data(0, m_width-1, row_ptr(y));
|
||||
}
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Class scanline_p - a general purpose scanline container with packed spans.
|
||||
//
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Adaptation for 32-bit screen coordinates (scanline32_p) has been sponsored by
|
||||
|
|
75
src/agg/agg_shorten_path.h
Normal file
75
src/agg/agg_shorten_path.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SHORTEN_PATH_INCLUDED
|
||||
#define AGG_SHORTEN_PATH_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vertex_sequence.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===========================================================shorten_path
|
||||
template<class VertexSequence>
|
||||
void shorten_path(VertexSequence& vs, double s, unsigned closed = 0)
|
||||
{
|
||||
typedef typename VertexSequence::value_type vertex_type;
|
||||
|
||||
if(s > 0.0 && vs.size() > 1)
|
||||
{
|
||||
double d;
|
||||
int n = int(vs.size() - 2);
|
||||
while(n)
|
||||
{
|
||||
d = vs[n].dist;
|
||||
if(d > s) break;
|
||||
vs.remove_last();
|
||||
s -= d;
|
||||
--n;
|
||||
}
|
||||
if(vs.size() < 2)
|
||||
{
|
||||
vs.remove_all();
|
||||
}
|
||||
else
|
||||
{
|
||||
n = vs.size() - 1;
|
||||
vertex_type& prev = vs[n-1];
|
||||
vertex_type& last = vs[n];
|
||||
d = (prev.dist - s) / prev.dist;
|
||||
double x = prev.x + (last.x - prev.x) * d;
|
||||
double y = prev.y + (last.y - prev.y) * d;
|
||||
last.x = x;
|
||||
last.y = y;
|
||||
if(!prev(last)) vs.remove_last();
|
||||
vs.close(closed != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,21 +1,27 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 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.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Affine transformation classes.
|
||||
//
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_TRANS_AFFINE_INCLUDED
|
||||
#define AGG_TRANS_AFFINE_INCLUDED
|
||||
|
||||
|
@ -211,14 +217,14 @@ namespace agg
|
|||
|
||||
// Multiply the matrix by another one and return
|
||||
// the result in a separete matrix.
|
||||
trans_affine operator * (const trans_affine& m) const
|
||||
trans_affine operator * (const trans_affine& m)
|
||||
{
|
||||
return trans_affine(*this).multiply(m);
|
||||
}
|
||||
|
||||
// Multiply the matrix by inverse of another one
|
||||
// and return the result in a separete matrix.
|
||||
trans_affine operator / (const trans_affine& m) const
|
||||
trans_affine operator / (const trans_affine& m)
|
||||
{
|
||||
return trans_affine(*this).multiply_inv(m);
|
||||
}
|
||||
|
@ -292,7 +298,7 @@ namespace agg
|
|||
//------------------------------------------------------------------------
|
||||
inline void trans_affine::transform(double* x, double* y) const
|
||||
{
|
||||
double tmp = *x;
|
||||
register double tmp = *x;
|
||||
*x = tmp * sx + *y * shx + tx;
|
||||
*y = tmp * shy + *y * sy + ty;
|
||||
}
|
||||
|
@ -300,7 +306,7 @@ namespace agg
|
|||
//------------------------------------------------------------------------
|
||||
inline void trans_affine::transform_2x2(double* x, double* y) const
|
||||
{
|
||||
double tmp = *x;
|
||||
register double tmp = *x;
|
||||
*x = tmp * sx + *y * shx;
|
||||
*y = tmp * shy + *y * sy;
|
||||
}
|
||||
|
@ -308,9 +314,9 @@ namespace agg
|
|||
//------------------------------------------------------------------------
|
||||
inline void trans_affine::inverse_transform(double* x, double* y) const
|
||||
{
|
||||
double d = determinant_reciprocal();
|
||||
double a = (*x - tx) * d;
|
||||
double b = (*y - ty) * d;
|
||||
register double d = determinant_reciprocal();
|
||||
register double a = (*x - tx) * d;
|
||||
register double b = (*y - ty) * d;
|
||||
*x = a * sy - b * shx;
|
||||
*y = b * sx - a * shy;
|
||||
}
|
||||
|
|
103
src/agg/agg_vcgen_contour.h
Normal file
103
src/agg/agg_vcgen_contour.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_VCGEN_CONTOUR_INCLUDED
|
||||
#define AGG_VCGEN_CONTOUR_INCLUDED
|
||||
|
||||
#include "agg_math_stroke.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//----------------------------------------------------------vcgen_contour
|
||||
//
|
||||
// See Implementation agg_vcgen_contour.cpp
|
||||
//
|
||||
class vcgen_contour
|
||||
{
|
||||
enum status_e
|
||||
{
|
||||
initial,
|
||||
ready,
|
||||
outline,
|
||||
out_vertices,
|
||||
end_poly,
|
||||
stop
|
||||
};
|
||||
|
||||
public:
|
||||
typedef vertex_sequence<vertex_dist, 6> vertex_storage;
|
||||
typedef pod_bvector<point_d, 6> coord_storage;
|
||||
|
||||
vcgen_contour();
|
||||
|
||||
void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); }
|
||||
void line_join(line_join_e lj) { m_stroker.line_join(lj); }
|
||||
void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); }
|
||||
|
||||
line_cap_e line_cap() const { return m_stroker.line_cap(); }
|
||||
line_join_e line_join() const { return m_stroker.line_join(); }
|
||||
inner_join_e inner_join() const { return m_stroker.inner_join(); }
|
||||
|
||||
void width(double w) { m_stroker.width(m_width = w); }
|
||||
void miter_limit(double ml) { m_stroker.miter_limit(ml); }
|
||||
void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); }
|
||||
void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); }
|
||||
void approximation_scale(double as) { m_stroker.approximation_scale(as); }
|
||||
|
||||
double width() const { return m_width; }
|
||||
double miter_limit() const { return m_stroker.miter_limit(); }
|
||||
double inner_miter_limit() const { return m_stroker.inner_miter_limit(); }
|
||||
double approximation_scale() const { return m_stroker.approximation_scale(); }
|
||||
|
||||
void auto_detect_orientation(bool v) { m_auto_detect = v; }
|
||||
bool auto_detect_orientation() const { return m_auto_detect; }
|
||||
|
||||
// Generator interface
|
||||
void remove_all();
|
||||
void add_vertex(double x, double y, unsigned cmd);
|
||||
|
||||
// Vertex Source Interface
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
vcgen_contour(const vcgen_contour&);
|
||||
const vcgen_contour& operator = (const vcgen_contour&);
|
||||
|
||||
math_stroke<coord_storage> m_stroker;
|
||||
double m_width;
|
||||
vertex_storage m_src_vertices;
|
||||
coord_storage m_out_vertices;
|
||||
status_e m_status;
|
||||
unsigned m_src_vertex;
|
||||
unsigned m_out_vertex;
|
||||
unsigned m_closed;
|
||||
unsigned m_orientation;
|
||||
bool m_auto_detect;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
111
src/agg/agg_vcgen_stroke.h
Normal file
111
src/agg/agg_vcgen_stroke.h
Normal file
|
@ -0,0 +1,111 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_VCGEN_STROKE_INCLUDED
|
||||
#define AGG_VCGEN_STROKE_INCLUDED
|
||||
|
||||
#include "agg_math_stroke.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//============================================================vcgen_stroke
|
||||
//
|
||||
// See Implementation agg_vcgen_stroke.cpp
|
||||
// Stroke generator
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
class vcgen_stroke
|
||||
{
|
||||
enum status_e
|
||||
{
|
||||
initial,
|
||||
ready,
|
||||
cap1,
|
||||
cap2,
|
||||
outline1,
|
||||
close_first,
|
||||
outline2,
|
||||
out_vertices,
|
||||
end_poly1,
|
||||
end_poly2,
|
||||
stop
|
||||
};
|
||||
|
||||
public:
|
||||
typedef vertex_sequence<vertex_dist, 6> vertex_storage;
|
||||
typedef pod_bvector<point_d, 6> coord_storage;
|
||||
|
||||
vcgen_stroke();
|
||||
|
||||
void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); }
|
||||
void line_join(line_join_e lj) { m_stroker.line_join(lj); }
|
||||
void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); }
|
||||
|
||||
line_cap_e line_cap() const { return m_stroker.line_cap(); }
|
||||
line_join_e line_join() const { return m_stroker.line_join(); }
|
||||
inner_join_e inner_join() const { return m_stroker.inner_join(); }
|
||||
|
||||
void width(double w) { m_stroker.width(w); }
|
||||
void miter_limit(double ml) { m_stroker.miter_limit(ml); }
|
||||
void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); }
|
||||
void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); }
|
||||
void approximation_scale(double as) { m_stroker.approximation_scale(as); }
|
||||
|
||||
double width() const { return m_stroker.width(); }
|
||||
double miter_limit() const { return m_stroker.miter_limit(); }
|
||||
double inner_miter_limit() const { return m_stroker.inner_miter_limit(); }
|
||||
double approximation_scale() const { return m_stroker.approximation_scale(); }
|
||||
|
||||
void shorten(double s) { m_shorten = s; }
|
||||
double shorten() const { return m_shorten; }
|
||||
|
||||
// Vertex Generator Interface
|
||||
void remove_all();
|
||||
void add_vertex(double x, double y, unsigned cmd);
|
||||
|
||||
// Vertex Source Interface
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
vcgen_stroke(const vcgen_stroke&);
|
||||
const vcgen_stroke& operator = (const vcgen_stroke&);
|
||||
|
||||
math_stroke<coord_storage> m_stroker;
|
||||
vertex_storage m_src_vertices;
|
||||
coord_storage m_out_vertices;
|
||||
double m_shorten;
|
||||
unsigned m_closed;
|
||||
status_e m_status;
|
||||
status_e m_prev_status;
|
||||
unsigned m_src_vertex;
|
||||
unsigned m_out_vertex;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
178
src/agg/agg_vertex_sequence.h
Normal file
178
src/agg/agg_vertex_sequence.h
Normal file
|
@ -0,0 +1,178 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_VERTEX_SEQUENCE_INCLUDED
|
||||
#define AGG_VERTEX_SEQUENCE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_array.h"
|
||||
#include "agg_math.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//----------------------------------------------------------vertex_sequence
|
||||
// Modified agg::pod_bvector. The data is interpreted as a sequence
|
||||
// of vertices. It means that the type T must expose:
|
||||
//
|
||||
// bool T::operator() (const T& val)
|
||||
//
|
||||
// that is called every time new vertex is being added. The main purpose
|
||||
// of this operator is the possibility to calculate some values during
|
||||
// adding and to return true if the vertex fits some criteria or false if
|
||||
// it doesn't. In the last case the new vertex is not added.
|
||||
//
|
||||
// The simple example is filtering coinciding vertices with calculation
|
||||
// of the distance between the current and previous ones:
|
||||
//
|
||||
// struct vertex_dist
|
||||
// {
|
||||
// double x;
|
||||
// double y;
|
||||
// double dist;
|
||||
//
|
||||
// vertex_dist() {}
|
||||
// vertex_dist(double x_, double y_) :
|
||||
// x(x_),
|
||||
// y(y_),
|
||||
// dist(0.0)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// bool operator () (const vertex_dist& val)
|
||||
// {
|
||||
// return (dist = calc_distance(x, y, val.x, val.y)) > EPSILON;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// Function close() calls this operator and removes the last vertex if
|
||||
// necessary.
|
||||
//------------------------------------------------------------------------
|
||||
template<class T, unsigned S=6>
|
||||
class vertex_sequence : public pod_bvector<T, S>
|
||||
{
|
||||
public:
|
||||
typedef pod_bvector<T, S> base_type;
|
||||
|
||||
void add(const T& val);
|
||||
void modify_last(const T& val);
|
||||
void close(bool remove_flag);
|
||||
};
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T, unsigned S>
|
||||
void vertex_sequence<T, S>::add(const T& val)
|
||||
{
|
||||
if(base_type::size() > 1)
|
||||
{
|
||||
if(!(*this)[base_type::size() - 2]((*this)[base_type::size() - 1]))
|
||||
{
|
||||
base_type::remove_last();
|
||||
}
|
||||
}
|
||||
base_type::add(val);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T, unsigned S>
|
||||
void vertex_sequence<T, S>::modify_last(const T& val)
|
||||
{
|
||||
base_type::remove_last();
|
||||
add(val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T, unsigned S>
|
||||
void vertex_sequence<T, S>::close(bool closed)
|
||||
{
|
||||
while(base_type::size() > 1)
|
||||
{
|
||||
if((*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) break;
|
||||
T t = (*this)[base_type::size() - 1];
|
||||
base_type::remove_last();
|
||||
modify_last(t);
|
||||
}
|
||||
|
||||
if(closed)
|
||||
{
|
||||
while(base_type::size() > 1)
|
||||
{
|
||||
if((*this)[base_type::size() - 1]((*this)[0])) break;
|
||||
base_type::remove_last();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------vertex_dist
|
||||
// Vertex (x, y) with the distance to the next one. The last vertex has
|
||||
// distance between the last and the first points if the polygon is closed
|
||||
// and 0.0 if it's a polyline.
|
||||
struct vertex_dist
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
double dist;
|
||||
|
||||
vertex_dist() {}
|
||||
vertex_dist(double x_, double y_) :
|
||||
x(x_),
|
||||
y(y_),
|
||||
dist(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator () (const vertex_dist& val)
|
||||
{
|
||||
bool ret = (dist = calc_distance(x, y, val.x, val.y)) > vertex_dist_epsilon;
|
||||
if(!ret) dist = 1.0 / vertex_dist_epsilon;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------vertex_dist_cmd
|
||||
// Save as the above but with additional "command" value
|
||||
struct vertex_dist_cmd : public vertex_dist
|
||||
{
|
||||
unsigned cmd;
|
||||
|
||||
vertex_dist_cmd() {}
|
||||
vertex_dist_cmd(double x_, double y_, unsigned cmd_) :
|
||||
vertex_dist(x_, y_),
|
||||
cmd(cmd_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
366
src/agg/copying
366
src/agg/copying
|
@ -1,65 +1,339 @@
|
|||
The Anti-Grain Geometry Project
|
||||
A high quality rendering engine for C++
|
||||
http://antigrain.com
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Anti-Grain Geometry has dual licensing model. The Modified BSD
|
||||
License was first added in version v2.4 just for convenience.
|
||||
It is a simple, permissive non-copyleft free software license,
|
||||
compatible with the GNU GPL. It's well proven and recognizable.
|
||||
See http://www.fsf.org/licensing/licenses/index_html#ModifiedBSD
|
||||
for details.
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Note that the Modified BSD license DOES NOT restrict your rights
|
||||
if you choose the Anti-Grain Geometry Public License.
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
Anti-Grain Geometry Public License
|
||||
====================================================
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
Anti-Grain Geometry - Version 2.4
|
||||
Copyright (C) 2002-2005 Maxim Shemanarev (McSeem)
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
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.
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Modified BSD License
|
||||
====================================================
|
||||
Anti-Grain Geometry - Version 2.4
|
||||
Copyright (C) 2002-2005 Maxim Shemanarev (McSeem)
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
3. The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
|
22
src/agg_svg/CMakeLists.txt
Normal file
22
src/agg_svg/CMakeLists.txt
Normal file
|
@ -0,0 +1,22 @@
|
|||
project(agg_svg)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
add_library(agg_svg STATIC
|
||||
agg_svg_exception.h
|
||||
agg_svg_parser.cpp
|
||||
agg_svg_parser.h
|
||||
agg_svg_path_renderer.cpp
|
||||
agg_svg_path_renderer.h
|
||||
agg_svg_path_tokenizer.cpp
|
||||
agg_svg_path_tokenizer.h
|
||||
|
||||
# agg_bezier_arc.cpp
|
||||
agg_curves.cpp
|
||||
agg_trans_affine.cpp
|
||||
agg_vcgen_contour.cpp
|
||||
agg_vcgen_stroke.cpp
|
||||
)
|
||||
|
||||
target_include_directories(agg_svg PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
target_link_libraries(agg_svg ${EXPAT_LIBRARIES})
|
261
src/agg_svg/agg_bezier_arc.cpp
Normal file
261
src/agg_svg/agg_bezier_arc.cpp
Normal file
|
@ -0,0 +1,261 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include <math.h>
|
||||
#include "agg_bezier_arc.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
// This epsilon is used to prevent us from adding degenerate curves
|
||||
// (converging to a single point).
|
||||
// The value isn't very critical. Function arc_to_bezier() has a limit
|
||||
// of the sweep_angle. If fabs(sweep_angle) exceeds pi/2 the curve
|
||||
// becomes inaccurate. But slight exceeding is quite appropriate.
|
||||
//-------------------------------------------------bezier_arc_angle_epsilon
|
||||
const double bezier_arc_angle_epsilon = 0.01;
|
||||
|
||||
//------------------------------------------------------------arc_to_bezier
|
||||
void arc_to_bezier(double cx, double cy, double rx, double ry,
|
||||
double start_angle, double sweep_angle,
|
||||
double* curve)
|
||||
{
|
||||
double x0 = cos(sweep_angle / 2.0);
|
||||
double y0 = sin(sweep_angle / 2.0);
|
||||
double tx = (1.0 - x0) * 4.0 / 3.0;
|
||||
double ty = y0 - tx * x0 / y0;
|
||||
double px[4];
|
||||
double py[4];
|
||||
px[0] = x0;
|
||||
py[0] = -y0;
|
||||
px[1] = x0 + tx;
|
||||
py[1] = -ty;
|
||||
px[2] = x0 + tx;
|
||||
py[2] = ty;
|
||||
px[3] = x0;
|
||||
py[3] = y0;
|
||||
|
||||
double sn = sin(start_angle + sweep_angle / 2.0);
|
||||
double cs = cos(start_angle + sweep_angle / 2.0);
|
||||
|
||||
unsigned i;
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
curve[i * 2] = cx + rx * (px[i] * cs - py[i] * sn);
|
||||
curve[i * 2 + 1] = cy + ry * (px[i] * sn + py[i] * cs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void bezier_arc::init(double x, double y,
|
||||
double rx, double ry,
|
||||
double start_angle,
|
||||
double sweep_angle)
|
||||
{
|
||||
start_angle = fmod(start_angle, 2.0 * pi);
|
||||
if(sweep_angle >= 2.0 * pi) sweep_angle = 2.0 * pi;
|
||||
if(sweep_angle <= -2.0 * pi) sweep_angle = -2.0 * pi;
|
||||
|
||||
if(fabs(sweep_angle) < 1e-10)
|
||||
{
|
||||
m_num_vertices = 4;
|
||||
m_cmd = path_cmd_line_to;
|
||||
m_vertices[0] = x + rx * cos(start_angle);
|
||||
m_vertices[1] = y + ry * sin(start_angle);
|
||||
m_vertices[2] = x + rx * cos(start_angle + sweep_angle);
|
||||
m_vertices[3] = y + ry * sin(start_angle + sweep_angle);
|
||||
return;
|
||||
}
|
||||
|
||||
double total_sweep = 0.0;
|
||||
double local_sweep = 0.0;
|
||||
double prev_sweep;
|
||||
m_num_vertices = 2;
|
||||
m_cmd = path_cmd_curve4;
|
||||
bool done = false;
|
||||
do
|
||||
{
|
||||
if(sweep_angle < 0.0)
|
||||
{
|
||||
prev_sweep = total_sweep;
|
||||
local_sweep = -pi * 0.5;
|
||||
total_sweep -= pi * 0.5;
|
||||
if(total_sweep <= sweep_angle + bezier_arc_angle_epsilon)
|
||||
{
|
||||
local_sweep = sweep_angle - prev_sweep;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_sweep = total_sweep;
|
||||
local_sweep = pi * 0.5;
|
||||
total_sweep += pi * 0.5;
|
||||
if(total_sweep >= sweep_angle - bezier_arc_angle_epsilon)
|
||||
{
|
||||
local_sweep = sweep_angle - prev_sweep;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
arc_to_bezier(x, y, rx, ry,
|
||||
start_angle,
|
||||
local_sweep,
|
||||
m_vertices + m_num_vertices - 2);
|
||||
|
||||
m_num_vertices += 6;
|
||||
start_angle += local_sweep;
|
||||
}
|
||||
while(!done && m_num_vertices < 26);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void bezier_arc_svg::init(double x0, double y0,
|
||||
double rx, double ry,
|
||||
double angle,
|
||||
bool large_arc_flag,
|
||||
bool sweep_flag,
|
||||
double x2, double y2)
|
||||
{
|
||||
m_radii_ok = true;
|
||||
|
||||
if(rx < 0.0) rx = -rx;
|
||||
if(ry < 0.0) ry = -rx;
|
||||
|
||||
// Calculate the middle point between
|
||||
// the current and the final points
|
||||
//------------------------
|
||||
double dx2 = (x0 - x2) / 2.0;
|
||||
double dy2 = (y0 - y2) / 2.0;
|
||||
|
||||
double cos_a = cos(angle);
|
||||
double sin_a = sin(angle);
|
||||
|
||||
// Calculate (x1, y1)
|
||||
//------------------------
|
||||
double x1 = cos_a * dx2 + sin_a * dy2;
|
||||
double y1 = -sin_a * dx2 + cos_a * dy2;
|
||||
|
||||
// Ensure radii are large enough
|
||||
//------------------------
|
||||
double prx = rx * rx;
|
||||
double pry = ry * ry;
|
||||
double px1 = x1 * x1;
|
||||
double py1 = y1 * y1;
|
||||
|
||||
// Check that radii are large enough
|
||||
//------------------------
|
||||
double radii_check = px1/prx + py1/pry;
|
||||
if(radii_check > 1.0)
|
||||
{
|
||||
rx = sqrt(radii_check) * rx;
|
||||
ry = sqrt(radii_check) * ry;
|
||||
prx = rx * rx;
|
||||
pry = ry * ry;
|
||||
if(radii_check > 10.0) m_radii_ok = false;
|
||||
}
|
||||
|
||||
// Calculate (cx1, cy1)
|
||||
//------------------------
|
||||
double sign = (large_arc_flag == sweep_flag) ? -1.0 : 1.0;
|
||||
double sq = (prx*pry - prx*py1 - pry*px1) / (prx*py1 + pry*px1);
|
||||
double coef = sign * sqrt((sq < 0) ? 0 : sq);
|
||||
double cx1 = coef * ((rx * y1) / ry);
|
||||
double cy1 = coef * -((ry * x1) / rx);
|
||||
|
||||
//
|
||||
// Calculate (cx, cy) from (cx1, cy1)
|
||||
//------------------------
|
||||
double sx2 = (x0 + x2) / 2.0;
|
||||
double sy2 = (y0 + y2) / 2.0;
|
||||
double cx = sx2 + (cos_a * cx1 - sin_a * cy1);
|
||||
double cy = sy2 + (sin_a * cx1 + cos_a * cy1);
|
||||
|
||||
// Calculate the start_angle (angle1) and the sweep_angle (dangle)
|
||||
//------------------------
|
||||
double ux = (x1 - cx1) / rx;
|
||||
double uy = (y1 - cy1) / ry;
|
||||
double vx = (-x1 - cx1) / rx;
|
||||
double vy = (-y1 - cy1) / ry;
|
||||
double p, n;
|
||||
|
||||
// Calculate the angle start
|
||||
//------------------------
|
||||
n = sqrt(ux*ux + uy*uy);
|
||||
p = ux; // (1 * ux) + (0 * uy)
|
||||
sign = (uy < 0) ? -1.0 : 1.0;
|
||||
double v = p / n;
|
||||
if(v < -1.0) v = -1.0;
|
||||
if(v > 1.0) v = 1.0;
|
||||
double start_angle = sign * acos(v);
|
||||
|
||||
// Calculate the sweep angle
|
||||
//------------------------
|
||||
n = sqrt((ux*ux + uy*uy) * (vx*vx + vy*vy));
|
||||
p = ux * vx + uy * vy;
|
||||
sign = (ux * vy - uy * vx < 0) ? -1.0 : 1.0;
|
||||
v = p / n;
|
||||
if(v < -1.0) v = -1.0;
|
||||
if(v > 1.0) v = 1.0;
|
||||
double sweep_angle = sign * acos(v);
|
||||
if(!sweep_flag && sweep_angle > 0)
|
||||
{
|
||||
sweep_angle -= pi * 2.0;
|
||||
}
|
||||
else
|
||||
if (sweep_flag && sweep_angle < 0)
|
||||
{
|
||||
sweep_angle += pi * 2.0;
|
||||
}
|
||||
|
||||
// We can now build and transform the resulting arc
|
||||
//------------------------
|
||||
m_arc.init(0.0, 0.0, rx, ry, start_angle, sweep_angle);
|
||||
trans_affine mtx = trans_affine_rotation(angle);
|
||||
mtx *= trans_affine_translation(cx, cy);
|
||||
|
||||
for(unsigned i = 2; i < m_arc.num_vertices()-2; i += 2)
|
||||
{
|
||||
mtx.transform(m_arc.vertices() + i, m_arc.vertices() + i + 1);
|
||||
}
|
||||
|
||||
// We must make sure that the starting and ending points
|
||||
// exactly coincide with the initial (x0,y0) and (x2,y2)
|
||||
m_arc.vertices()[0] = x0;
|
||||
m_arc.vertices()[1] = y0;
|
||||
if(m_arc.num_vertices() > 2)
|
||||
{
|
||||
m_arc.vertices()[m_arc.num_vertices() - 2] = x2;
|
||||
m_arc.vertices()[m_arc.num_vertices() - 1] = y2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
620
src/agg_svg/agg_curves.cpp
Normal file
620
src/agg_svg/agg_curves.cpp
Normal file
|
@ -0,0 +1,620 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include <math.h>
|
||||
#include <agg/agg_curves.h>
|
||||
#include <agg/agg_math.h>
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const double curve_distance_epsilon = 1e-30;
|
||||
const double curve_collinearity_epsilon = 1e-30;
|
||||
const double curve_angle_tolerance_epsilon = 0.01;
|
||||
enum curve_recursion_limit_e { curve_recursion_limit = 32 };
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve3_inc::approximation_scale(double s)
|
||||
{
|
||||
m_scale = s;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
double curve3_inc::approximation_scale() const
|
||||
{
|
||||
return m_scale;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve3_inc::init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3)
|
||||
{
|
||||
m_start_x = x1;
|
||||
m_start_y = y1;
|
||||
m_end_x = x3;
|
||||
m_end_y = y3;
|
||||
|
||||
double dx1 = x2 - x1;
|
||||
double dy1 = y2 - y1;
|
||||
double dx2 = x3 - x2;
|
||||
double dy2 = y3 - y2;
|
||||
|
||||
double len = sqrt(dx1 * dx1 + dy1 * dy1) + sqrt(dx2 * dx2 + dy2 * dy2);
|
||||
|
||||
m_num_steps = uround(len * 0.25 * m_scale);
|
||||
|
||||
if(m_num_steps < 4)
|
||||
{
|
||||
m_num_steps = 4;
|
||||
}
|
||||
|
||||
double subdivide_step = 1.0 / m_num_steps;
|
||||
double subdivide_step2 = subdivide_step * subdivide_step;
|
||||
|
||||
double tmpx = (x1 - x2 * 2.0 + x3) * subdivide_step2;
|
||||
double tmpy = (y1 - y2 * 2.0 + y3) * subdivide_step2;
|
||||
|
||||
m_saved_fx = m_fx = x1;
|
||||
m_saved_fy = m_fy = y1;
|
||||
|
||||
m_saved_dfx = m_dfx = tmpx + (x2 - x1) * (2.0 * subdivide_step);
|
||||
m_saved_dfy = m_dfy = tmpy + (y2 - y1) * (2.0 * subdivide_step);
|
||||
|
||||
m_ddfx = tmpx * 2.0;
|
||||
m_ddfy = tmpy * 2.0;
|
||||
|
||||
m_step = m_num_steps;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve3_inc::rewind(unsigned)
|
||||
{
|
||||
if(m_num_steps == 0)
|
||||
{
|
||||
m_step = -1;
|
||||
return;
|
||||
}
|
||||
m_step = m_num_steps;
|
||||
m_fx = m_saved_fx;
|
||||
m_fy = m_saved_fy;
|
||||
m_dfx = m_saved_dfx;
|
||||
m_dfy = m_saved_dfy;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
unsigned curve3_inc::vertex(double* x, double* y)
|
||||
{
|
||||
if(m_step < 0) return path_cmd_stop;
|
||||
if(m_step == m_num_steps)
|
||||
{
|
||||
*x = m_start_x;
|
||||
*y = m_start_y;
|
||||
--m_step;
|
||||
return path_cmd_move_to;
|
||||
}
|
||||
if(m_step == 0)
|
||||
{
|
||||
*x = m_end_x;
|
||||
*y = m_end_y;
|
||||
--m_step;
|
||||
return path_cmd_line_to;
|
||||
}
|
||||
m_fx += m_dfx;
|
||||
m_fy += m_dfy;
|
||||
m_dfx += m_ddfx;
|
||||
m_dfy += m_ddfy;
|
||||
*x = m_fx;
|
||||
*y = m_fy;
|
||||
--m_step;
|
||||
return path_cmd_line_to;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve3_div::init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3)
|
||||
{
|
||||
m_points.remove_all();
|
||||
m_distance_tolerance_square = 0.5 / m_approximation_scale;
|
||||
m_distance_tolerance_square *= m_distance_tolerance_square;
|
||||
bezier(x1, y1, x2, y2, x3, y3);
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve3_div::recursive_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
unsigned level)
|
||||
{
|
||||
if(level > curve_recursion_limit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate all the mid-points of the line segments
|
||||
//----------------------
|
||||
double x12 = (x1 + x2) / 2;
|
||||
double y12 = (y1 + y2) / 2;
|
||||
double x23 = (x2 + x3) / 2;
|
||||
double y23 = (y2 + y3) / 2;
|
||||
double x123 = (x12 + x23) / 2;
|
||||
double y123 = (y12 + y23) / 2;
|
||||
|
||||
double dx = x3-x1;
|
||||
double dy = y3-y1;
|
||||
double d = fabs(((x2 - x3) * dy - (y2 - y3) * dx));
|
||||
double da;
|
||||
|
||||
if(d > curve_collinearity_epsilon)
|
||||
{
|
||||
// Regular case
|
||||
//-----------------
|
||||
if(d * d <= m_distance_tolerance_square * (dx*dx + dy*dy))
|
||||
{
|
||||
// If the curvature doesn't exceed the distance_tolerance value
|
||||
// we tend to finish subdivisions.
|
||||
//----------------------
|
||||
if(m_angle_tolerance < curve_angle_tolerance_epsilon)
|
||||
{
|
||||
m_points.add(point_d(x123, y123));
|
||||
return;
|
||||
}
|
||||
|
||||
// Angle & Cusp Condition
|
||||
//----------------------
|
||||
da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));
|
||||
if(da >= pi) da = 2*pi - da;
|
||||
|
||||
if(da < m_angle_tolerance)
|
||||
{
|
||||
// Finally we can stop the recursion
|
||||
//----------------------
|
||||
m_points.add(point_d(x123, y123));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Collinear case
|
||||
//------------------
|
||||
da = dx*dx + dy*dy;
|
||||
if(da == 0)
|
||||
{
|
||||
d = calc_sq_distance(x1, y1, x2, y2);
|
||||
}
|
||||
else
|
||||
{
|
||||
d = ((x2 - x1)*dx + (y2 - y1)*dy) / da;
|
||||
if(d > 0 && d < 1)
|
||||
{
|
||||
// Simple collinear case, 1---2---3
|
||||
// We can leave just two endpoints
|
||||
return;
|
||||
}
|
||||
if(d <= 0) d = calc_sq_distance(x2, y2, x1, y1);
|
||||
else if(d >= 1) d = calc_sq_distance(x2, y2, x3, y3);
|
||||
else d = calc_sq_distance(x2, y2, x1 + d*dx, y1 + d*dy);
|
||||
}
|
||||
if(d < m_distance_tolerance_square)
|
||||
{
|
||||
m_points.add(point_d(x2, y2));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Continue subdivision
|
||||
//----------------------
|
||||
recursive_bezier(x1, y1, x12, y12, x123, y123, level + 1);
|
||||
recursive_bezier(x123, y123, x23, y23, x3, y3, level + 1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve3_div::bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3)
|
||||
{
|
||||
m_points.add(point_d(x1, y1));
|
||||
recursive_bezier(x1, y1, x2, y2, x3, y3, 0);
|
||||
m_points.add(point_d(x3, y3));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve4_inc::approximation_scale(double s)
|
||||
{
|
||||
m_scale = s;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
double curve4_inc::approximation_scale() const
|
||||
{
|
||||
return m_scale;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static double MSC60_fix_ICE(double v) { return v; }
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve4_inc::init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
m_start_x = x1;
|
||||
m_start_y = y1;
|
||||
m_end_x = x4;
|
||||
m_end_y = y4;
|
||||
|
||||
double dx1 = x2 - x1;
|
||||
double dy1 = y2 - y1;
|
||||
double dx2 = x3 - x2;
|
||||
double dy2 = y3 - y2;
|
||||
double dx3 = x4 - x3;
|
||||
double dy3 = y4 - y3;
|
||||
|
||||
double len = (sqrt(dx1 * dx1 + dy1 * dy1) +
|
||||
sqrt(dx2 * dx2 + dy2 * dy2) +
|
||||
sqrt(dx3 * dx3 + dy3 * dy3)) * 0.25 * m_scale;
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1200
|
||||
m_num_steps = uround(MSC60_fix_ICE(len));
|
||||
#else
|
||||
m_num_steps = uround(len);
|
||||
#endif
|
||||
|
||||
if(m_num_steps < 4)
|
||||
{
|
||||
m_num_steps = 4;
|
||||
}
|
||||
|
||||
double subdivide_step = 1.0 / m_num_steps;
|
||||
double subdivide_step2 = subdivide_step * subdivide_step;
|
||||
double subdivide_step3 = subdivide_step * subdivide_step * subdivide_step;
|
||||
|
||||
double pre1 = 3.0 * subdivide_step;
|
||||
double pre2 = 3.0 * subdivide_step2;
|
||||
double pre4 = 6.0 * subdivide_step2;
|
||||
double pre5 = 6.0 * subdivide_step3;
|
||||
|
||||
double tmp1x = x1 - x2 * 2.0 + x3;
|
||||
double tmp1y = y1 - y2 * 2.0 + y3;
|
||||
|
||||
double tmp2x = (x2 - x3) * 3.0 - x1 + x4;
|
||||
double tmp2y = (y2 - y3) * 3.0 - y1 + y4;
|
||||
|
||||
m_saved_fx = m_fx = x1;
|
||||
m_saved_fy = m_fy = y1;
|
||||
|
||||
m_saved_dfx = m_dfx = (x2 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdivide_step3;
|
||||
m_saved_dfy = m_dfy = (y2 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdivide_step3;
|
||||
|
||||
m_saved_ddfx = m_ddfx = tmp1x * pre4 + tmp2x * pre5;
|
||||
m_saved_ddfy = m_ddfy = tmp1y * pre4 + tmp2y * pre5;
|
||||
|
||||
m_dddfx = tmp2x * pre5;
|
||||
m_dddfy = tmp2y * pre5;
|
||||
|
||||
m_step = m_num_steps;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve4_inc::rewind(unsigned)
|
||||
{
|
||||
if(m_num_steps == 0)
|
||||
{
|
||||
m_step = -1;
|
||||
return;
|
||||
}
|
||||
m_step = m_num_steps;
|
||||
m_fx = m_saved_fx;
|
||||
m_fy = m_saved_fy;
|
||||
m_dfx = m_saved_dfx;
|
||||
m_dfy = m_saved_dfy;
|
||||
m_ddfx = m_saved_ddfx;
|
||||
m_ddfy = m_saved_ddfy;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
unsigned curve4_inc::vertex(double* x, double* y)
|
||||
{
|
||||
if(m_step < 0) return path_cmd_stop;
|
||||
if(m_step == m_num_steps)
|
||||
{
|
||||
*x = m_start_x;
|
||||
*y = m_start_y;
|
||||
--m_step;
|
||||
return path_cmd_move_to;
|
||||
}
|
||||
|
||||
if(m_step == 0)
|
||||
{
|
||||
*x = m_end_x;
|
||||
*y = m_end_y;
|
||||
--m_step;
|
||||
return path_cmd_line_to;
|
||||
}
|
||||
|
||||
m_fx += m_dfx;
|
||||
m_fy += m_dfy;
|
||||
m_dfx += m_ddfx;
|
||||
m_dfy += m_ddfy;
|
||||
m_ddfx += m_dddfx;
|
||||
m_ddfy += m_dddfy;
|
||||
|
||||
*x = m_fx;
|
||||
*y = m_fy;
|
||||
--m_step;
|
||||
return path_cmd_line_to;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve4_div::init(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
m_points.remove_all();
|
||||
m_distance_tolerance_square = 0.5 / m_approximation_scale;
|
||||
m_distance_tolerance_square *= m_distance_tolerance_square;
|
||||
bezier(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve4_div::recursive_bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4,
|
||||
unsigned level)
|
||||
{
|
||||
if(level > curve_recursion_limit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate all the mid-points of the line segments
|
||||
//----------------------
|
||||
double x12 = (x1 + x2) / 2;
|
||||
double y12 = (y1 + y2) / 2;
|
||||
double x23 = (x2 + x3) / 2;
|
||||
double y23 = (y2 + y3) / 2;
|
||||
double x34 = (x3 + x4) / 2;
|
||||
double y34 = (y3 + y4) / 2;
|
||||
double x123 = (x12 + x23) / 2;
|
||||
double y123 = (y12 + y23) / 2;
|
||||
double x234 = (x23 + x34) / 2;
|
||||
double y234 = (y23 + y34) / 2;
|
||||
double x1234 = (x123 + x234) / 2;
|
||||
double y1234 = (y123 + y234) / 2;
|
||||
|
||||
|
||||
// Try to approximate the full cubic curve by a single straight line
|
||||
//------------------
|
||||
double dx = x4-x1;
|
||||
double dy = y4-y1;
|
||||
|
||||
double d2 = fabs(((x2 - x4) * dy - (y2 - y4) * dx));
|
||||
double d3 = fabs(((x3 - x4) * dy - (y3 - y4) * dx));
|
||||
double da1, da2, k;
|
||||
|
||||
switch((int(d2 > curve_collinearity_epsilon) << 1) +
|
||||
int(d3 > curve_collinearity_epsilon))
|
||||
{
|
||||
case 0:
|
||||
// All collinear OR p1==p4
|
||||
//----------------------
|
||||
k = dx*dx + dy*dy;
|
||||
if(k == 0)
|
||||
{
|
||||
d2 = calc_sq_distance(x1, y1, x2, y2);
|
||||
d3 = calc_sq_distance(x4, y4, x3, y3);
|
||||
}
|
||||
else
|
||||
{
|
||||
k = 1 / k;
|
||||
da1 = x2 - x1;
|
||||
da2 = y2 - y1;
|
||||
d2 = k * (da1*dx + da2*dy);
|
||||
da1 = x3 - x1;
|
||||
da2 = y3 - y1;
|
||||
d3 = k * (da1*dx + da2*dy);
|
||||
if(d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1)
|
||||
{
|
||||
// Simple collinear case, 1---2---3---4
|
||||
// We can leave just two endpoints
|
||||
return;
|
||||
}
|
||||
if(d2 <= 0) d2 = calc_sq_distance(x2, y2, x1, y1);
|
||||
else if(d2 >= 1) d2 = calc_sq_distance(x2, y2, x4, y4);
|
||||
else d2 = calc_sq_distance(x2, y2, x1 + d2*dx, y1 + d2*dy);
|
||||
|
||||
if(d3 <= 0) d3 = calc_sq_distance(x3, y3, x1, y1);
|
||||
else if(d3 >= 1) d3 = calc_sq_distance(x3, y3, x4, y4);
|
||||
else d3 = calc_sq_distance(x3, y3, x1 + d3*dx, y1 + d3*dy);
|
||||
}
|
||||
if(d2 > d3)
|
||||
{
|
||||
if(d2 < m_distance_tolerance_square)
|
||||
{
|
||||
m_points.add(point_d(x2, y2));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(d3 < m_distance_tolerance_square)
|
||||
{
|
||||
m_points.add(point_d(x3, y3));
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// p1,p2,p4 are collinear, p3 is significant
|
||||
//----------------------
|
||||
if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy))
|
||||
{
|
||||
if(m_angle_tolerance < curve_angle_tolerance_epsilon)
|
||||
{
|
||||
m_points.add(point_d(x23, y23));
|
||||
return;
|
||||
}
|
||||
|
||||
// Angle Condition
|
||||
//----------------------
|
||||
da1 = fabs(atan2(y4 - y3, x4 - x3) - atan2(y3 - y2, x3 - x2));
|
||||
if(da1 >= pi) da1 = 2*pi - da1;
|
||||
|
||||
if(da1 < m_angle_tolerance)
|
||||
{
|
||||
m_points.add(point_d(x2, y2));
|
||||
m_points.add(point_d(x3, y3));
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_cusp_limit != 0.0)
|
||||
{
|
||||
if(da1 > m_cusp_limit)
|
||||
{
|
||||
m_points.add(point_d(x3, y3));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// p1,p3,p4 are collinear, p2 is significant
|
||||
//----------------------
|
||||
if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy))
|
||||
{
|
||||
if(m_angle_tolerance < curve_angle_tolerance_epsilon)
|
||||
{
|
||||
m_points.add(point_d(x23, y23));
|
||||
return;
|
||||
}
|
||||
|
||||
// Angle Condition
|
||||
//----------------------
|
||||
da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));
|
||||
if(da1 >= pi) da1 = 2*pi - da1;
|
||||
|
||||
if(da1 < m_angle_tolerance)
|
||||
{
|
||||
m_points.add(point_d(x2, y2));
|
||||
m_points.add(point_d(x3, y3));
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_cusp_limit != 0.0)
|
||||
{
|
||||
if(da1 > m_cusp_limit)
|
||||
{
|
||||
m_points.add(point_d(x2, y2));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// Regular case
|
||||
//-----------------
|
||||
if((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy))
|
||||
{
|
||||
// If the curvature doesn't exceed the distance_tolerance value
|
||||
// we tend to finish subdivisions.
|
||||
//----------------------
|
||||
if(m_angle_tolerance < curve_angle_tolerance_epsilon)
|
||||
{
|
||||
m_points.add(point_d(x23, y23));
|
||||
return;
|
||||
}
|
||||
|
||||
// Angle & Cusp Condition
|
||||
//----------------------
|
||||
k = atan2(y3 - y2, x3 - x2);
|
||||
da1 = fabs(k - atan2(y2 - y1, x2 - x1));
|
||||
da2 = fabs(atan2(y4 - y3, x4 - x3) - k);
|
||||
if(da1 >= pi) da1 = 2*pi - da1;
|
||||
if(da2 >= pi) da2 = 2*pi - da2;
|
||||
|
||||
if(da1 + da2 < m_angle_tolerance)
|
||||
{
|
||||
// Finally we can stop the recursion
|
||||
//----------------------
|
||||
m_points.add(point_d(x23, y23));
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_cusp_limit != 0.0)
|
||||
{
|
||||
if(da1 > m_cusp_limit)
|
||||
{
|
||||
m_points.add(point_d(x2, y2));
|
||||
return;
|
||||
}
|
||||
|
||||
if(da2 > m_cusp_limit)
|
||||
{
|
||||
m_points.add(point_d(x3, y3));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Continue subdivision
|
||||
//----------------------
|
||||
recursive_bezier(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1);
|
||||
recursive_bezier(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void curve4_div::bezier(double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double x4, double y4)
|
||||
{
|
||||
m_points.add(point_d(x1, y1));
|
||||
recursive_bezier(x1, y1, x2, y2, x3, y3, x4, y4, 0);
|
||||
m_points.add(point_d(x4, y4));
|
||||
}
|
||||
|
||||
}
|
||||
|
69
src/agg_svg/agg_svg_exception.h
Normal file
69
src/agg_svg/agg_svg_exception.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.3
|
||||
// Copyright (C) 2002-2005 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: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// SVG exception
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SVG_EXCEPTION_INCLUDED
|
||||
#define AGG_SVG_EXCEPTION_INCLUDED
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
namespace agg
|
||||
{
|
||||
namespace svg
|
||||
{
|
||||
class exception
|
||||
{
|
||||
public:
|
||||
~exception()
|
||||
{
|
||||
delete [] m_msg;
|
||||
}
|
||||
|
||||
exception() : m_msg(0) {}
|
||||
|
||||
exception(const char* fmt, ...) :
|
||||
m_msg(0)
|
||||
{
|
||||
if(fmt)
|
||||
{
|
||||
m_msg = new char [4096];
|
||||
va_list arg;
|
||||
va_start(arg, fmt);
|
||||
vsprintf(m_msg, fmt, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
}
|
||||
|
||||
exception(const exception& exc) :
|
||||
m_msg(exc.m_msg ? new char[strlen(exc.m_msg) + 1] : 0)
|
||||
{
|
||||
if(m_msg) strcpy(m_msg, exc.m_msg);
|
||||
}
|
||||
|
||||
const char* msg() const { return m_msg; }
|
||||
|
||||
private:
|
||||
char* m_msg;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
886
src/agg_svg/agg_svg_parser.cpp
Normal file
886
src/agg_svg/agg_svg_parser.cpp
Normal file
|
@ -0,0 +1,886 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.3
|
||||
// Copyright (C) 2002-2005 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: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// SVG parser.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "agg_svg_parser.h"
|
||||
#include "expat.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
namespace svg
|
||||
{
|
||||
struct named_color
|
||||
{
|
||||
char name[22];
|
||||
int8u r, g, b, a;
|
||||
};
|
||||
|
||||
named_color colors[] =
|
||||
{
|
||||
{ "aliceblue",240,248,255, 255 },
|
||||
{ "antiquewhite",250,235,215, 255 },
|
||||
{ "aqua",0,255,255, 255 },
|
||||
{ "aquamarine",127,255,212, 255 },
|
||||
{ "azure",240,255,255, 255 },
|
||||
{ "beige",245,245,220, 255 },
|
||||
{ "bisque",255,228,196, 255 },
|
||||
{ "black",0,0,0, 255 },
|
||||
{ "blanchedalmond",255,235,205, 255 },
|
||||
{ "blue",0,0,255, 255 },
|
||||
{ "blueviolet",138,43,226, 255 },
|
||||
{ "brown",165,42,42, 255 },
|
||||
{ "burlywood",222,184,135, 255 },
|
||||
{ "cadetblue",95,158,160, 255 },
|
||||
{ "chartreuse",127,255,0, 255 },
|
||||
{ "chocolate",210,105,30, 255 },
|
||||
{ "coral",255,127,80, 255 },
|
||||
{ "cornflowerblue",100,149,237, 255 },
|
||||
{ "cornsilk",255,248,220, 255 },
|
||||
{ "crimson",220,20,60, 255 },
|
||||
{ "cyan",0,255,255, 255 },
|
||||
{ "darkblue",0,0,139, 255 },
|
||||
{ "darkcyan",0,139,139, 255 },
|
||||
{ "darkgoldenrod",184,134,11, 255 },
|
||||
{ "darkgray",169,169,169, 255 },
|
||||
{ "darkgreen",0,100,0, 255 },
|
||||
{ "darkgrey",169,169,169, 255 },
|
||||
{ "darkkhaki",189,183,107, 255 },
|
||||
{ "darkmagenta",139,0,139, 255 },
|
||||
{ "darkolivegreen",85,107,47, 255 },
|
||||
{ "darkorange",255,140,0, 255 },
|
||||
{ "darkorchid",153,50,204, 255 },
|
||||
{ "darkred",139,0,0, 255 },
|
||||
{ "darksalmon",233,150,122, 255 },
|
||||
{ "darkseagreen",143,188,143, 255 },
|
||||
{ "darkslateblue",72,61,139, 255 },
|
||||
{ "darkslategray",47,79,79, 255 },
|
||||
{ "darkslategrey",47,79,79, 255 },
|
||||
{ "darkturquoise",0,206,209, 255 },
|
||||
{ "darkviolet",148,0,211, 255 },
|
||||
{ "deeppink",255,20,147, 255 },
|
||||
{ "deepskyblue",0,191,255, 255 },
|
||||
{ "dimgray",105,105,105, 255 },
|
||||
{ "dimgrey",105,105,105, 255 },
|
||||
{ "dodgerblue",30,144,255, 255 },
|
||||
{ "firebrick",178,34,34, 255 },
|
||||
{ "floralwhite",255,250,240, 255 },
|
||||
{ "forestgreen",34,139,34, 255 },
|
||||
{ "fuchsia",255,0,255, 255 },
|
||||
{ "gainsboro",220,220,220, 255 },
|
||||
{ "ghostwhite",248,248,255, 255 },
|
||||
{ "gold",255,215,0, 255 },
|
||||
{ "goldenrod",218,165,32, 255 },
|
||||
{ "gray",128,128,128, 255 },
|
||||
{ "green",0,128,0, 255 },
|
||||
{ "greenyellow",173,255,47, 255 },
|
||||
{ "grey",128,128,128, 255 },
|
||||
{ "honeydew",240,255,240, 255 },
|
||||
{ "hotpink",255,105,180, 255 },
|
||||
{ "indianred",205,92,92, 255 },
|
||||
{ "indigo",75,0,130, 255 },
|
||||
{ "ivory",255,255,240, 255 },
|
||||
{ "khaki",240,230,140, 255 },
|
||||
{ "lavender",230,230,250, 255 },
|
||||
{ "lavenderblush",255,240,245, 255 },
|
||||
{ "lawngreen",124,252,0, 255 },
|
||||
{ "lemonchiffon",255,250,205, 255 },
|
||||
{ "lightblue",173,216,230, 255 },
|
||||
{ "lightcoral",240,128,128, 255 },
|
||||
{ "lightcyan",224,255,255, 255 },
|
||||
{ "lightgoldenrodyellow",250,250,210, 255 },
|
||||
{ "lightgray",211,211,211, 255 },
|
||||
{ "lightgreen",144,238,144, 255 },
|
||||
{ "lightgrey",211,211,211, 255 },
|
||||
{ "lightpink",255,182,193, 255 },
|
||||
{ "lightsalmon",255,160,122, 255 },
|
||||
{ "lightseagreen",32,178,170, 255 },
|
||||
{ "lightskyblue",135,206,250, 255 },
|
||||
{ "lightslategray",119,136,153, 255 },
|
||||
{ "lightslategrey",119,136,153, 255 },
|
||||
{ "lightsteelblue",176,196,222, 255 },
|
||||
{ "lightyellow",255,255,224, 255 },
|
||||
{ "lime",0,255,0, 255 },
|
||||
{ "limegreen",50,205,50, 255 },
|
||||
{ "linen",250,240,230, 255 },
|
||||
{ "magenta",255,0,255, 255 },
|
||||
{ "maroon",128,0,0, 255 },
|
||||
{ "mediumaquamarine",102,205,170, 255 },
|
||||
{ "mediumblue",0,0,205, 255 },
|
||||
{ "mediumorchid",186,85,211, 255 },
|
||||
{ "mediumpurple",147,112,219, 255 },
|
||||
{ "mediumseagreen",60,179,113, 255 },
|
||||
{ "mediumslateblue",123,104,238, 255 },
|
||||
{ "mediumspringgreen",0,250,154, 255 },
|
||||
{ "mediumturquoise",72,209,204, 255 },
|
||||
{ "mediumvioletred",199,21,133, 255 },
|
||||
{ "midnightblue",25,25,112, 255 },
|
||||
{ "mintcream",245,255,250, 255 },
|
||||
{ "mistyrose",255,228,225, 255 },
|
||||
{ "moccasin",255,228,181, 255 },
|
||||
{ "navajowhite",255,222,173, 255 },
|
||||
{ "navy",0,0,128, 255 },
|
||||
{ "oldlace",253,245,230, 255 },
|
||||
{ "olive",128,128,0, 255 },
|
||||
{ "olivedrab",107,142,35, 255 },
|
||||
{ "orange",255,165,0, 255 },
|
||||
{ "orangered",255,69,0, 255 },
|
||||
{ "orchid",218,112,214, 255 },
|
||||
{ "palegoldenrod",238,232,170, 255 },
|
||||
{ "palegreen",152,251,152, 255 },
|
||||
{ "paleturquoise",175,238,238, 255 },
|
||||
{ "palevioletred",219,112,147, 255 },
|
||||
{ "papayawhip",255,239,213, 255 },
|
||||
{ "peachpuff",255,218,185, 255 },
|
||||
{ "peru",205,133,63, 255 },
|
||||
{ "pink",255,192,203, 255 },
|
||||
{ "plum",221,160,221, 255 },
|
||||
{ "powderblue",176,224,230, 255 },
|
||||
{ "purple",128,0,128, 255 },
|
||||
{ "red",255,0,0, 255 },
|
||||
{ "rosybrown",188,143,143, 255 },
|
||||
{ "royalblue",65,105,225, 255 },
|
||||
{ "saddlebrown",139,69,19, 255 },
|
||||
{ "salmon",250,128,114, 255 },
|
||||
{ "sandybrown",244,164,96, 255 },
|
||||
{ "seagreen",46,139,87, 255 },
|
||||
{ "seashell",255,245,238, 255 },
|
||||
{ "sienna",160,82,45, 255 },
|
||||
{ "silver",192,192,192, 255 },
|
||||
{ "skyblue",135,206,235, 255 },
|
||||
{ "slateblue",106,90,205, 255 },
|
||||
{ "slategray",112,128,144, 255 },
|
||||
{ "slategrey",112,128,144, 255 },
|
||||
{ "snow",255,250,250, 255 },
|
||||
{ "springgreen",0,255,127, 255 },
|
||||
{ "steelblue",70,130,180, 255 },
|
||||
{ "tan",210,180,140, 255 },
|
||||
{ "teal",0,128,128, 255 },
|
||||
{ "thistle",216,191,216, 255 },
|
||||
{ "tomato",255,99,71, 255 },
|
||||
{ "turquoise",64,224,208, 255 },
|
||||
{ "violet",238,130,238, 255 },
|
||||
{ "wheat",245,222,179, 255 },
|
||||
{ "white",255,255,255, 255 },
|
||||
{ "whitesmoke",245,245,245, 255 },
|
||||
{ "yellow",255,255,0, 255 },
|
||||
{ "yellowgreen",154,205,50, 255 },
|
||||
{ "zzzzzzzzzzz",0,0,0, 0 }
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
parser::~parser()
|
||||
{
|
||||
delete [] m_attr_value;
|
||||
delete [] m_attr_name;
|
||||
delete [] m_buf;
|
||||
delete [] m_title;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
parser::parser(path_renderer& path) :
|
||||
m_path(path),
|
||||
m_tokenizer(),
|
||||
m_buf(new char[buf_size]),
|
||||
m_title(new char[256]),
|
||||
m_title_len(0),
|
||||
m_title_flag(false),
|
||||
m_path_flag(false),
|
||||
m_attr_name(new char[128]),
|
||||
m_attr_value(new char[1024]),
|
||||
m_attr_name_len(127),
|
||||
m_attr_value_len(1023)
|
||||
{
|
||||
m_title[0] = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void parser::parse(const char* fname)
|
||||
{
|
||||
char msg[1024];
|
||||
XML_Parser p = XML_ParserCreate(NULL);
|
||||
if(p == 0)
|
||||
{
|
||||
throw exception("Couldn't allocate memory for parser");
|
||||
}
|
||||
|
||||
XML_SetUserData(p, this);
|
||||
XML_SetElementHandler(p, start_element, end_element);
|
||||
XML_SetCharacterDataHandler(p, content);
|
||||
|
||||
FILE* fd = fopen(fname, "r");
|
||||
if(fd == 0)
|
||||
{
|
||||
sprintf(msg, "Couldn't open file %s", fname);
|
||||
throw exception(msg);
|
||||
}
|
||||
|
||||
bool done = false;
|
||||
do
|
||||
{
|
||||
size_t len = fread(m_buf, 1, buf_size, fd);
|
||||
done = len < buf_size;
|
||||
if(!XML_Parse(p, m_buf, len, done))
|
||||
{
|
||||
sprintf(msg,
|
||||
"%s at line %d\n",
|
||||
XML_ErrorString(XML_GetErrorCode(p)),
|
||||
XML_GetCurrentLineNumber(p));
|
||||
throw exception(msg);
|
||||
}
|
||||
}
|
||||
while(!done);
|
||||
fclose(fd);
|
||||
XML_ParserFree(p);
|
||||
|
||||
char* ts = m_title;
|
||||
while(*ts)
|
||||
{
|
||||
if(*ts < ' ') *ts = ' ';
|
||||
++ts;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void parser::start_element(void* data, const char* el, const char** attr)
|
||||
{
|
||||
parser& self = *(parser*)data;
|
||||
|
||||
if(strcmp(el, "title") == 0)
|
||||
{
|
||||
self.m_title_flag = true;
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "g") == 0)
|
||||
{
|
||||
self.m_path.push_attr();
|
||||
self.parse_attr(attr);
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "path") == 0)
|
||||
{
|
||||
if(self.m_path_flag)
|
||||
{
|
||||
throw exception("start_element: Nested path");
|
||||
}
|
||||
self.m_path.begin_path();
|
||||
self.parse_path(attr);
|
||||
self.m_path.end_path();
|
||||
self.m_path_flag = true;
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "rect") == 0)
|
||||
{
|
||||
self.parse_rect(attr);
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "line") == 0)
|
||||
{
|
||||
self.parse_line(attr);
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "polyline") == 0)
|
||||
{
|
||||
self.parse_poly(attr, false);
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "polygon") == 0)
|
||||
{
|
||||
self.parse_poly(attr, true);
|
||||
}
|
||||
//else
|
||||
//if(strcmp(el, "<OTHER_ELEMENTS>") == 0)
|
||||
//{
|
||||
//}
|
||||
// . . .
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void parser::end_element(void* data, const char* el)
|
||||
{
|
||||
parser& self = *(parser*)data;
|
||||
|
||||
if(strcmp(el, "title") == 0)
|
||||
{
|
||||
self.m_title_flag = false;
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "g") == 0)
|
||||
{
|
||||
self.m_path.pop_attr();
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "path") == 0)
|
||||
{
|
||||
self.m_path_flag = false;
|
||||
}
|
||||
//else
|
||||
//if(strcmp(el, "<OTHER_ELEMENTS>") == 0)
|
||||
//{
|
||||
//}
|
||||
// . . .
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void parser::content(void* data, const char* s, int len)
|
||||
{
|
||||
parser& self = *(parser*)data;
|
||||
|
||||
// m_title_flag signals that the <title> tag is being parsed now.
|
||||
// The following code concatenates the pieces of content of the <title> tag.
|
||||
if(self.m_title_flag)
|
||||
{
|
||||
if(len + self.m_title_len > 255) len = 255 - self.m_title_len;
|
||||
if(len > 0)
|
||||
{
|
||||
memcpy(self.m_title + self.m_title_len, s, len);
|
||||
self.m_title_len += len;
|
||||
self.m_title[self.m_title_len] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void parser::parse_attr(const char** attr)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; attr[i]; i += 2)
|
||||
{
|
||||
if(strcmp(attr[i], "style") == 0)
|
||||
{
|
||||
parse_style(attr[i + 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
parse_attr(attr[i], attr[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::parse_path(const char** attr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; attr[i]; i += 2)
|
||||
{
|
||||
// The <path> tag can consist of the path itself ("d=")
|
||||
// as well as of other parameters like "style=", "transform=", etc.
|
||||
// In the last case we simply rely on the function of parsing
|
||||
// attributes (see 'else' branch).
|
||||
if(strcmp(attr[i], "d") == 0)
|
||||
{
|
||||
m_tokenizer.set_path_str(attr[i + 1]);
|
||||
m_path.parse_path(m_tokenizer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a temporary single pair "name-value" in order
|
||||
// to avoid multiple calls for the same attribute.
|
||||
const char* tmp[4];
|
||||
tmp[0] = attr[i];
|
||||
tmp[1] = attr[i + 1];
|
||||
tmp[2] = 0;
|
||||
tmp[3] = 0;
|
||||
parse_attr(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
int cmp_color(const void* p1, const void* p2)
|
||||
{
|
||||
return strcmp(((named_color*)p1)->name, ((named_color*)p2)->name);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
rgba8 parse_color(const char* str)
|
||||
{
|
||||
while(*str == ' ') ++str;
|
||||
unsigned c = 0;
|
||||
if(*str == '#')
|
||||
{
|
||||
sscanf(str + 1, "%x", &c);
|
||||
return rgb8_packed(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
named_color c;
|
||||
unsigned len = strlen(str);
|
||||
if(len > sizeof(c.name) - 1)
|
||||
{
|
||||
throw exception("parse_color: Invalid color name '%s'", str);
|
||||
}
|
||||
strcpy(c.name, str);
|
||||
const void* p = bsearch(&c,
|
||||
colors,
|
||||
sizeof(colors) / sizeof(colors[0]),
|
||||
sizeof(colors[0]),
|
||||
cmp_color);
|
||||
if(p == 0)
|
||||
{
|
||||
throw exception("parse_color: Invalid color name '%s'", str);
|
||||
}
|
||||
const named_color* pc = (const named_color*)p;
|
||||
return rgba8(pc->r, pc->g, pc->b, pc->a);
|
||||
}
|
||||
}
|
||||
|
||||
double parse_double(const char* str)
|
||||
{
|
||||
while(*str == ' ') ++str;
|
||||
return atof(str);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
bool parser::parse_attr(const char* name, const char* value)
|
||||
{
|
||||
if(strcmp(name, "style") == 0)
|
||||
{
|
||||
parse_style(value);
|
||||
}
|
||||
else
|
||||
if(strcmp(name, "fill") == 0)
|
||||
{
|
||||
if(strcmp(value, "none") == 0)
|
||||
{
|
||||
m_path.fill_none();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_path.fill(parse_color(value));
|
||||
}
|
||||
}
|
||||
else
|
||||
if(strcmp(name, "fill-opacity") == 0)
|
||||
{
|
||||
m_path.fill_opacity(parse_double(value));
|
||||
}
|
||||
else
|
||||
if(strcmp(name, "stroke") == 0)
|
||||
{
|
||||
if(strcmp(value, "none") == 0)
|
||||
{
|
||||
m_path.stroke_none();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_path.stroke(parse_color(value));
|
||||
}
|
||||
}
|
||||
else
|
||||
if(strcmp(name, "stroke-width") == 0)
|
||||
{
|
||||
m_path.stroke_width(parse_double(value));
|
||||
}
|
||||
else
|
||||
if(strcmp(name, "stroke-linecap") == 0)
|
||||
{
|
||||
if(strcmp(value, "butt") == 0) m_path.line_cap(butt_cap);
|
||||
else if(strcmp(value, "round") == 0) m_path.line_cap(round_cap);
|
||||
else if(strcmp(value, "square") == 0) m_path.line_cap(square_cap);
|
||||
}
|
||||
else
|
||||
if(strcmp(name, "stroke-linejoin") == 0)
|
||||
{
|
||||
if(strcmp(value, "miter") == 0) m_path.line_join(miter_join);
|
||||
else if(strcmp(value, "round") == 0) m_path.line_join(round_join);
|
||||
else if(strcmp(value, "bevel") == 0) m_path.line_join(bevel_join);
|
||||
}
|
||||
else
|
||||
if(strcmp(name, "stroke-miterlimit") == 0)
|
||||
{
|
||||
m_path.miter_limit(parse_double(value));
|
||||
}
|
||||
else
|
||||
if(strcmp(name, "stroke-opacity") == 0)
|
||||
{
|
||||
m_path.stroke_opacity(parse_double(value));
|
||||
}
|
||||
else
|
||||
if(strcmp(name, "transform") == 0)
|
||||
{
|
||||
parse_transform(value);
|
||||
}
|
||||
//else
|
||||
//if(strcmp(el, "<OTHER_ATTRIBUTES>") == 0)
|
||||
//{
|
||||
//}
|
||||
// . . .
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::copy_name(const char* start, const char* end)
|
||||
{
|
||||
unsigned len = unsigned(end - start);
|
||||
if(m_attr_name_len == 0 || len > m_attr_name_len)
|
||||
{
|
||||
delete [] m_attr_name;
|
||||
m_attr_name = new char[len + 1];
|
||||
m_attr_name_len = len;
|
||||
}
|
||||
if(len) memcpy(m_attr_name, start, len);
|
||||
m_attr_name[len] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::copy_value(const char* start, const char* end)
|
||||
{
|
||||
unsigned len = unsigned(end - start);
|
||||
if(m_attr_value_len == 0 || len > m_attr_value_len)
|
||||
{
|
||||
delete [] m_attr_value;
|
||||
m_attr_value = new char[len + 1];
|
||||
m_attr_value_len = len;
|
||||
}
|
||||
if(len) memcpy(m_attr_value, start, len);
|
||||
m_attr_value[len] = 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
bool parser::parse_name_value(const char* nv_start, const char* nv_end)
|
||||
{
|
||||
const char* str = nv_start;
|
||||
while(str < nv_end && *str != ':') ++str;
|
||||
|
||||
const char* val = str;
|
||||
|
||||
// Right Trim
|
||||
while(str > nv_start &&
|
||||
(*str == ':' || isspace(*str))) --str;
|
||||
++str;
|
||||
|
||||
copy_name(nv_start, str);
|
||||
|
||||
while(val < nv_end && (*val == ':' || isspace(*val))) ++val;
|
||||
|
||||
copy_value(val, nv_end);
|
||||
return parse_attr(m_attr_name, m_attr_value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::parse_style(const char* str)
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
// Left Trim
|
||||
while(*str && isspace(*str)) ++str;
|
||||
const char* nv_start = str;
|
||||
while(*str && *str != ';') ++str;
|
||||
const char* nv_end = str;
|
||||
|
||||
// Right Trim
|
||||
while(nv_end > nv_start &&
|
||||
(*nv_end == ';' || isspace(*nv_end))) --nv_end;
|
||||
++nv_end;
|
||||
|
||||
parse_name_value(nv_start, nv_end);
|
||||
if(*str) ++str;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::parse_rect(const char** attr)
|
||||
{
|
||||
int i;
|
||||
double x = 0.0;
|
||||
double y = 0.0;
|
||||
double w = 0.0;
|
||||
double h = 0.0;
|
||||
|
||||
m_path.begin_path();
|
||||
for(i = 0; attr[i]; i += 2)
|
||||
{
|
||||
if(!parse_attr(attr[i], attr[i + 1]))
|
||||
{
|
||||
if(strcmp(attr[i], "x") == 0) x = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "y") == 0) y = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "width") == 0) w = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "height") == 0) h = parse_double(attr[i + 1]);
|
||||
// rx - to be implemented
|
||||
// ry - to be implemented
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(w != 0.0 && h != 0.0)
|
||||
{
|
||||
if(w < 0.0) throw exception("parse_rect: Invalid width: %f", w);
|
||||
if(h < 0.0) throw exception("parse_rect: Invalid height: %f", h);
|
||||
|
||||
m_path.move_to(x, y);
|
||||
m_path.line_to(x + w, y);
|
||||
m_path.line_to(x + w, y + h);
|
||||
m_path.line_to(x, y + h);
|
||||
m_path.close_subpath();
|
||||
}
|
||||
m_path.end_path();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::parse_line(const char** attr)
|
||||
{
|
||||
int i;
|
||||
double x1 = 0.0;
|
||||
double y1 = 0.0;
|
||||
double x2 = 0.0;
|
||||
double y2 = 0.0;
|
||||
|
||||
m_path.begin_path();
|
||||
for(i = 0; attr[i]; i += 2)
|
||||
{
|
||||
if(!parse_attr(attr[i], attr[i + 1]))
|
||||
{
|
||||
if(strcmp(attr[i], "x1") == 0) x1 = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "y1") == 0) y1 = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "x2") == 0) x2 = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "y2") == 0) y2 = parse_double(attr[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
m_path.move_to(x1, y1);
|
||||
m_path.line_to(x2, y2);
|
||||
m_path.end_path();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::parse_poly(const char** attr, bool close_flag)
|
||||
{
|
||||
int i;
|
||||
double x = 0.0;
|
||||
double y = 0.0;
|
||||
|
||||
m_path.begin_path();
|
||||
for(i = 0; attr[i]; i += 2)
|
||||
{
|
||||
if(!parse_attr(attr[i], attr[i + 1]))
|
||||
{
|
||||
if(strcmp(attr[i], "points") == 0)
|
||||
{
|
||||
m_tokenizer.set_path_str(attr[i + 1]);
|
||||
if(!m_tokenizer.next())
|
||||
{
|
||||
throw exception("parse_poly: Too few coordinates");
|
||||
}
|
||||
x = m_tokenizer.last_number();
|
||||
if(!m_tokenizer.next())
|
||||
{
|
||||
throw exception("parse_poly: Too few coordinates");
|
||||
}
|
||||
y = m_tokenizer.last_number();
|
||||
m_path.move_to(x, y);
|
||||
while(m_tokenizer.next())
|
||||
{
|
||||
x = m_tokenizer.last_number();
|
||||
if(!m_tokenizer.next())
|
||||
{
|
||||
throw exception("parse_poly: Odd number of coordinates");
|
||||
}
|
||||
y = m_tokenizer.last_number();
|
||||
m_path.line_to(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(close_flag)
|
||||
{
|
||||
m_path.close_subpath();
|
||||
}
|
||||
m_path.end_path();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::parse_transform(const char* str)
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
if(islower(*str))
|
||||
{
|
||||
if(strncmp(str, "matrix", 6) == 0) str += parse_matrix(str); else
|
||||
if(strncmp(str, "translate", 9) == 0) str += parse_translate(str); else
|
||||
if(strncmp(str, "rotate", 6) == 0) str += parse_rotate(str); else
|
||||
if(strncmp(str, "scale", 5) == 0) str += parse_scale(str); else
|
||||
if(strncmp(str, "skewX", 5) == 0) str += parse_skew_x(str); else
|
||||
if(strncmp(str, "skewY", 5) == 0) str += parse_skew_y(str); else
|
||||
{
|
||||
++str;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
static bool is_numeric(char c)
|
||||
{
|
||||
return strchr("0123456789+-.eE", c) != 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
static unsigned parse_transform_args(const char* str,
|
||||
double* args,
|
||||
unsigned max_na,
|
||||
unsigned* na)
|
||||
{
|
||||
*na = 0;
|
||||
const char* ptr = str;
|
||||
while(*ptr && *ptr != '(') ++ptr;
|
||||
if(*ptr == 0)
|
||||
{
|
||||
throw exception("parse_transform_args: Invalid syntax");
|
||||
}
|
||||
const char* end = ptr;
|
||||
while(*end && *end != ')') ++end;
|
||||
if(*end == 0)
|
||||
{
|
||||
throw exception("parse_transform_args: Invalid syntax");
|
||||
}
|
||||
|
||||
while(ptr < end)
|
||||
{
|
||||
if(is_numeric(*ptr))
|
||||
{
|
||||
if(*na >= max_na)
|
||||
{
|
||||
throw exception("parse_transform_args: Too many arguments");
|
||||
}
|
||||
args[(*na)++] = atof(ptr);
|
||||
while(ptr < end && is_numeric(*ptr)) ++ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
return unsigned(end - str);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
unsigned parser::parse_matrix(const char* str)
|
||||
{
|
||||
double args[6];
|
||||
unsigned na = 0;
|
||||
unsigned len = parse_transform_args(str, args, 6, &na);
|
||||
if(na != 6)
|
||||
{
|
||||
throw exception("parse_matrix: Invalid number of arguments");
|
||||
}
|
||||
m_path.transform().premultiply(trans_affine(args[0], args[1], args[2], args[3], args[4], args[5]));
|
||||
return len;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
unsigned parser::parse_translate(const char* str)
|
||||
{
|
||||
double args[2];
|
||||
unsigned na = 0;
|
||||
unsigned len = parse_transform_args(str, args, 2, &na);
|
||||
if(na == 1) args[1] = 0.0;
|
||||
m_path.transform().premultiply(trans_affine_translation(args[0], args[1]));
|
||||
return len;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
unsigned parser::parse_rotate(const char* str)
|
||||
{
|
||||
double args[3];
|
||||
unsigned na = 0;
|
||||
unsigned len = parse_transform_args(str, args, 3, &na);
|
||||
if(na == 1)
|
||||
{
|
||||
m_path.transform().premultiply(trans_affine_rotation(deg2rad(args[0])));
|
||||
}
|
||||
else if(na == 3)
|
||||
{
|
||||
trans_affine t = trans_affine_translation(-args[1], -args[2]);
|
||||
t *= trans_affine_rotation(deg2rad(args[0]));
|
||||
t *= trans_affine_translation(args[1], args[2]);
|
||||
m_path.transform().premultiply(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw exception("parse_rotate: Invalid number of arguments");
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
unsigned parser::parse_scale(const char* str)
|
||||
{
|
||||
double args[2];
|
||||
unsigned na = 0;
|
||||
unsigned len = parse_transform_args(str, args, 2, &na);
|
||||
if(na == 1) args[1] = args[0];
|
||||
m_path.transform().premultiply(trans_affine_scaling(args[0], args[1]));
|
||||
return len;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
unsigned parser::parse_skew_x(const char* str)
|
||||
{
|
||||
double arg;
|
||||
unsigned na = 0;
|
||||
unsigned len = parse_transform_args(str, &arg, 1, &na);
|
||||
m_path.transform().premultiply(trans_affine_skewing(deg2rad(arg), 0.0));
|
||||
return len;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
unsigned parser::parse_skew_y(const char* str)
|
||||
{
|
||||
double arg;
|
||||
unsigned na = 0;
|
||||
unsigned len = parse_transform_args(str, &arg, 1, &na);
|
||||
m_path.transform().premultiply(trans_affine_skewing(0.0, deg2rad(arg)));
|
||||
return len;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
85
src/agg_svg/agg_svg_parser.h
Normal file
85
src/agg_svg/agg_svg_parser.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.3
|
||||
// Copyright (C) 2002-2005 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: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// SVG parser.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SVG_PARSER_INCLUDED
|
||||
#define AGG_SVG_PARSER_INCLUDED
|
||||
|
||||
#include "agg_svg_path_tokenizer.h"
|
||||
#include "agg_svg_path_renderer.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
namespace svg
|
||||
{
|
||||
|
||||
class parser
|
||||
{
|
||||
enum buf_size_e { buf_size = BUFSIZ };
|
||||
public:
|
||||
|
||||
~parser();
|
||||
parser(path_renderer& path);
|
||||
|
||||
void parse(const char* fname);
|
||||
const char* title() const { return m_title; }
|
||||
|
||||
private:
|
||||
// XML event handlers
|
||||
static void start_element(void* data, const char* el, const char** attr);
|
||||
static void end_element(void* data, const char* el);
|
||||
static void content(void* data, const char* s, int len);
|
||||
|
||||
void parse_attr(const char** attr);
|
||||
void parse_path(const char** attr);
|
||||
void parse_poly(const char** attr, bool close_flag);
|
||||
void parse_rect(const char** attr);
|
||||
void parse_line(const char** attr);
|
||||
void parse_style(const char* str);
|
||||
void parse_transform(const char* str);
|
||||
|
||||
unsigned parse_matrix(const char* str);
|
||||
unsigned parse_translate(const char* str);
|
||||
unsigned parse_rotate(const char* str);
|
||||
unsigned parse_scale(const char* str);
|
||||
unsigned parse_skew_x(const char* str);
|
||||
unsigned parse_skew_y(const char* str);
|
||||
|
||||
bool parse_attr(const char* name, const char* value);
|
||||
bool parse_name_value(const char* nv_start, const char* nv_end);
|
||||
void copy_name(const char* start, const char* end);
|
||||
void copy_value(const char* start, const char* end);
|
||||
|
||||
private:
|
||||
path_renderer& m_path;
|
||||
path_tokenizer m_tokenizer;
|
||||
char* m_buf;
|
||||
char* m_title;
|
||||
unsigned m_title_len;
|
||||
bool m_title_flag;
|
||||
bool m_path_flag;
|
||||
char* m_attr_name;
|
||||
char* m_attr_value;
|
||||
unsigned m_attr_name_len;
|
||||
unsigned m_attr_value_len;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
366
src/agg_svg/agg_svg_path_renderer.cpp
Normal file
366
src/agg_svg/agg_svg_path_renderer.cpp
Normal file
|
@ -0,0 +1,366 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.3
|
||||
// Copyright (C) 2002-2005 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: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// SVG path renderer.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include "agg_svg_path_renderer.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
namespace svg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
path_renderer::path_renderer() :
|
||||
m_curved(m_storage),
|
||||
m_curved_count(m_curved),
|
||||
|
||||
m_curved_stroked(m_curved_count),
|
||||
m_curved_stroked_trans(m_curved_stroked, m_transform),
|
||||
|
||||
m_curved_trans(m_curved_count, m_transform),
|
||||
m_curved_trans_contour(m_curved_trans)
|
||||
{
|
||||
m_curved_trans_contour.auto_detect_orientation(false);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::remove_all()
|
||||
{
|
||||
m_storage.remove_all();
|
||||
m_attr_storage.remove_all();
|
||||
m_attr_stack.remove_all();
|
||||
m_transform.reset();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::begin_path()
|
||||
{
|
||||
push_attr();
|
||||
unsigned idx = m_storage.start_new_path();
|
||||
m_attr_storage.add(path_attributes(cur_attr(), idx));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::end_path()
|
||||
{
|
||||
if(m_attr_storage.size() == 0)
|
||||
{
|
||||
throw exception("end_path : The path was not begun");
|
||||
}
|
||||
path_attributes attr = cur_attr();
|
||||
unsigned idx = m_attr_storage[m_attr_storage.size() - 1].index;
|
||||
attr.index = idx;
|
||||
m_attr_storage[m_attr_storage.size() - 1] = attr;
|
||||
pop_attr();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::move_to(double x, double y, bool rel) // M, m
|
||||
{
|
||||
if(rel) m_storage.rel_to_abs(&x, &y);
|
||||
m_storage.move_to(x, y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::line_to(double x, double y, bool rel) // L, l
|
||||
{
|
||||
if(rel) m_storage.rel_to_abs(&x, &y);
|
||||
m_storage.line_to(x, y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::hline_to(double x, bool rel) // H, h
|
||||
{
|
||||
double x2 = 0.0;
|
||||
double y2 = 0.0;
|
||||
if(m_storage.total_vertices())
|
||||
{
|
||||
m_storage.vertex(m_storage.total_vertices() - 1, &x2, &y2);
|
||||
if(rel) x += x2;
|
||||
m_storage.line_to(x, y2);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::vline_to(double y, bool rel) // V, v
|
||||
{
|
||||
double x2 = 0.0;
|
||||
double y2 = 0.0;
|
||||
if(m_storage.total_vertices())
|
||||
{
|
||||
m_storage.vertex(m_storage.total_vertices() - 1, &x2, &y2);
|
||||
if(rel) y += y2;
|
||||
m_storage.line_to(x2, y);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::curve3(double x1, double y1, // Q, q
|
||||
double x, double y, bool rel)
|
||||
{
|
||||
if(rel)
|
||||
{
|
||||
m_storage.rel_to_abs(&x1, &y1);
|
||||
m_storage.rel_to_abs(&x, &y);
|
||||
}
|
||||
m_storage.curve3(x1, y1, x, y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::curve3(double x, double y, bool rel) // T, t
|
||||
{
|
||||
// throw exception("curve3(x, y) : NOT IMPLEMENTED YET");
|
||||
if(rel)
|
||||
{
|
||||
m_storage.curve3_rel(x, y);
|
||||
} else
|
||||
{
|
||||
m_storage.curve3(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::curve4(double x1, double y1, // C, c
|
||||
double x2, double y2,
|
||||
double x, double y, bool rel)
|
||||
{
|
||||
if(rel)
|
||||
{
|
||||
m_storage.rel_to_abs(&x1, &y1);
|
||||
m_storage.rel_to_abs(&x2, &y2);
|
||||
m_storage.rel_to_abs(&x, &y);
|
||||
}
|
||||
m_storage.curve4(x1, y1, x2, y2, x, y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::curve4(double x2, double y2, // S, s
|
||||
double x, double y, bool rel)
|
||||
{
|
||||
//throw exception("curve4(x2, y2, x, y) : NOT IMPLEMENTED YET");
|
||||
if(rel)
|
||||
{
|
||||
m_storage.curve4_rel(x2, y2, x, y);
|
||||
} else
|
||||
{
|
||||
m_storage.curve4(x2, y2, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::close_subpath()
|
||||
{
|
||||
m_storage.end_poly(path_flags_close);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
path_attributes& path_renderer::cur_attr()
|
||||
{
|
||||
if(m_attr_stack.size() == 0)
|
||||
{
|
||||
throw exception("cur_attr : Attribute stack is empty");
|
||||
}
|
||||
return m_attr_stack[m_attr_stack.size() - 1];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::push_attr()
|
||||
{
|
||||
m_attr_stack.add(m_attr_stack.size() ?
|
||||
m_attr_stack[m_attr_stack.size() - 1] :
|
||||
path_attributes());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::pop_attr()
|
||||
{
|
||||
if(m_attr_stack.size() == 0)
|
||||
{
|
||||
throw exception("pop_attr : Attribute stack is empty");
|
||||
}
|
||||
m_attr_stack.remove_last();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::fill(const rgba8& f)
|
||||
{
|
||||
path_attributes& attr = cur_attr();
|
||||
attr.fill_color = f;
|
||||
attr.fill_flag = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::stroke(const rgba8& s)
|
||||
{
|
||||
path_attributes& attr = cur_attr();
|
||||
attr.stroke_color = s;
|
||||
attr.stroke_flag = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::even_odd(bool flag)
|
||||
{
|
||||
cur_attr().even_odd_flag = flag;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::stroke_width(double w)
|
||||
{
|
||||
cur_attr().stroke_width = w;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::fill_none()
|
||||
{
|
||||
cur_attr().fill_flag = false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::stroke_none()
|
||||
{
|
||||
cur_attr().stroke_flag = false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::fill_opacity(double op)
|
||||
{
|
||||
cur_attr().fill_color.opacity(op);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::stroke_opacity(double op)
|
||||
{
|
||||
cur_attr().stroke_color.opacity(op);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::line_join(line_join_e join)
|
||||
{
|
||||
cur_attr().line_join = join;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::line_cap(line_cap_e cap)
|
||||
{
|
||||
cur_attr().line_cap = cap;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::miter_limit(double ml)
|
||||
{
|
||||
cur_attr().miter_limit = ml;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
trans_affine& path_renderer::transform()
|
||||
{
|
||||
return cur_attr().transform;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::parse_path(path_tokenizer& tok)
|
||||
{
|
||||
while(tok.next())
|
||||
{
|
||||
double arg[10];
|
||||
char cmd = tok.last_command();
|
||||
unsigned i;
|
||||
switch(cmd)
|
||||
{
|
||||
case 'M': case 'm':
|
||||
arg[0] = tok.last_number();
|
||||
arg[1] = tok.next(cmd);
|
||||
move_to(arg[0], arg[1], cmd == 'm');
|
||||
break;
|
||||
|
||||
case 'L': case 'l':
|
||||
arg[0] = tok.last_number();
|
||||
arg[1] = tok.next(cmd);
|
||||
line_to(arg[0], arg[1], cmd == 'l');
|
||||
break;
|
||||
|
||||
case 'V': case 'v':
|
||||
vline_to(tok.last_number(), cmd == 'v');
|
||||
break;
|
||||
|
||||
case 'H': case 'h':
|
||||
hline_to(tok.last_number(), cmd == 'h');
|
||||
break;
|
||||
|
||||
case 'Q': case 'q':
|
||||
arg[0] = tok.last_number();
|
||||
for(i = 1; i < 4; i++)
|
||||
{
|
||||
arg[i] = tok.next(cmd);
|
||||
}
|
||||
curve3(arg[0], arg[1], arg[2], arg[3], cmd == 'q');
|
||||
break;
|
||||
|
||||
case 'T': case 't':
|
||||
arg[0] = tok.last_number();
|
||||
arg[1] = tok.next(cmd);
|
||||
curve3(arg[0], arg[1], cmd == 't');
|
||||
break;
|
||||
|
||||
case 'C': case 'c':
|
||||
arg[0] = tok.last_number();
|
||||
for(i = 1; i < 6; i++)
|
||||
{
|
||||
arg[i] = tok.next(cmd);
|
||||
}
|
||||
curve4(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], cmd == 'c');
|
||||
break;
|
||||
|
||||
case 'S': case 's':
|
||||
arg[0] = tok.last_number();
|
||||
for(i = 1; i < 4; i++)
|
||||
{
|
||||
arg[i] = tok.next(cmd);
|
||||
}
|
||||
curve4(arg[0], arg[1], arg[2], arg[3], cmd == 's');
|
||||
break;
|
||||
|
||||
case 'A': case 'a':
|
||||
arg[0] = tok.last_number();
|
||||
for (i = 1; i < 7; i++)
|
||||
{
|
||||
arg[i] = tok.next(cmd);
|
||||
}
|
||||
// curve3(arg[0], arg[1], arg[2], arg[3], cmd == 'q');
|
||||
// throw exception("parse_path: Command A: NOT IMPLEMENTED YET");
|
||||
break;
|
||||
|
||||
case 'Z': case 'z':
|
||||
close_subpath();
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
char buf[100];
|
||||
sprintf(buf, "parse_path: Invalid Command %c", cmd);
|
||||
throw exception(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
321
src/agg_svg/agg_svg_path_renderer.h
Normal file
321
src/agg_svg/agg_svg_path_renderer.h
Normal file
|
@ -0,0 +1,321 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.3
|
||||
// Copyright (C) 2002-2005 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: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// SVG path renderer.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_SVG_PATH_RENDERER_INCLUDED
|
||||
#define AGG_SVG_PATH_RENDERER_INCLUDED
|
||||
|
||||
#include <agg/agg_path_storage.h>
|
||||
#include <agg/agg_conv_transform.h>
|
||||
#include <agg/agg_conv_stroke.h>
|
||||
#include <agg/agg_conv_contour.h>
|
||||
#include <agg/agg_conv_curve.h>
|
||||
#include <agg/agg_color_rgba.h>
|
||||
#include <agg/agg_renderer_scanline.h>
|
||||
#include <agg/agg_bounding_rect.h>
|
||||
#include <agg/agg_rasterizer_scanline_aa.h>
|
||||
#include "agg_svg_path_tokenizer.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
namespace svg
|
||||
{
|
||||
template<class VertexSource> class conv_count
|
||||
{
|
||||
public:
|
||||
conv_count(VertexSource& vs) : m_source(&vs), m_count(0) {}
|
||||
|
||||
void count(unsigned n) { m_count = n; }
|
||||
unsigned count() const { return m_count; }
|
||||
|
||||
void rewind(unsigned path_id) { m_source->rewind(path_id); }
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
++m_count;
|
||||
return m_source->vertex(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
VertexSource* m_source;
|
||||
unsigned m_count;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//============================================================================
|
||||
// Basic path attributes
|
||||
struct path_attributes
|
||||
{
|
||||
unsigned index;
|
||||
rgba8 fill_color;
|
||||
rgba8 stroke_color;
|
||||
bool fill_flag;
|
||||
bool stroke_flag;
|
||||
bool even_odd_flag;
|
||||
line_join_e line_join;
|
||||
line_cap_e line_cap;
|
||||
double miter_limit;
|
||||
double stroke_width;
|
||||
trans_affine transform;
|
||||
|
||||
// Empty constructor
|
||||
path_attributes() :
|
||||
index(0),
|
||||
fill_color(rgba(0,0,0)),
|
||||
stroke_color(rgba(0,0,0)),
|
||||
fill_flag(true),
|
||||
stroke_flag(false),
|
||||
even_odd_flag(false),
|
||||
line_join(miter_join),
|
||||
line_cap(butt_cap),
|
||||
miter_limit(4.0),
|
||||
stroke_width(1.0),
|
||||
transform()
|
||||
{
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
path_attributes(const path_attributes& attr) :
|
||||
index(attr.index),
|
||||
fill_color(attr.fill_color),
|
||||
stroke_color(attr.stroke_color),
|
||||
fill_flag(attr.fill_flag),
|
||||
stroke_flag(attr.stroke_flag),
|
||||
even_odd_flag(attr.even_odd_flag),
|
||||
line_join(attr.line_join),
|
||||
line_cap(attr.line_cap),
|
||||
miter_limit(attr.miter_limit),
|
||||
stroke_width(attr.stroke_width),
|
||||
transform(attr.transform)
|
||||
{
|
||||
}
|
||||
|
||||
// Copy constructor with new index value
|
||||
path_attributes(const path_attributes& attr, unsigned idx) :
|
||||
index(idx),
|
||||
fill_color(attr.fill_color),
|
||||
stroke_color(attr.stroke_color),
|
||||
fill_flag(attr.fill_flag),
|
||||
stroke_flag(attr.stroke_flag),
|
||||
even_odd_flag(attr.even_odd_flag),
|
||||
line_join(attr.line_join),
|
||||
line_cap(attr.line_cap),
|
||||
miter_limit(attr.miter_limit),
|
||||
stroke_width(attr.stroke_width),
|
||||
transform(attr.transform)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//============================================================================
|
||||
// Path container and renderer.
|
||||
class path_renderer
|
||||
{
|
||||
public:
|
||||
typedef pod_bvector<path_attributes> attr_storage;
|
||||
|
||||
typedef conv_curve<path_storage> curved;
|
||||
typedef conv_count<curved> curved_count;
|
||||
|
||||
typedef conv_stroke<curved_count> curved_stroked;
|
||||
typedef conv_transform<curved_stroked> curved_stroked_trans;
|
||||
|
||||
typedef conv_transform<curved_count> curved_trans;
|
||||
typedef conv_contour<curved_trans> curved_trans_contour;
|
||||
|
||||
path_renderer();
|
||||
|
||||
void remove_all();
|
||||
|
||||
// Use these functions as follows:
|
||||
// begin_path() when the XML tag <path> comes ("start_element" handler)
|
||||
// parse_path() on "d=" tag attribute
|
||||
// end_path() when parsing of the entire tag is done.
|
||||
void begin_path();
|
||||
void parse_path(path_tokenizer& tok);
|
||||
void end_path();
|
||||
|
||||
// The following functions are essentially a "reflection" of
|
||||
// the respective SVG path commands.
|
||||
void move_to(double x, double y, bool rel=false); // M, m
|
||||
void line_to(double x, double y, bool rel=false); // L, l
|
||||
void hline_to(double x, bool rel=false); // H, h
|
||||
void vline_to(double y, bool rel=false); // V, v
|
||||
void curve3(double x1, double y1, // Q, q
|
||||
double x, double y, bool rel=false);
|
||||
void curve3(double x, double y, bool rel=false); // T, t
|
||||
void curve4(double x1, double y1, // C, c
|
||||
double x2, double y2,
|
||||
double x, double y, bool rel=false);
|
||||
void curve4(double x2, double y2, // S, s
|
||||
double x, double y, bool rel=false);
|
||||
void close_subpath(); // Z, z
|
||||
|
||||
// template<class VertexSource>
|
||||
// void add_path(VertexSource& vs,
|
||||
// unsigned path_id = 0,
|
||||
// bool solid_path = true)
|
||||
// {
|
||||
// m_storage.add_path(vs, path_id, solid_path);
|
||||
// }
|
||||
|
||||
|
||||
unsigned vertex_count() const { return m_curved_count.count(); }
|
||||
|
||||
|
||||
// Call these functions on <g> tag (start_element, end_element respectively)
|
||||
void push_attr();
|
||||
void pop_attr();
|
||||
|
||||
// Attribute setting functions.
|
||||
void fill(const rgba8& f);
|
||||
void stroke(const rgba8& s);
|
||||
void even_odd(bool flag);
|
||||
void stroke_width(double w);
|
||||
void fill_none();
|
||||
void stroke_none();
|
||||
void fill_opacity(double op);
|
||||
void stroke_opacity(double op);
|
||||
void line_join(line_join_e join);
|
||||
void line_cap(line_cap_e cap);
|
||||
void miter_limit(double ml);
|
||||
trans_affine& transform();
|
||||
|
||||
// Make all polygons CCW-oriented
|
||||
void arrange_orientations()
|
||||
{
|
||||
m_storage.arrange_orientations_all_paths(path_flags_ccw);
|
||||
}
|
||||
|
||||
// Expand all polygons
|
||||
void expand(double value)
|
||||
{
|
||||
m_curved_trans_contour.width(value);
|
||||
}
|
||||
|
||||
unsigned operator [](unsigned idx)
|
||||
{
|
||||
m_transform = m_attr_storage[idx].transform;
|
||||
return m_attr_storage[idx].index;
|
||||
}
|
||||
|
||||
void bounding_rect(double* x1, double* y1, double* x2, double* y2)
|
||||
{
|
||||
agg::conv_transform<agg::path_storage> trans(m_storage, m_transform);
|
||||
agg::bounding_rect(trans, *this, 0, m_attr_storage.size(), x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
// Rendering. One can specify two additional parameters:
|
||||
// trans_affine and opacity. They can be used to transform the whole
|
||||
// image and/or to make it translucent.
|
||||
template<class Rasterizer, class Scanline, class Renderer>
|
||||
void render(Rasterizer& ras,
|
||||
Scanline& sl,
|
||||
Renderer& ren,
|
||||
const trans_affine& mtx,
|
||||
const rect_i& cb,
|
||||
double opacity=1.0)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
ras.clip_box(cb.x1, cb.y1, cb.x2, cb.y2);
|
||||
m_curved_count.count(0);
|
||||
|
||||
for(i = 0; i < m_attr_storage.size(); i++)
|
||||
{
|
||||
const path_attributes& attr = m_attr_storage[i];
|
||||
m_transform = attr.transform;
|
||||
m_transform *= mtx;
|
||||
double scl = m_transform.scale();
|
||||
//m_curved.approximation_method(curve_inc);
|
||||
m_curved.approximation_scale(scl);
|
||||
m_curved.angle_tolerance(0.0);
|
||||
|
||||
rgba8 color;
|
||||
|
||||
if(attr.fill_flag)
|
||||
{
|
||||
ras.reset();
|
||||
ras.filling_rule(attr.even_odd_flag ? fill_even_odd : fill_non_zero);
|
||||
if(fabs(m_curved_trans_contour.width()) < 0.0001)
|
||||
{
|
||||
ras.add_path(m_curved_trans, attr.index);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curved_trans_contour.miter_limit(attr.miter_limit);
|
||||
ras.add_path(m_curved_trans_contour, attr.index);
|
||||
}
|
||||
|
||||
color = attr.fill_color;
|
||||
color.opacity(color.opacity() * opacity);
|
||||
ren.color(color);
|
||||
agg::render_scanlines(ras, sl, ren);
|
||||
}
|
||||
|
||||
if(attr.stroke_flag)
|
||||
{
|
||||
m_curved_stroked.width(attr.stroke_width);
|
||||
//m_curved_stroked.line_join((attr.line_join == miter_join) ? miter_join_round : attr.line_join);
|
||||
m_curved_stroked.line_join(attr.line_join);
|
||||
m_curved_stroked.line_cap(attr.line_cap);
|
||||
m_curved_stroked.miter_limit(attr.miter_limit);
|
||||
m_curved_stroked.inner_join(inner_round);
|
||||
m_curved_stroked.approximation_scale(scl);
|
||||
|
||||
// If the *visual* line width is considerable we
|
||||
// turn on processing of curve cusps.
|
||||
//---------------------
|
||||
if(attr.stroke_width * scl > 1.0)
|
||||
{
|
||||
m_curved.angle_tolerance(0.2);
|
||||
}
|
||||
ras.reset();
|
||||
ras.filling_rule(fill_non_zero);
|
||||
ras.add_path(m_curved_stroked_trans, attr.index);
|
||||
color = attr.stroke_color;
|
||||
color.opacity(color.opacity() * opacity);
|
||||
ren.color(color);
|
||||
agg::render_scanlines(ras, sl, ren);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
path_attributes& cur_attr();
|
||||
|
||||
path_storage m_storage;
|
||||
attr_storage m_attr_storage;
|
||||
attr_storage m_attr_stack;
|
||||
trans_affine m_transform;
|
||||
|
||||
curved m_curved;
|
||||
curved_count m_curved_count;
|
||||
|
||||
curved_stroked m_curved_stroked;
|
||||
curved_stroked_trans m_curved_stroked_trans;
|
||||
|
||||
curved_trans m_curved_trans;
|
||||
curved_trans_contour m_curved_trans_contour;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
151
src/agg_svg/agg_svg_path_tokenizer.cpp
Normal file
151
src/agg_svg/agg_svg_path_tokenizer.cpp
Normal file
|
@ -0,0 +1,151 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.3
|
||||
// Copyright (C) 2002-2005 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: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// SVG path tokenizer.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "agg_svg_exception.h"
|
||||
#include "agg_svg_path_tokenizer.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
namespace svg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const char path_tokenizer::s_commands[] = "+-MmZzLlHhVvCcSsQqTtAaFfPp";
|
||||
const char path_tokenizer::s_numeric[] = ".Ee0123456789";
|
||||
const char path_tokenizer::s_separators[] = " ,\t\n\r";
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
path_tokenizer::path_tokenizer()
|
||||
: m_path(0), m_last_command(0), m_last_number(0.0)
|
||||
{
|
||||
init_char_mask(m_commands_mask, s_commands);
|
||||
init_char_mask(m_numeric_mask, s_numeric);
|
||||
init_char_mask(m_separators_mask, s_separators);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_tokenizer::set_path_str(const char* str)
|
||||
{
|
||||
m_path = str;
|
||||
m_last_command = 0;
|
||||
m_last_number = 0.0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_tokenizer::init_char_mask(char* mask, const char* char_set)
|
||||
{
|
||||
memset(mask, 0, 256/8);
|
||||
while(*char_set)
|
||||
{
|
||||
unsigned c = unsigned(*char_set++) & 0xFF;
|
||||
mask[c >> 3] |= 1 << (c & 7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool path_tokenizer::next()
|
||||
{
|
||||
if(m_path == 0) return false;
|
||||
|
||||
// Skip all white spaces and other garbage
|
||||
while(*m_path && !is_command(*m_path) && !is_numeric(*m_path))
|
||||
{
|
||||
if(!is_separator(*m_path))
|
||||
{
|
||||
char buf[100];
|
||||
sprintf(buf, "path_tokenizer::next : Invalid Character %c", *m_path);
|
||||
throw exception(buf);
|
||||
}
|
||||
m_path++;
|
||||
}
|
||||
|
||||
if(*m_path == 0) return false;
|
||||
|
||||
if(is_command(*m_path))
|
||||
{
|
||||
// Check if the command is a numeric sign character
|
||||
if(*m_path == '-' || *m_path == '+')
|
||||
{
|
||||
return parse_number();
|
||||
}
|
||||
m_last_command = *m_path++;
|
||||
while(*m_path && is_separator(*m_path)) m_path++;
|
||||
if(*m_path == 0) return true;
|
||||
}
|
||||
return parse_number();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
double path_tokenizer::next(char cmd)
|
||||
{
|
||||
if(!next()) throw exception("parse_path: Unexpected end of path");
|
||||
if(last_command() != cmd)
|
||||
{
|
||||
char buf[100];
|
||||
sprintf(buf, "parse_path: Command %c: bad or missing parameters", cmd);
|
||||
throw exception(buf);
|
||||
}
|
||||
return last_number();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool path_tokenizer::parse_number()
|
||||
{
|
||||
char buf[256]; // Should be enough for any number
|
||||
char* buf_ptr = buf;
|
||||
|
||||
// Copy all sign characters
|
||||
while(buf_ptr < buf+255 && *m_path == '-' || *m_path == '+')
|
||||
{
|
||||
*buf_ptr++ = *m_path++;
|
||||
}
|
||||
|
||||
// Copy all numeric characters
|
||||
bool dot_seen = false;
|
||||
while(buf_ptr < buf+255 && is_numeric(*m_path))
|
||||
{
|
||||
char c = *m_path;
|
||||
if (c == '.') {
|
||||
if (dot_seen)
|
||||
break;
|
||||
dot_seen = true;
|
||||
}
|
||||
*buf_ptr++ = *m_path++;
|
||||
}
|
||||
*buf_ptr = 0;
|
||||
m_last_number = atof(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} //namespace svg
|
||||
} //namespace agg
|
||||
|
||||
|
||||
|
||||
|
114
src/agg_svg/agg_svg_path_tokenizer.h
Normal file
114
src/agg_svg/agg_svg_path_tokenizer.h
Normal file
|
@ -0,0 +1,114 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.3
|
||||
// Copyright (C) 2002-2005 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: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// SVG path tokenizer.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_SVG_PATH_TOKENIZER_INCLUDED
|
||||
#define AGG_SVG_PATH_TOKENIZER_INCLUDED
|
||||
|
||||
#include "agg_svg_exception.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
namespace svg
|
||||
{
|
||||
// SVG path tokenizer.
|
||||
// Example:
|
||||
//
|
||||
// agg::svg::path_tokenizer tok;
|
||||
//
|
||||
// tok.set_str("M-122.304 84.285L-122.304 84.285 122.203 86.179 ");
|
||||
// while(tok.next())
|
||||
// {
|
||||
// printf("command='%c' number=%f\n",
|
||||
// tok.last_command(),
|
||||
// tok.last_number());
|
||||
// }
|
||||
//
|
||||
// The tokenizer does all the routine job of parsing the SVG paths.
|
||||
// It doesn't recognize any graphical primitives, it even doesn't know
|
||||
// anything about pairs of coordinates (X,Y). The purpose of this class
|
||||
// is to tokenize the numeric values and commands. SVG paths can
|
||||
// have single numeric values for Horizontal or Vertical line_to commands
|
||||
// as well as more than two coordinates (4 or 6) for Bezier curves
|
||||
// depending on the semantics of the command.
|
||||
// The behaviour is as follows:
|
||||
//
|
||||
// Each call to next() returns true if there's new command or new numeric
|
||||
// value or false when the path ends. How to interpret the result
|
||||
// depends on the sematics of the command. For example, command "C"
|
||||
// (cubic Bezier curve) implies 6 floating point numbers preceded by this
|
||||
// command. If the command assumes no arguments (like z or Z) the
|
||||
// the last_number() values won't change, that is, last_number() always
|
||||
// returns the last recognized numeric value, so does last_command().
|
||||
//===============================================================
|
||||
class path_tokenizer
|
||||
{
|
||||
public:
|
||||
path_tokenizer();
|
||||
|
||||
void set_path_str(const char* str);
|
||||
bool next();
|
||||
|
||||
double next(char cmd);
|
||||
|
||||
char last_command() const { return m_last_command; }
|
||||
double last_number() const { return m_last_number; }
|
||||
|
||||
|
||||
private:
|
||||
static void init_char_mask(char* mask, const char* char_set);
|
||||
|
||||
bool contains(const char* mask, unsigned c) const
|
||||
{
|
||||
return (mask[(c >> 3) & (256/8-1)] & (1 << (c & 7))) != 0;
|
||||
}
|
||||
|
||||
bool is_command(unsigned c) const
|
||||
{
|
||||
return contains(m_commands_mask, c);
|
||||
}
|
||||
|
||||
bool is_numeric(unsigned c) const
|
||||
{
|
||||
return contains(m_numeric_mask, c);
|
||||
}
|
||||
|
||||
bool is_separator(unsigned c) const
|
||||
{
|
||||
return contains(m_separators_mask, c);
|
||||
}
|
||||
|
||||
bool parse_number();
|
||||
|
||||
char m_separators_mask[256/8];
|
||||
char m_commands_mask[256/8];
|
||||
char m_numeric_mask[256/8];
|
||||
|
||||
const char* m_path;
|
||||
double m_last_number;
|
||||
char m_last_command;
|
||||
|
||||
static const char s_commands[];
|
||||
static const char s_numeric[];
|
||||
static const char s_separators[];
|
||||
};
|
||||
|
||||
} //namespace svg
|
||||
} //namespace agg
|
||||
|
||||
|
||||
#endif
|
200
src/agg_svg/agg_trans_affine.cpp
Normal file
200
src/agg_svg/agg_trans_affine.cpp
Normal file
|
@ -0,0 +1,200 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include <agg/agg_trans_affine.h>
|
||||
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_affine& trans_affine::parl_to_parl(const double* src,
|
||||
const double* dst)
|
||||
{
|
||||
sx = src[2] - src[0];
|
||||
shy = src[3] - src[1];
|
||||
shx = src[4] - src[0];
|
||||
sy = src[5] - src[1];
|
||||
tx = src[0];
|
||||
ty = src[1];
|
||||
invert();
|
||||
multiply(trans_affine(dst[2] - dst[0], dst[3] - dst[1],
|
||||
dst[4] - dst[0], dst[5] - dst[1],
|
||||
dst[0], dst[1]));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_affine& trans_affine::rect_to_parl(double x1, double y1,
|
||||
double x2, double y2,
|
||||
const double* parl)
|
||||
{
|
||||
double src[6];
|
||||
src[0] = x1; src[1] = y1;
|
||||
src[2] = x2; src[3] = y1;
|
||||
src[4] = x2; src[5] = y2;
|
||||
parl_to_parl(src, parl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_affine& trans_affine::parl_to_rect(const double* parl,
|
||||
double x1, double y1,
|
||||
double x2, double y2)
|
||||
{
|
||||
double dst[6];
|
||||
dst[0] = x1; dst[1] = y1;
|
||||
dst[2] = x2; dst[3] = y1;
|
||||
dst[4] = x2; dst[5] = y2;
|
||||
parl_to_parl(parl, dst);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_affine& trans_affine::multiply(const trans_affine& m)
|
||||
{
|
||||
double t0 = sx * m.sx + shy * m.shx;
|
||||
double t2 = shx * m.sx + sy * m.shx;
|
||||
double t4 = tx * m.sx + ty * m.shx + m.tx;
|
||||
shy = sx * m.shy + shy * m.sy;
|
||||
sy = shx * m.shy + sy * m.sy;
|
||||
ty = tx * m.shy + ty * m.sy + m.ty;
|
||||
sx = t0;
|
||||
shx = t2;
|
||||
tx = t4;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_affine& trans_affine::invert()
|
||||
{
|
||||
double d = determinant_reciprocal();
|
||||
|
||||
double t0 = sy * d;
|
||||
sy = sx * d;
|
||||
shy = -shy * d;
|
||||
shx = -shx * d;
|
||||
|
||||
double t4 = -tx * t0 - ty * shx;
|
||||
ty = -tx * shy - ty * sy;
|
||||
|
||||
sx = t0;
|
||||
tx = t4;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_affine& trans_affine::flip_x()
|
||||
{
|
||||
sx = -sx;
|
||||
shy = -shy;
|
||||
tx = -tx;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_affine& trans_affine::flip_y()
|
||||
{
|
||||
shx = -shx;
|
||||
sy = -sy;
|
||||
ty = -ty;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const trans_affine& trans_affine::reset()
|
||||
{
|
||||
sx = sy = 1.0;
|
||||
shy = shx = tx = ty = 0.0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool trans_affine::is_identity(double epsilon) const
|
||||
{
|
||||
return is_equal_eps(sx, 1.0, epsilon) &&
|
||||
is_equal_eps(shy, 0.0, epsilon) &&
|
||||
is_equal_eps(shx, 0.0, epsilon) &&
|
||||
is_equal_eps(sy, 1.0, epsilon) &&
|
||||
is_equal_eps(tx, 0.0, epsilon) &&
|
||||
is_equal_eps(ty, 0.0, epsilon);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool trans_affine::is_valid(double epsilon) const
|
||||
{
|
||||
return fabs(sx) > epsilon && fabs(sy) > epsilon;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool trans_affine::is_equal(const trans_affine& m, double epsilon) const
|
||||
{
|
||||
return is_equal_eps(sx, m.sx, epsilon) &&
|
||||
is_equal_eps(shy, m.shy, epsilon) &&
|
||||
is_equal_eps(shx, m.shx, epsilon) &&
|
||||
is_equal_eps(sy, m.sy, epsilon) &&
|
||||
is_equal_eps(tx, m.tx, epsilon) &&
|
||||
is_equal_eps(ty, m.ty, epsilon);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
double trans_affine::rotation() const
|
||||
{
|
||||
double x1 = 0.0;
|
||||
double y1 = 0.0;
|
||||
double x2 = 1.0;
|
||||
double y2 = 0.0;
|
||||
transform(&x1, &y1);
|
||||
transform(&x2, &y2);
|
||||
return atan2(y2-y1, x2-x1);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void trans_affine::translation(double* dx, double* dy) const
|
||||
{
|
||||
*dx = tx;
|
||||
*dy = ty;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void trans_affine::scaling(double* x, double* y) const
|
||||
{
|
||||
double x1 = 0.0;
|
||||
double y1 = 0.0;
|
||||
double x2 = 1.0;
|
||||
double y2 = 1.0;
|
||||
trans_affine t(*this);
|
||||
t *= trans_affine_rotation(-rotation());
|
||||
t.transform(&x1, &y1);
|
||||
t.transform(&x2, &y2);
|
||||
*x = x2 - x1;
|
||||
*y = y2 - y1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
170
src/agg_svg/agg_vcgen_contour.cpp
Normal file
170
src/agg_svg/agg_vcgen_contour.cpp
Normal file
|
@ -0,0 +1,170 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include <math.h>
|
||||
#include <agg/agg_vcgen_contour.h>
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
vcgen_contour::vcgen_contour() :
|
||||
m_stroker(),
|
||||
m_width(1),
|
||||
m_src_vertices(),
|
||||
m_out_vertices(),
|
||||
m_status(initial),
|
||||
m_src_vertex(0),
|
||||
m_closed(0),
|
||||
m_orientation(0),
|
||||
m_auto_detect(false)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_contour::remove_all()
|
||||
{
|
||||
m_src_vertices.remove_all();
|
||||
m_closed = 0;
|
||||
m_orientation = 0;
|
||||
m_status = initial;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_contour::add_vertex(double x, double y, unsigned cmd)
|
||||
{
|
||||
m_status = initial;
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
m_src_vertices.modify_last(vertex_dist(x, y));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
m_src_vertices.add(vertex_dist(x, y));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
m_closed = get_close_flag(cmd);
|
||||
if(m_orientation == path_flags_none)
|
||||
{
|
||||
m_orientation = get_orientation(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_contour::rewind(unsigned)
|
||||
{
|
||||
if(m_status == initial)
|
||||
{
|
||||
m_src_vertices.close(true);
|
||||
if(m_auto_detect)
|
||||
{
|
||||
if(!is_oriented(m_orientation))
|
||||
{
|
||||
m_orientation = (calc_polygon_area(m_src_vertices) > 0.0) ?
|
||||
path_flags_ccw :
|
||||
path_flags_cw;
|
||||
}
|
||||
}
|
||||
if(is_oriented(m_orientation))
|
||||
{
|
||||
m_stroker.width(is_ccw(m_orientation) ? m_width : -m_width);
|
||||
}
|
||||
}
|
||||
m_status = ready;
|
||||
m_src_vertex = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
unsigned vcgen_contour::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_line_to;
|
||||
while(!is_stop(cmd))
|
||||
{
|
||||
switch(m_status)
|
||||
{
|
||||
case initial:
|
||||
rewind(0);
|
||||
|
||||
case ready:
|
||||
if(m_src_vertices.size() < 2 + unsigned(m_closed != 0))
|
||||
{
|
||||
cmd = path_cmd_stop;
|
||||
break;
|
||||
}
|
||||
m_status = outline;
|
||||
cmd = path_cmd_move_to;
|
||||
m_src_vertex = 0;
|
||||
m_out_vertex = 0;
|
||||
|
||||
case outline:
|
||||
if(m_src_vertex >= m_src_vertices.size())
|
||||
{
|
||||
m_status = end_poly;
|
||||
break;
|
||||
}
|
||||
m_stroker.calc_join(m_out_vertices,
|
||||
m_src_vertices.prev(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex),
|
||||
m_src_vertices.next(m_src_vertex),
|
||||
m_src_vertices.prev(m_src_vertex).dist,
|
||||
m_src_vertices.curr(m_src_vertex).dist);
|
||||
++m_src_vertex;
|
||||
m_status = out_vertices;
|
||||
m_out_vertex = 0;
|
||||
|
||||
case out_vertices:
|
||||
if(m_out_vertex >= m_out_vertices.size())
|
||||
{
|
||||
m_status = outline;
|
||||
}
|
||||
else
|
||||
{
|
||||
const point_d& c = m_out_vertices[m_out_vertex++];
|
||||
*x = c.x;
|
||||
*y = c.y;
|
||||
return cmd;
|
||||
}
|
||||
break;
|
||||
|
||||
case end_poly:
|
||||
if(!m_closed) return path_cmd_stop;
|
||||
m_status = stop;
|
||||
return path_cmd_end_poly | path_flags_close | path_flags_ccw;
|
||||
|
||||
case stop:
|
||||
return path_cmd_stop;
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
}
|
219
src/agg_svg/agg_vcgen_stroke.cpp
Normal file
219
src/agg_svg/agg_vcgen_stroke.cpp
Normal file
|
@ -0,0 +1,219 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry (AGG) - Version 2.5
|
||||
// A high quality rendering engine for C++
|
||||
// Copyright (C) 2002-2006 Maxim Shemanarev
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://antigrain.com
|
||||
//
|
||||
// AGG is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// AGG is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with AGG; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
// MA 02110-1301, USA.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include <math.h>
|
||||
#include <agg/agg_vcgen_stroke.h>
|
||||
#include <agg/agg_shorten_path.h>
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
vcgen_stroke::vcgen_stroke() :
|
||||
m_stroker(),
|
||||
m_src_vertices(),
|
||||
m_out_vertices(),
|
||||
m_shorten(0.0),
|
||||
m_closed(0),
|
||||
m_status(initial),
|
||||
m_src_vertex(0),
|
||||
m_out_vertex(0)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_stroke::remove_all()
|
||||
{
|
||||
m_src_vertices.remove_all();
|
||||
m_closed = 0;
|
||||
m_status = initial;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_stroke::add_vertex(double x, double y, unsigned cmd)
|
||||
{
|
||||
m_status = initial;
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
m_src_vertices.modify_last(vertex_dist(x, y));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
m_src_vertices.add(vertex_dist(x, y));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_closed = get_close_flag(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void vcgen_stroke::rewind(unsigned)
|
||||
{
|
||||
if(m_status == initial)
|
||||
{
|
||||
m_src_vertices.close(m_closed != 0);
|
||||
shorten_path(m_src_vertices, m_shorten, m_closed);
|
||||
if(m_src_vertices.size() < 3) m_closed = 0;
|
||||
}
|
||||
m_status = ready;
|
||||
m_src_vertex = 0;
|
||||
m_out_vertex = 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
unsigned vcgen_stroke::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_line_to;
|
||||
while(!is_stop(cmd))
|
||||
{
|
||||
switch(m_status)
|
||||
{
|
||||
case initial:
|
||||
rewind(0);
|
||||
|
||||
case ready:
|
||||
if(m_src_vertices.size() < 2 + unsigned(m_closed != 0))
|
||||
{
|
||||
cmd = path_cmd_stop;
|
||||
break;
|
||||
}
|
||||
m_status = m_closed ? outline1 : cap1;
|
||||
cmd = path_cmd_move_to;
|
||||
m_src_vertex = 0;
|
||||
m_out_vertex = 0;
|
||||
break;
|
||||
|
||||
case cap1:
|
||||
m_stroker.calc_cap(m_out_vertices,
|
||||
m_src_vertices[0],
|
||||
m_src_vertices[1],
|
||||
m_src_vertices[0].dist);
|
||||
m_src_vertex = 1;
|
||||
m_prev_status = outline1;
|
||||
m_status = out_vertices;
|
||||
m_out_vertex = 0;
|
||||
break;
|
||||
|
||||
case cap2:
|
||||
m_stroker.calc_cap(m_out_vertices,
|
||||
m_src_vertices[m_src_vertices.size() - 1],
|
||||
m_src_vertices[m_src_vertices.size() - 2],
|
||||
m_src_vertices[m_src_vertices.size() - 2].dist);
|
||||
m_prev_status = outline2;
|
||||
m_status = out_vertices;
|
||||
m_out_vertex = 0;
|
||||
break;
|
||||
|
||||
case outline1:
|
||||
if(m_closed)
|
||||
{
|
||||
if(m_src_vertex >= m_src_vertices.size())
|
||||
{
|
||||
m_prev_status = close_first;
|
||||
m_status = end_poly1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_src_vertex >= m_src_vertices.size() - 1)
|
||||
{
|
||||
m_status = cap2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_stroker.calc_join(m_out_vertices,
|
||||
m_src_vertices.prev(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex),
|
||||
m_src_vertices.next(m_src_vertex),
|
||||
m_src_vertices.prev(m_src_vertex).dist,
|
||||
m_src_vertices.curr(m_src_vertex).dist);
|
||||
++m_src_vertex;
|
||||
m_prev_status = m_status;
|
||||
m_status = out_vertices;
|
||||
m_out_vertex = 0;
|
||||
break;
|
||||
|
||||
case close_first:
|
||||
m_status = outline2;
|
||||
cmd = path_cmd_move_to;
|
||||
|
||||
case outline2:
|
||||
if(m_src_vertex <= unsigned(m_closed == 0))
|
||||
{
|
||||
m_status = end_poly2;
|
||||
m_prev_status = stop;
|
||||
break;
|
||||
}
|
||||
|
||||
--m_src_vertex;
|
||||
m_stroker.calc_join(m_out_vertices,
|
||||
m_src_vertices.next(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex),
|
||||
m_src_vertices.prev(m_src_vertex),
|
||||
m_src_vertices.curr(m_src_vertex).dist,
|
||||
m_src_vertices.prev(m_src_vertex).dist);
|
||||
|
||||
m_prev_status = m_status;
|
||||
m_status = out_vertices;
|
||||
m_out_vertex = 0;
|
||||
break;
|
||||
|
||||
case out_vertices:
|
||||
if(m_out_vertex >= m_out_vertices.size())
|
||||
{
|
||||
m_status = m_prev_status;
|
||||
}
|
||||
else
|
||||
{
|
||||
const point_d& c = m_out_vertices[m_out_vertex++];
|
||||
*x = c.x;
|
||||
*y = c.y;
|
||||
return cmd;
|
||||
}
|
||||
break;
|
||||
|
||||
case end_poly1:
|
||||
m_status = m_prev_status;
|
||||
return path_cmd_end_poly | path_flags_close | path_flags_ccw;
|
||||
|
||||
case end_poly2:
|
||||
m_status = m_prev_status;
|
||||
return path_cmd_end_poly | path_flags_close | path_flags_cw;
|
||||
|
||||
case stop:
|
||||
cmd = path_cmd_stop;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
}
|
|
@ -27,7 +27,7 @@ public:
|
|||
using TPixel = TPixelRenderer::color_type;
|
||||
using TRawBuffer = agg::rendering_buffer;
|
||||
|
||||
using TBuffer = std::vector<TPixelRenderer::pixel_type>;
|
||||
using TBuffer = std::vector<TPixelRenderer::value_type>;
|
||||
|
||||
using TRendererAA = agg::renderer_scanline_aa_solid<TRawRenderer>;
|
||||
|
||||
|
@ -36,6 +36,11 @@ public:
|
|||
|
||||
using Origin = Raster::Origin;
|
||||
|
||||
enum
|
||||
{
|
||||
num_components = 1,
|
||||
};
|
||||
|
||||
private:
|
||||
Raster::Resolution m_resolution;
|
||||
Raster::PixelDim m_pxdim;
|
||||
|
@ -58,7 +63,7 @@ public:
|
|||
m_buf(res.pixels()),
|
||||
m_rbuf(reinterpret_cast<TPixelRenderer::value_type*>(m_buf.data()),
|
||||
res.width_px, res.height_px,
|
||||
int(res.width_px*TPixelRenderer::num_components)),
|
||||
int(res.width_px*num_components)),
|
||||
m_pixfmt(m_rbuf),
|
||||
m_raw_renderer(m_pixfmt),
|
||||
m_renderer(m_raw_renderer),
|
||||
|
|
|
@ -121,6 +121,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
Utils/Bonjour.hpp
|
||||
Utils/PresetUpdater.cpp
|
||||
Utils/PresetUpdater.hpp
|
||||
Utils/SVGImport.cpp
|
||||
Utils/SVGImport.hpp
|
||||
Utils/Time.cpp
|
||||
Utils/Time.hpp
|
||||
Utils/HexFile.cpp
|
||||
|
@ -133,7 +135,10 @@ endif ()
|
|||
|
||||
add_library(libslic3r_gui STATIC ${SLIC3R_GUI_SOURCES})
|
||||
|
||||
target_link_libraries(libslic3r_gui libslic3r avrdude imgui)
|
||||
target_compile_definitions(libslic3r_gui PUBLIC -DUSE_TBB ${PNG_DEFINITIONS})
|
||||
target_include_directories(libslic3r_gui PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${PNG_INCLUDE_DIRS})
|
||||
target_link_libraries(libslic3r_gui libslic3r avrdude imgui ${PNG_LIBRARIES} agg_svg)
|
||||
|
||||
if (SLIC3R_PCH AND NOT SLIC3R_SYNTAXONLY)
|
||||
add_precompiled_header(libslic3r_gui pchheader.hpp FORCEINCLUDE)
|
||||
endif ()
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <fstream>
|
||||
#include "GUI_App.hpp"
|
||||
#include "Utils/SVGImport.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
@ -35,6 +36,9 @@ MainFrame::MainFrame() :
|
|||
wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe"),
|
||||
m_printhost_queue_dlg(new PrintHostQueueDialog(this))
|
||||
{
|
||||
|
||||
Slic3r::Utils::vojtikuv_pokus();
|
||||
|
||||
// Load the icon either from the exe, or from the ico file.
|
||||
#if _WIN32
|
||||
{
|
||||
|
|
98
src/slic3r/Utils/SVGImport.cpp
Normal file
98
src/slic3r/Utils/SVGImport.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include "SVGImport.hpp"
|
||||
|
||||
#include <agg/agg_basics.h>
|
||||
#include <agg/agg_rendering_buffer.h>
|
||||
#include <agg/agg_rasterizer_scanline_aa.h>
|
||||
#include <agg/agg_scanline_p.h>
|
||||
#include <agg/agg_renderer_scanline.h>
|
||||
#include <agg/agg_pixfmt_rgba.h>
|
||||
#include <agg_svg/agg_svg_parser.h>
|
||||
|
||||
#include <png/writer.hpp>
|
||||
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
|
||||
namespace Slic3r { namespace Utils {
|
||||
|
||||
int vojtikuv_pokus()
|
||||
{
|
||||
std::string fname = "D:\\temp\\svg_examples\\slicer_vnitrni-menu.svg";
|
||||
try
|
||||
{
|
||||
agg::svg::path_renderer path;
|
||||
agg::svg::parser prsr(path);
|
||||
prsr.parse(fname.c_str());
|
||||
path.arrange_orientations();
|
||||
double m_min_x;
|
||||
double m_min_y;
|
||||
double m_max_x;
|
||||
double m_max_y;
|
||||
path.bounding_rect(&m_min_x, &m_min_y, &m_max_x, &m_max_y);
|
||||
// caption(p.title());
|
||||
|
||||
|
||||
// typedef agg::pixfmt_bgra32 pixfmt;
|
||||
typedef agg::pixfmt_rgba32 pixfmt;
|
||||
typedef agg::renderer_base<pixfmt> renderer_base;
|
||||
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid;
|
||||
|
||||
unsigned int width_px = 1000;
|
||||
unsigned int height_px = 1000;
|
||||
std::vector<unsigned char> buffer(width_px * height_px * 4, 0);
|
||||
agg::rendering_buffer rbuf(reinterpret_cast<pixfmt::value_type*>(buffer.data()), width_px, height_px, int(width_px * 4));
|
||||
pixfmt pixf(rbuf);
|
||||
renderer_base rb(pixf);
|
||||
renderer_solid ren(rb);
|
||||
|
||||
rb.clear(agg::rgba(1,1,1));
|
||||
|
||||
agg::rasterizer_scanline_aa<> ras;
|
||||
agg::scanline_p8 sl;
|
||||
agg::trans_affine mtx;
|
||||
|
||||
ras.gamma(agg::gamma_power(1.));
|
||||
mtx *= agg::trans_affine_translation(- m_min_x, - m_min_y);
|
||||
mtx *= agg::trans_affine_scaling(double(width_px) / (m_max_x - m_min_x), double(height_px) / (m_max_y - m_min_y));
|
||||
|
||||
path.expand(1.);
|
||||
path.render(ras, sl, ren, mtx, rb.clip_box(), 1.0);
|
||||
|
||||
// ren.color(agg::rgba(0,0,0));
|
||||
ren.color(agg::rgba(1,1,1));
|
||||
agg::render_scanlines(ras, sl, ren);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
try {
|
||||
boost::nowide::ofstream c;
|
||||
c.open("d:\\temp\\rasterized.png", std::ios::out | std::ios::binary | std::ios::trunc);
|
||||
png::writer<std::ostream> wr(c);
|
||||
wr.set_bit_depth(8);
|
||||
wr.set_color_type(png::color_type_rgb_alpha);
|
||||
wr.set_width(width_px);
|
||||
wr.set_height(height_px);
|
||||
wr.set_compression_type(png::compression_type_default);
|
||||
wr.write_info();
|
||||
auto ptr = reinterpret_cast<png::byte*>(buffer.data());
|
||||
unsigned stride = 4 * width_px;
|
||||
for(unsigned r = 0; r < height_px; ++ r, ptr += stride)
|
||||
wr.write_row(ptr);
|
||||
wr.write_end_info();
|
||||
c.close();
|
||||
}
|
||||
catch (std::exception &ex) {
|
||||
printf("Hu!");
|
||||
}
|
||||
}
|
||||
catch(agg::svg::exception& e)
|
||||
{
|
||||
// app.message(e.msg());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} } // namespace Slic3r::Utils
|
12
src/slic3r/Utils/SVGImport.hpp
Normal file
12
src/slic3r/Utils/SVGImport.hpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef slic3r_Utils_SVGImport_hpp_
|
||||
#define slic3r_Utils_SVGImport_hpp_
|
||||
|
||||
namespace Slic3r {
|
||||
namespace Utils {
|
||||
|
||||
int vojtikuv_pokus();
|
||||
|
||||
}; // namespace Utils
|
||||
}; // namespace Slic3r
|
||||
|
||||
#endif /* slic3r_Utils_SVGImport_hpp_ */
|
Loading…
Reference in a new issue