xref: /haiku/headers/libs/agg/agg_conv_close_polygon.h (revision 93aeb8c3bc3f13cb1f282e3e749258a23790d947)
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_CLOSE_POLYGON_INCLUDED
17 #define AGG_CONV_CLOSE_POLYGON_INCLUDED
18 
19 #include "agg_basics.h"
20 #include "agg_vertex_iterator.h"
21 
22 namespace agg
23 {
24 
25     //======================================================conv_close_polygon
26     template<class VertexSource> class conv_close_polygon
27     {
28     public:
29         conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
30 
31         void set_source(VertexSource& source) { m_source = &source; }
32 
33         void rewind(unsigned path_id);
34         unsigned vertex(double* x, double* y);
35 
36         typedef conv_close_polygon<VertexSource> source_type;
37         typedef vertex_iterator<source_type> iterator;
38         iterator begin(unsigned id) { return iterator(*this, id); }
39         iterator end() { return iterator(path_cmd_stop); }
40 
41     private:
42         conv_close_polygon(const conv_close_polygon<VertexSource>&);
43         const conv_close_polygon<VertexSource>&
44             operator = (const conv_close_polygon<VertexSource>&);
45 
46         VertexSource* m_source;
47         unsigned      m_cmd[2];
48         double        m_x[2];
49         double        m_y[2];
50         unsigned      m_vertex;
51         bool          m_line_to;
52     };
53 
54 
55 
56     //------------------------------------------------------------------------
57     template<class VertexSource>
58     void conv_close_polygon<VertexSource>::rewind(unsigned path_id)
59     {
60         m_source->rewind(path_id);
61         m_vertex = 2;
62         m_line_to = false;
63     }
64 
65 
66 
67     //------------------------------------------------------------------------
68     template<class VertexSource>
69     unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y)
70     {
71         unsigned cmd = path_cmd_stop;
72         for(;;)
73         {
74             if(m_vertex < 2)
75             {
76                 *x = m_x[m_vertex];
77                 *y = m_y[m_vertex];
78                 cmd = m_cmd[m_vertex];
79                 ++m_vertex;
80                 break;
81             }
82 
83             cmd = m_source->vertex(x, y);
84 
85             if(is_end_poly(cmd))
86             {
87                 cmd |= path_flags_close;
88                 break;
89             }
90 
91             if(is_stop(cmd))
92             {
93                 if(m_line_to)
94                 {
95                     m_cmd[0]  = path_cmd_end_poly | path_flags_close;
96                     m_cmd[1]  = path_cmd_stop;
97                     m_vertex  = 0;
98                     m_line_to = false;
99                     continue;
100                 }
101                 break;
102             }
103 
104             if(is_move_to(cmd))
105             {
106                 if(m_line_to)
107                 {
108                     m_x[0]    = 0.0;
109                     m_y[0]    = 0.0;
110                     m_cmd[0]  = path_cmd_end_poly | path_flags_close;
111                     m_x[1]    = *x;
112                     m_y[1]    = *y;
113                     m_cmd[1]  = cmd;
114                     m_vertex  = 0;
115                     m_line_to = false;
116                     continue;
117                 }
118                 break;
119             }
120 
121             if(is_vertex(cmd))
122             {
123                 m_line_to = true;
124                 break;
125             }
126         }
127         return cmd;
128     }
129 
130 }
131 
132 #endif
133