xref: /haiku/headers/libs/agg/agg_basics.h (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
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     {
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 
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"
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 unsigned ufloor(double v)         //-------ufloor
147     {
148         return unsigned(floor(v));
149     }
150     AGG_INLINE unsigned uceil(double v)          //--------uceil
151     {
152         return unsigned(ceil(v));
153     }
154 #elif defined(AGG_QIFIST)
155     AGG_INLINE int iround(double v)
156     {
157         return int(v);
158     }
159     AGG_INLINE int uround(double v)
160     {
161         return unsigned(v);
162     }
163     AGG_INLINE unsigned ufloor(double v)
164     {
165         return unsigned(floor(v));
166     }
167     AGG_INLINE unsigned uceil(double v)
168     {
169         return unsigned(ceil(v));
170     }
171 #else
172     AGG_INLINE int iround(double v)
173     {
174         return int((v < 0.0) ? v - 0.5 : v + 0.5);
175     }
176     AGG_INLINE int uround(double v)
177     {
178         return unsigned(v + 0.5);
179     }
180     AGG_INLINE unsigned ufloor(double v)
181     {
182         return unsigned(v);
183     }
184     AGG_INLINE unsigned uceil(double v)
185     {
186         return unsigned(ceil(v));
187     }
188 #endif
189 
190     //---------------------------------------------------------------saturation
191     template<int Limit> struct saturation
192     {
193         AGG_INLINE static int iround(double v)
194         {
195             if(v < double(-Limit)) return -Limit;
196             if(v > double( Limit)) return  Limit;
197             return agg::iround(v);
198         }
199     };
200 
201     //------------------------------------------------------------------mul_one
202     template<unsigned Shift> struct mul_one
203     {
204         AGG_INLINE static unsigned mul(unsigned a, unsigned b)
205         {
206             register unsigned q = a * b + (1 << (Shift-1));
207             return (q + (q >> Shift)) >> Shift;
208         }
209     };
210 
211     //-------------------------------------------------------------------------
212     typedef unsigned char cover_type;    //----cover_type
213     enum cover_scale_e
214     {
215         cover_shift = 8,                 //----cover_shift
216         cover_size  = 1 << cover_shift,  //----cover_size
217         cover_mask  = cover_size - 1,    //----cover_mask
218         cover_none  = 0,                 //----cover_none
219         cover_full  = cover_mask         //----cover_full
220     };
221 
222     //----------------------------------------------------poly_subpixel_scale_e
223     // These constants determine the subpixel accuracy, to be more precise,
224     // the number of bits of the fractional part of the coordinates.
225     // The possible coordinate capacity in bits can be calculated by formula:
226     // sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and
227     // 8-bits fractional part the capacity is 24 bits.
228     enum poly_subpixel_scale_e
229     {
230         poly_subpixel_shift = 8,                      //----poly_subpixel_shift
231         poly_subpixel_scale = 1<<poly_subpixel_shift, //----poly_subpixel_scale
232         poly_subpixel_mask  = poly_subpixel_scale-1,  //----poly_subpixel_mask
233     };
234 
235     //----------------------------------------------------------filling_rule_e
236     enum filling_rule_e
237     {
238         fill_non_zero,
239         fill_even_odd
240     };
241 
242     //-----------------------------------------------------------------------pi
243     const double pi = 3.14159265358979323846;
244 
245     //------------------------------------------------------------------deg2rad
246     inline double deg2rad(double deg)
247     {
248         return deg * pi / 180.0;
249     }
250 
251     //------------------------------------------------------------------rad2deg
252     inline double rad2deg(double rad)
253     {
254         return rad * 180.0 / pi;
255     }
256 
257     //----------------------------------------------------------------rect_base
258     template<class T> struct rect_base
259     {
260         typedef rect_base<T> self_type;
261         T x1;
262         T y1;
263         T x2;
264         T y2;
265 
266         rect_base() {}
267         rect_base(T x1_, T y1_, T x2_, T y2_) :
268             x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
269 
270         const self_type& normalize()
271         {
272             T t;
273             if(x1 > x2) { t = x1; x1 = x2; x2 = t; }
274             if(y1 > y2) { t = y1; y1 = y2; y2 = t; }
275             return *this;
276         }
277 
278         bool clip(const self_type& r)
279         {
280             if(x2 > r.x2) x2 = r.x2;
281             if(y2 > r.y2) y2 = r.y2;
282             if(x1 < r.x1) x1 = r.x1;
283             if(y1 < r.y1) y1 = r.y1;
284             return x1 <= x2 && y1 <= y2;
285         }
286 
287         bool is_valid() const
288         {
289             return x1 <= x2 && y1 <= y2;
290         }
291     };
292 
293     //-----------------------------------------------------intersect_rectangles
294     template<class Rect>
295     inline Rect intersect_rectangles(const Rect& r1, const Rect& r2)
296     {
297         Rect r = r1;
298 
299         // First process x2,y2 because the other order
300         // results in Internal Compiler Error under
301         // Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in
302         // case of "Maximize Speed" optimization option.
303         //-----------------
304         if(r.x2 > r2.x2) r.x2 = r2.x2;
305         if(r.y2 > r2.y2) r.y2 = r2.y2;
306         if(r.x1 < r2.x1) r.x1 = r2.x1;
307         if(r.y1 < r2.y1) r.y1 = r2.y1;
308         return r;
309     }
310 
311 
312     //---------------------------------------------------------unite_rectangles
313     template<class Rect>
314     inline Rect unite_rectangles(const Rect& r1, const Rect& r2)
315     {
316         Rect r = r1;
317         if(r.x2 < r2.x2) r.x2 = r2.x2;
318         if(r.y2 < r2.y2) r.y2 = r2.y2;
319         if(r.x1 > r2.x1) r.x1 = r2.x1;
320         if(r.y1 > r2.y1) r.y1 = r2.y1;
321         return r;
322     }
323 
324     typedef rect_base<int>    rect_i; //----rect_i
325     typedef rect_base<float>  rect_f; //----rect_f
326     typedef rect_base<double> rect_d; //----rect_d
327 
328     //---------------------------------------------------------path_commands_e
329     enum path_commands_e
330     {
331         path_cmd_stop     = 0,        //----path_cmd_stop
332         path_cmd_move_to  = 1,        //----path_cmd_move_to
333         path_cmd_line_to  = 2,        //----path_cmd_line_to
334         path_cmd_curve3   = 3,        //----path_cmd_curve3
335         path_cmd_curve4   = 4,        //----path_cmd_curve4
336         path_cmd_curveN   = 5,        //----path_cmd_curveN
337         path_cmd_catrom   = 6,        //----path_cmd_catrom
338         path_cmd_ubspline = 7,        //----path_cmd_ubspline
339         path_cmd_end_poly = 0x0F,     //----path_cmd_end_poly
340         path_cmd_mask     = 0x0F      //----path_cmd_mask
341     };
342 
343     //------------------------------------------------------------path_flags_e
344     enum path_flags_e
345     {
346         path_flags_none  = 0,         //----path_flags_none
347         path_flags_ccw   = 0x10,      //----path_flags_ccw
348         path_flags_cw    = 0x20,      //----path_flags_cw
349         path_flags_close = 0x40,      //----path_flags_close
350         path_flags_mask  = 0xF0       //----path_flags_mask
351     };
352 
353     //---------------------------------------------------------------is_vertex
354     inline bool is_vertex(unsigned c)
355     {
356         return c >= path_cmd_move_to && c < path_cmd_end_poly;
357     }
358 
359     //--------------------------------------------------------------is_drawing
360     inline bool is_drawing(unsigned c)
361     {
362         return c >= path_cmd_line_to && c < path_cmd_end_poly;
363     }
364 
365     //-----------------------------------------------------------------is_stop
366     inline bool is_stop(unsigned c)
367     {
368         return c == path_cmd_stop;
369     }
370 
371     //--------------------------------------------------------------is_move_to
372     inline bool is_move_to(unsigned c)
373     {
374         return c == path_cmd_move_to;
375     }
376 
377     //--------------------------------------------------------------is_line_to
378     inline bool is_line_to(unsigned c)
379     {
380         return c == path_cmd_line_to;
381     }
382 
383     //----------------------------------------------------------------is_curve
384     inline bool is_curve(unsigned c)
385     {
386         return c == path_cmd_curve3 || c == path_cmd_curve4;
387     }
388 
389     //---------------------------------------------------------------is_curve3
390     inline bool is_curve3(unsigned c)
391     {
392         return c == path_cmd_curve3;
393     }
394 
395     //---------------------------------------------------------------is_curve4
396     inline bool is_curve4(unsigned c)
397     {
398         return c == path_cmd_curve4;
399     }
400 
401     //-------------------------------------------------------------is_end_poly
402     inline bool is_end_poly(unsigned c)
403     {
404         return (c & path_cmd_mask) == path_cmd_end_poly;
405     }
406 
407     //----------------------------------------------------------------is_close
408     inline bool is_close(unsigned c)
409     {
410         return (c & ~(path_flags_cw | path_flags_ccw)) ==
411                (path_cmd_end_poly | path_flags_close);
412     }
413 
414     //------------------------------------------------------------is_next_poly
415     inline bool is_next_poly(unsigned c)
416     {
417         return is_stop(c) || is_move_to(c) || is_end_poly(c);
418     }
419 
420     //-------------------------------------------------------------------is_cw
421     inline bool is_cw(unsigned c)
422     {
423         return (c & path_flags_cw) != 0;
424     }
425 
426     //------------------------------------------------------------------is_ccw
427     inline bool is_ccw(unsigned c)
428     {
429         return (c & path_flags_ccw) != 0;
430     }
431 
432     //-------------------------------------------------------------is_oriented
433     inline bool is_oriented(unsigned c)
434     {
435         return (c & (path_flags_cw | path_flags_ccw)) != 0;
436     }
437 
438     //---------------------------------------------------------------is_closed
439     inline bool is_closed(unsigned c)
440     {
441         return (c & path_flags_close) != 0;
442     }
443 
444     //----------------------------------------------------------get_close_flag
445     inline unsigned get_close_flag(unsigned c)
446     {
447         return c & path_flags_close;
448     }
449 
450     //-------------------------------------------------------clear_orientation
451     inline unsigned clear_orientation(unsigned c)
452     {
453         return c & ~(path_flags_cw | path_flags_ccw);
454     }
455 
456     //---------------------------------------------------------get_orientation
457     inline unsigned get_orientation(unsigned c)
458     {
459         return c & (path_flags_cw | path_flags_ccw);
460     }
461 
462     //---------------------------------------------------------set_orientation
463     inline unsigned set_orientation(unsigned c, unsigned o)
464     {
465         return clear_orientation(c) | o;
466     }
467 
468     //--------------------------------------------------------------point_base
469     template<class T> struct point_base
470     {
471         typedef T value_type;
472         T x,y;
473         point_base() {}
474         point_base(T x_, T y_) : x(x_), y(y_) {}
475     };
476     typedef point_base<int>    point_i; //-----point_i
477     typedef point_base<float>  point_f; //-----point_f
478     typedef point_base<double> point_d; //-----point_d
479 
480     //-------------------------------------------------------------vertex_base
481     template<class T> struct vertex_base
482     {
483         typedef T value_type;
484         T x,y;
485         unsigned cmd;
486         vertex_base() {}
487         vertex_base(T x_, T y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {}
488     };
489     typedef vertex_base<int>    vertex_i; //-----vertex_i
490     typedef vertex_base<float>  vertex_f; //-----vertex_f
491     typedef vertex_base<double> vertex_d; //-----vertex_d
492 
493 }
494 
495 
496 #endif
497 
498