1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef INCLUDED_BASEBMP_COMPOSITEITERATOR_HXX
29 #define INCLUDED_BASEBMP_COMPOSITEITERATOR_HXX
30 
31 #include <sal/types.h>
32 #include <osl/diagnose.h>
33 
34 #include <basebmp/nonstandarditerator.hxx>
35 #include <vigra/tuple.hxx>
36 #include <vigra/iteratortraits.hxx>
37 
38 
39 namespace basebmp
40 {
41 
42 namespace detail
43 {
44     template< typename T1, typename T2 > class ArithmeticProxy
45     {
46     public:
47         ArithmeticProxy(T1& val1, T2& val2) :
48             mpVal1( &val1 ),
49             mpVal2( &val2 )
50         {}
51 
52         void operator++() { ++(*mpVal1); ++(*mpVal2); }
53         void operator++(int) { (*mpVal1)++; (*mpVal2)++; }
54         void operator--() { --(*mpVal1); --(*mpVal2); }
55         void operator--(int) { (*mpVal1)--; (*mpVal2)--; }
56         void operator+=(int d) {*mpVal1+=d; *mpVal2+=d; }
57         void operator-=(int d) {*mpVal1-=d; *mpVal2-=d; }
58 
59         bool operator==(ArithmeticProxy const & rhs) const
60         { return *mpVal1==*rhs.mpVal1 && *mpVal2==*rhs.mpVal2; }
61 
62         bool operator!=(ArithmeticProxy const & rhs) const
63         { return *mpVal1!=*rhs.mpVal1 || *mpVal2!=*rhs.mpVal2; }
64 
65         bool operator<(ArithmeticProxy const & rhs) const
66         { return *mpVal1<*rhs.mpVal1 && *mpVal2<*rhs.mpVal2; }
67 
68         bool operator<=(ArithmeticProxy const & rhs) const
69         { return *mpVal1<=*rhs.mpVal1 && *mpVal2<=*rhs.mpVal2; }
70 
71         bool operator>(ArithmeticProxy const & rhs) const
72         { return *mpVal1>*rhs.mpVal1 && *mpVal2>*rhs.mpVal2; }
73 
74         bool operator>=(ArithmeticProxy const & rhs) const
75         { return *mpVal1>=*rhs.mpVal1 && *mpVal2>=*rhs.mpVal2; }
76 
77         int operator-(ArithmeticProxy const & rhs) const
78         { return *mpVal1 - *rhs.mpVal1; }
79 
80     private:
81         T1* mpVal1;
82         T2* mpVal2;
83     };
84 
85     template< typename Iterator1,
86               typename Iterator2,
87               typename ValueType,
88               typename DifferenceType,
89               typename IteratorCategory,
90               class Derived >
91     class CompositeIteratorBase : public NonStandardIterator
92     {
93     public:
94         typedef Iterator1        iterator1_type;
95         typedef Iterator2        iterator2_type;
96         typedef ValueType        value_type;
97         typedef DifferenceType   difference_type;
98         typedef IteratorCategory iterator_category;
99 
100     protected:
101         iterator1_type maIter1;
102         iterator2_type maIter2;
103 
104     private:
105         bool equal(CompositeIteratorBase const & rhs) const
106         {
107             return (maIter1 == rhs.maIter1) && (maIter2 == rhs.maIter2);
108         }
109 
110     public:
111         CompositeIteratorBase() :
112             maIter1(),
113             maIter2()
114         {}
115 
116         CompositeIteratorBase( const iterator1_type& rIter1, const iterator2_type& rIter2 ) :
117             maIter1( rIter1 ),
118             maIter2( rIter2 )
119         {}
120 
121         bool operator==(Derived const & rhs) const
122         {
123             return equal(rhs);
124         }
125 
126         bool operator!=(Derived const & rhs) const
127         {
128             return !equal(rhs);
129         }
130 
131         difference_type operator-(Derived const & rhs) const
132         {
133             OSL_ASSERT( maIter1 - rhs.maIter1 == maIter2 - rhs.maIter2 );
134             return maIter1 - rhs.maIter1;
135         }
136 
137         Derived & operator+=(difference_type const & s)
138         {
139             maIter1 += s;
140             maIter2 += s;
141             return static_cast<Derived&>(*this);
142         }
143 
144         Derived & operator-=(difference_type const & s)
145         {
146             maIter1 -= s;
147             maIter2 -= s;
148             return static_cast<Derived&>(*this);
149         }
150 
151         Derived operator+(difference_type const & s) const
152         {
153             Derived ret(static_cast<Derived const&>(*this));
154             ret += s;
155             return ret;
156         }
157 
158         Derived operator-(difference_type const & s) const
159         {
160             Derived ret(static_cast<Derived const&>(*this));
161             ret -= s;
162             return ret;
163         }
164 
165         Derived& operator++()
166         {
167             ++maIter1;
168             ++maIter2;
169             return static_cast<Derived&>(*this);
170         }
171 
172         Derived& operator--()
173         {
174             --maIter1;
175             --maIter2;
176             return static_cast<Derived&>(*this);
177         }
178 
179         Derived operator++(int)
180         {
181             Derived ret(static_cast<Derived const&>(*this));
182             ++maIter1;
183             ++maIter2;
184             return ret;
185         }
186 
187         Derived operator--(int)
188         {
189             Derived ret(static_cast<Derived const&>(*this));
190             --maIter1;
191             --maIter2;
192             return ret;
193         }
194 
195         value_type get() const
196         {
197             return value_type(maIter1.get(),
198                               maIter2.get());
199         }
200 
201         value_type get(difference_type const & d) const
202         {
203             return value_type(maIter1.get(d),
204                               maIter2.get(d));
205         }
206 
207         void set( value_type v ) const
208         {
209             maIter1.set(v);
210             maIter2.set(v);
211         }
212 
213         void set( value_type v, difference_type const & d ) const
214         {
215             maIter1.set(v,d);
216             maIter2.set(v,d);
217         }
218 
219         const iterator1_type& first() const { return maIter1; }
220         iterator1_type& first() { return maIter1; }
221 
222         const iterator2_type& second() const { return maIter2; }
223         iterator2_type& second() { return maIter2; }
224     };
225 }
226 
227 /** Provide the composition of two 1D image iterators
228 
229     Use this template to compose two iterators into one (e.g. image
230     and mask). Operations are transitive, e.g. operator== only returns
231     true, if both wrapped iterator operator== have yielded true.
232 
233     Note that both iterators must have compatible difference types. To
234     avoid funny effects, iterator ranges given by a CompositeIterator
235     should consist of wrapped iterators of similar range
236  */
237 template< typename Iterator1,
238           typename Iterator2,
239           typename ValueType,
240           typename DifferenceType,
241           typename IteratorCategory >
242 class CompositeIterator1D :
243     public detail::CompositeIteratorBase< Iterator1,
244                                           Iterator2,
245                                           ValueType,
246                                           DifferenceType,
247                                           IteratorCategory,
248                                           CompositeIterator1D<Iterator1,
249                                                               Iterator2,
250                                                               ValueType,
251                                                               DifferenceType,
252                                                               IteratorCategory> >
253 {
254     typedef detail::CompositeIteratorBase< Iterator1,
255                                            Iterator2,
256                                            ValueType,
257                                            DifferenceType,
258                                            IteratorCategory,
259                                            CompositeIterator1D<Iterator1,
260                                                                Iterator2,
261                                                                ValueType,
262                                                                DifferenceType,
263                                                                IteratorCategory> > base_type;
264 public:
265     CompositeIterator1D() :
266         base_type()
267     {}
268 
269     CompositeIterator1D( const Iterator1& rIter1,
270                          const Iterator2& rIter2 ) :
271         base_type( rIter1, rIter2 )
272     {}
273 };
274 
275 /** Provide the composition of two 2D image iterators
276 
277     Use this template to compose two iterators into one (e.g. image
278     and mask). Operations are transitive, e.g. operator== only returns
279     true, if both wrapped iterator operator== have yielded true.
280 
281     Note that both iterators must have compatible difference types. To
282     avoid funny effects, iterator ranges given by a CompositeIterator
283     should consist of wrapped iterators of similar range
284  */
285 template< typename Iterator1, typename Iterator2 > class CompositeIterator2D :
286     public detail::CompositeIteratorBase< Iterator1,
287                                           Iterator2,
288                                           std::pair<
289                                                 typename vigra::IteratorTraits<Iterator1>::value_type,
290                                                 typename vigra::IteratorTraits<Iterator2>::value_type >,
291                                           typename vigra::IteratorTraits<Iterator1>::difference_type,
292                                           typename vigra::IteratorTraits<Iterator1>::iterator_category,
293                                           CompositeIterator2D<Iterator1, Iterator2> >
294 {
295     typedef detail::CompositeIteratorBase< Iterator1,
296                                            Iterator2,
297                                            std::pair<
298                                                 typename vigra::IteratorTraits<Iterator1>::value_type,
299                                                 typename vigra::IteratorTraits<Iterator2>::value_type >,
300                                            typename vigra::IteratorTraits<Iterator1>::difference_type,
301                                            typename vigra::IteratorTraits<Iterator1>::iterator_category,
302                                            CompositeIterator2D<Iterator1, Iterator2> > base_type;
303 public:
304     typedef CompositeIterator1D< typename Iterator1::row_iterator,
305                                  typename Iterator2::row_iterator,
306                                  typename base_type::value_type,
307                                  int,
308                                  typename base_type::iterator_category >  row_iterator;
309     typedef CompositeIterator1D< typename Iterator1::column_iterator,
310                                  typename Iterator2::column_iterator,
311                                  typename base_type::value_type,
312                                  int,
313                                  typename base_type::iterator_category >  column_iterator;
314 
315     typedef detail::ArithmeticProxy< typename Iterator1::MoveX,
316                                      typename Iterator2::MoveX >            MoveX;
317     typedef detail::ArithmeticProxy< typename Iterator1::MoveY,
318                                      typename Iterator2::MoveY >            MoveY;
319 
320     MoveX x;
321     MoveY y;
322 
323     CompositeIterator2D() :
324         base_type(),
325         x(this->maIter1.x,this->maIter2.x),
326         y(this->maIter1.y,this->maIter2.y)
327     {}
328 
329     CompositeIterator2D( const Iterator1& rIter1, const Iterator2& rIter2 ) :
330         base_type( rIter1, rIter2 ),
331         x(this->maIter1.x,this->maIter2.x),
332         y(this->maIter1.y,this->maIter2.y)
333     {}
334 
335     CompositeIterator2D( const CompositeIterator2D& rOld ) :
336         base_type(rOld),
337         x(this->maIter1.x,this->maIter2.x),
338         y(this->maIter1.y,this->maIter2.y)
339     {}
340 
341     CompositeIterator2D& operator=( const CompositeIterator2D& rNew )
342     {
343         this->maIter1 = rNew.maIter1;
344         this->maIter2 = rNew.maIter2;
345 
346         x = MoveX(this->maIter1.x,
347                   this->maIter2.x);
348         y = MoveY(this->maIter1.y,
349                   this->maIter2.y);
350     }
351 
352     row_iterator rowIterator() const
353     {
354         return row_iterator(this->maIter1.rowIterator(),
355                             this->maIter2.rowIterator());
356     }
357 
358     column_iterator columnIterator() const
359     {
360         return column_iterator(this->maIter1.columnIterator(),
361                                this->maIter2.columnIterator());
362     }
363 };
364 
365 } // namespace basebmp
366 
367 #endif /* INCLUDED_BASEBMP_COMPOSITEITERATOR_HXX */
368