Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/agg
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2019-02-07 14:09:10 +0300
committerbubnikv <bubnikv@gmail.com>2019-02-07 14:09:10 +0300
commit34b14eb8fa4bfcec9612b7e26d95e160caefa027 (patch)
tree1c9ac54f01e2d6d7566472a880eba3c36aaea497 /src/agg
parenta178a0ff7e951e43d88114a43a99036fb5b6f2bb (diff)
Revert "WIP: SVG import & rasterization"
This reverts commit 9b15908a47af12658d6563cddac334505e27b60a.
Diffstat (limited to 'src/agg')
-rw-r--r--src/agg/AUTHORS5
-rw-r--r--src/agg/README21
-rw-r--r--src/agg/VERSION2
-rw-r--r--src/agg/agg_array.h30
-rw-r--r--src/agg/agg_basics.h83
-rw-r--r--src/agg/agg_bezier_arc.h36
-rw-r--r--src/agg/agg_bounding_rect.h122
-rw-r--r--src/agg/agg_clip_liang_barsky.h34
-rw-r--r--src/agg/agg_color_gray.h992
-rw-r--r--src/agg/agg_color_rgba.h1139
-rw-r--r--src/agg/agg_config.h2
-rw-r--r--src/agg/agg_conv_adaptor_vcgen.h166
-rw-r--r--src/agg/agg_conv_contour.h71
-rw-r--r--src/agg/agg_conv_curve.h206
-rw-r--r--src/agg/agg_conv_stroke.h79
-rw-r--r--src/agg/agg_conv_transform.h40
-rw-r--r--src/agg/agg_curves.h701
-rw-r--r--src/agg/agg_gamma_functions.h38
-rw-r--r--src/agg/agg_gamma_lut.h208
-rw-r--r--src/agg/agg_math.h29
-rw-r--r--src/agg/agg_math_stroke.h531
-rw-r--r--src/agg/agg_path_storage.h72
-rw-r--r--src/agg/agg_pixfmt_base.h97
-rw-r--r--src/agg/agg_pixfmt_gray.h505
-rw-r--r--src/agg/agg_pixfmt_rgb.h716
-rw-r--r--src/agg/agg_pixfmt_rgba.h2911
-rw-r--r--src/agg/agg_rasterizer_cells_aa.h139
-rw-r--r--src/agg/agg_rasterizer_scanline_aa.h65
-rw-r--r--src/agg/agg_rasterizer_scanline_aa_nogamma.h483
-rw-r--r--src/agg/agg_rasterizer_sl_clip.h32
-rw-r--r--src/agg/agg_renderer_base.h46
-rw-r--r--src/agg/agg_renderer_scanline.h35
-rw-r--r--src/agg/agg_rendering_buffer.h55
-rw-r--r--src/agg/agg_scanline_p.h33
-rw-r--r--src/agg/agg_shorten_path.h75
-rw-r--r--src/agg/agg_trans_affine.h48
-rw-r--r--src/agg/agg_vcgen_contour.h103
-rw-r--r--src/agg/agg_vcgen_stroke.h111
-rw-r--r--src/agg/agg_vertex_sequence.h178
-rw-r--r--src/agg/copying366
40 files changed, 3577 insertions, 7028 deletions
diff --git a/src/agg/AUTHORS b/src/agg/AUTHORS
index c0c4ea344..2bb6518ec 100644
--- a/src/agg/AUTHORS
+++ b/src/agg/AUTHORS
@@ -1,3 +1,2 @@
-Anti-Grain Geometry (AGG) - Version 2.5
-A high quality rendering engine for C++
-Copyright (C) 2002-2006 Maxim Shemanarev
+Anti-Grain Geometry - Version 2.4
+Copyright (C) 2002-2005 Maxim Shemanarev (McSeem)
diff --git a/src/agg/README b/src/agg/README
deleted file mode 100644
index 28420a850..000000000
--- a/src/agg/README
+++ /dev/null
@@ -1,21 +0,0 @@
-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. \ No newline at end of file
diff --git a/src/agg/VERSION b/src/agg/VERSION
new file mode 100644
index 000000000..c5de3e3b0
--- /dev/null
+++ b/src/agg/VERSION
@@ -0,0 +1,2 @@
+2.4
+svn revision 128 \ No newline at end of file
diff --git a/src/agg/agg_array.h b/src/agg/agg_array.h
index 5c6d390bf..8d5668384 100644
--- a/src/agg/agg_array.h
+++ b/src/agg/agg_array.h
@@ -1,27 +1,17 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
//----------------------------------------------------------------------------
-
#ifndef AGG_ARRAY_INCLUDED
#define AGG_ARRAY_INCLUDED
diff --git a/src/agg/agg_basics.h b/src/agg/agg_basics.h
index 4a1b481fc..273850ba1 100644
--- a/src/agg/agg_basics.h
+++ b/src/agg/agg_basics.h
@@ -1,31 +1,22 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_BASICS_INCLUDED
#define AGG_BASICS_INCLUDED
-#include <math.h>
+#include <cmath>
#include "agg_config.h"
//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR
@@ -152,10 +143,18 @@ 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));
@@ -169,10 +168,18 @@ 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));
@@ -186,10 +193,19 @@ 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));
@@ -212,7 +228,7 @@ namespace agg
{
AGG_INLINE static unsigned mul(unsigned a, unsigned b)
{
- register unsigned q = a * b + (1 << (Shift-1));
+ unsigned q = a * b + (1 << (Shift-1));
return (q + (q >> Shift)) >> Shift;
}
};
@@ -238,7 +254,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
@@ -305,6 +321,12 @@ 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
@@ -529,9 +551,22 @@ namespace agg
//------------------------------------------------------------is_equal_eps
template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon)
{
- return fabs(v1 - v2) <= double(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;
+ }
}
diff --git a/src/agg/agg_bezier_arc.h b/src/agg/agg_bezier_arc.h
index a6f2b2221..cfd9308ea 100644
--- a/src/agg/agg_bezier_arc.h
+++ b/src/agg/agg_bezier_arc.h
@@ -1,25 +1,21 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e.,
+// 4, 7, 10, or 13 vertices.
+//
//----------------------------------------------------------------------------
#ifndef AGG_BEZIER_ARC_INCLUDED
@@ -72,7 +68,7 @@ namespace agg
*x = m_vertices[m_vertex];
*y = m_vertices[m_vertex + 1];
m_vertex += 2;
- return (m_vertex == 2) ? path_cmd_move_to : m_cmd;
+ return (m_vertex == 2) ? unsigned(path_cmd_move_to) : m_cmd;
}
// Supplemantary functions. num_vertices() actually returns doubled
diff --git a/src/agg/agg_bounding_rect.h b/src/agg/agg_bounding_rect.h
deleted file mode 100644
index e82c181b2..000000000
--- a/src/agg/agg_bounding_rect.h
+++ /dev/null
@@ -1,122 +0,0 @@
-//----------------------------------------------------------------------------
-// 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
diff --git a/src/agg/agg_clip_liang_barsky.h b/src/agg/agg_clip_liang_barsky.h
index e89756024..4b5fedbab 100644
--- a/src/agg/agg_clip_liang_barsky.h
+++ b/src/agg/agg_clip_liang_barsky.h
@@ -1,27 +1,21 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// Liang-Barsky clipping
+//
//----------------------------------------------------------------------------
-
#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED
#define AGG_CLIP_LIANG_BARSKY_INCLUDED
diff --git a/src/agg/agg_color_gray.h b/src/agg/agg_color_gray.h
index a4d50e8a3..f66588c11 100644
--- a/src/agg/agg_color_gray.h
+++ b/src/agg/agg_color_gray.h
@@ -1,25 +1,16 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Adaptation for high precision colors has been sponsored by
@@ -44,7 +35,8 @@ namespace agg
{
//===================================================================gray8
- struct gray8
+ template<class Colorspace>
+ struct gray8T
{
typedef int8u value_type;
typedef int32u calc_type;
@@ -53,111 +45,329 @@ namespace agg
{
base_shift = 8,
base_scale = 1 << base_shift,
- base_mask = base_scale - 1
+ base_mask = base_scale - 1,
+ base_MSB = 1 << (base_shift - 1)
};
- typedef gray8 self_type;
+ typedef gray8T self_type;
value_type v;
value_type a;
+ static value_type luminance(const rgba& c)
+ {
+ // Calculate grayscale value as per ITU-R BT.709.
+ return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * base_mask));
+ }
+
+ static value_type luminance(const rgba8& c)
+ {
+ // Calculate grayscale value as per ITU-R BT.709.
+ return value_type((55u * c.r + 184u * c.g + 18u * c.b) >> 8);
+ }
+
+ static void convert(gray8T<linear>& dst, const gray8T<sRGB>& src)
+ {
+ dst.v = sRGB_conv<value_type>::rgb_from_sRGB(src.v);
+ dst.a = src.a;
+ }
+
+ static void convert(gray8T<sRGB>& dst, const gray8T<linear>& src)
+ {
+ dst.v = sRGB_conv<value_type>::rgb_to_sRGB(src.v);
+ dst.a = src.a;
+ }
+
+ static void convert(gray8T<linear>& dst, const rgba8& src)
+ {
+ dst.v = luminance(src);
+ dst.a = src.a;
+ }
+
+ static void convert(gray8T<linear>& dst, const srgba8& src)
+ {
+ // The RGB weights are only valid for linear values.
+ convert(dst, rgba8(src));
+ }
+
+ static void convert(gray8T<sRGB>& dst, const rgba8& src)
+ {
+ dst.v = sRGB_conv<value_type>::rgb_to_sRGB(luminance(src));
+ dst.a = src.a;
+ }
+
+ static void convert(gray8T<sRGB>& dst, const srgba8& src)
+ {
+ // The RGB weights are only valid for linear values.
+ convert(dst, rgba8(src));
+ }
+
//--------------------------------------------------------------------
- gray8() {}
+ gray8T() {}
//--------------------------------------------------------------------
- gray8(unsigned v_, unsigned a_=base_mask) :
+ explicit gray8T(unsigned v_, unsigned a_ = base_mask) :
v(int8u(v_)), a(int8u(a_)) {}
//--------------------------------------------------------------------
- gray8(const self_type& c, unsigned a_) :
+ gray8T(const self_type& c, unsigned a_) :
v(c.v), a(value_type(a_)) {}
//--------------------------------------------------------------------
- gray8(const rgba& c) :
- v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
- a((value_type)uround(c.a * double(base_mask))) {}
+ gray8T(const rgba& c) :
+ v(luminance(c)),
+ a(value_type(uround(c.a * base_mask))) {}
//--------------------------------------------------------------------
- gray8(const rgba& c, double a_) :
- v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
- a((value_type)uround(a_ * double(base_mask))) {}
+ template<class T>
+ gray8T(const gray8T<T>& c)
+ {
+ convert(*this, c);
+ }
//--------------------------------------------------------------------
- gray8(const rgba8& c) :
- v((c.r*77 + c.g*150 + c.b*29) >> 8),
- a(c.a) {}
+ template<class T>
+ gray8T(const rgba8T<T>& c)
+ {
+ convert(*this, c);
+ }
//--------------------------------------------------------------------
- gray8(const rgba8& c, unsigned a_) :
- v((c.r*77 + c.g*150 + c.b*29) >> 8),
- a(a_) {}
+ template<class T>
+ T convert_from_sRGB() const
+ {
+ typename T::value_type y = sRGB_conv<typename T::value_type>::rgb_from_sRGB(v);
+ return T(y, y, y, sRGB_conv<typename T::value_type>::alpha_from_sRGB(a));
+ }
+
+ template<class T>
+ T convert_to_sRGB() const
+ {
+ typename T::value_type y = sRGB_conv<typename T::value_type>::rgb_to_sRGB(v);
+ return T(y, y, y, sRGB_conv<typename T::value_type>::alpha_to_sRGB(a));
+ }
//--------------------------------------------------------------------
- void clear()
+ rgba8 make_rgba8(const linear&) const
{
- v = a = 0;
+ return rgba8(v, v, v, a);
+ }
+
+ rgba8 make_rgba8(const sRGB&) const
+ {
+ return convert_from_sRGB<srgba8>();
+ }
+
+ operator rgba8() const
+ {
+ return make_rgba8(Colorspace());
}
//--------------------------------------------------------------------
- const self_type& transparent()
+ srgba8 make_srgba8(const linear&) const
{
- a = 0;
- return *this;
+ return convert_to_sRGB<rgba8>();
+ }
+
+ srgba8 make_srgba8(const sRGB&) const
+ {
+ return srgba8(v, v, v, a);
+ }
+
+ operator srgba8() const
+ {
+ return make_rgba8(Colorspace());
}
//--------------------------------------------------------------------
- void opacity(double a_)
+ rgba16 make_rgba16(const linear&) const
+ {
+ rgba16::value_type rgb = (v << 8) | v;
+ return rgba16(rgb, rgb, rgb, (a << 8) | a);
+ }
+
+ rgba16 make_rgba16(const sRGB&) const
+ {
+ return convert_from_sRGB<rgba16>();
+ }
+
+ operator rgba16() const
{
- if(a_ < 0.0) a_ = 0.0;
- if(a_ > 1.0) a_ = 1.0;
- a = (value_type)uround(a_ * double(base_mask));
+ return make_rgba16(Colorspace());
}
//--------------------------------------------------------------------
- double opacity() const
+ rgba32 make_rgba32(const linear&) const
{
- return double(a) / double(base_mask);
+ rgba32::value_type v32 = v / 255.0f;
+ return rgba32(v32, v32, v32, a / 255.0f);
}
+ rgba32 make_rgba32(const sRGB&) const
+ {
+ return convert_from_sRGB<rgba32>();
+ }
+
+ operator rgba32() const
+ {
+ return make_rgba32(Colorspace());
+ }
//--------------------------------------------------------------------
- const self_type& premultiply()
+ static AGG_INLINE double to_double(value_type a)
{
- if(a == base_mask) return *this;
- if(a == 0)
+ return double(a) / base_mask;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type from_double(double a)
+ {
+ return value_type(uround(a * base_mask));
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type empty_value()
+ {
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type full_value()
+ {
+ return base_mask;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE bool is_transparent() const
+ {
+ return a == 0;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE bool is_opaque() const
+ {
+ return a == base_mask;
+ }
+
+ //--------------------------------------------------------------------
+ // Fixed-point multiply, exact over int8u.
+ static AGG_INLINE value_type multiply(value_type a, value_type b)
+ {
+ calc_type t = a * b + base_MSB;
+ return value_type(((t >> base_shift) + t) >> base_shift);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type demultiply(value_type a, value_type b)
+ {
+ if (a * b == 0)
{
- v = 0;
- return *this;
+ return 0;
}
- v = value_type((calc_type(v) * a) >> base_shift);
+ else if (a >= b)
+ {
+ return base_mask;
+ }
+ else return value_type((a * base_mask + (b >> 1)) / b);
+ }
+
+ //--------------------------------------------------------------------
+ template<typename T>
+ static AGG_INLINE T downscale(T a)
+ {
+ return a >> base_shift;
+ }
+
+ //--------------------------------------------------------------------
+ template<typename T>
+ static AGG_INLINE T downshift(T a, unsigned n)
+ {
+ return a >> n;
+ }
+
+ //--------------------------------------------------------------------
+ // Fixed-point multiply, exact over int8u.
+ // Specifically for multiplying a color component by a cover.
+ static AGG_INLINE value_type mult_cover(value_type a, value_type b)
+ {
+ return multiply(a, b);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
+ {
+ return multiply(b, a);
+ }
+
+ //--------------------------------------------------------------------
+ // Interpolate p to q by a, assuming q is premultiplied by a.
+ static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
+ {
+ return p + q - multiply(p, a);
+ }
+
+ //--------------------------------------------------------------------
+ // Interpolate p to q by a.
+ static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
+ {
+ int t = (q - p) * a + base_MSB - (p > q);
+ return value_type(p + (((t >> base_shift) + t) >> base_shift));
+ }
+
+ //--------------------------------------------------------------------
+ self_type& clear()
+ {
+ v = a = 0;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ self_type& transparent()
+ {
+ a = 0;
return *this;
}
//--------------------------------------------------------------------
- const self_type& premultiply(unsigned a_)
+ self_type& opacity(double a_)
+ {
+ if (a_ < 0) a = 0;
+ else if (a_ > 1) a = 1;
+ else a = (value_type)uround(a_ * double(base_mask));
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ double opacity() const
{
- if(a == base_mask && a_ >= base_mask) return *this;
- if(a == 0 || a_ == 0)
+ return double(a) / double(base_mask);
+ }
+
+ //--------------------------------------------------------------------
+ self_type& premultiply()
+ {
+ if (a < base_mask)
{
- v = a = 0;
- return *this;
+ if (a == 0) v = 0;
+ else v = multiply(v, a);
}
- calc_type v_ = (calc_type(v) * a_) / a;
- v = value_type((v_ > a_) ? a_ : v_);
- a = value_type(a_);
return *this;
}
//--------------------------------------------------------------------
- const self_type& demultiply()
+ self_type& demultiply()
{
- if(a == base_mask) return *this;
- if(a == 0)
+ if (a < base_mask)
{
- v = 0;
- return *this;
+ if (a == 0)
+ {
+ v = 0;
+ }
+ else
+ {
+ calc_type v_ = (calc_type(v) * base_mask) / a;
+ v = value_type((v_ > base_mask) ? (value_type)base_mask : v_);
+ }
}
- calc_type v_ = (calc_type(v) * base_mask) / a;
- v = value_type((v_ > base_mask) ? (value_type)base_mask : v_);
return *this;
}
@@ -166,8 +376,8 @@ namespace agg
{
self_type ret;
calc_type ik = uround(k * base_scale);
- ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift));
- ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
+ ret.v = lerp(v, c.v, ik);
+ ret.a = lerp(a, c.a, ik);
return ret;
}
@@ -175,59 +385,34 @@ namespace agg
AGG_INLINE void add(const self_type& c, unsigned cover)
{
calc_type cv, ca;
- if(cover == cover_mask)
+ if (cover == cover_mask)
{
- if(c.a == base_mask)
+ if (c.a == base_mask)
{
*this = c;
+ return;
}
else
{
- cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
- ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ cv = v + c.v;
+ ca = a + c.a;
}
}
else
{
- cv = v + ((c.v * cover + cover_mask/2) >> cover_shift);
- ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
- v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
- a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ cv = v + mult_cover(c.v, cover);
+ ca = a + mult_cover(c.a, cover);
}
+ v = (value_type)((cv > calc_type(base_mask)) ? calc_type(base_mask) : cv);
+ a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca);
}
//--------------------------------------------------------------------
static self_type no_color() { return self_type(0,0); }
};
-
- //-------------------------------------------------------------gray8_pre
- inline gray8 gray8_pre(unsigned v, unsigned a = gray8::base_mask)
- {
- return gray8(v,a).premultiply();
- }
- inline gray8 gray8_pre(const gray8& c, unsigned a)
- {
- return gray8(c,a).premultiply();
- }
- inline gray8 gray8_pre(const rgba& c)
- {
- return gray8(c).premultiply();
- }
- inline gray8 gray8_pre(const rgba& c, double a)
- {
- return gray8(c,a).premultiply();
- }
- inline gray8 gray8_pre(const rgba8& c)
- {
- return gray8(c).premultiply();
- }
- inline gray8 gray8_pre(const rgba8& c, unsigned a)
- {
- return gray8(c,a).premultiply();
- }
-
-
+ typedef gray8T<linear> gray8;
+ typedef gray8T<sRGB> sgray8;
//==================================================================gray16
@@ -240,18 +425,46 @@ namespace agg
{
base_shift = 16,
base_scale = 1 << base_shift,
- base_mask = base_scale - 1
+ base_mask = base_scale - 1,
+ base_MSB = 1 << (base_shift - 1)
};
typedef gray16 self_type;
value_type v;
value_type a;
+ static value_type luminance(const rgba& c)
+ {
+ // Calculate grayscale value as per ITU-R BT.709.
+ return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * base_mask));
+ }
+
+ static value_type luminance(const rgba16& c)
+ {
+ // Calculate grayscale value as per ITU-R BT.709.
+ return value_type((13933u * c.r + 46872u * c.g + 4732u * c.b) >> 16);
+ }
+
+ static value_type luminance(const rgba8& c)
+ {
+ return luminance(rgba16(c));
+ }
+
+ static value_type luminance(const srgba8& c)
+ {
+ return luminance(rgba16(c));
+ }
+
+ static value_type luminance(const rgba32& c)
+ {
+ return luminance(rgba(c));
+ }
+
//--------------------------------------------------------------------
gray16() {}
//--------------------------------------------------------------------
- gray16(unsigned v_, unsigned a_=base_mask) :
+ explicit gray16(unsigned v_, unsigned a_ = base_mask) :
v(int16u(v_)), a(int16u(a_)) {}
//--------------------------------------------------------------------
@@ -260,91 +473,231 @@ namespace agg
//--------------------------------------------------------------------
gray16(const rgba& c) :
- v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
+ v(luminance(c)),
a((value_type)uround(c.a * double(base_mask))) {}
//--------------------------------------------------------------------
- gray16(const rgba& c, double a_) :
- v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))),
- a((value_type)uround(a_ * double(base_mask))) {}
+ gray16(const rgba8& c) :
+ v(luminance(c)),
+ a((value_type(c.a) << 8) | c.a) {}
//--------------------------------------------------------------------
- gray16(const rgba8& c) :
- v(c.r*77 + c.g*150 + c.b*29),
+ gray16(const srgba8& c) :
+ v(luminance(c)),
+ a((value_type(c.a) << 8) | c.a) {}
+
+ //--------------------------------------------------------------------
+ gray16(const rgba16& c) :
+ v(luminance(c)),
+ a(c.a) {}
+
+ //--------------------------------------------------------------------
+ gray16(const gray8& c) :
+ v((value_type(c.v) << 8) | c.v),
a((value_type(c.a) << 8) | c.a) {}
//--------------------------------------------------------------------
- gray16(const rgba8& c, unsigned a_) :
- v(c.r*77 + c.g*150 + c.b*29),
- a((value_type(a_) << 8) | c.a) {}
+ gray16(const sgray8& c) :
+ v(sRGB_conv<value_type>::rgb_from_sRGB(c.v)),
+ a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {}
//--------------------------------------------------------------------
- void clear()
+ operator rgba8() const
{
- v = a = 0;
+ return rgba8(v >> 8, v >> 8, v >> 8, a >> 8);
}
//--------------------------------------------------------------------
- const self_type& transparent()
+ operator srgba8() const
{
- a = 0;
- return *this;
+ value_type y = sRGB_conv<value_type>::rgb_to_sRGB(v);
+ return srgba8(y, y, y, sRGB_conv<value_type>::alpha_to_sRGB(a));
}
//--------------------------------------------------------------------
- void opacity(double a_)
+ operator rgba16() const
{
- if(a_ < 0.0) a_ = 0.0;
- if(a_ > 1.0) a_ = 1.0;
- a = (value_type)uround(a_ * double(base_mask));
+ return rgba16(v, v, v, a);
+ }
+
+ //--------------------------------------------------------------------
+ operator rgba32() const
+ {
+ rgba32::value_type v32 = v / 65535.0f;
+ return rgba32(v32, v32, v32, a / 65535.0f);
+ }
+
+ //--------------------------------------------------------------------
+ operator gray8() const
+ {
+ return gray8(v >> 8, a >> 8);
}
//--------------------------------------------------------------------
- double opacity() const
+ operator sgray8() const
{
- return double(a) / double(base_mask);
+ return sgray8(
+ sRGB_conv<value_type>::rgb_to_sRGB(v),
+ sRGB_conv<value_type>::alpha_to_sRGB(a));
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE double to_double(value_type a)
+ {
+ return double(a) / base_mask;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type from_double(double a)
+ {
+ return value_type(uround(a * base_mask));
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type empty_value()
+ {
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type full_value()
+ {
+ return base_mask;
}
+ //--------------------------------------------------------------------
+ AGG_INLINE bool is_transparent() const
+ {
+ return a == 0;
+ }
//--------------------------------------------------------------------
- const self_type& premultiply()
+ AGG_INLINE bool is_opaque() const
{
- if(a == base_mask) return *this;
- if(a == 0)
+ return a == base_mask;
+ }
+
+ //--------------------------------------------------------------------
+ // Fixed-point multiply, exact over int16u.
+ static AGG_INLINE value_type multiply(value_type a, value_type b)
+ {
+ calc_type t = a * b + base_MSB;
+ return value_type(((t >> base_shift) + t) >> base_shift);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type demultiply(value_type a, value_type b)
+ {
+ if (a * b == 0)
+ {
+ return 0;
+ }
+ else if (a >= b)
{
- v = 0;
- return *this;
+ return base_mask;
}
- v = value_type((calc_type(v) * a) >> base_shift);
+ else return value_type((a * base_mask + (b >> 1)) / b);
+ }
+
+ //--------------------------------------------------------------------
+ template<typename T>
+ static AGG_INLINE T downscale(T a)
+ {
+ return a >> base_shift;
+ }
+
+ //--------------------------------------------------------------------
+ template<typename T>
+ static AGG_INLINE T downshift(T a, unsigned n)
+ {
+ return a >> n;
+ }
+
+ //--------------------------------------------------------------------
+ // Fixed-point multiply, almost exact over int16u.
+ // Specifically for multiplying a color component by a cover.
+ static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
+ {
+ return multiply(a, b << 8 | b);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
+ {
+ return mult_cover(b, a) >> 8;
+ }
+
+ //--------------------------------------------------------------------
+ // Interpolate p to q by a, assuming q is premultiplied by a.
+ static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
+ {
+ return p + q - multiply(p, a);
+ }
+
+ //--------------------------------------------------------------------
+ // Interpolate p to q by a.
+ static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
+ {
+ int t = (q - p) * a + base_MSB - (p > q);
+ return value_type(p + (((t >> base_shift) + t) >> base_shift));
+ }
+
+ //--------------------------------------------------------------------
+ self_type& clear()
+ {
+ v = a = 0;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ self_type& transparent()
+ {
+ a = 0;
return *this;
}
//--------------------------------------------------------------------
- const self_type& premultiply(unsigned a_)
+ self_type& opacity(double a_)
+ {
+ if (a_ < 0) a = 0;
+ else if(a_ > 1) a = 1;
+ else a = (value_type)uround(a_ * double(base_mask));
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ double opacity() const
+ {
+ return double(a) / double(base_mask);
+ }
+
+
+ //--------------------------------------------------------------------
+ self_type& premultiply()
{
- if(a == base_mask && a_ >= base_mask) return *this;
- if(a == 0 || a_ == 0)
+ if (a < base_mask)
{
- v = a = 0;
- return *this;
+ if(a == 0) v = 0;
+ else v = multiply(v, a);
}
- calc_type v_ = (calc_type(v) * a_) / a;
- v = value_type((v_ > a_) ? a_ : v_);
- a = value_type(a_);
return *this;
}
//--------------------------------------------------------------------
- const self_type& demultiply()
+ self_type& demultiply()
{
- if(a == base_mask) return *this;
- if(a == 0)
+ if (a < base_mask)
{
- v = 0;
- return *this;
+ if (a == 0)
+ {
+ v = 0;
+ }
+ else
+ {
+ calc_type v_ = (calc_type(v) * base_mask) / a;
+ v = (v_ > base_mask) ? value_type(base_mask) : value_type(v_);
+ }
}
- calc_type v_ = (calc_type(v) * base_mask) / a;
- v = value_type((v_ > base_mask) ? base_mask : v_);
return *this;
}
@@ -353,8 +706,8 @@ namespace agg
{
self_type ret;
calc_type ik = uround(k * base_scale);
- ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift));
- ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
+ ret.v = lerp(v, c.v, ik);
+ ret.a = lerp(a, c.a, ik);
return ret;
}
@@ -362,25 +715,26 @@ namespace agg
AGG_INLINE void add(const self_type& c, unsigned cover)
{
calc_type cv, ca;
- if(cover == cover_mask)
+ if (cover == cover_mask)
{
- if(c.a == base_mask)
+ if (c.a == base_mask)
{
*this = c;
+ return;
}
else
{
- cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
- ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ cv = v + c.v;
+ ca = a + c.a;
}
}
else
{
- cv = v + ((c.v * cover + cover_mask/2) >> cover_shift);
- ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
- v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
- a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ cv = v + mult_cover(c.v, cover);
+ ca = a + mult_cover(c.a, cover);
}
+ v = (value_type)((cv > calc_type(base_mask)) ? calc_type(base_mask) : cv);
+ a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca);
}
//--------------------------------------------------------------------
@@ -388,33 +742,303 @@ namespace agg
};
- //------------------------------------------------------------gray16_pre
- inline gray16 gray16_pre(unsigned v, unsigned a = gray16::base_mask)
- {
- return gray16(v,a).premultiply();
- }
- inline gray16 gray16_pre(const gray16& c, unsigned a)
+ //===================================================================gray32
+ struct gray32
{
- return gray16(c,a).premultiply();
- }
- inline gray16 gray16_pre(const rgba& c)
- {
- return gray16(c).premultiply();
- }
- inline gray16 gray16_pre(const rgba& c, double a)
- {
- return gray16(c,a).premultiply();
- }
- inline gray16 gray16_pre(const rgba8& c)
- {
- return gray16(c).premultiply();
- }
- inline gray16 gray16_pre(const rgba8& c, unsigned a)
- {
- return gray16(c,a).premultiply();
- }
+ typedef float value_type;
+ typedef double calc_type;
+ typedef double long_type;
+ typedef gray32 self_type;
+
+ value_type v;
+ value_type a;
+
+ // Calculate grayscale value as per ITU-R BT.709.
+ static value_type luminance(double r, double g, double b)
+ {
+ return value_type(0.2126 * r + 0.7152 * g + 0.0722 * b);
+ }
+
+ static value_type luminance(const rgba& c)
+ {
+ return luminance(c.r, c.g, c.b);
+ }
+ static value_type luminance(const rgba32& c)
+ {
+ return luminance(c.r, c.g, c.b);
+ }
+
+ static value_type luminance(const rgba8& c)
+ {
+ return luminance(c.r / 255.0, c.g / 255.0, c.g / 255.0);
+ }
+
+ static value_type luminance(const rgba16& c)
+ {
+ return luminance(c.r / 65535.0, c.g / 65535.0, c.g / 65535.0);
+ }
+
+ //--------------------------------------------------------------------
+ gray32() {}
+
+ //--------------------------------------------------------------------
+ explicit gray32(value_type v_, value_type a_ = 1) :
+ v(v_), a(a_) {}
+
+ //--------------------------------------------------------------------
+ gray32(const self_type& c, value_type a_) :
+ v(c.v), a(a_) {}
+
+ //--------------------------------------------------------------------
+ gray32(const rgba& c) :
+ v(luminance(c)),
+ a(value_type(c.a)) {}
+
+ //--------------------------------------------------------------------
+ gray32(const rgba8& c) :
+ v(luminance(c)),
+ a(value_type(c.a / 255.0)) {}
+
+ //--------------------------------------------------------------------
+ gray32(const srgba8& c) :
+ v(luminance(rgba32(c))),
+ a(value_type(c.a / 255.0)) {}
+
+ //--------------------------------------------------------------------
+ gray32(const rgba16& c) :
+ v(luminance(c)),
+ a(value_type(c.a / 65535.0)) {}
+
+ //--------------------------------------------------------------------
+ gray32(const rgba32& c) :
+ v(luminance(c)),
+ a(value_type(c.a)) {}
+
+ //--------------------------------------------------------------------
+ gray32(const gray8& c) :
+ v(value_type(c.v / 255.0)),
+ a(value_type(c.a / 255.0)) {}
+
+ //--------------------------------------------------------------------
+ gray32(const sgray8& c) :
+ v(sRGB_conv<value_type>::rgb_from_sRGB(c.v)),
+ a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {}
+
+ //--------------------------------------------------------------------
+ gray32(const gray16& c) :
+ v(value_type(c.v / 65535.0)),
+ a(value_type(c.a / 65535.0)) {}
+
+ //--------------------------------------------------------------------
+ operator rgba() const
+ {
+ return rgba(v, v, v, a);
+ }
+
+ //--------------------------------------------------------------------
+ operator gray8() const
+ {
+ return gray8(uround(v * 255.0), uround(a * 255.0));
+ }
+
+ //--------------------------------------------------------------------
+ operator sgray8() const
+ {
+ // Return (non-premultiplied) sRGB values.
+ return sgray8(
+ sRGB_conv<value_type>::rgb_to_sRGB(v),
+ sRGB_conv<value_type>::alpha_to_sRGB(a));
+ }
+
+ //--------------------------------------------------------------------
+ operator gray16() const
+ {
+ return gray16(uround(v * 65535.0), uround(a * 65535.0));
+ }
+ //--------------------------------------------------------------------
+ operator rgba8() const
+ {
+ rgba8::value_type y = uround(v * 255.0);
+ return rgba8(y, y, y, uround(a * 255.0));
+ }
+
+ //--------------------------------------------------------------------
+ operator srgba8() const
+ {
+ srgba8::value_type y = sRGB_conv<value_type>::rgb_to_sRGB(v);
+ return srgba8(y, y, y, sRGB_conv<value_type>::alpha_to_sRGB(a));
+ }
+
+ //--------------------------------------------------------------------
+ operator rgba16() const
+ {
+ rgba16::value_type y = uround(v * 65535.0);
+ return rgba16(y, y, y, uround(a * 65535.0));
+ }
+
+ //--------------------------------------------------------------------
+ operator rgba32() const
+ {
+ return rgba32(v, v, v, a);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE double to_double(value_type a)
+ {
+ return a;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type from_double(double a)
+ {
+ return value_type(a);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type empty_value()
+ {
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type full_value()
+ {
+ return 1;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE bool is_transparent() const
+ {
+ return a <= 0;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE bool is_opaque() const
+ {
+ return a >= 1;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type invert(value_type x)
+ {
+ return 1 - x;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type multiply(value_type a, value_type b)
+ {
+ return value_type(a * b);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type demultiply(value_type a, value_type b)
+ {
+ return (b == 0) ? 0 : value_type(a / b);
+ }
+
+ //--------------------------------------------------------------------
+ template<typename T>
+ static AGG_INLINE T downscale(T a)
+ {
+ return a;
+ }
+
+ //--------------------------------------------------------------------
+ template<typename T>
+ static AGG_INLINE T downshift(T a, unsigned n)
+ {
+ return n > 0 ? a / (1 << n) : a;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
+ {
+ return value_type(a * b / cover_mask);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
+ {
+ return cover_type(uround(a * b));
+ }
+
+ //--------------------------------------------------------------------
+ // Interpolate p to q by a, assuming q is premultiplied by a.
+ static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
+ {
+ return (1 - a) * p + q; // more accurate than "p + q - p * a"
+ }
+
+ //--------------------------------------------------------------------
+ // Interpolate p to q by a.
+ static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
+ {
+ // The form "p + a * (q - p)" avoids a multiplication, but may produce an
+ // inaccurate result. For example, "p + (q - p)" may not be exactly equal
+ // to q. Therefore, stick to the basic expression, which at least produces
+ // the correct result at either extreme.
+ return (1 - a) * p + a * q;
+ }
+
+ //--------------------------------------------------------------------
+ self_type& clear()
+ {
+ v = a = 0;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ self_type& transparent()
+ {
+ a = 0;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ self_type& opacity(double a_)
+ {
+ if (a_ < 0) a = 0;
+ else if (a_ > 1) a = 1;
+ else a = value_type(a_);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ double opacity() const
+ {
+ return a;
+ }
+
+
+ //--------------------------------------------------------------------
+ self_type& premultiply()
+ {
+ if (a < 0) v = 0;
+ else if(a < 1) v *= a;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ self_type& demultiply()
+ {
+ if (a < 0) v = 0;
+ else if (a < 1) v /= a;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ self_type gradient(self_type c, double k) const
+ {
+ return self_type(
+ value_type(v + (c.v - v) * k),
+ value_type(a + (c.a - a) * k));
+ }
+
+ //--------------------------------------------------------------------
+ static self_type no_color() { return self_type(0,0); }
+ };
}
diff --git a/src/agg/agg_color_rgba.h b/src/agg/agg_color_rgba.h
index 77efac8ee..ff33a1179 100644
--- a/src/agg/agg_color_rgba.h
+++ b/src/agg/agg_color_rgba.h
@@ -1,25 +1,12 @@
//----------------------------------------------------------------------------
-// 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.
+// 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.
+//
//----------------------------------------------------------------------------
//
// Adaptation for high precision colors has been sponsored by
@@ -39,17 +26,22 @@
#include <math.h>
#include "agg_basics.h"
+#include "agg_gamma_lut.h"
namespace agg
{
- // Supported byte orders for RGB and RGBA pixel formats
+ // Supported component orders for RGB and RGBA pixel formats
//=======================================================================
- struct order_rgb { enum rgb_e { R=0, G=1, B=2, rgb_tag }; }; //----order_rgb
- struct order_bgr { enum bgr_e { B=0, G=1, R=2, rgb_tag }; }; //----order_bgr
- struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag }; }; //----order_rgba
- struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag }; }; //----order_argb
- struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag }; }; //----order_abgr
- struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag }; }; //----order_bgra
+ struct order_rgb { enum rgb_e { R=0, G=1, B=2, N=3 }; };
+ struct order_bgr { enum bgr_e { B=0, G=1, R=2, N=3 }; };
+ struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, N=4 }; };
+ struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, N=4 }; };
+ struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, N=4 }; };
+ struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, N=4 }; };
+
+ // Colorspace tag types.
+ struct linear {};
+ struct sRGB {};
//====================================================================rgba
struct rgba
@@ -72,24 +64,25 @@ namespace agg
rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {}
//--------------------------------------------------------------------
- void clear()
+ rgba& clear()
{
r = g = b = a = 0;
+ return *this;
}
//--------------------------------------------------------------------
- const rgba& transparent()
+ rgba& transparent()
{
- a = 0.0;
+ a = 0;
return *this;
}
//--------------------------------------------------------------------
- const rgba& opacity(double a_)
+ rgba& opacity(double a_)
{
- if(a_ < 0.0) a_ = 0.0;
- if(a_ > 1.0) a_ = 1.0;
- a = a_;
+ if (a_ < 0) a = 0;
+ else if (a_ > 1) a = 1;
+ else a = a_;
return *this;
}
@@ -100,7 +93,7 @@ namespace agg
}
//--------------------------------------------------------------------
- const rgba& premultiply()
+ rgba& premultiply()
{
r *= a;
g *= a;
@@ -109,33 +102,37 @@ namespace agg
}
//--------------------------------------------------------------------
- const rgba& premultiply(double a_)
+ rgba& premultiply(double a_)
{
- if(a <= 0.0 || a_ <= 0.0)
+ if (a <= 0 || a_ <= 0)
{
- r = g = b = a = 0.0;
- return *this;
+ r = g = b = a = 0;
+ }
+ else
+ {
+ a_ /= a;
+ r *= a_;
+ g *= a_;
+ b *= a_;
+ a = a_;
}
- a_ /= a;
- r *= a_;
- g *= a_;
- b *= a_;
- a = a_;
return *this;
}
//--------------------------------------------------------------------
- const rgba& demultiply()
+ rgba& demultiply()
{
- if(a == 0)
+ if (a == 0)
{
r = g = b = 0;
- return *this;
}
- double a_ = 1.0 / a;
- r *= a_;
- g *= a_;
- b *= a_;
+ else
+ {
+ double a_ = 1.0 / a;
+ r *= a_;
+ g *= a_;
+ b *= a_;
+ }
return *this;
}
@@ -151,12 +148,30 @@ namespace agg
return ret;
}
+ rgba& operator+=(const rgba& c)
+ {
+ r += c.r;
+ g += c.g;
+ b += c.b;
+ a += c.a;
+ return *this;
+ }
+
+ rgba& operator*=(double k)
+ {
+ r *= k;
+ g *= k;
+ b *= k;
+ a *= k;
+ return *this;
+ }
+
//--------------------------------------------------------------------
static rgba no_color() { return rgba(0,0,0,0); }
//--------------------------------------------------------------------
static rgba from_wavelength(double wl, double gamma = 1.0);
-
+
//--------------------------------------------------------------------
explicit rgba(double wavelen, double gamma=1.0)
{
@@ -165,18 +180,14 @@ namespace agg
};
- //----------------------------------------------------------------rgba_pre
- inline rgba rgba_pre(double r, double g, double b, double a=1.0)
+ inline rgba operator+(const rgba& a, const rgba& b)
{
- return rgba(r, g, b, a).premultiply();
+ return rgba(a) += b;
}
- inline rgba rgba_pre(const rgba& c)
- {
- return rgba(c).premultiply();
- }
- inline rgba rgba_pre(const rgba& c, double a)
+
+ inline rgba operator*(const rgba& a, double b)
{
- return rgba(c, a).premultiply();
+ return rgba(a) *= b;
}
//------------------------------------------------------------------------
@@ -184,44 +195,39 @@ namespace agg
{
rgba t(0.0, 0.0, 0.0);
- if(wl >= 380.0 && wl <= 440.0)
+ if (wl >= 380.0 && wl <= 440.0)
{
t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0);
t.b = 1.0;
}
- else
- if(wl >= 440.0 && wl <= 490.0)
+ else if (wl >= 440.0 && wl <= 490.0)
{
t.g = (wl - 440.0) / (490.0 - 440.0);
t.b = 1.0;
}
- else
- if(wl >= 490.0 && wl <= 510.0)
+ else if (wl >= 490.0 && wl <= 510.0)
{
t.g = 1.0;
t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0);
}
- else
- if(wl >= 510.0 && wl <= 580.0)
+ else if (wl >= 510.0 && wl <= 580.0)
{
t.r = (wl - 510.0) / (580.0 - 510.0);
t.g = 1.0;
}
- else
- if(wl >= 580.0 && wl <= 645.0)
+ else if (wl >= 580.0 && wl <= 645.0)
{
t.r = 1.0;
t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0);
}
- else
- if(wl >= 645.0 && wl <= 780.0)
+ else if (wl >= 645.0 && wl <= 780.0)
{
t.r = 1.0;
}
double s = 1.0;
- if(wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0);
- else if(wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0);
+ if (wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0);
+ else if (wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0);
t.r = pow(t.r * s, gamma);
t.g = pow(t.g * s, gamma);
@@ -229,11 +235,15 @@ namespace agg
return t;
}
-
+ inline rgba rgba_pre(double r, double g, double b, double a)
+ {
+ return rgba(r, g, b, a).premultiply();
+ }
//===================================================================rgba8
- struct rgba8
+ template<class Colorspace>
+ struct rgba8T
{
typedef int8u value_type;
typedef int32u calc_type;
@@ -242,9 +252,10 @@ namespace agg
{
base_shift = 8,
base_scale = 1 << base_shift,
- base_mask = base_scale - 1
+ base_mask = base_scale - 1,
+ base_MSB = 1 << (base_shift - 1)
};
- typedef rgba8 self_type;
+ typedef rgba8T self_type;
value_type r;
@@ -252,53 +263,218 @@ namespace agg
value_type b;
value_type a;
+ static void convert(rgba8T<linear>& dst, const rgba8T<sRGB>& src)
+ {
+ dst.r = sRGB_conv<value_type>::rgb_from_sRGB(src.r);
+ dst.g = sRGB_conv<value_type>::rgb_from_sRGB(src.g);
+ dst.b = sRGB_conv<value_type>::rgb_from_sRGB(src.b);
+ dst.a = src.a;
+ }
+
+ static void convert(rgba8T<sRGB>& dst, const rgba8T<linear>& src)
+ {
+ dst.r = sRGB_conv<value_type>::rgb_to_sRGB(src.r);
+ dst.g = sRGB_conv<value_type>::rgb_to_sRGB(src.g);
+ dst.b = sRGB_conv<value_type>::rgb_to_sRGB(src.b);
+ dst.a = src.a;
+ }
+
+ static void convert(rgba8T<linear>& dst, const rgba& src)
+ {
+ dst.r = value_type(uround(src.r * base_mask));
+ dst.g = value_type(uround(src.g * base_mask));
+ dst.b = value_type(uround(src.b * base_mask));
+ dst.a = value_type(uround(src.a * base_mask));
+ }
+
+ static void convert(rgba8T<sRGB>& dst, const rgba& src)
+ {
+ // Use the "float" table.
+ dst.r = sRGB_conv<float>::rgb_to_sRGB(float(src.r));
+ dst.g = sRGB_conv<float>::rgb_to_sRGB(float(src.g));
+ dst.b = sRGB_conv<float>::rgb_to_sRGB(float(src.b));
+ dst.a = sRGB_conv<float>::alpha_to_sRGB(float(src.a));
+ }
+
+ static void convert(rgba& dst, const rgba8T<linear>& src)
+ {
+ dst.r = src.r / 255.0;
+ dst.g = src.g / 255.0;
+ dst.b = src.b / 255.0;
+ dst.a = src.a / 255.0;
+ }
+
+ static void convert(rgba& dst, const rgba8T<sRGB>& src)
+ {
+ // Use the "float" table.
+ dst.r = sRGB_conv<float>::rgb_from_sRGB(src.r);
+ dst.g = sRGB_conv<float>::rgb_from_sRGB(src.g);
+ dst.b = sRGB_conv<float>::rgb_from_sRGB(src.b);
+ dst.a = sRGB_conv<float>::alpha_from_sRGB(src.a);
+ }
+
//--------------------------------------------------------------------
- rgba8() {}
+ rgba8T() {}
//--------------------------------------------------------------------
- rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) :
+ rgba8T(unsigned r_, unsigned g_, unsigned b_, unsigned a_ = base_mask) :
r(value_type(r_)),
g(value_type(g_)),
b(value_type(b_)),
a(value_type(a_)) {}
//--------------------------------------------------------------------
- rgba8(const rgba& c, double a_) :
- r((value_type)uround(c.r * double(base_mask))),
- g((value_type)uround(c.g * double(base_mask))),
- b((value_type)uround(c.b * double(base_mask))),
- a((value_type)uround(a_ * double(base_mask))) {}
+ rgba8T(const rgba& c)
+ {
+ convert(*this, c);
+ }
//--------------------------------------------------------------------
- rgba8(const self_type& c, unsigned a_) :
+ rgba8T(const self_type& c, unsigned a_) :
r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
//--------------------------------------------------------------------
- rgba8(const rgba& c) :
- r((value_type)uround(c.r * double(base_mask))),
- g((value_type)uround(c.g * double(base_mask))),
- b((value_type)uround(c.b * double(base_mask))),
- a((value_type)uround(c.a * double(base_mask))) {}
+ template<class T>
+ rgba8T(const rgba8T<T>& c)
+ {
+ convert(*this, c);
+ }
+
+ //--------------------------------------------------------------------
+ operator rgba() const
+ {
+ rgba c;
+ convert(c, *this);
+ return c;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE double to_double(value_type a)
+ {
+ return double(a) / base_mask;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type from_double(double a)
+ {
+ return value_type(uround(a * base_mask));
+ }
//--------------------------------------------------------------------
- void clear()
+ static AGG_INLINE value_type empty_value()
+ {
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type full_value()
+ {
+ return base_mask;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE bool is_transparent() const
+ {
+ return a == 0;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE bool is_opaque() const
+ {
+ return a == base_mask;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type invert(value_type x)
+ {
+ return base_mask - x;
+ }
+
+ //--------------------------------------------------------------------
+ // Fixed-point multiply, exact over int8u.
+ static AGG_INLINE value_type multiply(value_type a, value_type b)
+ {
+ calc_type t = a * b + base_MSB;
+ return value_type(((t >> base_shift) + t) >> base_shift);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type demultiply(value_type a, value_type b)
+ {
+ if (a * b == 0)
+ {
+ return 0;
+ }
+ else if (a >= b)
+ {
+ return base_mask;
+ }
+ else return value_type((a * base_mask + (b >> 1)) / b);
+ }
+
+ //--------------------------------------------------------------------
+ template<typename T>
+ static AGG_INLINE T downscale(T a)
+ {
+ return a >> base_shift;
+ }
+
+ //--------------------------------------------------------------------
+ template<typename T>
+ static AGG_INLINE T downshift(T a, unsigned n)
+ {
+ return a >> n;
+ }
+
+ //--------------------------------------------------------------------
+ // Fixed-point multiply, exact over int8u.
+ // Specifically for multiplying a color component by a cover.
+ static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
+ {
+ return multiply(a, b);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
+ {
+ return multiply(b, a);
+ }
+
+ //--------------------------------------------------------------------
+ // Interpolate p to q by a, assuming q is premultiplied by a.
+ static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
+ {
+ return p + q - multiply(p, a);
+ }
+
+ //--------------------------------------------------------------------
+ // Interpolate p to q by a.
+ static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
+ {
+ int t = (q - p) * a + base_MSB - (p > q);
+ return value_type(p + (((t >> base_shift) + t) >> base_shift));
+ }
+
+ //--------------------------------------------------------------------
+ self_type& clear()
{
r = g = b = a = 0;
+ return *this;
}
//--------------------------------------------------------------------
- const self_type& transparent()
+ self_type& transparent()
{
a = 0;
return *this;
}
//--------------------------------------------------------------------
- const self_type& opacity(double a_)
+ self_type& opacity(double a_)
{
- if(a_ < 0.0) a_ = 0.0;
- if(a_ > 1.0) a_ = 1.0;
- a = (value_type)uround(a_ * double(base_mask));
+ if (a_ < 0) a = 0;
+ else if (a_ > 1) a = 1;
+ else a = (value_type)uround(a_ * double(base_mask));
return *this;
}
@@ -309,54 +485,66 @@ namespace agg
}
//--------------------------------------------------------------------
- AGG_INLINE const self_type& premultiply()
+ AGG_INLINE self_type& premultiply()
{
- if(a == base_mask) return *this;
- if(a == 0)
+ if (a != base_mask)
{
- r = g = b = 0;
- return *this;
+ if (a == 0)
+ {
+ r = g = b = 0;
+ }
+ else
+ {
+ r = multiply(r, a);
+ g = multiply(g, a);
+ b = multiply(b, a);
+ }
}
- r = value_type((calc_type(r) * a) >> base_shift);
- g = value_type((calc_type(g) * a) >> base_shift);
- b = value_type((calc_type(b) * a) >> base_shift);
return *this;
}
//--------------------------------------------------------------------
- AGG_INLINE const self_type& premultiply(unsigned a_)
+ AGG_INLINE self_type& premultiply(unsigned a_)
{
- if(a == base_mask && a_ >= base_mask) return *this;
- if(a == 0 || a_ == 0)
+ if (a != base_mask || a_ < base_mask)
{
- r = g = b = a = 0;
- return *this;
+ if (a == 0 || a_ == 0)
+ {
+ r = g = b = a = 0;
+ }
+ else
+ {
+ calc_type r_ = (calc_type(r) * a_) / a;
+ calc_type g_ = (calc_type(g) * a_) / a;
+ calc_type b_ = (calc_type(b) * a_) / a;
+ r = value_type((r_ > a_) ? a_ : r_);
+ g = value_type((g_ > a_) ? a_ : g_);
+ b = value_type((b_ > a_) ? a_ : b_);
+ a = value_type(a_);
+ }
}
- calc_type r_ = (calc_type(r) * a_) / a;
- calc_type g_ = (calc_type(g) * a_) / a;
- calc_type b_ = (calc_type(b) * a_) / a;
- r = value_type((r_ > a_) ? a_ : r_);
- g = value_type((g_ > a_) ? a_ : g_);
- b = value_type((b_ > a_) ? a_ : b_);
- a = value_type(a_);
return *this;
}
//--------------------------------------------------------------------
- AGG_INLINE const self_type& demultiply()
+ AGG_INLINE self_type& demultiply()
{
- if(a == base_mask) return *this;
- if(a == 0)
+ if (a < base_mask)
{
- r = g = b = 0;
- return *this;
+ if (a == 0)
+ {
+ r = g = b = 0;
+ }
+ else
+ {
+ calc_type r_ = (calc_type(r) * base_mask) / a;
+ calc_type g_ = (calc_type(g) * base_mask) / a;
+ calc_type b_ = (calc_type(b) * base_mask) / a;
+ r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
+ g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
+ b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
+ }
}
- calc_type r_ = (calc_type(r) * base_mask) / a;
- calc_type g_ = (calc_type(g) * base_mask) / a;
- calc_type b_ = (calc_type(b) * base_mask) / a;
- r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
- g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
- b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
return *this;
}
@@ -364,11 +552,11 @@ namespace agg
AGG_INLINE self_type gradient(const self_type& c, double k) const
{
self_type ret;
- calc_type ik = uround(k * base_scale);
- ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift));
- ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift));
- ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift));
- ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
+ calc_type ik = uround(k * base_mask);
+ ret.r = lerp(r, c.r, ik);
+ ret.g = lerp(g, c.g, ik);
+ ret.b = lerp(b, c.b, ik);
+ ret.a = lerp(a, c.a, ik);
return ret;
}
@@ -376,31 +564,32 @@ namespace agg
AGG_INLINE void add(const self_type& c, unsigned cover)
{
calc_type cr, cg, cb, ca;
- if(cover == cover_mask)
+ if (cover == cover_mask)
{
- if(c.a == base_mask)
+ if (c.a == base_mask)
{
*this = c;
+ return;
}
else
{
- cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
- cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
- cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
- ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ cr = r + c.r;
+ cg = g + c.g;
+ cb = b + c.b;
+ ca = a + c.a;
}
}
else
{
- cr = r + ((c.r * cover + cover_mask/2) >> cover_shift);
- cg = g + ((c.g * cover + cover_mask/2) >> cover_shift);
- cb = b + ((c.b * cover + cover_mask/2) >> cover_shift);
- ca = a + ((c.a * cover + cover_mask/2) >> cover_shift);
- r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
- g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
- b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
- a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ cr = r + mult_cover(c.r, cover);
+ cg = g + mult_cover(c.g, cover);
+ cb = b + mult_cover(c.b, cover);
+ ca = a + mult_cover(c.a, cover);
}
+ r = (value_type)((cr > calc_type(base_mask)) ? calc_type(base_mask) : cr);
+ g = (value_type)((cg > calc_type(base_mask)) ? calc_type(base_mask) : cg);
+ b = (value_type)((cb > calc_type(base_mask)) ? calc_type(base_mask) : cb);
+ a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca);
}
//--------------------------------------------------------------------
@@ -431,29 +620,8 @@ namespace agg
}
};
-
- //-------------------------------------------------------------rgba8_pre
- inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b,
- unsigned a = rgba8::base_mask)
- {
- return rgba8(r,g,b,a).premultiply();
- }
- inline rgba8 rgba8_pre(const rgba8& c)
- {
- return rgba8(c).premultiply();
- }
- inline rgba8 rgba8_pre(const rgba8& c, unsigned a)
- {
- return rgba8(c,a).premultiply();
- }
- inline rgba8 rgba8_pre(const rgba& c)
- {
- return rgba8(c).premultiply();
- }
- inline rgba8 rgba8_pre(const rgba& c, double a)
- {
- return rgba8(c,a).premultiply();
- }
+ typedef rgba8T<linear> rgba8;
+ typedef rgba8T<sRGB> srgba8;
//-------------------------------------------------------------rgb8_packed
@@ -490,8 +658,6 @@ namespace agg
-
-
//==================================================================rgba16
struct rgba16
{
@@ -502,7 +668,8 @@ namespace agg
{
base_shift = 16,
base_scale = 1 << base_shift,
- base_mask = base_scale - 1
+ base_mask = base_scale - 1,
+ base_MSB = 1 << (base_shift - 1)
};
typedef rgba16 self_type;
@@ -533,13 +700,6 @@ namespace agg
a((value_type)uround(c.a * double(base_mask))) {}
//--------------------------------------------------------------------
- rgba16(const rgba& c, double a_) :
- r((value_type)uround(c.r * double(base_mask))),
- g((value_type)uround(c.g * double(base_mask))),
- b((value_type)uround(c.b * double(base_mask))),
- a((value_type)uround(a_ * double(base_mask))) {}
-
- //--------------------------------------------------------------------
rgba16(const rgba8& c) :
r(value_type((value_type(c.r) << 8) | c.r)),
g(value_type((value_type(c.g) << 8) | c.g)),
@@ -547,31 +707,166 @@ namespace agg
a(value_type((value_type(c.a) << 8) | c.a)) {}
//--------------------------------------------------------------------
- rgba16(const rgba8& c, unsigned a_) :
- r(value_type((value_type(c.r) << 8) | c.r)),
- g(value_type((value_type(c.g) << 8) | c.g)),
- b(value_type((value_type(c.b) << 8) | c.b)),
- a(value_type(( a_ << 8) | c.a)) {}
+ rgba16(const srgba8& c) :
+ r(sRGB_conv<value_type>::rgb_from_sRGB(c.r)),
+ g(sRGB_conv<value_type>::rgb_from_sRGB(c.g)),
+ b(sRGB_conv<value_type>::rgb_from_sRGB(c.b)),
+ a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {}
+
+ //--------------------------------------------------------------------
+ operator rgba() const
+ {
+ return rgba(
+ r / 65535.0,
+ g / 65535.0,
+ b / 65535.0,
+ a / 65535.0);
+ }
+
+ //--------------------------------------------------------------------
+ operator rgba8() const
+ {
+ return rgba8(r >> 8, g >> 8, b >> 8, a >> 8);
+ }
//--------------------------------------------------------------------
- void clear()
+ operator srgba8() const
+ {
+ // Return (non-premultiplied) sRGB values.
+ return srgba8(
+ sRGB_conv<value_type>::rgb_to_sRGB(r),
+ sRGB_conv<value_type>::rgb_to_sRGB(g),
+ sRGB_conv<value_type>::rgb_to_sRGB(b),
+ sRGB_conv<value_type>::alpha_to_sRGB(a));
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE double to_double(value_type a)
+ {
+ return double(a) / base_mask;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type from_double(double a)
+ {
+ return value_type(uround(a * base_mask));
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type empty_value()
+ {
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type full_value()
+ {
+ return base_mask;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE bool is_transparent() const
+ {
+ return a == 0;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE bool is_opaque() const
+ {
+ return a == base_mask;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type invert(value_type x)
+ {
+ return base_mask - x;
+ }
+
+ //--------------------------------------------------------------------
+ // Fixed-point multiply, exact over int16u.
+ static AGG_INLINE value_type multiply(value_type a, value_type b)
+ {
+ calc_type t = a * b + base_MSB;
+ return value_type(((t >> base_shift) + t) >> base_shift);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type demultiply(value_type a, value_type b)
+ {
+ if (a * b == 0)
+ {
+ return 0;
+ }
+ else if (a >= b)
+ {
+ return base_mask;
+ }
+ else return value_type((a * base_mask + (b >> 1)) / b);
+ }
+
+ //--------------------------------------------------------------------
+ template<typename T>
+ static AGG_INLINE T downscale(T a)
+ {
+ return a >> base_shift;
+ }
+
+ //--------------------------------------------------------------------
+ template<typename T>
+ static AGG_INLINE T downshift(T a, unsigned n)
+ {
+ return a >> n;
+ }
+
+ //--------------------------------------------------------------------
+ // Fixed-point multiply, almost exact over int16u.
+ // Specifically for multiplying a color component by a cover.
+ static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
+ {
+ return multiply(a, (b << 8) | b);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
+ {
+ return multiply((a << 8) | a, b) >> 8;
+ }
+
+ //--------------------------------------------------------------------
+ // Interpolate p to q by a, assuming q is premultiplied by a.
+ static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
+ {
+ return p + q - multiply(p, a);
+ }
+
+ //--------------------------------------------------------------------
+ // Interpolate p to q by a.
+ static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
+ {
+ int t = (q - p) * a + base_MSB - (p > q);
+ return value_type(p + (((t >> base_shift) + t) >> base_shift));
+ }
+
+ //--------------------------------------------------------------------
+ self_type& clear()
{
r = g = b = a = 0;
+ return *this;
}
//--------------------------------------------------------------------
- const self_type& transparent()
+ self_type& transparent()
{
a = 0;
return *this;
}
//--------------------------------------------------------------------
- AGG_INLINE const self_type& opacity(double a_)
+ AGG_INLINE self_type& opacity(double a_)
{
- if(a_ < 0.0) a_ = 0.0;
- if(a_ > 1.0) a_ = 1.0;
- a = (value_type)uround(a_ * double(base_mask));
+ if (a_ < 0) a = 0;
+ if (a_ > 1) a = 1;
+ a = value_type(uround(a_ * double(base_mask)));
return *this;
}
@@ -582,54 +877,66 @@ namespace agg
}
//--------------------------------------------------------------------
- AGG_INLINE const self_type& premultiply()
+ AGG_INLINE self_type& premultiply()
{
- if(a == base_mask) return *this;
- if(a == 0)
+ if (a != base_mask)
{
- r = g = b = 0;
- return *this;
+ if (a == 0)
+ {
+ r = g = b = 0;
+ }
+ else
+ {
+ r = multiply(r, a);
+ g = multiply(g, a);
+ b = multiply(b, a);
+ }
}
- r = value_type((calc_type(r) * a) >> base_shift);
- g = value_type((calc_type(g) * a) >> base_shift);
- b = value_type((calc_type(b) * a) >> base_shift);
return *this;
}
//--------------------------------------------------------------------
- AGG_INLINE const self_type& premultiply(unsigned a_)
+ AGG_INLINE self_type& premultiply(unsigned a_)
{
- if(a == base_mask && a_ >= base_mask) return *this;
- if(a == 0 || a_ == 0)
+ if (a < base_mask || a_ < base_mask)
{
- r = g = b = a = 0;
- return *this;
+ if (a == 0 || a_ == 0)
+ {
+ r = g = b = a = 0;
+ }
+ else
+ {
+ calc_type r_ = (calc_type(r) * a_) / a;
+ calc_type g_ = (calc_type(g) * a_) / a;
+ calc_type b_ = (calc_type(b) * a_) / a;
+ r = value_type((r_ > a_) ? a_ : r_);
+ g = value_type((g_ > a_) ? a_ : g_);
+ b = value_type((b_ > a_) ? a_ : b_);
+ a = value_type(a_);
+ }
}
- calc_type r_ = (calc_type(r) * a_) / a;
- calc_type g_ = (calc_type(g) * a_) / a;
- calc_type b_ = (calc_type(b) * a_) / a;
- r = value_type((r_ > a_) ? a_ : r_);
- g = value_type((g_ > a_) ? a_ : g_);
- b = value_type((b_ > a_) ? a_ : b_);
- a = value_type(a_);
return *this;
}
//--------------------------------------------------------------------
- AGG_INLINE const self_type& demultiply()
+ AGG_INLINE self_type& demultiply()
{
- if(a == base_mask) return *this;
- if(a == 0)
+ if (a < base_mask)
{
- r = g = b = 0;
- return *this;
+ if (a == 0)
+ {
+ r = g = b = 0;
+ }
+ else
+ {
+ calc_type r_ = (calc_type(r) * base_mask) / a;
+ calc_type g_ = (calc_type(g) * base_mask) / a;
+ calc_type b_ = (calc_type(b) * base_mask) / a;
+ r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
+ g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
+ b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
+ }
}
- calc_type r_ = (calc_type(r) * base_mask) / a;
- calc_type g_ = (calc_type(g) * base_mask) / a;
- calc_type b_ = (calc_type(b) * base_mask) / a;
- r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
- g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
- b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
return *this;
}
@@ -637,11 +944,11 @@ namespace agg
AGG_INLINE self_type gradient(const self_type& c, double k) const
{
self_type ret;
- calc_type ik = uround(k * base_scale);
- ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift));
- ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift));
- ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift));
- ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
+ calc_type ik = uround(k * base_mask);
+ ret.r = lerp(r, c.r, ik);
+ ret.g = lerp(g, c.g, ik);
+ ret.b = lerp(b, c.b, ik);
+ ret.a = lerp(a, c.a, ik);
return ret;
}
@@ -649,31 +956,32 @@ namespace agg
AGG_INLINE void add(const self_type& c, unsigned cover)
{
calc_type cr, cg, cb, ca;
- if(cover == cover_mask)
+ if (cover == cover_mask)
{
- if(c.a == base_mask)
+ if (c.a == base_mask)
{
*this = c;
+ return;
}
else
{
- cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
- cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
- cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
- ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ cr = r + c.r;
+ cg = g + c.g;
+ cb = b + c.b;
+ ca = a + c.a;
}
}
else
{
- cr = r + ((c.r * cover + cover_mask) >> cover_shift);
- cg = g + ((c.g * cover + cover_mask) >> cover_shift);
- cb = b + ((c.b * cover + cover_mask) >> cover_shift);
- ca = a + ((c.a * cover + cover_mask) >> cover_shift);
- r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr;
- g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg;
- b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb;
- a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
+ cr = r + mult_cover(c.r, cover);
+ cg = g + mult_cover(c.g, cover);
+ cb = b + mult_cover(c.b, cover);
+ ca = a + mult_cover(c.a, cover);
}
+ r = (value_type)((cr > calc_type(base_mask)) ? calc_type(base_mask) : cr);
+ g = (value_type)((cg > calc_type(base_mask)) ? calc_type(base_mask) : cg);
+ b = (value_type)((cb > calc_type(base_mask)) ? calc_type(base_mask) : cb);
+ a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca);
}
//--------------------------------------------------------------------
@@ -705,35 +1013,6 @@ namespace agg
};
-
- //--------------------------------------------------------------rgba16_pre
- inline rgba16 rgba16_pre(unsigned r, unsigned g, unsigned b,
- unsigned a = rgba16::base_mask)
- {
- return rgba16(r,g,b,a).premultiply();
- }
- inline rgba16 rgba16_pre(const rgba16& c, unsigned a)
- {
- return rgba16(c,a).premultiply();
- }
- inline rgba16 rgba16_pre(const rgba& c)
- {
- return rgba16(c).premultiply();
- }
- inline rgba16 rgba16_pre(const rgba& c, double a)
- {
- return rgba16(c,a).premultiply();
- }
- inline rgba16 rgba16_pre(const rgba8& c)
- {
- return rgba16(c).premultiply();
- }
- inline rgba16 rgba16_pre(const rgba8& c, unsigned a)
- {
- return rgba16(c,a).premultiply();
- }
-
-
//------------------------------------------------------rgba16_gamma_dir
template<class GammaLUT>
rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma)
@@ -748,7 +1027,325 @@ namespace agg
return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
}
+ //====================================================================rgba32
+ struct rgba32
+ {
+ typedef float value_type;
+ typedef double calc_type;
+ typedef double long_type;
+ typedef rgba32 self_type;
+
+ value_type r;
+ value_type g;
+ value_type b;
+ value_type a;
+
+ //--------------------------------------------------------------------
+ rgba32() {}
+
+ //--------------------------------------------------------------------
+ rgba32(value_type r_, value_type g_, value_type b_, value_type a_= 1) :
+ r(r_), g(g_), b(b_), a(a_) {}
+
+ //--------------------------------------------------------------------
+ rgba32(const self_type& c, float a_) :
+ r(c.r), g(c.g), b(c.b), a(a_) {}
+
+ //--------------------------------------------------------------------
+ rgba32(const rgba& c) :
+ r(value_type(c.r)), g(value_type(c.g)), b(value_type(c.b)), a(value_type(c.a)) {}
+
+ //--------------------------------------------------------------------
+ rgba32(const rgba8& c) :
+ r(value_type(c.r / 255.0)),
+ g(value_type(c.g / 255.0)),
+ b(value_type(c.b / 255.0)),
+ a(value_type(c.a / 255.0)) {}
+
+ //--------------------------------------------------------------------
+ rgba32(const srgba8& c) :
+ r(sRGB_conv<value_type>::rgb_from_sRGB(c.r)),
+ g(sRGB_conv<value_type>::rgb_from_sRGB(c.g)),
+ b(sRGB_conv<value_type>::rgb_from_sRGB(c.b)),
+ a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {}
+
+ //--------------------------------------------------------------------
+ rgba32(const rgba16& c) :
+ r(value_type(c.r / 65535.0)),
+ g(value_type(c.g / 65535.0)),
+ b(value_type(c.b / 65535.0)),
+ a(value_type(c.a / 65535.0)) {}
+
+ //--------------------------------------------------------------------
+ operator rgba() const
+ {
+ return rgba(r, g, b, a);
+ }
+
+ //--------------------------------------------------------------------
+ operator rgba8() const
+ {
+ return rgba8(
+ uround(r * 255.0),
+ uround(g * 255.0),
+ uround(b * 255.0),
+ uround(a * 255.0));
+ }
+
+ //--------------------------------------------------------------------
+ operator srgba8() const
+ {
+ return srgba8(
+ sRGB_conv<value_type>::rgb_to_sRGB(r),
+ sRGB_conv<value_type>::rgb_to_sRGB(g),
+ sRGB_conv<value_type>::rgb_to_sRGB(b),
+ sRGB_conv<value_type>::alpha_to_sRGB(a));
+ }
+
+ //--------------------------------------------------------------------
+ operator rgba16() const
+ {
+ return rgba8(
+ uround(r * 65535.0),
+ uround(g * 65535.0),
+ uround(b * 65535.0),
+ uround(a * 65535.0));
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE double to_double(value_type a)
+ {
+ return a;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type from_double(double a)
+ {
+ return value_type(a);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type empty_value()
+ {
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type full_value()
+ {
+ return 1;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE bool is_transparent() const
+ {
+ return a <= 0;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE bool is_opaque() const
+ {
+ return a >= 1;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type invert(value_type x)
+ {
+ return 1 - x;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type multiply(value_type a, value_type b)
+ {
+ return value_type(a * b);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type demultiply(value_type a, value_type b)
+ {
+ return (b == 0) ? 0 : value_type(a / b);
+ }
+
+ //--------------------------------------------------------------------
+ template<typename T>
+ static AGG_INLINE T downscale(T a)
+ {
+ return a;
+ }
+
+ //--------------------------------------------------------------------
+ template<typename T>
+ static AGG_INLINE T downshift(T a, unsigned n)
+ {
+ return n > 0 ? a / (1 << n) : a;
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
+ {
+ return value_type(a * b / cover_mask);
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
+ {
+ return cover_type(uround(a * b));
+ }
+
+ //--------------------------------------------------------------------
+ // Interpolate p to q by a, assuming q is premultiplied by a.
+ static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
+ {
+ return (1 - a) * p + q; // more accurate than "p + q - p * a"
+ }
+
+ //--------------------------------------------------------------------
+ // Interpolate p to q by a.
+ static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
+ {
+ // The form "p + a * (q - p)" avoids a multiplication, but may produce an
+ // inaccurate result. For example, "p + (q - p)" may not be exactly equal
+ // to q. Therefore, stick to the basic expression, which at least produces
+ // the correct result at either extreme.
+ return (1 - a) * p + a * q;
+ }
+
+ //--------------------------------------------------------------------
+ self_type& clear()
+ {
+ r = g = b = a = 0;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ self_type& transparent()
+ {
+ a = 0;
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE self_type& opacity(double a_)
+ {
+ if (a_ < 0) a = 0;
+ else if (a_ > 1) a = 1;
+ else a = value_type(a_);
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ double opacity() const
+ {
+ return a;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE self_type& premultiply()
+ {
+ if (a < 1)
+ {
+ if (a <= 0)
+ {
+ r = g = b = 0;
+ }
+ else
+ {
+ r *= a;
+ g *= a;
+ b *= a;
+ }
+ }
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE self_type& demultiply()
+ {
+ if (a < 1)
+ {
+ if (a <= 0)
+ {
+ r = g = b = 0;
+ }
+ else
+ {
+ r /= a;
+ g /= a;
+ b /= a;
+ }
+ }
+ return *this;
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE self_type gradient(const self_type& c, double k) const
+ {
+ self_type ret;
+ ret.r = value_type(r + (c.r - r) * k);
+ ret.g = value_type(g + (c.g - g) * k);
+ ret.b = value_type(b + (c.b - b) * k);
+ ret.a = value_type(a + (c.a - a) * k);
+ return ret;
+ }
+ //--------------------------------------------------------------------
+ AGG_INLINE void add(const self_type& c, unsigned cover)
+ {
+ if (cover == cover_mask)
+ {
+ if (c.is_opaque())
+ {
+ *this = c;
+ return;
+ }
+ else
+ {
+ r += c.r;
+ g += c.g;
+ b += c.b;
+ a += c.a;
+ }
+ }
+ else
+ {
+ r += mult_cover(c.r, cover);
+ g += mult_cover(c.g, cover);
+ b += mult_cover(c.b, cover);
+ a += mult_cover(c.a, cover);
+ }
+ if (a > 1) a = 1;
+ if (r > a) r = a;
+ if (g > a) g = a;
+ if (b > a) b = a;
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLUT>
+ AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma)
+ {
+ r = gamma.dir(r);
+ g = gamma.dir(g);
+ b = gamma.dir(b);
+ }
+
+ //--------------------------------------------------------------------
+ template<class GammaLUT>
+ AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma)
+ {
+ r = gamma.inv(r);
+ g = gamma.inv(g);
+ b = gamma.inv(b);
+ }
+
+ //--------------------------------------------------------------------
+ static self_type no_color() { return self_type(0,0,0,0); }
+
+ //--------------------------------------------------------------------
+ static self_type from_wavelength(double wl, double gamma = 1)
+ {
+ return self_type(rgba::from_wavelength(wl, gamma));
+ }
+ };
}
diff --git a/src/agg/agg_config.h b/src/agg/agg_config.h
index 81c75f124..fa1dae2ba 100644
--- a/src/agg/agg_config.h
+++ b/src/agg/agg_config.h
@@ -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 simultaneouslyin your applications
+// You can still use both of them simultaneously in your applications
// This #define is used only for default rendering_buffer type,
// in short hand typedefs like pixfmt_rgba32.
diff --git a/src/agg/agg_conv_adaptor_vcgen.h b/src/agg/agg_conv_adaptor_vcgen.h
deleted file mode 100644
index 7bd9b0709..000000000
--- a/src/agg/agg_conv_adaptor_vcgen.h
+++ /dev/null
@@ -1,166 +0,0 @@
-//----------------------------------------------------------------------------
-// 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
diff --git a/src/agg/agg_conv_contour.h b/src/agg/agg_conv_contour.h
deleted file mode 100644
index dd29861b4..000000000
--- a/src/agg/agg_conv_contour.h
+++ /dev/null
@@ -1,71 +0,0 @@
-//----------------------------------------------------------------------------
-// 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
diff --git a/src/agg/agg_conv_curve.h b/src/agg/agg_conv_curve.h
deleted file mode 100644
index 1280903c0..000000000
--- a/src/agg/agg_conv_curve.h
+++ /dev/null
@@ -1,206 +0,0 @@
-//----------------------------------------------------------------------------
-// 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
diff --git a/src/agg/agg_conv_stroke.h b/src/agg/agg_conv_stroke.h
deleted file mode 100644
index 271310078..000000000
--- a/src/agg/agg_conv_stroke.h
+++ /dev/null
@@ -1,79 +0,0 @@
-//----------------------------------------------------------------------------
-// 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
diff --git a/src/agg/agg_conv_transform.h b/src/agg/agg_conv_transform.h
index 33c19b6e2..0c88a245b 100644
--- a/src/agg/agg_conv_transform.h
+++ b/src/agg/agg_conv_transform.h
@@ -1,27 +1,21 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// class conv_transform
+//
//----------------------------------------------------------------------------
-
#ifndef AGG_CONV_TRANSFORM_INCLUDED
#define AGG_CONV_TRANSFORM_INCLUDED
@@ -35,7 +29,7 @@ namespace agg
template<class VertexSource, class Transformer=trans_affine> class conv_transform
{
public:
- conv_transform(VertexSource& source, const Transformer& tr) :
+ conv_transform(VertexSource& source, Transformer& tr) :
m_source(&source), m_trans(&tr) {}
void attach(VertexSource& source) { m_source = &source; }
@@ -54,7 +48,7 @@ namespace agg
return cmd;
}
- void transformer(const Transformer& tr)
+ void transformer(Transformer& tr)
{
m_trans = &tr;
}
@@ -65,7 +59,7 @@ namespace agg
operator = (const conv_transform<VertexSource>&);
VertexSource* m_source;
- const Transformer* m_trans;
+ Transformer* m_trans;
};
diff --git a/src/agg/agg_curves.h b/src/agg/agg_curves.h
deleted file mode 100644
index 25845cab3..000000000
--- a/src/agg/agg_curves.h
+++ /dev/null
@@ -1,701 +0,0 @@
-//----------------------------------------------------------------------------
-// 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
diff --git a/src/agg/agg_gamma_functions.h b/src/agg/agg_gamma_functions.h
index fa38a45ad..5d720daa9 100644
--- a/src/agg/agg_gamma_functions.h
+++ b/src/agg/agg_gamma_functions.h
@@ -1,25 +1,16 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_GAMMA_FUNCTIONS_INCLUDED
@@ -124,6 +115,15 @@ 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
diff --git a/src/agg/agg_gamma_lut.h b/src/agg/agg_gamma_lut.h
index 5240da798..e30873632 100644
--- a/src/agg/agg_gamma_lut.h
+++ b/src/agg/agg_gamma_lut.h
@@ -1,25 +1,16 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_GAMMA_LUT_INCLUDED
@@ -27,6 +18,7 @@
#include <math.h>
#include "agg_basics.h"
+#include "agg_gamma_functions.h"
namespace agg
{
@@ -125,6 +117,184 @@ 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
diff --git a/src/agg/agg_math.h b/src/agg/agg_math.h
index 4e512facb..2ec49cf3f 100644
--- a/src/agg/agg_math.h
+++ b/src/agg/agg_math.h
@@ -1,25 +1,16 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
//----------------------------------------------------------------------------
// Bessel function (besj) was adapted for use in AGG library by Andy Wilk
// Contact: castor.vulgaris@gmail.com
diff --git a/src/agg/agg_math_stroke.h b/src/agg/agg_math_stroke.h
deleted file mode 100644
index ad09af27e..000000000
--- a/src/agg/agg_math_stroke.h
+++ /dev/null
@@ -1,531 +0,0 @@
-//----------------------------------------------------------------------------
-// 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
diff --git a/src/agg/agg_path_storage.h b/src/agg/agg_path_storage.h
index 7be7393c9..f55c89957 100644
--- a/src/agg/agg_path_storage.h
+++ b/src/agg/agg_path_storage.h
@@ -1,25 +1,16 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_PATH_STORAGE_INCLUDED
@@ -499,14 +490,14 @@ namespace agg
m_stop(false)
{}
- poly_container_reverse_adaptor(const Container& data, bool closed) :
+ poly_container_reverse_adaptor(Container& data, bool closed) :
m_container(&data),
m_index(-1),
m_closed(closed),
m_stop(false)
{}
- void init(const Container& data, bool closed)
+ void init(Container& data, bool closed)
{
m_container = &data;
m_index = m_container->size() - 1;
@@ -540,7 +531,7 @@ namespace agg
}
private:
- const Container* m_container;
+ Container* m_container;
int m_index;
bool m_closed;
bool m_stop;
@@ -844,6 +835,43 @@ 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);
diff --git a/src/agg/agg_pixfmt_base.h b/src/agg/agg_pixfmt_base.h
new file mode 100644
index 000000000..57ae19cfe
--- /dev/null
+++ b/src/agg/agg_pixfmt_base.h
@@ -0,0 +1,97 @@
+//----------------------------------------------------------------------------
+// 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
diff --git a/src/agg/agg_pixfmt_gray.h b/src/agg/agg_pixfmt_gray.h
index 8f3f4ec9d..d03dc8650 100644
--- a/src/agg/agg_pixfmt_gray.h
+++ b/src/agg/agg_pixfmt_gray.h
@@ -1,25 +1,16 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Adaptation for high precision colors has been sponsored by
@@ -34,8 +25,7 @@
#define AGG_PIXFMT_GRAY_INCLUDED
#include <string.h>
-#include "agg_basics.h"
-#include "agg_color_gray.h"
+#include "agg_pixfmt_base.h"
#include "agg_rendering_buffer.h"
namespace agg
@@ -47,12 +37,22 @@ namespace agg
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
- enum base_scale_e { base_shift = color_type::base_shift };
+ typedef typename color_type::long_type long_type;
+
+ // 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, unsigned cv,
- unsigned alpha, unsigned cover=0)
+ static AGG_INLINE void blend_pix(value_type* p,
+ value_type cv, value_type alpha, cover_type cover)
{
- *p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift);
+ 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);
}
};
@@ -63,20 +63,21 @@ namespace agg
typedef ColorT color_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
- enum base_scale_e { base_shift = color_type::base_shift };
+ typedef typename color_type::long_type long_type;
- static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
- unsigned alpha, unsigned cover)
+ // 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)
{
- alpha = color_type::base_mask - alpha;
- cover = (cover + 1) << (base_shift - 8);
- *p = (value_type)((*p * alpha + cv * cover) >> base_shift);
+ blend_pix(p, color_type::mult_cover(cv, cover), color_type::mult_cover(alpha, cover));
}
- static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
- unsigned alpha)
+ static AGG_INLINE void blend_pix(value_type* p,
+ value_type cv, value_type alpha)
{
- *p = (value_type)(((*p * (color_type::base_mask - alpha)) >> base_shift) + cv);
+ *p = color_type::prelerp(*p, cv, alpha);
}
};
@@ -121,10 +122,11 @@ 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;
@@ -132,54 +134,117 @@ 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 base_scale_e
- {
- 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
+ enum
+ {
+ 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);
+ }
};
private:
//--------------------------------------------------------------------
- static AGG_INLINE void copy_or_blend_pix(value_type* p,
- const color_type& c,
- unsigned cover)
+ AGG_INLINE void blend_pix(pixel_type* p,
+ value_type v, value_type a,
+ unsigned cover)
{
- if (c.a)
+ 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())
{
- calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
- if(alpha == base_mask)
+ if (c.is_opaque() && cover == cover_mask)
{
- *p = c.v;
+ p->set(c);
}
else
{
- Blender::blend_pix(p, c.v, alpha, cover);
+ blend_pix(p, c, cover);
}
}
}
-
- static AGG_INLINE void copy_or_blend_pix(value_type* p,
- const color_type& c)
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c)
{
- if (c.a)
+ if (!c.is_transparent())
{
- if(c.a == base_mask)
+ if (c.is_opaque())
{
- *p = c.v;
+ p->set(c);
}
else
{
- Blender::blend_pix(p, c.v, c.a);
+ blend_pix(p, c);
}
}
}
-
public:
//--------------------------------------------------------------------
explicit pixfmt_alpha_blend_gray(rbuf_type& rb) :
@@ -192,7 +257,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),
@@ -210,61 +275,98 @@ 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); }
- const int8u* pix_ptr(int x, int y) const
+ //--------------------------------------------------------------------
+ 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)
{
- return m_rbuf->row_ptr(y) + x * Step + Offset;
+ return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step + pix_offset));
}
- int8u* pix_ptr(int x, int y)
+ // 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* 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 m_rbuf->row_ptr(y) + x * Step + Offset;
+ return pix_value_ptr(p)->get();
}
//--------------------------------------------------------------------
AGG_INLINE static void make_pix(int8u* p, const color_type& c)
{
- *(value_type*)p = c.v;
+ ((pixel_type*)p)->set(c);
}
//--------------------------------------------------------------------
AGG_INLINE color_type pixel(int x, int y) const
{
- value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset;
- return color_type(*p);
+ if (const pixel_type* p = pix_value_ptr(x, y))
+ {
+ return p->get();
+ }
+ return color_type::no_color();
}
//--------------------------------------------------------------------
AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
{
- *((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v;
+ pix_value_ptr(x, y, 1)->set(c);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
{
- copy_or_blend_pix((value_type*)
- m_rbuf->row_ptr(x, y, 1) + x * Step + Offset,
- c,
- cover);
+ copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover);
}
-
//--------------------------------------------------------------------
AGG_INLINE void copy_hline(int x, int y,
unsigned len,
const color_type& c)
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
-
+ pixel_type* p = pix_value_ptr(x, y, len);
do
{
- *p = c.v;
- p += Step;
+ p->set(c);
+ p = p->next();
}
while(--len);
}
@@ -277,12 +379,9 @@ namespace agg
{
do
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
-
- *p = c.v;
+ pix_value_ptr(x, y++, 1)->set(c);
}
- while(--len);
+ while (--len);
}
@@ -292,29 +391,27 @@ namespace agg
const color_type& c,
int8u cover)
{
- if (c.a)
+ if (!c.is_transparent())
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
+ pixel_type* p = pix_value_ptr(x, y, len);
- calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
- if(alpha == base_mask)
+ if (c.is_opaque() && cover == cover_mask)
{
do
{
- *p = c.v;
- p += Step;
+ p->set(c);
+ p = p->next();
}
- while(--len);
+ while (--len);
}
else
{
do
{
- Blender::blend_pix(p, c.v, alpha, cover);
- p += Step;
+ blend_pix(p, c, cover);
+ p = p->next();
}
- while(--len);
+ while (--len);
}
}
}
@@ -326,31 +423,23 @@ namespace agg
const color_type& c,
int8u cover)
{
- if (c.a)
+ if (!c.is_transparent())
{
- value_type* p;
- calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
- if(alpha == base_mask)
+ if (c.is_opaque() && cover == cover_mask)
{
do
{
- p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
-
- *p = c.v;
+ pix_value_ptr(x, y++, 1)->set(c);
}
- while(--len);
+ while (--len);
}
else
{
do
{
- p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
-
- Blender::blend_pix(p, c.v, alpha, cover);
+ blend_pix(pix_value_ptr(x, y++, 1), c, cover);
}
- while(--len);
+ while (--len);
}
}
}
@@ -362,26 +451,24 @@ namespace agg
const color_type& c,
const int8u* covers)
{
- if (c.a)
+ if (!c.is_transparent())
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
+ pixel_type* p = pix_value_ptr(x, y, len);
do
{
- calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
- if(alpha == base_mask)
+ if (c.is_opaque() && *covers == cover_mask)
{
- *p = c.v;
+ p->set(c);
}
else
{
- Blender::blend_pix(p, c.v, alpha, *covers);
+ blend_pix(p, c, *covers);
}
- p += Step;
+ p = p->next();
++covers;
}
- while(--len);
+ while (--len);
}
}
@@ -392,26 +479,23 @@ namespace agg
const color_type& c,
const int8u* covers)
{
- if (c.a)
+ if (!c.is_transparent())
{
do
{
- calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
-
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
+ pixel_type* p = pix_value_ptr(x, y++, 1);
- if(alpha == base_mask)
+ if (c.is_opaque() && *covers == cover_mask)
{
- *p = c.v;
+ p->set(c);
}
else
{
- Blender::blend_pix(p, c.v, alpha, *covers);
+ blend_pix(p, c, *covers);
}
++covers;
}
- while(--len);
+ while (--len);
}
}
@@ -421,16 +505,14 @@ namespace agg
unsigned len,
const color_type* colors)
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
+ pixel_type* p = pix_value_ptr(x, y, len);
do
{
- *p = colors->v;
- p += Step;
- ++colors;
+ p->set(*colors++);
+ p = p->next();
}
- while(--len);
+ while (--len);
}
@@ -441,12 +523,9 @@ namespace agg
{
do
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
- *p = colors->v;
- ++colors;
+ pix_value_ptr(x, y++, 1)->set(*colors++);
}
- while(--len);
+ while (--len);
}
@@ -457,50 +536,40 @@ namespace agg
const int8u* covers,
int8u cover)
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
+ pixel_type* p = pix_value_ptr(x, y, len);
- if(covers)
+ if (covers)
{
do
{
copy_or_blend_pix(p, *colors++, *covers++);
- p += Step;
+ p = p->next();
}
- while(--len);
+ while (--len);
}
else
{
- if(cover == 255)
+ if (cover == cover_mask)
{
do
{
- if(colors->a == base_mask)
- {
- *p = colors->v;
- }
- else
- {
- copy_or_blend_pix(p, *colors);
- }
- p += Step;
- ++colors;
+ copy_or_blend_pix(p, *colors++);
+ p = p->next();
}
- while(--len);
+ while (--len);
}
else
{
do
{
copy_or_blend_pix(p, *colors++, cover);
- p += Step;
+ p = p->next();
}
- while(--len);
+ while (--len);
}
}
}
-
-
+
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y,
@@ -509,49 +578,31 @@ namespace agg
const int8u* covers,
int8u cover)
{
- value_type* p;
- if(covers)
+ if (covers)
{
do
{
- p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
-
- copy_or_blend_pix(p, *colors++, *covers++);
+ copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++);
}
- while(--len);
+ while (--len);
}
else
{
- if(cover == 255)
+ if (cover == cover_mask)
{
do
{
- 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;
+ copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++);
}
- while(--len);
+ while (--len);
}
else
{
do
{
- p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
-
- copy_or_blend_pix(p, *colors++, cover);
+ copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover);
}
- while(--len);
+ while (--len);
}
}
}
@@ -560,22 +611,19 @@ 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;
-
- value_type* p = (value_type*)
- m_rbuf->row_ptr(r.x1, y, len) + r.x1 * Step + Offset;
-
+ pixel_type* p = pix_value_ptr(r.x1, y, len);
do
{
- f(p);
- p += Step;
+ f(p->c);
+ p = p->next();
}
- while(--len);
+ while (--len);
}
}
}
@@ -599,8 +647,7 @@ namespace agg
int xsrc, int ysrc,
unsigned len)
{
- const int8u* p = from.row_ptr(ysrc);
- if(p)
+ if (const int8u* p = from.row_ptr(ysrc))
{
memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
p + xsrc * pix_width,
@@ -609,6 +656,7 @@ 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,
@@ -617,25 +665,26 @@ namespace agg
unsigned len,
int8u cover)
{
- typedef typename SrcPixelFormatRenderer::value_type src_value_type;
- const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
- if(psrc)
+ 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))
{
- value_type* pdst =
- (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
+ pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
+
do
{
- copy_or_blend_pix(pdst,
- color,
- (*psrc * cover + base_mask) >> base_shift);
- ++psrc;
- ++pdst;
+ copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0]));
+ psrc = psrc->next();
+ pdst = pdst->next();
}
- 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,
@@ -644,19 +693,19 @@ namespace agg
unsigned len,
int8u cover)
{
- typedef typename SrcPixelFormatRenderer::value_type src_value_type;
- const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
- if(psrc)
+ typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
+
+ if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
{
- value_type* pdst =
- (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
+ pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
+
do
{
- copy_or_blend_pix(pdst, color_lut[*psrc], cover);
- ++psrc;
- ++pdst;
+ copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover);
+ psrc = psrc->next();
+ pdst = pdst->next();
}
- while(--len);
+ while (--len);
}
}
@@ -664,15 +713,25 @@ namespace agg
rbuf_type* m_rbuf;
};
- typedef blender_gray<gray8> blender_gray8;
- typedef blender_gray_pre<gray8> blender_gray8_pre;
- typedef blender_gray<gray16> blender_gray16;
+ 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_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, 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
+ 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;
}
#endif
diff --git a/src/agg/agg_pixfmt_rgb.h b/src/agg/agg_pixfmt_rgb.h
index 48947178b..6fa8772ce 100644
--- a/src/agg/agg_pixfmt_rgb.h
+++ b/src/agg/agg_pixfmt_rgb.h
@@ -1,25 +1,16 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Adaptation for high precision colors has been sponsored by
@@ -34,8 +25,7 @@
#define AGG_PIXFMT_RGB_INCLUDED
#include <string.h>
-#include "agg_basics.h"
-#include "agg_color_rgba.h"
+#include "agg_pixfmt_base.h"
#include "agg_rendering_buffer.h"
namespace agg
@@ -83,66 +73,73 @@ namespace agg
//=========================================================blender_rgb
- template<class ColorT, class Order> struct blender_rgb
+ template<class ColorT, class Order>
+ struct blender_rgb
{
typedef ColorT color_type;
typedef Order order_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
- enum base_scale_e { base_shift = color_type::base_shift };
+ typedef typename color_type::long_type long_type;
+
+ // 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,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned alpha,
- unsigned cover=0)
+ value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
+ {
+ blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover));
+ }
+
+ //--------------------------------------------------------------------
+ static AGG_INLINE void blend_pix(value_type* p,
+ value_type cr, value_type cg, value_type cb, value_type alpha)
{
- p[Order::R] += (value_type)(((cr - p[Order::R]) * alpha) >> base_shift);
- p[Order::G] += (value_type)(((cg - p[Order::G]) * alpha) >> base_shift);
- p[Order::B] += (value_type)(((cb - p[Order::B]) * alpha) >> base_shift);
+ p[Order::R] = color_type::lerp(p[Order::R], cr, alpha);
+ p[Order::G] = color_type::lerp(p[Order::G], cg, alpha);
+ p[Order::B] = color_type::lerp(p[Order::B], cb, alpha);
}
};
-
//======================================================blender_rgb_pre
- template<class ColorT, class Order> struct blender_rgb_pre
+ template<class ColorT, class Order>
+ struct blender_rgb_pre
{
typedef ColorT color_type;
typedef Order order_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
- enum base_scale_e { base_shift = color_type::base_shift };
+ typedef typename color_type::long_type long_type;
+
+ // Blend pixels using the premultiplied form of Alvy-Ray Smith's
+ // compositing function.
//--------------------------------------------------------------------
static AGG_INLINE void blend_pix(value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned alpha,
- unsigned cover)
+ value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
{
- alpha = color_type::base_mask - alpha;
- cover = (cover + 1) << (base_shift - 8);
- p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift);
- p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift);
- p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift);
+ blend_pix(p,
+ color_type::mult_cover(cr, cover),
+ color_type::mult_cover(cg, cover),
+ color_type::mult_cover(cb, cover),
+ color_type::mult_cover(alpha, cover));
}
//--------------------------------------------------------------------
static AGG_INLINE void blend_pix(value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned alpha)
+ value_type cr, value_type cg, value_type cb, value_type alpha)
{
- alpha = color_type::base_mask - alpha;
- p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr);
- p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg);
- p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb);
+ p[Order::R] = color_type::prelerp(p[Order::R], cr, alpha);
+ p[Order::G] = color_type::prelerp(p[Order::G], cg, alpha);
+ p[Order::B] = color_type::prelerp(p[Order::B], cb, alpha);
}
-
};
-
-
//===================================================blender_rgb_gamma
- template<class ColorT, class Order, class Gamma> class blender_rgb_gamma
+ template<class ColorT, class Order, class Gamma>
+ class blender_rgb_gamma : public blender_base<ColorT, Order>
{
public:
typedef ColorT color_type;
@@ -150,7 +147,7 @@ namespace agg
typedef Gamma gamma_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
- enum base_scale_e { base_shift = color_type::base_shift };
+ typedef typename color_type::long_type long_type;
//--------------------------------------------------------------------
blender_rgb_gamma() : m_gamma(0) {}
@@ -158,29 +155,34 @@ namespace agg
//--------------------------------------------------------------------
AGG_INLINE void blend_pix(value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned alpha,
- unsigned cover=0)
+ value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
+ {
+ blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover));
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_pix(value_type* p,
+ value_type cr, value_type cg, value_type cb, value_type alpha)
{
calc_type r = m_gamma->dir(p[Order::R]);
calc_type g = m_gamma->dir(p[Order::G]);
calc_type b = m_gamma->dir(p[Order::B]);
- p[Order::R] = m_gamma->inv((((m_gamma->dir(cr) - r) * alpha) >> base_shift) + r);
- p[Order::G] = m_gamma->inv((((m_gamma->dir(cg) - g) * alpha) >> base_shift) + g);
- p[Order::B] = m_gamma->inv((((m_gamma->dir(cb) - b) * alpha) >> base_shift) + b);
+ p[Order::R] = m_gamma->inv(color_type::downscale((m_gamma->dir(cr) - r) * alpha) + r);
+ p[Order::G] = m_gamma->inv(color_type::downscale((m_gamma->dir(cg) - g) * alpha) + g);
+ p[Order::B] = m_gamma->inv(color_type::downscale((m_gamma->dir(cb) - b) * alpha) + b);
}
-
+
private:
const gamma_type* m_gamma;
};
-
-
//==================================================pixfmt_alpha_blend_rgb
- template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb
+ template<class Blender, class RenBuf, unsigned Step, unsigned Offset = 0>
+ class pixfmt_alpha_blend_rgb
{
public:
+ typedef pixfmt_rgb_tag pixfmt_category;
typedef RenBuf rbuf_type;
typedef Blender blender_type;
typedef typename rbuf_type::row_data row_data;
@@ -188,56 +190,125 @@ namespace agg
typedef typename blender_type::order_type order_type;
typedef typename color_type::value_type value_type;
typedef typename color_type::calc_type calc_type;
- enum base_scale_e
+ enum
+ {
+ num_components = 3,
+ pix_step = Step,
+ pix_offset = Offset,
+ pix_width = sizeof(value_type) * pix_step
+ };
+ struct pixel_type
{
- base_shift = color_type::base_shift,
- base_scale = color_type::base_scale,
- base_mask = color_type::base_mask,
- pix_width = sizeof(value_type) * 3
+ value_type c[num_components];
+
+ void set(value_type r, value_type g, value_type b)
+ {
+ c[order_type::R] = r;
+ c[order_type::G] = g;
+ c[order_type::B] = b;
+ }
+
+ void set(const color_type& color)
+ {
+ set(color.r, color.g, color.b);
+ }
+
+ void get(value_type& r, value_type& g, value_type& b) const
+ {
+ r = c[order_type::R];
+ g = c[order_type::G];
+ b = c[order_type::B];
+ }
+
+ color_type get() const
+ {
+ return color_type(
+ c[order_type::R],
+ c[order_type::G],
+ c[order_type::B]);
+ }
+
+ 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);
+ }
};
private:
//--------------------------------------------------------------------
- AGG_INLINE void copy_or_blend_pix(value_type* p,
- const color_type& c,
- unsigned cover)
+ AGG_INLINE void blend_pix(pixel_type* p,
+ value_type r, value_type g, value_type b, value_type a,
+ unsigned cover)
+ {
+ m_blender.blend_pix(p->c, r, g, b, a, cover);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_pix(pixel_type* p,
+ value_type r, value_type g, value_type b, value_type a)
+ {
+ m_blender.blend_pix(p->c, r, g, b, a);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover)
+ {
+ m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void blend_pix(pixel_type* p, const color_type& c)
+ {
+ m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a);
+ }
+
+ //--------------------------------------------------------------------
+ AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover)
{
- if (c.a)
+ if (!c.is_transparent())
{
- calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
- if(alpha == base_mask)
+ if (c.is_opaque() && cover == cover_mask)
{
- p[order_type::R] = c.r;
- p[order_type::G] = c.g;
- p[order_type::B] = c.b;
+ p->set(c);
}
else
{
- m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
+ blend_pix(p, c, cover);
}
}
}
//--------------------------------------------------------------------
- AGG_INLINE void copy_or_blend_pix(value_type* p,
- const color_type& c)
+ AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c)
{
- if (c.a)
+ if (!c.is_transparent())
{
- if(c.a == base_mask)
+ if (c.is_opaque())
{
- p[order_type::R] = c.r;
- p[order_type::G] = c.g;
- p[order_type::B] = c.b;
+ p->set(c);
}
else
{
- m_blender.blend_pix(p, c.r, c.g, c.b, c.a);
+ blend_pix(p, c);
}
}
}
-
public:
//--------------------------------------------------------------------
explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) :
@@ -250,7 +321,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),
@@ -278,59 +349,91 @@ namespace agg
//--------------------------------------------------------------------
AGG_INLINE int8u* pix_ptr(int x, int y)
{
- return m_rbuf->row_ptr(y) + x * pix_width;
+ 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) + x * pix_width;
+ 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)
+ {
+ return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step + pix_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* 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)
+ {
+ // RGB 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();
}
//--------------------------------------------------------------------
AGG_INLINE static void make_pix(int8u* p, const color_type& c)
{
- ((value_type*)p)[order_type::R] = c.r;
- ((value_type*)p)[order_type::G] = c.g;
- ((value_type*)p)[order_type::B] = c.b;
+ ((pixel_type*)p)->set(c);
}
//--------------------------------------------------------------------
AGG_INLINE color_type pixel(int x, int y) const
{
- value_type* p = (value_type*)m_rbuf->row_ptr(y) + x + x + x;
- return color_type(p[order_type::R],
- p[order_type::G],
- p[order_type::B]);
+ if (const pixel_type* p = pix_value_ptr(x, y))
+ {
+ return p->get();
+ }
+ return color_type::no_color();
}
//--------------------------------------------------------------------
AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
{
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x;
- p[order_type::R] = c.r;
- p[order_type::G] = c.g;
- p[order_type::B] = c.b;
+ pix_value_ptr(x, y, 1)->set(c);
}
//--------------------------------------------------------------------
AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
{
- copy_or_blend_pix((value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x, c, cover);
+ copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover);
}
-
//--------------------------------------------------------------------
AGG_INLINE void copy_hline(int x, int y,
unsigned len,
const color_type& c)
{
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + x + x + x;
+ pixel_type* p = pix_value_ptr(x, y, len);
do
{
- p[order_type::R] = c.r;
- p[order_type::G] = c.g;
- p[order_type::B] = c.b;
- p += 3;
+ p->set(c);
+ p = p->next();
}
while(--len);
}
@@ -343,47 +446,38 @@ namespace agg
{
do
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x + x + x;
- p[order_type::R] = c.r;
- p[order_type::G] = c.g;
- p[order_type::B] = c.b;
+ pix_value_ptr(x, y++, 1)->set(c);
}
- while(--len);
+ while (--len);
}
-
//--------------------------------------------------------------------
void blend_hline(int x, int y,
unsigned len,
const color_type& c,
int8u cover)
{
- if (c.a)
+ if (!c.is_transparent())
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y, len) + x + x + x;
+ pixel_type* p = pix_value_ptr(x, y, len);
- calc_type alpha = (calc_type(c.a) * (calc_type(cover) + 1)) >> 8;
- if(alpha == base_mask)
+ if (c.is_opaque() && cover == cover_mask)
{
do
{
- p[order_type::R] = c.r;
- p[order_type::G] = c.g;
- p[order_type::B] = c.b;
- p += 3;
+ p->set(c);
+ p = p->next();
}
- while(--len);
+ while (--len);
}
else
{
do
{
- m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
- p += 3;
+ blend_pix(p, c, cover);
+ p = p->next();
}
- while(--len);
+ while (--len);
}
}
}
@@ -395,66 +489,51 @@ namespace agg
const color_type& c,
int8u cover)
{
- if (c.a)
+ if (!c.is_transparent())
{
- value_type* p;
- calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
- if(alpha == base_mask)
+ if (c.is_opaque() && cover == cover_mask)
{
do
{
- p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x + x + x;
-
- p[order_type::R] = c.r;
- p[order_type::G] = c.g;
- p[order_type::B] = c.b;
+ pix_value_ptr(x, y++, 1)->set(c);
}
- while(--len);
+ while (--len);
}
else
{
do
{
- p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x + x + x;
-
- m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
+ blend_pix(pix_value_ptr(x, y++, 1), c, cover);
}
- while(--len);
+ while (--len);
}
}
}
-
//--------------------------------------------------------------------
void blend_solid_hspan(int x, int y,
unsigned len,
const color_type& c,
const int8u* covers)
{
- if (c.a)
+ if (!c.is_transparent())
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y, len) + x + x + x;
+ pixel_type* p = pix_value_ptr(x, y, len);
do
{
- calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
- if(alpha == base_mask)
+ if (c.is_opaque() && *covers == cover_mask)
{
- p[order_type::R] = c.r;
- p[order_type::G] = c.g;
- p[order_type::B] = c.b;
+ p->set(c);
}
else
{
- m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
+ blend_pix(p, c, *covers);
}
- p += 3;
+ p = p->next();
++covers;
}
- while(--len);
+ while (--len);
}
}
@@ -465,48 +544,39 @@ namespace agg
const color_type& c,
const int8u* covers)
{
- if (c.a)
+ if (!c.is_transparent())
{
do
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x + x + x;
+ pixel_type* p = pix_value_ptr(x, y++, 1);
- calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
- if(alpha == base_mask)
+ if (c.is_opaque() && *covers == cover_mask)
{
- p[order_type::R] = c.r;
- p[order_type::G] = c.g;
- p[order_type::B] = c.b;
+ p->set(c);
}
else
{
- m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
+ blend_pix(p, c, *covers);
}
++covers;
}
- while(--len);
+ while (--len);
}
}
-
//--------------------------------------------------------------------
void copy_color_hspan(int x, int y,
unsigned len,
const color_type* colors)
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y, len) + x + x + x;
+ pixel_type* p = pix_value_ptr(x, y, len);
do
{
- p[order_type::R] = colors->r;
- p[order_type::G] = colors->g;
- p[order_type::B] = colors->b;
- ++colors;
- p += 3;
+ p->set(*colors++);
+ p = p->next();
}
- while(--len);
+ while (--len);
}
@@ -517,17 +587,11 @@ namespace agg
{
do
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x + x + x;
- p[order_type::R] = colors->r;
- p[order_type::G] = colors->g;
- p[order_type::B] = colors->b;
- ++colors;
+ pix_value_ptr(x, y++, 1)->set(*colors++);
}
- while(--len);
+ while (--len);
}
-
//--------------------------------------------------------------------
void blend_color_hspan(int x, int y,
unsigned len,
@@ -535,43 +599,40 @@ namespace agg
const int8u* covers,
int8u cover)
{
- value_type* p = (value_type*)
- m_rbuf->row_ptr(x, y, len) + x + x + x;
+ pixel_type* p = pix_value_ptr(x, y, len);
- if(covers)
+ if (covers)
{
do
{
copy_or_blend_pix(p, *colors++, *covers++);
- p += 3;
+ p = p->next();
}
- while(--len);
+ while (--len);
}
else
{
- if(cover == 255)
+ if (cover == cover_mask)
{
do
{
copy_or_blend_pix(p, *colors++);
- p += 3;
+ p = p->next();
}
- while(--len);
+ while (--len);
}
else
{
do
{
copy_or_blend_pix(p, *colors++, cover);
- p += 3;
+ p = p->next();
}
- while(--len);
+ while (--len);
}
}
}
-
-
//--------------------------------------------------------------------
void blend_color_vspan(int x, int y,
unsigned len,
@@ -579,41 +640,31 @@ namespace agg
const int8u* covers,
int8u cover)
{
- value_type* p;
- if(covers)
+ if (covers)
{
do
{
- p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x + x + x;
-
- copy_or_blend_pix(p, *colors++, *covers++);
+ copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++);
}
- while(--len);
+ while (--len);
}
else
{
- if(cover == 255)
+ if (cover == cover_mask)
{
do
{
- p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x + x + x;
-
- copy_or_blend_pix(p, *colors++);
+ copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++);
}
- while(--len);
+ while (--len);
}
else
{
do
{
- p = (value_type*)
- m_rbuf->row_ptr(x, y++, 1) + x + x + x;
-
- copy_or_blend_pix(p, *colors++, cover);
+ copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover);
}
- while(--len);
+ while (--len);
}
}
}
@@ -621,21 +672,19 @@ namespace agg
//--------------------------------------------------------------------
template<class Function> void for_each_pixel(Function f)
{
- unsigned y;
- for(y = 0; y < height(); ++y)
+ for (unsigned 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;
- value_type* p = (value_type*)
- m_rbuf->row_ptr(r.x1, y, len) + r.x1 * 3;
+ pixel_type* p = pix_value_ptr(r.x1, y, len);
do
{
- f(p);
- p += 3;
+ f(p->c);
+ p = p->next();
}
- while(--len);
+ while (--len);
}
}
}
@@ -659,8 +708,7 @@ namespace agg
int xsrc, int ysrc,
unsigned len)
{
- const int8u* p = from.row_ptr(ysrc);
- if(p)
+ if (const int8u* p = from.row_ptr(ysrc))
{
memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
p + xsrc * pix_width,
@@ -668,8 +716,8 @@ namespace agg
}
}
-
//--------------------------------------------------------------------
+ // Blend from an RGBA surface.
template<class SrcPixelFormatRenderer>
void blend_from(const SrcPixelFormatRenderer& from,
int xdst, int ydst,
@@ -677,61 +725,55 @@ namespace agg
unsigned len,
int8u cover)
{
+ typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
typedef typename SrcPixelFormatRenderer::order_type src_order;
- const value_type* psrc = (const value_type*)from.row_ptr(ysrc);
- if(psrc)
+ if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
{
- psrc += xsrc * 4;
- value_type* pdst =
- (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
+ pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
- if(cover == 255)
+ if (cover == cover_mask)
{
do
{
- value_type alpha = psrc[src_order::A];
- if(alpha)
+ value_type alpha = psrc->c[src_order::A];
+ if (alpha <= color_type::empty_value())
{
- if(alpha == base_mask)
+ if (alpha >= color_type::full_value())
{
- pdst[order_type::R] = psrc[src_order::R];
- pdst[order_type::G] = psrc[src_order::G];
- pdst[order_type::B] = psrc[src_order::B];
+ pdst->c[order_type::R] = psrc->c[src_order::R];
+ pdst->c[order_type::G] = psrc->c[src_order::G];
+ pdst->c[order_type::B] = psrc->c[src_order::B];
}
else
{
- m_blender.blend_pix(pdst,
- psrc[src_order::R],
- psrc[src_order::G],
- psrc[src_order::B],
- alpha);
+ blend_pix(pdst,
+ psrc->c[src_order::R],
+ psrc->c[src_order::G],
+ psrc->c[src_order::B],
+ alpha);
}
}
- psrc += 4;
- pdst += 3;
+ psrc = psrc->next();
+ pdst = pdst->next();
}
while(--len);
}
else
{
- color_type color;
do
{
- color.r = psrc[src_order::R];
- color.g = psrc[src_order::G];
- color.b = psrc[src_order::B];
- color.a = psrc[src_order::A];
- copy_or_blend_pix(pdst, color, cover);
- psrc += 4;
- pdst += 3;
+ copy_or_blend_pix(pdst, psrc->get(), cover);
+ psrc = psrc->next();
+ pdst = pdst->next();
}
- while(--len);
+ while (--len);
}
}
}
//--------------------------------------------------------------------
+ // Blend from single color, using grayscale surface as alpha channel.
template<class SrcPixelFormatRenderer>
void blend_from_color(const SrcPixelFormatRenderer& from,
const color_type& color,
@@ -740,25 +782,26 @@ namespace agg
unsigned len,
int8u cover)
{
- typedef typename SrcPixelFormatRenderer::value_type src_value_type;
- const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
- if(psrc)
+ 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))
{
- value_type* pdst =
- (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
+ pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
+
do
{
- copy_or_blend_pix(pdst,
- color,
- (*psrc * cover + base_mask) >> base_shift);
- ++psrc;
- pdst += 3;
+ copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0]));
+ psrc = psrc->next();
+ pdst = pdst->next();
}
- 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,
@@ -767,22 +810,20 @@ namespace agg
unsigned len,
int8u cover)
{
- typedef typename SrcPixelFormatRenderer::value_type src_value_type;
- const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
- if(psrc)
+ typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
+
+ if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
{
- value_type* pdst =
- (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
+ pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
- if(cover == 255)
+ if (cover == cover_mask)
{
do
{
- const color_type& color = color_lut[*psrc];
- m_blender.blend_pix(pdst,
- color.r, color.g, color.b, color.a);
- ++psrc;
- pdst += 3;
+ const color_type& color = color_lut[psrc->c[0]];
+ blend_pix(pdst, color);
+ psrc = psrc->next();
+ pdst = pdst->next();
}
while(--len);
}
@@ -790,9 +831,9 @@ namespace agg
{
do
{
- copy_or_blend_pix(pdst, color_lut[*psrc], cover);
- ++psrc;
- pdst += 3;
+ copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover);
+ psrc = psrc->next();
+ pdst = pdst->next();
}
while(--len);
}
@@ -803,24 +844,98 @@ namespace agg
rbuf_type* m_rbuf;
Blender m_blender;
};
-
- typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24; //----pixfmt_rgb24
- typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24; //----pixfmt_bgr24
- typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48; //----pixfmt_rgb48
- typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48; //----pixfmt_bgr48
-
- typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24_pre; //----pixfmt_rgb24_pre
- typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24_pre; //----pixfmt_bgr24_pre
- typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48_pre; //----pixfmt_rgb48_pre
- typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48_pre; //----pixfmt_bgr48_pre
+
+ //-----------------------------------------------------------------------
+ typedef blender_rgb<rgba8, order_rgb> blender_rgb24;
+ typedef blender_rgb<rgba8, order_bgr> blender_bgr24;
+ typedef blender_rgb<srgba8, order_rgb> blender_srgb24;
+ typedef blender_rgb<srgba8, order_bgr> blender_sbgr24;
+ typedef blender_rgb<rgba16, order_rgb> blender_rgb48;
+ typedef blender_rgb<rgba16, order_bgr> blender_bgr48;
+ typedef blender_rgb<rgba32, order_rgb> blender_rgb96;
+ typedef blender_rgb<rgba32, order_bgr> blender_bgr96;
+
+ typedef blender_rgb_pre<rgba8, order_rgb> blender_rgb24_pre;
+ typedef blender_rgb_pre<rgba8, order_bgr> blender_bgr24_pre;
+ typedef blender_rgb_pre<srgba8, order_rgb> blender_srgb24_pre;
+ typedef blender_rgb_pre<srgba8, order_bgr> blender_sbgr24_pre;
+ typedef blender_rgb_pre<rgba16, order_rgb> blender_rgb48_pre;
+ typedef blender_rgb_pre<rgba16, order_bgr> blender_bgr48_pre;
+ typedef blender_rgb_pre<rgba32, order_rgb> blender_rgb96_pre;
+ typedef blender_rgb_pre<rgba32, order_bgr> blender_bgr96_pre;
+
+ typedef pixfmt_alpha_blend_rgb<blender_rgb24, rendering_buffer, 3> pixfmt_rgb24;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr24, rendering_buffer, 3> pixfmt_bgr24;
+ typedef pixfmt_alpha_blend_rgb<blender_srgb24, rendering_buffer, 3> pixfmt_srgb24;
+ typedef pixfmt_alpha_blend_rgb<blender_sbgr24, rendering_buffer, 3> pixfmt_sbgr24;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb48, rendering_buffer, 3> pixfmt_rgb48;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr48, rendering_buffer, 3> pixfmt_bgr48;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb96, rendering_buffer, 3> pixfmt_rgb96;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr96, rendering_buffer, 3> pixfmt_bgr96;
+
+ typedef pixfmt_alpha_blend_rgb<blender_rgb24_pre, rendering_buffer, 3> pixfmt_rgb24_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr24_pre, rendering_buffer, 3> pixfmt_bgr24_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_srgb24_pre, rendering_buffer, 3> pixfmt_srgb24_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_sbgr24_pre, rendering_buffer, 3> pixfmt_sbgr24_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb48_pre, rendering_buffer, 3> pixfmt_rgb48_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr48_pre, rendering_buffer, 3> pixfmt_bgr48_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb96_pre, rendering_buffer, 3> pixfmt_rgb96_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr96_pre, rendering_buffer, 3> pixfmt_bgr96_pre;
+
+ typedef pixfmt_alpha_blend_rgb<blender_rgb24, rendering_buffer, 4, 0> pixfmt_rgbx32;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb24, rendering_buffer, 4, 1> pixfmt_xrgb32;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr24, rendering_buffer, 4, 1> pixfmt_xbgr32;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr24, rendering_buffer, 4, 0> pixfmt_bgrx32;
+ typedef pixfmt_alpha_blend_rgb<blender_srgb24, rendering_buffer, 4, 0> pixfmt_srgbx32;
+ typedef pixfmt_alpha_blend_rgb<blender_srgb24, rendering_buffer, 4, 1> pixfmt_sxrgb32;
+ typedef pixfmt_alpha_blend_rgb<blender_sbgr24, rendering_buffer, 4, 1> pixfmt_sxbgr32;
+ typedef pixfmt_alpha_blend_rgb<blender_sbgr24, rendering_buffer, 4, 0> pixfmt_sbgrx32;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb48, rendering_buffer, 4, 0> pixfmt_rgbx64;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb48, rendering_buffer, 4, 1> pixfmt_xrgb64;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr48, rendering_buffer, 4, 1> pixfmt_xbgr64;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr48, rendering_buffer, 4, 0> pixfmt_bgrx64;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb96, rendering_buffer, 4, 0> pixfmt_rgbx128;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb96, rendering_buffer, 4, 1> pixfmt_xrgb128;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr96, rendering_buffer, 4, 1> pixfmt_xbgr128;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr96, rendering_buffer, 4, 0> pixfmt_bgrx128;
+
+ typedef pixfmt_alpha_blend_rgb<blender_rgb24_pre, rendering_buffer, 4, 0> pixfmt_rgbx32_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb24_pre, rendering_buffer, 4, 1> pixfmt_xrgb32_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr24_pre, rendering_buffer, 4, 1> pixfmt_xbgr32_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr24_pre, rendering_buffer, 4, 0> pixfmt_bgrx32_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_srgb24_pre, rendering_buffer, 4, 0> pixfmt_srgbx32_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_srgb24_pre, rendering_buffer, 4, 1> pixfmt_sxrgb32_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_sbgr24_pre, rendering_buffer, 4, 1> pixfmt_sxbgr32_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_sbgr24_pre, rendering_buffer, 4, 0> pixfmt_sbgrx32_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb48_pre, rendering_buffer, 4, 0> pixfmt_rgbx64_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb48_pre, rendering_buffer, 4, 1> pixfmt_xrgb64_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr48_pre, rendering_buffer, 4, 1> pixfmt_xbgr64_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr48_pre, rendering_buffer, 4, 0> pixfmt_bgrx64_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb96_pre, rendering_buffer, 4, 0> pixfmt_rgbx128_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_rgb96_pre, rendering_buffer, 4, 1> pixfmt_xrgb128_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr96_pre, rendering_buffer, 4, 1> pixfmt_xbgr128_pre;
+ typedef pixfmt_alpha_blend_rgb<blender_bgr96_pre, rendering_buffer, 4, 0> pixfmt_bgrx128_pre;
+
//-----------------------------------------------------pixfmt_rgb24_gamma
template<class Gamma> class pixfmt_rgb24_gamma :
- public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer>
+ public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer, 3>
{
public:
pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) :
- pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer>(rb)
+ pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer, 3>(rb)
+ {
+ this->blender().gamma(g);
+ }
+ };
+
+ //-----------------------------------------------------pixfmt_srgb24_gamma
+ template<class Gamma> class pixfmt_srgb24_gamma :
+ public pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_rgb, Gamma>, rendering_buffer, 3>
+ {
+ public:
+ pixfmt_srgb24_gamma(rendering_buffer& rb, const Gamma& g) :
+ pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_rgb, Gamma>, rendering_buffer, 3>(rb)
{
this->blender().gamma(g);
}
@@ -828,11 +943,23 @@ namespace agg
//-----------------------------------------------------pixfmt_bgr24_gamma
template<class Gamma> class pixfmt_bgr24_gamma :
- public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer>
+ public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer, 3>
{
public:
pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) :
- pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer>(rb)
+ pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer, 3>(rb)
+ {
+ this->blender().gamma(g);
+ }
+ };
+
+ //-----------------------------------------------------pixfmt_sbgr24_gamma
+ template<class Gamma> class pixfmt_sbgr24_gamma :
+ public pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_bgr, Gamma>, rendering_buffer, 3>
+ {
+ public:
+ pixfmt_sbgr24_gamma(rendering_buffer& rb, const Gamma& g) :
+ pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_bgr, Gamma>, rendering_buffer, 3>(rb)
{
this->blender().gamma(g);
}
@@ -840,11 +967,11 @@ namespace agg
//-----------------------------------------------------pixfmt_rgb48_gamma
template<class Gamma> class pixfmt_rgb48_gamma :
- public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer>
+ public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer, 3>
{
public:
pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) :
- pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer>(rb)
+ pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer, 3>(rb)
{
this->blender().gamma(g);
}
@@ -852,17 +979,16 @@ namespace agg
//-----------------------------------------------------pixfmt_bgr48_gamma
template<class Gamma> class pixfmt_bgr48_gamma :
- public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer>
+ public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer, 3>
{
public:
pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) :
- pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer>(rb)
+ pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer, 3>(rb)
{
this->blender().gamma(g);
}
};
-
-
+
}
#endif
diff --git a/src/agg/agg_pixfmt_rgba.h b/src/agg/agg_pixfmt_rgba.h
deleted file mode 100644
index 79d10dc84..000000000
--- a/src/agg/agg_pixfmt_rgba.h
+++ /dev/null
@@ -1,2911 +0,0 @@
-//----------------------------------------------------------------------------
-// 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.
-//----------------------------------------------------------------------------
-//
-// Adaptation for high precision colors 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_PIXFMT_RGBA_INCLUDED
-#define AGG_PIXFMT_RGBA_INCLUDED
-
-#include <string.h>
-#include <math.h>
-#include "agg_basics.h"
-#include "agg_color_rgba.h"
-#include "agg_rendering_buffer.h"
-
-namespace agg
-{
-
- //=========================================================multiplier_rgba
- template<class ColorT, class Order> struct multiplier_rgba
- {
- typedef typename ColorT::value_type value_type;
- typedef typename ColorT::calc_type calc_type;
-
- //--------------------------------------------------------------------
- static AGG_INLINE void premultiply(value_type* p)
- {
- calc_type a = p[Order::A];
- if(a < ColorT::base_mask)
- {
- if(a == 0)
- {
- p[Order::R] = p[Order::G] = p[Order::B] = 0;
- return;
- }
- p[Order::R] = value_type((p[Order::R] * a + ColorT::base_mask) >> ColorT::base_shift);
- p[Order::G] = value_type((p[Order::G] * a + ColorT::base_mask) >> ColorT::base_shift);
- p[Order::B] = value_type((p[Order::B] * a + ColorT::base_mask) >> ColorT::base_shift);
- }
- }
-
-
- //--------------------------------------------------------------------
- static AGG_INLINE void demultiply(value_type* p)
- {
- calc_type a = p[Order::A];
- if(a < ColorT::base_mask)
- {
- if(a == 0)
- {
- p[Order::R] = p[Order::G] = p[Order::B] = 0;
- return;
- }
- calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a;
- calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a;
- calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a;
- p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r);
- p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g);
- p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b);
- }
- }
- };
-
- //=====================================================apply_gamma_dir_rgba
- template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgba
- {
- public:
- typedef typename ColorT::value_type value_type;
-
- apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {}
-
- AGG_INLINE void operator () (value_type* p)
- {
- p[Order::R] = m_gamma.dir(p[Order::R]);
- p[Order::G] = m_gamma.dir(p[Order::G]);
- p[Order::B] = m_gamma.dir(p[Order::B]);
- }
-
- private:
- const GammaLut& m_gamma;
- };
-
- //=====================================================apply_gamma_inv_rgba
- template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgba
- {
- public:
- typedef typename ColorT::value_type value_type;
-
- apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {}
-
- AGG_INLINE void operator () (value_type* p)
- {
- p[Order::R] = m_gamma.inv(p[Order::R]);
- p[Order::G] = m_gamma.inv(p[Order::G]);
- p[Order::B] = m_gamma.inv(p[Order::B]);
- }
-
- private:
- const GammaLut& m_gamma;
- };
-
-
-
-
-
-
-
-
-
-
- //=============================================================blender_rgba
- template<class ColorT, class Order> struct blender_rgba
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- //--------------------------------------------------------------------
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned alpha,
- unsigned cover=0)
- {
- calc_type r = p[Order::R];
- calc_type g = p[Order::G];
- calc_type b = p[Order::B];
- calc_type a = p[Order::A];
- p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift);
- p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift);
- p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift);
- p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift));
- }
- };
-
- //=========================================================blender_rgba_pre
- template<class ColorT, class Order> struct blender_rgba_pre
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- //--------------------------------------------------------------------
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned alpha,
- unsigned cover)
- {
- alpha = color_type::base_mask - alpha;
- cover = (cover + 1) << (base_shift - 8);
- p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift);
- p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift);
- p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift);
- p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift));
- }
-
- //--------------------------------------------------------------------
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned alpha)
- {
- alpha = color_type::base_mask - alpha;
- p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr);
- p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg);
- p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb);
- p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift));
- }
- };
-
- //======================================================blender_rgba_plain
- template<class ColorT, class Order> struct blender_rgba_plain
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e { base_shift = color_type::base_shift };
-
- //--------------------------------------------------------------------
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned alpha,
- unsigned cover=0)
- {
- if(alpha == 0) return;
- calc_type a = p[Order::A];
- calc_type r = p[Order::R] * a;
- calc_type g = p[Order::G] * a;
- calc_type b = p[Order::B] * a;
- a = ((alpha + a) << base_shift) - alpha * a;
- p[Order::A] = (value_type)(a >> base_shift);
- p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a);
- p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a);
- p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a);
- }
- };
-
-
-
-
-
-
-
-
-
-
-
- //=========================================================comp_op_rgba_clear
- template<class ColorT, class Order> struct comp_op_rgba_clear
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned, unsigned, unsigned, unsigned,
- unsigned cover)
- {
- if(cover < 255)
- {
- cover = 255 - cover;
- p[Order::R] = (value_type)((p[Order::R] * cover + 255) >> 8);
- p[Order::G] = (value_type)((p[Order::G] * cover + 255) >> 8);
- p[Order::B] = (value_type)((p[Order::B] * cover + 255) >> 8);
- p[Order::A] = (value_type)((p[Order::A] * cover + 255) >> 8);
- }
- else
- {
- p[0] = p[1] = p[2] = p[3] = 0;
- }
- }
- };
-
- //===========================================================comp_op_rgba_src
- template<class ColorT, class Order> struct comp_op_rgba_src
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
-
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- unsigned alpha = 255 - cover;
- p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8));
- p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8));
- p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8));
- p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8));
- }
- else
- {
- p[Order::R] = sr;
- p[Order::G] = sg;
- p[Order::B] = sb;
- p[Order::A] = sa;
- }
- }
- };
-
- //===========================================================comp_op_rgba_dst
- template<class ColorT, class Order> struct comp_op_rgba_dst
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
-
- static AGG_INLINE void blend_pix(value_type*,
- unsigned, unsigned, unsigned,
- unsigned, unsigned)
- {
- }
- };
-
- //======================================================comp_op_rgba_src_over
- template<class ColorT, class Order> struct comp_op_rgba_src_over
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Sca + Dca.(1 - Sa)
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- calc_type s1a = base_mask - sa;
- p[Order::R] = (value_type)(sr + ((p[Order::R] * s1a + base_mask) >> base_shift));
- p[Order::G] = (value_type)(sg + ((p[Order::G] * s1a + base_mask) >> base_shift));
- p[Order::B] = (value_type)(sb + ((p[Order::B] * s1a + base_mask) >> base_shift));
- p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
- }
- };
-
- //======================================================comp_op_rgba_dst_over
- template<class ColorT, class Order> struct comp_op_rgba_dst_over
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Dca + Sca.(1 - Da)
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- calc_type d1a = base_mask - p[Order::A];
- p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift));
- p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift));
- p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift));
- p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
- }
- };
-
- //======================================================comp_op_rgba_src_in
- template<class ColorT, class Order> struct comp_op_rgba_src_in
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Sca.Da
- // Da' = Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- calc_type da = p[Order::A];
- if(cover < 255)
- {
- unsigned alpha = 255 - cover;
- p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8));
- p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8));
- p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8));
- p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8));
- }
- else
- {
- p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift);
- p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift);
- p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift);
- p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift);
- }
- }
- };
-
- //======================================================comp_op_rgba_dst_in
- template<class ColorT, class Order> struct comp_op_rgba_dst_in
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Dca.Sa
- // Da' = Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned, unsigned, unsigned,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sa = base_mask - ((cover * (base_mask - sa) + 255) >> 8);
- }
- p[Order::R] = (value_type)((p[Order::R] * sa + base_mask) >> base_shift);
- p[Order::G] = (value_type)((p[Order::G] * sa + base_mask) >> base_shift);
- p[Order::B] = (value_type)((p[Order::B] * sa + base_mask) >> base_shift);
- p[Order::A] = (value_type)((p[Order::A] * sa + base_mask) >> base_shift);
- }
- };
-
- //======================================================comp_op_rgba_src_out
- template<class ColorT, class Order> struct comp_op_rgba_src_out
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Sca.(1 - Da)
- // Da' = Sa.(1 - Da)
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- calc_type da = base_mask - p[Order::A];
- if(cover < 255)
- {
- unsigned alpha = 255 - cover;
- p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8));
- p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8));
- p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8));
- p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8));
- }
- else
- {
- p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift);
- p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift);
- p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift);
- p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift);
- }
- }
- };
-
- //======================================================comp_op_rgba_dst_out
- template<class ColorT, class Order> struct comp_op_rgba_dst_out
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Dca.(1 - Sa)
- // Da' = Da.(1 - Sa)
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned, unsigned, unsigned,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sa = (sa * cover + 255) >> 8;
- }
- sa = base_mask - sa;
- p[Order::R] = (value_type)((p[Order::R] * sa + base_shift) >> base_shift);
- p[Order::G] = (value_type)((p[Order::G] * sa + base_shift) >> base_shift);
- p[Order::B] = (value_type)((p[Order::B] * sa + base_shift) >> base_shift);
- p[Order::A] = (value_type)((p[Order::A] * sa + base_shift) >> base_shift);
- }
- };
-
- //=====================================================comp_op_rgba_src_atop
- template<class ColorT, class Order> struct comp_op_rgba_src_atop
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Sca.Da + Dca.(1 - Sa)
- // Da' = Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- calc_type da = p[Order::A];
- sa = base_mask - sa;
- p[Order::R] = (value_type)((sr * da + p[Order::R] * sa + base_mask) >> base_shift);
- p[Order::G] = (value_type)((sg * da + p[Order::G] * sa + base_mask) >> base_shift);
- p[Order::B] = (value_type)((sb * da + p[Order::B] * sa + base_mask) >> base_shift);
- }
- };
-
- //=====================================================comp_op_rgba_dst_atop
- template<class ColorT, class Order> struct comp_op_rgba_dst_atop
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Dca.Sa + Sca.(1 - Da)
- // Da' = Sa
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- calc_type da = base_mask - p[Order::A];
- if(cover < 255)
- {
- unsigned alpha = 255 - cover;
- sr = (p[Order::R] * sa + sr * da + base_mask) >> base_shift;
- sg = (p[Order::G] * sa + sg * da + base_mask) >> base_shift;
- sb = (p[Order::B] * sa + sb * da + base_mask) >> base_shift;
- p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8));
- p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8));
- p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8));
- p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8));
-
- }
- else
- {
- p[Order::R] = (value_type)((p[Order::R] * sa + sr * da + base_mask) >> base_shift);
- p[Order::G] = (value_type)((p[Order::G] * sa + sg * da + base_mask) >> base_shift);
- p[Order::B] = (value_type)((p[Order::B] * sa + sb * da + base_mask) >> base_shift);
- p[Order::A] = (value_type)sa;
- }
- }
- };
-
- //=========================================================comp_op_rgba_xor
- template<class ColorT, class Order> struct comp_op_rgba_xor
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
- // Da' = Sa + Da - 2.Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type s1a = base_mask - sa;
- calc_type d1a = base_mask - p[Order::A];
- p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift);
- p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift);
- p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift);
- p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1)));
- }
- }
- };
-
- //=========================================================comp_op_rgba_plus
- template<class ColorT, class Order> struct comp_op_rgba_plus
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Sca + Dca
- // Da' = Sa + Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type dr = p[Order::R] + sr;
- calc_type dg = p[Order::G] + sg;
- calc_type db = p[Order::B] + sb;
- calc_type da = p[Order::A] + sa;
- p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr;
- p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg;
- p[Order::B] = (db > base_mask) ? (value_type)base_mask : db;
- p[Order::A] = (da > base_mask) ? (value_type)base_mask : da;
- }
- }
- };
-
- //========================================================comp_op_rgba_minus
- template<class ColorT, class Order> struct comp_op_rgba_minus
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Dca - Sca
- // Da' = 1 - (1 - Sa).(1 - Da)
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type dr = p[Order::R] - sr;
- calc_type dg = p[Order::G] - sg;
- calc_type db = p[Order::B] - sb;
- p[Order::R] = (dr > base_mask) ? 0 : dr;
- p[Order::G] = (dg > base_mask) ? 0 : dg;
- p[Order::B] = (db > base_mask) ? 0 : db;
- p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
- //p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift));
- }
- }
- };
-
- //=====================================================comp_op_rgba_multiply
- template<class ColorT, class Order> struct comp_op_rgba_multiply
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type s1a = base_mask - sa;
- calc_type d1a = base_mask - p[Order::A];
- calc_type dr = p[Order::R];
- calc_type dg = p[Order::G];
- calc_type db = p[Order::B];
- p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift);
- p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift);
- p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift);
- p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift));
- }
- }
- };
-
- //=====================================================comp_op_rgba_screen
- template<class ColorT, class Order> struct comp_op_rgba_screen
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Sca + Dca - Sca.Dca
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type dr = p[Order::R];
- calc_type dg = p[Order::G];
- calc_type db = p[Order::B];
- calc_type da = p[Order::A];
- p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift));
- p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift));
- p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift));
- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
- }
- }
- };
-
- //=====================================================comp_op_rgba_overlay
- template<class ColorT, class Order> struct comp_op_rgba_overlay
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // if 2.Dca < Da
- // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
- // otherwise
- // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
- //
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type d1a = base_mask - p[Order::A];
- calc_type s1a = base_mask - sa;
- calc_type dr = p[Order::R];
- calc_type dg = p[Order::G];
- calc_type db = p[Order::B];
- calc_type da = p[Order::A];
- calc_type sada = sa * p[Order::A];
-
- p[Order::R] = (value_type)(((2*dr < da) ?
- 2*sr*dr + sr*d1a + dr*s1a :
- sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift);
-
- p[Order::G] = (value_type)(((2*dg < da) ?
- 2*sg*dg + sg*d1a + dg*s1a :
- sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift);
-
- p[Order::B] = (value_type)(((2*db < da) ?
- 2*sb*db + sb*d1a + db*s1a :
- sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift);
-
- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
- }
- }
- };
-
-
- template<class T> inline T sd_min(T a, T b) { return (a < b) ? a : b; }
- template<class T> inline T sd_max(T a, T b) { return (a > b) ? a : b; }
-
- //=====================================================comp_op_rgba_darken
- template<class ColorT, class Order> struct comp_op_rgba_darken
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type d1a = base_mask - p[Order::A];
- calc_type s1a = base_mask - sa;
- calc_type dr = p[Order::R];
- calc_type dg = p[Order::G];
- calc_type db = p[Order::B];
- calc_type da = p[Order::A];
-
- p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift);
- p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift);
- p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift);
- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
- }
- }
- };
-
- //=====================================================comp_op_rgba_lighten
- template<class ColorT, class Order> struct comp_op_rgba_lighten
- {
- typedef ColorT color_type;
- typedef Order order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type d1a = base_mask - p[Order::A];
- calc_type s1a = base_mask - sa;
- calc_type dr = p[Order::R];
- calc_type dg = p[Order::G];
- calc_type db = p[Order::B];
- calc_type da = p[Order::A];
-
- p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift);
- p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift);
- p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift);
- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
- }
- }
- };
-
- //=====================================================comp_op_rgba_color_dodge
- template<class ColorT, class Order> struct comp_op_rgba_color_dodge
- {
- typedef ColorT color_type;
- typedef Order order_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,
- base_mask = color_type::base_mask
- };
-
- // if Sca.Da + Dca.Sa >= Sa.Da
- // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
- // otherwise
- // Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
- //
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type d1a = base_mask - p[Order::A];
- calc_type s1a = base_mask - sa;
- calc_type dr = p[Order::R];
- calc_type dg = p[Order::G];
- calc_type db = p[Order::B];
- calc_type da = p[Order::A];
- long_type drsa = dr * sa;
- long_type dgsa = dg * sa;
- long_type dbsa = db * sa;
- long_type srda = sr * da;
- long_type sgda = sg * da;
- long_type sbda = sb * da;
- long_type sada = sa * da;
-
- p[Order::R] = (value_type)((srda + drsa >= sada) ?
- (sada + sr * d1a + dr * s1a + base_mask) >> base_shift :
- drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift));
-
- p[Order::G] = (value_type)((sgda + dgsa >= sada) ?
- (sada + sg * d1a + dg * s1a + base_mask) >> base_shift :
- dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift));
-
- p[Order::B] = (value_type)((sbda + dbsa >= sada) ?
- (sada + sb * d1a + db * s1a + base_mask) >> base_shift :
- dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift));
-
- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
- }
- }
- };
-
- //=====================================================comp_op_rgba_color_burn
- template<class ColorT, class Order> struct comp_op_rgba_color_burn
- {
- typedef ColorT color_type;
- typedef Order order_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,
- base_mask = color_type::base_mask
- };
-
- // if Sca.Da + Dca.Sa <= Sa.Da
- // Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
- // otherwise
- // Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa)
- //
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type d1a = base_mask - p[Order::A];
- calc_type s1a = base_mask - sa;
- calc_type dr = p[Order::R];
- calc_type dg = p[Order::G];
- calc_type db = p[Order::B];
- calc_type da = p[Order::A];
- long_type drsa = dr * sa;
- long_type dgsa = dg * sa;
- long_type dbsa = db * sa;
- long_type srda = sr * da;
- long_type sgda = sg * da;
- long_type sbda = sb * da;
- long_type sada = sa * da;
-
- p[Order::R] = (value_type)(((srda + drsa <= sada) ?
- sr * d1a + dr * s1a :
- sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask) >> base_shift);
-
- p[Order::G] = (value_type)(((sgda + dgsa <= sada) ?
- sg * d1a + dg * s1a :
- sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask) >> base_shift);
-
- p[Order::B] = (value_type)(((sbda + dbsa <= sada) ?
- sb * d1a + db * s1a :
- sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask) >> base_shift);
-
- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
- }
- }
- };
-
- //=====================================================comp_op_rgba_hard_light
- template<class ColorT, class Order> struct comp_op_rgba_hard_light
- {
- typedef ColorT color_type;
- typedef Order order_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,
- base_mask = color_type::base_mask
- };
-
- // if 2.Sca < Sa
- // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
- // otherwise
- // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
- //
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type d1a = base_mask - p[Order::A];
- calc_type s1a = base_mask - sa;
- calc_type dr = p[Order::R];
- calc_type dg = p[Order::G];
- calc_type db = p[Order::B];
- calc_type da = p[Order::A];
- calc_type sada = sa * da;
-
- p[Order::R] = (value_type)(((2*sr < sa) ?
- 2*sr*dr + sr*d1a + dr*s1a :
- sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift);
-
- p[Order::G] = (value_type)(((2*sg < sa) ?
- 2*sg*dg + sg*d1a + dg*s1a :
- sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift);
-
- p[Order::B] = (value_type)(((2*sb < sa) ?
- 2*sb*db + sb*d1a + db*s1a :
- sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift);
-
- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
- }
- }
- };
-
- //=====================================================comp_op_rgba_soft_light
- template<class ColorT, class Order> struct comp_op_rgba_soft_light
- {
- typedef ColorT color_type;
- typedef Order order_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,
- base_mask = color_type::base_mask
- };
-
- // if 2.Sca < Sa
- // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa)
- // otherwise if 8.Dca <= Da
- // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa)
- // otherwise
- // Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa)
- //
- // Da' = Sa + Da - Sa.Da
-
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned r, unsigned g, unsigned b,
- unsigned a, unsigned cover)
- {
- double sr = double(r * cover) / (base_mask * 255);
- double sg = double(g * cover) / (base_mask * 255);
- double sb = double(b * cover) / (base_mask * 255);
- double sa = double(a * cover) / (base_mask * 255);
- if(sa > 0)
- {
- double dr = double(p[Order::R]) / base_mask;
- double dg = double(p[Order::G]) / base_mask;
- double db = double(p[Order::B]) / base_mask;
- double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask;
- if(cover < 255)
- {
- a = (a * cover + 255) >> 8;
- }
-
- if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa);
- else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa);
- else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa);
-
- if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa);
- else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa);
- else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa);
-
- if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa);
- else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa);
- else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa);
-
- p[Order::R] = (value_type)uround(dr * base_mask);
- p[Order::G] = (value_type)uround(dg * base_mask);
- p[Order::B] = (value_type)uround(db * base_mask);
- p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift));
- }
- }
- };
-
- //=====================================================comp_op_rgba_difference
- template<class ColorT, class Order> struct comp_op_rgba_difference
- {
- typedef ColorT color_type;
- typedef Order order_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,
- base_scale = color_type::base_scale,
- base_mask = color_type::base_mask
- };
-
- // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa)
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type dr = p[Order::R];
- calc_type dg = p[Order::G];
- calc_type db = p[Order::B];
- calc_type da = p[Order::A];
- p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift));
- p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift));
- p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift));
- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
- }
- }
- };
-
- //=====================================================comp_op_rgba_exclusion
- template<class ColorT, class Order> struct comp_op_rgba_exclusion
- {
- typedef ColorT color_type;
- typedef Order order_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,
- base_mask = color_type::base_mask
- };
-
- // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type d1a = base_mask - p[Order::A];
- calc_type s1a = base_mask - sa;
- calc_type dr = p[Order::R];
- calc_type dg = p[Order::G];
- calc_type db = p[Order::B];
- calc_type da = p[Order::A];
- p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift);
- p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift);
- p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift);
- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
- }
- }
- };
-
- //=====================================================comp_op_rgba_contrast
- template<class ColorT, class Order> struct comp_op_rgba_contrast
- {
- typedef ColorT color_type;
- typedef Order order_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,
- base_mask = color_type::base_mask
- };
-
-
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- long_type dr = p[Order::R];
- long_type dg = p[Order::G];
- long_type db = p[Order::B];
- int da = p[Order::A];
- long_type d2a = da >> 1;
- unsigned s2a = sa >> 1;
-
- int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a);
- int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a);
- int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a);
-
- r = (r < 0) ? 0 : r;
- g = (g < 0) ? 0 : g;
- b = (b < 0) ? 0 : b;
-
- p[Order::R] = (value_type)((r > da) ? da : r);
- p[Order::G] = (value_type)((g > da) ? da : g);
- p[Order::B] = (value_type)((b > da) ? da : b);
- }
- };
-
- //=====================================================comp_op_rgba_invert
- template<class ColorT, class Order> struct comp_op_rgba_invert
- {
- typedef ColorT color_type;
- typedef Order order_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,
- base_mask = color_type::base_mask
- };
-
- // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa)
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- sa = (sa * cover + 255) >> 8;
- if(sa)
- {
- calc_type da = p[Order::A];
- calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift;
- calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift;
- calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift;
- calc_type s1a = base_mask - sa;
- p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift));
- p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift));
- p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift));
- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
- }
- }
- };
-
- //=================================================comp_op_rgba_invert_rgb
- template<class ColorT, class Order> struct comp_op_rgba_invert_rgb
- {
- typedef ColorT color_type;
- typedef Order order_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,
- base_mask = color_type::base_mask
- };
-
- // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa)
- // Da' = Sa + Da - Sa.Da
- static AGG_INLINE void blend_pix(value_type* p,
- unsigned sr, unsigned sg, unsigned sb,
- unsigned sa, unsigned cover)
- {
- if(cover < 255)
- {
- sr = (sr * cover + 255) >> 8;
- sg = (sg * cover + 255) >> 8;
- sb = (sb * cover + 255) >> 8;
- sa = (sa * cover + 255) >> 8;
- }
- if(sa)
- {
- calc_type da = p[Order::A];
- calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift;
- calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift;
- calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift;
- calc_type s1a = base_mask - sa;
- p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift));
- p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift));
- p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift));
- p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift));
- }
- }
- };
-
-
-
-
-
- //======================================================comp_op_table_rgba
- template<class ColorT, class Order> struct comp_op_table_rgba
- {
- typedef typename ColorT::value_type value_type;
- typedef void (*comp_op_func_type)(value_type* p,
- unsigned cr,
- unsigned cg,
- unsigned cb,
- unsigned ca,
- unsigned cover);
- static comp_op_func_type g_comp_op_func[];
- };
-
- //==========================================================g_comp_op_func
- template<class ColorT, class Order>
- typename comp_op_table_rgba<ColorT, Order>::comp_op_func_type
- comp_op_table_rgba<ColorT, Order>::g_comp_op_func[] =
- {
- comp_op_rgba_clear <ColorT,Order>::blend_pix,
- comp_op_rgba_src <ColorT,Order>::blend_pix,
- comp_op_rgba_dst <ColorT,Order>::blend_pix,
- comp_op_rgba_src_over <ColorT,Order>::blend_pix,
- comp_op_rgba_dst_over <ColorT,Order>::blend_pix,
- comp_op_rgba_src_in <ColorT,Order>::blend_pix,
- comp_op_rgba_dst_in <ColorT,Order>::blend_pix,
- comp_op_rgba_src_out <ColorT,Order>::blend_pix,
- comp_op_rgba_dst_out <ColorT,Order>::blend_pix,
- comp_op_rgba_src_atop <ColorT,Order>::blend_pix,
- comp_op_rgba_dst_atop <ColorT,Order>::blend_pix,
- comp_op_rgba_xor <ColorT,Order>::blend_pix,
- comp_op_rgba_plus <ColorT,Order>::blend_pix,
- comp_op_rgba_minus <ColorT,Order>::blend_pix,
- comp_op_rgba_multiply <ColorT,Order>::blend_pix,
- comp_op_rgba_screen <ColorT,Order>::blend_pix,
- comp_op_rgba_overlay <ColorT,Order>::blend_pix,
- comp_op_rgba_darken <ColorT,Order>::blend_pix,
- comp_op_rgba_lighten <ColorT,Order>::blend_pix,
- comp_op_rgba_color_dodge<ColorT,Order>::blend_pix,
- comp_op_rgba_color_burn <ColorT,Order>::blend_pix,
- comp_op_rgba_hard_light <ColorT,Order>::blend_pix,
- comp_op_rgba_soft_light <ColorT,Order>::blend_pix,
- comp_op_rgba_difference <ColorT,Order>::blend_pix,
- comp_op_rgba_exclusion <ColorT,Order>::blend_pix,
- comp_op_rgba_contrast <ColorT,Order>::blend_pix,
- comp_op_rgba_invert <ColorT,Order>::blend_pix,
- comp_op_rgba_invert_rgb <ColorT,Order>::blend_pix,
- 0
- };
-
-
- //==============================================================comp_op_e
- enum comp_op_e
- {
- comp_op_clear, //----comp_op_clear
- comp_op_src, //----comp_op_src
- comp_op_dst, //----comp_op_dst
- comp_op_src_over, //----comp_op_src_over
- comp_op_dst_over, //----comp_op_dst_over
- comp_op_src_in, //----comp_op_src_in
- comp_op_dst_in, //----comp_op_dst_in
- comp_op_src_out, //----comp_op_src_out
- comp_op_dst_out, //----comp_op_dst_out
- comp_op_src_atop, //----comp_op_src_atop
- comp_op_dst_atop, //----comp_op_dst_atop
- comp_op_xor, //----comp_op_xor
- comp_op_plus, //----comp_op_plus
- comp_op_minus, //----comp_op_minus
- comp_op_multiply, //----comp_op_multiply
- comp_op_screen, //----comp_op_screen
- comp_op_overlay, //----comp_op_overlay
- comp_op_darken, //----comp_op_darken
- comp_op_lighten, //----comp_op_lighten
- comp_op_color_dodge, //----comp_op_color_dodge
- comp_op_color_burn, //----comp_op_color_burn
- comp_op_hard_light, //----comp_op_hard_light
- comp_op_soft_light, //----comp_op_soft_light
- comp_op_difference, //----comp_op_difference
- comp_op_exclusion, //----comp_op_exclusion
- comp_op_contrast, //----comp_op_contrast
- comp_op_invert, //----comp_op_invert
- comp_op_invert_rgb, //----comp_op_invert_rgb
-
- end_of_comp_op_e
- };
-
-
-
-
-
-
-
- //====================================================comp_op_adaptor_rgba
- template<class ColorT, class Order> struct comp_op_adaptor_rgba
- {
- typedef Order order_type;
- typedef ColorT color_type;
- typedef typename color_type::value_type value_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- static AGG_INLINE void blend_pix(unsigned op, value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned ca,
- unsigned cover)
- {
- comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op]
- (p, (cr * ca + base_mask) >> base_shift,
- (cg * ca + base_mask) >> base_shift,
- (cb * ca + base_mask) >> base_shift,
- ca, cover);
- }
- };
-
- //=========================================comp_op_adaptor_clip_to_dst_rgba
- template<class ColorT, class Order> struct comp_op_adaptor_clip_to_dst_rgba
- {
- typedef Order order_type;
- typedef ColorT color_type;
- typedef typename color_type::value_type value_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- static AGG_INLINE void blend_pix(unsigned op, value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned ca,
- unsigned cover)
- {
- cr = (cr * ca + base_mask) >> base_shift;
- cg = (cg * ca + base_mask) >> base_shift;
- cb = (cb * ca + base_mask) >> base_shift;
- unsigned da = p[Order::A];
- comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op]
- (p, (cr * da + base_mask) >> base_shift,
- (cg * da + base_mask) >> base_shift,
- (cb * da + base_mask) >> base_shift,
- (ca * da + base_mask) >> base_shift,
- cover);
- }
- };
-
- //================================================comp_op_adaptor_rgba_pre
- template<class ColorT, class Order> struct comp_op_adaptor_rgba_pre
- {
- typedef Order order_type;
- typedef ColorT color_type;
- typedef typename color_type::value_type value_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- static AGG_INLINE void blend_pix(unsigned op, value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned ca,
- unsigned cover)
- {
- comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op](p, cr, cg, cb, ca, cover);
- }
- };
-
- //=====================================comp_op_adaptor_clip_to_dst_rgba_pre
- template<class ColorT, class Order> struct comp_op_adaptor_clip_to_dst_rgba_pre
- {
- typedef Order order_type;
- typedef ColorT color_type;
- typedef typename color_type::value_type value_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- static AGG_INLINE void blend_pix(unsigned op, value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned ca,
- unsigned cover)
- {
- unsigned da = p[Order::A];
- comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op]
- (p, (cr * da + base_mask) >> base_shift,
- (cg * da + base_mask) >> base_shift,
- (cb * da + base_mask) >> base_shift,
- (ca * da + base_mask) >> base_shift,
- cover);
- }
- };
-
- //=======================================================comp_adaptor_rgba
- template<class BlenderPre> struct comp_adaptor_rgba
- {
- typedef typename BlenderPre::order_type order_type;
- typedef typename BlenderPre::color_type color_type;
- typedef typename color_type::value_type value_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- static AGG_INLINE void blend_pix(unsigned op, value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned ca,
- unsigned cover)
- {
- BlenderPre::blend_pix(p,
- (cr * ca + base_mask) >> base_shift,
- (cg * ca + base_mask) >> base_shift,
- (cb * ca + base_mask) >> base_shift,
- ca, cover);
- }
- };
-
- //==========================================comp_adaptor_clip_to_dst_rgba
- template<class BlenderPre> struct comp_adaptor_clip_to_dst_rgba
- {
- typedef typename BlenderPre::order_type order_type;
- typedef typename BlenderPre::color_type color_type;
- typedef typename color_type::value_type value_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- static AGG_INLINE void blend_pix(unsigned op, value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned ca,
- unsigned cover)
- {
- cr = (cr * ca + base_mask) >> base_shift;
- cg = (cg * ca + base_mask) >> base_shift;
- cb = (cb * ca + base_mask) >> base_shift;
- unsigned da = p[order_type::A];
- BlenderPre::blend_pix(p,
- (cr * da + base_mask) >> base_shift,
- (cg * da + base_mask) >> base_shift,
- (cb * da + base_mask) >> base_shift,
- (ca * da + base_mask) >> base_shift,
- cover);
- }
- };
-
- //======================================comp_adaptor_clip_to_dst_rgba_pre
- template<class BlenderPre> struct comp_adaptor_clip_to_dst_rgba_pre
- {
- typedef typename BlenderPre::order_type order_type;
- typedef typename BlenderPre::color_type color_type;
- typedef typename color_type::value_type value_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_mask = color_type::base_mask
- };
-
- static AGG_INLINE void blend_pix(unsigned op, value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned ca,
- unsigned cover)
- {
- unsigned da = p[order_type::A];
- BlenderPre::blend_pix(p,
- (cr * da + base_mask) >> base_shift,
- (cg * da + base_mask) >> base_shift,
- (cb * da + base_mask) >> base_shift,
- (ca * da + base_mask) >> base_shift,
- cover);
- }
- };
-
-
-
-
-
-
- //===============================================copy_or_blend_rgba_wrapper
- template<class Blender> struct copy_or_blend_rgba_wrapper
- {
- typedef typename Blender::color_type color_type;
- typedef typename Blender::order_type order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_scale = color_type::base_scale,
- base_mask = color_type::base_mask
- };
-
- //--------------------------------------------------------------------
- static AGG_INLINE void copy_or_blend_pix(value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned alpha)
- {
- if(alpha)
- {
- if(alpha == base_mask)
- {
- p[order_type::R] = cr;
- p[order_type::G] = cg;
- p[order_type::B] = cb;
- p[order_type::A] = base_mask;
- }
- else
- {
- Blender::blend_pix(p, cr, cg, cb, alpha);
- }
- }
- }
-
- //--------------------------------------------------------------------
- static AGG_INLINE void copy_or_blend_pix(value_type* p,
- unsigned cr, unsigned cg, unsigned cb,
- unsigned alpha,
- unsigned cover)
- {
- if(cover == 255)
- {
- copy_or_blend_pix(p, cr, cg, cb, alpha);
- }
- else
- {
- if(alpha)
- {
- alpha = (alpha * (cover + 1)) >> 8;
- if(alpha == base_mask)
- {
- p[order_type::R] = cr;
- p[order_type::G] = cg;
- p[order_type::B] = cb;
- p[order_type::A] = base_mask;
- }
- else
- {
- Blender::blend_pix(p, cr, cg, cb, alpha, cover);
- }
- }
- }
- }
- };
-
-
-
-
-
-
- //=================================================pixfmt_alpha_blend_rgba
- template<class Blender, class RenBuf, class PixelT = int32u>
- class pixfmt_alpha_blend_rgba
- {
- public:
- typedef RenBuf rbuf_type;
- typedef typename rbuf_type::row_data row_data;
- typedef PixelT pixel_type;
- typedef Blender blender_type;
- typedef typename blender_type::color_type color_type;
- typedef typename blender_type::order_type order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- typedef copy_or_blend_rgba_wrapper<blender_type> cob_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_scale = color_type::base_scale,
- base_mask = color_type::base_mask,
- pix_width = sizeof(pixel_type)
- };
-
- //--------------------------------------------------------------------
- pixfmt_alpha_blend_rgba() : m_rbuf(0) {}
- explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {}
- void attach(rbuf_type& rb) { m_rbuf = &rb; }
-
- //--------------------------------------------------------------------
- template<class PixFmt>
- 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)))
- {
- int stride = pixf.stride();
- m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
- (r.x2 - r.x1) + 1,
- (r.y2 - r.y1) + 1,
- stride);
- return true;
- }
- return false;
- }
-
- //--------------------------------------------------------------------
- AGG_INLINE unsigned width() const { return m_rbuf->width(); }
- AGG_INLINE unsigned height() const { return m_rbuf->height(); }
- AGG_INLINE int stride() const { return m_rbuf->stride(); }
-
- //--------------------------------------------------------------------
- AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
- AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
- AGG_INLINE 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) + x * pix_width;
- }
-
- AGG_INLINE const int8u* pix_ptr(int x, int y) const
- {
- return m_rbuf->row_ptr(y) + x * pix_width;
- }
-
-
- //--------------------------------------------------------------------
- AGG_INLINE static void make_pix(int8u* p, const color_type& c)
- {
- ((value_type*)p)[order_type::R] = c.r;
- ((value_type*)p)[order_type::G] = c.g;
- ((value_type*)p)[order_type::B] = c.b;
- ((value_type*)p)[order_type::A] = c.a;
- }
-
- //--------------------------------------------------------------------
- AGG_INLINE color_type pixel(int x, int y) const
- {
- const value_type* p = (const value_type*)m_rbuf->row_ptr(y);
- if(p)
- {
- p += x << 2;
- return color_type(p[order_type::R],
- p[order_type::G],
- p[order_type::B],
- p[order_type::A]);
- }
- return color_type::no_color();
- }
-
- //--------------------------------------------------------------------
- AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
- {
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2);
- p[order_type::R] = c.r;
- p[order_type::G] = c.g;
- p[order_type::B] = c.b;
- p[order_type::A] = c.a;
- }
-
- //--------------------------------------------------------------------
- AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
- {
- cob_type::copy_or_blend_pix(
- (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2),
- c.r, c.g, c.b, c.a,
- cover);
- }
-
-
- //--------------------------------------------------------------------
- AGG_INLINE void copy_hline(int x, int y,
- unsigned len,
- const color_type& c)
- {
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
- pixel_type v;
- ((value_type*)&v)[order_type::R] = c.r;
- ((value_type*)&v)[order_type::G] = c.g;
- ((value_type*)&v)[order_type::B] = c.b;
- ((value_type*)&v)[order_type::A] = c.a;
- do
- {
- *(pixel_type*)p = v;
- p += 4;
- }
- while(--len);
- }
-
-
- //--------------------------------------------------------------------
- AGG_INLINE void copy_vline(int x, int y,
- unsigned len,
- const color_type& c)
- {
- pixel_type v;
- ((value_type*)&v)[order_type::R] = c.r;
- ((value_type*)&v)[order_type::G] = c.g;
- ((value_type*)&v)[order_type::B] = c.b;
- ((value_type*)&v)[order_type::A] = c.a;
- do
- {
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
- *(pixel_type*)p = v;
- }
- while(--len);
- }
-
-
- //--------------------------------------------------------------------
- void blend_hline(int x, int y,
- unsigned len,
- const color_type& c,
- int8u cover)
- {
- if (c.a)
- {
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
- calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
- if(alpha == base_mask)
- {
- pixel_type v;
- ((value_type*)&v)[order_type::R] = c.r;
- ((value_type*)&v)[order_type::G] = c.g;
- ((value_type*)&v)[order_type::B] = c.b;
- ((value_type*)&v)[order_type::A] = c.a;
- do
- {
- *(pixel_type*)p = v;
- p += 4;
- }
- while(--len);
- }
- else
- {
- if(cover == 255)
- {
- do
- {
- blender_type::blend_pix(p, c.r, c.g, c.b, alpha);
- p += 4;
- }
- while(--len);
- }
- else
- {
- do
- {
- blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover);
- p += 4;
- }
- while(--len);
- }
- }
- }
- }
-
-
- //--------------------------------------------------------------------
- void blend_vline(int x, int y,
- unsigned len,
- const color_type& c,
- int8u cover)
- {
- if (c.a)
- {
- value_type* p;
- calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
- if(alpha == base_mask)
- {
- pixel_type v;
- ((value_type*)&v)[order_type::R] = c.r;
- ((value_type*)&v)[order_type::G] = c.g;
- ((value_type*)&v)[order_type::B] = c.b;
- ((value_type*)&v)[order_type::A] = c.a;
- do
- {
- p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
- *(pixel_type*)p = v;
- }
- while(--len);
- }
- else
- {
- if(cover == 255)
- {
- do
- {
- p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
- blender_type::blend_pix(p, c.r, c.g, c.b, alpha);
- }
- while(--len);
- }
- else
- {
- do
- {
- p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
- blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover);
- }
- while(--len);
- }
- }
- }
- }
-
-
- //--------------------------------------------------------------------
- void blend_solid_hspan(int x, int y,
- unsigned len,
- const color_type& c,
- const int8u* covers)
- {
- if (c.a)
- {
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
- do
- {
- calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
- if(alpha == base_mask)
- {
- p[order_type::R] = c.r;
- p[order_type::G] = c.g;
- p[order_type::B] = c.b;
- p[order_type::A] = base_mask;
- }
- else
- {
- blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers);
- }
- p += 4;
- ++covers;
- }
- while(--len);
- }
- }
-
-
- //--------------------------------------------------------------------
- void blend_solid_vspan(int x, int y,
- unsigned len,
- const color_type& c,
- const int8u* covers)
- {
- if (c.a)
- {
- do
- {
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
- calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
- if(alpha == base_mask)
- {
- p[order_type::R] = c.r;
- p[order_type::G] = c.g;
- p[order_type::B] = c.b;
- p[order_type::A] = base_mask;
- }
- else
- {
- blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers);
- }
- ++covers;
- }
- while(--len);
- }
- }
-
-
- //--------------------------------------------------------------------
- void copy_color_hspan(int x, int y,
- unsigned len,
- const color_type* colors)
- {
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
- do
- {
- p[order_type::R] = colors->r;
- p[order_type::G] = colors->g;
- p[order_type::B] = colors->b;
- p[order_type::A] = colors->a;
- ++colors;
- p += 4;
- }
- while(--len);
- }
-
-
- //--------------------------------------------------------------------
- void copy_color_vspan(int x, int y,
- unsigned len,
- const color_type* colors)
- {
- do
- {
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
- p[order_type::R] = colors->r;
- p[order_type::G] = colors->g;
- p[order_type::B] = colors->b;
- p[order_type::A] = colors->a;
- ++colors;
- }
- while(--len);
- }
-
-
- //--------------------------------------------------------------------
- void blend_color_hspan(int x, int y,
- unsigned len,
- const color_type* colors,
- const int8u* covers,
- int8u cover)
- {
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
- if(covers)
- {
- do
- {
- cob_type::copy_or_blend_pix(p,
- colors->r,
- colors->g,
- colors->b,
- colors->a,
- *covers++);
- p += 4;
- ++colors;
- }
- while(--len);
- }
- else
- {
- if(cover == 255)
- {
- do
- {
- cob_type::copy_or_blend_pix(p,
- colors->r,
- colors->g,
- colors->b,
- colors->a);
- p += 4;
- ++colors;
- }
- while(--len);
- }
- else
- {
- do
- {
- cob_type::copy_or_blend_pix(p,
- colors->r,
- colors->g,
- colors->b,
- colors->a,
- cover);
- p += 4;
- ++colors;
- }
- while(--len);
- }
- }
- }
-
-
-
- //--------------------------------------------------------------------
- void blend_color_vspan(int x, int y,
- unsigned len,
- const color_type* colors,
- const int8u* covers,
- int8u cover)
- {
- value_type* p;
- if(covers)
- {
- do
- {
- p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
- cob_type::copy_or_blend_pix(p,
- colors->r,
- colors->g,
- colors->b,
- colors->a,
- *covers++);
- ++colors;
- }
- while(--len);
- }
- else
- {
- if(cover == 255)
- {
- do
- {
- p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
- cob_type::copy_or_blend_pix(p,
- colors->r,
- colors->g,
- colors->b,
- colors->a);
- ++colors;
- }
- while(--len);
- }
- else
- {
- do
- {
- p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
- cob_type::copy_or_blend_pix(p,
- colors->r,
- colors->g,
- colors->b,
- colors->a,
- cover);
- ++colors;
- }
- while(--len);
- }
- }
- }
-
- //--------------------------------------------------------------------
- template<class Function> void for_each_pixel(Function f)
- {
- unsigned y;
- for(y = 0; y < height(); ++y)
- {
- row_data r = m_rbuf->row(y);
- if(r.ptr)
- {
- unsigned len = r.x2 - r.x1 + 1;
- value_type* p =
- (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2);
- do
- {
- f(p);
- p += 4;
- }
- while(--len);
- }
- }
- }
-
- //--------------------------------------------------------------------
- void premultiply()
- {
- for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply);
- }
-
- //--------------------------------------------------------------------
- void demultiply()
- {
- for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply);
- }
-
- //--------------------------------------------------------------------
- template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
- {
- for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g));
- }
-
- //--------------------------------------------------------------------
- template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
- {
- for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g));
- }
-
- //--------------------------------------------------------------------
- template<class RenBuf2> void copy_from(const RenBuf2& from,
- int xdst, int ydst,
- int xsrc, int ysrc,
- unsigned len)
- {
- const int8u* p = from.row_ptr(ysrc);
- if(p)
- {
- memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
- p + xsrc * pix_width,
- len * pix_width);
- }
- }
-
- //--------------------------------------------------------------------
- template<class SrcPixelFormatRenderer>
- void blend_from(const SrcPixelFormatRenderer& from,
- int xdst, int ydst,
- int xsrc, int ysrc,
- unsigned len,
- int8u cover)
- {
- typedef typename SrcPixelFormatRenderer::order_type src_order;
- const value_type* psrc = (value_type*)from.row_ptr(ysrc);
- if(psrc)
- {
- psrc += xsrc << 2;
- value_type* pdst =
- (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
- int incp = 4;
- if(xdst > xsrc)
- {
- psrc += (len-1) << 2;
- pdst += (len-1) << 2;
- incp = -4;
- }
-
- if(cover == 255)
- {
- do
- {
- cob_type::copy_or_blend_pix(pdst,
- psrc[src_order::R],
- psrc[src_order::G],
- psrc[src_order::B],
- psrc[src_order::A]);
- psrc += incp;
- pdst += incp;
- }
- while(--len);
- }
- else
- {
- do
- {
- cob_type::copy_or_blend_pix(pdst,
- psrc[src_order::R],
- psrc[src_order::G],
- psrc[src_order::B],
- psrc[src_order::A],
- cover);
- psrc += incp;
- pdst += incp;
- }
- while(--len);
- }
- }
- }
-
- //--------------------------------------------------------------------
- template<class SrcPixelFormatRenderer>
- void blend_from_color(const SrcPixelFormatRenderer& from,
- const color_type& color,
- int xdst, int ydst,
- int xsrc, int ysrc,
- unsigned len,
- int8u cover)
- {
- typedef typename SrcPixelFormatRenderer::value_type src_value_type;
- const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
- if(psrc)
- {
- value_type* pdst =
- (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
- do
- {
- cob_type::copy_or_blend_pix(pdst,
- color.r, color.g, color.b, color.a,
- (*psrc * cover + base_mask) >> base_shift);
- ++psrc;
- pdst += 4;
- }
- while(--len);
- }
- }
-
- //--------------------------------------------------------------------
- template<class SrcPixelFormatRenderer>
- void blend_from_lut(const SrcPixelFormatRenderer& from,
- const color_type* color_lut,
- int xdst, int ydst,
- int xsrc, int ysrc,
- unsigned len,
- int8u cover)
- {
- typedef typename SrcPixelFormatRenderer::value_type src_value_type;
- const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
- if(psrc)
- {
- value_type* pdst =
- (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
-
- if(cover == 255)
- {
- do
- {
- const color_type& color = color_lut[*psrc];
- cob_type::copy_or_blend_pix(pdst,
- color.r, color.g, color.b, color.a);
- ++psrc;
- pdst += 4;
- }
- while(--len);
- }
- else
- {
- do
- {
- const color_type& color = color_lut[*psrc];
- cob_type::copy_or_blend_pix(pdst,
- color.r, color.g, color.b, color.a,
- cover);
- ++psrc;
- pdst += 4;
- }
- while(--len);
- }
- }
- }
-
- private:
- rbuf_type* m_rbuf;
- };
-
-
-
-
- //================================================pixfmt_custom_blend_rgba
- template<class Blender, class RenBuf> class pixfmt_custom_blend_rgba
- {
- public:
- typedef RenBuf rbuf_type;
- typedef typename rbuf_type::row_data row_data;
- typedef Blender blender_type;
- typedef typename blender_type::color_type color_type;
- typedef typename blender_type::order_type order_type;
- typedef typename color_type::value_type value_type;
- typedef typename color_type::calc_type calc_type;
- enum base_scale_e
- {
- base_shift = color_type::base_shift,
- base_scale = color_type::base_scale,
- base_mask = color_type::base_mask,
- pix_width = sizeof(value_type) * 4
- };
-
-
- //--------------------------------------------------------------------
- pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {}
- explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) :
- m_rbuf(&rb),
- m_comp_op(comp_op)
- {}
- void attach(rbuf_type& rb) { m_rbuf = &rb; }
-
- //--------------------------------------------------------------------
- template<class PixFmt>
- 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)))
- {
- int stride = pixf.stride();
- m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
- (r.x2 - r.x1) + 1,
- (r.y2 - r.y1) + 1,
- stride);
- return true;
- }
- return false;
- }
-
- //--------------------------------------------------------------------
- AGG_INLINE unsigned width() const { return m_rbuf->width(); }
- AGG_INLINE unsigned height() const { return m_rbuf->height(); }
- AGG_INLINE int stride() const { return m_rbuf->stride(); }
-
- //--------------------------------------------------------------------
- AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
- AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
- AGG_INLINE 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) + x * pix_width;
- }
-
- AGG_INLINE const int8u* pix_ptr(int x, int y) const
- {
- return m_rbuf->row_ptr(y) + x * pix_width;
- }
-
- //--------------------------------------------------------------------
- void comp_op(unsigned op) { m_comp_op = op; }
- unsigned comp_op() const { return m_comp_op; }
-
- //--------------------------------------------------------------------
- AGG_INLINE static void make_pix(int8u* p, const color_type& c)
- {
- ((value_type*)p)[order_type::R] = c.r;
- ((value_type*)p)[order_type::G] = c.g;
- ((value_type*)p)[order_type::B] = c.b;
- ((value_type*)p)[order_type::A] = c.a;
- }
-
- //--------------------------------------------------------------------
- color_type pixel(int x, int y) const
- {
- const value_type* p = (value_type*)m_rbuf->row_ptr(y) + (x << 2);
- return color_type(p[order_type::R],
- p[order_type::G],
- p[order_type::B],
- p[order_type::A]);
- }
-
- //--------------------------------------------------------------------
- void copy_pixel(int x, int y, const color_type& c)
- {
- blender_type::blend_pix(
- m_comp_op,
- (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2),
- c.r, c.g, c.b, c.a, 255);
- }
-
- //--------------------------------------------------------------------
- void blend_pixel(int x, int y, const color_type& c, int8u cover)
- {
- blender_type::blend_pix(
- m_comp_op,
- (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2),
- c.r, c.g, c.b, c.a,
- cover);
- }
-
- //--------------------------------------------------------------------
- void copy_hline(int x, int y, unsigned len, const color_type& c)
- {
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);;
- do
- {
- blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, 255);
- p += 4;
- }
- while(--len);
- }
-
- //--------------------------------------------------------------------
- void copy_vline(int x, int y, unsigned len, const color_type& c)
- {
- do
- {
- blender_type::blend_pix(
- m_comp_op,
- (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2),
- c.r, c.g, c.b, c.a, 255);
- }
- while(--len);
- }
-
- //--------------------------------------------------------------------
- void blend_hline(int x, int y, unsigned len,
- const color_type& c, int8u cover)
- {
-
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
- do
- {
- blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, cover);
- p += 4;
- }
- while(--len);
- }
-
- //--------------------------------------------------------------------
- void blend_vline(int x, int y, unsigned len,
- const color_type& c, int8u cover)
- {
-
- do
- {
- blender_type::blend_pix(
- m_comp_op,
- (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2),
- c.r, c.g, c.b, c.a,
- cover);
- }
- while(--len);
- }
-
- //--------------------------------------------------------------------
- void blend_solid_hspan(int x, int y, unsigned len,
- const color_type& c, const int8u* covers)
- {
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
- do
- {
- blender_type::blend_pix(m_comp_op,
- p, c.r, c.g, c.b, c.a,
- *covers++);
- p += 4;
- }
- while(--len);
- }
-
- //--------------------------------------------------------------------
- void blend_solid_vspan(int x, int y, unsigned len,
- const color_type& c, const int8u* covers)
- {
- do
- {
- blender_type::blend_pix(
- m_comp_op,
- (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2),
- c.r, c.g, c.b, c.a,
- *covers++);
- }
- while(--len);
- }
-
- //--------------------------------------------------------------------
- void copy_color_hspan(int x, int y,
- unsigned len,
- const color_type* colors)
- {
-
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
- do
- {
- p[order_type::R] = colors->r;
- p[order_type::G] = colors->g;
- p[order_type::B] = colors->b;
- p[order_type::A] = colors->a;
- ++colors;
- p += 4;
- }
- while(--len);
- }
-
- //--------------------------------------------------------------------
- void copy_color_vspan(int x, int y,
- unsigned len,
- const color_type* colors)
- {
- do
- {
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2);
- p[order_type::R] = colors->r;
- p[order_type::G] = colors->g;
- p[order_type::B] = colors->b;
- p[order_type::A] = colors->a;
- ++colors;
- }
- while(--len);
- }
-
- //--------------------------------------------------------------------
- void blend_color_hspan(int x, int y, unsigned len,
- const color_type* colors,
- const int8u* covers,
- int8u cover)
- {
- value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);
- do
- {
- blender_type::blend_pix(m_comp_op,
- p,
- colors->r,
- colors->g,
- colors->b,
- colors->a,
- covers ? *covers++ : cover);
- p += 4;
- ++colors;
- }
- while(--len);
- }
-
- //--------------------------------------------------------------------
- void blend_color_vspan(int x, int y, unsigned len,
- const color_type* colors,
- const int8u* covers,
- int8u cover)
- {
- do
- {
- blender_type::blend_pix(
- m_comp_op,
- (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2),
- colors->r,
- colors->g,
- colors->b,
- colors->a,
- covers ? *covers++ : cover);
- ++colors;
- }
- while(--len);
-
- }
-
- //--------------------------------------------------------------------
- template<class Function> void for_each_pixel(Function f)
- {
- unsigned y;
- for(y = 0; y < height(); ++y)
- {
- row_data r = m_rbuf->row(y);
- if(r.ptr)
- {
- unsigned len = r.x2 - r.x1 + 1;
- value_type* p =
- (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2);
- do
- {
- f(p);
- p += 4;
- }
- while(--len);
- }
- }
- }
-
- //--------------------------------------------------------------------
- void premultiply()
- {
- for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply);
- }
-
- //--------------------------------------------------------------------
- void demultiply()
- {
- for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply);
- }
-
- //--------------------------------------------------------------------
- template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
- {
- for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g));
- }
-
- //--------------------------------------------------------------------
- template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
- {
- for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g));
- }
-
- //--------------------------------------------------------------------
- template<class RenBuf2> void copy_from(const RenBuf2& from,
- int xdst, int ydst,
- int xsrc, int ysrc,
- unsigned len)
- {
- const int8u* p = from.row_ptr(ysrc);
- if(p)
- {
- memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
- p + xsrc * pix_width,
- len * pix_width);
- }
- }
-
- //--------------------------------------------------------------------
- template<class SrcPixelFormatRenderer>
- void blend_from(const SrcPixelFormatRenderer& from,
- int xdst, int ydst,
- int xsrc, int ysrc,
- unsigned len,
- int8u cover)
- {
- typedef typename SrcPixelFormatRenderer::order_type src_order;
- const value_type* psrc = (const value_type*)from.row_ptr(ysrc);
- if(psrc)
- {
- psrc += xsrc << 2;
- value_type* pdst =
- (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
-
- int incp = 4;
- if(xdst > xsrc)
- {
- psrc += (len-1) << 2;
- pdst += (len-1) << 2;
- incp = -4;
- }
-
- do
- {
- blender_type::blend_pix(m_comp_op,
- pdst,
- psrc[src_order::R],
- psrc[src_order::G],
- psrc[src_order::B],
- psrc[src_order::A],
- cover);
- psrc += incp;
- pdst += incp;
- }
- while(--len);
- }
- }
-
- //--------------------------------------------------------------------
- template<class SrcPixelFormatRenderer>
- void blend_from_color(const SrcPixelFormatRenderer& from,
- const color_type& color,
- int xdst, int ydst,
- int xsrc, int ysrc,
- unsigned len,
- int8u cover)
- {
- typedef typename SrcPixelFormatRenderer::value_type src_value_type;
- const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
- if(psrc)
- {
- value_type* pdst =
- (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
- do
- {
- blender_type::blend_pix(m_comp_op,
- pdst,
- color.r, color.g, color.b, color.a,
- (*psrc * cover + base_mask) >> base_shift);
- ++psrc;
- pdst += 4;
- }
- while(--len);
- }
- }
-
- //--------------------------------------------------------------------
- template<class SrcPixelFormatRenderer>
- void blend_from_lut(const SrcPixelFormatRenderer& from,
- const color_type* color_lut,
- int xdst, int ydst,
- int xsrc, int ysrc,
- unsigned len,
- int8u cover)
- {
- typedef typename SrcPixelFormatRenderer::value_type src_value_type;
- const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
- if(psrc)
- {
- value_type* pdst =
- (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2);
- do
- {
- const color_type& color = color_lut[*psrc];
- blender_type::blend_pix(m_comp_op,
- pdst,
- color.r, color.g, color.b, color.a,
- cover);
- ++psrc;
- pdst += 4;
- }
- while(--len);
- }
- }
-
- private:
- rbuf_type* m_rbuf;
- unsigned m_comp_op;
- };
-
-
-
-
- //-----------------------------------------------------------------------
- typedef blender_rgba<rgba8, order_rgba> blender_rgba32; //----blender_rgba32
- typedef blender_rgba<rgba8, order_argb> blender_argb32; //----blender_argb32
- typedef blender_rgba<rgba8, order_abgr> blender_abgr32; //----blender_abgr32
- typedef blender_rgba<rgba8, order_bgra> blender_bgra32; //----blender_bgra32
-
- typedef blender_rgba_pre<rgba8, order_rgba> blender_rgba32_pre; //----blender_rgba32_pre
- typedef blender_rgba_pre<rgba8, order_argb> blender_argb32_pre; //----blender_argb32_pre
- typedef blender_rgba_pre<rgba8, order_abgr> blender_abgr32_pre; //----blender_abgr32_pre
- typedef blender_rgba_pre<rgba8, order_bgra> blender_bgra32_pre; //----blender_bgra32_pre
-
- typedef blender_rgba_plain<rgba8, order_rgba> blender_rgba32_plain; //----blender_rgba32_plain
- typedef blender_rgba_plain<rgba8, order_argb> blender_argb32_plain; //----blender_argb32_plain
- typedef blender_rgba_plain<rgba8, order_abgr> blender_abgr32_plain; //----blender_abgr32_plain
- typedef blender_rgba_plain<rgba8, order_bgra> blender_bgra32_plain; //----blender_bgra32_plain
-
- typedef blender_rgba<rgba16, order_rgba> blender_rgba64; //----blender_rgba64
- typedef blender_rgba<rgba16, order_argb> blender_argb64; //----blender_argb64
- typedef blender_rgba<rgba16, order_abgr> blender_abgr64; //----blender_abgr64
- typedef blender_rgba<rgba16, order_bgra> blender_bgra64; //----blender_bgra64
-
- typedef blender_rgba_pre<rgba16, order_rgba> blender_rgba64_pre; //----blender_rgba64_pre
- typedef blender_rgba_pre<rgba16, order_argb> blender_argb64_pre; //----blender_argb64_pre
- typedef blender_rgba_pre<rgba16, order_abgr> blender_abgr64_pre; //----blender_abgr64_pre
- typedef blender_rgba_pre<rgba16, order_bgra> blender_bgra64_pre; //----blender_bgra64_pre
-
-
- //-----------------------------------------------------------------------
- typedef int32u pixel32_type;
- typedef pixfmt_alpha_blend_rgba<blender_rgba32, rendering_buffer, pixel32_type> pixfmt_rgba32; //----pixfmt_rgba32
- typedef pixfmt_alpha_blend_rgba<blender_argb32, rendering_buffer, pixel32_type> pixfmt_argb32; //----pixfmt_argb32
- typedef pixfmt_alpha_blend_rgba<blender_abgr32, rendering_buffer, pixel32_type> pixfmt_abgr32; //----pixfmt_abgr32
- typedef pixfmt_alpha_blend_rgba<blender_bgra32, rendering_buffer, pixel32_type> pixfmt_bgra32; //----pixfmt_bgra32
-
- typedef pixfmt_alpha_blend_rgba<blender_rgba32_pre, rendering_buffer, pixel32_type> pixfmt_rgba32_pre; //----pixfmt_rgba32_pre
- typedef pixfmt_alpha_blend_rgba<blender_argb32_pre, rendering_buffer, pixel32_type> pixfmt_argb32_pre; //----pixfmt_argb32_pre
- typedef pixfmt_alpha_blend_rgba<blender_abgr32_pre, rendering_buffer, pixel32_type> pixfmt_abgr32_pre; //----pixfmt_abgr32_pre
- typedef pixfmt_alpha_blend_rgba<blender_bgra32_pre, rendering_buffer, pixel32_type> pixfmt_bgra32_pre; //----pixfmt_bgra32_pre
-
- typedef pixfmt_alpha_blend_rgba<blender_rgba32_plain, rendering_buffer, pixel32_type> pixfmt_rgba32_plain; //----pixfmt_rgba32_plain
- typedef pixfmt_alpha_blend_rgba<blender_argb32_plain, rendering_buffer, pixel32_type> pixfmt_argb32_plain; //----pixfmt_argb32_plain
- typedef pixfmt_alpha_blend_rgba<blender_abgr32_plain, rendering_buffer, pixel32_type> pixfmt_abgr32_plain; //----pixfmt_abgr32_plain
- typedef pixfmt_alpha_blend_rgba<blender_bgra32_plain, rendering_buffer, pixel32_type> pixfmt_bgra32_plain; //----pixfmt_bgra32_plain
-
- struct pixel64_type { int16u c[4]; };
- typedef pixfmt_alpha_blend_rgba<blender_rgba64, rendering_buffer, pixel64_type> pixfmt_rgba64; //----pixfmt_rgba64
- typedef pixfmt_alpha_blend_rgba<blender_argb64, rendering_buffer, pixel64_type> pixfmt_argb64; //----pixfmt_argb64
- typedef pixfmt_alpha_blend_rgba<blender_abgr64, rendering_buffer, pixel64_type> pixfmt_abgr64; //----pixfmt_abgr64
- typedef pixfmt_alpha_blend_rgba<blender_bgra64, rendering_buffer, pixel64_type> pixfmt_bgra64; //----pixfmt_bgra64
-
- typedef pixfmt_alpha_blend_rgba<blender_rgba64_pre, rendering_buffer, pixel64_type> pixfmt_rgba64_pre; //----pixfmt_rgba64_pre
- typedef pixfmt_alpha_blend_rgba<blender_argb64_pre, rendering_buffer, pixel64_type> pixfmt_argb64_pre; //----pixfmt_argb64_pre
- typedef pixfmt_alpha_blend_rgba<blender_abgr64_pre, rendering_buffer, pixel64_type> pixfmt_abgr64_pre; //----pixfmt_abgr64_pre
- typedef pixfmt_alpha_blend_rgba<blender_bgra64_pre, rendering_buffer, pixel64_type> pixfmt_bgra64_pre; //----pixfmt_bgra64_pre
-}
-
-#endif
-
diff --git a/src/agg/agg_rasterizer_cells_aa.h b/src/agg/agg_rasterizer_cells_aa.h
index d3bb1387c..1147148fa 100644
--- a/src/agg/agg_rasterizer_cells_aa.h
+++ b/src/agg/agg_rasterizer_cells_aa.h
@@ -1,25 +1,12 @@
//----------------------------------------------------------------------------
-// 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.
+// 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,
@@ -27,6 +14,10 @@
// 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
@@ -35,12 +26,12 @@
// PostScript and PDF technology for software developers.
//
//----------------------------------------------------------------------------
-
#ifndef AGG_RASTERIZER_CELLS_AA_INCLUDED
#define AGG_RASTERIZER_CELLS_AA_INCLUDED
#include <string.h>
-#include <math.h>
+#include <cstdlib>
+#include <limits>
#include "agg_math.h"
#include "agg_array.h"
@@ -160,10 +151,10 @@ namespace agg
m_curr_cell_ptr(0),
m_sorted_cells(),
m_sorted_y(),
- m_min_x(0x7FFFFFFF),
- m_min_y(0x7FFFFFFF),
- m_max_x(-0x7FFFFFFF),
- m_max_y(-0x7FFFFFFF),
+ 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_sorted(false)
{
m_style_cell.initial();
@@ -179,10 +170,10 @@ namespace agg
m_curr_cell.initial();
m_style_cell.initial();
m_sorted = false;
- m_min_x = 0x7FFFFFFF;
- m_min_y = 0x7FFFFFFF;
- m_max_x = -0x7FFFFFFF;
- m_max_y = -0x7FFFFFFF;
+ 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();
}
//------------------------------------------------------------------------
@@ -227,7 +218,8 @@ namespace agg
int fx1 = x1 & poly_subpixel_mask;
int fx2 = x2 & poly_subpixel_mask;
- int delta, p, first, dx;
+ int delta, p, first;
+ long long dx;
int incr, lift, mod, rem;
//trivial case. Happens often
@@ -252,7 +244,7 @@ namespace agg
first = poly_subpixel_scale;
incr = 1;
- dx = x2 - x1;
+ dx = (long long)x2 - (long long)x1;
if(dx < 0)
{
@@ -262,13 +254,13 @@ namespace agg
dx = -dx;
}
- delta = p / dx;
- mod = p % dx;
+ delta = (int)(p / dx);
+ mod = (int)(p % dx);
if(mod < 0)
{
delta--;
- mod += dx;
+ mod += static_cast<int>(dx);
}
m_curr_cell.cover += delta;
@@ -281,16 +273,16 @@ namespace agg
if(ex1 != ex2)
{
p = poly_subpixel_scale * (y2 - y1 + delta);
- lift = p / dx;
- rem = p % dx;
+ lift = (int)(p / dx);
+ rem = (int)(p % dx);
if (rem < 0)
{
lift--;
- rem += dx;
+ rem += static_cast<int>(dx);
}
- mod -= dx;
+ mod -= static_cast<int>(dx);
while (ex1 != ex2)
{
@@ -298,7 +290,7 @@ namespace agg
mod += rem;
if(mod >= 0)
{
- mod -= dx;
+ mod -= static_cast<int>(dx);
delta++;
}
@@ -327,17 +319,17 @@ namespace agg
{
enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift };
- int dx = x2 - x1;
+ long long dx = (long long)x2 - (long long)x1;
if(dx >= dx_limit || dx <= -dx_limit)
{
- int cx = (x1 + x2) >> 1;
- int cy = (y1 + y2) >> 1;
+ int cx = (int)(((long long)x1 + (long long)x2) >> 1);
+ int cy = (int)(((long long)y1 + (long long)y2) >> 1);
line(x1, y1, cx, cy);
line(cx, cy, x2, y2);
}
- int dy = y2 - y1;
+ long long dy = (long long)y2 - (long long)y1;
int ex1 = x1 >> poly_subpixel_shift;
int ex2 = x2 >> poly_subpixel_shift;
int ey1 = y1 >> poly_subpixel_shift;
@@ -346,7 +338,8 @@ namespace agg
int fy2 = y2 & poly_subpixel_mask;
int x_from, x_to;
- int p, rem, mod, lift, delta, first, incr;
+ int rem, mod, lift, delta, first, incr;
+ long long p;
if(ex1 < m_min_x) m_min_x = ex1;
if(ex1 > m_max_x) m_max_x = ex1;
@@ -423,13 +416,13 @@ namespace agg
dy = -dy;
}
- delta = p / dy;
- mod = p % dy;
+ delta = (int)(p / dy);
+ mod = (int)(p % dy);
if(mod < 0)
{
delta--;
- mod += dy;
+ mod += static_cast<int>(dy);
}
x_from = x1 + delta;
@@ -441,15 +434,15 @@ namespace agg
if(ey1 != ey2)
{
p = poly_subpixel_scale * dx;
- lift = p / dy;
- rem = p % dy;
+ lift = (int)(p / dy);
+ rem = (int)(p % dy);
if(rem < 0)
{
lift--;
- rem += dy;
+ rem += static_cast<int>(dy);
}
- mod -= dy;
+ mod -= static_cast<int>(dy);
while(ey1 != ey2)
{
@@ -457,7 +450,7 @@ namespace agg
mod += rem;
if (mod >= 0)
{
- mod -= dy;
+ mod -= static_cast<int>(dy);
delta++;
}
@@ -635,8 +628,8 @@ namespace agg
if(m_sorted) return; //Perform sort only the first time.
add_curr_cell();
- m_curr_cell.x = 0x7FFFFFFF;
- m_curr_cell.y = 0x7FFFFFFF;
+ m_curr_cell.x = std::numeric_limits<int>::max();
+ m_curr_cell.y = std::numeric_limits<int>::max();
m_curr_cell.cover = 0;
m_curr_cell.area = 0;
@@ -664,12 +657,13 @@ 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 >> cell_block_shift;
+ unsigned nb = m_num_cells;
unsigned i;
- while(nb--)
+ while(nb)
{
cell_ptr = *block_ptr++;
- i = cell_block_size;
+ i = (nb > cell_block_size) ? unsigned(cell_block_size) : nb;
+ nb -= i;
while(i--)
{
m_sorted_y[cell_ptr->y - m_min_y].start++;
@@ -677,14 +671,6 @@ 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++)
@@ -696,12 +682,13 @@ namespace agg
// Fill the cell pointer array sorted by Y
block_ptr = m_cells;
- nb = m_num_cells >> cell_block_shift;
- while(nb--)
+ nb = m_num_cells;
+ while(nb)
{
cell_ptr = *block_ptr++;
- i = cell_block_size;
- while(i--)
+ i = (nb > cell_block_size) ? unsigned(cell_block_size) : nb;
+ nb -= i;
+ 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;
@@ -710,16 +697,6 @@ 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++)
{
diff --git a/src/agg/agg_rasterizer_scanline_aa.h b/src/agg/agg_rasterizer_scanline_aa.h
index 80e138c2e..ffc2ddf94 100644
--- a/src/agg/agg_rasterizer_scanline_aa.h
+++ b/src/agg/agg_rasterizer_scanline_aa.h
@@ -1,25 +1,12 @@
//----------------------------------------------------------------------------
-// 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.
+// 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,
@@ -27,6 +14,10 @@
// 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
@@ -35,47 +26,17 @@
// 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
diff --git a/src/agg/agg_rasterizer_scanline_aa_nogamma.h b/src/agg/agg_rasterizer_scanline_aa_nogamma.h
new file mode 100644
index 000000000..9a809aa5a
--- /dev/null
+++ b/src/agg/agg_rasterizer_scanline_aa_nogamma.h
@@ -0,0 +1,483 @@
+//----------------------------------------------------------------------------
+// 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
+
diff --git a/src/agg/agg_rasterizer_sl_clip.h b/src/agg/agg_rasterizer_sl_clip.h
index cdfee1af0..3a7f3a103 100644
--- a/src/agg/agg_rasterizer_sl_clip.h
+++ b/src/agg/agg_rasterizer_sl_clip.h
@@ -1,27 +1,17 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
//----------------------------------------------------------------------------
-
#ifndef AGG_RASTERIZER_SL_CLIP_INCLUDED
#define AGG_RASTERIZER_SL_CLIP_INCLUDED
@@ -327,7 +317,7 @@ namespace agg
rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {}
void reset_clipping() {}
- void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) {}
+ void clip_box(coord_type, coord_type, coord_type, coord_type) {}
void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; }
template<class Rasterizer>
diff --git a/src/agg/agg_renderer_base.h b/src/agg/agg_renderer_base.h
index 180894465..527c62f78 100644
--- a/src/agg/agg_renderer_base.h
+++ b/src/agg/agg_renderer_base.h
@@ -1,25 +1,20 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// class renderer_base
+//
//----------------------------------------------------------------------------
#ifndef AGG_RENDERER_BASE_INCLUDED
@@ -140,6 +135,19 @@ 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)
{
if(inbox(x, y))
diff --git a/src/agg/agg_renderer_scanline.h b/src/agg/agg_renderer_scanline.h
index c3bb6f05b..311e9f739 100644
--- a/src/agg/agg_renderer_scanline.h
+++ b/src/agg/agg_renderer_scanline.h
@@ -1,30 +1,23 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
//----------------------------------------------------------------------------
#ifndef AGG_RENDERER_SCANLINE_INCLUDED
#define AGG_RENDERER_SCANLINE_INCLUDED
+#include <limits>
+#include <cstdlib>
#include "agg_basics.h"
#include "agg_renderer_base.h"
@@ -74,7 +67,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))
@@ -754,7 +747,7 @@ namespace agg
0,
sl_len * sizeof(cover_type));
- int sl_y = 0x7FFFFFFF;
+ int sl_y = std::numeric_limits<int>::max();
unsigned i;
for(i = 0; i < num_styles; i++)
{
diff --git a/src/agg/agg_rendering_buffer.h b/src/agg/agg_rendering_buffer.h
index 3a39caa81..0eff6ff27 100644
--- a/src/agg/agg_rendering_buffer.h
+++ b/src/agg/agg_rendering_buffer.h
@@ -1,25 +1,20 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// class rendering_buffer
+//
//----------------------------------------------------------------------------
#ifndef AGG_RENDERING_BUFFER_INCLUDED
@@ -61,14 +56,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;
+ }
}
//--------------------------------------------------------------------
@@ -83,13 +78,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));
}
diff --git a/src/agg/agg_scanline_p.h b/src/agg/agg_scanline_p.h
index 0c29638d6..1d1cbe72f 100644
--- a/src/agg/agg_scanline_p.h
+++ b/src/agg/agg_scanline_p.h
@@ -1,25 +1,20 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// Class scanline_p - a general purpose scanline container with packed spans.
+//
//----------------------------------------------------------------------------
//
// Adaptation for 32-bit screen coordinates (scanline32_p) has been sponsored by
diff --git a/src/agg/agg_shorten_path.h b/src/agg/agg_shorten_path.h
deleted file mode 100644
index ba72b947b..000000000
--- a/src/agg/agg_shorten_path.h
+++ /dev/null
@@ -1,75 +0,0 @@
-//----------------------------------------------------------------------------
-// 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
diff --git a/src/agg/agg_trans_affine.h b/src/agg/agg_trans_affine.h
index a662099f2..1a6116388 100644
--- a/src/agg/agg_trans_affine.h
+++ b/src/agg/agg_trans_affine.h
@@ -1,27 +1,21 @@
//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
+// 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://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.
+// http://www.antigrain.com
+//----------------------------------------------------------------------------
+//
+// Affine transformation classes.
+//
//----------------------------------------------------------------------------
-
#ifndef AGG_TRANS_AFFINE_INCLUDED
#define AGG_TRANS_AFFINE_INCLUDED
@@ -217,14 +211,14 @@ namespace agg
// Multiply the matrix by another one and return
// the result in a separete matrix.
- trans_affine operator * (const trans_affine& m)
+ trans_affine operator * (const trans_affine& m) const
{
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)
+ trans_affine operator / (const trans_affine& m) const
{
return trans_affine(*this).multiply_inv(m);
}
@@ -298,7 +292,7 @@ namespace agg
//------------------------------------------------------------------------
inline void trans_affine::transform(double* x, double* y) const
{
- register double tmp = *x;
+ double tmp = *x;
*x = tmp * sx + *y * shx + tx;
*y = tmp * shy + *y * sy + ty;
}
@@ -306,7 +300,7 @@ namespace agg
//------------------------------------------------------------------------
inline void trans_affine::transform_2x2(double* x, double* y) const
{
- register double tmp = *x;
+ double tmp = *x;
*x = tmp * sx + *y * shx;
*y = tmp * shy + *y * sy;
}
@@ -314,9 +308,9 @@ namespace agg
//------------------------------------------------------------------------
inline void trans_affine::inverse_transform(double* x, double* y) const
{
- register double d = determinant_reciprocal();
- register double a = (*x - tx) * d;
- register double b = (*y - ty) * d;
+ double d = determinant_reciprocal();
+ double a = (*x - tx) * d;
+ double b = (*y - ty) * d;
*x = a * sy - b * shx;
*y = b * sx - a * shy;
}
diff --git a/src/agg/agg_vcgen_contour.h b/src/agg/agg_vcgen_contour.h
deleted file mode 100644
index 1a3a4bcad..000000000
--- a/src/agg/agg_vcgen_contour.h
+++ /dev/null
@@ -1,103 +0,0 @@
-//----------------------------------------------------------------------------
-// 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
diff --git a/src/agg/agg_vcgen_stroke.h b/src/agg/agg_vcgen_stroke.h
deleted file mode 100644
index 4edba7660..000000000
--- a/src/agg/agg_vcgen_stroke.h
+++ /dev/null
@@ -1,111 +0,0 @@
-//----------------------------------------------------------------------------
-// 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
diff --git a/src/agg/agg_vertex_sequence.h b/src/agg/agg_vertex_sequence.h
deleted file mode 100644
index f3ef35cf1..000000000
--- a/src/agg/agg_vertex_sequence.h
+++ /dev/null
@@ -1,178 +0,0 @@
-//----------------------------------------------------------------------------
-// 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
diff --git a/src/agg/copying b/src/agg/copying
index d511905c1..b6028e519 100644
--- a/src/agg/copying
+++ b/src/agg/copying
@@ -1,339 +1,65 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
+The Anti-Grain Geometry Project
+A high quality rendering engine for C++
+http://antigrain.com
- 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.
+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.
- Preamble
+Note that the Modified BSD license DOES NOT restrict your rights
+if you choose the Anti-Grain Geometry Public License.
- 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.
- 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 Public License
+====================================================
- 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.
+Anti-Grain Geometry - Version 2.4
+Copyright (C) 2002-2005 Maxim Shemanarev (McSeem)
- 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.
+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.
- 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".
-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.
+Modified BSD License
+====================================================
+Anti-Grain Geometry - Version 2.4
+Copyright (C) 2002-2005 Maxim Shemanarev (McSeem)
- 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.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
-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.
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
- 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:
+ 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.
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
+ 3. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
- 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.
+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.
- 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.