1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
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_BASICS_INCLUDED
17 #define AGG_BASICS_INCLUDED
20 #include "agg_config.h"
22 //---------------------------------------------------------AGG_CUSTOM_ALLOCATOR
23 #ifdef AGG_CUSTOM_ALLOCATOR
24 #include "agg_allocator.h"
28 // The policy of all AGG containers and memory allocation strategy
29 // in general is that no allocated data requires explicit construction.
30 // It means that the allocator can be really simple; you can even
31 // replace new/delete to malloc/free. The constructors and destructors
32 // won't be called in this case, however everything will remain working.
33 // The second argument of deallocate() is the size of the allocated
34 // block. You can use this information if you wish.
35 //------------------------------------------------------------pod_allocator
36 template<class T
> struct pod_allocator
38 static T
* allocate(unsigned num
) { return new T
[num
]; }
39 static void deallocate(T
* ptr
, unsigned) { delete [] ptr
; }
42 // Single object allocator. It's also can be replaced with your custom
43 // allocator. The difference is that it can only allocate a single
44 // object and the constructor and destructor must be called.
45 // In AGG there is no need to allocate an array of objects with
46 // calling their constructors (only single ones). So that, if you
47 // replace these new/delete to malloc/free make sure that the in-place
48 // new is called and take care of calling the destructor too.
49 //------------------------------------------------------------obj_allocator
50 template<class T
> struct obj_allocator
52 static T
* allocate() { return new T
; }
53 static void deallocate(T
* ptr
) { delete ptr
; }
59 //-------------------------------------------------------- Default basic types
61 // If the compiler has different capacity of the basic types you can redefine
62 // them via the compiler command line or by generating agg_config.h that is
66 #define AGG_INT8 signed char
70 #define AGG_INT8U unsigned char
74 #define AGG_INT16 short
78 #define AGG_INT16U unsigned short
86 #define AGG_INT32U unsigned
90 #if defined(_MSC_VER) || defined(__BORLANDC__)
91 #define AGG_INT64 signed __int64
93 #define AGG_INT64 signed long long
98 #if defined(_MSC_VER) || defined(__BORLANDC__)
99 #define AGG_INT64U unsigned __int64
101 #define AGG_INT64U unsigned long long
105 //------------------------------------------------ Some fixes for MS Visual C++
106 #if defined(_MSC_VER)
107 #pragma warning(disable:4786) // Identifier was truncated...
110 #if defined(_MSC_VER)
111 #define AGG_INLINE __forceinline
113 #define AGG_INLINE inline
118 //-------------------------------------------------------------------------
119 typedef AGG_INT8 int8
; //----int8
120 typedef AGG_INT8U int8u
; //----int8u
121 typedef AGG_INT16 int16
; //----int16
122 typedef AGG_INT16U int16u
; //----int16u
123 typedef AGG_INT32 int32
; //----int32
124 typedef AGG_INT32U int32u
; //----int32u
125 typedef AGG_INT64 int64
; //----int64
126 typedef AGG_INT64U int64u
; //----int64u
128 #if defined(AGG_FISTP)
129 #pragma warning(push)
130 #pragma warning(disable : 4035) //Disable warning "no return value"
131 AGG_INLINE
int iround(double v
) //-------iround
134 __asm fld qword ptr
[v
]
135 __asm fistp dword ptr
[t
]
136 __asm mov eax
, dword ptr
[t
]
138 AGG_INLINE
unsigned uround(double v
) //-------uround
141 __asm fld qword ptr
[v
]
142 __asm fistp dword ptr
[t
]
143 __asm mov eax
, dword ptr
[t
]
146 AGG_INLINE
int ifloor(double v
)
148 return int(floor(v
));
150 AGG_INLINE
unsigned ufloor(double v
) //-------ufloor
152 return unsigned(floor(v
));
154 AGG_INLINE
int iceil(double v
)
158 AGG_INLINE
unsigned uceil(double v
) //--------uceil
160 return unsigned(ceil(v
));
162 #elif defined(AGG_QIFIST)
163 AGG_INLINE
int iround(double v
)
167 AGG_INLINE
int uround(double v
)
171 AGG_INLINE
int ifloor(double v
)
173 return int(floor(v
));
175 AGG_INLINE
unsigned ufloor(double v
)
177 return unsigned(floor(v
));
179 AGG_INLINE
int iceil(double v
)
183 AGG_INLINE
unsigned uceil(double v
)
185 return unsigned(ceil(v
));
188 AGG_INLINE
int iround(double v
)
190 return int((v
< 0.0) ? v
- 0.5 : v
+ 0.5);
192 AGG_INLINE
int uround(double v
)
194 return unsigned(v
+ 0.5);
196 AGG_INLINE
int ifloor(double v
)
201 AGG_INLINE
unsigned ufloor(double v
)
205 AGG_INLINE
int iceil(double v
)
209 AGG_INLINE
unsigned uceil(double v
)
211 return unsigned(ceil(v
));
215 //---------------------------------------------------------------saturation
216 template<int Limit
> struct saturation
218 AGG_INLINE
static int iround(double v
)
220 if(v
< double(-Limit
)) return -Limit
;
221 if(v
> double( Limit
)) return Limit
;
222 return agg::iround(v
);
226 //------------------------------------------------------------------mul_one
227 template<unsigned Shift
> struct mul_one
229 AGG_INLINE
static unsigned mul(unsigned a
, unsigned b
)
231 unsigned q
= a
* b
+ (1 << (Shift
-1));
232 return (q
+ (q
>> Shift
)) >> Shift
;
236 //-------------------------------------------------------------------------
237 typedef unsigned char cover_type
; //----cover_type
240 cover_shift
= 8, //----cover_shift
241 cover_size
= 1 << cover_shift
, //----cover_size
242 cover_mask
= cover_size
- 1, //----cover_mask
243 cover_none
= 0, //----cover_none
244 cover_full
= cover_mask
//----cover_full
247 //----------------------------------------------------poly_subpixel_scale_e
248 // These constants determine the subpixel accuracy, to be more precise,
249 // the number of bits of the fractional part of the coordinates.
250 // The possible coordinate capacity in bits can be calculated by formula:
251 // sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and
252 // 8-bits fractional part the capacity is 24 bits.
253 enum poly_subpixel_scale_e
255 poly_subpixel_shift
= 8, //----poly_subpixel_shift
256 poly_subpixel_scale
= 1<<poly_subpixel_shift
, //----poly_subpixel_scale
257 poly_subpixel_mask
= poly_subpixel_scale
-1 //----poly_subpixel_mask
260 //----------------------------------------------------------filling_rule_e
267 //-----------------------------------------------------------------------pi
268 const double pi
= 3.14159265358979323846;
270 //------------------------------------------------------------------deg2rad
271 inline double deg2rad(double deg
)
273 return deg
* pi
/ 180.0;
276 //------------------------------------------------------------------rad2deg
277 inline double rad2deg(double rad
)
279 return rad
* 180.0 / pi
;
282 //----------------------------------------------------------------rect_base
283 template<class T
> struct rect_base
285 typedef T value_type
;
286 typedef rect_base
<T
> self_type
;
290 rect_base(T x1_
, T y1_
, T x2_
, T y2_
) :
291 x1(x1_
), y1(y1_
), x2(x2_
), y2(y2_
) {}
293 void init(T x1_
, T y1_
, T x2_
, T y2_
)
295 x1
= x1_
; y1
= y1_
; x2
= x2_
; y2
= y2_
;
298 const self_type
& normalize()
301 if(x1
> x2
) { t
= x1
; x1
= x2
; x2
= t
; }
302 if(y1
> y2
) { t
= y1
; y1
= y2
; y2
= t
; }
306 bool clip(const self_type
& r
)
308 if(x2
> r
.x2
) x2
= r
.x2
;
309 if(y2
> r
.y2
) y2
= r
.y2
;
310 if(x1
< r
.x1
) x1
= r
.x1
;
311 if(y1
< r
.y1
) y1
= r
.y1
;
312 return x1
<= x2
&& y1
<= y2
;
315 bool is_valid() const
317 return x1
<= x2
&& y1
<= y2
;
320 bool hit_test(T x
, T y
) const
322 return (x
>= x1
&& x
<= x2
&& y
>= y1
&& y
<= y2
);
325 bool overlaps(const self_type
& r
) const
327 return !(r
.x1
> x2
|| r
.x2
< x1
328 || r
.y1
> y2
|| r
.y2
< y1
);
332 //-----------------------------------------------------intersect_rectangles
334 inline Rect
intersect_rectangles(const Rect
& r1
, const Rect
& r2
)
338 // First process x2,y2 because the other order
339 // results in Internal Compiler Error under
340 // Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in
341 // case of "Maximize Speed" optimization option.
343 if(r
.x2
> r2
.x2
) r
.x2
= r2
.x2
;
344 if(r
.y2
> r2
.y2
) r
.y2
= r2
.y2
;
345 if(r
.x1
< r2
.x1
) r
.x1
= r2
.x1
;
346 if(r
.y1
< r2
.y1
) r
.y1
= r2
.y1
;
351 //---------------------------------------------------------unite_rectangles
353 inline Rect
unite_rectangles(const Rect
& r1
, const Rect
& r2
)
356 if(r
.x2
< r2
.x2
) r
.x2
= r2
.x2
;
357 if(r
.y2
< r2
.y2
) r
.y2
= r2
.y2
;
358 if(r
.x1
> r2
.x1
) r
.x1
= r2
.x1
;
359 if(r
.y1
> r2
.y1
) r
.y1
= r2
.y1
;
363 typedef rect_base
<int> rect_i
; //----rect_i
364 typedef rect_base
<float> rect_f
; //----rect_f
365 typedef rect_base
<double> rect_d
; //----rect_d
367 //---------------------------------------------------------path_commands_e
370 path_cmd_stop
= 0, //----path_cmd_stop
371 path_cmd_move_to
= 1, //----path_cmd_move_to
372 path_cmd_line_to
= 2, //----path_cmd_line_to
373 path_cmd_curve3
= 3, //----path_cmd_curve3
374 path_cmd_curve4
= 4, //----path_cmd_curve4
375 path_cmd_curveN
= 5, //----path_cmd_curveN
376 path_cmd_catrom
= 6, //----path_cmd_catrom
377 path_cmd_ubspline
= 7, //----path_cmd_ubspline
378 path_cmd_end_poly
= 0x0F, //----path_cmd_end_poly
379 path_cmd_mask
= 0x0F //----path_cmd_mask
382 //------------------------------------------------------------path_flags_e
385 path_flags_none
= 0, //----path_flags_none
386 path_flags_ccw
= 0x10, //----path_flags_ccw
387 path_flags_cw
= 0x20, //----path_flags_cw
388 path_flags_close
= 0x40, //----path_flags_close
389 path_flags_mask
= 0xF0 //----path_flags_mask
392 //---------------------------------------------------------------is_vertex
393 inline bool is_vertex(unsigned c
)
395 return c
>= path_cmd_move_to
&& c
< path_cmd_end_poly
;
398 //--------------------------------------------------------------is_drawing
399 inline bool is_drawing(unsigned c
)
401 return c
>= path_cmd_line_to
&& c
< path_cmd_end_poly
;
404 //-----------------------------------------------------------------is_stop
405 inline bool is_stop(unsigned c
)
407 return c
== path_cmd_stop
;
410 //--------------------------------------------------------------is_move_to
411 inline bool is_move_to(unsigned c
)
413 return c
== path_cmd_move_to
;
416 //--------------------------------------------------------------is_line_to
417 inline bool is_line_to(unsigned c
)
419 return c
== path_cmd_line_to
;
422 //----------------------------------------------------------------is_curve
423 inline bool is_curve(unsigned c
)
425 return c
== path_cmd_curve3
|| c
== path_cmd_curve4
;
428 //---------------------------------------------------------------is_curve3
429 inline bool is_curve3(unsigned c
)
431 return c
== path_cmd_curve3
;
434 //---------------------------------------------------------------is_curve4
435 inline bool is_curve4(unsigned c
)
437 return c
== path_cmd_curve4
;
440 //-------------------------------------------------------------is_end_poly
441 inline bool is_end_poly(unsigned c
)
443 return (c
& path_cmd_mask
) == path_cmd_end_poly
;
446 //----------------------------------------------------------------is_close
447 inline bool is_close(unsigned c
)
449 return (c
& ~(path_flags_cw
| path_flags_ccw
)) ==
450 (path_cmd_end_poly
| path_flags_close
);
453 //------------------------------------------------------------is_next_poly
454 inline bool is_next_poly(unsigned c
)
456 return is_stop(c
) || is_move_to(c
) || is_end_poly(c
);
459 //-------------------------------------------------------------------is_cw
460 inline bool is_cw(unsigned c
)
462 return (c
& path_flags_cw
) != 0;
465 //------------------------------------------------------------------is_ccw
466 inline bool is_ccw(unsigned c
)
468 return (c
& path_flags_ccw
) != 0;
471 //-------------------------------------------------------------is_oriented
472 inline bool is_oriented(unsigned c
)
474 return (c
& (path_flags_cw
| path_flags_ccw
)) != 0;
477 //---------------------------------------------------------------is_closed
478 inline bool is_closed(unsigned c
)
480 return (c
& path_flags_close
) != 0;
483 //----------------------------------------------------------get_close_flag
484 inline unsigned get_close_flag(unsigned c
)
486 return c
& path_flags_close
;
489 //-------------------------------------------------------clear_orientation
490 inline unsigned clear_orientation(unsigned c
)
492 return c
& ~(path_flags_cw
| path_flags_ccw
);
495 //---------------------------------------------------------get_orientation
496 inline unsigned get_orientation(unsigned c
)
498 return c
& (path_flags_cw
| path_flags_ccw
);
501 //---------------------------------------------------------set_orientation
502 inline unsigned set_orientation(unsigned c
, unsigned o
)
504 return clear_orientation(c
) | o
;
507 //--------------------------------------------------------------point_base
508 template<class T
> struct point_base
510 typedef T value_type
;
513 point_base(T x_
, T y_
) : x(x_
), y(y_
) {}
515 typedef point_base
<int> point_i
; //-----point_i
516 typedef point_base
<float> point_f
; //-----point_f
517 typedef point_base
<double> point_d
; //-----point_d
519 //-------------------------------------------------------------vertex_base
520 template<class T
> struct vertex_base
522 typedef T value_type
;
526 vertex_base(T x_
, T y_
, unsigned cmd_
) : x(x_
), y(y_
), cmd(cmd_
) {}
528 typedef vertex_base
<int> vertex_i
; //-----vertex_i
529 typedef vertex_base
<float> vertex_f
; //-----vertex_f
530 typedef vertex_base
<double> vertex_d
; //-----vertex_d
532 //----------------------------------------------------------------row_info
533 template<class T
> struct row_info
538 row_info(int x1_
, int x2_
, T
* ptr_
) : x1(x1_
), x2(x2_
), ptr(ptr_
) {}
541 //----------------------------------------------------------const_row_info
542 template<class T
> struct const_row_info
547 const_row_info(int x1_
, int x2_
, const T
* ptr_
) :
548 x1(x1_
), x2(x2_
), ptr(ptr_
) {}
551 //------------------------------------------------------------is_equal_eps
552 template<class T
> inline bool is_equal_eps(T v1
, T v2
, T epsilon
)
554 return fabs(v1
- v2
) <= double(epsilon
);