xref: /haiku/headers/libs/agg/agg_conv_adaptor_vpgen.h (revision a3e794ae459fec76826407f8ba8c94cd3535f128)
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 
21 namespace 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