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_IMAGE_ACCESSORS_INCLUDED 17 #define AGG_IMAGE_ACCESSORS_INCLUDED 18 19 #include "agg_basics.h" 20 21 namespace agg 22 { 23 24 //-----------------------------------------------------image_accessor_clip 25 template<class PixFmt> class image_accessor_clip 26 { 27 public: 28 typedef PixFmt pixfmt_type; 29 typedef typename pixfmt_type::color_type color_type; 30 typedef typename pixfmt_type::order_type order_type; 31 typedef typename pixfmt_type::value_type value_type; 32 enum pix_width_e { pix_width = pixfmt_type::pix_width }; 33 34 image_accessor_clip() {} 35 image_accessor_clip(const pixfmt_type& pixf, const color_type& bk) : 36 m_pixf(&pixf) 37 { 38 pixfmt_type::make_pix(m_bk_buf, bk); 39 } 40 41 void attach(const pixfmt_type& pixf) 42 { 43 m_pixf = &pixf; 44 } 45 46 void background_color(const color_type& bk) 47 { 48 pixfmt_type::make_pix(m_bk_buf, bk); 49 } 50 51 private: 52 AGG_INLINE const int8u* pixel() const 53 { 54 if(m_y >= 0 && m_y < (int)m_pixf->height() && 55 m_x >= 0 && m_x < (int)m_pixf->width()) 56 { 57 return m_pixf->pix_ptr(m_x, m_y); 58 } 59 return m_bk_buf; 60 } 61 62 public: 63 AGG_INLINE const int8u* span(int x, int y, unsigned len) 64 { 65 m_x = m_x0 = x; 66 m_y = y; 67 if(y >= 0 && y < (int)m_pixf->height() && 68 x >= 0 && x+(int)len <= (int)m_pixf->width()) 69 { 70 return m_pix_ptr = m_pixf->pix_ptr(x, y); 71 } 72 m_pix_ptr = 0; 73 return pixel(); 74 } 75 76 AGG_INLINE const int8u* next_x() 77 { 78 if(m_pix_ptr) return m_pix_ptr += pix_width; 79 ++m_x; 80 return pixel(); 81 } 82 83 AGG_INLINE const int8u* next_y() 84 { 85 ++m_y; 86 m_x = m_x0; 87 if(m_pix_ptr && 88 m_y >= 0 && m_y < (int)m_pixf->height()) 89 { 90 return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); 91 } 92 m_pix_ptr = 0; 93 return pixel(); 94 } 95 96 private: 97 const pixfmt_type* m_pixf; 98 int8u m_bk_buf[4]; 99 int m_x, m_x0, m_y; 100 const int8u* m_pix_ptr; 101 }; 102 103 104 105 106 //--------------------------------------------------image_accessor_no_clip 107 template<class PixFmt> class image_accessor_no_clip 108 { 109 public: 110 typedef PixFmt pixfmt_type; 111 typedef typename pixfmt_type::color_type color_type; 112 typedef typename pixfmt_type::order_type order_type; 113 typedef typename pixfmt_type::value_type value_type; 114 enum pix_width_e { pix_width = pixfmt_type::pix_width }; 115 116 image_accessor_no_clip() {} 117 image_accessor_no_clip(const pixfmt_type& pixf) : m_pixf(&pixf) {} 118 119 void attach(const pixfmt_type& pixf) 120 { 121 m_pixf = &pixf; 122 } 123 124 AGG_INLINE const int8u* span(int x, int y, unsigned) 125 { 126 m_x = x; 127 m_y = y; 128 return m_pix_ptr = m_pixf->pix_ptr(x, y); 129 } 130 131 AGG_INLINE const int8u* next_x() 132 { 133 return m_pix_ptr += pix_width; 134 } 135 136 AGG_INLINE const int8u* next_y() 137 { 138 ++m_y; 139 return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); 140 } 141 142 private: 143 const pixfmt_type* m_pixf; 144 int m_x, m_y; 145 const int8u* m_pix_ptr; 146 }; 147 148 149 150 151 //----------------------------------------------------image_accessor_clone 152 template<class PixFmt> class image_accessor_clone 153 { 154 public: 155 typedef PixFmt pixfmt_type; 156 typedef typename pixfmt_type::color_type color_type; 157 typedef typename pixfmt_type::order_type order_type; 158 typedef typename pixfmt_type::value_type value_type; 159 enum pix_width_e { pix_width = pixfmt_type::pix_width }; 160 161 image_accessor_clone() {} 162 image_accessor_clone(const pixfmt_type& pixf) : m_pixf(&pixf) {} 163 164 void attach(const pixfmt_type& pixf) 165 { 166 m_pixf = &pixf; 167 } 168 169 private: 170 AGG_INLINE const int8u* pixel() const 171 { 172 int x = m_x; 173 int y = m_y; 174 if(x < 0) x = 0; 175 if(y < 0) y = 0; 176 if(x >= (int)m_pixf->width()) x = m_pixf->width() - 1; 177 if(y >= (int)m_pixf->height()) y = m_pixf->height() - 1; 178 return m_pixf->pix_ptr(x, y); 179 } 180 181 public: 182 AGG_INLINE const int8u* span(int x, int y, unsigned len) 183 { 184 m_x = m_x0 = x; 185 m_y = y; 186 if(y >= 0 && y < (int)m_pixf->height() && 187 x >= 0 && (int)(x+len) <= (int)m_pixf->width()) 188 { 189 return m_pix_ptr = m_pixf->pix_ptr(x, y); 190 } 191 m_pix_ptr = 0; 192 return pixel(); 193 } 194 195 AGG_INLINE const int8u* next_x() 196 { 197 if(m_pix_ptr) return m_pix_ptr += pix_width; 198 ++m_x; 199 return pixel(); 200 } 201 202 AGG_INLINE const int8u* next_y() 203 { 204 ++m_y; 205 m_x = m_x0; 206 if(m_pix_ptr && 207 m_y >= 0 && m_y < (int)m_pixf->height()) 208 { 209 return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); 210 } 211 m_pix_ptr = 0; 212 return pixel(); 213 } 214 215 private: 216 const pixfmt_type* m_pixf; 217 int m_x, m_x0, m_y; 218 const int8u* m_pix_ptr; 219 }; 220 221 222 223 224 225 //-----------------------------------------------------image_accessor_wrap 226 template<class PixFmt, class WrapX, class WrapY> class image_accessor_wrap 227 { 228 public: 229 typedef PixFmt pixfmt_type; 230 typedef typename pixfmt_type::color_type color_type; 231 typedef typename pixfmt_type::order_type order_type; 232 typedef typename pixfmt_type::value_type value_type; 233 enum pix_width_e { pix_width = pixfmt_type::pix_width }; 234 235 image_accessor_wrap() {} 236 image_accessor_wrap(const pixfmt_type& pixf) : 237 m_pixf(&pixf), 238 m_wrap_x(pixf.width()), 239 m_wrap_y(pixf.height()) 240 {} 241 242 void attach(const pixfmt_type& pixf) 243 { 244 m_pixf = &pixf; 245 } 246 247 AGG_INLINE const int8u* span(int x, int y, unsigned) 248 { 249 m_x = x; 250 m_row_ptr = m_pixf->row_ptr(m_wrap_y(y)); 251 return m_row_ptr + m_wrap_x(x) * pix_width; 252 } 253 254 AGG_INLINE const int8u* next_x() 255 { 256 int x = ++m_wrap_x; 257 return m_row_ptr + x * pix_width; 258 } 259 260 AGG_INLINE const int8u* next_y() 261 { 262 m_row_ptr = m_pixf->row_ptr(++m_wrap_y); 263 return m_row_ptr + m_wrap_x(m_x) * pix_width; 264 } 265 266 private: 267 const pixfmt_type* m_pixf; 268 const int8u* m_row_ptr; 269 int m_x; 270 WrapX m_wrap_x; 271 WrapY m_wrap_y; 272 }; 273 274 275 276 277 //--------------------------------------------------------wrap_mode_repeat 278 class wrap_mode_repeat 279 { 280 public: 281 wrap_mode_repeat() {} 282 wrap_mode_repeat(unsigned size) : 283 m_size(size), 284 m_add(size * (0x3FFFFFFF / size)), 285 m_value(0) 286 {} 287 288 AGG_INLINE unsigned operator() (int v) 289 { 290 return m_value = (unsigned(v) + m_add) % m_size; 291 } 292 293 AGG_INLINE unsigned operator++ () 294 { 295 ++m_value; 296 if(m_value >= m_size) m_value = 0; 297 return m_value; 298 } 299 private: 300 unsigned m_size; 301 unsigned m_add; 302 unsigned m_value; 303 }; 304 305 306 //---------------------------------------------------wrap_mode_repeat_pow2 307 class wrap_mode_repeat_pow2 308 { 309 public: 310 wrap_mode_repeat_pow2() {} 311 wrap_mode_repeat_pow2(unsigned size) : m_value(0) 312 { 313 m_mask = 1; 314 while(m_mask < size) m_mask = (m_mask << 1) | 1; 315 m_mask >>= 1; 316 } 317 AGG_INLINE unsigned operator() (int v) 318 { 319 return m_value = unsigned(v) & m_mask; 320 } 321 AGG_INLINE unsigned operator++ () 322 { 323 ++m_value; 324 if(m_value > m_mask) m_value = 0; 325 return m_value; 326 } 327 private: 328 unsigned m_mask; 329 unsigned m_value; 330 }; 331 332 333 //----------------------------------------------wrap_mode_repeat_auto_pow2 334 class wrap_mode_repeat_auto_pow2 335 { 336 public: 337 wrap_mode_repeat_auto_pow2() {} 338 wrap_mode_repeat_auto_pow2(unsigned size) : 339 m_size(size), 340 m_add(size * (0x3FFFFFFF / size)), 341 m_mask((m_size & (m_size-1)) ? 0 : m_size-1), 342 m_value(0) 343 {} 344 345 AGG_INLINE unsigned operator() (int v) 346 { 347 if(m_mask) return m_value = unsigned(v) & m_mask; 348 return m_value = (unsigned(v) + m_add) % m_size; 349 } 350 AGG_INLINE unsigned operator++ () 351 { 352 ++m_value; 353 if(m_value >= m_size) m_value = 0; 354 return m_value; 355 } 356 357 private: 358 unsigned m_size; 359 unsigned m_add; 360 unsigned m_mask; 361 unsigned m_value; 362 }; 363 364 365 //-------------------------------------------------------wrap_mode_reflect 366 class wrap_mode_reflect 367 { 368 public: 369 wrap_mode_reflect() {} 370 wrap_mode_reflect(unsigned size) : 371 m_size(size), 372 m_size2(size * 2), 373 m_add(m_size2 * (0x3FFFFFFF / m_size2)), 374 m_value(0) 375 {} 376 377 AGG_INLINE unsigned operator() (int v) 378 { 379 m_value = (unsigned(v) + m_add) % m_size2; 380 if(m_value >= m_size) return m_size2 - m_value - 1; 381 return m_value; 382 } 383 384 AGG_INLINE unsigned operator++ () 385 { 386 ++m_value; 387 if(m_value >= m_size2) m_value = 0; 388 if(m_value >= m_size) return m_size2 - m_value - 1; 389 return m_value; 390 } 391 private: 392 unsigned m_size; 393 unsigned m_size2; 394 unsigned m_add; 395 unsigned m_value; 396 }; 397 398 399 400 //--------------------------------------------------wrap_mode_reflect_pow2 401 class wrap_mode_reflect_pow2 402 { 403 public: 404 wrap_mode_reflect_pow2() {} 405 wrap_mode_reflect_pow2(unsigned size) : m_value(0) 406 { 407 m_mask = 1; 408 m_size = 1; 409 while(m_mask < size) 410 { 411 m_mask = (m_mask << 1) | 1; 412 m_size <<= 1; 413 } 414 } 415 AGG_INLINE unsigned operator() (int v) 416 { 417 m_value = unsigned(v) & m_mask; 418 if(m_value >= m_size) return m_mask - m_value; 419 return m_value; 420 } 421 AGG_INLINE unsigned operator++ () 422 { 423 ++m_value; 424 m_value &= m_mask; 425 if(m_value >= m_size) return m_mask - m_value; 426 return m_value; 427 } 428 private: 429 unsigned m_size; 430 unsigned m_mask; 431 unsigned m_value; 432 }; 433 434 435 436 //---------------------------------------------wrap_mode_reflect_auto_pow2 437 class wrap_mode_reflect_auto_pow2 438 { 439 public: 440 wrap_mode_reflect_auto_pow2() {} 441 wrap_mode_reflect_auto_pow2(unsigned size) : 442 m_size(size), 443 m_size2(size * 2), 444 m_add(m_size2 * (0x3FFFFFFF / m_size2)), 445 m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1), 446 m_value(0) 447 {} 448 449 AGG_INLINE unsigned operator() (int v) 450 { 451 m_value = m_mask ? unsigned(v) & m_mask : 452 (unsigned(v) + m_add) % m_size2; 453 if(m_value >= m_size) return m_size2 - m_value - 1; 454 return m_value; 455 } 456 AGG_INLINE unsigned operator++ () 457 { 458 ++m_value; 459 if(m_value >= m_size2) m_value = 0; 460 if(m_value >= m_size) return m_size2 - m_value - 1; 461 return m_value; 462 } 463 464 private: 465 unsigned m_size; 466 unsigned m_size2; 467 unsigned m_add; 468 unsigned m_mask; 469 unsigned m_value; 470 }; 471 472 473 } 474 475 476 #endif 477