1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #ifndef INCLUDED_BASEBMP_COMPOSITEITERATOR_HXX 25 #define INCLUDED_BASEBMP_COMPOSITEITERATOR_HXX 26 27 #include <sal/types.h> 28 #include <osl/diagnose.h> 29 30 #include <basebmp/nonstandarditerator.hxx> 31 #include <vigra/tuple.hxx> 32 #include <vigra/iteratortraits.hxx> 33 34 35 namespace basebmp 36 { 37 38 namespace detail 39 { 40 template< typename T1, typename T2 > class ArithmeticProxy 41 { 42 public: ArithmeticProxy(T1 & val1,T2 & val2)43 ArithmeticProxy(T1& val1, T2& val2) : 44 mpVal1( &val1 ), 45 mpVal2( &val2 ) 46 {} 47 operator ++()48 void operator++() { ++(*mpVal1); ++(*mpVal2); } operator ++(int)49 void operator++(int) { (*mpVal1)++; (*mpVal2)++; } operator --()50 void operator--() { --(*mpVal1); --(*mpVal2); } operator --(int)51 void operator--(int) { (*mpVal1)--; (*mpVal2)--; } operator +=(int d)52 void operator+=(int d) {*mpVal1+=d; *mpVal2+=d; } operator -=(int d)53 void operator-=(int d) {*mpVal1-=d; *mpVal2-=d; } 54 operator ==(ArithmeticProxy const & rhs) const55 bool operator==(ArithmeticProxy const & rhs) const 56 { return *mpVal1==*rhs.mpVal1 && *mpVal2==*rhs.mpVal2; } 57 operator !=(ArithmeticProxy const & rhs) const58 bool operator!=(ArithmeticProxy const & rhs) const 59 { return *mpVal1!=*rhs.mpVal1 || *mpVal2!=*rhs.mpVal2; } 60 operator <(ArithmeticProxy const & rhs) const61 bool operator<(ArithmeticProxy const & rhs) const 62 { return *mpVal1<*rhs.mpVal1 && *mpVal2<*rhs.mpVal2; } 63 operator <=(ArithmeticProxy const & rhs) const64 bool operator<=(ArithmeticProxy const & rhs) const 65 { return *mpVal1<=*rhs.mpVal1 && *mpVal2<=*rhs.mpVal2; } 66 operator >(ArithmeticProxy const & rhs) const67 bool operator>(ArithmeticProxy const & rhs) const 68 { return *mpVal1>*rhs.mpVal1 && *mpVal2>*rhs.mpVal2; } 69 operator >=(ArithmeticProxy const & rhs) const70 bool operator>=(ArithmeticProxy const & rhs) const 71 { return *mpVal1>=*rhs.mpVal1 && *mpVal2>=*rhs.mpVal2; } 72 operator -(ArithmeticProxy const & rhs) const73 int operator-(ArithmeticProxy const & rhs) const 74 { return *mpVal1 - *rhs.mpVal1; } 75 76 private: 77 T1* mpVal1; 78 T2* mpVal2; 79 }; 80 81 template< typename Iterator1, 82 typename Iterator2, 83 typename ValueType, 84 typename DifferenceType, 85 typename IteratorCategory, 86 class Derived > 87 class CompositeIteratorBase : public NonStandardIterator 88 { 89 public: 90 typedef Iterator1 iterator1_type; 91 typedef Iterator2 iterator2_type; 92 typedef ValueType value_type; 93 typedef DifferenceType difference_type; 94 typedef IteratorCategory iterator_category; 95 96 protected: 97 iterator1_type maIter1; 98 iterator2_type maIter2; 99 100 private: equal(CompositeIteratorBase const & rhs) const101 bool equal(CompositeIteratorBase const & rhs) const 102 { 103 return (maIter1 == rhs.maIter1) && (maIter2 == rhs.maIter2); 104 } 105 106 public: CompositeIteratorBase()107 CompositeIteratorBase() : 108 maIter1(), 109 maIter2() 110 {} 111 CompositeIteratorBase(const iterator1_type & rIter1,const iterator2_type & rIter2)112 CompositeIteratorBase( const iterator1_type& rIter1, const iterator2_type& rIter2 ) : 113 maIter1( rIter1 ), 114 maIter2( rIter2 ) 115 {} 116 operator ==(Derived const & rhs) const117 bool operator==(Derived const & rhs) const 118 { 119 return equal(rhs); 120 } 121 operator !=(Derived const & rhs) const122 bool operator!=(Derived const & rhs) const 123 { 124 return !equal(rhs); 125 } 126 operator -(Derived const & rhs) const127 difference_type operator-(Derived const & rhs) const 128 { 129 OSL_ASSERT( maIter1 - rhs.maIter1 == maIter2 - rhs.maIter2 ); 130 return maIter1 - rhs.maIter1; 131 } 132 operator +=(difference_type const & s)133 Derived & operator+=(difference_type const & s) 134 { 135 maIter1 += s; 136 maIter2 += s; 137 return static_cast<Derived&>(*this); 138 } 139 operator -=(difference_type const & s)140 Derived & operator-=(difference_type const & s) 141 { 142 maIter1 -= s; 143 maIter2 -= s; 144 return static_cast<Derived&>(*this); 145 } 146 operator +(difference_type const & s) const147 Derived operator+(difference_type const & s) const 148 { 149 Derived ret(static_cast<Derived const&>(*this)); 150 ret += s; 151 return ret; 152 } 153 operator -(difference_type const & s) const154 Derived operator-(difference_type const & s) const 155 { 156 Derived ret(static_cast<Derived const&>(*this)); 157 ret -= s; 158 return ret; 159 } 160 operator ++()161 Derived& operator++() 162 { 163 ++maIter1; 164 ++maIter2; 165 return static_cast<Derived&>(*this); 166 } 167 operator --()168 Derived& operator--() 169 { 170 --maIter1; 171 --maIter2; 172 return static_cast<Derived&>(*this); 173 } 174 operator ++(int)175 Derived operator++(int) 176 { 177 Derived ret(static_cast<Derived const&>(*this)); 178 ++maIter1; 179 ++maIter2; 180 return ret; 181 } 182 operator --(int)183 Derived operator--(int) 184 { 185 Derived ret(static_cast<Derived const&>(*this)); 186 --maIter1; 187 --maIter2; 188 return ret; 189 } 190 get() const191 value_type get() const 192 { 193 return value_type(maIter1.get(), 194 maIter2.get()); 195 } 196 get(difference_type const & d) const197 value_type get(difference_type const & d) const 198 { 199 return value_type(maIter1.get(d), 200 maIter2.get(d)); 201 } 202 set(value_type v) const203 void set( value_type v ) const 204 { 205 maIter1.set(v); 206 maIter2.set(v); 207 } 208 set(value_type v,difference_type const & d) const209 void set( value_type v, difference_type const & d ) const 210 { 211 maIter1.set(v,d); 212 maIter2.set(v,d); 213 } 214 first() const215 const iterator1_type& first() const { return maIter1; } first()216 iterator1_type& first() { return maIter1; } 217 second() const218 const iterator2_type& second() const { return maIter2; } second()219 iterator2_type& second() { return maIter2; } 220 }; 221 } 222 223 /** Provide the composition of two 1D image iterators 224 225 Use this template to compose two iterators into one (e.g. image 226 and mask). Operations are transitive, e.g. operator== only returns 227 true, if both wrapped iterator operator== have yielded true. 228 229 Note that both iterators must have compatible difference types. To 230 avoid funny effects, iterator ranges given by a CompositeIterator 231 should consist of wrapped iterators of similar range 232 */ 233 template< typename Iterator1, 234 typename Iterator2, 235 typename ValueType, 236 typename DifferenceType, 237 typename IteratorCategory > 238 class CompositeIterator1D : 239 public detail::CompositeIteratorBase< Iterator1, 240 Iterator2, 241 ValueType, 242 DifferenceType, 243 IteratorCategory, 244 CompositeIterator1D<Iterator1, 245 Iterator2, 246 ValueType, 247 DifferenceType, 248 IteratorCategory> > 249 { 250 typedef detail::CompositeIteratorBase< Iterator1, 251 Iterator2, 252 ValueType, 253 DifferenceType, 254 IteratorCategory, 255 CompositeIterator1D<Iterator1, 256 Iterator2, 257 ValueType, 258 DifferenceType, 259 IteratorCategory> > base_type; 260 public: CompositeIterator1D()261 CompositeIterator1D() : 262 base_type() 263 {} 264 CompositeIterator1D(const Iterator1 & rIter1,const Iterator2 & rIter2)265 CompositeIterator1D( const Iterator1& rIter1, 266 const Iterator2& rIter2 ) : 267 base_type( rIter1, rIter2 ) 268 {} 269 }; 270 271 /** Provide the composition of two 2D image iterators 272 273 Use this template to compose two iterators into one (e.g. image 274 and mask). Operations are transitive, e.g. operator== only returns 275 true, if both wrapped iterator operator== have yielded true. 276 277 Note that both iterators must have compatible difference types. To 278 avoid funny effects, iterator ranges given by a CompositeIterator 279 should consist of wrapped iterators of similar range 280 */ 281 template< typename Iterator1, typename Iterator2 > class CompositeIterator2D : 282 public detail::CompositeIteratorBase< Iterator1, 283 Iterator2, 284 std::pair< 285 typename vigra::IteratorTraits<Iterator1>::value_type, 286 typename vigra::IteratorTraits<Iterator2>::value_type >, 287 typename vigra::IteratorTraits<Iterator1>::difference_type, 288 typename vigra::IteratorTraits<Iterator1>::iterator_category, 289 CompositeIterator2D<Iterator1, Iterator2> > 290 { 291 typedef detail::CompositeIteratorBase< Iterator1, 292 Iterator2, 293 std::pair< 294 typename vigra::IteratorTraits<Iterator1>::value_type, 295 typename vigra::IteratorTraits<Iterator2>::value_type >, 296 typename vigra::IteratorTraits<Iterator1>::difference_type, 297 typename vigra::IteratorTraits<Iterator1>::iterator_category, 298 CompositeIterator2D<Iterator1, Iterator2> > base_type; 299 public: 300 typedef CompositeIterator1D< typename Iterator1::row_iterator, 301 typename Iterator2::row_iterator, 302 typename base_type::value_type, 303 int, 304 typename base_type::iterator_category > row_iterator; 305 typedef CompositeIterator1D< typename Iterator1::column_iterator, 306 typename Iterator2::column_iterator, 307 typename base_type::value_type, 308 int, 309 typename base_type::iterator_category > column_iterator; 310 311 typedef detail::ArithmeticProxy< typename Iterator1::MoveX, 312 typename Iterator2::MoveX > MoveX; 313 typedef detail::ArithmeticProxy< typename Iterator1::MoveY, 314 typename Iterator2::MoveY > MoveY; 315 316 MoveX x; 317 MoveY y; 318 CompositeIterator2D()319 CompositeIterator2D() : 320 base_type(), 321 x(this->maIter1.x,this->maIter2.x), 322 y(this->maIter1.y,this->maIter2.y) 323 {} 324 CompositeIterator2D(const Iterator1 & rIter1,const Iterator2 & rIter2)325 CompositeIterator2D( const Iterator1& rIter1, const Iterator2& rIter2 ) : 326 base_type( rIter1, rIter2 ), 327 x(this->maIter1.x,this->maIter2.x), 328 y(this->maIter1.y,this->maIter2.y) 329 {} 330 CompositeIterator2D(const CompositeIterator2D & rOld)331 CompositeIterator2D( const CompositeIterator2D& rOld ) : 332 base_type(rOld), 333 x(this->maIter1.x,this->maIter2.x), 334 y(this->maIter1.y,this->maIter2.y) 335 {} 336 operator =(const CompositeIterator2D & rNew)337 CompositeIterator2D& operator=( const CompositeIterator2D& rNew ) 338 { 339 this->maIter1 = rNew.maIter1; 340 this->maIter2 = rNew.maIter2; 341 342 x = MoveX(this->maIter1.x, 343 this->maIter2.x); 344 y = MoveY(this->maIter1.y, 345 this->maIter2.y); 346 } 347 rowIterator() const348 row_iterator rowIterator() const 349 { 350 return row_iterator(this->maIter1.rowIterator(), 351 this->maIter2.rowIterator()); 352 } 353 columnIterator() const354 column_iterator columnIterator() const 355 { 356 return column_iterator(this->maIter1.columnIterator(), 357 this->maIter2.columnIterator()); 358 } 359 }; 360 361 } // namespace basebmp 362 363 #endif /* INCLUDED_BASEBMP_COMPOSITEITERATOR_HXX */ 364