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