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