xref: /aosp_15_r20/external/pdfium/third_party/agg23/agg_vcgen_dash.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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