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