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 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