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