From 95d26be57285b20d7f1bed925ffd3f837922804c Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Sat, 4 Feb 2006 21:30:08 +0000 Subject: [PATCH] updated agg-2.4 --- agg/include/agg_basics.h | 7 ++ agg/include/agg_math_stroke.h | 43 ++++++++--- agg/include/agg_rasterizer_compound_aa.h | 22 +++++- agg/include/agg_rasterizer_scanline_aa.h | 7 -- agg/include/agg_vpgen_clip_polyline.h | 49 +----------- agg/src/agg_vpgen_clip_polyline.cpp | 97 ++++-------------------- 6 files changed, 79 insertions(+), 146 deletions(-) diff --git a/agg/include/agg_basics.h b/agg/include/agg_basics.h index cf3cc5f29..58edd2eb4 100644 --- a/agg/include/agg_basics.h +++ b/agg/include/agg_basics.h @@ -193,6 +193,13 @@ namespace agg poly_subpixel_mask = poly_subpixel_scale-1, //----poly_subpixel_mask }; + //----------------------------------------------------------filling_rule_e + enum filling_rule_e + { + fill_non_zero, + fill_even_odd + }; + //-----------------------------------------------------------------------pi const double pi = 3.14159265358979323846; diff --git a/agg/include/agg_math_stroke.h b/agg/include/agg_math_stroke.h index eaa7e680d..d06959590 100644 --- a/agg/include/agg_math_stroke.h +++ b/agg/include/agg_math_stroke.h @@ -38,9 +38,9 @@ namespace agg { miter_join = 0, miter_join_revert = 1, - miter_join_round = 4, round_join = 2, - bevel_join = 3 + bevel_join = 3, + miter_join_round = 4 }; @@ -71,14 +71,6 @@ namespace agg double a2 = atan2(dy2, dx2); double da = a1 - a2; - // Possible optimization. Not important at all; consumes time but happens rarely - //if(fabs(da) < stroke_theta) - //{ - // out_vertices.add(coord_type((x + x + dx1 + dx2) * 0.5, - // (y + y + dy1 + dy2) * 0.5)); - // return; - //} - bool ccw = da > 0.0 && da < pi; if(width < 0) width = -width; @@ -280,6 +272,7 @@ namespace agg typedef typename VertexConsumer::value_type coord_type; double dx1, dy1, dx2, dy2; + double d; dx1 = width * (v1.y - v0.y) / len1; dy1 = width * (v1.x - v0.x) / len1; @@ -312,7 +305,7 @@ namespace agg case inner_jag: case inner_round: { - double d = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2); + d = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2); if(d < len1 * len1 && d < len2 * len2) { stroke_calc_miter(out_vertices, @@ -349,6 +342,34 @@ namespace agg { // Outer join //--------------- + if(line_join == round_join || line_join == bevel_join) + { + // This is an optimization that reduces the number of points + // in cases of almost collonear 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 switch + // to the miter join. + // + // The constant in the expression makes the result approximately + // the same as in round joins and caps. One can safely comment + // out this "if". + //------------------- + double dx = (dx1 + dx2) / 2; + double dy = (dy1 + dy2) / 2; + d = width - sqrt(dx * dx + dy * dy); + if(d < 0.0625 / approximation_scale) + { + line_join = miter_join; + } + } + switch(line_join) { case miter_join: diff --git a/agg/include/agg_rasterizer_compound_aa.h b/agg/include/agg_rasterizer_compound_aa.h index c6c69e24b..2e301d753 100755 --- a/agg/include/agg_rasterizer_compound_aa.h +++ b/agg/include/agg_rasterizer_compound_aa.h @@ -93,13 +93,16 @@ namespace agg { aa_shift = 8, aa_scale = 1 << aa_shift, - aa_mask = aa_scale - 1 + aa_mask = aa_scale - 1, + aa_scale2 = aa_scale * 2, + aa_mask2 = aa_scale2 - 1 }; //-------------------------------------------------------------------- rasterizer_compound_aa() : m_outline(), m_clipper(), + m_filling_rule(fill_non_zero), m_styles(), // Active Styles m_ast(), // Active Style Table (unique values) m_asm(), // Active Style Mask @@ -113,6 +116,7 @@ namespace agg 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 styles(int left, int right); @@ -161,6 +165,14 @@ namespace agg { 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; } @@ -229,6 +241,7 @@ namespace agg private: rasterizer_cells_aa m_outline; clip_type m_clipper; + filling_rule_e m_filling_rule; pod_vector m_styles; // Active Styles pod_vector m_ast; // Active Style Table (unique values) pod_vector m_asm; // Active Style Mask @@ -258,6 +271,13 @@ namespace agg m_scan_y = 0x7FFFFFFF; } + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::filling_rule(filling_rule_e filling_rule) + { + m_filling_rule = filling_rule; + } + //------------------------------------------------------------------------ template void rasterizer_compound_aa::clip_box(double x1, double y1, diff --git a/agg/include/agg_rasterizer_scanline_aa.h b/agg/include/agg_rasterizer_scanline_aa.h index 20f4c97a9..04b516fd7 100644 --- a/agg/include/agg_rasterizer_scanline_aa.h +++ b/agg/include/agg_rasterizer_scanline_aa.h @@ -65,13 +65,6 @@ namespace agg } }; - //----------------------------------------------------------filling_rule_e - enum filling_rule_e - { - fill_non_zero, - fill_even_odd - }; - //==================================================rasterizer_scanline_aa // Polygon rasterizer that is used to render filled polygons with diff --git a/agg/include/agg_vpgen_clip_polyline.h b/agg/include/agg_vpgen_clip_polyline.h index 6f0985650..b070a7759 100644 --- a/agg/include/agg_vpgen_clip_polyline.h +++ b/agg/include/agg_vpgen_clip_polyline.h @@ -32,12 +32,9 @@ namespace agg m_clip_box(0, 0, 1, 1), m_x1(0), m_y1(0), - m_f1(0), - m_x2(0), - m_y2(0), - m_f2(0), m_num_vertices(0), - m_vertex(0) + m_vertex(0), + m_move_to(false) { } @@ -50,7 +47,6 @@ namespace agg m_clip_box.normalize(); } - double x1() const { return m_clip_box.x1; } double y1() const { return m_clip_box.y1; } double x2() const { return m_clip_box.x2; } @@ -64,55 +60,16 @@ namespace agg void line_to(double x, double y); unsigned vertex(double* x, double* y); - private: - enum clipping_flags_def - { - clip_x1 = 1, - clip_x2 = 2, - clip_y1 = 4, - clip_y2 = 8 - }; - - // Determine the clipping code of the vertex according to the - // Cyrus-Beck line clipping algorithm - //-------------------------------------------------------------------- - unsigned clipping_flags_x(double x) - { - unsigned f = 0; - if(x < m_clip_box.x1) f |= clip_x1; - if(x > m_clip_box.x2) f |= clip_x2; - return f; - } - - unsigned clipping_flags_y(double y) - { - unsigned f = 0; - if(y < m_clip_box.y1) f |= clip_y1; - if(y > m_clip_box.y2) f |= clip_y2; - return f; - } - - unsigned clipping_flags(double x, double y) - { - return clipping_flags_x(x) | clipping_flags_y(y); - } - - bool move_point(double& x, double& y, unsigned& flags); - void clip_line_segment(); - private: rect_d m_clip_box; double m_x1; double m_y1; - unsigned m_f1; - double m_x2; - double m_y2; - unsigned m_f2; double m_x[2]; double m_y[2]; unsigned m_cmd[2]; unsigned m_num_vertices; unsigned m_vertex; + bool m_move_to; }; } diff --git a/agg/src/agg_vpgen_clip_polyline.cpp b/agg/src/agg_vpgen_clip_polyline.cpp index 36d1247f5..6840803a9 100644 --- a/agg/src/agg_vpgen_clip_polyline.cpp +++ b/agg/src/agg_vpgen_clip_polyline.cpp @@ -13,19 +13,17 @@ // http://www.antigrain.com //---------------------------------------------------------------------------- -#include #include "agg_vpgen_clip_polyline.h" +#include "agg_clip_liang_barsky.h" namespace agg { - static double clip_epsilon = 1e-10; - - //---------------------------------------------------------------------------- void vpgen_clip_polyline::reset() { m_vertex = 0; m_num_vertices = 0; + m_move_to = false; } //---------------------------------------------------------------------------- @@ -33,99 +31,38 @@ namespace agg { m_vertex = 0; m_num_vertices = 0; - m_f1 = clipping_flags(x, y); - if(m_f1 == 0) - { - m_x[0] = x; - m_y[0] = y; - m_cmd[0] = path_cmd_move_to; - m_num_vertices = 1; - } m_x1 = x; m_y1 = y; - } - - - //---------------------------------------------------------------------------- - bool vpgen_clip_polyline::move_point(double& x, double& y, unsigned& flags) - { - double bound; - - if(flags & (clip_x1 | clip_x2)) - { - bound = (flags & clip_x1) ? m_clip_box.x1 : m_clip_box.x2; - y = (bound - m_x1) * (m_y2 - m_y1) / (m_x2 - m_x1) + m_y1; - x = bound; - flags = clipping_flags_y(y); - } - if(fabs(m_y2 - m_y1) < clip_epsilon && fabs(m_x2 - m_x1) < clip_epsilon) - { - return false; - } - if(flags & (clip_y1 | clip_y2)) - { - bound = (flags & clip_y1) ? m_clip_box.y1 : m_clip_box.y2; - x = (bound - m_y1) * (m_x2 - m_x1) / (m_y2 - m_y1) + m_x1; - y = bound; - } - flags = 0; - return true; + m_move_to = true; } //---------------------------------------------------------------------------- - void vpgen_clip_polyline::clip_line_segment() + void vpgen_clip_polyline::line_to(double x, double y) { - if((m_f1 & m_f2) == 0) + double x2 = x; + double y2 = y; + unsigned flags = clip_line_segment(&m_x1, &m_y1, &x2, &y2, m_clip_box); + + m_vertex = 0; + m_num_vertices = 0; + if((flags & 4) == 0) { - if(m_f1) - { - if(!move_point(m_x1, m_y1, m_f1)) return; - if(m_f1) return; + if((flags & 1) != 0 || m_move_to) + { m_x[0] = m_x1; m_y[0] = m_y1; m_cmd[0] = path_cmd_move_to; m_num_vertices = 1; } - if(m_f2) - { // Move Point 2 - if(!move_point(m_x2, m_y2, m_f2)) return; - } - m_x[m_num_vertices] = m_x2; - m_y[m_num_vertices] = m_y2; + m_x[m_num_vertices] = x2; + m_y[m_num_vertices] = y2; m_cmd[m_num_vertices++] = path_cmd_line_to; + m_move_to = (flags & 2) != 0; } - } - - - - //---------------------------------------------------------------------------- - void vpgen_clip_polyline::line_to(double x, double y) - { - m_vertex = 0; - m_num_vertices = 0; - unsigned f = m_f2 = clipping_flags(m_x2 = x, m_y2 = y); - - if(m_f2 == m_f1) - { - if(m_f2 == 0) - { - m_x[0] = x; - m_y[0] = y; - m_cmd[0] = path_cmd_line_to; - m_num_vertices = 1; - } - } - else - { - clip_line_segment(); - } - - m_f1 = f; m_x1 = x; m_y1 = y; } - //---------------------------------------------------------------------------- unsigned vpgen_clip_polyline::vertex(double* x, double* y) { @@ -137,6 +74,4 @@ namespace agg } return path_cmd_stop; } - - }