xref: /haiku/headers/libs/agg/agg_conv_adaptor_vpgen.h (revision 5412911f7f8ca41340b0f5cb928ed9726322ab44)
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.2
3 // Copyright (C) 2002-2004 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 #include "agg_vertex_iterator.h"
21 
22 namespace agg
23 {
24 
25     //======================================================conv_adaptor_vpgen
26     template<class VertexSource, class VPGen> class conv_adaptor_vpgen
27     {
28     public:
29         conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
30 
31         void set_source(VertexSource& source) { m_source = &source; }
32 
33         VPGen& vpgen() { return m_vpgen; }
34         const VPGen& vpgen() const { return m_vpgen; }
35 
36         void rewind(unsigned path_id);
37         unsigned vertex(double* x, double* y);
38 
39         typedef conv_adaptor_vpgen<VertexSource, VPGen> source_type;
40         typedef vertex_iterator<source_type> iterator;
41         iterator begin(unsigned id) { return iterator(*this, id); }
42         iterator end() { return iterator(path_cmd_stop); }
43 
44     private:
45         conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);
46         const conv_adaptor_vpgen<VertexSource, VPGen>&
47             operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&);
48 
49         VertexSource* m_source;
50         VPGen         m_vpgen;
51         double        m_start_x;
52         double        m_start_y;
53         unsigned      m_poly_flags;
54         int           m_vertices;
55     };
56 
57 
58 
59     //------------------------------------------------------------------------
60     template<class VertexSource, class VPGen>
61     void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id)
62     {
63         m_source->rewind(path_id);
64         m_vpgen.reset();
65         m_start_x    = 0;
66         m_start_y    = 0;
67         m_poly_flags = 0;
68         m_vertices   = 0;
69     }
70 
71 
72     //------------------------------------------------------------------------
73     template<class VertexSource, class VPGen>
74     unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y)
75     {
76         unsigned cmd = path_cmd_stop;
77         for(;;)
78         {
79             cmd = m_vpgen.vertex(x, y);
80             if(!is_stop(cmd)) break;
81 
82             if(m_poly_flags && !m_vpgen.auto_unclose())
83             {
84                 *x = 0.0;
85                 *y = 0.0;
86                 cmd = m_poly_flags;
87                 m_poly_flags = 0;
88                 break;
89             }
90 
91             if(m_vertices < 0)
92             {
93                 if(m_vertices < -1)
94                 {
95                     m_vertices = 0;
96                     return path_cmd_stop;
97                 }
98                 m_vpgen.move_to(m_start_x, m_start_y);
99                 m_vertices = 1;
100                 continue;
101             }
102 
103             double tx, ty;
104             cmd = m_source->vertex(&tx, &ty);
105             if(is_vertex(cmd))
106             {
107                 if(is_move_to(cmd))
108                 {
109                     if(m_vpgen.auto_close() && m_vertices > 2)
110                     {
111                         m_vpgen.line_to(m_start_x, m_start_y);
112                         m_poly_flags = path_cmd_end_poly | path_flags_close;
113                         m_start_x    = tx;
114                         m_start_y    = ty;
115                         m_vertices   = -1;
116                         continue;
117                     }
118                     m_vpgen.move_to(tx, ty);
119                     m_start_x  = tx;
120                     m_start_y  = ty;
121                     m_vertices = 1;
122                 }
123                 else
124                 {
125                     m_vpgen.line_to(tx, ty);
126                     ++m_vertices;
127                 }
128             }
129             else
130             {
131                 if(is_end_poly(cmd))
132                 {
133                     m_poly_flags = cmd;
134                     if(is_closed(cmd) || m_vpgen.auto_close())
135                     {
136                         if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close;
137                         if(m_vertices > 2)
138                         {
139                             m_vpgen.line_to(m_start_x, m_start_y);
140                         }
141                         m_vertices = 0;
142                     }
143                 }
144                 else
145                 {
146                     // path_cmd_stop
147                     if(m_vpgen.auto_close() && m_vertices > 2)
148                     {
149                         m_vpgen.line_to(m_start_x, m_start_y);
150                         m_poly_flags = path_cmd_end_poly | path_flags_close;
151                         m_vertices   = -2;
152                         continue;
153                     }
154                     break;
155                 }
156             }
157         }
158         return cmd;
159     }
160 
161 
162 }
163 
164 
165 #endif
166 
167