blob: 4bbd00440ebd42d4fa9621d2821da0b8fd62ae6d [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#ifndef INCLUDED_BASEBMP_COMPOSITEITERATOR_HXX
#define INCLUDED_BASEBMP_COMPOSITEITERATOR_HXX
#include <sal/types.h>
#include <osl/diagnose.h>
#include <basebmp/nonstandarditerator.hxx>
#include <vigra/tuple.hxx>
#include <vigra/iteratortraits.hxx>
namespace basebmp
{
namespace detail
{
template< typename T1, typename T2 > class ArithmeticProxy
{
public:
ArithmeticProxy(T1& val1, T2& val2) :
mpVal1( &val1 ),
mpVal2( &val2 )
{}
void operator++() { ++(*mpVal1); ++(*mpVal2); }
void operator++(int) { (*mpVal1)++; (*mpVal2)++; }
void operator--() { --(*mpVal1); --(*mpVal2); }
void operator--(int) { (*mpVal1)--; (*mpVal2)--; }
void operator+=(int d) {*mpVal1+=d; *mpVal2+=d; }
void operator-=(int d) {*mpVal1-=d; *mpVal2-=d; }
bool operator==(ArithmeticProxy const & rhs) const
{ return *mpVal1==*rhs.mpVal1 && *mpVal2==*rhs.mpVal2; }
bool operator!=(ArithmeticProxy const & rhs) const
{ return *mpVal1!=*rhs.mpVal1 || *mpVal2!=*rhs.mpVal2; }
bool operator<(ArithmeticProxy const & rhs) const
{ return *mpVal1<*rhs.mpVal1 && *mpVal2<*rhs.mpVal2; }
bool operator<=(ArithmeticProxy const & rhs) const
{ return *mpVal1<=*rhs.mpVal1 && *mpVal2<=*rhs.mpVal2; }
bool operator>(ArithmeticProxy const & rhs) const
{ return *mpVal1>*rhs.mpVal1 && *mpVal2>*rhs.mpVal2; }
bool operator>=(ArithmeticProxy const & rhs) const
{ return *mpVal1>=*rhs.mpVal1 && *mpVal2>=*rhs.mpVal2; }
int operator-(ArithmeticProxy const & rhs) const
{ return *mpVal1 - *rhs.mpVal1; }
private:
T1* mpVal1;
T2* mpVal2;
};
template< typename Iterator1,
typename Iterator2,
typename ValueType,
typename DifferenceType,
typename IteratorCategory,
class Derived >
class CompositeIteratorBase : public NonStandardIterator
{
public:
typedef Iterator1 iterator1_type;
typedef Iterator2 iterator2_type;
typedef ValueType value_type;
typedef DifferenceType difference_type;
typedef IteratorCategory iterator_category;
protected:
iterator1_type maIter1;
iterator2_type maIter2;
private:
bool equal(CompositeIteratorBase const & rhs) const
{
return (maIter1 == rhs.maIter1) && (maIter2 == rhs.maIter2);
}
public:
CompositeIteratorBase() :
maIter1(),
maIter2()
{}
CompositeIteratorBase( const iterator1_type& rIter1, const iterator2_type& rIter2 ) :
maIter1( rIter1 ),
maIter2( rIter2 )
{}
bool operator==(Derived const & rhs) const
{
return equal(rhs);
}
bool operator!=(Derived const & rhs) const
{
return !equal(rhs);
}
difference_type operator-(Derived const & rhs) const
{
OSL_ASSERT( maIter1 - rhs.maIter1 == maIter2 - rhs.maIter2 );
return maIter1 - rhs.maIter1;
}
Derived & operator+=(difference_type const & s)
{
maIter1 += s;
maIter2 += s;
return static_cast<Derived&>(*this);
}
Derived & operator-=(difference_type const & s)
{
maIter1 -= s;
maIter2 -= s;
return static_cast<Derived&>(*this);
}
Derived operator+(difference_type const & s) const
{
Derived ret(static_cast<Derived const&>(*this));
ret += s;
return ret;
}
Derived operator-(difference_type const & s) const
{
Derived ret(static_cast<Derived const&>(*this));
ret -= s;
return ret;
}
Derived& operator++()
{
++maIter1;
++maIter2;
return static_cast<Derived&>(*this);
}
Derived& operator--()
{
--maIter1;
--maIter2;
return static_cast<Derived&>(*this);
}
Derived operator++(int)
{
Derived ret(static_cast<Derived const&>(*this));
++maIter1;
++maIter2;
return ret;
}
Derived operator--(int)
{
Derived ret(static_cast<Derived const&>(*this));
--maIter1;
--maIter2;
return ret;
}
value_type get() const
{
return value_type(maIter1.get(),
maIter2.get());
}
value_type get(difference_type const & d) const
{
return value_type(maIter1.get(d),
maIter2.get(d));
}
void set( value_type v ) const
{
maIter1.set(v);
maIter2.set(v);
}
void set( value_type v, difference_type const & d ) const
{
maIter1.set(v,d);
maIter2.set(v,d);
}
const iterator1_type& first() const { return maIter1; }
iterator1_type& first() { return maIter1; }
const iterator2_type& second() const { return maIter2; }
iterator2_type& second() { return maIter2; }
};
}
/** Provide the composition of two 1D image iterators
Use this template to compose two iterators into one (e.g. image
and mask). Operations are transitive, e.g. operator== only returns
true, if both wrapped iterator operator== have yielded true.
Note that both iterators must have compatible difference types. To
avoid funny effects, iterator ranges given by a CompositeIterator
should consist of wrapped iterators of similar range
*/
template< typename Iterator1,
typename Iterator2,
typename ValueType,
typename DifferenceType,
typename IteratorCategory >
class CompositeIterator1D :
public detail::CompositeIteratorBase< Iterator1,
Iterator2,
ValueType,
DifferenceType,
IteratorCategory,
CompositeIterator1D<Iterator1,
Iterator2,
ValueType,
DifferenceType,
IteratorCategory> >
{
typedef detail::CompositeIteratorBase< Iterator1,
Iterator2,
ValueType,
DifferenceType,
IteratorCategory,
CompositeIterator1D<Iterator1,
Iterator2,
ValueType,
DifferenceType,
IteratorCategory> > base_type;
public:
CompositeIterator1D() :
base_type()
{}
CompositeIterator1D( const Iterator1& rIter1,
const Iterator2& rIter2 ) :
base_type( rIter1, rIter2 )
{}
};
/** Provide the composition of two 2D image iterators
Use this template to compose two iterators into one (e.g. image
and mask). Operations are transitive, e.g. operator== only returns
true, if both wrapped iterator operator== have yielded true.
Note that both iterators must have compatible difference types. To
avoid funny effects, iterator ranges given by a CompositeIterator
should consist of wrapped iterators of similar range
*/
template< typename Iterator1, typename Iterator2 > class CompositeIterator2D :
public detail::CompositeIteratorBase< Iterator1,
Iterator2,
std::pair<
typename vigra::IteratorTraits<Iterator1>::value_type,
typename vigra::IteratorTraits<Iterator2>::value_type >,
typename vigra::IteratorTraits<Iterator1>::difference_type,
typename vigra::IteratorTraits<Iterator1>::iterator_category,
CompositeIterator2D<Iterator1, Iterator2> >
{
typedef detail::CompositeIteratorBase< Iterator1,
Iterator2,
std::pair<
typename vigra::IteratorTraits<Iterator1>::value_type,
typename vigra::IteratorTraits<Iterator2>::value_type >,
typename vigra::IteratorTraits<Iterator1>::difference_type,
typename vigra::IteratorTraits<Iterator1>::iterator_category,
CompositeIterator2D<Iterator1, Iterator2> > base_type;
public:
typedef CompositeIterator1D< typename Iterator1::row_iterator,
typename Iterator2::row_iterator,
typename base_type::value_type,
int,
typename base_type::iterator_category > row_iterator;
typedef CompositeIterator1D< typename Iterator1::column_iterator,
typename Iterator2::column_iterator,
typename base_type::value_type,
int,
typename base_type::iterator_category > column_iterator;
typedef detail::ArithmeticProxy< typename Iterator1::MoveX,
typename Iterator2::MoveX > MoveX;
typedef detail::ArithmeticProxy< typename Iterator1::MoveY,
typename Iterator2::MoveY > MoveY;
MoveX x;
MoveY y;
CompositeIterator2D() :
base_type(),
x(this->maIter1.x,this->maIter2.x),
y(this->maIter1.y,this->maIter2.y)
{}
CompositeIterator2D( const Iterator1& rIter1, const Iterator2& rIter2 ) :
base_type( rIter1, rIter2 ),
x(this->maIter1.x,this->maIter2.x),
y(this->maIter1.y,this->maIter2.y)
{}
CompositeIterator2D( const CompositeIterator2D& rOld ) :
base_type(rOld),
x(this->maIter1.x,this->maIter2.x),
y(this->maIter1.y,this->maIter2.y)
{}
CompositeIterator2D& operator=( const CompositeIterator2D& rNew )
{
this->maIter1 = rNew.maIter1;
this->maIter2 = rNew.maIter2;
x = MoveX(this->maIter1.x,
this->maIter2.x);
y = MoveY(this->maIter1.y,
this->maIter2.y);
}
row_iterator rowIterator() const
{
return row_iterator(this->maIter1.rowIterator(),
this->maIter2.rowIterator());
}
column_iterator columnIterator() const
{
return column_iterator(this->maIter1.columnIterator(),
this->maIter2.columnIterator());
}
};
} // namespace basebmp
#endif /* INCLUDED_BASEBMP_COMPOSITEITERATOR_HXX */