1//----------------------------------------------------------------------------
2// Anti-Grain Geometry - Version 2.4
3// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4//
5// Permission to copy, use, modify, sell and distribute this software
6// is granted provided this copyright notice appears in all copies.
7// This software is provided "as is" without express or implied
8// warranty, and with no claim as to its suitability for any purpose.
9//
10//----------------------------------------------------------------------------
11// Contact: mcseem@antigrain.com
12//          mcseemagg@yahoo.com
13//          http://www.antigrain.com
14//----------------------------------------------------------------------------
15
16#ifndef AGG_CONV_ADAPTOR_VPGEN_INCLUDED
17#define AGG_CONV_ADAPTOR_VPGEN_INCLUDED
18
19#include "agg_basics.h"
20
21namespace agg
22{
23
24    //======================================================conv_adaptor_vpgen
25    template<class VertexSource, class VPGen> class conv_adaptor_vpgen
26    {
27    public:
28        conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
29        void attach(VertexSource& source) { m_source = &source; }
30
31        VPGen& vpgen() { return m_vpgen; }
32        const VPGen& vpgen() const { return m_vpgen; }
33
34        void rewind(unsigned path_id);
35        unsigned vertex(double* x, double* y);
36
37    private:
38        conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);
39        const conv_adaptor_vpgen<VertexSource, VPGen>&
40            operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&);
41
42        VertexSource* m_source;
43        VPGen         m_vpgen;
44        double        m_start_x;
45        double        m_start_y;
46        unsigned      m_poly_flags;
47        int           m_vertices;
48    };
49
50
51
52    //------------------------------------------------------------------------
53    template<class VertexSource, class VPGen>
54    void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id)
55    {
56        m_source->rewind(path_id);
57        m_vpgen.reset();
58        m_start_x    = 0;
59        m_start_y    = 0;
60        m_poly_flags = 0;
61        m_vertices   = 0;
62    }
63
64
65    //------------------------------------------------------------------------
66    template<class VertexSource, class VPGen>
67    unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y)
68    {
69        unsigned cmd = path_cmd_stop;
70        for(;;)
71        {
72            cmd = m_vpgen.vertex(x, y);
73            if(!is_stop(cmd)) break;
74
75            if(m_poly_flags && !m_vpgen.auto_unclose())
76            {
77                *x = 0.0;
78                *y = 0.0;
79                cmd = m_poly_flags;
80                m_poly_flags = 0;
81                break;
82            }
83
84            if(m_vertices < 0)
85            {
86                if(m_vertices < -1)
87                {
88                    m_vertices = 0;
89                    return path_cmd_stop;
90                }
91                m_vpgen.move_to(m_start_x, m_start_y);
92                m_vertices = 1;
93                continue;
94            }
95
96            double tx, ty;
97            cmd = m_source->vertex(&tx, &ty);
98            if(is_vertex(cmd))
99            {
100                if(is_move_to(cmd))
101                {
102                    if(m_vpgen.auto_close() && m_vertices > 2)
103                    {
104                        m_vpgen.line_to(m_start_x, m_start_y);
105                        m_poly_flags = path_cmd_end_poly | path_flags_close;
106                        m_start_x    = tx;
107                        m_start_y    = ty;
108                        m_vertices   = -1;
109                        continue;
110                    }
111                    m_vpgen.move_to(tx, ty);
112                    m_start_x  = tx;
113                    m_start_y  = ty;
114                    m_vertices = 1;
115                }
116                else
117                {
118                    m_vpgen.line_to(tx, ty);
119                    ++m_vertices;
120                }
121            }
122            else
123            {
124                if(is_end_poly(cmd))
125                {
126                    m_poly_flags = cmd;
127                    if(is_closed(cmd) || m_vpgen.auto_close())
128                    {
129                        if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close;
130                        if(m_vertices > 2)
131                        {
132                            m_vpgen.line_to(m_start_x, m_start_y);
133                        }
134                        m_vertices = 0;
135                    }
136                }
137                else
138                {
139                    // path_cmd_stop
140                    if(m_vpgen.auto_close() && m_vertices > 2)
141                    {
142                        m_vpgen.line_to(m_start_x, m_start_y);
143                        m_poly_flags = path_cmd_end_poly | path_flags_close;
144                        m_vertices   = -2;
145                        continue;
146                    }
147                    break;
148                }
149            }
150        }
151        return cmd;
152    }
153
154
155}
156
157
158#endif
159
160