1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
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.
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
16 #ifndef AGG_PATH_STORAGE_INTEGER_INCLUDED
17 #define AGG_PATH_STORAGE_INTEGER_INCLUDED
20 #include "agg_array.h"
25 //---------------------------------------------------------vertex_integer
26 template<class T
, unsigned CoordShift
=6> struct vertex_integer
38 coord_shift
= CoordShift
,
39 coord_mult
= 1 << coord_shift
44 vertex_integer(T x_
, T y_
, unsigned flag
) :
45 x(((x_
<< 1) & ~1) | (flag
& 1)),
46 y(((y_
<< 1) & ~1) | (flag
>> 1)) {}
48 unsigned vertex(double* x_
, double* y_
,
49 double dx
=0, double dy
=0,
50 double scale
=1.0) const
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))
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
;
66 //---------------------------------------------------path_storage_integer
67 template<class T
, unsigned CoordShift
=6> class path_storage_integer
70 typedef vertex_integer
<T
, CoordShift
> vertex_integer_type
;
72 //--------------------------------------------------------------------
73 path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {}
75 //--------------------------------------------------------------------
76 void remove_all() { m_storage
.remove_all(); }
78 //--------------------------------------------------------------------
79 void move_to(T x
, T y
)
81 m_storage
.add(vertex_integer_type(x
, y
, vertex_integer_type::cmd_move_to
));
84 //--------------------------------------------------------------------
85 void line_to(T x
, T y
)
87 m_storage
.add(vertex_integer_type(x
, y
, vertex_integer_type::cmd_line_to
));
90 //--------------------------------------------------------------------
91 void curve3(T x_ctrl
, T y_ctrl
,
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
));
98 //--------------------------------------------------------------------
99 void curve4(T x_ctrl1
, T y_ctrl1
,
100 T x_ctrl2
, T y_ctrl2
,
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
));
108 //--------------------------------------------------------------------
109 void close_polygon() {}
111 //--------------------------------------------------------------------
112 unsigned size() const { return m_storage
.size(); }
113 unsigned vertex(unsigned idx
, T
* x
, T
* y
) const
115 const vertex_integer_type
& v
= m_storage
[idx
];
118 return ((v
.y
& 1) << 1) | (v
.x
& 1);
121 //--------------------------------------------------------------------
122 unsigned byte_size() const { return m_storage
.size() * sizeof(vertex_integer_type
); }
123 void serialize(int8u
* ptr
) const
126 for(i
= 0; i
< m_storage
.size(); i
++)
128 memcpy(ptr
, &m_storage
[i
], sizeof(vertex_integer_type
));
129 ptr
+= sizeof(vertex_integer_type
);
134 //--------------------------------------------------------------------
135 void rewind(unsigned)
141 //--------------------------------------------------------------------
142 unsigned vertex(double* x
, double* y
)
144 if(m_storage
.size() < 2 || m_vertex_idx
> m_storage
.size())
148 return path_cmd_stop
;
150 if(m_vertex_idx
== m_storage
.size())
155 return path_cmd_end_poly
| path_flags_close
;
157 unsigned cmd
= m_storage
[m_vertex_idx
].vertex(x
, y
);
158 if(is_move_to(cmd
) && !m_closed
)
163 return path_cmd_end_poly
| path_flags_close
;
170 //--------------------------------------------------------------------
171 rect_d
bounding_rect() const
173 rect_d
bounds(1e100
, 1e100
, -1e100
, -1e100
);
174 if(m_storage
.size() == 0)
176 bounds
.x1
= bounds
.y1
= bounds
.x2
= bounds
.y2
= 0.0;
181 for(i
= 0; i
< m_storage
.size(); i
++)
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
;
196 pod_deque
<vertex_integer_type
, 6> m_storage
;
197 unsigned m_vertex_idx
;
204 //-----------------------------------------serialized_integer_path_adaptor
205 template<class T
, unsigned CoordShift
=6> class serialized_integer_path_adaptor
208 typedef vertex_integer
<T
, CoordShift
> vertex_integer_type
;
210 //--------------------------------------------------------------------
211 serialized_integer_path_adaptor() :
221 //--------------------------------------------------------------------
222 serialized_integer_path_adaptor(const int8u
* data
, unsigned size
,
223 double dx
, double dy
) :
232 //--------------------------------------------------------------------
233 void init(const int8u
* data
, unsigned size
,
234 double dx
, double dy
, double scale
=1.0)
246 //--------------------------------------------------------------------
247 void rewind(unsigned)
253 //--------------------------------------------------------------------
254 unsigned vertex(double* x
, double* y
)
256 if(m_data
== 0 || m_ptr
> m_end
)
260 return path_cmd_stop
;
267 m_ptr
+= sizeof(vertex_integer_type
);
268 return path_cmd_end_poly
| path_flags_close
;
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)
279 return path_cmd_end_poly
| path_flags_close
;
282 m_ptr
+= sizeof(vertex_integer_type
);