xref: /aoo4110/main/basebmp/test/bmpdemo.cxx (revision b1cdbd2c)
1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski #ifndef  _USE_MATH_DEFINES
25*b1cdbd2cSJim Jagielski #define  _USE_MATH_DEFINES  // needed by Visual C++ for math constants
26*b1cdbd2cSJim Jagielski #endif
27*b1cdbd2cSJim Jagielski #include <math.h>
28*b1cdbd2cSJim Jagielski 
29*b1cdbd2cSJim Jagielski #include <comphelper/processfactory.hxx>
30*b1cdbd2cSJim Jagielski #include <comphelper/regpathhelper.hxx>
31*b1cdbd2cSJim Jagielski #include <cppuhelper/servicefactory.hxx>
32*b1cdbd2cSJim Jagielski #include <cppuhelper/bootstrap.hxx>
33*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/XInitialization.hpp>
35*b1cdbd2cSJim Jagielski #include <com/sun/star/registry/XSimpleRegistry.hpp>
36*b1cdbd2cSJim Jagielski 
37*b1cdbd2cSJim Jagielski #include <ucbhelper/contentbroker.hxx>
38*b1cdbd2cSJim Jagielski #include <ucbhelper/configurationkeys.hxx>
39*b1cdbd2cSJim Jagielski 
40*b1cdbd2cSJim Jagielski #include <vcl/window.hxx>
41*b1cdbd2cSJim Jagielski #include <vcl/svapp.hxx>
42*b1cdbd2cSJim Jagielski #include <vcl/msgbox.hxx>
43*b1cdbd2cSJim Jagielski #include <vcl/unowrap.hxx>
44*b1cdbd2cSJim Jagielski #include <vcl/bitmap.hxx>
45*b1cdbd2cSJim Jagielski #include <vcl/bmpacc.hxx>
46*b1cdbd2cSJim Jagielski 
47*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dlinegeometry.hxx>
48*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolypolygon.hxx>
49*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolypolygontools.hxx>
50*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolypolygonrasterconverter.hxx>
51*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolygontools.hxx>
52*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolygon.hxx>
53*b1cdbd2cSJim Jagielski #include <basegfx/numeric/ftools.hxx>
54*b1cdbd2cSJim Jagielski #include <basegfx/range/b2irange.hxx>
55*b1cdbd2cSJim Jagielski #include <basegfx/vector/b2isize.hxx>
56*b1cdbd2cSJim Jagielski #include <basegfx/point/b2ipoint.hxx>
57*b1cdbd2cSJim Jagielski 
58*b1cdbd2cSJim Jagielski #include <basebmp/color.hxx>
59*b1cdbd2cSJim Jagielski #include <basebmp/scanlineformats.hxx>
60*b1cdbd2cSJim Jagielski #include <basebmp/bitmapdevice.hxx>
61*b1cdbd2cSJim Jagielski #include <basebmp/debug.hxx>
62*b1cdbd2cSJim Jagielski 
63*b1cdbd2cSJim Jagielski #include <rtl/bootstrap.hxx>
64*b1cdbd2cSJim Jagielski 
65*b1cdbd2cSJim Jagielski #include <vigra/metaprogramming.hxx>
66*b1cdbd2cSJim Jagielski #include <vigra/static_assert.hxx>
67*b1cdbd2cSJim Jagielski #include <vigra/basicimageview.hxx>
68*b1cdbd2cSJim Jagielski 
69*b1cdbd2cSJim Jagielski #include <boost/static_assert.hpp>
70*b1cdbd2cSJim Jagielski #include <algorithm>
71*b1cdbd2cSJim Jagielski #include <iostream>
72*b1cdbd2cSJim Jagielski #include <fstream>
73*b1cdbd2cSJim Jagielski 
74*b1cdbd2cSJim Jagielski using namespace ::com::sun::star;
75*b1cdbd2cSJim Jagielski 
76*b1cdbd2cSJim Jagielski 
77*b1cdbd2cSJim Jagielski namespace
78*b1cdbd2cSJim Jagielski {
79*b1cdbd2cSJim Jagielski 
80*b1cdbd2cSJim Jagielski /// template meta function: add const qualifier, if given 2nd type has it
81*b1cdbd2cSJim Jagielski template<typename A, typename B> struct clone_const
82*b1cdbd2cSJim Jagielski {
83*b1cdbd2cSJim Jagielski     typedef B type;
84*b1cdbd2cSJim Jagielski };
85*b1cdbd2cSJim Jagielski template<typename A, typename B> struct clone_const<const A,B>
86*b1cdbd2cSJim Jagielski {
87*b1cdbd2cSJim Jagielski     typedef const B type;
88*b1cdbd2cSJim Jagielski };
89*b1cdbd2cSJim Jagielski 
90*b1cdbd2cSJim Jagielski template< class DestIterator, class DestAccessor > class Renderer :
91*b1cdbd2cSJim Jagielski         public basegfx::B2DPolyPolygonRasterConverter
92*b1cdbd2cSJim Jagielski {
93*b1cdbd2cSJim Jagielski private:
94*b1cdbd2cSJim Jagielski     typename DestIterator::value_type fillColor_;
95*b1cdbd2cSJim Jagielski     typename DestIterator::value_type clearColor_;
96*b1cdbd2cSJim Jagielski     DestIterator                      begin_;
97*b1cdbd2cSJim Jagielski     DestAccessor                      accessor_;
98*b1cdbd2cSJim Jagielski 
99*b1cdbd2cSJim Jagielski public:
Renderer(const basegfx::B2DPolyPolygon & rPolyPolyRaster,typename DestIterator::value_type fillColor,typename DestIterator::value_type clearColor,DestIterator begin,DestIterator end,DestAccessor accessor)100*b1cdbd2cSJim Jagielski     Renderer(const basegfx::B2DPolyPolygon&     rPolyPolyRaster,
101*b1cdbd2cSJim Jagielski              typename DestIterator::value_type  fillColor,
102*b1cdbd2cSJim Jagielski              typename DestIterator::value_type  clearColor,
103*b1cdbd2cSJim Jagielski              DestIterator                       begin,
104*b1cdbd2cSJim Jagielski              DestIterator                       end,
105*b1cdbd2cSJim Jagielski              DestAccessor                       accessor ) :
106*b1cdbd2cSJim Jagielski         B2DPolyPolygonRasterConverter(rPolyPolyRaster,
107*b1cdbd2cSJim Jagielski                                       basegfx::B2DRange(0,0,
108*b1cdbd2cSJim Jagielski                                                         end.x - end.x,
109*b1cdbd2cSJim Jagielski                                                         begin.y - begin.y )),
110*b1cdbd2cSJim Jagielski         fillColor_( fillColor ),
111*b1cdbd2cSJim Jagielski         clearColor_( clearColor ),
112*b1cdbd2cSJim Jagielski         begin_( begin ),
113*b1cdbd2cSJim Jagielski         accessor_( accessor )
114*b1cdbd2cSJim Jagielski     {
115*b1cdbd2cSJim Jagielski     }
116*b1cdbd2cSJim Jagielski 
span(const double & rfXLeft,const double & rfXRight,sal_Int32 nY,bool bOn)117*b1cdbd2cSJim Jagielski     virtual void span(const double& rfXLeft,
118*b1cdbd2cSJim Jagielski                       const double& rfXRight,
119*b1cdbd2cSJim Jagielski                       sal_Int32 	nY,
120*b1cdbd2cSJim Jagielski                       bool 			bOn )
121*b1cdbd2cSJim Jagielski     {
122*b1cdbd2cSJim Jagielski         DestIterator currIter( begin_ + vigra::Diff2D(0,nY) );
123*b1cdbd2cSJim Jagielski         typename DestIterator::row_iterator rowIter( currIter.rowIterator() +
124*b1cdbd2cSJim Jagielski                                                      basegfx::fround(rfXLeft) );
125*b1cdbd2cSJim Jagielski         typename DestIterator::row_iterator rowEnd( currIter.rowIterator() +
126*b1cdbd2cSJim Jagielski                                                     basegfx::fround(rfXRight) );
127*b1cdbd2cSJim Jagielski         if( bOn )
128*b1cdbd2cSJim Jagielski             while( rowIter != rowEnd )
129*b1cdbd2cSJim Jagielski             {
130*b1cdbd2cSJim Jagielski                 accessor_.set(fillColor_, rowIter);
131*b1cdbd2cSJim Jagielski                 ++rowIter;
132*b1cdbd2cSJim Jagielski             }
133*b1cdbd2cSJim Jagielski         else
134*b1cdbd2cSJim Jagielski             while( rowIter != rowEnd )
135*b1cdbd2cSJim Jagielski             {
136*b1cdbd2cSJim Jagielski                 accessor_.set(accessor_(rowIter)*clearColor_, rowIter);
137*b1cdbd2cSJim Jagielski                 ++rowIter;
138*b1cdbd2cSJim Jagielski             }
139*b1cdbd2cSJim Jagielski     }
140*b1cdbd2cSJim Jagielski };
141*b1cdbd2cSJim Jagielski 
142*b1cdbd2cSJim Jagielski template< class DestIterator, class DestAccessor >
makeRenderer(const basegfx::B2DPolyPolygon & rPolyPolyRaster,typename DestIterator::value_type fillColor,typename DestIterator::value_type clearColor,vigra::triple<DestIterator,DestIterator,DestAccessor> dest)143*b1cdbd2cSJim Jagielski     std::auto_ptr< Renderer< DestIterator, DestAccessor > > makeRenderer(
144*b1cdbd2cSJim Jagielski         const basegfx::B2DPolyPolygon&                          rPolyPolyRaster,
145*b1cdbd2cSJim Jagielski         typename DestIterator::value_type                       fillColor,
146*b1cdbd2cSJim Jagielski         typename DestIterator::value_type                       clearColor,
147*b1cdbd2cSJim Jagielski         vigra::triple<DestIterator, DestIterator, DestAccessor> dest )
148*b1cdbd2cSJim Jagielski {
149*b1cdbd2cSJim Jagielski     return std::auto_ptr< Renderer< DestIterator, DestAccessor > >(
150*b1cdbd2cSJim Jagielski         new Renderer< DestIterator, DestAccessor >(rPolyPolyRaster,
151*b1cdbd2cSJim Jagielski                                                    fillColor,
152*b1cdbd2cSJim Jagielski                                                    clearColor,
153*b1cdbd2cSJim Jagielski                                                    dest.first,
154*b1cdbd2cSJim Jagielski                                                    dest.second,
155*b1cdbd2cSJim Jagielski                                                    dest.third));
156*b1cdbd2cSJim Jagielski }
157*b1cdbd2cSJim Jagielski 
158*b1cdbd2cSJim Jagielski 
159*b1cdbd2cSJim Jagielski // changed semantics re. DirectionSelector<StridedArrayTag>: stride
160*b1cdbd2cSJim Jagielski // now counts in <em>raw</em> bytes!
161*b1cdbd2cSJim Jagielski template< typename T > class StridedArrayIterator
162*b1cdbd2cSJim Jagielski {
163*b1cdbd2cSJim Jagielski public:
164*b1cdbd2cSJim Jagielski     typedef typename clone_const<T, unsigned char>::type  internal_type;
165*b1cdbd2cSJim Jagielski 
StridedArrayIterator(int stride,T * ptr=0)166*b1cdbd2cSJim Jagielski     StridedArrayIterator(int stride, T* ptr = 0) :
167*b1cdbd2cSJim Jagielski         stride_(stride),
168*b1cdbd2cSJim Jagielski         current_(reinterpret_cast<internal_type*>(ptr))
169*b1cdbd2cSJim Jagielski     {}
170*b1cdbd2cSJim Jagielski 
171*b1cdbd2cSJim Jagielski     /// Copy from other StridedArrayIterator, plus given offset
StridedArrayIterator(StridedArrayIterator const & rSrc,int offset)172*b1cdbd2cSJim Jagielski     StridedArrayIterator( StridedArrayIterator const& rSrc,
173*b1cdbd2cSJim Jagielski                           int                         offset ) :
174*b1cdbd2cSJim Jagielski         stride_(rSrc.stride_),
175*b1cdbd2cSJim Jagielski         current_(reinterpret_cast<internal_type*>(
176*b1cdbd2cSJim Jagielski                      reinterpret_cast<T*>(rSrc.current_)+offset))
177*b1cdbd2cSJim Jagielski     {}
178*b1cdbd2cSJim Jagielski 
operator ++()179*b1cdbd2cSJim Jagielski     void operator++() {current_ += stride_; }
operator ++(int)180*b1cdbd2cSJim Jagielski     void operator++(int) {current_ += stride_; }
operator --()181*b1cdbd2cSJim Jagielski     void operator--() {current_ -= stride_; }
operator --(int)182*b1cdbd2cSJim Jagielski     void operator--(int) {current_ -= stride_; }
operator +=(int dy)183*b1cdbd2cSJim Jagielski     void operator+=(int dy) {current_ += dy*stride_; }
operator -=(int dy)184*b1cdbd2cSJim Jagielski     void operator-=(int dy) {current_ -= dy*stride_; }
185*b1cdbd2cSJim Jagielski 
operator ==(StridedArrayIterator const & rhs) const186*b1cdbd2cSJim Jagielski     bool operator==(StridedArrayIterator const & rhs) const
187*b1cdbd2cSJim Jagielski     { return (current_ == rhs.current_); }
188*b1cdbd2cSJim Jagielski 
operator !=(StridedArrayIterator const & rhs) const189*b1cdbd2cSJim Jagielski     bool operator!=(StridedArrayIterator const & rhs) const
190*b1cdbd2cSJim Jagielski     { return (current_ != rhs.current_); }
191*b1cdbd2cSJim Jagielski 
operator <(StridedArrayIterator const & rhs) const192*b1cdbd2cSJim Jagielski     bool operator<(StridedArrayIterator const & rhs) const
193*b1cdbd2cSJim Jagielski     { return (current_ < rhs.current_); }
194*b1cdbd2cSJim Jagielski 
operator <=(StridedArrayIterator const & rhs) const195*b1cdbd2cSJim Jagielski     bool operator<=(StridedArrayIterator const & rhs) const
196*b1cdbd2cSJim Jagielski     { return (current_ <= rhs.current_); }
197*b1cdbd2cSJim Jagielski 
operator >(StridedArrayIterator const & rhs) const198*b1cdbd2cSJim Jagielski     bool operator>(StridedArrayIterator const & rhs) const
199*b1cdbd2cSJim Jagielski     { return (current_ > rhs.current_); }
200*b1cdbd2cSJim Jagielski 
operator >=(StridedArrayIterator const & rhs) const201*b1cdbd2cSJim Jagielski     bool operator>=(StridedArrayIterator const & rhs) const
202*b1cdbd2cSJim Jagielski     { return (current_ >= rhs.current_); }
203*b1cdbd2cSJim Jagielski 
operator -(StridedArrayIterator const & rhs) const204*b1cdbd2cSJim Jagielski     int operator-(StridedArrayIterator const & rhs) const
205*b1cdbd2cSJim Jagielski     { return (current_ - rhs.current_) / stride_; }
206*b1cdbd2cSJim Jagielski 
operator ()() const207*b1cdbd2cSJim Jagielski     T* operator()() const
208*b1cdbd2cSJim Jagielski     { return reinterpret_cast<T*>(current_); }
209*b1cdbd2cSJim Jagielski 
operator ()(int d) const210*b1cdbd2cSJim Jagielski     T* operator()(int d) const
211*b1cdbd2cSJim Jagielski     { return reinterpret_cast<T*>(current_ + d*stride_); }
212*b1cdbd2cSJim Jagielski 
213*b1cdbd2cSJim Jagielski     int            stride_;
214*b1cdbd2cSJim Jagielski     internal_type* current_;
215*b1cdbd2cSJim Jagielski };
216*b1cdbd2cSJim Jagielski 
217*b1cdbd2cSJim Jagielski /// template meta function: remove const qualifier from plain type
218*b1cdbd2cSJim Jagielski template <typename T> struct remove_const
219*b1cdbd2cSJim Jagielski {
220*b1cdbd2cSJim Jagielski     typedef T type;
221*b1cdbd2cSJim Jagielski };
222*b1cdbd2cSJim Jagielski template <typename T> struct remove_const<const T>
223*b1cdbd2cSJim Jagielski {
224*b1cdbd2cSJim Jagielski     typedef T type;
225*b1cdbd2cSJim Jagielski };
226*b1cdbd2cSJim Jagielski 
227*b1cdbd2cSJim Jagielski /// returns true, if given number is strictly less than 0
is_negative(T x)228*b1cdbd2cSJim Jagielski template< typename T > inline bool is_negative( T x )
229*b1cdbd2cSJim Jagielski {
230*b1cdbd2cSJim Jagielski     return x < 0;
231*b1cdbd2cSJim Jagielski }
232*b1cdbd2cSJim Jagielski 
233*b1cdbd2cSJim Jagielski /// Overload for ints (branch-free)
is_negative(int x)234*b1cdbd2cSJim Jagielski inline bool is_negative( int x )
235*b1cdbd2cSJim Jagielski {
236*b1cdbd2cSJim Jagielski     // force logic shift (result for signed shift right is undefined)
237*b1cdbd2cSJim Jagielski     return static_cast<unsigned int>(x) >> (sizeof(int)*8-1);
238*b1cdbd2cSJim Jagielski }
239*b1cdbd2cSJim Jagielski 
240*b1cdbd2cSJim Jagielski /// Get bitmask for data at given intra-word position, for given bit depth
get_mask(difference_type d)241*b1cdbd2cSJim Jagielski template< typename data_type, int bits_per_pixel, bool MsbFirst, typename difference_type > inline data_type get_mask( difference_type d )
242*b1cdbd2cSJim Jagielski {
243*b1cdbd2cSJim Jagielski     BOOST_STATIC_ASSERT(bits_per_pixel > 0);
244*b1cdbd2cSJim Jagielski     BOOST_STATIC_ASSERT(sizeof(data_type)*8 % bits_per_pixel == 0);
245*b1cdbd2cSJim Jagielski     BOOST_STATIC_ASSERT(sizeof(data_type)*8 / bits_per_pixel > 1);
246*b1cdbd2cSJim Jagielski     BOOST_STATIC_ASSERT(vigra::TypeTraits<data_type>::isPOD::asBool);
247*b1cdbd2cSJim Jagielski 
248*b1cdbd2cSJim Jagielski     const unsigned int nIntraWordPositions( sizeof(data_type)*8 / bits_per_pixel );
249*b1cdbd2cSJim Jagielski 
250*b1cdbd2cSJim Jagielski     //      create bits_per_pixel 1s      shift to intra-word position
251*b1cdbd2cSJim Jagielski     return ((~(~0 << bits_per_pixel)) << bits_per_pixel*(MsbFirst ?
252*b1cdbd2cSJim Jagielski                                                          (nIntraWordPositions-1 - (d % nIntraWordPositions)) :
253*b1cdbd2cSJim Jagielski                                                          (d % nIntraWordPositions)));
254*b1cdbd2cSJim Jagielski }
255*b1cdbd2cSJim Jagielski 
get_shift(difference_type remainder)256*b1cdbd2cSJim Jagielski template< int num_intraword_positions, int bits_per_pixel, bool MsbFirst, typename difference_type > inline difference_type get_shift( difference_type remainder )
257*b1cdbd2cSJim Jagielski {
258*b1cdbd2cSJim Jagielski     return bits_per_pixel*(MsbFirst ?
259*b1cdbd2cSJim Jagielski                            (num_intraword_positions - 1 - remainder) :
260*b1cdbd2cSJim Jagielski                            remainder);
261*b1cdbd2cSJim Jagielski }
262*b1cdbd2cSJim Jagielski 
263*b1cdbd2cSJim Jagielski template< typename Datatype,
264*b1cdbd2cSJim Jagielski           typename Valuetype,
265*b1cdbd2cSJim Jagielski           int      bits_per_pixel,
266*b1cdbd2cSJim Jagielski           bool     MsbFirst > class PackedPixelColumnIterator
267*b1cdbd2cSJim Jagielski {
268*b1cdbd2cSJim Jagielski public:
269*b1cdbd2cSJim Jagielski     // no reference, no index_reference type here
270*b1cdbd2cSJim Jagielski     typedef Datatype                                    data_type;
271*b1cdbd2cSJim Jagielski     typedef Valuetype                                   value_type;
272*b1cdbd2cSJim Jagielski     typedef int                                         difference_type;
273*b1cdbd2cSJim Jagielski     typedef image_traverser_tag                         iterator_category;
274*b1cdbd2cSJim Jagielski 
275*b1cdbd2cSJim Jagielski     typedef typename remove_const<data_type>::type      mask_type;
276*b1cdbd2cSJim Jagielski     typedef data_type*                                  pointer;
277*b1cdbd2cSJim Jagielski     typedef StridedArrayIterator< data_type >           MoveY;
278*b1cdbd2cSJim Jagielski 
279*b1cdbd2cSJim Jagielski     enum {
280*b1cdbd2cSJim Jagielski         /** The number of pixel within a single data_type value
281*b1cdbd2cSJim Jagielski          */
282*b1cdbd2cSJim Jagielski         num_intraword_positions=sizeof(data_type)*8/bits_per_pixel,
283*b1cdbd2cSJim Jagielski         /** Bit mask for one pixel (least significant bits)
284*b1cdbd2cSJim Jagielski          */
285*b1cdbd2cSJim Jagielski         bit_mask=~(~0 << bits_per_pixel)
286*b1cdbd2cSJim Jagielski     };
287*b1cdbd2cSJim Jagielski 
288*b1cdbd2cSJim Jagielski private:
289*b1cdbd2cSJim Jagielski     MoveY           y;
290*b1cdbd2cSJim Jagielski     mask_type       mask_;
291*b1cdbd2cSJim Jagielski     difference_type shift_;
292*b1cdbd2cSJim Jagielski 
inc()293*b1cdbd2cSJim Jagielski     void inc()
294*b1cdbd2cSJim Jagielski     {
295*b1cdbd2cSJim Jagielski         ++y;
296*b1cdbd2cSJim Jagielski     }
297*b1cdbd2cSJim Jagielski 
dec()298*b1cdbd2cSJim Jagielski     void dec()
299*b1cdbd2cSJim Jagielski     {
300*b1cdbd2cSJim Jagielski         --y;
301*b1cdbd2cSJim Jagielski     }
302*b1cdbd2cSJim Jagielski 
equal(PackedPixelColumnIterator const & rhs) const303*b1cdbd2cSJim Jagielski     bool equal( PackedPixelColumnIterator const & rhs ) const
304*b1cdbd2cSJim Jagielski     {
305*b1cdbd2cSJim Jagielski         return rhs.y == y;
306*b1cdbd2cSJim Jagielski     }
307*b1cdbd2cSJim Jagielski 
less(PackedPixelColumnIterator const & rhs) const308*b1cdbd2cSJim Jagielski     bool less( PackedPixelColumnIterator const & rhs ) const
309*b1cdbd2cSJim Jagielski     {
310*b1cdbd2cSJim Jagielski         return y < rhs.y;
311*b1cdbd2cSJim Jagielski     }
312*b1cdbd2cSJim Jagielski 
313*b1cdbd2cSJim Jagielski public:
PackedPixelColumnIterator()314*b1cdbd2cSJim Jagielski     PackedPixelColumnIterator() :
315*b1cdbd2cSJim Jagielski         y(0),
316*b1cdbd2cSJim Jagielski         mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ),
317*b1cdbd2cSJim Jagielski         shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst, difference_type>(0) )
318*b1cdbd2cSJim Jagielski     {}
319*b1cdbd2cSJim Jagielski 
PackedPixelColumnIterator(const MoveY & base,difference_type remainder)320*b1cdbd2cSJim Jagielski     PackedPixelColumnIterator( const MoveY& base, difference_type remainder ) :
321*b1cdbd2cSJim Jagielski         y(base),
322*b1cdbd2cSJim Jagielski         mask_( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) ),
323*b1cdbd2cSJim Jagielski         shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder) )
324*b1cdbd2cSJim Jagielski     {}
325*b1cdbd2cSJim Jagielski 
operator +=(difference_type d)326*b1cdbd2cSJim Jagielski     PackedPixelColumnIterator& operator+=( difference_type d )
327*b1cdbd2cSJim Jagielski     {
328*b1cdbd2cSJim Jagielski         y += d;
329*b1cdbd2cSJim Jagielski         return *this;
330*b1cdbd2cSJim Jagielski     }
331*b1cdbd2cSJim Jagielski 
operator -=(difference_type d)332*b1cdbd2cSJim Jagielski     PackedPixelColumnIterator& operator-=( difference_type d )
333*b1cdbd2cSJim Jagielski     {
334*b1cdbd2cSJim Jagielski         y -= d;
335*b1cdbd2cSJim Jagielski         return *this;
336*b1cdbd2cSJim Jagielski     }
337*b1cdbd2cSJim Jagielski 
operator +(difference_type d)338*b1cdbd2cSJim Jagielski     PackedPixelColumnIterator operator+( difference_type d )
339*b1cdbd2cSJim Jagielski     {
340*b1cdbd2cSJim Jagielski         PackedPixelColumnIterator res(*this);
341*b1cdbd2cSJim Jagielski         res += d;
342*b1cdbd2cSJim Jagielski         return res;
343*b1cdbd2cSJim Jagielski     }
344*b1cdbd2cSJim Jagielski 
operator -(difference_type d)345*b1cdbd2cSJim Jagielski     PackedPixelColumnIterator operator-( difference_type d )
346*b1cdbd2cSJim Jagielski     {
347*b1cdbd2cSJim Jagielski         PackedPixelColumnIterator res(*this);
348*b1cdbd2cSJim Jagielski         res -= d;
349*b1cdbd2cSJim Jagielski         return res;
350*b1cdbd2cSJim Jagielski     }
351*b1cdbd2cSJim Jagielski 
operator ++()352*b1cdbd2cSJim Jagielski     PackedPixelColumnIterator& operator++()
353*b1cdbd2cSJim Jagielski     {
354*b1cdbd2cSJim Jagielski         inc();
355*b1cdbd2cSJim Jagielski         return *this;
356*b1cdbd2cSJim Jagielski     }
357*b1cdbd2cSJim Jagielski 
operator --()358*b1cdbd2cSJim Jagielski     PackedPixelColumnIterator& operator--()
359*b1cdbd2cSJim Jagielski     {
360*b1cdbd2cSJim Jagielski         dec();
361*b1cdbd2cSJim Jagielski         return *this;
362*b1cdbd2cSJim Jagielski     }
363*b1cdbd2cSJim Jagielski 
operator ++(int)364*b1cdbd2cSJim Jagielski     PackedPixelColumnIterator operator++(int)
365*b1cdbd2cSJim Jagielski     {
366*b1cdbd2cSJim Jagielski         PackedPixelColumnIterator res(*this);
367*b1cdbd2cSJim Jagielski         res.inc();
368*b1cdbd2cSJim Jagielski         return res;
369*b1cdbd2cSJim Jagielski     }
370*b1cdbd2cSJim Jagielski 
operator --(int)371*b1cdbd2cSJim Jagielski     PackedPixelColumnIterator operator--(int)
372*b1cdbd2cSJim Jagielski     {
373*b1cdbd2cSJim Jagielski         PackedPixelColumnIterator res(*this);
374*b1cdbd2cSJim Jagielski         res.dec();
375*b1cdbd2cSJim Jagielski         return res;
376*b1cdbd2cSJim Jagielski     }
377*b1cdbd2cSJim Jagielski 
operator ==(PackedPixelColumnIterator const & rhs) const378*b1cdbd2cSJim Jagielski     bool operator==(PackedPixelColumnIterator const & rhs) const
379*b1cdbd2cSJim Jagielski     {
380*b1cdbd2cSJim Jagielski         return equal( rhs );
381*b1cdbd2cSJim Jagielski     }
382*b1cdbd2cSJim Jagielski 
operator !=(PackedPixelColumnIterator const & rhs) const383*b1cdbd2cSJim Jagielski     bool operator!=(PackedPixelColumnIterator const & rhs) const
384*b1cdbd2cSJim Jagielski     {
385*b1cdbd2cSJim Jagielski         return !equal( rhs );
386*b1cdbd2cSJim Jagielski     }
387*b1cdbd2cSJim Jagielski 
operator <(PackedPixelColumnIterator const & rhs) const388*b1cdbd2cSJim Jagielski     bool operator<(PackedPixelColumnIterator const & rhs) const
389*b1cdbd2cSJim Jagielski     {
390*b1cdbd2cSJim Jagielski         return less(rhs);
391*b1cdbd2cSJim Jagielski     }
392*b1cdbd2cSJim Jagielski 
operator <=(PackedPixelColumnIterator const & rhs) const393*b1cdbd2cSJim Jagielski     bool operator<=(PackedPixelColumnIterator const & rhs) const
394*b1cdbd2cSJim Jagielski     {
395*b1cdbd2cSJim Jagielski         return !less(rhs);
396*b1cdbd2cSJim Jagielski     }
397*b1cdbd2cSJim Jagielski 
operator >(PackedPixelColumnIterator const & rhs) const398*b1cdbd2cSJim Jagielski     bool operator>(PackedPixelColumnIterator const & rhs) const
399*b1cdbd2cSJim Jagielski     {
400*b1cdbd2cSJim Jagielski         return rhs.less(*this);
401*b1cdbd2cSJim Jagielski     }
402*b1cdbd2cSJim Jagielski 
operator >=(PackedPixelColumnIterator const & rhs) const403*b1cdbd2cSJim Jagielski     bool operator>=(PackedPixelColumnIterator const & rhs) const
404*b1cdbd2cSJim Jagielski     {
405*b1cdbd2cSJim Jagielski         return !rhs.less(*this);
406*b1cdbd2cSJim Jagielski     }
407*b1cdbd2cSJim Jagielski 
operator -(PackedPixelColumnIterator const & rhs) const408*b1cdbd2cSJim Jagielski     difference_type operator-(PackedPixelColumnIterator const & rhs) const
409*b1cdbd2cSJim Jagielski     {
410*b1cdbd2cSJim Jagielski         return y - rhs.y;
411*b1cdbd2cSJim Jagielski     }
412*b1cdbd2cSJim Jagielski 
get() const413*b1cdbd2cSJim Jagielski     value_type get() const
414*b1cdbd2cSJim Jagielski     {
415*b1cdbd2cSJim Jagielski         // TODO(Q3): use traits to get unsigned type for data_type (if
416*b1cdbd2cSJim Jagielski         // not already)
417*b1cdbd2cSJim Jagielski         return static_cast<unsigned int>(*y() & mask_) >> shift_;
418*b1cdbd2cSJim Jagielski     }
419*b1cdbd2cSJim Jagielski 
get(difference_type d) const420*b1cdbd2cSJim Jagielski     value_type get(difference_type d) const
421*b1cdbd2cSJim Jagielski     {
422*b1cdbd2cSJim Jagielski         // TODO(Q3): use traits to get unsigned type for data_type (if
423*b1cdbd2cSJim Jagielski         // not already)
424*b1cdbd2cSJim Jagielski         return static_cast<unsigned int>(*y(d) & mask_) >> shift_;
425*b1cdbd2cSJim Jagielski     }
426*b1cdbd2cSJim Jagielski 
set(value_type v) const427*b1cdbd2cSJim Jagielski     void set( value_type v ) const
428*b1cdbd2cSJim Jagielski     {
429*b1cdbd2cSJim Jagielski         const value_type pixel_value( (v << shift_) & mask_ );
430*b1cdbd2cSJim Jagielski         *y() = (*y() & ~mask_) | pixel_value;
431*b1cdbd2cSJim Jagielski     }
432*b1cdbd2cSJim Jagielski 
set(value_type v,difference_type d) const433*b1cdbd2cSJim Jagielski     void set( value_type v, difference_type d ) const
434*b1cdbd2cSJim Jagielski     {
435*b1cdbd2cSJim Jagielski         const value_type pixel_value( (v << shift_) & mask_ );
436*b1cdbd2cSJim Jagielski         *y(d) = (*y(d) & ~mask_) | pixel_value;
437*b1cdbd2cSJim Jagielski     }
438*b1cdbd2cSJim Jagielski };
439*b1cdbd2cSJim Jagielski 
440*b1cdbd2cSJim Jagielski template< typename Datatype,
441*b1cdbd2cSJim Jagielski           typename Valuetype,
442*b1cdbd2cSJim Jagielski           int      bits_per_pixel,
443*b1cdbd2cSJim Jagielski           bool     MsbFirst > class PackedPixelRowIterator
444*b1cdbd2cSJim Jagielski {
445*b1cdbd2cSJim Jagielski public:
446*b1cdbd2cSJim Jagielski     // no reference, no index_reference type here
447*b1cdbd2cSJim Jagielski     typedef Datatype                                    data_type;
448*b1cdbd2cSJim Jagielski     typedef Valuetype                                   value_type;
449*b1cdbd2cSJim Jagielski     typedef int                                         difference_type;
450*b1cdbd2cSJim Jagielski     typedef image_traverser_tag                         iterator_category;
451*b1cdbd2cSJim Jagielski 
452*b1cdbd2cSJim Jagielski     typedef typename remove_const<data_type>::type      mask_type;
453*b1cdbd2cSJim Jagielski     typedef data_type*                                  pointer;
454*b1cdbd2cSJim Jagielski 
455*b1cdbd2cSJim Jagielski     enum {
456*b1cdbd2cSJim Jagielski         /** The number of pixel within a single data_type value
457*b1cdbd2cSJim Jagielski          */
458*b1cdbd2cSJim Jagielski         num_intraword_positions=sizeof(data_type)*8/bits_per_pixel,
459*b1cdbd2cSJim Jagielski         /** Bit mask for one pixel (least significant bits)
460*b1cdbd2cSJim Jagielski          */
461*b1cdbd2cSJim Jagielski         bit_mask=~(~0 << bits_per_pixel)
462*b1cdbd2cSJim Jagielski     };
463*b1cdbd2cSJim Jagielski 
464*b1cdbd2cSJim Jagielski private:
465*b1cdbd2cSJim Jagielski     pointer         data_;
466*b1cdbd2cSJim Jagielski     mask_type       mask_;
467*b1cdbd2cSJim Jagielski     difference_type remainder_;
468*b1cdbd2cSJim Jagielski 
update_mask()469*b1cdbd2cSJim Jagielski     void update_mask()
470*b1cdbd2cSJim Jagielski     {
471*b1cdbd2cSJim Jagielski         mask_ = get_mask<data_type, bits_per_pixel, MsbFirst>(remainder_);
472*b1cdbd2cSJim Jagielski     }
473*b1cdbd2cSJim Jagielski 
inc()474*b1cdbd2cSJim Jagielski     void inc()
475*b1cdbd2cSJim Jagielski     {
476*b1cdbd2cSJim Jagielski         const difference_type newValue( remainder_ + 1 );
477*b1cdbd2cSJim Jagielski         const difference_type data_offset( newValue / num_intraword_positions );
478*b1cdbd2cSJim Jagielski 
479*b1cdbd2cSJim Jagielski         data_ += data_offset;
480*b1cdbd2cSJim Jagielski         remainder_ = newValue % num_intraword_positions;
481*b1cdbd2cSJim Jagielski 
482*b1cdbd2cSJim Jagielski         const mask_type shifted_mask(
483*b1cdbd2cSJim Jagielski             MsbFirst ?
484*b1cdbd2cSJim Jagielski             // TODO(Q3): use traits to get unsigned type for data_type
485*b1cdbd2cSJim Jagielski             // (if not already)
486*b1cdbd2cSJim Jagielski             static_cast<unsigned int>(mask_) >> bits_per_pixel :
487*b1cdbd2cSJim Jagielski             mask_ << bits_per_pixel );
488*b1cdbd2cSJim Jagielski 
489*b1cdbd2cSJim Jagielski         // data_offset is 0 for shifted mask, and 1 for wrapped-around mask
490*b1cdbd2cSJim Jagielski         mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ?
491*b1cdbd2cSJim Jagielski                                                             bit_mask << bits_per_pixel*(num_intraword_positions-1) :
492*b1cdbd2cSJim Jagielski                                                             bit_mask);
493*b1cdbd2cSJim Jagielski     }
494*b1cdbd2cSJim Jagielski 
dec()495*b1cdbd2cSJim Jagielski     void dec()
496*b1cdbd2cSJim Jagielski     {
497*b1cdbd2cSJim Jagielski         const difference_type newValue( remainder_ - 1 );
498*b1cdbd2cSJim Jagielski         const bool            isNegative( is_negative(newValue) );
499*b1cdbd2cSJim Jagielski         const difference_type newRemainder( newValue % num_intraword_positions );
500*b1cdbd2cSJim Jagielski 
501*b1cdbd2cSJim Jagielski         // calc  data_ += newValue / num_intraword_positions;
502*b1cdbd2cSJim Jagielski         //       remainder_ = newRemainder;
503*b1cdbd2cSJim Jagielski         // for newValue >= 0, and
504*b1cdbd2cSJim Jagielski         //       data_ += newValue / num_intraword_positions - 1;
505*b1cdbd2cSJim Jagielski         //       remainder_ = num_intraword_positions - newRemainder;
506*b1cdbd2cSJim Jagielski         // (to force remainder_ to be positive).
507*b1cdbd2cSJim Jagielski         // This is branch-free, if is_negative() is branch-free
508*b1cdbd2cSJim Jagielski         const difference_type data_offset( newValue / num_intraword_positions - isNegative );
509*b1cdbd2cSJim Jagielski         data_     += data_offset;
510*b1cdbd2cSJim Jagielski         remainder_ = newRemainder + isNegative*num_intraword_positions;
511*b1cdbd2cSJim Jagielski 
512*b1cdbd2cSJim Jagielski         const mask_type shifted_mask(
513*b1cdbd2cSJim Jagielski             MsbFirst ?
514*b1cdbd2cSJim Jagielski             mask_ << bits_per_pixel :
515*b1cdbd2cSJim Jagielski             // TODO(Q3): use traits to get unsigned type for data_type
516*b1cdbd2cSJim Jagielski             // (if not already)
517*b1cdbd2cSJim Jagielski             static_cast<unsigned int>(mask_) >> bits_per_pixel );
518*b1cdbd2cSJim Jagielski 
519*b1cdbd2cSJim Jagielski         // data_offset is 0 for shifted mask, and 1 for wrapped-around mask
520*b1cdbd2cSJim Jagielski         mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ?
521*b1cdbd2cSJim Jagielski                                                             bit_mask :
522*b1cdbd2cSJim Jagielski                                                             bit_mask << bits_per_pixel*(num_intraword_positions-1));
523*b1cdbd2cSJim Jagielski     }
524*b1cdbd2cSJim Jagielski 
equal(PackedPixelRowIterator const & rhs) const525*b1cdbd2cSJim Jagielski     bool equal( PackedPixelRowIterator const & rhs ) const
526*b1cdbd2cSJim Jagielski     {
527*b1cdbd2cSJim Jagielski         return rhs.data_ == data_ && rhs.remainder_ == remainder_;
528*b1cdbd2cSJim Jagielski     }
529*b1cdbd2cSJim Jagielski 
less(PackedPixelRowIterator const & rhs) const530*b1cdbd2cSJim Jagielski     bool less( PackedPixelRowIterator const & rhs ) const
531*b1cdbd2cSJim Jagielski     {
532*b1cdbd2cSJim Jagielski         return data_ == rhs.data_ ?
533*b1cdbd2cSJim Jagielski             (remainder_ < rhs.remainder_) :
534*b1cdbd2cSJim Jagielski             (data_ < rhs.data_);
535*b1cdbd2cSJim Jagielski     }
536*b1cdbd2cSJim Jagielski 
537*b1cdbd2cSJim Jagielski public:
PackedPixelRowIterator()538*b1cdbd2cSJim Jagielski     PackedPixelRowIterator() :
539*b1cdbd2cSJim Jagielski         data_(0),
540*b1cdbd2cSJim Jagielski         mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ),
541*b1cdbd2cSJim Jagielski         remainder_(0)
542*b1cdbd2cSJim Jagielski     {}
543*b1cdbd2cSJim Jagielski 
PackedPixelRowIterator(pointer base)544*b1cdbd2cSJim Jagielski     explicit PackedPixelRowIterator( pointer base ) :
545*b1cdbd2cSJim Jagielski         data_(base),
546*b1cdbd2cSJim Jagielski         mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ),
547*b1cdbd2cSJim Jagielski         remainder_(0)
548*b1cdbd2cSJim Jagielski     {}
549*b1cdbd2cSJim Jagielski 
operator +=(difference_type d)550*b1cdbd2cSJim Jagielski     PackedPixelRowIterator& operator+=( difference_type d )
551*b1cdbd2cSJim Jagielski     {
552*b1cdbd2cSJim Jagielski         const difference_type newValue( remainder_ + d );
553*b1cdbd2cSJim Jagielski 
554*b1cdbd2cSJim Jagielski         data_ += newValue / num_intraword_positions;
555*b1cdbd2cSJim Jagielski         remainder_ = newValue % num_intraword_positions;
556*b1cdbd2cSJim Jagielski         update_mask();
557*b1cdbd2cSJim Jagielski 
558*b1cdbd2cSJim Jagielski         return *this;
559*b1cdbd2cSJim Jagielski     }
560*b1cdbd2cSJim Jagielski 
operator -=(difference_type d)561*b1cdbd2cSJim Jagielski     PackedPixelRowIterator& operator-=( difference_type d )
562*b1cdbd2cSJim Jagielski     {
563*b1cdbd2cSJim Jagielski         const difference_type newValue( remainder_ - d );
564*b1cdbd2cSJim Jagielski         const bool            isNegative( is_negative(newValue) );
565*b1cdbd2cSJim Jagielski         const difference_type newRemainder( newValue % num_intraword_positions );
566*b1cdbd2cSJim Jagielski 
567*b1cdbd2cSJim Jagielski         // calc  data_ += newValue / num_intraword_positions;
568*b1cdbd2cSJim Jagielski         //       remainder_ = newRemainder;
569*b1cdbd2cSJim Jagielski         // for newValue >= 0, and
570*b1cdbd2cSJim Jagielski         //       data_ += newValue / num_intraword_positions - 1;
571*b1cdbd2cSJim Jagielski         //       remainder_ = num_intraword_positions - newRemainder;
572*b1cdbd2cSJim Jagielski         // (to force remainder_ to be positive).
573*b1cdbd2cSJim Jagielski         // This is branch-free, if is_negative() is branch-free
574*b1cdbd2cSJim Jagielski         data_     += newValue / num_intraword_positions - isNegative;
575*b1cdbd2cSJim Jagielski         remainder_ = newRemainder + isNegative*(num_intraword_positions - 2*newRemainder);
576*b1cdbd2cSJim Jagielski         update_mask();
577*b1cdbd2cSJim Jagielski 
578*b1cdbd2cSJim Jagielski         return *this;
579*b1cdbd2cSJim Jagielski     }
580*b1cdbd2cSJim Jagielski 
operator +(difference_type d)581*b1cdbd2cSJim Jagielski     PackedPixelRowIterator operator+( difference_type d )
582*b1cdbd2cSJim Jagielski     {
583*b1cdbd2cSJim Jagielski         PackedPixelRowIterator res(*this);
584*b1cdbd2cSJim Jagielski         res += d;
585*b1cdbd2cSJim Jagielski         return res;
586*b1cdbd2cSJim Jagielski     }
587*b1cdbd2cSJim Jagielski 
operator -(difference_type d)588*b1cdbd2cSJim Jagielski     PackedPixelRowIterator operator-( difference_type d )
589*b1cdbd2cSJim Jagielski     {
590*b1cdbd2cSJim Jagielski         PackedPixelRowIterator res(*this);
591*b1cdbd2cSJim Jagielski         res -= d;
592*b1cdbd2cSJim Jagielski         return res;
593*b1cdbd2cSJim Jagielski     }
594*b1cdbd2cSJim Jagielski 
operator ++()595*b1cdbd2cSJim Jagielski     PackedPixelRowIterator& operator++()
596*b1cdbd2cSJim Jagielski     {
597*b1cdbd2cSJim Jagielski         inc();
598*b1cdbd2cSJim Jagielski         return *this;
599*b1cdbd2cSJim Jagielski     }
600*b1cdbd2cSJim Jagielski 
operator --()601*b1cdbd2cSJim Jagielski     PackedPixelRowIterator& operator--()
602*b1cdbd2cSJim Jagielski     {
603*b1cdbd2cSJim Jagielski         dec();
604*b1cdbd2cSJim Jagielski         return *this;
605*b1cdbd2cSJim Jagielski     }
606*b1cdbd2cSJim Jagielski 
operator ++(int)607*b1cdbd2cSJim Jagielski     PackedPixelRowIterator operator++(int)
608*b1cdbd2cSJim Jagielski     {
609*b1cdbd2cSJim Jagielski         PackedPixelRowIterator res(*this);
610*b1cdbd2cSJim Jagielski         res.inc();
611*b1cdbd2cSJim Jagielski         return res;
612*b1cdbd2cSJim Jagielski     }
613*b1cdbd2cSJim Jagielski 
operator --(int)614*b1cdbd2cSJim Jagielski     PackedPixelRowIterator operator--(int)
615*b1cdbd2cSJim Jagielski     {
616*b1cdbd2cSJim Jagielski         PackedPixelRowIterator res(*this);
617*b1cdbd2cSJim Jagielski         res.dec();
618*b1cdbd2cSJim Jagielski         return res;
619*b1cdbd2cSJim Jagielski     }
620*b1cdbd2cSJim Jagielski 
operator ==(PackedPixelRowIterator const & rhs) const621*b1cdbd2cSJim Jagielski     bool operator==(PackedPixelRowIterator const & rhs) const
622*b1cdbd2cSJim Jagielski     {
623*b1cdbd2cSJim Jagielski         return equal( rhs );
624*b1cdbd2cSJim Jagielski     }
625*b1cdbd2cSJim Jagielski 
operator !=(PackedPixelRowIterator const & rhs) const626*b1cdbd2cSJim Jagielski     bool operator!=(PackedPixelRowIterator const & rhs) const
627*b1cdbd2cSJim Jagielski     {
628*b1cdbd2cSJim Jagielski         return !equal( rhs );
629*b1cdbd2cSJim Jagielski     }
630*b1cdbd2cSJim Jagielski 
operator <(PackedPixelRowIterator const & rhs) const631*b1cdbd2cSJim Jagielski     bool operator<(PackedPixelRowIterator const & rhs) const
632*b1cdbd2cSJim Jagielski     {
633*b1cdbd2cSJim Jagielski         return less(rhs);
634*b1cdbd2cSJim Jagielski     }
635*b1cdbd2cSJim Jagielski 
operator <=(PackedPixelRowIterator const & rhs) const636*b1cdbd2cSJim Jagielski     bool operator<=(PackedPixelRowIterator const & rhs) const
637*b1cdbd2cSJim Jagielski     {
638*b1cdbd2cSJim Jagielski         return !less(rhs);
639*b1cdbd2cSJim Jagielski     }
640*b1cdbd2cSJim Jagielski 
operator >(PackedPixelRowIterator const & rhs) const641*b1cdbd2cSJim Jagielski     bool operator>(PackedPixelRowIterator const & rhs) const
642*b1cdbd2cSJim Jagielski     {
643*b1cdbd2cSJim Jagielski         return rhs.less(*this);
644*b1cdbd2cSJim Jagielski     }
645*b1cdbd2cSJim Jagielski 
operator >=(PackedPixelRowIterator const & rhs) const646*b1cdbd2cSJim Jagielski     bool operator>=(PackedPixelRowIterator const & rhs) const
647*b1cdbd2cSJim Jagielski     {
648*b1cdbd2cSJim Jagielski         return !rhs.less(*this);
649*b1cdbd2cSJim Jagielski     }
650*b1cdbd2cSJim Jagielski 
operator -(PackedPixelRowIterator const & rhs) const651*b1cdbd2cSJim Jagielski     difference_type operator-(PackedPixelRowIterator const & rhs) const
652*b1cdbd2cSJim Jagielski     {
653*b1cdbd2cSJim Jagielski         return (data_ - rhs.data_)*num_intraword_positions + (remainder_ - rhs.remainder_);
654*b1cdbd2cSJim Jagielski     }
655*b1cdbd2cSJim Jagielski 
get() const656*b1cdbd2cSJim Jagielski     value_type get() const
657*b1cdbd2cSJim Jagielski     {
658*b1cdbd2cSJim Jagielski         // TODO(Q3): use traits to get unsigned type for data_type (if
659*b1cdbd2cSJim Jagielski         // not already)
660*b1cdbd2cSJim Jagielski         return static_cast<unsigned int>(*data_ & mask_) >>
661*b1cdbd2cSJim Jagielski             get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder_);
662*b1cdbd2cSJim Jagielski     }
663*b1cdbd2cSJim Jagielski 
get(difference_type d) const664*b1cdbd2cSJim Jagielski     value_type get(difference_type d) const
665*b1cdbd2cSJim Jagielski     {
666*b1cdbd2cSJim Jagielski         PackedPixelRowIterator tmp(*this);
667*b1cdbd2cSJim Jagielski         tmp += d;
668*b1cdbd2cSJim Jagielski         return tmp.get();
669*b1cdbd2cSJim Jagielski     }
670*b1cdbd2cSJim Jagielski 
set(value_type v) const671*b1cdbd2cSJim Jagielski     void set( value_type v ) const
672*b1cdbd2cSJim Jagielski     {
673*b1cdbd2cSJim Jagielski         const value_type pixel_value(
674*b1cdbd2cSJim Jagielski             (v <<
675*b1cdbd2cSJim Jagielski              get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder_))
676*b1cdbd2cSJim Jagielski             & mask_ );
677*b1cdbd2cSJim Jagielski         *data_ = (*data_ & ~mask_) | pixel_value;
678*b1cdbd2cSJim Jagielski     }
679*b1cdbd2cSJim Jagielski 
set(value_type v,difference_type d) const680*b1cdbd2cSJim Jagielski     void set( value_type v, difference_type d ) const
681*b1cdbd2cSJim Jagielski     {
682*b1cdbd2cSJim Jagielski         PackedPixelRowIterator tmp(*this);
683*b1cdbd2cSJim Jagielski         tmp += d;
684*b1cdbd2cSJim Jagielski         tmp.set(v);
685*b1cdbd2cSJim Jagielski     }
686*b1cdbd2cSJim Jagielski };
687*b1cdbd2cSJim Jagielski 
688*b1cdbd2cSJim Jagielski template< typename Datatype,
689*b1cdbd2cSJim Jagielski           typename Valuetype,
690*b1cdbd2cSJim Jagielski           int      bits_per_pixel,
691*b1cdbd2cSJim Jagielski           bool     MsbFirst > class PackedPixelIterator
692*b1cdbd2cSJim Jagielski {
693*b1cdbd2cSJim Jagielski public:
694*b1cdbd2cSJim Jagielski     // no reference, no index_reference type here
695*b1cdbd2cSJim Jagielski     typedef Datatype                                    data_type;
696*b1cdbd2cSJim Jagielski     typedef Valuetype                                   value_type;
697*b1cdbd2cSJim Jagielski     typedef vigra::Diff2D                               difference_type;
698*b1cdbd2cSJim Jagielski     typedef image_traverser_tag                         iterator_category;
699*b1cdbd2cSJim Jagielski     typedef PackedPixelRowIterator<data_type,
700*b1cdbd2cSJim Jagielski                                    value_type,
701*b1cdbd2cSJim Jagielski                                    bits_per_pixel,
702*b1cdbd2cSJim Jagielski                                    MsbFirst>            row_iterator;
703*b1cdbd2cSJim Jagielski     typedef PackedPixelColumnIterator<data_type,
704*b1cdbd2cSJim Jagielski                                       value_type,
705*b1cdbd2cSJim Jagielski                                       bits_per_pixel,
706*b1cdbd2cSJim Jagielski                                       MsbFirst>         column_iterator;
707*b1cdbd2cSJim Jagielski 
708*b1cdbd2cSJim Jagielski     typedef data_type*                                  pointer;
709*b1cdbd2cSJim Jagielski     typedef int                                         MoveX;
710*b1cdbd2cSJim Jagielski     typedef StridedArrayIterator< data_type >           MoveY;
711*b1cdbd2cSJim Jagielski 
712*b1cdbd2cSJim Jagielski     enum {
713*b1cdbd2cSJim Jagielski         /** The number of pixel within a single data_type value
714*b1cdbd2cSJim Jagielski          */
715*b1cdbd2cSJim Jagielski         num_intraword_positions=sizeof(data_type)*8/bits_per_pixel,
716*b1cdbd2cSJim Jagielski         /** Bit mask for one pixel (least significant bits)
717*b1cdbd2cSJim Jagielski          */
718*b1cdbd2cSJim Jagielski         bit_mask=~(~0 << bits_per_pixel)
719*b1cdbd2cSJim Jagielski     };
720*b1cdbd2cSJim Jagielski 
721*b1cdbd2cSJim Jagielski     // TODO(F2): direction of iteration (ImageIterator can be made to
722*b1cdbd2cSJim Jagielski     // run backwards)
723*b1cdbd2cSJim Jagielski 
724*b1cdbd2cSJim Jagielski private:
current() const725*b1cdbd2cSJim Jagielski     pointer current() const
726*b1cdbd2cSJim Jagielski     {
727*b1cdbd2cSJim Jagielski         return y() + (x / num_intraword_positions);
728*b1cdbd2cSJim Jagielski     }
729*b1cdbd2cSJim Jagielski 
current(int dx,int dy) const730*b1cdbd2cSJim Jagielski     pointer current(int dx, int dy) const
731*b1cdbd2cSJim Jagielski     {
732*b1cdbd2cSJim Jagielski         return y(dy) + ((x+dx)/num_intraword_positions);
733*b1cdbd2cSJim Jagielski     }
734*b1cdbd2cSJim Jagielski 
equal(PackedPixelIterator const & rhs) const735*b1cdbd2cSJim Jagielski     bool equal(PackedPixelIterator const & rhs) const
736*b1cdbd2cSJim Jagielski     {
737*b1cdbd2cSJim Jagielski         return (x == rhs.x) && (y == rhs.y);
738*b1cdbd2cSJim Jagielski     }
739*b1cdbd2cSJim Jagielski 
740*b1cdbd2cSJim Jagielski public:
PackedPixelIterator()741*b1cdbd2cSJim Jagielski     PackedPixelIterator() :
742*b1cdbd2cSJim Jagielski         x(0),
743*b1cdbd2cSJim Jagielski         y(0)
744*b1cdbd2cSJim Jagielski     {}
745*b1cdbd2cSJim Jagielski 
PackedPixelIterator(pointer base,int ystride)746*b1cdbd2cSJim Jagielski     PackedPixelIterator(pointer base, int ystride) :
747*b1cdbd2cSJim Jagielski         x(0),
748*b1cdbd2cSJim Jagielski         y(ystride,base)
749*b1cdbd2cSJim Jagielski     {}
750*b1cdbd2cSJim Jagielski 
operator ==(PackedPixelIterator const & rhs) const751*b1cdbd2cSJim Jagielski     bool operator==(PackedPixelIterator const & rhs) const
752*b1cdbd2cSJim Jagielski     {
753*b1cdbd2cSJim Jagielski         return equal(rhs);
754*b1cdbd2cSJim Jagielski     }
755*b1cdbd2cSJim Jagielski 
operator !=(PackedPixelIterator const & rhs) const756*b1cdbd2cSJim Jagielski     bool operator!=(PackedPixelIterator const & rhs) const
757*b1cdbd2cSJim Jagielski     {
758*b1cdbd2cSJim Jagielski         return !equal(rhs);
759*b1cdbd2cSJim Jagielski     }
760*b1cdbd2cSJim Jagielski 
operator -(PackedPixelIterator const & rhs) const761*b1cdbd2cSJim Jagielski     difference_type operator-(PackedPixelIterator const & rhs) const
762*b1cdbd2cSJim Jagielski     {
763*b1cdbd2cSJim Jagielski         return difference_type(x - rhs.x, y - rhs.y);
764*b1cdbd2cSJim Jagielski     }
765*b1cdbd2cSJim Jagielski 
766*b1cdbd2cSJim Jagielski     MoveX x;
767*b1cdbd2cSJim Jagielski     MoveY y;
768*b1cdbd2cSJim Jagielski 
operator +=(difference_type const & s)769*b1cdbd2cSJim Jagielski     PackedPixelIterator & operator+=(difference_type const & s)
770*b1cdbd2cSJim Jagielski     {
771*b1cdbd2cSJim Jagielski         x += s.x;
772*b1cdbd2cSJim Jagielski         y += s.y;
773*b1cdbd2cSJim Jagielski         return *this;
774*b1cdbd2cSJim Jagielski     }
775*b1cdbd2cSJim Jagielski 
operator -=(difference_type const & s)776*b1cdbd2cSJim Jagielski     PackedPixelIterator & operator-=(difference_type const & s)
777*b1cdbd2cSJim Jagielski     {
778*b1cdbd2cSJim Jagielski         x -= s.x;
779*b1cdbd2cSJim Jagielski         y -= s.y;
780*b1cdbd2cSJim Jagielski         return *this;
781*b1cdbd2cSJim Jagielski     }
782*b1cdbd2cSJim Jagielski 
operator +(difference_type const & s) const783*b1cdbd2cSJim Jagielski     PackedPixelIterator operator+(difference_type const & s) const
784*b1cdbd2cSJim Jagielski     {
785*b1cdbd2cSJim Jagielski         PackedPixelIterator ret(*this);
786*b1cdbd2cSJim Jagielski         ret += s;
787*b1cdbd2cSJim Jagielski         return ret;
788*b1cdbd2cSJim Jagielski     }
789*b1cdbd2cSJim Jagielski 
operator -(difference_type const & s) const790*b1cdbd2cSJim Jagielski     PackedPixelIterator operator-(difference_type const & s) const
791*b1cdbd2cSJim Jagielski     {
792*b1cdbd2cSJim Jagielski         PackedPixelIterator ret(*this);
793*b1cdbd2cSJim Jagielski         ret -= s;
794*b1cdbd2cSJim Jagielski         return ret;
795*b1cdbd2cSJim Jagielski     }
796*b1cdbd2cSJim Jagielski 
rowIterator() const797*b1cdbd2cSJim Jagielski     row_iterator rowIterator() const
798*b1cdbd2cSJim Jagielski     {
799*b1cdbd2cSJim Jagielski         return row_iterator(current());
800*b1cdbd2cSJim Jagielski     }
801*b1cdbd2cSJim Jagielski 
columnIterator() const802*b1cdbd2cSJim Jagielski     column_iterator columnIterator() const
803*b1cdbd2cSJim Jagielski     {
804*b1cdbd2cSJim Jagielski         return column_iterator(MoveY(y,
805*b1cdbd2cSJim Jagielski                                      x / num_intraword_positions),
806*b1cdbd2cSJim Jagielski                                x % num_intraword_positions);
807*b1cdbd2cSJim Jagielski     }
808*b1cdbd2cSJim Jagielski 
get() const809*b1cdbd2cSJim Jagielski     value_type get() const
810*b1cdbd2cSJim Jagielski     {
811*b1cdbd2cSJim Jagielski         const int remainder( x() % num_intraword_positions );
812*b1cdbd2cSJim Jagielski 
813*b1cdbd2cSJim Jagielski         // TODO(Q3): use traits to get unsigned type for data_type (if
814*b1cdbd2cSJim Jagielski         // not already)
815*b1cdbd2cSJim Jagielski         return (static_cast<unsigned int>(*current() &
816*b1cdbd2cSJim Jagielski                                           get_mask<data_type, bits_per_pixel, MsbFirst>(remainder))
817*b1cdbd2cSJim Jagielski                 >> (MsbFirst ?
818*b1cdbd2cSJim Jagielski                     (num_intraword_positions - remainder) :
819*b1cdbd2cSJim Jagielski                     remainder));
820*b1cdbd2cSJim Jagielski     }
821*b1cdbd2cSJim Jagielski 
get(difference_type const & d) const822*b1cdbd2cSJim Jagielski     value_type get(difference_type const & d) const
823*b1cdbd2cSJim Jagielski     {
824*b1cdbd2cSJim Jagielski         const int remainder( x(d.x) % num_intraword_positions );
825*b1cdbd2cSJim Jagielski 
826*b1cdbd2cSJim Jagielski         // TODO(Q3): use traits to get unsigned type for data_type (if
827*b1cdbd2cSJim Jagielski         // not already)
828*b1cdbd2cSJim Jagielski         return (static_cast<unsigned int>(*current(d.x,d.y) &
829*b1cdbd2cSJim Jagielski                                           get_mask<data_type, bits_per_pixel, MsbFirst>(remainder))
830*b1cdbd2cSJim Jagielski                 >> get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder));
831*b1cdbd2cSJim Jagielski     }
832*b1cdbd2cSJim Jagielski 
set(value_type v) const833*b1cdbd2cSJim Jagielski     void set( value_type v ) const
834*b1cdbd2cSJim Jagielski     {
835*b1cdbd2cSJim Jagielski         const int remainder( x() % num_intraword_positions );
836*b1cdbd2cSJim Jagielski         const int mask( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) );
837*b1cdbd2cSJim Jagielski         const value_type pixel_value(
838*b1cdbd2cSJim Jagielski             (v <<
839*b1cdbd2cSJim Jagielski              get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder))
840*b1cdbd2cSJim Jagielski             & mask );
841*b1cdbd2cSJim Jagielski         pointer p = current();
842*b1cdbd2cSJim Jagielski         *p = (*p & ~mask) | pixel_value;
843*b1cdbd2cSJim Jagielski     }
844*b1cdbd2cSJim Jagielski 
set(value_type v,difference_type const & d) const845*b1cdbd2cSJim Jagielski     void set( value_type v, difference_type const & d ) const
846*b1cdbd2cSJim Jagielski     {
847*b1cdbd2cSJim Jagielski         const int remainder( x(d.x) % num_intraword_positions );
848*b1cdbd2cSJim Jagielski         const int mask( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) );
849*b1cdbd2cSJim Jagielski         const value_type pixel_value(
850*b1cdbd2cSJim Jagielski             (v <<
851*b1cdbd2cSJim Jagielski              get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder))
852*b1cdbd2cSJim Jagielski              & mask );
853*b1cdbd2cSJim Jagielski         pointer p = current(d.x,d.y);
854*b1cdbd2cSJim Jagielski         *p = (*p & ~mask) | pixel_value;
855*b1cdbd2cSJim Jagielski     }
856*b1cdbd2cSJim Jagielski };
857*b1cdbd2cSJim Jagielski 
858*b1cdbd2cSJim Jagielski 
859*b1cdbd2cSJim Jagielski /** Access (possibly packed-pixel) data via palette indirection
860*b1cdbd2cSJim Jagielski  */
861*b1cdbd2cSJim Jagielski template< typename Valuetype, typename Datatype > class PaletteImageAccessor
862*b1cdbd2cSJim Jagielski {
863*b1cdbd2cSJim Jagielski   public:
864*b1cdbd2cSJim Jagielski     typedef Valuetype                                   value_type;
865*b1cdbd2cSJim Jagielski     typedef Datatype                                    data_type;
866*b1cdbd2cSJim Jagielski     typedef typename remove_const<data_type>::type      count_type;
867*b1cdbd2cSJim Jagielski 
868*b1cdbd2cSJim Jagielski 
869*b1cdbd2cSJim Jagielski private:
870*b1cdbd2cSJim Jagielski     const BitmapColor* palette;
871*b1cdbd2cSJim Jagielski     count_type         num_entries;
872*b1cdbd2cSJim Jagielski 
norm(BitmapColor const & rLHS,BitmapColor const & rRHS) const873*b1cdbd2cSJim Jagielski     double norm( BitmapColor const& rLHS,
874*b1cdbd2cSJim Jagielski                  BitmapColor const& rRHS ) const
875*b1cdbd2cSJim Jagielski     {
876*b1cdbd2cSJim Jagielski         // convert RGBValue's linear space to a normed linear space
877*b1cdbd2cSJim Jagielski         return sqrt(
878*b1cdbd2cSJim Jagielski             vigra::sq(rLHS.GetRed()-rRHS.GetRed()) +
879*b1cdbd2cSJim Jagielski             vigra::sq(rLHS.GetGreen()-rRHS.GetGreen()) +
880*b1cdbd2cSJim Jagielski             vigra::sq(rLHS.GetBlue()-rRHS.GetBlue()) );
881*b1cdbd2cSJim Jagielski     }
882*b1cdbd2cSJim Jagielski 
find_best_match(value_type const & v) const883*b1cdbd2cSJim Jagielski     data_type find_best_match(value_type const& v) const
884*b1cdbd2cSJim Jagielski     {
885*b1cdbd2cSJim Jagielski         // TODO(F3): not generic!!!
886*b1cdbd2cSJim Jagielski         const BitmapColor aTmpCol(v.red(),
887*b1cdbd2cSJim Jagielski                                   v.green(),
888*b1cdbd2cSJim Jagielski                                   v.blue());
889*b1cdbd2cSJim Jagielski 
890*b1cdbd2cSJim Jagielski         // TODO(P3): use table-based/octree approach here!
891*b1cdbd2cSJim Jagielski         const BitmapColor* best_entry;
892*b1cdbd2cSJim Jagielski         const BitmapColor* palette_end( palette+num_entries );
893*b1cdbd2cSJim Jagielski         if( (best_entry=std::find( palette, palette_end, aTmpCol)) != palette_end )
894*b1cdbd2cSJim Jagielski             return best_entry-palette;
895*b1cdbd2cSJim Jagielski 
896*b1cdbd2cSJim Jagielski         // TODO(F3): HACK. Need palette traits, and an error function
897*b1cdbd2cSJim Jagielski         // here. We blatantly assume value_type is a normed linear
898*b1cdbd2cSJim Jagielski         // space.
899*b1cdbd2cSJim Jagielski         const BitmapColor* curr_entry( palette );
900*b1cdbd2cSJim Jagielski         best_entry = curr_entry;
901*b1cdbd2cSJim Jagielski         while( curr_entry != palette_end )
902*b1cdbd2cSJim Jagielski         {
903*b1cdbd2cSJim Jagielski             if( norm(*curr_entry,*best_entry) > norm(*curr_entry,aTmpCol) )
904*b1cdbd2cSJim Jagielski                 best_entry = curr_entry;
905*b1cdbd2cSJim Jagielski 
906*b1cdbd2cSJim Jagielski             ++curr_entry;
907*b1cdbd2cSJim Jagielski         }
908*b1cdbd2cSJim Jagielski 
909*b1cdbd2cSJim Jagielski         return best_entry-palette;
910*b1cdbd2cSJim Jagielski     }
911*b1cdbd2cSJim Jagielski 
toCol(BitmapColor const & rCol) const912*b1cdbd2cSJim Jagielski     value_type toCol( BitmapColor const& rCol ) const
913*b1cdbd2cSJim Jagielski     {
914*b1cdbd2cSJim Jagielski         return value_type(rCol.GetRed(),rCol.GetGreen(),rCol.GetBlue());
915*b1cdbd2cSJim Jagielski     }
916*b1cdbd2cSJim Jagielski 
917*b1cdbd2cSJim Jagielski public:
PaletteImageAccessor()918*b1cdbd2cSJim Jagielski     PaletteImageAccessor() :
919*b1cdbd2cSJim Jagielski         palette(0),
920*b1cdbd2cSJim Jagielski         num_entries(0)
921*b1cdbd2cSJim Jagielski     {}
922*b1cdbd2cSJim Jagielski 
PaletteImageAccessor(const BitmapColor * pPalette,data_type entries)923*b1cdbd2cSJim Jagielski     PaletteImageAccessor( const BitmapColor* pPalette,
924*b1cdbd2cSJim Jagielski                           data_type          entries ) :
925*b1cdbd2cSJim Jagielski         palette(pPalette),
926*b1cdbd2cSJim Jagielski         num_entries(entries)
927*b1cdbd2cSJim Jagielski     {}
928*b1cdbd2cSJim Jagielski 
929*b1cdbd2cSJim Jagielski     template< class Iterator >
operator ()(Iterator const & i) const930*b1cdbd2cSJim Jagielski     value_type operator()(Iterator const& i) const { return toCol(palette[i.get()]); }
operator ()(data_type const * i) const931*b1cdbd2cSJim Jagielski     value_type operator()(data_type const* i) const { return toCol(palette[*i]); }
932*b1cdbd2cSJim Jagielski 
933*b1cdbd2cSJim Jagielski     template< class Iterator, class Difference >
operator ()(Iterator const & i,Difference const & diff) const934*b1cdbd2cSJim Jagielski     value_type operator()(Iterator const& i, Difference const& diff) const
935*b1cdbd2cSJim Jagielski     {
936*b1cdbd2cSJim Jagielski         return toCol(palette[i.get(diff)]);
937*b1cdbd2cSJim Jagielski     }
938*b1cdbd2cSJim Jagielski 
939*b1cdbd2cSJim Jagielski     template< typename V, class Iterator >
set(V const & value,Iterator const & i) const940*b1cdbd2cSJim Jagielski     void set(V const& value, Iterator const& i) const
941*b1cdbd2cSJim Jagielski     {
942*b1cdbd2cSJim Jagielski         i.set(
943*b1cdbd2cSJim Jagielski             find_best_match(
944*b1cdbd2cSJim Jagielski                 vigra::detail::RequiresExplicitCast<value_type>::cast(value) ));
945*b1cdbd2cSJim Jagielski     }
946*b1cdbd2cSJim Jagielski 
947*b1cdbd2cSJim Jagielski     template< typename V, class Iterator, class Difference >
set(V const & value,Iterator const & i,Difference const & diff) const948*b1cdbd2cSJim Jagielski     void set(V const& value, Iterator const& i, Difference const& diff) const
949*b1cdbd2cSJim Jagielski     {
950*b1cdbd2cSJim Jagielski         i.set(
951*b1cdbd2cSJim Jagielski             find_best_match(
952*b1cdbd2cSJim Jagielski                 vigra::detail::RequiresExplicitCast<value_type>::cast(value)),
953*b1cdbd2cSJim Jagielski             diff );
954*b1cdbd2cSJim Jagielski     }
955*b1cdbd2cSJim Jagielski };
956*b1cdbd2cSJim Jagielski 
957*b1cdbd2cSJim Jagielski }
958*b1cdbd2cSJim Jagielski 
959*b1cdbd2cSJim Jagielski 
960*b1cdbd2cSJim Jagielski class TestApp : public Application
961*b1cdbd2cSJim Jagielski {
962*b1cdbd2cSJim Jagielski public:
963*b1cdbd2cSJim Jagielski 	virtual void Main();
964*b1cdbd2cSJim Jagielski 	virtual USHORT	Exception( USHORT nError );
965*b1cdbd2cSJim Jagielski };
966*b1cdbd2cSJim Jagielski 
967*b1cdbd2cSJim Jagielski class TestWindow : public Dialog
968*b1cdbd2cSJim Jagielski {
969*b1cdbd2cSJim Jagielski 	public:
TestWindow()970*b1cdbd2cSJim Jagielski 		TestWindow() : Dialog( (Window *) NULL )
971*b1cdbd2cSJim Jagielski 		{
972*b1cdbd2cSJim Jagielski 			SetText( rtl::OUString::createFromAscii( "VIGRA test" ) );
973*b1cdbd2cSJim Jagielski 			SetSizePixel( Size( 1024, 1024 ) );
974*b1cdbd2cSJim Jagielski 			EnablePaint( true );
975*b1cdbd2cSJim Jagielski 			Show();
976*b1cdbd2cSJim Jagielski 		}
~TestWindow()977*b1cdbd2cSJim Jagielski 		virtual ~TestWindow() {}
MouseButtonUp(const MouseEvent &)978*b1cdbd2cSJim Jagielski         virtual void MouseButtonUp( const MouseEvent& /*rMEvt*/ )
979*b1cdbd2cSJim Jagielski 		{
980*b1cdbd2cSJim Jagielski 			//TODO: do something cool
981*b1cdbd2cSJim Jagielski             EndDialog();
982*b1cdbd2cSJim Jagielski         }
983*b1cdbd2cSJim Jagielski 		virtual void Paint( const Rectangle& rRect );
984*b1cdbd2cSJim Jagielski };
985*b1cdbd2cSJim Jagielski 
986*b1cdbd2cSJim Jagielski 
project(const basegfx::B2IPoint & rPoint)987*b1cdbd2cSJim Jagielski static basegfx::B2IPoint project( const basegfx::B2IPoint& rPoint )
988*b1cdbd2cSJim Jagielski {
989*b1cdbd2cSJim Jagielski 	const double angle_x = M_PI / 6.0;
990*b1cdbd2cSJim Jagielski 	const double angle_z = M_PI / 6.0;
991*b1cdbd2cSJim Jagielski 
992*b1cdbd2cSJim Jagielski 	// transform planar coordinates to 3d
993*b1cdbd2cSJim Jagielski 	double x = rPoint.getX();
994*b1cdbd2cSJim Jagielski 	double y = rPoint.getY();
995*b1cdbd2cSJim Jagielski 	//double z = 0;
996*b1cdbd2cSJim Jagielski 
997*b1cdbd2cSJim Jagielski 	// rotate around X axis
998*b1cdbd2cSJim Jagielski 	double x1 = x;
999*b1cdbd2cSJim Jagielski 	double y1 = y * cos( angle_x );
1000*b1cdbd2cSJim Jagielski 	double z1 = y * sin( angle_x );
1001*b1cdbd2cSJim Jagielski 
1002*b1cdbd2cSJim Jagielski 	// rotate around Z axis
1003*b1cdbd2cSJim Jagielski 	double x2 = x1 * cos( angle_z ) + y1 * sin( angle_z );
1004*b1cdbd2cSJim Jagielski 	//double y2 = y1 * cos( angle_z ) - x1 * sin( angle_z );
1005*b1cdbd2cSJim Jagielski 	double z2 = z1;
1006*b1cdbd2cSJim Jagielski 
1007*b1cdbd2cSJim Jagielski 	//return basegfx::B2IPoint( (sal_Int32)3*x2, (sal_Int32)3*z2 );
1008*b1cdbd2cSJim Jagielski 	return basegfx::B2IPoint( (sal_Int32)(6*x2), (sal_Int32)(6*z2) );
1009*b1cdbd2cSJim Jagielski }
1010*b1cdbd2cSJim Jagielski 
approachColor(const basebmp::Color & rFrom,const basebmp::Color & rTo)1011*b1cdbd2cSJim Jagielski static basebmp::Color approachColor( const basebmp::Color& rFrom, const basebmp::Color& rTo )
1012*b1cdbd2cSJim Jagielski {
1013*b1cdbd2cSJim Jagielski 	basebmp::Color aColor;
1014*b1cdbd2cSJim Jagielski 	UINT8 nDiff;
1015*b1cdbd2cSJim Jagielski 	// approach red
1016*b1cdbd2cSJim Jagielski 	if( rFrom.getRed() < rTo.getRed() )
1017*b1cdbd2cSJim Jagielski 	{
1018*b1cdbd2cSJim Jagielski 		nDiff = rTo.getRed() - rFrom.getRed();
1019*b1cdbd2cSJim Jagielski 		aColor.setRed( rFrom.getRed() + ( nDiff < 10 ? nDiff : 10 ) );
1020*b1cdbd2cSJim Jagielski 	}
1021*b1cdbd2cSJim Jagielski 	else if( rFrom.getRed() > rTo.getRed() )
1022*b1cdbd2cSJim Jagielski 	{
1023*b1cdbd2cSJim Jagielski 		nDiff = rFrom.getRed() - rTo.getRed();
1024*b1cdbd2cSJim Jagielski 		aColor.setRed( rFrom.getRed() - ( nDiff < 10 ? nDiff : 10 ) );
1025*b1cdbd2cSJim Jagielski 	}
1026*b1cdbd2cSJim Jagielski 	else
1027*b1cdbd2cSJim Jagielski 		aColor.setRed( rFrom.getRed() );
1028*b1cdbd2cSJim Jagielski 
1029*b1cdbd2cSJim Jagielski 	// approach Green
1030*b1cdbd2cSJim Jagielski 	if( rFrom.getGreen() < rTo.getGreen() )
1031*b1cdbd2cSJim Jagielski 	{
1032*b1cdbd2cSJim Jagielski 		nDiff = rTo.getGreen() - rFrom.getGreen();
1033*b1cdbd2cSJim Jagielski 		aColor.setGreen( rFrom.getGreen() + ( nDiff < 10 ? nDiff : 10 ) );
1034*b1cdbd2cSJim Jagielski 	}
1035*b1cdbd2cSJim Jagielski 	else if( rFrom.getGreen() > rTo.getGreen() )
1036*b1cdbd2cSJim Jagielski 	{
1037*b1cdbd2cSJim Jagielski 		nDiff = rFrom.getGreen() - rTo.getGreen();
1038*b1cdbd2cSJim Jagielski 		aColor.setGreen( rFrom.getGreen() - ( nDiff < 10 ? nDiff : 10 ) );
1039*b1cdbd2cSJim Jagielski 	}
1040*b1cdbd2cSJim Jagielski 	else
1041*b1cdbd2cSJim Jagielski 		aColor.setGreen( rFrom.getGreen() );
1042*b1cdbd2cSJim Jagielski 
1043*b1cdbd2cSJim Jagielski 	// approach blue
1044*b1cdbd2cSJim Jagielski 	if( rFrom.getBlue() < rTo.getBlue() )
1045*b1cdbd2cSJim Jagielski 	{
1046*b1cdbd2cSJim Jagielski 		nDiff = rTo.getBlue() - rFrom.getBlue();
1047*b1cdbd2cSJim Jagielski 		aColor.setBlue( rFrom.getBlue() + ( nDiff < 10 ? nDiff : 10 ) );
1048*b1cdbd2cSJim Jagielski 	}
1049*b1cdbd2cSJim Jagielski 	else if( rFrom.getBlue() > rTo.getBlue() )
1050*b1cdbd2cSJim Jagielski 	{
1051*b1cdbd2cSJim Jagielski 		nDiff = rFrom.getBlue() - rTo.getBlue();
1052*b1cdbd2cSJim Jagielski 		aColor.setBlue( rFrom.getBlue() - ( nDiff < 10 ? nDiff : 10 ) );
1053*b1cdbd2cSJim Jagielski 	}
1054*b1cdbd2cSJim Jagielski 	else
1055*b1cdbd2cSJim Jagielski 		aColor.setBlue( rFrom.getBlue() );
1056*b1cdbd2cSJim Jagielski 
1057*b1cdbd2cSJim Jagielski 	return aColor;
1058*b1cdbd2cSJim Jagielski }
1059*b1cdbd2cSJim Jagielski 
1060*b1cdbd2cSJim Jagielski #define DELTA 5.0
1061*b1cdbd2cSJim Jagielski 
1062*b1cdbd2cSJim Jagielski 
1063*b1cdbd2cSJim Jagielski 
Paint(const Rectangle &)1064*b1cdbd2cSJim Jagielski void TestWindow::Paint( const Rectangle& /*rRect*/ )
1065*b1cdbd2cSJim Jagielski {
1066*b1cdbd2cSJim Jagielski     basegfx::B2ISize aTestSize(1000,1000);
1067*b1cdbd2cSJim Jagielski     basebmp::BitmapDeviceSharedPtr pDevice( basebmp::createBitmapDevice( aTestSize,
1068*b1cdbd2cSJim Jagielski                                                                          false,
1069*b1cdbd2cSJim Jagielski                                                                          basebmp::Format::THIRTYTWO_BIT_TC_MASK ));
1070*b1cdbd2cSJim Jagielski 
1071*b1cdbd2cSJim Jagielski     {
1072*b1cdbd2cSJim Jagielski         ::rtl::OUString aSvg;
1073*b1cdbd2cSJim Jagielski         basegfx::B2DPolyPolygon aPoly;
1074*b1cdbd2cSJim Jagielski 
1075*b1cdbd2cSJim Jagielski         basegfx::tools::importFromSvgD( aPoly,
1076*b1cdbd2cSJim Jagielski                                         ::rtl::OUString::createFromAscii(
1077*b1cdbd2cSJim Jagielski                                             "m0 0 h7 v7 h-7 z" ) );
1078*b1cdbd2cSJim Jagielski         basegfx::tools::importFromSvgD( aPoly,
1079*b1cdbd2cSJim Jagielski                                         ::rtl::OUString::createFromAscii(
1080*b1cdbd2cSJim Jagielski                                             "m2 2 h3 v3 h-3 z" ) );
1081*b1cdbd2cSJim Jagielski 
1082*b1cdbd2cSJim Jagielski         pDevice->fillPolyPolygon(
1083*b1cdbd2cSJim Jagielski             aPoly,
1084*b1cdbd2cSJim Jagielski             basebmp::Color(0xFFFFFFFF),
1085*b1cdbd2cSJim Jagielski             basebmp::DrawMode_PAINT );
1086*b1cdbd2cSJim Jagielski     }
1087*b1cdbd2cSJim Jagielski 
1088*b1cdbd2cSJim Jagielski #if 0
1089*b1cdbd2cSJim Jagielski     {
1090*b1cdbd2cSJim Jagielski         basebmp::BitmapDeviceSharedPtr pMask( basebmp::createBitmapDevice( aTestSize,
1091*b1cdbd2cSJim Jagielski                                                                            false,
1092*b1cdbd2cSJim Jagielski                                                                            basebmp::Format::ONE_BIT_MSB_GREY ));
1093*b1cdbd2cSJim Jagielski 
1094*b1cdbd2cSJim Jagielski         const basegfx::B2IPoint aPt111(10,10);
1095*b1cdbd2cSJim Jagielski         const basegfx::B2IPoint aPt222(0,10);
1096*b1cdbd2cSJim Jagielski         const basebmp::Color aCol333(0xFFFFFFFF);
1097*b1cdbd2cSJim Jagielski         pMask->drawLine( aPt111, aPt222, aCol333, basebmp::DrawMode_PAINT );
1098*b1cdbd2cSJim Jagielski 
1099*b1cdbd2cSJim Jagielski 
1100*b1cdbd2cSJim Jagielski         ::rtl::OUString aSvg = ::rtl::OUString::createFromAscii(
1101*b1cdbd2cSJim Jagielski             "m 0 0 h5 l5 5 v5 h-5 l-5-5 z" );
1102*b1cdbd2cSJim Jagielski         basegfx::B2DPolyPolygon aPoly;
1103*b1cdbd2cSJim Jagielski         basegfx::tools::importFromSvgD( aPoly, aSvg );
1104*b1cdbd2cSJim Jagielski         pMask->clear(basebmp::Color(0xFFFFFFFF));
1105*b1cdbd2cSJim Jagielski         pMask->drawPolygon(
1106*b1cdbd2cSJim Jagielski             aPoly.getB2DPolygon(0),
1107*b1cdbd2cSJim Jagielski             basebmp::Color(0),
1108*b1cdbd2cSJim Jagielski             basebmp::DrawMode_PAINT );
1109*b1cdbd2cSJim Jagielski 
1110*b1cdbd2cSJim Jagielski         basebmp::BitmapDeviceSharedPtr pSubsetDevice =
1111*b1cdbd2cSJim Jagielski             basebmp::subsetBitmapDevice( pDevice,
1112*b1cdbd2cSJim Jagielski                                          basegfx::B2IRange(3,3,7,7) );
1113*b1cdbd2cSJim Jagielski 
1114*b1cdbd2cSJim Jagielski         const basegfx::B2IPoint aPt1(0,0);
1115*b1cdbd2cSJim Jagielski         const basegfx::B2IPoint aPt2(1,9);
1116*b1cdbd2cSJim Jagielski         const basebmp::Color aCol(0xFFFFFFFF);
1117*b1cdbd2cSJim Jagielski         pDevice->drawLine( aPt1, aPt2, aCol, basebmp::DrawMode_PAINT, pMask );
1118*b1cdbd2cSJim Jagielski     }
1119*b1cdbd2cSJim Jagielski 
1120*b1cdbd2cSJim Jagielski     {
1121*b1cdbd2cSJim Jagielski         const basebmp::Color aCol(0xFFFFFFFF);
1122*b1cdbd2cSJim Jagielski         basegfx::B2DPolygon aRect = basegfx::tools::createPolygonFromRect(
1123*b1cdbd2cSJim Jagielski             basegfx::B2DRange( 0,0,1001,1001 ));
1124*b1cdbd2cSJim Jagielski         pDevice->drawPolygon( aRect, aCol, basebmp::DrawMode_PAINT );
1125*b1cdbd2cSJim Jagielski 
1126*b1cdbd2cSJim Jagielski         const basegfx::B2IPoint aPt1(0,0);
1127*b1cdbd2cSJim Jagielski         const basegfx::B2IPoint aPt2(0,800);
1128*b1cdbd2cSJim Jagielski         pDevice->drawLine( aPt1, aPt2, aCol, basebmp::DrawMode_PAINT );
1129*b1cdbd2cSJim Jagielski 
1130*b1cdbd2cSJim Jagielski         const basegfx::B2IPoint aPt3(0,1001);
1131*b1cdbd2cSJim Jagielski         pDevice->drawLine( aPt1, aPt3, aCol, basebmp::DrawMode_PAINT );
1132*b1cdbd2cSJim Jagielski     }
1133*b1cdbd2cSJim Jagielski #endif
1134*b1cdbd2cSJim Jagielski 
1135*b1cdbd2cSJim Jagielski     {
1136*b1cdbd2cSJim Jagielski         pDevice->clear(basebmp::Color(0));
1137*b1cdbd2cSJim Jagielski 
1138*b1cdbd2cSJim Jagielski         basegfx::B2IPoint aCenter( aTestSize.getX()/2,
1139*b1cdbd2cSJim Jagielski                                    aTestSize.getY()/2 );
1140*b1cdbd2cSJim Jagielski         //basegfx::B2IPoint aP1( aTestSize.getX()/48, 0), aP2( aTestSize.getX()/40, 0 ), aPoint;
1141*b1cdbd2cSJim Jagielski         //basegfx::B2IPoint aP1( aTestSize.getX()/7, 0), aP2( aTestSize.getX()/6, 0 ), aPoint;
1142*b1cdbd2cSJim Jagielski         //basegfx::B2IPoint aP1( aTestSize.getX()/5, 0), aP2( aTestSize.getX()/4, 0 ), aPoint;
1143*b1cdbd2cSJim Jagielski         basegfx::B2IPoint aP1( aTestSize.getX()/12, 0), aP2( aTestSize.getX()/11, 0 ), aPoint;
1144*b1cdbd2cSJim Jagielski 
1145*b1cdbd2cSJim Jagielski         double sind = sin( DELTA*M_PI/180.0 );
1146*b1cdbd2cSJim Jagielski         double cosd = cos( DELTA*M_PI/180.0 );
1147*b1cdbd2cSJim Jagielski         double factor = 1 + (DELTA/1000.0);
1148*b1cdbd2cSJim Jagielski         int n=0;
1149*b1cdbd2cSJim Jagielski         basebmp::Color aLineColor( 0, 0, 0 );
1150*b1cdbd2cSJim Jagielski         basebmp::Color aApproachColor( 0, 0, 200 );
1151*b1cdbd2cSJim Jagielski         while ( aP2.getX() < aCenter.getX() && n++ < 680 )
1152*b1cdbd2cSJim Jagielski         {
1153*b1cdbd2cSJim Jagielski             aLineColor = approachColor( aLineColor, aApproachColor );
1154*b1cdbd2cSJim Jagielski 
1155*b1cdbd2cSJim Jagielski             // switch aproach color
1156*b1cdbd2cSJim Jagielski             if( aApproachColor == aLineColor )
1157*b1cdbd2cSJim Jagielski             {
1158*b1cdbd2cSJim Jagielski                 if( aApproachColor.getRed() )
1159*b1cdbd2cSJim Jagielski                     aApproachColor = basebmp::Color( 0, 0, 200 );
1160*b1cdbd2cSJim Jagielski                 else if( aApproachColor.getGreen() )
1161*b1cdbd2cSJim Jagielski                     aApproachColor = basebmp::Color( 200, 0, 0 );
1162*b1cdbd2cSJim Jagielski                 else
1163*b1cdbd2cSJim Jagielski                     aApproachColor = basebmp::Color( 0, 200, 0 );
1164*b1cdbd2cSJim Jagielski             }
1165*b1cdbd2cSJim Jagielski 
1166*b1cdbd2cSJim Jagielski             basegfx::B2DPolygon aPoly;
1167*b1cdbd2cSJim Jagielski             aPoly.append( basegfx::B2DPoint(project( aP1 ) + aCenter) );
1168*b1cdbd2cSJim Jagielski             aPoly.append( basegfx::B2DPoint(project( aP2 ) + aCenter) );
1169*b1cdbd2cSJim Jagielski             pDevice->fillPolyPolygon(
1170*b1cdbd2cSJim Jagielski                 basegfx::tools::createAreaGeometryForPolygon(
1171*b1cdbd2cSJim Jagielski                     aPoly,
1172*b1cdbd2cSJim Jagielski //                    std::max(1,n/30),
1173*b1cdbd2cSJim Jagielski //                    std::max(1,n/60),
1174*b1cdbd2cSJim Jagielski                     std::max(1,n/30),
1175*b1cdbd2cSJim Jagielski                     basegfx::tools::B2DLINEJOIN_NONE),
1176*b1cdbd2cSJim Jagielski                 aLineColor,
1177*b1cdbd2cSJim Jagielski                 basebmp::DrawMode_PAINT);
1178*b1cdbd2cSJim Jagielski 
1179*b1cdbd2cSJim Jagielski             aPoint.setX( (int)((((double)aP1.getX())*cosd - ((double)aP1.getY())*sind)*factor) );
1180*b1cdbd2cSJim Jagielski             aPoint.setY( (int)((((double)aP1.getY())*cosd + ((double)aP1.getX())*sind)*factor) );
1181*b1cdbd2cSJim Jagielski             aP1 = aPoint;
1182*b1cdbd2cSJim Jagielski             aPoint.setX( (int)((((double)aP2.getX())*cosd - ((double)aP2.getY())*sind)*factor) );
1183*b1cdbd2cSJim Jagielski             aPoint.setY( (int)((((double)aP2.getY())*cosd + ((double)aP2.getX())*sind)*factor) );
1184*b1cdbd2cSJim Jagielski             aP2 = aPoint;
1185*b1cdbd2cSJim Jagielski         }
1186*b1cdbd2cSJim Jagielski     }
1187*b1cdbd2cSJim Jagielski 
1188*b1cdbd2cSJim Jagielski     Bitmap aBitmap( Size(aTestSize.getX(),
1189*b1cdbd2cSJim Jagielski                          aTestSize.getY()), 24 );
1190*b1cdbd2cSJim Jagielski 
1191*b1cdbd2cSJim Jagielski     // Fill bitmap with generated content
1192*b1cdbd2cSJim Jagielski     {
1193*b1cdbd2cSJim Jagielski         ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(),
1194*b1cdbd2cSJim Jagielski                                               aBitmap );
1195*b1cdbd2cSJim Jagielski         for( int y=0; y<aTestSize.getY(); ++y )
1196*b1cdbd2cSJim Jagielski             for( int x=0; x<aTestSize.getX(); ++x )
1197*b1cdbd2cSJim Jagielski                 pWriteAccess->SetPixel(y,x,
1198*b1cdbd2cSJim Jagielski                                        Color(pDevice->getPixelData(basegfx::B2IPoint(x,y))) );
1199*b1cdbd2cSJim Jagielski     }
1200*b1cdbd2cSJim Jagielski 
1201*b1cdbd2cSJim Jagielski     DrawBitmap( Point(), aBitmap );
1202*b1cdbd2cSJim Jagielski }
1203*b1cdbd2cSJim Jagielski 
Exception(USHORT nError)1204*b1cdbd2cSJim Jagielski USHORT TestApp::Exception( USHORT nError )
1205*b1cdbd2cSJim Jagielski {
1206*b1cdbd2cSJim Jagielski 	switch( nError & EXC_MAJORTYPE )
1207*b1cdbd2cSJim Jagielski 	{
1208*b1cdbd2cSJim Jagielski 		case EXC_RSCNOTLOADED:
1209*b1cdbd2cSJim Jagielski 			Abort( String::CreateFromAscii( "Error: could not load language resources.\nPlease check your installation.\n" ) );
1210*b1cdbd2cSJim Jagielski 			break;
1211*b1cdbd2cSJim Jagielski 	}
1212*b1cdbd2cSJim Jagielski 	return 0;
1213*b1cdbd2cSJim Jagielski }
1214*b1cdbd2cSJim Jagielski 
Main()1215*b1cdbd2cSJim Jagielski void TestApp::Main()
1216*b1cdbd2cSJim Jagielski {
1217*b1cdbd2cSJim Jagielski 	//-------------------------------------------------
1218*b1cdbd2cSJim Jagielski 	// create the global service-manager
1219*b1cdbd2cSJim Jagielski 	//-------------------------------------------------
1220*b1cdbd2cSJim Jagielski     uno::Reference< lang::XMultiServiceFactory > xFactory;
1221*b1cdbd2cSJim Jagielski     try
1222*b1cdbd2cSJim Jagielski     {
1223*b1cdbd2cSJim Jagielski         uno::Reference< uno::XComponentContext > xCtx = ::cppu::defaultBootstrap_InitialComponentContext();
1224*b1cdbd2cSJim Jagielski         xFactory = uno::Reference< lang::XMultiServiceFactory >(  xCtx->getServiceManager(),
1225*b1cdbd2cSJim Jagielski                                                                   uno::UNO_QUERY );
1226*b1cdbd2cSJim Jagielski         if( xFactory.is() )
1227*b1cdbd2cSJim Jagielski             ::comphelper::setProcessServiceFactory( xFactory );
1228*b1cdbd2cSJim Jagielski     }
1229*b1cdbd2cSJim Jagielski     catch( uno::Exception& )
1230*b1cdbd2cSJim Jagielski     {
1231*b1cdbd2cSJim Jagielski     }
1232*b1cdbd2cSJim Jagielski 
1233*b1cdbd2cSJim Jagielski     if( !xFactory.is() )
1234*b1cdbd2cSJim Jagielski     {
1235*b1cdbd2cSJim Jagielski         OSL_TRACE( "Could not bootstrap UNO, installation must be in disorder. Exiting.\n" );
1236*b1cdbd2cSJim Jagielski         exit( 1 );
1237*b1cdbd2cSJim Jagielski     }
1238*b1cdbd2cSJim Jagielski 
1239*b1cdbd2cSJim Jagielski     // Create UCB.
1240*b1cdbd2cSJim Jagielski     uno::Sequence< uno::Any > aArgs( 2 );
1241*b1cdbd2cSJim Jagielski 	aArgs[ 0 ] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY1_LOCAL );
1242*b1cdbd2cSJim Jagielski 	aArgs[ 1 ] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY2_OFFICE );
1243*b1cdbd2cSJim Jagielski     ::ucb::ContentBroker::initialize( xFactory, aArgs );
1244*b1cdbd2cSJim Jagielski 
1245*b1cdbd2cSJim Jagielski 	TestWindow pWindow;
1246*b1cdbd2cSJim Jagielski 	pWindow.Execute();
1247*b1cdbd2cSJim Jagielski 
1248*b1cdbd2cSJim Jagielski     // clean up UCB
1249*b1cdbd2cSJim Jagielski 	::ucb::ContentBroker::deinitialize();
1250*b1cdbd2cSJim Jagielski }
1251*b1cdbd2cSJim Jagielski 
1252*b1cdbd2cSJim Jagielski TestApp aDemoApp;
1253