diff --git a/0001-Fix-non-terminating-loop-conditions-when-len-1.patch b/0001-Fix-non-terminating-loop-conditions-when-len-1.patch new file mode 100644 index 0000000..b5f57e5 --- /dev/null +++ b/0001-Fix-non-terminating-loop-conditions-when-len-1.patch @@ -0,0 +1,81 @@ +From 085983cdd2bdf79247a12fcee603e6f1bd6b587e Mon Sep 17 00:00:00 2001 +From: Tom Hughes +Date: Sun, 19 May 2013 10:55:37 +0100 +Subject: [PATCH 01/11] Fix non-terminating loop conditions when len=1 + +- while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) ++ while(abs(sx - lp.x1) + abs(sy - lp.y1) > 1 + lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; + } +--- + include/agg_renderer_outline_aa.h | 8 ++++---- + include/agg_renderer_outline_image.h | 4 ++-- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/include/agg_renderer_outline_aa.h b/include/agg_renderer_outline_aa.h +index ce25a2e..cb2aa00 100644 +--- a/include/agg_renderer_outline_aa.h ++++ b/include/agg_renderer_outline_aa.h +@@ -1659,7 +1659,7 @@ namespace agg + } + else + { +- while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) ++ while(abs(sx - lp.x1) + abs(sy - lp.y1) > 1 + lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; +@@ -1726,7 +1726,7 @@ namespace agg + } + else + { +- while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) ++ while(abs(ex - lp.x2) + abs(ey - lp.y2) > 1 + lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; +@@ -1798,7 +1798,7 @@ namespace agg + } + else + { +- while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) ++ while(abs(sx - lp.x1) + abs(sy - lp.y1) > 1 + lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; +@@ -1811,7 +1811,7 @@ namespace agg + } + else + { +- while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) ++ while(abs(ex - lp.x2) + abs(ey - lp.y2) > 1 + lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; +diff --git a/include/agg_renderer_outline_image.h b/include/agg_renderer_outline_image.h +index fbfac10..66d2b9a 100644 +--- a/include/agg_renderer_outline_image.h ++++ b/include/agg_renderer_outline_image.h +@@ -969,7 +969,7 @@ namespace agg + } + else + { +- while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) ++ while(abs(sx - lp.x1) + abs(sy - lp.y1) > 1 + lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; +@@ -982,7 +982,7 @@ namespace agg + } + else + { +- while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) ++ while(abs(ex - lp.x2) + abs(ey - lp.y2) > 1 + lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; +-- +1.8.1.4 + diff --git a/0002-Cure-recursion-by-aborting-if-the-co-ordinates-are-t.patch b/0002-Cure-recursion-by-aborting-if-the-co-ordinates-are-t.patch new file mode 100644 index 0000000..18d43dd --- /dev/null +++ b/0002-Cure-recursion-by-aborting-if-the-co-ordinates-are-t.patch @@ -0,0 +1,40 @@ +From dab3a675d4fe1294f12f65c7ae72fd740b043a19 Mon Sep 17 00:00:00 2001 +From: Tom Hughes +Date: Sun, 19 May 2013 11:03:26 +0100 +Subject: [PATCH 02/11] Cure recursion by aborting if the co-ordinates are to + big to handle + +--- + include/agg_rasterizer_cells_aa.h | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/include/agg_rasterizer_cells_aa.h b/include/agg_rasterizer_cells_aa.h +index d3bb138..3a616d9 100644 +--- a/include/agg_rasterizer_cells_aa.h ++++ b/include/agg_rasterizer_cells_aa.h +@@ -40,7 +40,8 @@ + #define AGG_RASTERIZER_CELLS_AA_INCLUDED + + #include +-#include ++#include ++#include + #include "agg_math.h" + #include "agg_array.h" + +@@ -333,6 +334,12 @@ namespace agg + { + int cx = (x1 + x2) >> 1; + int cy = (y1 + y2) >> 1; ++ ++ // Bail if values are so large they are likely to wrap ++ if ((std::abs(x1) >= std::numeric_limits::max()/2) || (std::abs(y1) >= std::numeric_limits::max()/2) || ++ (std::abs(x2) >= std::numeric_limits::max()/2) || (std::abs(y2) >= std::numeric_limits::max()/2)) ++ return; ++ + line(x1, y1, cx, cy); + line(cx, cy, x2, y2); + } +-- +1.8.1.4 + diff --git a/0003-Get-coordinates-from-previous-vertex-if-last-command.patch b/0003-Get-coordinates-from-previous-vertex-if-last-command.patch new file mode 100644 index 0000000..e4cbdba --- /dev/null +++ b/0003-Get-coordinates-from-previous-vertex-if-last-command.patch @@ -0,0 +1,30 @@ +From 3dbfb18b984dd2bdd2b1fd33108817ffe581c09b Mon Sep 17 00:00:00 2001 +From: Tom Hughes +Date: Sun, 19 May 2013 11:40:49 +0100 +Subject: [PATCH 03/11] Get coordinates from previous vertex if last command is + path_cmd_end_poly + +--- + include/agg_path_storage.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/include/agg_path_storage.h b/include/agg_path_storage.h +index 7be7393..8922fc8 100644 +--- a/include/agg_path_storage.h ++++ b/include/agg_path_storage.h +@@ -878,6 +878,12 @@ namespace agg + *x += x2; + *y += y2; + } ++ else if (!is_stop(m_vertices.last_command()) && ++ is_vertex(m_vertices.prev_vertex(&x2, &y2))) ++ { ++ *x += x2; ++ *y += y2; ++ } + } + } + +-- +1.8.1.4 + diff --git a/0004-Make-rasterizer_outline_aa-ignore-close_polygon-when.patch b/0004-Make-rasterizer_outline_aa-ignore-close_polygon-when.patch new file mode 100644 index 0000000..77a5564 --- /dev/null +++ b/0004-Make-rasterizer_outline_aa-ignore-close_polygon-when.patch @@ -0,0 +1,138 @@ +From e12c9df003505093b6fc81ed6458185271825146 Mon Sep 17 00:00:00 2001 +From: Tom Hughes +Date: Sun, 19 May 2013 14:17:43 +0100 +Subject: [PATCH 04/11] Make rasterizer_outline_aa ignore close_polygon when + vertex count < 3 + +--- + include/agg_rasterizer_outline_aa.h | 107 ++++++++++++++++++------------------ + 1 file changed, 52 insertions(+), 55 deletions(-) + +diff --git a/include/agg_rasterizer_outline_aa.h b/include/agg_rasterizer_outline_aa.h +index 4d6dd57..24301d5 100644 +--- a/include/agg_rasterizer_outline_aa.h ++++ b/include/agg_rasterizer_outline_aa.h +@@ -333,68 +333,65 @@ namespace agg + int y2; + int lprev; + +- if(close_polygon) ++ if(close_polygon && (m_src_vertices.size() >= 3)) + { +- if(m_src_vertices.size() >= 3) ++ dv.idx = 2; ++ ++ v = &m_src_vertices[m_src_vertices.size() - 1]; ++ x1 = v->x; ++ y1 = v->y; ++ lprev = v->len; ++ ++ v = &m_src_vertices[0]; ++ x2 = v->x; ++ y2 = v->y; ++ dv.lcurr = v->len; ++ line_parameters prev(x1, y1, x2, y2, lprev); ++ ++ v = &m_src_vertices[1]; ++ dv.x1 = v->x; ++ dv.y1 = v->y; ++ dv.lnext = v->len; ++ dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr); ++ ++ v = &m_src_vertices[dv.idx]; ++ dv.x2 = v->x; ++ dv.y2 = v->y; ++ dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); ++ ++ dv.xb1 = 0; ++ dv.yb1 = 0; ++ dv.xb2 = 0; ++ dv.yb2 = 0; ++ ++ switch(m_line_join) + { +- dv.idx = 2; +- +- v = &m_src_vertices[m_src_vertices.size() - 1]; +- x1 = v->x; +- y1 = v->y; +- lprev = v->len; +- +- v = &m_src_vertices[0]; +- x2 = v->x; +- y2 = v->y; +- dv.lcurr = v->len; +- line_parameters prev(x1, y1, x2, y2, lprev); +- +- v = &m_src_vertices[1]; +- dv.x1 = v->x; +- dv.y1 = v->y; +- dv.lnext = v->len; +- dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr); +- +- v = &m_src_vertices[dv.idx]; +- dv.x2 = v->x; +- dv.y2 = v->y; +- dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); +- +- dv.xb1 = 0; +- dv.yb1 = 0; +- dv.xb2 = 0; +- dv.yb2 = 0; +- +- switch(m_line_join) +- { +- case outline_no_join: +- dv.flags = 3; +- break; ++ case outline_no_join: ++ dv.flags = 3; ++ break; + +- case outline_miter_join: +- case outline_round_join: +- dv.flags = +- (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | +- ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); +- break; ++ case outline_miter_join: ++ case outline_round_join: ++ dv.flags = ++ (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | ++ ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); ++ break; + +- case outline_miter_accurate_join: +- dv.flags = 0; +- break; +- } ++ case outline_miter_accurate_join: ++ dv.flags = 0; ++ break; ++ } + +- if((dv.flags & 1) == 0 && m_line_join != outline_round_join) +- { +- bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); +- } ++ if((dv.flags & 1) == 0 && m_line_join != outline_round_join) ++ { ++ bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); ++ } + +- if((dv.flags & 2) == 0 && m_line_join != outline_round_join) +- { +- bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); +- } +- draw(dv, 0, m_src_vertices.size()); ++ if((dv.flags & 2) == 0 && m_line_join != outline_round_join) ++ { ++ bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + } ++ draw(dv, 0, m_src_vertices.size()); + } + else + { +-- +1.8.1.4 + diff --git a/0005-Remove-VC-6-workaround.patch b/0005-Remove-VC-6-workaround.patch new file mode 100644 index 0000000..78d8ec7 --- /dev/null +++ b/0005-Remove-VC-6-workaround.patch @@ -0,0 +1,52 @@ +From 9fb6c7e39bb0cf01f7268a55b13d7ae828ab8321 Mon Sep 17 00:00:00 2001 +From: Tom Hughes +Date: Sun, 19 May 2013 15:04:05 +0100 +Subject: [PATCH 05/11] Remove VC++ 6 workaround + +--- + include/agg_renderer_scanline.h | 29 +---------------------------- + 1 file changed, 1 insertion(+), 28 deletions(-) + +diff --git a/include/agg_renderer_scanline.h b/include/agg_renderer_scanline.h +index c3bb6f0..c27ca60 100644 +--- a/include/agg_renderer_scanline.h ++++ b/include/agg_renderer_scanline.h +@@ -79,34 +79,7 @@ namespace agg + sl.reset(ras.min_x(), ras.max_x()); + while(ras.sweep_scanline(sl)) + { +- //render_scanline_aa_solid(sl, ren, ren_color); +- +- // This code is equivalent to the above call (copy/paste). +- // It's just a "manual" optimization for old compilers, +- // like Microsoft Visual C++ v6.0 +- //------------------------------- +- int y = sl.y(); +- unsigned num_spans = sl.num_spans(); +- typename Scanline::const_iterator span = sl.begin(); +- +- for(;;) +- { +- int x = span->x; +- if(span->len > 0) +- { +- ren.blend_solid_hspan(x, y, (unsigned)span->len, +- ren_color, +- span->covers); +- } +- else +- { +- ren.blend_hline(x, y, (unsigned)(x - span->len - 1), +- ren_color, +- *(span->covers)); +- } +- if(--num_spans == 0) break; +- ++span; +- } ++ render_scanline_aa_solid(sl, ren, ren_color); + } + } + } +-- +1.8.1.4 + diff --git a/0006-Implement-grain-merge-blending-mode-GIMP.patch b/0006-Implement-grain-merge-blending-mode-GIMP.patch new file mode 100644 index 0000000..2526d06 --- /dev/null +++ b/0006-Implement-grain-merge-blending-mode-GIMP.patch @@ -0,0 +1,85 @@ +From 09c4b068b9512e33736e6f23896ad2522f3b65da Mon Sep 17 00:00:00 2001 +From: Tom Hughes +Date: Sun, 19 May 2013 15:31:01 +0100 +Subject: [PATCH 06/11] Implement grain-merge blending mode (GIMP) + +--- + include/agg_pixfmt_rgba.h | 42 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 40 insertions(+), 2 deletions(-) + +diff --git a/include/agg_pixfmt_rgba.h b/include/agg_pixfmt_rgba.h +index 79d10dc..99b1c9f 100644 +--- a/include/agg_pixfmt_rgba.h ++++ b/include/agg_pixfmt_rgba.h +@@ -1401,9 +1401,46 @@ namespace agg + } + }; + ++ //================================================comp_op_rgba_grain_merge ++ template struct comp_op_rgba_grain_merge ++ { ++ 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 ++ }; + ++ // E = I + M - 128 ++ 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 = sr + p[Order::R] - 128; ++ calc_type dg = sg + p[Order::G] - 128; ++ calc_type db = sb + p[Order::B] - 128; ++ p[Order::R] = (value_type)(dr < 0 ? 0 : (dr > 255 ? 255 : dr)); ++ p[Order::G] = (value_type)(dg < 0 ? 0 : (dg > 255 ? 255 : dg)); ++ p[Order::B] = (value_type)(db < 0 ? 0 : (db > 255 ? 255 : db)); ++ p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); ++ } ++ } ++ }; + + //======================================================comp_op_table_rgba + template struct comp_op_table_rgba +@@ -1451,6 +1488,7 @@ namespace agg + comp_op_rgba_contrast ::blend_pix, + comp_op_rgba_invert ::blend_pix, + comp_op_rgba_invert_rgb ::blend_pix, ++ comp_op_rgba_grain_merge::blend_pix, + 0 + }; + +@@ -1486,6 +1524,7 @@ namespace agg + comp_op_contrast, //----comp_op_contrast + comp_op_invert, //----comp_op_invert + comp_op_invert_rgb, //----comp_op_invert_rgb ++ comp_op_grain_merge, //----comp_op_grain_merge + + end_of_comp_op_e + }; +@@ -2908,4 +2947,3 @@ namespace agg + } + + #endif +- +-- +1.8.1.4 + diff --git a/0007-Implement-grain-extract-blending-mode-GIMP.patch b/0007-Implement-grain-extract-blending-mode-GIMP.patch new file mode 100644 index 0000000..656f885 --- /dev/null +++ b/0007-Implement-grain-extract-blending-mode-GIMP.patch @@ -0,0 +1,84 @@ +From 6cef3ddecc1b8a614ba4d47bf9daf6b04bea9995 Mon Sep 17 00:00:00 2001 +From: Tom Hughes +Date: Sun, 19 May 2013 15:43:18 +0100 +Subject: [PATCH 07/11] Implement grain-extract blending mode (GIMP) + +--- + include/agg_pixfmt_rgba.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 47 insertions(+) + +diff --git a/include/agg_pixfmt_rgba.h b/include/agg_pixfmt_rgba.h +index 99b1c9f..e0a6dc1 100644 +--- a/include/agg_pixfmt_rgba.h ++++ b/include/agg_pixfmt_rgba.h +@@ -1442,6 +1442,51 @@ namespace agg + } + }; + ++ //==============================================comp_op_rgba_grain_extract ++ template struct comp_op_rgba_grain_extract ++ { ++ 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 ++ }; ++ ++ // E = I - M + 128 ++ 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] * sa + 255) >> 8; ++ calc_type dr = p[Order::R] - sr + 128; ++ calc_type dg = p[Order::G] - sg + 128; ++ calc_type db = p[Order::B] - sb + 128; ++ ++ dr = dr < 0 ? 0 : (dr > 255 ? 255 : dr); ++ dg = dg < 0 ? 0 : (dg > 255 ? 255 : dg); ++ db = db < 0 ? 0 : (db > 255 ? 255 : db); ++ ++ p[Order::A] = da; ++ ++ if(da < 255) ++ { ++ p[Order::R] = (dr * da + 255) >> 8; ++ p[Order::G] = (dg * da + 255) >> 8; ++ p[Order::B] = (db * da + 255) >> 8; ++ } ++ else ++ { ++ p[Order::R] = dr; ++ p[Order::G] = dg; ++ p[Order::B] = db; ++ } ++ } ++ }; ++ + //======================================================comp_op_table_rgba + template struct comp_op_table_rgba + { +@@ -1489,6 +1534,7 @@ namespace agg + comp_op_rgba_invert ::blend_pix, + comp_op_rgba_invert_rgb ::blend_pix, + comp_op_rgba_grain_merge::blend_pix, ++ comp_op_rgba_grain_extract::blend_pix, + 0 + }; + +@@ -1525,6 +1571,7 @@ namespace agg + comp_op_invert, //----comp_op_invert + comp_op_invert_rgb, //----comp_op_invert_rgb + comp_op_grain_merge, //----comp_op_grain_merge ++ comp_op_grain_extract, //----comp_op_grain_extract + + end_of_comp_op_e + }; +-- +1.8.1.4 + diff --git a/0008-Declare-multiplication-and-division-operators-as-con.patch b/0008-Declare-multiplication-and-division-operators-as-con.patch new file mode 100644 index 0000000..58fc18a --- /dev/null +++ b/0008-Declare-multiplication-and-division-operators-as-con.patch @@ -0,0 +1,36 @@ +From 6f8f30a6af5b335c14065e421d953b821fb7660f Mon Sep 17 00:00:00 2001 +From: Tom Hughes +Date: Sun, 19 May 2013 16:15:01 +0100 +Subject: [PATCH 08/11] Declare multiplication and division operators as const + +--- + include/agg_trans_affine.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/include/agg_trans_affine.h b/include/agg_trans_affine.h +index a662099..2f602a0 100644 +--- a/include/agg_trans_affine.h ++++ b/include/agg_trans_affine.h +@@ -216,15 +216,15 @@ namespace agg + } + + // Multiply the matrix by another one and return +- // the result in a separete matrix. +- trans_affine operator * (const trans_affine& m) ++ // the result in a separate matrix. ++ 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) ++ // and return the result in a separate matrix. ++ trans_affine operator / (const trans_affine& m) const + { + return trans_affine(*this).multiply_inv(m); + } +-- +1.8.1.4 + diff --git a/0009-Add-a-static-identity-transformation.patch b/0009-Add-a-static-identity-transformation.patch new file mode 100644 index 0000000..9ee9b79 --- /dev/null +++ b/0009-Add-a-static-identity-transformation.patch @@ -0,0 +1,37 @@ +From 7669098f8e80929eec2e380967e12b31b68a4310 Mon Sep 17 00:00:00 2001 +From: Tom Hughes +Date: Sun, 19 May 2013 16:15:36 +0100 +Subject: [PATCH 09/11] Add a static identity transformation + +--- + include/agg_trans_affine.h | 1 + + src/agg_trans_affine.cpp | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/include/agg_trans_affine.h b/include/agg_trans_affine.h +index 2f602a0..67fe5ca 100644 +--- a/include/agg_trans_affine.h ++++ b/include/agg_trans_affine.h +@@ -92,6 +92,7 @@ namespace agg + //---------------------------------------------------------------------- + struct trans_affine + { ++ static const trans_affine identity; + double sx, shy, shx, sy, tx, ty; + + //------------------------------------------ Construction +diff --git a/src/agg_trans_affine.cpp b/src/agg_trans_affine.cpp +index aca18c2..b3d9bc0 100644 +--- a/src/agg_trans_affine.cpp ++++ b/src/agg_trans_affine.cpp +@@ -28,6 +28,7 @@ + + namespace agg + { ++ const trans_affine trans_affine::identity; + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::parl_to_parl(const double* src, +-- +1.8.1.4 + diff --git a/0010-Add-renderer_scanline_aa_alpha.patch b/0010-Add-renderer_scanline_aa_alpha.patch new file mode 100644 index 0000000..33acf70 --- /dev/null +++ b/0010-Add-renderer_scanline_aa_alpha.patch @@ -0,0 +1,193 @@ +From 15fa2c5afe649b4f41aede636243c9bea7aa74a4 Mon Sep 17 00:00:00 2001 +From: Tom Hughes +Date: Sun, 19 May 2013 16:43:25 +0100 +Subject: [PATCH 10/11] Add renderer_scanline_aa_alpha + +--- + include/agg_pixfmt_rgba.h | 24 +++++++++++++- + include/agg_renderer_base.h | 28 ++++++++++++++++ + include/agg_renderer_scanline.h | 71 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 122 insertions(+), 1 deletion(-) + +diff --git a/include/agg_pixfmt_rgba.h b/include/agg_pixfmt_rgba.h +index e0a6dc1..d912ba3 100644 +--- a/include/agg_pixfmt_rgba.h ++++ b/include/agg_pixfmt_rgba.h +@@ -2246,7 +2246,6 @@ namespace agg + } + + +- + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, +@@ -2750,6 +2749,29 @@ namespace agg + } + + //-------------------------------------------------------------------- ++ void blend_color_hspan_alpha(int x, int y, unsigned len, ++ const color_type* colors, ++ value_type alpha, ++ 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 * alpha + 255) >> 8, ++ (colors->g * alpha + 255) >> 8, ++ (colors->b * alpha + 255) >> 8, ++ (colors->a * alpha + 255) >> 8, ++ 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, +diff --git a/include/agg_renderer_base.h b/include/agg_renderer_base.h +index 1808944..25f07c3 100644 +--- a/include/agg_renderer_base.h ++++ b/include/agg_renderer_base.h +@@ -37,6 +37,7 @@ namespace agg + public: + typedef PixelFormat pixfmt_type; + typedef typename pixfmt_type::color_type color_type; ++ typedef typename pixfmt_type::color_type::value_type value_type; + typedef typename pixfmt_type::row_data row_data; + + //-------------------------------------------------------------------- +@@ -383,6 +384,33 @@ namespace agg + } + + //-------------------------------------------------------------------- ++ void blend_color_hspan_alpha(int x, int y, int len, ++ const color_type* colors, ++ value_type alpha, ++ const cover_type* covers, ++ cover_type cover = agg::cover_full) ++ { ++ if(y > ymax()) return; ++ if(y < ymin()) return; ++ ++ if(x < xmin()) ++ { ++ int d = xmin() - x; ++ len -= d; ++ if(len <= 0) return; ++ if(covers) covers += d; ++ colors += d; ++ x = xmin(); ++ } ++ if(x + len > xmax()) ++ { ++ len = xmax() - x + 1; ++ if(len <= 0) return; ++ } ++ m_ren->blend_color_hspan_alpha(x, y, len, colors, alpha, covers, cover); ++ } ++ ++ //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, +diff --git a/include/agg_renderer_scanline.h b/include/agg_renderer_scanline.h +index c27ca60..4fcb557 100644 +--- a/include/agg_renderer_scanline.h ++++ b/include/agg_renderer_scanline.h +@@ -156,6 +156,35 @@ namespace agg + } + } + ++ //================================================render_scanline_aa_alpha ++ template ++ void render_scanline_aa_alpha(const Scanline& sl, BaseRenderer& ren, ++ SpanAllocator& alloc, SpanGenerator& span_gen, ++ unsigned alpha) ++ { ++ int y = sl.y(); ++ ++ unsigned num_spans = sl.num_spans(); ++ typename Scanline::const_iterator span = sl.begin(); ++ for(;;) ++ { ++ int x = span->x; ++ int len = span->len; ++ const typename Scanline::cover_type* covers = span->covers; ++ ++ if(len < 0) len = -len; ++ typename BaseRenderer::color_type* colors = alloc.allocate(len); ++ span_gen.generate(colors, x, y, len); ++ ren.blend_color_hspan_alpha(x, y, len, colors, alpha, ++ (span->len < 0) ? 0 : covers, *covers); ++ ++ if(--num_spans == 0) break; ++ ++span; ++ } ++ } ++ ++ + //=====================================================render_scanlines_aa + template +@@ -216,8 +245,50 @@ namespace agg + }; + + ++ //==============================================renderer_scanline_aa_alpha ++ template ++ class renderer_scanline_aa_alpha ++ { ++ public: ++ typedef BaseRenderer base_ren_type; ++ typedef SpanAllocator alloc_type; ++ typedef SpanGenerator span_gen_type; + ++ //-------------------------------------------------------------------- ++ renderer_scanline_aa_alpha() : m_ren(0), m_alloc(0), m_span_gen(0), m_alpha(1.0) {} ++ renderer_scanline_aa_alpha(base_ren_type& ren, ++ alloc_type& alloc, ++ span_gen_type& span_gen, ++ unsigned alpha) : ++ m_ren(&ren), ++ m_alloc(&alloc), ++ m_span_gen(&span_gen), ++ m_alpha(alpha) ++ {} ++ void attach(base_ren_type& ren, ++ alloc_type& alloc, ++ span_gen_type& span_gen) ++ { ++ m_ren = &ren; ++ m_alloc = &alloc; ++ m_span_gen = &span_gen; ++ } + ++ //-------------------------------------------------------------------- ++ void prepare() { m_span_gen->prepare(); } ++ ++ //-------------------------------------------------------------------- ++ template void render(const Scanline& sl) ++ { ++ render_scanline_aa_alpha(sl, *m_ren, *m_alloc, *m_span_gen, m_alpha); ++ } ++ ++ private: ++ base_ren_type* m_ren; ++ alloc_type* m_alloc; ++ span_gen_type* m_span_gen; ++ unsigned m_alpha; ++ }; + + + //===============================================render_scanline_bin_solid +-- +1.8.1.4 + diff --git a/0011-Avoid-division-by-zero-in-color-burn-mode.patch b/0011-Avoid-division-by-zero-in-color-burn-mode.patch new file mode 100644 index 0000000..9b431fe --- /dev/null +++ b/0011-Avoid-division-by-zero-in-color-burn-mode.patch @@ -0,0 +1,58 @@ +From 85de27e76d433db8c577e9475e29794cad5f999a Mon Sep 17 00:00:00 2001 +From: Tom Hughes +Date: Sun, 19 May 2013 16:49:08 +0100 +Subject: [PATCH 11/11] Avoid division by zero in color-burn mode + +FIXME: re-work using latest math from http://www.w3.org/TR/SVGCompositing/ +--- + include/agg_pixfmt_rgba.h | 21 ++++++++++++++++++--- + 1 file changed, 18 insertions(+), 3 deletions(-) + +diff --git a/include/agg_pixfmt_rgba.h b/include/agg_pixfmt_rgba.h +index d912ba3..e30860c 100644 +--- a/include/agg_pixfmt_rgba.h ++++ b/include/agg_pixfmt_rgba.h +@@ -1027,6 +1027,21 @@ namespace agg + // Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da ++ ++ ++ // http://www.w3.org/TR/SVGCompositing/ ++ // if Sca == 0 and Dca == Da ++ // Dca' = Sa × Da + Sca × (1 - Da) + Dca × (1 - Sa) ++ // = Sa × Da + Dca × (1 - Sa) ++ // = Da = Dca ++ // otherwise if Sca == 0 ++ // Dca' = Sca × (1 - Da) + Dca × (1 - Sa) ++ // = Dca × (1 - Sa) ++ // otherwise if Sca > 0 ++ // Dca' = Sa × Da - Sa × Da × min(1, (1 - Dca/Da) × Sa/Sca) + Sca × (1 - Da) + Dca × (1 - Sa) ++ // = Sa × Da × (1 - min(1, (1 - Dca/Da) × Sa/Sca)) + Sca × (1 - Da) + Dca × (1 - Sa) ++ ++ // sa * da * (255 - std::min(255, (255 - p[0]/da)*(sa/(sc*sa)) + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) +@@ -1056,15 +1071,15 @@ namespace agg + + 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); ++ (sr > 0 ? sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask : 0)) >> 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); ++ (sg > 0 ? sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask : 0)) >> 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); ++ (sb > 0 ? sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask : 0)) >> base_shift); + + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } +-- +1.8.1.4 +