agg_basics.h revision 8cc5325a
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
26namespace 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    {
38        static T*   allocate(unsigned num)       { return new T [num]; }
39        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    {
52        static T*   allocate()         { return new T; }
53        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
116namespace 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"
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    }
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)
146    AGG_INLINE int ifloor(double v)
147    {
148        return int(floor(v));
149    }
150    AGG_INLINE unsigned ufloor(double v)         //-------ufloor
151    {
152        return unsigned(floor(v));
153    }
154    AGG_INLINE int iceil(double v)
155    {
156        return int(ceil(v));
157    }
158    AGG_INLINE unsigned uceil(double v)          //--------uceil
159    {
160        return unsigned(ceil(v));
161    }
162#elif defined(AGG_QIFIST)
163    AGG_INLINE int iround(double v)
164    {
165        return int(v);
166    }
167    AGG_INLINE int uround(double v)
168    {
169        return unsigned(v);
170    }
171    AGG_INLINE int ifloor(double v)
172    {
173        return int(floor(v));
174    }
175    AGG_INLINE unsigned ufloor(double v)
176    {
177        return unsigned(floor(v));
178    }
179    AGG_INLINE int iceil(double v)
180    {
181        return int(ceil(v));
182    }
183    AGG_INLINE unsigned uceil(double v)
184    {
185        return unsigned(ceil(v));
186    }
187#else
188    AGG_INLINE int iround(double v)
189    {
190        return int((v < 0.0) ? v - 0.5 : v + 0.5);
191    }
192    AGG_INLINE int uround(double v)
193    {
194        return unsigned(v + 0.5);
195    }
196    AGG_INLINE int ifloor(double v)
197    {
198        int i = int(v);
199        return i - (i > v);
200    }
201    AGG_INLINE unsigned ufloor(double v)
202    {
203        return unsigned(v);
204    }
205    AGG_INLINE int iceil(double v)
206    {
207        return int(ceil(v));
208    }
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    {
218        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    {
229        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
271    inline double deg2rad(double deg)
272    {
273        return deg * pi / 180.0;
274    }
275
276    //------------------------------------------------------------------rad2deg
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
289        rect_base() {}
290        rect_base(T x1_, T y1_, T x2_, T y2_) :
291            x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
292
293        void init(T x1_, T y1_, T x2_, T y2_)
294        {
295            x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_;
296        }
297
298        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
306        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
315        bool is_valid() const
316        {
317            return x1 <= x2 && y1 <= y2;
318        }
319
320        bool hit_test(T x, T y) const
321        {
322            return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
323        }
324
325        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>
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>
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
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
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
405    inline bool is_stop(unsigned c)
406    {
407        return c == path_cmd_stop;
408    }
409
410    //--------------------------------------------------------------is_move_to
411    inline bool is_move_to(unsigned c)
412    {
413        return c == path_cmd_move_to;
414    }
415
416    //--------------------------------------------------------------is_line_to
417    inline bool is_line_to(unsigned c)
418    {
419        return c == path_cmd_line_to;
420    }
421
422    //----------------------------------------------------------------is_curve
423    inline bool is_curve(unsigned c)
424    {
425        return c == path_cmd_curve3 || c == path_cmd_curve4;
426    }
427
428    //---------------------------------------------------------------is_curve3
429    inline bool is_curve3(unsigned c)
430    {
431        return c == path_cmd_curve3;
432    }
433
434    //---------------------------------------------------------------is_curve4
435    inline bool is_curve4(unsigned c)
436    {
437        return c == path_cmd_curve4;
438    }
439
440    //-------------------------------------------------------------is_end_poly
441    inline bool is_end_poly(unsigned c)
442    {
443        return (c & path_cmd_mask) == path_cmd_end_poly;
444    }
445
446    //----------------------------------------------------------------is_close
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
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
460    inline bool is_cw(unsigned c)
461    {
462        return (c & path_flags_cw) != 0;
463    }
464
465    //------------------------------------------------------------------is_ccw
466    inline bool is_ccw(unsigned c)
467    {
468        return (c & path_flags_ccw) != 0;
469    }
470
471    //-------------------------------------------------------------is_oriented
472    inline bool is_oriented(unsigned c)
473    {
474        return (c & (path_flags_cw | path_flags_ccw)) != 0;
475    }
476
477    //---------------------------------------------------------------is_closed
478    inline bool is_closed(unsigned c)
479    {
480        return (c & path_flags_close) != 0;
481    }
482
483    //----------------------------------------------------------get_close_flag
484    inline unsigned get_close_flag(unsigned c)
485    {
486        return c & path_flags_close;
487    }
488
489    //-------------------------------------------------------clear_orientation
490    inline unsigned clear_orientation(unsigned c)
491    {
492        return c & ~(path_flags_cw | path_flags_ccw);
493    }
494
495    //---------------------------------------------------------get_orientation
496    inline unsigned get_orientation(unsigned c)
497    {
498        return c & (path_flags_cw | path_flags_ccw);
499    }
500
501    //---------------------------------------------------------set_orientation
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;
512        point_base() {}
513        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;
525        vertex_base() {}
526        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;
537        row_info() {}
538        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;
546        const_row_info() {}
547        const_row_info(int x1_, int x2_, const T* ptr_) :
548            x1(x1_), x2(x2_), ptr(ptr_) {}
549    };
550
551    //------------------------------------------------------------is_equal_eps
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