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_BASICS_INCLUDED
17 #define AGG_BASICS_INCLUDED
18 
19 #include <math.h>
20 #include "agg_config.h"
21 
22 //---------------------------------------------------------AGG_CUSTOM_ALLOCATOR
23 #ifdef AGG_CUSTOM_ALLOCATOR
24 #include "agg_allocator.h"
25 #else
26 namespace agg
27 {
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
37     {
allocatepod_allocator38         static T*   allocate(unsigned num)       { return new T [num]; }
deallocatepod_allocator39         static void deallocate(T* ptr, unsigned) { delete [] ptr;      }
40     };
41 
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
51     {
allocateobj_allocator52         static T*   allocate()         { return new T; }
deallocateobj_allocator53         static void deallocate(T* ptr) { delete ptr;   }
54     };
55 }
56 #endif
57 
58 
59 //-------------------------------------------------------- Default basic types
60 //
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
63 // empty by default.
64 //
65 #ifndef AGG_INT8
66 #define AGG_INT8 signed char
67 #endif
68 
69 #ifndef AGG_INT8U
70 #define AGG_INT8U unsigned char
71 #endif
72 
73 #ifndef AGG_INT16
74 #define AGG_INT16 short
75 #endif
76 
77 #ifndef AGG_INT16U
78 #define AGG_INT16U unsigned short
79 #endif
80 
81 #ifndef AGG_INT32
82 #define AGG_INT32 int
83 #endif
84 
85 #ifndef AGG_INT32U
86 #define AGG_INT32U unsigned
87 #endif
88 
89 #ifndef AGG_INT64
90 #if defined(_MSC_VER) || defined(__BORLANDC__)
91 #define AGG_INT64 signed __int64
92 #else
93 #define AGG_INT64 signed long long
94 #endif
95 #endif
96 
97 #ifndef AGG_INT64U
98 #if defined(_MSC_VER) || defined(__BORLANDC__)
99 #define AGG_INT64U unsigned __int64
100 #else
101 #define AGG_INT64U unsigned long long
102 #endif
103 #endif
104 
105 //------------------------------------------------ Some fixes for MS Visual C++
106 #if defined(_MSC_VER)
107 #pragma warning(disable:4786) // Identifier was truncated...
108 #endif
109 
110 #if defined(_MSC_VER)
111 #define AGG_INLINE __forceinline
112 #else
113 #define AGG_INLINE inline
114 #endif
115 
116 namespace agg
117 {
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
127 
128 #if defined(AGG_FISTP)
129 #pragma warning(push)
130 #pragma warning(disable : 4035) //Disable warning "no return value"
iround(double v)131     AGG_INLINE int iround(double v)              //-------iround
132     {
133         int t;
134         __asm fld   qword ptr [v]
135         __asm fistp dword ptr [t]
136         __asm mov eax, dword ptr [t]
137     }
uround(double v)138     AGG_INLINE unsigned uround(double v)         //-------uround
139     {
140         unsigned t;
141         __asm fld   qword ptr [v]
142         __asm fistp dword ptr [t]
143         __asm mov eax, dword ptr [t]
144     }
145 #pragma warning(pop)
ifloor(double v)146     AGG_INLINE int ifloor(double v)
147     {
148         return int(floor(v));
149     }
ufloor(double v)150     AGG_INLINE unsigned ufloor(double v)         //-------ufloor
151     {
152         return unsigned(floor(v));
153     }
iceil(double v)154     AGG_INLINE int iceil(double v)
155     {
156         return int(ceil(v));
157     }
uceil(double v)158     AGG_INLINE unsigned uceil(double v)          //--------uceil
159     {
160         return unsigned(ceil(v));
161     }
162 #elif defined(AGG_QIFIST)
iround(double v)163     AGG_INLINE int iround(double v)
164     {
165         return int(v);
166     }
uround(double v)167     AGG_INLINE int uround(double v)
168     {
169         return unsigned(v);
170     }
ifloor(double v)171     AGG_INLINE int ifloor(double v)
172     {
173         return int(floor(v));
174     }
ufloor(double v)175     AGG_INLINE unsigned ufloor(double v)
176     {
177         return unsigned(floor(v));
178     }
iceil(double v)179     AGG_INLINE int iceil(double v)
180     {
181         return int(ceil(v));
182     }
uceil(double v)183     AGG_INLINE unsigned uceil(double v)
184     {
185         return unsigned(ceil(v));
186     }
187 #else
iround(double v)188     AGG_INLINE int iround(double v)
189     {
190         return int((v < 0.0) ? v - 0.5 : v + 0.5);
191     }
uround(double v)192     AGG_INLINE int uround(double v)
193     {
194         return unsigned(v + 0.5);
195     }
ifloor(double v)196     AGG_INLINE int ifloor(double v)
197     {
198         int i = int(v);
199         return i - (i > v);
200     }
ufloor(double v)201     AGG_INLINE unsigned ufloor(double v)
202     {
203         return unsigned(v);
204     }
iceil(double v)205     AGG_INLINE int iceil(double v)
206     {
207         return int(ceil(v));
208     }
uceil(double v)209     AGG_INLINE unsigned uceil(double v)
210     {
211         return unsigned(ceil(v));
212     }
213 #endif
214 
215     //---------------------------------------------------------------saturation
216     template<int Limit> struct saturation
217     {
iroundsaturation218         AGG_INLINE static int iround(double v)
219         {
220             if(v < double(-Limit)) return -Limit;
221             if(v > double( Limit)) return  Limit;
222             return agg::iround(v);
223         }
224     };
225 
226     //------------------------------------------------------------------mul_one
227     template<unsigned Shift> struct mul_one
228     {
mulmul_one229         AGG_INLINE static unsigned mul(unsigned a, unsigned b)
230         {
231             unsigned q = a * b + (1 << (Shift-1));
232             return (q + (q >> Shift)) >> Shift;
233         }
234     };
235 
236     //-------------------------------------------------------------------------
237     typedef unsigned char cover_type;    //----cover_type
238     enum cover_scale_e
239     {
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
245     };
246 
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
254     {
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
258     };
259 
260     //----------------------------------------------------------filling_rule_e
261     enum filling_rule_e
262     {
263         fill_non_zero,
264         fill_even_odd
265     };
266 
267     //-----------------------------------------------------------------------pi
268     const double pi = 3.14159265358979323846;
269 
270     //------------------------------------------------------------------deg2rad
deg2rad(double deg)271     inline double deg2rad(double deg)
272     {
273         return deg * pi / 180.0;
274     }
275 
276     //------------------------------------------------------------------rad2deg
rad2deg(double rad)277     inline double rad2deg(double rad)
278     {
279         return rad * 180.0 / pi;
280     }
281 
282     //----------------------------------------------------------------rect_base
283     template<class T> struct rect_base
284     {
285         typedef T            value_type;
286         typedef rect_base<T> self_type;
287         T x1, y1, x2, y2;
288 
rect_baserect_base289         rect_base() {}
rect_baserect_base290         rect_base(T x1_, T y1_, T x2_, T y2_) :
291             x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
292 
initrect_base293         void init(T x1_, T y1_, T x2_, T y2_)
294         {
295             x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_;
296         }
297 
normalizerect_base298         const self_type& normalize()
299         {
300             T t;
301             if(x1 > x2) { t = x1; x1 = x2; x2 = t; }
302             if(y1 > y2) { t = y1; y1 = y2; y2 = t; }
303             return *this;
304         }
305 
cliprect_base306         bool clip(const self_type& r)
307         {
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;
313         }
314 
is_validrect_base315         bool is_valid() const
316         {
317             return x1 <= x2 && y1 <= y2;
318         }
319 
hit_testrect_base320         bool hit_test(T x, T y) const
321         {
322             return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
323         }
324 
overlapsrect_base325         bool overlaps(const self_type& r) const
326         {
327             return !(r.x1 > x2 || r.x2 < x1
328                   || r.y1 > y2 || r.y2 < y1);
329         }
330     };
331 
332     //-----------------------------------------------------intersect_rectangles
333     template<class Rect>
intersect_rectangles(const Rect & r1,const Rect & r2)334     inline Rect intersect_rectangles(const Rect& r1, const Rect& r2)
335     {
336         Rect r = r1;
337 
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.
342         //-----------------
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;
347         return r;
348     }
349 
350 
351     //---------------------------------------------------------unite_rectangles
352     template<class Rect>
unite_rectangles(const Rect & r1,const Rect & r2)353     inline Rect unite_rectangles(const Rect& r1, const Rect& r2)
354     {
355         Rect r = r1;
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;
360         return r;
361     }
362 
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
366 
367     //---------------------------------------------------------path_commands_e
368     enum path_commands_e
369     {
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
380     };
381 
382     //------------------------------------------------------------path_flags_e
383     enum path_flags_e
384     {
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
390     };
391 
392     //---------------------------------------------------------------is_vertex
is_vertex(unsigned c)393     inline bool is_vertex(unsigned c)
394     {
395         return c >= path_cmd_move_to && c < path_cmd_end_poly;
396     }
397 
398     //--------------------------------------------------------------is_drawing
is_drawing(unsigned c)399     inline bool is_drawing(unsigned c)
400     {
401         return c >= path_cmd_line_to && c < path_cmd_end_poly;
402     }
403 
404     //-----------------------------------------------------------------is_stop
is_stop(unsigned c)405     inline bool is_stop(unsigned c)
406     {
407         return c == path_cmd_stop;
408     }
409 
410     //--------------------------------------------------------------is_move_to
is_move_to(unsigned c)411     inline bool is_move_to(unsigned c)
412     {
413         return c == path_cmd_move_to;
414     }
415 
416     //--------------------------------------------------------------is_line_to
is_line_to(unsigned c)417     inline bool is_line_to(unsigned c)
418     {
419         return c == path_cmd_line_to;
420     }
421 
422     //----------------------------------------------------------------is_curve
is_curve(unsigned c)423     inline bool is_curve(unsigned c)
424     {
425         return c == path_cmd_curve3 || c == path_cmd_curve4;
426     }
427 
428     //---------------------------------------------------------------is_curve3
is_curve3(unsigned c)429     inline bool is_curve3(unsigned c)
430     {
431         return c == path_cmd_curve3;
432     }
433 
434     //---------------------------------------------------------------is_curve4
is_curve4(unsigned c)435     inline bool is_curve4(unsigned c)
436     {
437         return c == path_cmd_curve4;
438     }
439 
440     //-------------------------------------------------------------is_end_poly
is_end_poly(unsigned c)441     inline bool is_end_poly(unsigned c)
442     {
443         return (c & path_cmd_mask) == path_cmd_end_poly;
444     }
445 
446     //----------------------------------------------------------------is_close
is_close(unsigned c)447     inline bool is_close(unsigned c)
448     {
449         return (c & ~(path_flags_cw | path_flags_ccw)) ==
450                (path_cmd_end_poly | path_flags_close);
451     }
452 
453     //------------------------------------------------------------is_next_poly
is_next_poly(unsigned c)454     inline bool is_next_poly(unsigned c)
455     {
456         return is_stop(c) || is_move_to(c) || is_end_poly(c);
457     }
458 
459     //-------------------------------------------------------------------is_cw
is_cw(unsigned c)460     inline bool is_cw(unsigned c)
461     {
462         return (c & path_flags_cw) != 0;
463     }
464 
465     //------------------------------------------------------------------is_ccw
is_ccw(unsigned c)466     inline bool is_ccw(unsigned c)
467     {
468         return (c & path_flags_ccw) != 0;
469     }
470 
471     //-------------------------------------------------------------is_oriented
is_oriented(unsigned c)472     inline bool is_oriented(unsigned c)
473     {
474         return (c & (path_flags_cw | path_flags_ccw)) != 0;
475     }
476 
477     //---------------------------------------------------------------is_closed
is_closed(unsigned c)478     inline bool is_closed(unsigned c)
479     {
480         return (c & path_flags_close) != 0;
481     }
482 
483     //----------------------------------------------------------get_close_flag
get_close_flag(unsigned c)484     inline unsigned get_close_flag(unsigned c)
485     {
486         return c & path_flags_close;
487     }
488 
489     //-------------------------------------------------------clear_orientation
clear_orientation(unsigned c)490     inline unsigned clear_orientation(unsigned c)
491     {
492         return c & ~(path_flags_cw | path_flags_ccw);
493     }
494 
495     //---------------------------------------------------------get_orientation
get_orientation(unsigned c)496     inline unsigned get_orientation(unsigned c)
497     {
498         return c & (path_flags_cw | path_flags_ccw);
499     }
500 
501     //---------------------------------------------------------set_orientation
set_orientation(unsigned c,unsigned o)502     inline unsigned set_orientation(unsigned c, unsigned o)
503     {
504         return clear_orientation(c) | o;
505     }
506 
507     //--------------------------------------------------------------point_base
508     template<class T> struct point_base
509     {
510         typedef T value_type;
511         T x,y;
point_basepoint_base512         point_base() {}
point_basepoint_base513         point_base(T x_, T y_) : x(x_), y(y_) {}
514     };
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
518 
519     //-------------------------------------------------------------vertex_base
520     template<class T> struct vertex_base
521     {
522         typedef T value_type;
523         T x,y;
524         unsigned cmd;
vertex_basevertex_base525         vertex_base() {}
vertex_basevertex_base526         vertex_base(T x_, T y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {}
527     };
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
531 
532     //----------------------------------------------------------------row_info
533     template<class T> struct row_info
534     {
535         int x1, x2;
536         T* ptr;
row_inforow_info537         row_info() {}
row_inforow_info538         row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {}
539     };
540 
541     //----------------------------------------------------------const_row_info
542     template<class T> struct const_row_info
543     {
544         int x1, x2;
545         const T* ptr;
const_row_infoconst_row_info546         const_row_info() {}
const_row_infoconst_row_info547         const_row_info(int x1_, int x2_, const T* ptr_) :
548             x1(x1_), x2(x2_), ptr(ptr_) {}
549     };
550 
551     //------------------------------------------------------------is_equal_eps
is_equal_eps(T v1,T v2,T epsilon)552     template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon)
553     {
554         return fabs(v1 - v2) <= double(epsilon);
555     }
556 }
557 
558 
559 #endif
560 
561