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