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