xref: /haiku/headers/libs/agg/agg_conv_adaptor_vcgen.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_ADAPTOR_VCGEN_INCLUDED
17 #define AGG_CONV_ADAPTOR_VCGEN_INCLUDED
18 
19 #include "agg_basics.h"
20 #include "agg_vertex_iterator.h"
21 
22 namespace agg
23 {
24     //------------------------------------------------------------null_markers
25     struct null_markers
26     {
27         void remove_all() {}
28         void add_vertex(double, double, unsigned) {}
29         void prepare_src() {}
30 
31         void rewind(unsigned) {}
32         unsigned vertex(double*, double*) { return path_cmd_stop; }
33 
34         typedef null_markers source_type;
35         typedef vertex_iterator<source_type> iterator;
36         iterator begin(unsigned id) { return iterator(*this, id); }
37         iterator end() { return iterator(path_cmd_stop); }
38     };
39 
40 
41     //------------------------------------------------------conv_adaptor_vcgen
42     template<class VertexSource,
43              class Generator,
44              class Markers=null_markers> class conv_adaptor_vcgen
45     {
46         enum status
47         {
48             initial,
49             accumulate,
50             generate
51         };
52 
53     public:
54         conv_adaptor_vcgen(VertexSource& source) :
55             m_source(&source),
56             m_status(initial)
57         {}
58 
59         void set_source(VertexSource& source) { m_source = &source; }
60 
61         Generator& generator() { return m_generator; }
62         const Generator& generator() const { return m_generator; }
63 
64         Markers& markers() { return m_markers; }
65         const Markers& markers() const { return m_markers; }
66 
67         void rewind(unsigned id)
68         {
69             m_source->rewind(id);
70             m_status = initial;
71         }
72 
73         unsigned vertex(double* x, double* y);
74 
75         typedef conv_adaptor_vcgen<VertexSource, Generator, Markers> source_type;
76         typedef vertex_iterator<source_type> iterator;
77         iterator begin(unsigned id) { return iterator(*this, id); }
78         iterator end() { return iterator(path_cmd_stop); }
79 
80     private:
81         // Prohibit copying
82         conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
83         const conv_adaptor_vcgen<VertexSource, Generator, Markers>&
84             operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
85 
86         VertexSource* m_source;
87         Generator     m_generator;
88         Markers       m_markers;
89         status        m_status;
90         unsigned      m_last_cmd;
91         double        m_start_x;
92         double        m_start_y;
93     };
94 
95 
96 
97 
98 
99     //------------------------------------------------------------------------
100     template<class VertexSource, class Generator, class Markers>
101     unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y)
102     {
103         unsigned cmd = path_cmd_stop;
104         bool done = false;
105         while(!done)
106         {
107             switch(m_status)
108             {
109             case initial:
110                 m_markers.remove_all();
111                 m_last_cmd = m_source->vertex(&m_start_x, &m_start_y);
112                 m_status = accumulate;
113 
114             case accumulate:
115                 if(is_stop(m_last_cmd)) return path_cmd_stop;
116 
117                 m_generator.remove_all();
118                 m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
119                 m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
120 
121                 for(;;)
122                 {
123                     cmd = m_source->vertex(x, y);
124                     if(is_vertex(cmd))
125                     {
126                         m_last_cmd = cmd;
127                         if(is_move_to(cmd))
128                         {
129                             m_start_x = *x;
130                             m_start_y = *y;
131                             break;
132                         }
133                         m_generator.add_vertex(*x, *y, cmd);
134                         m_markers.add_vertex(*x, *y, path_cmd_line_to);
135                     }
136                     else
137                     {
138                         if(is_stop(cmd))
139                         {
140                             m_last_cmd = path_cmd_stop;
141                             break;
142                         }
143                         if(is_end_poly(cmd))
144                         {
145                             m_generator.add_vertex(*x, *y, cmd);
146                             break;
147                         }
148                     }
149                 }
150                 m_generator.rewind(0);
151                 m_status = generate;
152 
153             case generate:
154                 cmd = m_generator.vertex(x, y);
155                 if(is_stop(cmd))
156                 {
157                     m_status = accumulate;
158                     break;
159                 }
160                 done = true;
161                 break;
162             }
163         }
164         return cmd;
165     }
166 
167 }
168 
169 #endif
170