1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//----------------------------------------------------------------------------
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Anti-Grain Geometry - Version 2.3
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Permission to copy, use, modify, sell and distribute this software
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// is granted provided this copyright notice appears in all copies.
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This software is provided "as is" without express or implied
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// warranty, and with no claim as to its suitability for any purpose.
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//----------------------------------------------------------------------------
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Contact: mcseem@antigrain.com
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//          mcseemagg@yahoo.com
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//          http://www.antigrain.com
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//----------------------------------------------------------------------------
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Line dash generator
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//----------------------------------------------------------------------------
20ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "agg_shorten_path.h"
22ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "agg_vcgen_dash.h"
234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fxcrt/fx_basic.h"
24ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovnamespace agg
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvcgen_dash::vcgen_dash() :
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_total_dash_len(0),
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_num_dashes(0),
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_dash_start(0),
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_shorten(0),
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_curr_dash_start(0),
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_curr_dash(0),
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_src_vertices(),
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_closed(0),
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_status(initial),
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_src_vertex(0)
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid vcgen_dash::remove_all_dashes()
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_total_dash_len = 0;
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_num_dashes = 0;
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_curr_dash_start = 0;
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_curr_dash = 0;
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid vcgen_dash::add_dash(FX_FLOAT dash_len, FX_FLOAT gap_len)
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if(m_num_dashes < max_dashes) {
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_total_dash_len += dash_len + gap_len;
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_dashes[m_num_dashes++] = dash_len;
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_dashes[m_num_dashes++] = gap_len;
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid vcgen_dash::dash_start(FX_FLOAT ds)
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_dash_start = ds;
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    calc_dash_start(FXSYS_fabs(ds));
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid vcgen_dash::calc_dash_start(FX_FLOAT ds)
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_curr_dash = 0;
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_curr_dash_start = 0;
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while(ds > 0) {
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if(ds > m_dashes[m_curr_dash]) {
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ds -= m_dashes[m_curr_dash];
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ++m_curr_dash;
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_curr_dash_start = 0;
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if(m_curr_dash >= m_num_dashes) {
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_curr_dash = 0;
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_curr_dash_start = ds;
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ds = 0;
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid vcgen_dash::remove_all()
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_status = initial;
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_src_vertices.remove_all();
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_closed = 0;
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid vcgen_dash::add_vertex(FX_FLOAT x, FX_FLOAT y, unsigned cmd)
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_status = initial;
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if(is_move_to(cmd)) {
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_src_vertices.modify_last(vertex_dist(x, y));
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if(is_vertex(cmd)) {
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_src_vertices.add(vertex_dist(x, y));
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_closed = get_close_flag(cmd);
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid vcgen_dash::rewind(unsigned)
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if(m_status == initial) {
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_src_vertices.close(m_closed != 0);
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        shorten_path(m_src_vertices, m_shorten, m_closed);
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_status = ready;
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_src_vertex = 0;
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovunsigned vcgen_dash::vertex(FX_FLOAT* x, FX_FLOAT* y)
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    unsigned cmd = path_cmd_move_to;
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while(!is_stop(cmd)) {
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        switch(m_status) {
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case initial:
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                rewind(0);
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case ready:
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if(m_num_dashes < 2 || m_src_vertices.size() < 2) {
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    cmd = path_cmd_stop;
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    break;
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_status = polyline;
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_src_vertex = 1;
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_v1 = &m_src_vertices[0];
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_v2 = &m_src_vertices[1];
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_curr_rest = m_v1->dist;
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *x = m_v1->x;
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *y = m_v1->y;
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if(m_dash_start >= 0) {
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    calc_dash_start(m_dash_start);
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return path_cmd_move_to;
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case polyline: {
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FX_FLOAT dash_rest = m_dashes[m_curr_dash] - m_curr_dash_start;
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    unsigned cmd = (m_curr_dash & 1) ?
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                   path_cmd_move_to :
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                   path_cmd_line_to;
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if(m_curr_rest > dash_rest) {
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        m_curr_rest -= dash_rest;
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        ++m_curr_dash;
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        if(m_curr_dash >= m_num_dashes) {
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            m_curr_dash = 0;
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        }
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        m_curr_dash_start = 0;
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *x = m_v2->x - (m_v2->x - m_v1->x) * m_curr_rest / m_v1->dist;
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *y = m_v2->y - (m_v2->y - m_v1->y) * m_curr_rest / m_v1->dist;
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        m_curr_dash_start += m_curr_rest;
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *x = m_v2->x;
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *y = m_v2->y;
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        ++m_src_vertex;
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        m_v1 = m_v2;
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        m_curr_rest = m_v1->dist;
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        if(m_closed) {
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            if(m_src_vertex > m_src_vertices.size()) {
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                m_status = stop;
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            } else {
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                m_v2 = &m_src_vertices
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                       [
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                           (m_src_vertex >= m_src_vertices.size()) ? 0 :
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                           m_src_vertex
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                       ];
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            }
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        } else {
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            if(m_src_vertex >= m_src_vertices.size()) {
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                m_status = stop;
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            } else {
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                m_v2 = &m_src_vertices[m_src_vertex];
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            }
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        }
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    return cmd;
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case stop:
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                cmd = path_cmd_stop;
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return path_cmd_stop;
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
179