diff --git a/headers/libs/agg/agg_array.h b/headers/libs/agg/agg_array.h index e29a22dca1..70ec2855a4 100644 --- a/headers/libs/agg/agg_array.h +++ b/headers/libs/agg/agg_array.h @@ -15,6 +15,7 @@ #ifndef AGG_ARRAY_INCLUDED #define AGG_ARRAY_INCLUDED +#include #include #include "agg_basics.h" @@ -45,7 +46,10 @@ namespace agg void add(const T& v) { m_array[m_size++] = v; } void inc_size(unsigned size) { m_size += size; } - unsigned size() const { return m_size; } + unsigned size() const { return m_size; } + unsigned byte_size() const { return m_size * sizeof(T); } + void serialize(int8u* ptr) const; + void deserialize(const int8u* data, unsigned byte_size); const T& operator [] (unsigned idx) const { return m_array[idx]; } T& operator [] (unsigned idx) { return m_array[idx]; } @@ -116,9 +120,20 @@ namespace agg return *this; } + //------------------------------------------------------------------------ + template void pod_array::serialize(int8u* ptr) const + { + if(m_size) memcpy(ptr, m_array, m_size * sizeof(T)); + } - - + //------------------------------------------------------------------------ + template + void pod_array::deserialize(const int8u* data, unsigned byte_size) + { + byte_size /= sizeof(T); + capacity(byte_size); + if(byte_size) memcpy(m_array, data, byte_size * sizeof(T)); + } //------------------------------------------------------------------------ template class pod_array_adaptor @@ -154,6 +169,7 @@ namespace agg //------------------------------------------------------------------------ template class pod_deque { + public: enum { block_shift = S, @@ -161,7 +177,6 @@ namespace agg block_mask = block_size - 1 }; - public: typedef T value_type; ~pod_deque(); @@ -181,6 +196,23 @@ namespace agg int allocate_continuous_block(unsigned num_elements); + void add_array(const T* ptr, unsigned num_elem) + { + while(num_elem--) + { + add(*ptr++); + } + } + + template void add_data(DataAccessor& data) + { + while(data.size()) + { + add(*data); + ++data; + } + } + void cut_at(unsigned size) { if(size < m_size) m_size = size; @@ -240,6 +272,58 @@ namespace agg unsigned byte_size() const; void serialize(int8u* ptr) const; + void deserialize(const int8u* data, unsigned byte_size); + void deserialize(unsigned start, const T& empty_val, + const int8u* data, unsigned byte_size); + + template + void deserialize(ByteAccessor data) + { + remove_all(); + unsigned elem_size = data.size() / sizeof(T); + + for(unsigned i = 0; i < elem_size; ++i) + { + int8u* ptr = (int8u*)data_ptr(); + for(unsigned j = 0; j < sizeof(T); ++j) + { + *ptr++ = *data; + ++data; + } + ++m_size; + } + } + + template + void deserialize(unsigned start, const T& empty_val, ByteAccessor data) + { + while(m_size < start) + { + add(empty_val); + } + + unsigned elem_size = data.size() / sizeof(T); + for(unsigned i = 0; i < elem_size; ++i) + { + int8u* ptr; + if(start + i < m_size) + { + ptr = (int8u*)(&((*this)[start + i])); + } + else + { + ptr = (int8u*)data_ptr(); + ++m_size; + } + for(unsigned j = 0; j < sizeof(T); ++j) + { + *ptr++ = *data; + ++data; + } + } + } + + const T* block(unsigned nb) const { return m_blocks[nb]; } private: void allocate_block(unsigned nb); @@ -253,8 +337,6 @@ namespace agg }; - - //------------------------------------------------------------------------ template pod_deque::~pod_deque() { @@ -461,8 +543,49 @@ namespace agg } } + //------------------------------------------------------------------------ + template + void pod_deque::deserialize(const int8u* data, unsigned byte_size) + { + remove_all(); + byte_size /= sizeof(T); + for(unsigned i = 0; i < byte_size; ++i) + { + T* ptr = data_ptr(); + memcpy(ptr, data, sizeof(T)); + ++m_size; + data += sizeof(T); + } + } + // Replace or add a number of elements starting from "start" position + //------------------------------------------------------------------------ + template + void pod_deque::deserialize(unsigned start, const T& empty_val, + const int8u* data, unsigned byte_size) + { + while(m_size < start) + { + add(empty_val); + } + + byte_size /= sizeof(T); + for(unsigned i = 0; i < byte_size; ++i) + { + if(start + i < m_size) + { + memcpy(&((*this)[start + i]), data, sizeof(T)); + } + else + { + T* ptr = data_ptr(); + memcpy(ptr, data, sizeof(T)); + ++m_size; + } + data += sizeof(T); + } + } //-----------------------------------------------------------pod_allocator @@ -520,7 +643,7 @@ namespace agg int8u* ptr = m_buf_ptr; if(alignment > 1) { - unsigned align = (alignment - unsigned(ptr) % alignment) % alignment; + unsigned align = (alignment - unsigned((size_t)ptr) % alignment) % alignment; size += align; ptr += align; if(size <= m_rest) diff --git a/headers/libs/agg/agg_bezier_arc.h b/headers/libs/agg/agg_bezier_arc.h index 4e3d0db90b..588a326331 100644 --- a/headers/libs/agg/agg_bezier_arc.h +++ b/headers/libs/agg/agg_bezier_arc.h @@ -39,6 +39,7 @@ namespace agg class bezier_arc { public: + //-------------------------------------------------------------------- bezier_arc() : m_vertex(26) {} bezier_arc(double x, double y, double rx, double ry, @@ -48,6 +49,7 @@ namespace agg init(x, y, rx, ry, start_angle, sweep_angle); } + //-------------------------------------------------------------------- void init(double x, double y, double rx, double ry, double start_angle, diff --git a/headers/libs/agg/agg_bounding_rect.h b/headers/libs/agg/agg_bounding_rect.h index 5715a58371..58072fec9c 100644 --- a/headers/libs/agg/agg_bounding_rect.h +++ b/headers/libs/agg/agg_bounding_rect.h @@ -35,6 +35,11 @@ namespace agg double y; bool first = true; + *x1 = CoordT(1); + *y1 = CoordT(1); + *x2 = CoordT(0); + *y2 = CoordT(0); + for(i = 0; i < num; i++) { vs.rewind(gi[start + i]); @@ -74,6 +79,11 @@ namespace agg double y; bool first = true; + *x1 = CoordT(1); + *y1 = CoordT(1); + *x2 = CoordT(0); + *y2 = CoordT(0); + vs.rewind(path_id); unsigned cmd; while(!is_stop(cmd = vs.vertex(&x, &y))) diff --git a/headers/libs/agg/agg_clip_liang_barsky.h b/headers/libs/agg/agg_clip_liang_barsky.h index 897c0f2261..d3a47b493f 100644 --- a/headers/libs/agg/agg_clip_liang_barsky.h +++ b/headers/libs/agg/agg_clip_liang_barsky.h @@ -24,6 +24,35 @@ namespace agg { + //----------------------------------------------------------clipping_flags + // Determine the clipping code of the vertex according to the + // Cyrus-Beck line clipping algorithm + // + // | | + // 0110 | 0010 | 0011 + // | | + // -------+--------+-------- clip_box.y2 + // | | + // 0100 | 0000 | 0001 + // | | + // -------+--------+-------- clip_box.y1 + // | | + // 1100 | 1000 | 1001 + // | | + // clip_box.x1 clip_box.x2 + // + // + template + inline unsigned clipping_flags(T x, T y, const rect_base& clip_box) + { + return (x > clip_box.x2) | + ((y > clip_box.y2) << 1) | + ((x < clip_box.x1) << 2) | + ((y < clip_box.y1) << 3); + } + + + //-------------------------------------------------------clip_liang_barsky template inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, diff --git a/headers/libs/agg/agg_color_rgba.h b/headers/libs/agg/agg_color_rgba.h index fce76f4ae1..d826dc917d 100644 --- a/headers/libs/agg/agg_color_rgba.h +++ b/headers/libs/agg/agg_color_rgba.h @@ -28,6 +28,7 @@ namespace agg //====================================================================rgba struct rgba { + typedef double alpha_type; enum premul { pre }; double r; diff --git a/headers/libs/agg/agg_color_rgba8.h b/headers/libs/agg/agg_color_rgba8.h index e85c4eb39d..6790b8a095 100644 --- a/headers/libs/agg/agg_color_rgba8.h +++ b/headers/libs/agg/agg_color_rgba8.h @@ -38,6 +38,7 @@ namespace agg //==================================================================rgba8 struct rgba8 { + typedef int8u alpha_type; enum order { rgb, bgr }; enum premul { pre }; @@ -230,7 +231,7 @@ namespace agg //------------------------------------------------------------------------ - inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, unsigned a=1.0) + inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, unsigned a=255) { return rgba8(rgba8::pre, r, g, b, a); } diff --git a/headers/libs/agg/agg_conv_adaptor_vpgen.h b/headers/libs/agg/agg_conv_adaptor_vpgen.h index b5e5845e26..a258096de7 100755 --- a/headers/libs/agg/agg_conv_adaptor_vpgen.h +++ b/headers/libs/agg/agg_conv_adaptor_vpgen.h @@ -51,6 +51,7 @@ namespace agg double m_start_x; double m_start_y; unsigned m_poly_flags; + int m_vertices; }; @@ -64,6 +65,7 @@ namespace agg m_start_x = 0; m_start_y = 0; m_poly_flags = 0; + m_vertices = 0; } @@ -77,26 +79,51 @@ namespace agg cmd = m_vpgen.vertex(x, y); if(!is_stop(cmd)) break; - if(m_poly_flags) + if(m_poly_flags && !m_vpgen.auto_unclose()) { + *x = 0.0; + *y = 0.0; cmd = m_poly_flags; m_poly_flags = 0; break; } + if(m_vertices < 0) + { + if(m_vertices < -1) + { + m_vertices = 0; + return path_cmd_stop; + } + m_vpgen.move_to(m_start_x, m_start_y); + m_vertices = 1; + continue; + } + double tx, ty; cmd = m_source->vertex(&tx, &ty); if(is_vertex(cmd)) { if(is_move_to(cmd)) { + if(m_vpgen.auto_close() && m_vertices > 2) + { + m_vpgen.line_to(m_start_x, m_start_y); + m_poly_flags = path_cmd_end_poly | path_flags_close; + m_start_x = tx; + m_start_y = ty; + m_vertices = -1; + continue; + } m_vpgen.move_to(tx, ty); - m_start_x = tx; - m_start_y = ty; + m_start_x = tx; + m_start_y = ty; + m_vertices = 1; } else { m_vpgen.line_to(tx, ty); + ++m_vertices; } } else @@ -104,14 +131,26 @@ namespace agg if(is_end_poly(cmd)) { m_poly_flags = cmd; - if(is_closed(cmd)) + if(is_closed(cmd) || m_vpgen.auto_close()) { - m_vpgen.line_to(m_start_x, m_start_y); + if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close; + if(m_vertices > 2) + { + m_vpgen.line_to(m_start_x, m_start_y); + } + m_vertices = 0; } } else { - // The adaptor should be transparent to all unknown commands + // path_cmd_stop + if(m_vpgen.auto_close() && m_vertices > 2) + { + m_vpgen.line_to(m_start_x, m_start_y); + m_poly_flags = path_cmd_end_poly | path_flags_close; + m_vertices = -2; + continue; + } break; } } diff --git a/headers/libs/agg/agg_conv_clip_polyline.h b/headers/libs/agg/agg_conv_clip_polyline.h new file mode 100644 index 0000000000..96115335e3 --- /dev/null +++ b/headers/libs/agg/agg_conv_clip_polyline.h @@ -0,0 +1,69 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.2 +// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// polyline clipping converter +// There an optimized Liang-Basky algorithm is used. +// The algorithm doesn't optimize the degenerate edges, i.e. it will never +// break a closed polyline into two or more ones, instead, there will be +// degenerate edges coinciding with the respective clipping boundaries. +// This is a sub-optimal solution, because that optimization would require +// extra, rather expensive math while the rasterizer tolerates it quite well, +// without any considerable overhead. +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_CLIP_polyline_INCLUDED +#define AGG_CONV_CLIP_polyline_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vpgen.h" +#include "agg_vpgen_clip_polyline.h" +#include "agg_vertex_iterator.h" + +namespace agg +{ + + //=======================================================conv_clip_polyline + template + struct conv_clip_polyline : public conv_adaptor_vpgen + { + typedef conv_adaptor_vpgen base_type; + + conv_clip_polyline(VertexSource& vs) : + conv_adaptor_vpgen(vs) {} + + void clip_box(double x1, double y1, double x2, double y2) + { + base_type::vpgen().clip_box(x1, y1, x2, y2); + } + + double x1() const { return base_type::vpgen().x1(); } + double y1() const { return base_type::vpgen().y1(); } + double x2() const { return base_type::vpgen().x2(); } + double y2() const { return base_type::vpgen().y2(); } + + typedef conv_clip_polyline source_type; + typedef vertex_iterator iterator; + iterator begin(unsigned id) { return iterator(*this, id); } + iterator end() { return iterator(path_cmd_stop); } + + private: + conv_clip_polyline(const conv_clip_polyline&); + const conv_clip_polyline& + operator = (const conv_clip_polyline&); + }; + +} + +#endif diff --git a/headers/libs/agg/agg_conv_contour.h b/headers/libs/agg/agg_conv_contour.h index c525f16a98..76091caf89 100644 --- a/headers/libs/agg/agg_conv_contour.h +++ b/headers/libs/agg/agg_conv_contour.h @@ -37,13 +37,21 @@ namespace agg { } + void line_join(line_join_e lj) { base_type::generator().line_join(lj); } + void inner_line_join(line_join_e lj) { base_type::generator().inner_line_join(lj); } void width(double w) { base_type::generator().width(w); } void miter_limit(double ml) { base_type::generator().miter_limit(ml); } void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); } + void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); } + void approximation_scale(double as) { base_type::generator().approximation_scale(as); } void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); } + line_join_e line_join() const { return base_type::generator().line_join(); } + line_join_e inner_line_join() const { return base_type::generator().inner_line_join(); } double width() const { return base_type::generator().width(); } double miter_limit() const { return base_type::generator().miter_limit(); } + double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); } + double approximation_scale() const { return base_type::generator().approximation_scale(); } bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); } private: diff --git a/headers/libs/agg/agg_conv_stroke.h b/headers/libs/agg/agg_conv_stroke.h index 57e72075cc..707119edfc 100644 --- a/headers/libs/agg/agg_conv_stroke.h +++ b/headers/libs/agg/agg_conv_stroke.h @@ -39,19 +39,23 @@ namespace agg { } - void line_cap(vcgen_stroke::line_cap_e lc) { base_type::generator().line_cap(lc); } - void line_join(vcgen_stroke::line_join_e lj) { base_type::generator().line_join(lj); } + void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); } + void line_join(line_join_e lj) { base_type::generator().line_join(lj); } + void inner_line_join(line_join_e lj) { base_type::generator().inner_line_join(lj); } - vcgen_stroke::line_cap_e line_cap() const { return base_type::generator().line_cap(); } - vcgen_stroke::line_join_e line_join() const { return base_type::generator().line_join(); } + line_cap_e line_cap() const { return base_type::generator().line_cap(); } + line_join_e line_join() const { return base_type::generator().line_join(); } + line_join_e inner_line_join() const { return base_type::generator().inner_line_join(); } void width(double w) { base_type::generator().width(w); } void miter_limit(double ml) { base_type::generator().miter_limit(ml); } void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); } + void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); } void approximation_scale(double as) { base_type::generator().approximation_scale(as); } double width() const { return base_type::generator().width(); } double miter_limit() const { return base_type::generator().miter_limit(); } + double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); } double approximation_scale() const { return base_type::generator().approximation_scale(); } void shorten(double s) { base_type::generator().shorten(s); } diff --git a/headers/libs/agg/agg_font_cache_manager.h b/headers/libs/agg/agg_font_cache_manager.h index a2a96943ed..42adb0add2 100755 --- a/headers/libs/agg/agg_font_cache_manager.h +++ b/headers/libs/agg/agg_font_cache_manager.h @@ -299,12 +299,15 @@ namespace agg } //-------------------------------------------------------------------- - void init_embedded_adaptors(const glyph_cache* gl, double x, double y) + void init_embedded_adaptors(const glyph_cache* gl, + double x, double y, + double scale=1.0) { if(gl) { switch(gl->data_type) { + default: return; case glyph_data_mono: m_mono_adaptor.init(gl->data, gl->data_size, x, y); break; @@ -314,7 +317,7 @@ namespace agg break; case glyph_data_outline: - m_path_adaptor.init(gl->data, gl->data_size, x, y); + m_path_adaptor.init(gl->data, gl->data_size, x, y, scale); break; } } diff --git a/headers/libs/agg/agg_gray8.h b/headers/libs/agg/agg_gray8.h index e5bac0e369..6adc665f18 100755 --- a/headers/libs/agg/agg_gray8.h +++ b/headers/libs/agg/agg_gray8.h @@ -30,6 +30,7 @@ namespace agg //===================================================================gray8 struct gray8 { + typedef int8u alpha_type; int8u v; int8u a; diff --git a/headers/libs/agg/agg_gsv_text.h b/headers/libs/agg/agg_gsv_text.h index cb9b50bcaf..c8c5421ede 100644 --- a/headers/libs/agg/agg_gsv_text.h +++ b/headers/libs/agg/agg_gsv_text.h @@ -132,8 +132,8 @@ namespace agg void rewind(unsigned id) { m_trans.rewind(id); - m_polyline.line_join(vcgen_stroke::round_join); - m_polyline.line_cap(vcgen_stroke::round_cap); + m_polyline.line_join(round_join); + m_polyline.line_cap(round_cap); } unsigned vertex(double* x, double* y) diff --git a/headers/libs/agg/agg_math_stroke.h b/headers/libs/agg/agg_math_stroke.h new file mode 100644 index 0000000000..4ee8f45789 --- /dev/null +++ b/headers/libs/agg/agg_math_stroke.h @@ -0,0 +1,340 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.2 +// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Stroke math +// +//---------------------------------------------------------------------------- + +#ifndef AGG_STROKE_MATH_INCLUDED +#define AGG_STROKE_MATH_INCLUDED + +#include "agg_math.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + //-------------------------------------------------------------line_cap_e + enum line_cap_e + { + butt_cap, + square_cap, + round_cap + }; + + //------------------------------------------------------------line_join_e + enum line_join_e + { + miter_join, + miter_join_revert, + round_join, + bevel_join + }; + + // Minimal angle to calculate round joins, less than 0.1 degree. + const double stroke_theta = 0.001; //----stroke_theta + + + //--------------------------------------------------------stroke_calc_arc + template + void stroke_calc_arc(VertexConsumer& out_vertices, + double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double width, + double approximation_scale) + { + typedef typename VertexConsumer::value_type coord_type; + + // Check if we actually need the arc + //----------------- + double dd = calc_distance(dx1, dy1, dx2, dy2); + if(dd < approximation_scale) + { + out_vertices.add(coord_type(x + dx1, y + dy1)); + if(dd > approximation_scale * 0.25) + { + out_vertices.add(coord_type(x + dx2, y + dy2)); + } + return; + } + + double a1 = atan2(dy1, dx1); + double a2 = atan2(dy2, dx2); + double da = a1 - a2; + + //if(fabs(da) < stroke_theta) + //{ + // out_vertices.add(coord_type(x + dx1, y + dy1)); + // //out_vertices.add(coord_type(x + dx2, y + dy2)); + // return; + //} + + bool ccw = da > 0.0 && da < pi; + + if(width < 0) width = -width; + da = fabs(1.0 / (width * approximation_scale)); + if(!ccw) + { + if(a1 > a2) a2 += 2 * pi; + while(a1 < a2) + { + out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width)); + a1 += da; + } + } + else + { + if(a1 < a2) a2 -= 2 * pi; + while(a1 > a2) + { + out_vertices.add(coord_type(x + cos(a1) * width, y + sin(a1) * width)); + a1 -= da; + } + } + out_vertices.add(coord_type(x + dx2, y + dy2)); + } + + + + //-------------------------------------------------------stroke_calc_miter + template + void stroke_calc_miter(VertexConsumer& out_vertices, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double dx1, double dy1, + double dx2, double dy2, + double width, + bool revert_flag, + double miter_limit) + { + typedef typename VertexConsumer::value_type coord_type; + + double xi = v1.x; + double yi = v1.y; + + if(!calc_intersection(v0.x + dx1, v0.y - dy1, + v1.x + dx1, v1.y - dy1, + v1.x + dx2, v1.y - dy2, + v2.x + dx2, v2.y - dy2, + &xi, &yi)) + { + // The calculation didn't succeed, most probaly + // the three points lie one straight line + //---------------- + if(calc_distance(dx1, -dy1, dx2, -dy2) < width * 0.025) + { + // This case means that the next segment continues + // the previous one (straight line) + //----------------- + out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1)); + } + else + { + // This case means that the next segment goes back + //----------------- + if(revert_flag) + { + out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1)); + out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2)); + } + else + { + // If no miter-revert, calcuate new dx1, dy1, dx2, dy2 + out_vertices.add(coord_type(v1.x + dx1 + dy1 * miter_limit, + v1.y - dy1 + dx1 * miter_limit)); + out_vertices.add(coord_type(v1.x + dx2 - dy2 * miter_limit, + v1.y - dy2 - dx2 * miter_limit)); + } + } + } + else + { + double d1 = calc_distance(v1.x, v1.y, xi, yi); + double lim = width * miter_limit; + if(d1 > lim) + { + // Miter limit exceeded + //------------------------ + if(revert_flag) + { + // For the compatibility with SVG, PDF, etc, + // we use a simple bevel join instead of + // "smart" bevel + //------------------- + out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1)); + out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2)); + } + else + { + // Smart bevel that cuts the miter at the limit point + //------------------- + d1 = lim / d1; + double x1 = v1.x + dx1; + double y1 = v1.y - dy1; + double x2 = v1.x + dx2; + double y2 = v1.y - dy2; + + x1 += (xi - x1) * d1; + y1 += (yi - y1) * d1; + x2 += (xi - x2) * d1; + y2 += (yi - y2) * d1; + out_vertices.add(coord_type(x1, y1)); + out_vertices.add(coord_type(x2, y2)); + } + } + else + { + // Inside the miter limit + //--------------------- + out_vertices.add(coord_type(xi, yi)); + } + } + } + + + + + + + //--------------------------------------------------------stroke_calc_cap + template + void stroke_calc_cap(VertexConsumer& out_vertices, + const vertex_dist& v0, + const vertex_dist& v1, + double len, + line_cap_e line_cap, + double width, + double approximation_scale) + { + typedef typename VertexConsumer::value_type coord_type; + + out_vertices.remove_all(); + + double dx1 = width * (v1.y - v0.y) / len; + double dy1 = width * (v1.x - v0.x) / len; + double dx2 = 0; + double dy2 = 0; + + if(line_cap == square_cap) + { + dx2 = dy1; + dy2 = dx1; + } + + if(line_cap == round_cap) + { + double a1 = atan2(dy1, -dx1); + double a2 = a1 + pi; + double da = fabs(1.0 / (width * approximation_scale)); + while(a1 < a2) + { + out_vertices.add(coord_type(v0.x + cos(a1) * width, + v0.y + sin(a1) * width)); + a1 += da; + } + out_vertices.add(coord_type(v0.x + dx1, v0.y - dy1)); + } + else + { + out_vertices.add(coord_type(v0.x - dx1 - dx2, v0.y + dy1 - dy2)); + out_vertices.add(coord_type(v0.x + dx1 - dx2, v0.y - dy1 - dy2)); + } + } + + + + //-------------------------------------------------------stroke_calc_join + template + void stroke_calc_join(VertexConsumer& out_vertices, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double len1, + double len2, + double width, + line_join_e line_join, + line_join_e inner_line_join, + double miter_limit, + double inner_miter_limit, + double approximation_scale) + { + typedef typename VertexConsumer::value_type coord_type; + + double dx1, dy1, dx2, dy2; + + dx1 = width * (v1.y - v0.y) / len1; + dy1 = width * (v1.x - v0.x) / len1; + + dx2 = width * (v2.y - v1.y) / len2; + dy2 = width * (v2.x - v1.x) / len2; + + out_vertices.remove_all(); + + if(calc_point_location(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y) > 0.0) + { + // Inner join + //--------------- + stroke_calc_miter(out_vertices, + v0, v1, v2, dx1, dy1, dx2, dy2, + width, + inner_line_join == miter_join_revert, + inner_miter_limit); + } + else + { + // Outer join + //--------------- + switch(line_join) + { + case miter_join: + stroke_calc_miter(out_vertices, + v0, v1, v2, dx1, dy1, dx2, dy2, + width, + false, + miter_limit); + break; + + case miter_join_revert: + stroke_calc_miter(out_vertices, + v0, v1, v2, dx1, dy1, dx2, dy2, + width, + true, + miter_limit); + break; + + case round_join: + stroke_calc_arc(out_vertices, + v1.x, v1.y, dx1, -dy1, dx2, -dy2, + width, approximation_scale); + break; + + default: // Bevel join + out_vertices.add(coord_type(v1.x + dx1, v1.y - dy1)); + if(calc_distance(dx1, dy1, dx2, dy2) > approximation_scale * 0.25) + { + out_vertices.add(coord_type(v1.x + dx2, v1.y - dy2)); + } + break; + } + } + } + + + + +} + +#endif diff --git a/headers/libs/agg/agg_path_storage.h b/headers/libs/agg/agg_path_storage.h index 8fbc4d4241..277a962abd 100644 --- a/headers/libs/agg/agg_path_storage.h +++ b/headers/libs/agg/agg_path_storage.h @@ -166,11 +166,6 @@ namespace agg bool solid_path = false, unsigned end_flags = path_flags_none); - void add_vertices(const double* vertices, unsigned num) - { - add_poly(vertices, num, path_flags_none); - } - template void add_path(VertexSource& vs, unsigned path_id = 0, diff --git a/headers/libs/agg/agg_path_storage_integer.h b/headers/libs/agg/agg_path_storage_integer.h index f140bbcbf7..2773336522 100755 --- a/headers/libs/agg/agg_path_storage_integer.h +++ b/headers/libs/agg/agg_path_storage_integer.h @@ -45,10 +45,12 @@ namespace agg x(((x_ << 1) & ~1) | (flag & 1)), y(((y_ << 1) & ~1) | (flag >> 1)) {} - unsigned vertex(double* x_, double* y_, double dx=0, double dy=0) const + unsigned vertex(double* x_, double* y_, + double dx=0, double dy=0, + double scale=1.0) const { - *x_ = dx + (double(x >> 1) / coord_mult); - *y_ = dy + (double(y >> 1) / coord_mult); + *x_ = dx + (double(x >> 1) / coord_mult) * scale; + *y_ = dy + (double(y >> 1) / coord_mult) * scale; switch(((y & 1) << 1) | (x & 1)) { case cmd_move_to: return path_cmd_move_to; @@ -171,7 +173,7 @@ namespace agg rect_d bounds(1e100, 1e100, -1e100, -1e100); if(m_storage.size() == 0) { - bounds.x1 = bounds.x1 = bounds.x2 = bounds.y2 = 0.0; + bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0; } else { @@ -212,7 +214,8 @@ namespace agg m_ptr(0), m_dx(0.0), m_dy(0.0), - m_closed(true) + m_scale(1.0), + m_vertices(0) {} //-------------------------------------------------------------------- @@ -223,26 +226,28 @@ namespace agg m_ptr(data), m_dx(dx), m_dy(dy), - m_closed(true) + m_vertices(0) {} //-------------------------------------------------------------------- - void init(const int8u* data, unsigned size, double dx, double dy) + void init(const int8u* data, unsigned size, + double dx, double dy, double scale=1.0) { - m_data = data; - m_end = data + size; - m_ptr = data; - m_dx = dx; - m_dy = dy; - m_closed = true; + m_data = data; + m_end = data + size; + m_ptr = data; + m_dx = dx; + m_dy = dy; + m_scale = scale; + m_vertices = 0; } //-------------------------------------------------------------------- void rewind(unsigned) { - m_ptr = m_data; - m_closed = true; + m_ptr = m_data; + m_vertices = 0; } //-------------------------------------------------------------------- @@ -254,6 +259,7 @@ namespace agg *y = 0; return path_cmd_stop; } + if(m_ptr == m_end) { *x = 0; @@ -264,15 +270,15 @@ namespace agg vertex_integer_type v; memcpy(&v, m_ptr, sizeof(vertex_integer_type)); - unsigned cmd = v.vertex(x, y, m_dx, m_dy); - if(is_move_to(cmd) && !m_closed) + unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale); + if(is_move_to(cmd) && m_vertices > 2) { *x = 0; *y = 0; - m_closed = true; + m_vertices = 0; return path_cmd_end_poly | path_flags_close; } - m_closed = false; + ++m_vertices; m_ptr += sizeof(vertex_integer_type); return cmd; } @@ -283,7 +289,8 @@ namespace agg const int8u* m_ptr; double m_dx; double m_dy; - bool m_closed; + double m_scale; + unsigned m_vertices; }; } diff --git a/headers/libs/agg/agg_pixfmt_crb_rgba32.h b/headers/libs/agg/agg_pixfmt_crb_rgba32.h new file mode 100644 index 0000000000..fe045261ee --- /dev/null +++ b/headers/libs/agg/agg_pixfmt_crb_rgba32.h @@ -0,0 +1,429 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.2 +// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_CRB_RGBA32_INCLUDED +#define AGG_PIXFMT_CRB_RGBA32_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_color_rgba8.h" + +namespace agg +{ + + //================================================pixel_formats_crb_rgba32 + template class pixel_formats_crb_rgba32 + { + public: + typedef rgba8 color_type; + typedef RenBuf buffer_type; + typedef Order order_type; + + typedef typename RenBuf::row_data row_data; + + //-------------------------------------------------------------------- + pixel_formats_crb_rgba32(RenBuf& rb) : m_rbuf(&rb) {} + + //-------------------------------------------------------------------- + unsigned width() const { return m_rbuf->width(); } + unsigned height() const { return m_rbuf->height(); } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + const int8u* p = m_rbuf->span_ptr(x, y, 1); + return p ? color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]) : + color_type::no_color(); + } + + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return m_rbuf->span(x, y); + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + int8u* p = m_rbuf->span_ptr(x, y, 1); + p[Order::R] = (int8u)c.r; + p[Order::G] = (int8u)c.g; + p[Order::B] = (int8u)c.b; + p[Order::A] = (int8u)c.a; + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + int8u* p = m_rbuf->span_ptr(x, y, 1); + int alpha = int(cover) * int(c.a); + if(alpha == 255*255) + { + p[Order::R] = (int8u)c.r; + p[Order::G] = (int8u)c.g; + p[Order::B] = (int8u)c.b; + p[Order::A] = (int8u)c.a; + } + else + { + int r = p[Order::R]; + int g = p[Order::G]; + int b = p[Order::B]; + int a = p[Order::A]; + p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); + p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); + p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); + p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); + } + } + + //-------------------------------------------------------------------- + void copy_hline(int x, int y, unsigned len, const color_type& c) + { + int32u v; + int8u* p8 = (int8u*)&v; + p8[Order::R] = (int8u)c.r; + p8[Order::G] = (int8u)c.g; + p8[Order::B] = (int8u)c.b; + p8[Order::A] = (int8u)c.a; + int32u* p32 = (int32u*)(m_rbuf->span_ptr(x, y, len)); + do + { + *p32++ = v; + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y, unsigned len, const color_type& c) + { + int32u v; + int8u* p8 = (int8u*)&v; + p8[Order::R] = (int8u)c.r; + p8[Order::G] = (int8u)c.g; + p8[Order::B] = (int8u)c.b; + p8[Order::A] = (int8u)c.a; + do + { + *(int32u*)(m_rbuf->span_ptr(x, y, 1)) = v; + ++y; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { + int alpha = int(cover) * int(c.a); + if(alpha == 255*255) + { + int32u v; + int8u* p8 = (int8u*)&v; + p8[Order::R] = (int8u)c.r; + p8[Order::G] = (int8u)c.g; + p8[Order::B] = (int8u)c.b; + p8[Order::A] = (int8u)c.a; + int32u* p32 = (int32u*)(m_rbuf->span_ptr(x, y, len)); + do + { + *p32++ = v; + } + while(--len); + } + else + { + int8u* p = m_rbuf->span_ptr(x, y, len); + do + { + int r = p[Order::R]; + int g = p[Order::G]; + int b = p[Order::B]; + int a = p[Order::A]; + p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); + p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); + p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); + p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); + p += 4; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { + int alpha = int(cover) * c.a; + if(alpha == 255*255) + { + int32u v; + int8u* p8 = (int8u*)&v; + p8[Order::R] = (int8u)c.r; + p8[Order::G] = (int8u)c.g; + p8[Order::B] = (int8u)c.b; + p8[Order::A] = (int8u)c.a; + do + { + *(int32u*)(m_rbuf->span_ptr(x, y, 1)) = v; + ++y; + } + while(--len); + } + else + { + do + { + int8u* p = m_rbuf->span_ptr(x, y, 1); + int r = p[Order::R]; + int g = p[Order::G]; + int b = p[Order::B]; + int a = p[Order::A]; + p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); + p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); + p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); + p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); + ++y; + } + while(--len); + } + } + + + + //-------------------------------------------------------------------- + template void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row(ysrc); + if(p) + { + p += xsrc << 2; + memmove(m_rbuf->span_ptr(xdst, ydst, len), p, len * 4); + } + } + + + + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& from, + const int8u* psrc, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + int8u* pdst = m_rbuf->span_ptr(xdst, ydst, len); + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } + do + { + int alpha = psrc[src_order::A]; + + if(alpha) + { + if(alpha == 255) + { + pdst[Order::R] = psrc[src_order::R]; + pdst[Order::G] = psrc[src_order::G]; + pdst[Order::B] = psrc[src_order::B]; + pdst[Order::A] = psrc[src_order::A]; + } + else + { + int r = pdst[Order::R]; + int g = pdst[Order::G]; + int b = pdst[Order::B]; + int a = pdst[Order::A]; + pdst[Order::R] = (int8u)((((psrc[src_order::R] - r) * alpha) + (r << 8)) >> 8); + pdst[Order::G] = (int8u)((((psrc[src_order::G] - g) * alpha) + (g << 8)) >> 8); + pdst[Order::B] = (int8u)((((psrc[src_order::B] - b) * alpha) + (b << 8)) >> 8); + pdst[Order::A] = (int8u)((alpha + a) - ((alpha * a) >> 8)); + } + } + psrc += incp; + pdst += incp; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + int8u* p = m_rbuf->span_ptr(x, y, len); + do + { + int alpha = int(*covers++) * c.a; + + if(alpha) + { + if(alpha == 255*255) + { + p[Order::R] = (int8u)c.r; + p[Order::G] = (int8u)c.g; + p[Order::B] = (int8u)c.b; + p[Order::A] = (int8u)c.a; + } + else + { + int r = p[Order::R]; + int g = p[Order::G]; + int b = p[Order::B]; + int a = p[Order::A]; + p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); + p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); + p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); + p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); + } + } + p += 4; + } + while(--len); + } + + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + do + { + int8u* p = m_rbuf->span_ptr(x, y, 1); + int alpha = int(*covers++) * c.a; + + if(alpha) + { + if(alpha == 255*255) + { + p[Order::R] = (int8u)c.r; + p[Order::G] = (int8u)c.g; + p[Order::B] = (int8u)c.b; + p[Order::A] = (int8u)c.a; + } + else + { + int r = p[Order::R]; + int g = p[Order::G]; + int b = p[Order::B]; + int a = p[Order::A]; + p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16); + p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16); + p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16); + p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); + } + } + ++y; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + int8u* p = m_rbuf->span_ptr(x, y, len); + do + { + int alpha = colors->a * (covers ? int(*covers++) : int(cover)); + + if(alpha) + { + if(alpha == 255*255) + { + p[Order::R] = (int8u)colors->r; + p[Order::G] = (int8u)colors->g; + p[Order::B] = (int8u)colors->b; + p[Order::A] = (int8u)colors->a; + } + else + { + int r = p[Order::R]; + int g = p[Order::G]; + int b = p[Order::B]; + int a = p[Order::A]; + p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16); + p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16); + p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16); + p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); + } + } + p += 4; + ++colors; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + do + { + int8u* p = m_rbuf->span_ptr(x, y, 1); + int alpha = colors->a * (covers ? int(*covers++) : int(cover)); + + if(alpha) + { + if(alpha == 255*255) + { + p[Order::R] = (int8u)colors->r; + p[Order::G] = (int8u)colors->g; + p[Order::B] = (int8u)colors->b; + p[Order::A] = (int8u)colors->a; + } + else + { + int r = p[Order::R]; + int g = p[Order::G]; + int b = p[Order::B]; + int a = p[Order::A]; + p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16); + p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16); + p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16); + p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8); + } + } + ++y; + ++colors; + } + while(--len); + } + + private: + RenBuf* m_rbuf; + }; + + +} + +#endif + diff --git a/headers/libs/agg/agg_pixfmt_crb_rgba32_pre.h b/headers/libs/agg/agg_pixfmt_crb_rgba32_pre.h new file mode 100644 index 0000000000..c666089ea9 --- /dev/null +++ b/headers/libs/agg/agg_pixfmt_crb_rgba32_pre.h @@ -0,0 +1,345 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.2 +// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_CRB_RGBA32_PRE_INCLUDED +#define AGG_PIXFMT_CRB_RGBA32_PRE_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_color_rgba8.h" + +namespace agg +{ + + //============================================pixel_formats_crb_rgba32_pre + template class pixel_formats_crb_rgba32_pre + { + public: + typedef rgba8 color_type; + typedef RenBuf buffer_type; + typedef Order order_type; + + typedef typename RenBuf::row_data row_data; + + private: + //-------------------------------------------------------------------- + static inline void copy_pix(int8u* p, const color_type& c) + { + p[Order::R] = (int8u)c.r; + p[Order::G] = (int8u)c.g; + p[Order::B] = (int8u)c.b; + p[Order::A] = (int8u)c.a; + } + + //-------------------------------------------------------------------- + static inline void blend_pix(int8u* p, const color_type& c, + unsigned cover, unsigned alpha) + { + p[Order::R] = (int8u)((p[Order::R] * alpha + ((c.r * cover) << 8)) >> 16); + p[Order::G] = (int8u)((p[Order::G] * alpha + ((c.g * cover) << 8)) >> 16); + p[Order::B] = (int8u)((p[Order::B] * alpha + ((c.b * cover) << 8)) >> 16); + p[Order::A] = (int8u)(255 - ((alpha * (255 - p[Order::A])) >> 16)); + } + + //-------------------------------------------------------------------- + static inline void copy_or_blend_pix(int8u* p, const color_type& c, unsigned cover) + { + unsigned alpha = 65535 - cover * c.a; + + if(alpha < 65535) + { + if(alpha <= 65535-255*255) + { + copy_pix(p, c); + } + else + { + blend_pix(p, c, cover, alpha); + } + } + } + + //-------------------------------------------------------------------- + static inline void copy_or_blend_pix(int8u* p, const color_type& c) + { + unsigned alpha = 255 - c.a; + if(alpha < 255) + { + if(alpha == 0) + { + copy_pix(p, c); + } + else + { + p[Order::R] = (int8u)((p[Order::R] * alpha + (c.r << 8)) >> 8); + p[Order::G] = (int8u)((p[Order::G] * alpha + (c.g << 8)) >> 8); + p[Order::B] = (int8u)((p[Order::B] * alpha + (c.b << 8)) >> 8); + p[Order::A] = (int8u)(255 - ((alpha * (255 - p[Order::A])) >> 8)); + } + } + } + + public: + //-------------------------------------------------------------------- + pixel_formats_crb_rgba32_pre(RenBuf& rb) : m_rbuf(&rb) {} + + //-------------------------------------------------------------------- + unsigned width() const { return m_rbuf->width(); } + unsigned height() const { return m_rbuf->height(); } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + const int8u* p = m_rbuf->span_ptr(x, y, 1); + return p ? color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]) : + color_type::no_color(); + } + + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return m_rbuf->span(x, y); + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + int8u* p = m_rbuf->span_ptr(x, y, 1); + p[Order::R] = (int8u)c.r; + p[Order::G] = (int8u)c.g; + p[Order::B] = (int8u)c.b; + p[Order::A] = (int8u)c.a; + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + copy_or_blend_pix(m_rbuf->span_ptr(x, y, 1), c, cover); + } + + //-------------------------------------------------------------------- + void copy_hline(int x, int y, unsigned len, const color_type& c) + { + int32u v; + copy_pix((int8u*)&v, c); + int32u* p32 = (int32u*)(m_rbuf->span_ptr(x, y, len)); + do + { + *p32++ = v; + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y, unsigned len, const color_type& c) + { + int32u v; + copy_pix((int8u*)&v, c); + do + { + *(int32u*)(m_rbuf->span_ptr(x, y, 1)) = v; + ++y; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { + int alpha = int(cover) * int(c.a); + if(alpha == 255*255) + { + int32u v; + copy_pix((int8u*)&v, c); + int32u* p32 = (int32u*)(m_rbuf->span_ptr(x, y, len)); + do + { + *p32++ = v; + } + while(--len); + } + else + { + int8u* p = m_rbuf->span_ptr(x, y, len); + alpha = 65535 - alpha; + do + { + blend_pix(p, c, cover, alpha); + p += 4; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { + int alpha = int(cover) * c.a; + if(alpha == 255*255) + { + int32u v; + copy_pix((int8u*)&v, c); + do + { + *(int32u*)(m_rbuf->span_ptr(x, y, 1)) = v; + ++y; + } + while(--len); + } + else + { + alpha = 65535 - alpha; + do + { + blend_pix(m_rbuf->span_ptr(x, y, 1), c, cover, alpha); + ++y; + } + while(--len); + } + } + + + + //-------------------------------------------------------------------- + template void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row(ysrc); + if(p) + { + p += xsrc << 2; + memmove(m_rbuf->span_ptr(xdst, ydst, len), p, len * 4); + } + } + + + + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& from, + const int8u* psrc, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + int8u* pdst = m_rbuf->span_ptr(xdst, ydst, len); + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } + do + { + unsigned alpha = 255 - psrc[src_order::A]; + if(alpha < 255) + { + if(alpha == 0) + { + pdst[Order::R] = psrc[src_order::R]; + pdst[Order::G] = psrc[src_order::G]; + pdst[Order::B] = psrc[src_order::B]; + pdst[Order::A] = psrc[src_order::A]; + } + else + { + pdst[Order::R] = (int8u)((pdst[Order::R] * alpha + (psrc[src_order::R] << 8)) >> 8); + pdst[Order::G] = (int8u)((pdst[Order::G] * alpha + (psrc[src_order::G] << 8)) >> 8); + pdst[Order::B] = (int8u)((pdst[Order::B] * alpha + (psrc[src_order::B] << 8)) >> 8); + pdst[Order::A] = (int8u)(255 - ((alpha * (255 - pdst[Order::A])) >> 8)); + } + } + psrc += incp; + pdst += incp; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + int8u* p = m_rbuf->span_ptr(x, y, len); + do + { + copy_or_blend_pix(p, c, *covers++); + p += 4; + } + while(--len); + } + + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + do + { + copy_or_blend_pix(m_rbuf->span_ptr(x, y, 1), c, *covers++); + ++y; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + int8u* p = m_rbuf->span_ptr(x, y, len); + do + { + copy_or_blend_pix(p, *colors++, covers ? *covers++ : cover); + p += 4; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + do + { + copy_or_blend_pix(m_rbuf->span_ptr(x, y, 1), + *colors++, + covers ? *covers++ : cover); + ++y; + } + while(--len); + } + + private: + RenBuf* m_rbuf; + }; + + +} + +#endif + diff --git a/headers/libs/agg/agg_pixfmt_gray8.h b/headers/libs/agg/agg_pixfmt_gray8.h index 20346ac3b9..df37dfe7d5 100644 --- a/headers/libs/agg/agg_pixfmt_gray8.h +++ b/headers/libs/agg/agg_pixfmt_gray8.h @@ -30,6 +30,9 @@ namespace agg { public: typedef gray8 color_type; + typedef bool order_type; + typedef rendering_buffer::row_data row_data; + //-------------------------------------------------------------------- pixfmt_gray8_base(rendering_buffer& rb) @@ -42,11 +45,17 @@ namespace agg unsigned height() const { return m_rbuf->height(); } //-------------------------------------------------------------------- - color_type pixel(int x, int y) + color_type pixel(int x, int y) const { return color_type(m_rbuf->row(y)[x * Step + Offset]); } + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return row_data(x, width() - 1, m_rbuf->row(y) + x); + } + //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { diff --git a/headers/libs/agg/agg_pixfmt_rgb24.h b/headers/libs/agg/agg_pixfmt_rgb24.h index 513f4bf56b..5482d53d83 100644 --- a/headers/libs/agg/agg_pixfmt_rgb24.h +++ b/headers/libs/agg/agg_pixfmt_rgb24.h @@ -29,6 +29,8 @@ namespace agg { public: typedef rgba8 color_type; + typedef Order order_type; + typedef rendering_buffer::row_data row_data; //-------------------------------------------------------------------- pixel_formats_rgb24(rendering_buffer& rb) @@ -41,12 +43,18 @@ namespace agg unsigned height() const { return m_rbuf->height(); } //-------------------------------------------------------------------- - color_type pixel(int x, int y) + color_type pixel(int x, int y) const { int8u* p = m_rbuf->row(y) + x + x + x; return color_type(p[Order::R], p[Order::G], p[Order::B]); } + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return row_data(x, width() - 1, m_rbuf->row(y) + x * 3); + } + //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { diff --git a/headers/libs/agg/agg_pixfmt_rgb24_gamma.h b/headers/libs/agg/agg_pixfmt_rgb24_gamma.h index 1a92229759..c5be4b66cd 100644 --- a/headers/libs/agg/agg_pixfmt_rgb24_gamma.h +++ b/headers/libs/agg/agg_pixfmt_rgb24_gamma.h @@ -32,6 +32,8 @@ namespace agg public: typedef rgba8 color_type; typedef Gamma gamma_type; + typedef Order order_type; + typedef rendering_buffer::row_data row_data; private: //-------------------------------------------------------------------- @@ -105,12 +107,18 @@ namespace agg unsigned height() const { return m_rbuf->height(); } //-------------------------------------------------------------------- - color_type pixel(int x, int y) + color_type pixel(int x, int y) const { int8u* p = m_rbuf->row(y) + x + x + x; return color_type(p[Order::R], p[Order::G], p[Order::B]); } + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return row_data(x, width() - 1, m_rbuf->row(y) + x * 3); + } + //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { diff --git a/headers/libs/agg/agg_pixfmt_rgb24_pre.h b/headers/libs/agg/agg_pixfmt_rgb24_pre.h index 5edc92f237..67b10b3524 100644 --- a/headers/libs/agg/agg_pixfmt_rgb24_pre.h +++ b/headers/libs/agg/agg_pixfmt_rgb24_pre.h @@ -30,7 +30,8 @@ namespace agg { public: typedef rgba8 color_type; - + typedef Order order_type; + typedef rendering_buffer::row_data row_data; private: //-------------------------------------------------------------------- @@ -101,12 +102,18 @@ namespace agg unsigned height() const { return m_rbuf->height(); } //-------------------------------------------------------------------- - color_type pixel(int x, int y) + color_type pixel(int x, int y) const { int8u* p = m_rbuf->row(y) + x + x + x; return color_type(p[Order::R], p[Order::G], p[Order::B]); } + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return row_data(x, width() - 1, m_rbuf->row(y) + x * 3); + } + //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { diff --git a/headers/libs/agg/agg_pixfmt_rgb555.h b/headers/libs/agg/agg_pixfmt_rgb555.h index ab0eab8f62..2f8f5fc5b9 100644 --- a/headers/libs/agg/agg_pixfmt_rgb555.h +++ b/headers/libs/agg/agg_pixfmt_rgb555.h @@ -36,6 +36,8 @@ namespace agg { public: typedef rgba8 color_type; + typedef bool order_type; + typedef rendering_buffer::row_data row_data; //-------------------------------------------------------------------- pixfmt_rgb555(rendering_buffer& rb) @@ -48,7 +50,7 @@ namespace agg unsigned height() const { return m_rbuf->height(); } //-------------------------------------------------------------------- - color_type pixel(int x, int y) + color_type pixel(int x, int y) const { unsigned rgb = ((int16u*)(m_rbuf->row(y)))[x]; return color_type((rgb >> 7) & 0xF8, @@ -56,6 +58,12 @@ namespace agg (rgb << 3) & 0xF8); } + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return row_data(x, width() - 1, m_rbuf->row(y) + x * 2); + } + //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { diff --git a/headers/libs/agg/agg_pixfmt_rgb565.h b/headers/libs/agg/agg_pixfmt_rgb565.h index 45713a2561..88c4021207 100644 --- a/headers/libs/agg/agg_pixfmt_rgb565.h +++ b/headers/libs/agg/agg_pixfmt_rgb565.h @@ -36,6 +36,8 @@ namespace agg { public: typedef rgba8 color_type; + typedef bool order_type; + typedef rendering_buffer::row_data row_data; //-------------------------------------------------------------------- pixfmt_rgb565(rendering_buffer& rb) @@ -48,7 +50,7 @@ namespace agg unsigned height() const { return m_rbuf->height(); } //-------------------------------------------------------------------- - color_type pixel(int x, int y) + color_type pixel(int x, int y) const { unsigned rgb = ((int16u*)(m_rbuf->row(y)))[x]; return color_type((rgb >> 8) & 0xF8, @@ -56,6 +58,12 @@ namespace agg (rgb << 3) & 0xF8); } + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return row_data(x, width() - 1, m_rbuf->row(y) + x * 2); + } + //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { diff --git a/headers/libs/agg/agg_pixfmt_rgba32.h b/headers/libs/agg/agg_pixfmt_rgba32.h index 236eea57d1..a1a8cc2bc9 100644 --- a/headers/libs/agg/agg_pixfmt_rgba32.h +++ b/headers/libs/agg/agg_pixfmt_rgba32.h @@ -29,6 +29,8 @@ namespace agg { public: typedef rgba8 color_type; + typedef Order order_type; + typedef rendering_buffer::row_data row_data; //-------------------------------------------------------------------- pixel_formats_rgba32(rendering_buffer& rb) @@ -41,12 +43,18 @@ namespace agg unsigned height() const { return m_rbuf->height(); } //-------------------------------------------------------------------- - color_type pixel(int x, int y) + color_type pixel(int x, int y) const { int8u* p = m_rbuf->row(y) + (x << 2); return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]); } + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return row_data(x, width() - 1, m_rbuf->row(y) + (x << 2)); + } + //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { @@ -207,6 +215,59 @@ namespace agg } + + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& from, + const int8u* psrc, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + + int8u* pdst = m_rbuf->row(ydst) + (xdst << 2); + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } + do + { + int alpha = psrc[src_order::A]; + + if(alpha) + { + if(alpha == 255) + { + pdst[Order::R] = psrc[src_order::R]; + pdst[Order::G] = psrc[src_order::G]; + pdst[Order::B] = psrc[src_order::B]; + pdst[Order::A] = psrc[src_order::A]; + } + else + { + int r = pdst[Order::R]; + int g = pdst[Order::G]; + int b = pdst[Order::B]; + int a = pdst[Order::A]; + pdst[Order::R] = (int8u)((((psrc[src_order::R] - r) * alpha) + (r << 8)) >> 8); + pdst[Order::G] = (int8u)((((psrc[src_order::G] - g) * alpha) + (g << 8)) >> 8); + pdst[Order::B] = (int8u)((((psrc[src_order::B] - b) * alpha) + (b << 8)) >> 8); + pdst[Order::A] = (int8u)((alpha + a) - ((alpha * a) >> 8)); + } + } + psrc += incp; + pdst += incp; + } + while(--len); + } + + + + //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) diff --git a/headers/libs/agg/agg_pixfmt_rgba32_plain.h b/headers/libs/agg/agg_pixfmt_rgba32_plain.h index 2b49e67880..286e4ef247 100644 --- a/headers/libs/agg/agg_pixfmt_rgba32_plain.h +++ b/headers/libs/agg/agg_pixfmt_rgba32_plain.h @@ -30,7 +30,8 @@ namespace agg { public: typedef rgba8 color_type; - + typedef Order order_type; + typedef rendering_buffer::row_data row_data; private: //-------------------------------------------------------------------- @@ -117,12 +118,18 @@ namespace agg unsigned height() const { return m_rbuf->height(); } //-------------------------------------------------------------------- - color_type pixel(int x, int y) + color_type pixel(int x, int y) const { int8u* p = m_rbuf->row(y) + (x << 2); return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]); } + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return row_data(x, width() - 1, m_rbuf->row(y) + (x << 2)); + } + //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { diff --git a/headers/libs/agg/agg_pixfmt_rgba32_pre.h b/headers/libs/agg/agg_pixfmt_rgba32_pre.h index f0c6409b24..fb50ba8a6e 100644 --- a/headers/libs/agg/agg_pixfmt_rgba32_pre.h +++ b/headers/libs/agg/agg_pixfmt_rgba32_pre.h @@ -30,6 +30,8 @@ namespace agg { public: typedef rgba8 color_type; + typedef Order order_type; + typedef rendering_buffer::row_data row_data; private: @@ -104,12 +106,18 @@ namespace agg unsigned height() const { return m_rbuf->height(); } //-------------------------------------------------------------------- - color_type pixel(int x, int y) + color_type pixel(int x, int y) const { int8u* p = m_rbuf->row(y) + (x << 2); return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]); } + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + return row_data(x, width() - 1, m_rbuf->row(y) + (x << 2)); + } + //-------------------------------------------------------------------- void copy_pixel(int x, int y, const color_type& c) { @@ -223,6 +231,52 @@ namespace agg } + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& from, + const int8u* psrc, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + + int8u* pdst = m_rbuf->row(ydst) + (xdst << 2); + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } + do + { + unsigned alpha = 255 - psrc[src_order::A]; + if(alpha < 255) + { + if(alpha == 0) + { + pdst[Order::R] = psrc[src_order::R]; + pdst[Order::G] = psrc[src_order::G]; + pdst[Order::B] = psrc[src_order::B]; + pdst[Order::A] = psrc[src_order::A]; + } + else + { + pdst[Order::R] = (int8u)((pdst[Order::R] * alpha + (psrc[src_order::R] << 8)) >> 8); + pdst[Order::G] = (int8u)((pdst[Order::G] * alpha + (psrc[src_order::G] << 8)) >> 8); + pdst[Order::B] = (int8u)((pdst[Order::B] * alpha + (psrc[src_order::B] << 8)) >> 8); + pdst[Order::A] = (int8u)(255 - ((alpha * (255 - pdst[Order::A])) >> 8)); + } + } + psrc += incp; + pdst += incp; + } + while(--len); + } + + + //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, unsigned len, const color_type& c, const int8u* covers) diff --git a/headers/libs/agg/agg_rasterizer_scanline_aa.h b/headers/libs/agg/agg_rasterizer_scanline_aa.h index 15902c468f..e7d3e53fda 100644 --- a/headers/libs/agg/agg_rasterizer_scanline_aa.h +++ b/headers/libs/agg/agg_rasterizer_scanline_aa.h @@ -148,34 +148,6 @@ namespace agg }; - - //----------------------------------------------------------clipping_flags - // Determine the clipping code of the vertex according to the - // Cyrus-Beck line clipping algorithm - // - // | | - // 0110 | 0010 | 0011 - // | | - // -------+--------+-------- clip_box.y2 - // | | - // 0100 | 0000 | 0001 - // | | - // -------+--------+-------- clip_box.y1 - // | | - // 1100 | 1000 | 1001 - // | | - // clip_box.x1 clip_box.x2 - // - // - inline unsigned clipping_flags(int x, int y, const rect& clip_box) - { - return (x > clip_box.x2) | - ((y > clip_box.y2) << 1) | - ((x < clip_box.x1) << 2) | - ((y < clip_box.y1) << 3); - } - - //==================================================rasterizer_scanline_aa // Polygon rasterizer that is used to render filled polygons with // high-quality Anti-Aliasing. Internally, by default, the class uses @@ -207,7 +179,7 @@ namespace agg // // filling_rule() and gamma() can be called anytime before "sweeping". //------------------------------------------------------------------------ - template class rasterizer_scanline_aa + template class rasterizer_scanline_aa { enum status { @@ -455,9 +427,9 @@ namespace agg private: //-------------------------------------------------------------------- // Disable copying - rasterizer_scanline_aa(const rasterizer_scanline_aa&); - const rasterizer_scanline_aa& - operator = (const rasterizer_scanline_aa&); + rasterizer_scanline_aa(const rasterizer_scanline_aa&); + const rasterizer_scanline_aa& + operator = (const rasterizer_scanline_aa&); //-------------------------------------------------------------------- void move_to_no_clip(int x, int y); @@ -492,23 +464,23 @@ namespace agg //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::reset() + template + void rasterizer_scanline_aa::reset() { m_outline.reset(); m_status = status_initial; } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::filling_rule(filling_rule_e filling_rule) + template + void rasterizer_scanline_aa::filling_rule(filling_rule_e filling_rule) { m_filling_rule = filling_rule; } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::clip_box(double x1, double y1, double x2, double y2) + template + void rasterizer_scanline_aa::clip_box(double x1, double y1, double x2, double y2) { reset(); m_clip_box = rect(poly_coord(x1), poly_coord(y1), @@ -518,8 +490,8 @@ namespace agg } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::reset_clipping() + template + void rasterizer_scanline_aa::reset_clipping() { reset(); m_clipping = false; @@ -528,14 +500,14 @@ namespace agg //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::move_to_no_clip(int x, int y) + template + void rasterizer_scanline_aa::move_to_no_clip(int x, int y) { if(m_status == status_line_to) { close_polygon_no_clip(); } - m_outline.move_to(x, y); + m_outline.move_to(x * XScale, y); m_clipped_start_x = x; m_clipped_start_y = y; m_status = status_line_to; @@ -543,32 +515,32 @@ namespace agg //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::line_to_no_clip(int x, int y) + template + void rasterizer_scanline_aa::line_to_no_clip(int x, int y) { if(m_status != status_initial) { - m_outline.line_to(x, y); + m_outline.line_to(x * XScale, y); m_status = status_line_to; } } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::close_polygon_no_clip() + template + void rasterizer_scanline_aa::close_polygon_no_clip() { if(m_status == status_line_to) { - m_outline.line_to(m_clipped_start_x, m_clipped_start_y); + m_outline.line_to(m_clipped_start_x * XScale, m_clipped_start_y); m_status = status_closed; } } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::clip_segment(int x, int y) + template + void rasterizer_scanline_aa::clip_segment(int x, int y) { unsigned flags = clipping_flags(x, y, m_clip_box); if(m_prev_flags == flags) @@ -615,8 +587,8 @@ namespace agg //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::add_vertex(double x, double y, unsigned cmd) + template + void rasterizer_scanline_aa::add_vertex(double x, double y, unsigned cmd) { if(is_close(cmd)) { @@ -641,8 +613,8 @@ namespace agg //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::move_to(int x, int y) + template + void rasterizer_scanline_aa::move_to(int x, int y) { if(m_clipping) { @@ -670,8 +642,8 @@ namespace agg } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::line_to(int x, int y) + template + void rasterizer_scanline_aa::line_to(int x, int y) { if(m_clipping) { @@ -684,8 +656,8 @@ namespace agg } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::close_polygon() + template + void rasterizer_scanline_aa::close_polygon() { if(m_clipping) { @@ -695,23 +667,23 @@ namespace agg } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::move_to_d(double x, double y) + template + void rasterizer_scanline_aa::move_to_d(double x, double y) { move_to(poly_coord(x), poly_coord(y)); } //------------------------------------------------------------------------ - template - void rasterizer_scanline_aa::line_to_d(double x, double y) + template + void rasterizer_scanline_aa::line_to_d(double x, double y) { line_to(poly_coord(x), poly_coord(y)); } //------------------------------------------------------------------------ - template - bool rasterizer_scanline_aa::hit_test(int tx, int ty) + template + bool rasterizer_scanline_aa::hit_test(int tx, int ty) { close_polygon(); const cell_aa* const* cells = m_outline.cells(); diff --git a/headers/libs/agg/agg_renderer_base.h b/headers/libs/agg/agg_renderer_base.h index f83406d49c..f4d4bdf8ea 100644 --- a/headers/libs/agg/agg_renderer_base.h +++ b/headers/libs/agg/agg_renderer_base.h @@ -25,6 +25,7 @@ namespace agg { + //-----------------------------------------------------------renderer_base template class renderer_base { @@ -371,43 +372,169 @@ namespace agg m_ren->blend_color_vspan(x, y, len, colors, covers, cover); } + //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - const rect* rc=0, - int x_to=0, - int y_to=0) + rect clip_rect_area(rect& dst, rect& src, int wsrc, int hsrc) const { - rect tmp_rect(0, 0, from.width(), from.height()); - if(rc == 0) + rect rc(0,0,0,0); + rect cb = clip_box(); + ++cb.x2; + ++cb.y2; + + if(src.x1 < 0) { - rc = &tmp_rect; + dst.x1 -= src.x1; + src.x1 = 0; + } + if(src.y1 < 0) + { + dst.y1 -= src.y1; + src.y1 = 0; } - rect rc2(*rc); - rc2.normalize(); - if(rc2.clip(rect(0, 0, from.width() - 1, from.height() - 1))) - { - rect rc3(x_to + rc2.x1 - rc->x1, - y_to + rc2.y1 - rc->y1, - x_to + rc2.x2 - rc->x1, - y_to + rc2.y2 - rc->y1); - rc3.normalize(); + if(src.x2 > wsrc) src.x2 = wsrc; + if(src.y2 > hsrc) src.y2 = hsrc; - if(rc3.clip(clip_box())) + if(dst.x1 < cb.x1) + { + src.x1 += cb.x1 - dst.x1; + dst.x1 = cb.x1; + } + if(dst.y1 < cb.y1) + { + src.y1 += cb.y1 - dst.y1; + dst.y1 = cb.y1; + } + + if(dst.x2 > cb.x2) dst.x2 = cb.x2; + if(dst.y2 > cb.y2) dst.y2 = cb.y2; + + rc.x2 = dst.x2 - dst.x1; + rc.y2 = dst.y2 - dst.y1; + + if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1; + if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1; + return rc; + } + + + //-------------------------------------------------------------------- + void copy_from(const rendering_buffer& src, + const rect* rect_src_ptr = 0, + int dx = 0, + int dy = 0) + { + rect rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + + rect rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) { - while(rc3.y1 <= rc3.y2) - { - m_ren->copy_from(from, - rc3.x1, rc3.y1, - rc2.x1, rc2.y1, - rc3.x2 - rc3.x1 + 1); - ++rc2.y1; - ++rc3.y1; - } + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + m_ren->copy_from(src, + rdst.x1, rdst.y1, + rsrc.x1, rsrc.y1, + rc.x2); + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; } } } - + + + + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& src, + const rect* rect_src_ptr = 0, + int dx = 0, + int dy = 0) + { + rect rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + + rect rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + typename SrcPixelFormatRenderer::row_data span = src.span(rsrc.x1, rsrc.y1); + if(span.ptr) + { + int x1src = rsrc.x1; + int x1dst = rdst.x1; + int len = rc.x2; + if(span.x1 > x1src) + { + x1dst += span.x1 - x1src; + len -= span.x1 - x1src; + x1src = span.x1; + } + if(len > 0) + { + if(x1src + len-1 > span.x2) + { + len -= x1src + len - span.x2 - 1; + } + if(len > 0) + { + m_ren->blend_from(src, span.ptr, + x1dst, rdst.y1, + x1src, rsrc.y1, + len); + } + } + } + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + private: pixfmt_type* m_ren; diff --git a/headers/libs/agg/agg_renderer_outline_image.h b/headers/libs/agg/agg_renderer_outline_image.h index 79a2c14926..5056f51208 100644 --- a/headers/libs/agg/agg_renderer_outline_image.h +++ b/headers/libs/agg/agg_renderer_outline_image.h @@ -41,6 +41,7 @@ namespace agg color_type pixel(int x, int y) const { + //double src_y = (y + 0.5) * m_scale - 0.5; double src_y = y * m_scale; int h = int(m_source.height()) - 1; int y1 = int(floor(src_y)); @@ -170,16 +171,16 @@ namespace agg int line_width() const { return m_half_height_hr; } //-------------------------------------------------------------------- - color_type pixel(int x, int y) const + void pixel(color_type* p, int x, int y) const { - return m_filter->pixel_high_res(m_buf.rows(), - x % m_width_hr + m_dilation_hr, - y + m_offset_y_hr); + m_filter->pixel_high_res(m_buf.rows(), + p, + x % m_width_hr + m_dilation_hr, + y + m_offset_y_hr); } //-------------------------------------------------------------------- - const filter_type& filter() const { return m_filter; } - filter_type& filter() { return m_filter; } + const filter_type& filter() const { return *m_filter; } private: line_image_pattern(const line_image_pattern&); @@ -830,8 +831,12 @@ namespace agg const pattern_type& pattern() const { return *m_pattern; } //--------------------------------------------------------------------- - void scale_x(double s) { m_scale_x = s; } - double scale_x() const { return m_scale_x; } + void scale_x(double s) { m_scale_x = s; } + double scale_x() const { return m_scale_x; } + + //--------------------------------------------------------------------- + void start_x(double s) { m_start = int(s * line_subpixel_size); } + double start_x() const { return double(m_start) / line_subpixel_size; } //--------------------------------------------------------------------- int subpixel_width() const { return m_pattern->line_width(); } diff --git a/headers/libs/agg/agg_renderer_scanline.h b/headers/libs/agg/agg_renderer_scanline.h index d928b375cd..e01eca29e6 100644 --- a/headers/libs/agg/agg_renderer_scanline.h +++ b/headers/libs/agg/agg_renderer_scanline.h @@ -72,9 +72,13 @@ namespace agg if(x < xmin) { len -= xmin - x; - covers += xmin - x; + if(!solid) + { + covers += xmin - x; + } x = xmin; } + if(len > 0) { if(x + len > xmax) diff --git a/headers/libs/agg/agg_rendering_buffer.h b/headers/libs/agg/agg_rendering_buffer.h index d11c0834a2..278d37ef86 100644 --- a/headers/libs/agg/agg_rendering_buffer.h +++ b/headers/libs/agg/agg_rendering_buffer.h @@ -29,6 +29,16 @@ namespace agg template class row_ptr_cache { public: + //-------------------------------------------------------------------- + struct row_data + { + int x1, x2; + const int8u* ptr; + row_data() {} + row_data(int x1_, int x2_, const int8u* ptr_) : + x1(x1_), x2(x2_), ptr(ptr_) {} + }; + //------------------------------------------------------------------- ~row_ptr_cache() { @@ -122,6 +132,22 @@ namespace agg } } + //-------------------------------------------------------------------- + void clear(T value) + { + unsigned y; + for(y = 0; y < height(); y++) + { + T* p = row(y); + unsigned x; + for(x = 0; x < stride_abs(); x++) + { + *p++ = value; + } + } + } + + private: //-------------------------------------------------------------------- // Prohibit copying diff --git a/headers/libs/agg/agg_rendering_buffer_dynarow.h b/headers/libs/agg/agg_rendering_buffer_dynarow.h new file mode 100644 index 0000000000..733e01fdb9 --- /dev/null +++ b/headers/libs/agg/agg_rendering_buffer_dynarow.h @@ -0,0 +1,184 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.2 +// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// class rendering_buffer_dynarow +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED +#define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //===============================================rendering_buffer_dynarow + // Rendering buffer class with dynamic allocation of the rows. + // The rows are allocated as needed when requesting for span_ptr(). + // The class automatically calculates min_x and max_x for each row. + // Generally it's more efficient to use this class as a temporary buffer + // for rendering a few lines and then to blend it with another buffer. + // + template class rendering_buffer_dynarow + { + public: + //------------------------------------------------------------------- + struct row_data + { + int8u* ptr; + int x1; + int x2; + }; + + //------------------------------------------------------------------- + ~rendering_buffer_dynarow() + { + init(0,0); + } + + //------------------------------------------------------------------- + rendering_buffer_dynarow() : + m_rows(0), + m_width(0), + m_height(0) + { + } + + // Allocate and clear the buffer + //-------------------------------------------------------------------- + rendering_buffer_dynarow(unsigned width, unsigned height) : + m_rows(new row_data[height]), + m_width(width), + m_height(height) + { + memset(m_rows, 0, sizeof(row_data) * height); + } + + // Allocate and clear the buffer + //-------------------------------------------------------------------- + void init(unsigned width, unsigned height) + { + unsigned i; + for(i = 0; i < m_height; ++i) delete [] m_rows[i].ptr; + delete [] m_rows; + m_rows = 0; + if(width && height) + { + m_width = width; + m_height = height; + m_rows = new row_data[height]; + memset(m_rows, 0, sizeof(row_data) * height); + } + } + + //-------------------------------------------------------------------- + unsigned width() const { return m_width; } + unsigned height() const { return m_height; } + + // Get pointer to the beginning of the row. Memory for the row + // is allocated as needed. + //-------------------------------------------------------------------- + int8u* row(int y) + { + row_data* r = m_rows + y; + if(r->ptr == 0) + { + r->ptr = new int8u [m_width * PixWidth]; + memset(r->ptr, 0, m_width * PixWidth); + } + return r->ptr; + } + + // Get const pointer to the row. The caller must check it for null. + //-------------------------------------------------------------------- + const int8u* row(int y) const + { + return m_rows[y].ptr; + } + + // Get the Y-th span. The pointer r.ptr is automatically adjusted + // to the actual beginning of the span. Use this function as follows: + // + // rendering_buffer_dynarow::row_data r = rbuf.span(x, y); + // if(r.ptr) + // { + // do { blend(r.ptr); r.ptr += PixWidth } while(++r.x1 < r.x2); + // } + //-------------------------------------------------------------------- + row_data span(int x, int y) const + { + row_data r = m_rows[y]; + if(r.ptr) + { + if(x < r.x1) x = r.x1; + r.ptr += x * PixWidth; + } + return r; + } + + + // The main function used for rendering. Returns pointer to the + // pre-allocated span. Memory for the row is allocated as needed. + //-------------------------------------------------------------------- + int8u* span_ptr(int x, int y, unsigned len) + { + row_data* r = m_rows + y; + int x2 = x + len - 1; + if(r->ptr) + { + if(x < r->x1) { r->x1 = x; } + if(x2 > r->x2) { r->x2 = x2; } + } + else + { + r->ptr = new int8u [m_width * PixWidth]; + r->x1 = x; + r->x2 = x2; + memset(r->ptr, 0, m_width * PixWidth); + } + return r->ptr + x * PixWidth; + } + + // Get const pointer to the span. Used mostly in GetPixel function + // The caller must check the returned pointer for null. + //-------------------------------------------------------------------- + const int8u* span_ptr(int x, int y, unsigned) const + { + row_data* r = m_rows + y; + return r->ptr ? r->ptr + x * PixWidth : 0; + } + + + + private: + //-------------------------------------------------------------------- + // Prohibit copying + rendering_buffer_dynarow(const rendering_buffer_dynarow&); + const rendering_buffer_dynarow& + operator = (const rendering_buffer_dynarow&); + + private: + //-------------------------------------------------------------------- + row_data* m_rows; // Pointers to each row of the buffer + unsigned m_width; // Width in pixels + unsigned m_height; // Height in pixels + }; + + +} + + +#endif diff --git a/headers/libs/agg/agg_scanline_storage_aa.h b/headers/libs/agg/agg_scanline_storage_aa.h index ec70567edd..243aa4eb3a 100644 --- a/headers/libs/agg/agg_scanline_storage_aa.h +++ b/headers/libs/agg/agg_scanline_storage_aa.h @@ -303,12 +303,13 @@ namespace agg sp.x = span_iterator->x; sp.len = span_iterator->len; + int len = abs(int(sp.len)); sp.covers_id = m_covers.add_cells(span_iterator->covers, - unsigned(abs(int(sp.len)))); + unsigned(len)); m_spans.add(sp); int x1 = sp.x; - int x2 = sp.x + sp.len - 1; + int x2 = sp.x + len - 1; if(x1 < m_min_x) m_min_x = x1; if(x2 > m_max_x) m_max_x = x2; ++span_iterator; diff --git a/headers/libs/agg/agg_scanline_storage_bin.h b/headers/libs/agg/agg_scanline_storage_bin.h index 1014d04bee..679a3f35dc 100644 --- a/headers/libs/agg/agg_scanline_storage_bin.h +++ b/headers/libs/agg/agg_scanline_storage_bin.h @@ -236,18 +236,8 @@ namespace agg for(i = 0; i < m_scanlines.size(); ++i) { - size += sizeof(int16) * 2; // Y, num_spans - - const scanline_data& sl_this = m_scanlines[i]; - - unsigned num_spans = sl_this.num_spans; - unsigned span_idx = sl_this.start_span; - do - { - const span_data& sp = m_spans[span_idx++]; - size += sizeof(int16) * 2; // X, span_len - } - while(--num_spans); + size += sizeof(int16) * 2 + // Y, num_spans + unsigned(m_scanlines[i].num_spans) * sizeof(int16) * 2; // X, span_len } return size; } diff --git a/headers/libs/agg/agg_span_converter.h b/headers/libs/agg/agg_span_converter.h index efe4cf316b..fc16c44a6b 100644 --- a/headers/libs/agg/agg_span_converter.h +++ b/headers/libs/agg/agg_span_converter.h @@ -39,7 +39,7 @@ namespace agg color_type* generate(int x, int y, unsigned len) { color_type* span = m_span_gen->generate(x, y, len); - m_conv->convert(span, len); + m_conv->convert(span, x, y, len); return span; } diff --git a/headers/libs/agg/agg_span_gradient.h b/headers/libs/agg/agg_span_gradient.h index be54477f71..a60f81cf17 100644 --- a/headers/libs/agg/agg_span_gradient.h +++ b/headers/libs/agg/agg_span_gradient.h @@ -26,6 +26,14 @@ namespace agg { + enum + { + gradient_subpixel_shift = 4, + gradient_subpixel_size = 1 << gradient_subpixel_shift, + gradient_subpixel_mask = gradient_subpixel_size - 1 + }; + + //==========================================================span_gradient template m_focus_y) ? m_trivial : -m_trivial; + } + else + { + // Slope of the focus-current line + //------------------------------- + double slope = double(y - m_focus_y) / double(x - m_focus_x); + + // y-intercept of that same line + //-------------------------------- + double yint = double(y) - (slope * x); + + // Use the classical quadratic formula to calculate + // the intersection point + //-------------------------------- + double a = (slope * slope) + 1; + double b = 2 * slope * yint; + double c = yint * yint - m_radius2; + double det = sqrt((b * b) - (4.0 * a * c)); + solution_x = -b; + + // Choose the positive or negative root depending + // on where the X coord lies with respect to the focus. + solution_x += (x < m_focus_x) ? -det : det; + solution_x /= 2.0 * a; + + // Calculating of Y is trivial + solution_y = (slope * solution_x) + yint; + } + + // Calculate the percentage (0...1) of the current point along the + // focus-circumference line and return the normalized (0...d) value + //------------------------------- + solution_x -= double(m_focus_x); + solution_y -= double(m_focus_y); + double int_to_focus = solution_x * solution_x + solution_y * solution_y; + double cur_to_focus = double(x - m_focus_x) * double(x - m_focus_x) + + double(y - m_focus_y) * double(y - m_focus_y); + + return int(sqrt(cur_to_focus / int_to_focus) * d); + } + + private: + //--------------------------------------------------------------------- + void update_values() + { + // For use in the quadractic equation + //------------------------------- + m_radius2 = double(m_radius) * double(m_radius); + + double dist = sqrt(double(m_focus_x) * double(m_focus_x) + + double(m_focus_y) * double(m_focus_y)); + + // Test if distance from focus to center is greater than the radius + // For the sake of assurance factor restrict the point to be + // no further than 99% of the radius. + //------------------------------- + double r = m_radius * 0.99; + if(dist > r) + { + // clamp focus to radius + // x = r cos theta, y = r sin theta + //------------------------ + double a = atan2(double(m_focus_y), double(m_focus_x)); + m_focus_x = int(r * cos(a)); + m_focus_y = int(r * sin(a)); + } + + // Calculate the solution to be used in the case where x == focus_x + //------------------------------ + m_trivial = sqrt(m_radius2 - (m_focus_x * m_focus_x)); + } + + int m_radius; + int m_focus_x; + int m_focus_y; + double m_radius2; + double m_trivial; + }; + + + + //==============================================================gradient_x class gradient_x { public: @@ -170,7 +325,7 @@ namespace agg }; - //--------------------------------------------------------------gradient_y + //==============================================================gradient_y class gradient_y { public: @@ -178,7 +333,7 @@ namespace agg }; - //--------------------------------------------------------gradient_diamond + //========================================================gradient_diamond class gradient_diamond { public: @@ -191,7 +346,7 @@ namespace agg }; - //-------------------------------------------------------------gradient_xy + //=============================================================gradient_xy class gradient_xy { public: @@ -202,7 +357,7 @@ namespace agg }; - //--------------------------------------------------------gradient_sqrt_xy + //========================================================gradient_sqrt_xy class gradient_sqrt_xy { public: @@ -213,7 +368,7 @@ namespace agg }; - //----------------------------------------------------------gradient_conic + //==========================================================gradient_conic class gradient_conic { public: @@ -224,6 +379,44 @@ namespace agg }; + //=================================================gradient_repeat_adaptor + template class gradient_repeat_adaptor + { + public: + gradient_repeat_adaptor(const GradientF& gradient) : + m_gradient(&gradient) {} + + int calculate(int x, int y, int d) const + { + int ret = m_gradient->calculate(x, y, d) % d; + if(ret < 0) ret += d; + return ret; + } + + private: + const GradientF* m_gradient; + }; + + + //================================================gradient_reflect_adaptor + template class gradient_reflect_adaptor + { + public: + gradient_reflect_adaptor(const GradientF& gradient) : + m_gradient(&gradient) {} + + int calculate(int x, int y, int d) const + { + int d2 = d << 1; + int ret = m_gradient->calculate(x, y, d) % d2; + if(ret < 0) ret += d2; + if(ret >= d) ret = d2 - ret; + return ret; + } + + private: + const GradientF* m_gradient; + }; } diff --git a/headers/libs/agg/agg_span_gradient_alpha.h b/headers/libs/agg/agg_span_gradient_alpha.h new file mode 100644 index 0000000000..19327c3dbf --- /dev/null +++ b/headers/libs/agg/agg_span_gradient_alpha.h @@ -0,0 +1,126 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.2 +// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_GRADIENT_ALPHA_INCLUDED +#define AGG_SPAN_GRADIENT_ALPHA_INCLUDED + +#include "agg_span_gradient.h" + +namespace agg +{ + //======================================================span_gradient_alpha + template + class span_gradient_alpha + { + public: + typedef Interpolator interpolator_type; + typedef ColorT color_type; + typedef typename color_type::alpha_type alpha_type; + + enum + { + base_shift = 8, + base_size = 1 << base_shift, + base_mask = base_size - 1, + downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift + }; + + + //-------------------------------------------------------------------- + span_gradient_alpha() {} + + //-------------------------------------------------------------------- + span_gradient_alpha(interpolator_type& inter, + const GradientF& gradient_function, + AlphaF alpha_function, + double d1, double d2) : + m_interpolator(&inter), + m_gradient_function(&gradient_function), + m_alpha_function(alpha_function), + m_d1(int(d1 * gradient_subpixel_size)), + m_d2(int(d2 * gradient_subpixel_size)) + {} + + //-------------------------------------------------------------------- + interpolator_type& interpolator() { return *m_interpolator; } + const GradientF& gradient_function() const { return *m_gradient_function; } + const AlphaF alpha_function() const { return m_alpha_function; } + double d1() const { return double(m_d1) / gradient_subpixel_size; } + double d2() const { return double(m_d2) / gradient_subpixel_size; } + + //-------------------------------------------------------------------- + void interpolator(interpolator_type& i) { m_interpolator = &i; } + void gradient_function(const GradientF& gf) { m_gradient_function = &gf; } + void alpha_function(AlphaF af) { m_alpha_function = af; } + void d1(double v) { m_d1 = int(v * gradient_subpixel_size); } + void d2(double v) { m_d2 = int(v * gradient_subpixel_size); } + + //-------------------------------------------------------------------- + void convert(color_type* span, int x, int y, unsigned len) + { + int dd = m_d2 - m_d1; + if(dd < 1) dd = 1; + m_interpolator->begin(x+0.5, y+0.5, len); + do + { + m_interpolator->coordinates(&x, &y); + int d = m_gradient_function->calculate(x >> downscale_shift, + y >> downscale_shift, dd); + d = ((d - m_d1) << base_shift) / dd; + if(d < 0) d = 0; + if(d > base_mask) d = base_mask; + span->a = m_alpha_function[d]; + ++span; + ++(*m_interpolator); + } + while(--len); + } + + private: + interpolator_type* m_interpolator; + const GradientF* m_gradient_function; + AlphaF m_alpha_function; + int m_d1; + int m_d2; + }; + + + //=======================================================gradient_alpha_x + template struct gradient_alpha_x + { + typedef typename ColorT::alpha_type alpha_type; + alpha_type operator [] (alpha_type x) const { return x; } + }; + + //====================================================gradient_alpha_x_u8 + struct gradient_alpha_x_u8 + { + typedef int8u alpha_type; + alpha_type operator [] (alpha_type x) const { return x; } + }; + + //==========================================gradient_alpha_one_munus_x_u8 + struct gradient_alpha_one_munus_x_u8 + { + typedef int8u alpha_type; + alpha_type operator [] (alpha_type x) const { return 255-x; } + }; + +} + +#endif diff --git a/headers/libs/agg/agg_span_image_filter.h b/headers/libs/agg/agg_span_image_filter.h index a8af950aa8..5d90fca3df 100644 --- a/headers/libs/agg/agg_span_image_filter.h +++ b/headers/libs/agg/agg_span_image_filter.h @@ -52,19 +52,35 @@ namespace agg m_src(&src), m_back_color(back_color), m_interpolator(&interpolator), - m_filter(filter) + m_filter(filter), + m_dx_dbl(0.5), + m_dy_dbl(0.5), + m_dx_int(image_subpixel_size / 2), + m_dy_int(image_subpixel_size / 2) {} //---------------------------------------------------------------- - const rendering_buffer& source_image() const { return *m_src; } - const color_type& background_color() const { return m_back_color; } - const image_filter_base& filter() const { return *m_filter; } + const rendering_buffer& source_image() const { return *m_src; } + const color_type& background_color() const { return m_back_color; } + const image_filter_base& filter() const { return *m_filter; } + int filter_dx_int() const { return m_dx_int; } + int filter_dy_int() const { return m_dy_int; } + double filter_dx_dbl() const { return m_dx_dbl; } + double filter_dy_dbl() const { return m_dy_dbl; } //---------------------------------------------------------------- void source_image(const rendering_buffer& v) { m_src = &v; } void background_color(const color_type& v) { m_back_color = v; } void interpolator(interpolator_type& v) { m_interpolator = &v; } void filter(const image_filter_base& v) { m_filter = &v; } + void filter_offset(double dx, double dy) + { + m_dx_dbl = dx; + m_dy_dbl = dy; + m_dx_int = int(dx * image_subpixel_size); + m_dy_int = int(dy * image_subpixel_size); + } + void filter_offset(double d) { filter_offset(d, d); } //---------------------------------------------------------------- interpolator_type& interpolator() { return *m_interpolator; } @@ -75,6 +91,69 @@ namespace agg color_type m_back_color; interpolator_type* m_interpolator; const image_filter_base* m_filter; + double m_dx_dbl; + double m_dy_dbl; + unsigned m_dx_int; + unsigned m_dy_int; + }; + + + + //-------------------------------------------------remainder_unsigned + class remainder_unsigned + { + public: + remainder_unsigned(unsigned size) : + m_size(size), + m_add(size * (0x3FFFFFFF / size)) + {} + + unsigned operator () (int v) const + { + return (unsigned(v) + m_add) % m_size; + } + private: + unsigned m_size; + unsigned m_add; + }; + + + //----------------------------------------------------remainder_pow2 + class remainder_pow2 + { + public: + remainder_pow2(unsigned size) + { + m_mask = 1; + while(m_mask < size) m_mask = (m_mask << 1) | 1; + m_mask >>= 1; + } + unsigned operator () (int v) const { return unsigned(v) & m_mask; } + private: + unsigned m_mask; + }; + + + //-----------------------------------------------remainder_auto_pow2 + class remainder_auto_pow2 + { + public: + remainder_auto_pow2(unsigned size) : + m_size(size), + m_add(size * (0x3FFFFFFF / size)), + m_mask((m_size & (m_size-1)) ? 0 : m_size-1) + {} + + unsigned operator () (int v) const + { + if(m_mask) return unsigned(v) & m_mask; + return (unsigned(v) + m_add) % m_size; + } + + private: + unsigned m_size; + unsigned m_add; + unsigned m_mask; }; diff --git a/headers/libs/agg/agg_span_image_filter_rgb24.h b/headers/libs/agg/agg_span_image_filter_rgb24.h index 7dd734445a..efc4931cff 100644 --- a/headers/libs/agg/agg_span_image_filter_rgb24.h +++ b/headers/libs/agg/agg_span_image_filter_rgb24.h @@ -52,7 +52,8 @@ namespace agg //-------------------------------------------------------------------- color_type* generate(int x, int y, unsigned len) { - base_type::interpolator().begin(x, y, len); + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); int fg[3]; int src_alpha; @@ -130,8 +131,8 @@ namespace agg //-------------------------------------------------------------------- color_type* generate(int x, int y, unsigned len) { - base_type::interpolator().begin(x, y, len); - + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); int fg[3]; int src_alpha; int back_r = base_type::background_color().r; @@ -154,6 +155,9 @@ namespace agg base_type::interpolator().coordinates(&x_hr, &y_hr); + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; int weight; @@ -349,7 +353,8 @@ namespace agg //-------------------------------------------------------------------- color_type* generate(int x, int y, unsigned len) { - base_type::interpolator().begin(x, y, len); + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); int fg[3]; int src_alpha; @@ -381,6 +386,9 @@ namespace agg { base_type::interpolator().coordinates(&x, &y); + x -= base_type::filter_dx_int(); + y -= base_type::filter_dy_int(); + int x_hr = x; int y_hr = y; @@ -502,10 +510,10 @@ namespace agg if(fg[2] < 0) fg[2] = 0; if(src_alpha < 0) src_alpha = 0; - if(fg[0] > 255) fg[0] = 255; - if(fg[1] > 255) fg[1] = 255; - if(fg[2] > 255) fg[2] = 255; if(src_alpha > 255) src_alpha = 255; + if(fg[0] > src_alpha) fg[0] = src_alpha; + if(fg[1] > src_alpha) fg[1] = src_alpha; + if(fg[2] > src_alpha) fg[2] = src_alpha; } } diff --git a/headers/libs/agg/agg_span_image_filter_rgb24_gamma.h b/headers/libs/agg/agg_span_image_filter_rgb24_gamma.h index 4fc746d097..8b1839e6dc 100644 --- a/headers/libs/agg/agg_span_image_filter_rgb24_gamma.h +++ b/headers/libs/agg/agg_span_image_filter_rgb24_gamma.h @@ -61,8 +61,8 @@ namespace agg //-------------------------------------------------------------------- color_type* generate(int x, int y, unsigned len) { - base_type::interpolator().begin(x, y, len); - + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); int fg[3]; int src_alpha; int back_r = m_gamma->dir(base_type::background_color().r); @@ -85,6 +85,9 @@ namespace agg base_type::interpolator().coordinates(&x_hr, &y_hr); + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; int weight; @@ -290,8 +293,8 @@ namespace agg //-------------------------------------------------------------------- color_type* generate(int x, int y, unsigned len) { - base_type::interpolator().begin(x, y, len); - + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); int fg[3]; int src_alpha; int back_r = m_gamma->dir(base_type::background_color().r); @@ -322,6 +325,9 @@ namespace agg { base_type::interpolator().coordinates(&x, &y); + x -= base_type::filter_dx_int(); + y -= base_type::filter_dy_int(); + int x_hr = x; int y_hr = y; diff --git a/headers/libs/agg/agg_span_image_filter_rgba32.h b/headers/libs/agg/agg_span_image_filter_rgba32.h index f36098e916..783f1bee5f 100644 --- a/headers/libs/agg/agg_span_image_filter_rgba32.h +++ b/headers/libs/agg/agg_span_image_filter_rgba32.h @@ -54,7 +54,8 @@ namespace agg //-------------------------------------------------------------------- color_type* generate(int x, int y, unsigned len) { - base_type::interpolator().begin(x, y, len); + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); int fg[4]; @@ -139,7 +140,8 @@ namespace agg //-------------------------------------------------------------------- color_type* generate(int x, int y, unsigned len) { - base_type::interpolator().begin(x, y, len); + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); int fg[4]; int back_r = base_type::background_color().r; @@ -162,8 +164,12 @@ namespace agg base_type::interpolator().coordinates(&x_hr, &y_hr); + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + int x_lr = x_hr >> image_subpixel_shift; int y_lr = y_hr >> image_subpixel_shift; + int weight; if(x_lr >= 0 && y_lr >= 0 && @@ -176,6 +182,7 @@ namespace agg x_hr &= image_subpixel_mask; y_hr &= image_subpixel_mask; + fg_ptr = base_type::source_image().row(y_lr) + (x_lr << 2); weight = (image_subpixel_size - x_hr) * @@ -362,7 +369,8 @@ namespace agg //-------------------------------------------------------------------- color_type* generate(int x, int y, unsigned len) { - base_type::interpolator().begin(x, y, len); + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); int fg[4]; @@ -394,6 +402,9 @@ namespace agg { base_type::interpolator().coordinates(&x, &y); + x -= base_type::filter_dx_int(); + y -= base_type::filter_dy_int(); + int x_hr = x; int y_hr = y; @@ -446,10 +457,10 @@ namespace agg if(fg[2] < 0) fg[2] = 0; if(fg[3] < 0) fg[3] = 0; - if(fg[0] > 255) fg[0] = 255; - if(fg[1] > 255) fg[1] = 255; - if(fg[2] > 255) fg[2] = 255; - if(fg[3] > 255) fg[3] = 255; + if(fg[Order::A] > 255) fg[Order::A] = 255; + if(fg[Order::R] > fg[Order::A]) fg[Order::R] = fg[Order::A]; + if(fg[Order::G] > fg[Order::A]) fg[Order::G] = fg[Order::A]; + if(fg[Order::B] > fg[Order::A]) fg[Order::B] = fg[Order::A]; } else { @@ -517,10 +528,10 @@ namespace agg if(fg[2] < 0) fg[2] = 0; if(fg[3] < 0) fg[3] = 0; - if(fg[0] > 255) fg[0] = 255; - if(fg[1] > 255) fg[1] = 255; - if(fg[2] > 255) fg[2] = 255; - if(fg[3] > 255) fg[3] = 255; + if(fg[Order::A] > 255) fg[Order::A] = 255; + if(fg[Order::R] > fg[Order::A]) fg[Order::R] = fg[Order::A]; + if(fg[Order::G] > fg[Order::A]) fg[Order::G] = fg[Order::A]; + if(fg[Order::B] > fg[Order::A]) fg[Order::B] = fg[Order::A]; } } diff --git a/headers/libs/agg/agg_trans_viewport.h b/headers/libs/agg/agg_trans_viewport.h index 1fba5142cf..4817dec109 100755 --- a/headers/libs/agg/agg_trans_viewport.h +++ b/headers/libs/agg/agg_trans_viewport.h @@ -141,12 +141,25 @@ namespace agg *y = (*y - m_dy1) / m_ky + m_wy1; } + //------------------------------------------------------------------- + double scale_x() const + { + return m_kx; + } + + //------------------------------------------------------------------- + double scale_y() const + { + return m_ky; + } + //------------------------------------------------------------------- double scale() const { return (m_kx + m_ky) * 0.5; } + //------------------------------------------------------------------- unsigned byte_size() const { diff --git a/headers/libs/agg/agg_vcgen_contour.h b/headers/libs/agg/agg_vcgen_contour.h index 3531e7d0ee..2e79d01905 100755 --- a/headers/libs/agg/agg_vcgen_contour.h +++ b/headers/libs/agg/agg_vcgen_contour.h @@ -16,8 +16,8 @@ #ifndef AGG_VCGEN_CONTOUR_INCLUDED #define AGG_VCGEN_CONTOUR_INCLUDED -#include "agg_basics.h" -#include "agg_vertex_sequence.h" +#include "agg_math_stroke.h" +#include "agg_vertex_iterator.h" namespace agg { @@ -33,22 +33,32 @@ namespace agg initial, ready, outline, - add_point, - end_poly + out_vertices, + end_poly, + stop }; public: typedef vertex_sequence vertex_storage; + typedef pod_deque coord_storage; vcgen_contour(); + void line_join(line_join_e lj) { m_line_join = lj; } + void inner_line_join(line_join_e lj) { m_inner_line_join = lj; } void width(double w) { m_width = w * 0.5; } void miter_limit(double ml) { m_miter_limit = ml; } void miter_limit_theta(double t); + void inner_miter_limit(double ml) { m_inner_miter_limit = ml; } + void approximation_scale(double as) { m_approx_scale = as; } void auto_detect_orientation(bool v) { m_auto_detect = v; } + line_join_e line_join() const { return m_line_join; } + line_join_e inner_line_join() const { return m_inner_line_join; } double width() const { return m_width * 2.0; } double miter_limit() const { return m_miter_limit; } + double inner_miter_limit() const { return m_inner_miter_limit; } + double approximation_scale() const { return m_approx_scale; } bool auto_detect_orientation() const { return m_auto_detect; } // Generator interface @@ -63,24 +73,22 @@ namespace agg vcgen_contour(const vcgen_contour&); const vcgen_contour& operator = (const vcgen_contour&); - bool calc_miter(const vertex_dist& v0, - const vertex_dist& v1, - const vertex_dist& v2); - vertex_storage m_src_vertices; + coord_storage m_out_vertices; double m_width; + line_join_e m_line_join; + line_join_e m_inner_line_join; + double m_approx_scale; double m_abs_width; double m_signed_width; double m_miter_limit; + double m_inner_miter_limit; status_e m_status; unsigned m_src_vertex; + unsigned m_out_vertex; unsigned m_closed; unsigned m_orientation; bool m_auto_detect; - double m_x1; - double m_y1; - double m_x2; - double m_y2; }; } diff --git a/headers/libs/agg/agg_vcgen_stroke.h b/headers/libs/agg/agg_vcgen_stroke.h index 825cc1525b..5fa2ff475b 100755 --- a/headers/libs/agg/agg_vcgen_stroke.h +++ b/headers/libs/agg/agg_vcgen_stroke.h @@ -16,16 +16,13 @@ #ifndef AGG_VCGEN_STROKE_INCLUDED #define AGG_VCGEN_STROKE_INCLUDED -#include "agg_basics.h" -#include "agg_vertex_sequence.h" +#include "agg_math_stroke.h" #include "agg_vertex_iterator.h" + namespace agg { - // Minimal angle to calculate round joins - const double vcgen_stroke_theta = 1e-10; //----vcgen_stroke_theta - //============================================================vcgen_stroke // // See Implementation agg_vcgen_stroke.cpp @@ -50,48 +47,28 @@ namespace agg }; public: - enum line_cap_e - { - butt_cap, - square_cap, - round_cap - }; - - enum line_join_e - { - miter_join, - miter_join_revert, - round_join, - bevel_join - }; - - struct coord_type - { - double x, y; - - coord_type() {} - coord_type(double x_, double y_) : x(x_), y(y_) {} - }; - - typedef vertex_sequence vertex_storage; - typedef pod_deque coord_storage; + typedef pod_deque coord_storage; vcgen_stroke(); void line_cap(line_cap_e lc) { m_line_cap = lc; } void line_join(line_join_e lj) { m_line_join = lj; } + void inner_line_join(line_join_e lj) { m_inner_line_join = lj; } line_cap_e line_cap() const { return m_line_cap; } line_join_e line_join() const { return m_line_join; } + line_join_e inner_line_join() const { return m_inner_line_join; } void width(double w) { m_width = w * 0.5; } void miter_limit(double ml) { m_miter_limit = ml; } void miter_limit_theta(double t); + void inner_miter_limit(double ml) { m_inner_miter_limit = ml; } void approximation_scale(double as) { m_approx_scale = as; } double width() const { return m_width * 2.0; } double miter_limit() const { return m_miter_limit; } + double inner_miter_limit() const { return m_inner_miter_limit; } double approximation_scale() const { return m_approx_scale; } void shorten(double s) { m_shorten = s; } @@ -114,34 +91,16 @@ namespace agg vcgen_stroke(const vcgen_stroke&); const vcgen_stroke& operator = (const vcgen_stroke&); - void calc_join(const vertex_dist& v0, - const vertex_dist& v1, - const vertex_dist& v2, - double len1, double len2); - - void calc_miter(const vertex_dist& v0, - const vertex_dist& v1, - const vertex_dist& v2, - double dx1, double dy1, - double dx2, double dy2, - bool revert_flag); - - void calc_arc(double x, double y, - double dx1, double dy1, - double dx2, double dy2); - - void calc_cap(const vertex_dist& v0, - const vertex_dist& v1, - double len); - vertex_storage m_src_vertices; coord_storage m_out_vertices; double m_width; double m_miter_limit; + double m_inner_miter_limit; double m_approx_scale; double m_shorten; line_cap_e m_line_cap; line_join_e m_line_join; + line_join_e m_inner_line_join; unsigned m_closed; status_e m_status; status_e m_prev_status; diff --git a/headers/libs/agg/agg_vpgen_clip_polygon.h b/headers/libs/agg/agg_vpgen_clip_polygon.h index c1e331a703..835ae57c28 100644 --- a/headers/libs/agg/agg_vpgen_clip_polygon.h +++ b/headers/libs/agg/agg_vpgen_clip_polygon.h @@ -54,6 +54,9 @@ namespace agg double x2() const { return m_clip_box.x2; } double y2() const { return m_clip_box.y2; } + static bool auto_close() { return true; } + static bool auto_unclose() { return false; } + void reset(); void move_to(double x, double y); void line_to(double x, double y); diff --git a/headers/libs/agg/agg_vpgen_clip_polyline.h b/headers/libs/agg/agg_vpgen_clip_polyline.h new file mode 100644 index 0000000000..87dbffe88f --- /dev/null +++ b/headers/libs/agg/agg_vpgen_clip_polyline.h @@ -0,0 +1,121 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.2 +// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_VPGEN_CLIP_POLYLINE_INCLUDED +#define AGG_VPGEN_CLIP_POLYLINE_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================vpgen_clip_polyline + // + // See Implementation agg_vpgen_clip_polyline.cpp + // + class vpgen_clip_polyline + { + public: + vpgen_clip_polyline() : + m_clip_box(0, 0, 1, 1), + m_x1(0), + m_y1(0), + m_f1(0), + m_x2(0), + m_y2(0), + m_f2(0), + m_num_vertices(0), + m_vertex(0) + { + } + + void clip_box(double x1, double y1, double x2, double y2) + { + m_clip_box.x1 = x1; + m_clip_box.y1 = y1; + m_clip_box.x2 = x2; + m_clip_box.y2 = y2; + m_clip_box.normalize(); + } + + + double x1() const { return m_clip_box.x1; } + double y1() const { return m_clip_box.y1; } + double x2() const { return m_clip_box.x2; } + double y2() const { return m_clip_box.y2; } + + static bool auto_close() { return false; } + static bool auto_unclose() { return true; } + + void reset(); + void move_to(double x, double y); + void line_to(double x, double y); + unsigned vertex(double* x, double* y); + + private: + enum clipping_flags_def + { + clip_x1 = 1, + clip_x2 = 2, + clip_y1 = 4, + clip_y2 = 8 + }; + + // Determine the clipping code of the vertex according to the + // Cyrus-Beck line clipping algorithm + //-------------------------------------------------------------------- + unsigned clipping_flags_x(double x) + { + unsigned f = 0; + if(x < m_clip_box.x1) f |= clip_x1; + if(x > m_clip_box.x2) f |= clip_x2; + return f; + } + + unsigned clipping_flags_y(double y) + { + unsigned f = 0; + if(y < m_clip_box.y1) f |= clip_y1; + if(y > m_clip_box.y2) f |= clip_y2; + return f; + } + + unsigned clipping_flags(double x, double y) + { + return clipping_flags_x(x) | clipping_flags_y(y); + } + + bool move_point(double& x, double& y, unsigned& flags); + void clip_line_segment(); + + private: + rect_d m_clip_box; + double m_x1; + double m_y1; + unsigned m_f1; + double m_x2; + double m_y2; + unsigned m_f2; + double m_x[2]; + double m_y[2]; + unsigned m_cmd[2]; + unsigned m_num_vertices; + unsigned m_vertex; + }; + +} + + +#endif diff --git a/headers/libs/agg/agg_vpgen_segmentator.h b/headers/libs/agg/agg_vpgen_segmentator.h index cbfde4d35d..6564aa064d 100755 --- a/headers/libs/agg/agg_vpgen_segmentator.h +++ b/headers/libs/agg/agg_vpgen_segmentator.h @@ -34,11 +34,12 @@ namespace agg void approximation_scale(double s) { m_approximation_scale = s; } double approximation_scale() const { return m_approximation_scale; } - void reset() { m_cmd = path_cmd_stop; } + static bool auto_close() { return false; } + static bool auto_unclose() { return false; } + void reset() { m_cmd = path_cmd_stop; } void move_to(double x, double y); void line_to(double x, double y); - unsigned vertex(double* x, double* y); private: diff --git a/headers/libs/agg/ctrl/agg_bezier_ctrl.h b/headers/libs/agg/ctrl/agg_bezier_ctrl.h new file mode 100644 index 0000000000..d3f030c869 --- /dev/null +++ b/headers/libs/agg/ctrl/agg_bezier_ctrl.h @@ -0,0 +1,112 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.2 +// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// classes bezier_ctrl_impl, bezier_ctrl +// +//---------------------------------------------------------------------------- + +#ifndef AGG_BEZIER_CTRL_INCLUDED +#define AGG_BEZIER_CTRL_INCLUDED + +#include "agg_math.h" +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_conv_stroke.h" +#include "agg_conv_curve.h" +#include "agg_polygon_ctrl.h" + + +namespace agg +{ + + //--------------------------------------------------------bezier_ctrl_impl + class bezier_ctrl_impl : public ctrl + { + public: + bezier_ctrl_impl(); + + void curve(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + curve4& curve(); + + double x1() const { return m_poly.xn(0); } + double y1() const { return m_poly.yn(0); } + double x2() const { return m_poly.xn(1); } + double y2() const { return m_poly.yn(1); } + double x3() const { return m_poly.xn(2); } + double y3() const { return m_poly.yn(2); } + double x4() const { return m_poly.xn(3); } + double y4() const { return m_poly.yn(3); } + + void line_width(double w) { m_stroke.width(w); } + double line_width() const { return m_stroke.width(); } + + void point_radius(double r) { m_poly.point_radius(r); } + double point_radius() const { return m_poly.point_radius(); } + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex source interface + unsigned num_paths() { return 7; }; + void rewind(unsigned id); + unsigned vertex(double* x, double* y); + + + private: + curve4 m_curve; + ellipse m_ellipse; + conv_stroke m_stroke; + polygon_ctrl_impl m_poly; + unsigned m_idx; + }; + + + + //----------------------------------------------------------bezier_ctrl + template class bezier_ctrl : public bezier_ctrl_impl + { + public: + bezier_ctrl() : + m_color(rgba(0.0, 0.0, 0.0)) + { + } + + void line_color(const ColorT& c) { m_color = c; } + const ColorT& color(unsigned i) const { return m_color; } + + private: + bezier_ctrl(const bezier_ctrl&); + const bezier_ctrl& operator = (const bezier_ctrl&); + + ColorT m_color; + }; + + + + + +} + + + +#endif + diff --git a/headers/libs/agg/ctrl/agg_ctrl.h b/headers/libs/agg/ctrl/agg_ctrl.h index 9c120ae2c4..34a57a64cc 100644 --- a/headers/libs/agg/ctrl/agg_ctrl.h +++ b/headers/libs/agg/ctrl/agg_ctrl.h @@ -31,6 +31,7 @@ namespace agg { public: //-------------------------------------------------------------------- + virtual ~ctrl() {} ctrl(double x1, double y1, double x2, double y2, bool flip_y) : m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2), m_flip_y(flip_y), diff --git a/headers/libs/agg/ctrl/agg_polygon_ctrl.h b/headers/libs/agg/ctrl/agg_polygon_ctrl.h new file mode 100644 index 0000000000..4d0920f02d --- /dev/null +++ b/headers/libs/agg/ctrl/agg_polygon_ctrl.h @@ -0,0 +1,166 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.2 +// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// classes polygon_ctrl_impl, polygon_ctrl +// +//---------------------------------------------------------------------------- + +#ifndef POLYGON_CTRL_INCLUDED +#define POLYGON_CTRL_INCLUDED + +#include "agg_conv_stroke.h" +#include "agg_ellipse.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + +namespace agg +{ + class simple_polygon_vertex_source + { + public: + simple_polygon_vertex_source(const double* polygon, unsigned np, + bool roundoff = false, + bool close = true) : + m_polygon(polygon), + m_num_points(np), + m_vertex(0), + m_roundoff(roundoff), + m_close(close) + { + } + + void close(bool f) { m_close = f; } + bool close() const { return m_close; } + + void rewind(unsigned) + { + m_vertex = 0; + } + + unsigned vertex(double* x, double* y) + { + if(m_vertex > m_num_points) return path_cmd_stop; + if(m_vertex == m_num_points) + { + ++m_vertex; + return path_cmd_end_poly | (m_close ? path_flags_close : 0); + } + *x = m_polygon[m_vertex * 2]; + *y = m_polygon[m_vertex * 2 + 1]; + if(m_roundoff) + { + *x = floor(*x) + 0.5; + *y = floor(*y) + 0.5; + } + ++m_vertex; + return (m_vertex == 1) ? path_cmd_move_to : path_cmd_line_to; + } + + private: + const double* m_polygon; + unsigned m_num_points; + unsigned m_vertex; + bool m_roundoff; + bool m_close; + }; + + + + + class polygon_ctrl_impl : public ctrl + { + public: + ~polygon_ctrl_impl(); + polygon_ctrl_impl(unsigned np, double point_radius=5); + + unsigned num_points() const { return m_num_points; } + double xn(unsigned n) const { return m_polygon[n * 2]; } + double yn(unsigned n) const { return m_polygon[n * 2 + 1]; } + double& xn(unsigned n) { return m_polygon[n * 2]; } + double& yn(unsigned n) { return m_polygon[n * 2 + 1]; } + + const double* polygon() const { return m_polygon; } + + void line_width(double w) { m_stroke.width(w); } + double line_width() const { return m_stroke.width(); } + + void point_radius(double r) { m_point_radius = r; } + double point_radius() const { return m_point_radius; } + + void in_polygon_check(bool f) { m_in_polygon_check = f; } + bool in_polygon_check() const { return m_in_polygon_check; } + + void close(bool f) { m_vs.close(f); } + bool close() const { return m_vs.close(); } + + // Vertex source interface + unsigned num_paths() { return 1; } + void rewind(unsigned id); + unsigned vertex(double* x, double* y); + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + + private: + bool check_edge(unsigned i, double x, double y) const; + bool point_in_polygon(double x, double y) const; + + double* m_polygon; + unsigned m_num_points; + int m_node; + int m_edge; + simple_polygon_vertex_source m_vs; + conv_stroke m_stroke; + ellipse m_ellipse; + double m_point_radius; + unsigned m_status; + double m_dx; + double m_dy; + bool m_in_polygon_check; + }; + + + + //----------------------------------------------------------polygon_ctrl + template class polygon_ctrl : public polygon_ctrl_impl + { + public: + polygon_ctrl(unsigned np, double point_radius=5) : + polygon_ctrl_impl(np, point_radius), + m_color(rgba(0.0, 0.0, 0.0)) + { + } + + void line_color(const ColorT& c) { m_color = c; } + const ColorT& color(unsigned i) const { return m_color; } + + private: + polygon_ctrl(const polygon_ctrl&); + const polygon_ctrl& operator = (const polygon_ctrl&); + + ColorT m_color; + }; + + + + +} + +#endif + diff --git a/headers/libs/agg/ctrl/agg_spline_ctrl.h b/headers/libs/agg/ctrl/agg_spline_ctrl.h index 01160df593..39aafafccb 100644 --- a/headers/libs/agg/ctrl/agg_spline_ctrl.h +++ b/headers/libs/agg/ctrl/agg_spline_ctrl.h @@ -58,8 +58,8 @@ namespace agg void active_point(int i); - const double* spline() const { return m_spline_values; } - const unsigned char* spline8() const { return m_spline_values8; } + const double* spline() const { return m_spline_values; } + const int8u* spline8() const { return m_spline_values8; } double value(double x) const; void value(unsigned idx, double y); void point(unsigned idx, double x, double y); @@ -87,7 +87,7 @@ namespace agg double m_yp[32]; bspline m_spline; double m_spline_values[256]; - unsigned char m_spline_values8[256]; + int8u m_spline_values8[256]; double m_border_width; double m_border_extra; double m_curve_width;