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