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 #ifndef AGG_PATH_STORAGE_INTEGER_INCLUDED
17 #define AGG_PATH_STORAGE_INTEGER_INCLUDED
18 
19 #include <string.h>
20 #include "agg_array.h"
21 
22 namespace mapserver
23 {
24     //---------------------------------------------------------vertex_integer
25     template<class T, unsigned CoordShift=6> struct vertex_integer
26     {
27         enum path_cmd
28         {
29             cmd_move_to = 0,
30             cmd_line_to = 1,
31             cmd_curve3  = 2,
32             cmd_curve4  = 3
33         };
34 
35         enum coord_scale_e
36         {
37             coord_shift = CoordShift,
38             coord_scale  = 1 << coord_shift
39         };
40 
41         T x,y;
vertex_integervertex_integer42         vertex_integer() {}
vertex_integervertex_integer43         vertex_integer(T x_, T y_, unsigned flag) :
44             x(((x_ << 1) & ~1) | (flag &  1)),
45             y(((y_ << 1) & ~1) | (flag >> 1)) {}
46 
47         unsigned vertex(double* x_, double* y_,
48                         double dx=0, double dy=0,
49                         double scale=1.0) const
50         {
51             *x_ = dx + (double(x >> 1) / coord_scale) * scale;
52             *y_ = dy + (double(y >> 1) / coord_scale) * scale;
53             switch(((y & 1) << 1) | (x & 1))
54             {
55                 case cmd_move_to: return path_cmd_move_to;
56                 case cmd_line_to: return path_cmd_line_to;
57                 case cmd_curve3:  return path_cmd_curve3;
58                 case cmd_curve4:  return path_cmd_curve4;
59             }
60             return path_cmd_stop;
61         }
62     };
63 
64 
65     //---------------------------------------------------path_storage_integer
66     template<class T, unsigned CoordShift=6> class path_storage_integer
67     {
68     public:
69         typedef T value_type;
70         typedef vertex_integer<T, CoordShift> vertex_integer_type;
71 
72         //--------------------------------------------------------------------
path_storage_integer()73         path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {}
74 
75         //--------------------------------------------------------------------
remove_all()76         void remove_all() { m_storage.remove_all(); }
77 
78         //--------------------------------------------------------------------
move_to(T x,T y)79         void move_to(T x, T y)
80         {
81             m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to));
82         }
83 
84         //--------------------------------------------------------------------
line_to(T x,T y)85         void line_to(T x, T y)
86         {
87             m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_line_to));
88         }
89 
90         //--------------------------------------------------------------------
curve3(T x_ctrl,T y_ctrl,T x_to,T y_to)91         void curve3(T x_ctrl,  T y_ctrl,
92                     T x_to,    T y_to)
93         {
94             m_storage.add(vertex_integer_type(x_ctrl, y_ctrl, vertex_integer_type::cmd_curve3));
95             m_storage.add(vertex_integer_type(x_to,   y_to,   vertex_integer_type::cmd_curve3));
96         }
97 
98         //--------------------------------------------------------------------
curve4(T x_ctrl1,T y_ctrl1,T x_ctrl2,T y_ctrl2,T x_to,T y_to)99         void curve4(T x_ctrl1, T y_ctrl1,
100                     T x_ctrl2, T y_ctrl2,
101                     T x_to,    T y_to)
102         {
103             m_storage.add(vertex_integer_type(x_ctrl1, y_ctrl1, vertex_integer_type::cmd_curve4));
104             m_storage.add(vertex_integer_type(x_ctrl2, y_ctrl2, vertex_integer_type::cmd_curve4));
105             m_storage.add(vertex_integer_type(x_to,    y_to,    vertex_integer_type::cmd_curve4));
106         }
107 
108         //--------------------------------------------------------------------
close_polygon()109         void close_polygon() {}
110 
111         //--------------------------------------------------------------------
size()112         unsigned size() const { return m_storage.size(); }
vertex(unsigned idx,double * x,double * y)113         unsigned vertex(unsigned idx, double* x, double* y) const
114         {
115             return m_storage[idx].vertex(x, y);
116         }
117 
118         //--------------------------------------------------------------------
byte_size()119         unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); }
serialize(int8u * ptr)120         void serialize(int8u* ptr) const
121         {
122             unsigned i;
123             for(i = 0; i < m_storage.size(); i++)
124             {
125                 memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type));
126                 ptr += sizeof(vertex_integer_type);
127             }
128         }
129 
130         //--------------------------------------------------------------------
rewind(unsigned)131         void rewind(unsigned)
132         {
133             m_vertex_idx = 0;
134             m_closed = true;
135         }
136 
137         //--------------------------------------------------------------------
vertex(double * x,double * y)138         unsigned vertex(double* x, double* y)
139         {
140             if(m_storage.size() < 2 || m_vertex_idx > m_storage.size())
141             {
142                 *x = 0;
143                 *y = 0;
144                 return path_cmd_stop;
145             }
146             if(m_vertex_idx == m_storage.size())
147             {
148                 *x = 0;
149                 *y = 0;
150                 ++m_vertex_idx;
151                 return path_cmd_end_poly | path_flags_close;
152             }
153             unsigned cmd = m_storage[m_vertex_idx].vertex(x, y);
154             if(is_move_to(cmd) && !m_closed)
155             {
156                 *x = 0;
157                 *y = 0;
158                 m_closed = true;
159                 return path_cmd_end_poly | path_flags_close;
160             }
161             m_closed = false;
162             ++m_vertex_idx;
163             return cmd;
164         }
165 
166         //--------------------------------------------------------------------
bounding_rect()167         rect_d bounding_rect() const
168         {
169             rect_d bounds(1e100, 1e100, -1e100, -1e100);
170             if(m_storage.size() == 0)
171             {
172                 bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0;
173             }
174             else
175             {
176                 unsigned i;
177                 for(i = 0; i < m_storage.size(); i++)
178                 {
179                     double x, y;
180                     m_storage[i].vertex(&x, &y);
181                     if(x < bounds.x1) bounds.x1 = x;
182                     if(y < bounds.y1) bounds.y1 = y;
183                     if(x > bounds.x2) bounds.x2 = x;
184                     if(y > bounds.y2) bounds.y2 = y;
185                 }
186             }
187             return bounds;
188         }
189 
190     private:
191         pod_bvector<vertex_integer_type, 6> m_storage;
192         unsigned                            m_vertex_idx;
193         bool                                m_closed;
194     };
195 
196 
197 
198 
199     //-----------------------------------------serialized_integer_path_adaptor
200     template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor
201     {
202     public:
203         typedef vertex_integer<T, CoordShift> vertex_integer_type;
204 
205         //--------------------------------------------------------------------
serialized_integer_path_adaptor()206         serialized_integer_path_adaptor() :
207             m_data(0),
208             m_end(0),
209             m_ptr(0),
210             m_dx(0.0),
211             m_dy(0.0),
212             m_scale(1.0),
213             m_vertices(0)
214         {}
215 
216         //--------------------------------------------------------------------
serialized_integer_path_adaptor(const int8u * data,unsigned size,double dx,double dy)217         serialized_integer_path_adaptor(const int8u* data, unsigned size,
218                                         double dx, double dy) :
219             m_data(data),
220             m_end(data + size),
221             m_ptr(data),
222             m_dx(dx),
223             m_dy(dy),
224             m_vertices(0)
225         {}
226 
227         //--------------------------------------------------------------------
228         void init(const int8u* data, unsigned size,
229                   double dx, double dy, double scale=1.0)
230         {
231             m_data     = data;
232             m_end      = data + size;
233             m_ptr      = data;
234             m_dx       = dx;
235             m_dy       = dy;
236             m_scale    = scale;
237             m_vertices = 0;
238         }
239 
240 
241         //--------------------------------------------------------------------
rewind(unsigned)242         void rewind(unsigned)
243         {
244             m_ptr      = m_data;
245             m_vertices = 0;
246         }
247 
248         //--------------------------------------------------------------------
vertex(double * x,double * y)249         unsigned vertex(double* x, double* y)
250         {
251             if(m_data == 0 || m_ptr > m_end)
252             {
253                 *x = 0;
254                 *y = 0;
255                 return path_cmd_stop;
256             }
257 
258             if(m_ptr == m_end)
259             {
260                 *x = 0;
261                 *y = 0;
262                 m_ptr += sizeof(vertex_integer_type);
263                 return path_cmd_end_poly | path_flags_close;
264             }
265 
266             vertex_integer_type v;
267             memcpy(&v, m_ptr, sizeof(vertex_integer_type));
268             unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale);
269             if(is_move_to(cmd) && m_vertices > 2)
270             {
271                 *x = 0;
272                 *y = 0;
273                 m_vertices = 0;
274                 return path_cmd_end_poly | path_flags_close;
275             }
276             ++m_vertices;
277             m_ptr += sizeof(vertex_integer_type);
278             return cmd;
279         }
280 
281     private:
282         const int8u* m_data;
283         const int8u* m_end;
284         const int8u* m_ptr;
285         double       m_dx;
286         double       m_dy;
287         double       m_scale;
288         unsigned     m_vertices;
289     };
290 
291 }
292 
293 
294 #endif
295 
296