xref: /haiku/headers/libs/agg/agg_conv_marker.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 // conv_marker
17 //
18 //----------------------------------------------------------------------------
19 #ifndef AGG_CONV_MARKER_INCLUDED
20 #define AGG_CONV_MARKER_INCLUDED
21 
22 #include "agg_basics.h"
23 #include "agg_trans_affine.h"
24 #include "agg_vertex_iterator.h"
25 
26 namespace agg
27 {
28     //-------------------------------------------------------------conv_marker
29     template<class MarkerLocator, class MarkerShapes>
30     class conv_marker
31     {
32     public:
33         conv_marker(MarkerLocator& ml, MarkerShapes& ms);
34 
35         trans_affine& transform() { return m_transform; }
36         const trans_affine& transform() const { return m_transform; }
37 
38         void rewind(unsigned id);
39         unsigned vertex(double* x, double* y);
40 
41         typedef conv_marker<MarkerLocator, MarkerShapes> source_type;
42         typedef vertex_iterator<source_type> iterator;
43         iterator begin(unsigned id) { return iterator(*this, id); }
44         iterator end() { return iterator(path_cmd_stop); }
45 
46     private:
47         conv_marker(const conv_marker<MarkerLocator, MarkerShapes>&);
48         const conv_marker<MarkerLocator, MarkerShapes>&
49             operator = (const conv_marker<MarkerLocator, MarkerShapes>&);
50 
51         enum status_e
52         {
53             initial,
54             markers,
55             polygon,
56             stop
57         };
58 
59         MarkerLocator* m_marker_locator;
60         MarkerShapes*  m_marker_shapes;
61         trans_affine   m_transform;
62         trans_affine   m_mtx;
63         status_e       m_status;
64         unsigned       m_marker;
65         unsigned       m_num_markers;
66     };
67 
68 
69     //------------------------------------------------------------------------
70     template<class MarkerLocator, class MarkerShapes>
71     conv_marker<MarkerLocator, MarkerShapes>::conv_marker(MarkerLocator& ml, MarkerShapes& ms) :
72         m_marker_locator(&ml),
73         m_marker_shapes(&ms),
74         m_status(initial),
75         m_marker(0),
76         m_num_markers(1)
77     {
78     }
79 
80 
81     //------------------------------------------------------------------------
82     template<class MarkerLocator, class MarkerShapes>
83     void conv_marker<MarkerLocator, MarkerShapes>::rewind(unsigned)
84     {
85         m_status = initial;
86         m_marker = 0;
87         m_num_markers = 1;
88     }
89 
90 
91     //------------------------------------------------------------------------
92     template<class MarkerLocator, class MarkerShapes>
93     unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y)
94     {
95         unsigned cmd = path_cmd_move_to;
96         double x1, y1, x2, y2;
97 
98         while(!is_stop(cmd))
99         {
100             switch(m_status)
101             {
102             case initial:
103                 if(m_num_markers == 0)
104                 {
105                    cmd = path_cmd_stop;
106                    break;
107                 }
108                 m_marker_locator->rewind(m_marker);
109                 ++m_marker;
110                 m_num_markers = 0;
111                 m_status = markers;
112 
113             case markers:
114                 if(is_stop(m_marker_locator->vertex(&x1, &y1)))
115                 {
116                     m_status = initial;
117                     break;
118                 }
119                 if(is_stop(m_marker_locator->vertex(&x2, &y2)))
120                 {
121                     m_status = initial;
122                     break;
123                 }
124                 ++m_num_markers;
125                 m_mtx = m_transform;
126                 m_mtx *= trans_affine_rotation(atan2(y2 - y1, x2 - x1));
127                 m_mtx *= trans_affine_translation(x1, y1);
128                 m_marker_shapes->rewind(m_marker - 1);
129                 m_status = polygon;
130 
131             case polygon:
132                 cmd = m_marker_shapes->vertex(x, y);
133                 if(is_stop(cmd))
134                 {
135                     cmd = path_cmd_move_to;
136                     m_status = markers;
137                     break;
138                 }
139                 m_mtx.transform(x, y);
140                 return cmd;
141 
142             case stop:
143                 cmd = path_cmd_stop;
144                 break;
145             }
146         }
147         return cmd;
148     }
149 
150 }
151 
152 
153 #endif
154 
155