bump product version to 4.1.6.2
[LibreOffice.git] / basebmp / test / bmpdemo.cxx
blobae24c65bd22d44b60e8e8e3015013a787a864092
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sal/config.h"
22 #include <math.h>
24 #include <comphelper/processfactory.hxx>
25 #include <cppuhelper/servicefactory.hxx>
26 #include <cppuhelper/bootstrap.hxx>
27 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 #include <com/sun/star/lang/XInitialization.hpp>
29 #include <com/sun/star/registry/XSimpleRegistry.hpp>
30 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
32 #include <vcl/window.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/msgbox.hxx>
35 #include <vcl/unowrap.hxx>
36 #include <vcl/bitmap.hxx>
37 #include <vcl/bmpacc.hxx>
39 #include <basegfx/polygon/b2dlinegeometry.hxx>
40 #include <basegfx/polygon/b2dpolypolygon.hxx>
41 #include <basegfx/polygon/b2dpolypolygontools.hxx>
42 #include <basegfx/polygon/b2dpolygontools.hxx>
43 #include <basegfx/polygon/b2dpolygon.hxx>
44 #include <basegfx/numeric/ftools.hxx>
45 #include <basegfx/range/b2ibox.hxx>
46 #include <basegfx/vector/b2isize.hxx>
47 #include <basegfx/vector/b2enums.hxx>
48 #include <basegfx/point/b2ipoint.hxx>
50 #include <basebmp/color.hxx>
51 #include <basebmp/scanlineformats.hxx>
52 #include <basebmp/bitmapdevice.hxx>
54 #include <rtl/bootstrap.hxx>
56 #include <vigra/metaprogramming.hxx>
57 #include <vigra/static_assert.hxx>
58 #include <vigra/basicimageview.hxx>
60 #include <boost/static_assert.hpp>
61 #include <algorithm>
63 using namespace ::com::sun::star;
66 namespace
69 /// template meta function: add const qualifier, if given 2nd type has it
70 template<typename A, typename B> struct clone_const
72 typedef B type;
74 template<typename A, typename B> struct clone_const<const A,B>
76 typedef const B type;
79 template< class DestIterator, class DestAccessor > class Renderer :
80 public basegfx::B2DPolyPolygonRasterConverter
82 private:
83 typename DestIterator::value_type fillColor_;
84 typename DestIterator::value_type clearColor_;
85 DestIterator begin_;
86 DestAccessor accessor_;
88 public:
89 Renderer(const basegfx::B2DPolyPolygon& rPolyPolyRaster,
90 typename DestIterator::value_type fillColor,
91 typename DestIterator::value_type clearColor,
92 DestIterator begin,
93 DestIterator end,
94 DestAccessor accessor ) :
95 B2DPolyPolygonRasterConverter(rPolyPolyRaster,
96 basegfx::B2DRange(0,0,
97 end.x - end.x,
98 begin.y - begin.y )),
99 fillColor_( fillColor ),
100 clearColor_( clearColor ),
101 begin_( begin ),
102 accessor_( accessor )
106 virtual void span(const double& rfXLeft,
107 const double& rfXRight,
108 sal_Int32 nY,
109 bool bOn )
111 DestIterator currIter( begin_ + vigra::Diff2D(0,nY) );
112 typename DestIterator::row_iterator rowIter( currIter.rowIterator() +
113 basegfx::fround(rfXLeft) );
114 typename DestIterator::row_iterator rowEnd( currIter.rowIterator() +
115 basegfx::fround(rfXRight) );
116 if( bOn )
117 while( rowIter != rowEnd )
119 accessor_.set(fillColor_, rowIter);
120 ++rowIter;
122 else
123 while( rowIter != rowEnd )
125 accessor_.set(accessor_(rowIter)*clearColor_, rowIter);
126 ++rowIter;
131 template< class DestIterator, class DestAccessor >
132 std::auto_ptr< Renderer< DestIterator, DestAccessor > > makeRenderer(
133 const basegfx::B2DPolyPolygon& rPolyPolyRaster,
134 typename DestIterator::value_type fillColor,
135 typename DestIterator::value_type clearColor,
136 vigra::triple<DestIterator, DestIterator, DestAccessor> dest )
138 return std::auto_ptr< Renderer< DestIterator, DestAccessor > >(
139 new Renderer< DestIterator, DestAccessor >(rPolyPolyRaster,
140 fillColor,
141 clearColor,
142 dest.first,
143 dest.second,
144 dest.third));
148 // changed semantics re. DirectionSelector<StridedArrayTag>: stride
149 // now counts in <em>raw</em> bytes!
150 template< typename T > class StridedArrayIterator
152 public:
153 typedef typename clone_const<T, unsigned char>::type internal_type;
155 StridedArrayIterator(int stride, T* ptr = 0) :
156 stride_(stride),
157 current_(reinterpret_cast<internal_type*>(ptr))
160 /// Copy from other StridedArrayIterator, plus given offset
161 StridedArrayIterator( StridedArrayIterator const& rSrc,
162 int offset ) :
163 stride_(rSrc.stride_),
164 current_(reinterpret_cast<internal_type*>(
165 reinterpret_cast<T*>(rSrc.current_)+offset))
168 void operator++() {current_ += stride_; }
169 void operator++(int) {current_ += stride_; }
170 void operator--() {current_ -= stride_; }
171 void operator--(int) {current_ -= stride_; }
172 void operator+=(int dy) {current_ += dy*stride_; }
173 void operator-=(int dy) {current_ -= dy*stride_; }
175 bool operator==(StridedArrayIterator const & rhs) const
176 { return (current_ == rhs.current_); }
178 bool operator!=(StridedArrayIterator const & rhs) const
179 { return (current_ != rhs.current_); }
181 bool operator<(StridedArrayIterator const & rhs) const
182 { return (current_ < rhs.current_); }
184 bool operator<=(StridedArrayIterator const & rhs) const
185 { return (current_ <= rhs.current_); }
187 bool operator>(StridedArrayIterator const & rhs) const
188 { return (current_ > rhs.current_); }
190 bool operator>=(StridedArrayIterator const & rhs) const
191 { return (current_ >= rhs.current_); }
193 int operator-(StridedArrayIterator const & rhs) const
194 { return (current_ - rhs.current_) / stride_; }
196 T* operator()() const
197 { return reinterpret_cast<T*>(current_); }
199 T* operator()(int d) const
200 { return reinterpret_cast<T*>(current_ + d*stride_); }
202 int stride_;
203 internal_type* current_;
206 /// template meta function: remove const qualifier from plain type
207 template <typename T> struct remove_const
209 typedef T type;
211 template <typename T> struct remove_const<const T>
213 typedef T type;
216 /// returns true, if given number is strictly less than 0
217 template< typename T > inline bool is_negative( T x )
219 return x < 0;
222 /// Overload for ints (branch-free)
223 inline bool is_negative( int x )
225 // force logic shift (result for signed shift right is undefined)
226 return static_cast<unsigned int>(x) >> (sizeof(int)*8-1);
229 /// Get bitmask for data at given intra-word position, for given bit depth
230 template< typename data_type, int bits_per_pixel, bool MsbFirst, typename difference_type > inline data_type get_mask( difference_type d )
232 BOOST_STATIC_ASSERT(bits_per_pixel > 0);
233 BOOST_STATIC_ASSERT(sizeof(data_type)*8 % bits_per_pixel == 0);
234 BOOST_STATIC_ASSERT(sizeof(data_type)*8 / bits_per_pixel > 1);
235 BOOST_STATIC_ASSERT(vigra::TypeTraits<data_type>::isPOD::asBool);
237 const unsigned int nIntraWordPositions( sizeof(data_type)*8 / bits_per_pixel );
239 // create bits_per_pixel 1s shift to intra-word position
240 return ((~(~0 << bits_per_pixel)) << bits_per_pixel*(MsbFirst ?
241 (nIntraWordPositions-1 - (d % nIntraWordPositions)) :
242 (d % nIntraWordPositions)));
245 template< int num_intraword_positions, int bits_per_pixel, bool MsbFirst, typename difference_type > inline difference_type get_shift( difference_type remainder )
247 return bits_per_pixel*(MsbFirst ?
248 (num_intraword_positions - 1 - remainder) :
249 remainder);
252 template< typename Datatype,
253 typename Valuetype,
254 int bits_per_pixel,
255 bool MsbFirst > class PackedPixelColumnIterator
257 public:
258 // no reference, no index_reference type here
259 typedef Datatype data_type;
260 typedef Valuetype value_type;
261 typedef int difference_type;
262 typedef image_traverser_tag iterator_category;
264 typedef typename remove_const<data_type>::type mask_type;
265 typedef data_type* pointer;
266 typedef StridedArrayIterator< data_type > MoveY;
268 enum {
269 /** The number of pixel within a single data_type value
271 num_intraword_positions=sizeof(data_type)*8/bits_per_pixel,
272 /** Bit mask for one pixel (least significant bits)
274 bit_mask=~(~0 << bits_per_pixel)
277 private:
278 MoveY y;
279 mask_type mask_;
280 difference_type shift_;
282 void inc()
284 ++y;
287 void dec()
289 --y;
292 bool equal( PackedPixelColumnIterator const & rhs ) const
294 return rhs.y == y;
297 bool less( PackedPixelColumnIterator const & rhs ) const
299 return y < rhs.y;
302 public:
303 PackedPixelColumnIterator() :
304 y(0),
305 mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ),
306 shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst, difference_type>(0) )
309 PackedPixelColumnIterator( const MoveY& base, difference_type remainder ) :
310 y(base),
311 mask_( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) ),
312 shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder) )
315 PackedPixelColumnIterator& operator+=( difference_type d )
317 y += d;
318 return *this;
321 PackedPixelColumnIterator& operator-=( difference_type d )
323 y -= d;
324 return *this;
327 PackedPixelColumnIterator operator+( difference_type d )
329 PackedPixelColumnIterator res(*this);
330 res += d;
331 return res;
334 PackedPixelColumnIterator operator-( difference_type d )
336 PackedPixelColumnIterator res(*this);
337 res -= d;
338 return res;
341 PackedPixelColumnIterator& operator++()
343 inc();
344 return *this;
347 PackedPixelColumnIterator& operator--()
349 dec();
350 return *this;
353 PackedPixelColumnIterator operator++(int)
355 PackedPixelColumnIterator res(*this);
356 res.inc();
357 return res;
360 PackedPixelColumnIterator operator--(int)
362 PackedPixelColumnIterator res(*this);
363 res.dec();
364 return res;
367 bool operator==(PackedPixelColumnIterator const & rhs) const
369 return equal( rhs );
372 bool operator!=(PackedPixelColumnIterator const & rhs) const
374 return !equal( rhs );
377 bool operator<(PackedPixelColumnIterator const & rhs) const
379 return less(rhs);
382 bool operator<=(PackedPixelColumnIterator const & rhs) const
384 return !less(rhs);
387 bool operator>(PackedPixelColumnIterator const & rhs) const
389 return rhs.less(*this);
392 bool operator>=(PackedPixelColumnIterator const & rhs) const
394 return !rhs.less(*this);
397 difference_type operator-(PackedPixelColumnIterator const & rhs) const
399 return y - rhs.y;
402 value_type get() const
404 // TODO(Q3): use traits to get unsigned type for data_type (if
405 // not already)
406 return static_cast<unsigned int>(*y() & mask_) >> shift_;
409 value_type get(difference_type d) const
411 // TODO(Q3): use traits to get unsigned type for data_type (if
412 // not already)
413 return static_cast<unsigned int>(*y(d) & mask_) >> shift_;
416 void set( value_type v ) const
418 const value_type pixel_value( (v << shift_) & mask_ );
419 *y() = (*y() & ~mask_) | pixel_value;
422 void set( value_type v, difference_type d ) const
424 const value_type pixel_value( (v << shift_) & mask_ );
425 *y(d) = (*y(d) & ~mask_) | pixel_value;
429 template< typename Datatype,
430 typename Valuetype,
431 int bits_per_pixel,
432 bool MsbFirst > class PackedPixelRowIterator
434 public:
435 // no reference, no index_reference type here
436 typedef Datatype data_type;
437 typedef Valuetype value_type;
438 typedef int difference_type;
439 typedef image_traverser_tag iterator_category;
441 typedef typename remove_const<data_type>::type mask_type;
442 typedef data_type* pointer;
444 enum {
445 /** The number of pixel within a single data_type value
447 num_intraword_positions=sizeof(data_type)*8/bits_per_pixel,
448 /** Bit mask for one pixel (least significant bits)
450 bit_mask=~(~0 << bits_per_pixel)
453 private:
454 pointer data_;
455 mask_type mask_;
456 difference_type remainder_;
458 void update_mask()
460 mask_ = get_mask<data_type, bits_per_pixel, MsbFirst>(remainder_);
463 void inc()
465 const difference_type newValue( remainder_ + 1 );
466 const difference_type data_offset( newValue / num_intraword_positions );
468 data_ += data_offset;
469 remainder_ = newValue % num_intraword_positions;
471 const mask_type shifted_mask(
472 MsbFirst ?
473 // TODO(Q3): use traits to get unsigned type for data_type
474 // (if not already)
475 static_cast<unsigned int>(mask_) >> bits_per_pixel :
476 mask_ << bits_per_pixel );
478 // data_offset is 0 for shifted mask, and 1 for wrapped-around mask
479 mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ?
480 bit_mask << bits_per_pixel*(num_intraword_positions-1) :
481 bit_mask);
484 void dec()
486 const difference_type newValue( remainder_ - 1 );
487 const bool isNegative( is_negative(newValue) );
488 const difference_type newRemainder( newValue % num_intraword_positions );
490 // calc data_ += newValue / num_intraword_positions;
491 // remainder_ = newRemainder;
492 // for newValue >= 0, and
493 // data_ += newValue / num_intraword_positions - 1;
494 // remainder_ = num_intraword_positions - newRemainder;
495 // (to force remainder_ to be positive).
496 // This is branch-free, if is_negative() is branch-free
497 const difference_type data_offset( newValue / num_intraword_positions - isNegative );
498 data_ += data_offset;
499 remainder_ = newRemainder + isNegative*num_intraword_positions;
501 const mask_type shifted_mask(
502 MsbFirst ?
503 mask_ << bits_per_pixel :
504 // TODO(Q3): use traits to get unsigned type for data_type
505 // (if not already)
506 static_cast<unsigned int>(mask_) >> bits_per_pixel );
508 // data_offset is 0 for shifted mask, and 1 for wrapped-around mask
509 mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ?
510 bit_mask :
511 bit_mask << bits_per_pixel*(num_intraword_positions-1));
514 bool equal( PackedPixelRowIterator const & rhs ) const
516 return rhs.data_ == data_ && rhs.remainder_ == remainder_;
519 bool less( PackedPixelRowIterator const & rhs ) const
521 return data_ == rhs.data_ ?
522 (remainder_ < rhs.remainder_) :
523 (data_ < rhs.data_);
526 public:
527 PackedPixelRowIterator() :
528 data_(0),
529 mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ),
530 remainder_(0)
533 explicit PackedPixelRowIterator( pointer base ) :
534 data_(base),
535 mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ),
536 remainder_(0)
539 PackedPixelRowIterator& operator+=( difference_type d )
541 const difference_type newValue( remainder_ + d );
543 data_ += newValue / num_intraword_positions;
544 remainder_ = newValue % num_intraword_positions;
545 update_mask();
547 return *this;
550 PackedPixelRowIterator& operator-=( difference_type d )
552 const difference_type newValue( remainder_ - d );
553 const bool isNegative( is_negative(newValue) );
554 const difference_type newRemainder( newValue % num_intraword_positions );
556 // calc data_ += newValue / num_intraword_positions;
557 // remainder_ = newRemainder;
558 // for newValue >= 0, and
559 // data_ += newValue / num_intraword_positions - 1;
560 // remainder_ = num_intraword_positions - newRemainder;
561 // (to force remainder_ to be positive).
562 // This is branch-free, if is_negative() is branch-free
563 data_ += newValue / num_intraword_positions - isNegative;
564 remainder_ = newRemainder + isNegative*(num_intraword_positions - 2*newRemainder);
565 update_mask();
567 return *this;
570 PackedPixelRowIterator operator+( difference_type d )
572 PackedPixelRowIterator res(*this);
573 res += d;
574 return res;
577 PackedPixelRowIterator operator-( difference_type d )
579 PackedPixelRowIterator res(*this);
580 res -= d;
581 return res;
584 PackedPixelRowIterator& operator++()
586 inc();
587 return *this;
590 PackedPixelRowIterator& operator--()
592 dec();
593 return *this;
596 PackedPixelRowIterator operator++(int)
598 PackedPixelRowIterator res(*this);
599 res.inc();
600 return res;
603 PackedPixelRowIterator operator--(int)
605 PackedPixelRowIterator res(*this);
606 res.dec();
607 return res;
610 bool operator==(PackedPixelRowIterator const & rhs) const
612 return equal( rhs );
615 bool operator!=(PackedPixelRowIterator const & rhs) const
617 return !equal( rhs );
620 bool operator<(PackedPixelRowIterator const & rhs) const
622 return less(rhs);
625 bool operator<=(PackedPixelRowIterator const & rhs) const
627 return !less(rhs);
630 bool operator>(PackedPixelRowIterator const & rhs) const
632 return rhs.less(*this);
635 bool operator>=(PackedPixelRowIterator const & rhs) const
637 return !rhs.less(*this);
640 difference_type operator-(PackedPixelRowIterator const & rhs) const
642 return (data_ - rhs.data_)*num_intraword_positions + (remainder_ - rhs.remainder_);
645 value_type get() const
647 // TODO(Q3): use traits to get unsigned type for data_type (if
648 // not already)
649 return static_cast<unsigned int>(*data_ & mask_) >>
650 get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder_);
653 value_type get(difference_type d) const
655 PackedPixelRowIterator tmp(*this);
656 tmp += d;
657 return tmp.get();
660 void set( value_type v ) const
662 const value_type pixel_value(
663 (v <<
664 get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder_))
665 & mask_ );
666 *data_ = (*data_ & ~mask_) | pixel_value;
669 void set( value_type v, difference_type d ) const
671 PackedPixelRowIterator tmp(*this);
672 tmp += d;
673 tmp.set(v);
677 template< typename Datatype,
678 typename Valuetype,
679 int bits_per_pixel,
680 bool MsbFirst > class PackedPixelIterator
682 public:
683 // no reference, no index_reference type here
684 typedef Datatype data_type;
685 typedef Valuetype value_type;
686 typedef vigra::Diff2D difference_type;
687 typedef image_traverser_tag iterator_category;
688 typedef PackedPixelRowIterator<data_type,
689 value_type,
690 bits_per_pixel,
691 MsbFirst> row_iterator;
692 typedef PackedPixelColumnIterator<data_type,
693 value_type,
694 bits_per_pixel,
695 MsbFirst> column_iterator;
697 typedef data_type* pointer;
698 typedef int MoveX;
699 typedef StridedArrayIterator< data_type > MoveY;
701 enum {
702 /** The number of pixel within a single data_type value
704 num_intraword_positions=sizeof(data_type)*8/bits_per_pixel,
705 /** Bit mask for one pixel (least significant bits)
707 bit_mask=~(~0 << bits_per_pixel)
710 // TODO(F2): direction of iteration (ImageIterator can be made to
711 // run backwards)
713 private:
714 pointer current() const
716 return y() + (x / num_intraword_positions);
719 pointer current(int dx, int dy) const
721 return y(dy) + ((x+dx)/num_intraword_positions);
724 bool equal(PackedPixelIterator const & rhs) const
726 return (x == rhs.x) && (y == rhs.y);
729 public:
730 PackedPixelIterator() :
731 x(0),
732 y(0)
735 PackedPixelIterator(pointer base, int ystride) :
736 x(0),
737 y(ystride,base)
740 bool operator==(PackedPixelIterator const & rhs) const
742 return equal(rhs);
745 bool operator!=(PackedPixelIterator const & rhs) const
747 return !equal(rhs);
750 difference_type operator-(PackedPixelIterator const & rhs) const
752 return difference_type(x - rhs.x, y - rhs.y);
755 MoveX x;
756 MoveY y;
758 PackedPixelIterator & operator+=(difference_type const & s)
760 x += s.x;
761 y += s.y;
762 return *this;
765 PackedPixelIterator & operator-=(difference_type const & s)
767 x -= s.x;
768 y -= s.y;
769 return *this;
772 PackedPixelIterator operator+(difference_type const & s) const
774 PackedPixelIterator ret(*this);
775 ret += s;
776 return ret;
779 PackedPixelIterator operator-(difference_type const & s) const
781 PackedPixelIterator ret(*this);
782 ret -= s;
783 return ret;
786 row_iterator rowIterator() const
788 return row_iterator(current());
791 column_iterator columnIterator() const
793 return column_iterator(MoveY(y,
794 x / num_intraword_positions),
795 x % num_intraword_positions);
798 value_type get() const
800 const int remainder( x() % num_intraword_positions );
802 // TODO(Q3): use traits to get unsigned type for data_type (if
803 // not already)
804 return (static_cast<unsigned int>(*current() &
805 get_mask<data_type, bits_per_pixel, MsbFirst>(remainder))
806 >> (MsbFirst ?
807 (num_intraword_positions - remainder) :
808 remainder));
811 value_type get(difference_type const & d) const
813 const int remainder( x(d.x) % num_intraword_positions );
815 // TODO(Q3): use traits to get unsigned type for data_type (if
816 // not already)
817 return (static_cast<unsigned int>(*current(d.x,d.y) &
818 get_mask<data_type, bits_per_pixel, MsbFirst>(remainder))
819 >> get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder));
822 void set( value_type v ) const
824 const int remainder( x() % num_intraword_positions );
825 const int mask( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) );
826 const value_type pixel_value(
827 (v <<
828 get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder))
829 & mask );
830 pointer p = current();
831 *p = (*p & ~mask) | pixel_value;
834 void set( value_type v, difference_type const & d ) const
836 const int remainder( x(d.x) % num_intraword_positions );
837 const int mask( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) );
838 const value_type pixel_value(
839 (v <<
840 get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder))
841 & mask );
842 pointer p = current(d.x,d.y);
843 *p = (*p & ~mask) | pixel_value;
848 /** Access (possibly packed-pixel) data via palette indirection
850 template< typename Valuetype, typename Datatype > class PaletteImageAccessor
852 public:
853 typedef Valuetype value_type;
854 typedef Datatype data_type;
855 typedef typename remove_const<data_type>::type count_type;
858 private:
859 const BitmapColor* palette;
860 count_type num_entries;
862 double norm( BitmapColor const& rLHS,
863 BitmapColor const& rRHS ) const
865 // convert RGBValue's linear space to a normed linear space
866 return sqrt(
867 vigra::sq(rLHS.GetRed()-rRHS.GetRed()) +
868 vigra::sq(rLHS.GetGreen()-rRHS.GetGreen()) +
869 vigra::sq(rLHS.GetBlue()-rRHS.GetBlue()) );
872 data_type find_best_match(value_type const& v) const
874 // TODO(F3): not generic!!!
875 const BitmapColor aTmpCol(v.red(),
876 v.green(),
877 v.blue());
879 // TODO(P3): use table-based/octree approach here!
880 const BitmapColor* best_entry;
881 const BitmapColor* palette_end( palette+num_entries );
882 if( (best_entry=std::find( palette, palette_end, aTmpCol)) != palette_end )
883 return best_entry-palette;
885 // TODO(F3): HACK. Need palette traits, and an error function
886 // here. We blatantly assume value_type is a normed linear
887 // space.
888 const BitmapColor* curr_entry( palette );
889 best_entry = curr_entry;
890 while( curr_entry != palette_end )
892 if( norm(*curr_entry,*best_entry) > norm(*curr_entry,aTmpCol) )
893 best_entry = curr_entry;
895 ++curr_entry;
898 return best_entry-palette;
901 value_type toCol( BitmapColor const& rCol ) const
903 return value_type(rCol.GetRed(),rCol.GetGreen(),rCol.GetBlue());
906 public:
907 PaletteImageAccessor() :
908 palette(0),
909 num_entries(0)
912 PaletteImageAccessor( const BitmapColor* pPalette,
913 data_type entries ) :
914 palette(pPalette),
915 num_entries(entries)
918 template< class Iterator >
919 value_type operator()(Iterator const& i) const { return toCol(palette[i.get()]); }
920 value_type operator()(data_type const* i) const { return toCol(palette[*i]); }
922 template< class Iterator, class Difference >
923 value_type operator()(Iterator const& i, Difference const& diff) const
925 return toCol(palette[i.get(diff)]);
928 template< typename V, class Iterator >
929 void set(V const& value, Iterator const& i) const
931 i.set(
932 find_best_match(
933 vigra::detail::RequiresExplicitCast<value_type>::cast(value) ));
936 template< typename V, class Iterator, class Difference >
937 void set(V const& value, Iterator const& i, Difference const& diff) const
939 i.set(
940 find_best_match(
941 vigra::detail::RequiresExplicitCast<value_type>::cast(value)),
942 diff );
949 class TestApp : public Application
951 public:
952 virtual void Main();
953 virtual USHORT Exception( USHORT nError );
956 class TestWindow : public Dialog
958 public:
959 TestWindow() : Dialog( (Window *) NULL )
961 SetText( OUString( "VIGRA test" ) );
962 SetSizePixel( Size( 1024, 1024 ) );
963 EnablePaint( true );
964 Show();
966 virtual ~TestWindow() {}
967 virtual void MouseButtonUp( const MouseEvent& /*rMEvt*/ )
969 //TODO: do something cool
970 EndDialog();
972 virtual void Paint( const Rectangle& rRect );
976 static basegfx::B2IPoint project( const basegfx::B2IPoint& rPoint )
978 const double angle_x = M_PI / 6.0;
979 const double angle_z = M_PI / 6.0;
981 // transform planar coordinates to 3d
982 double x = rPoint.getX();
983 double y = rPoint.getY();
984 //double z = 0;
986 // rotate around X axis
987 double x1 = x;
988 double y1 = y * cos( angle_x );
989 double z1 = y * sin( angle_x );
991 // rotate around Z axis
992 double x2 = x1 * cos( angle_z ) + y1 * sin( angle_z );
993 //double y2 = y1 * cos( angle_z ) - x1 * sin( angle_z );
994 double z2 = z1;
996 //return basegfx::B2IPoint( (sal_Int32)3*x2, (sal_Int32)3*z2 );
997 return basegfx::B2IPoint( (sal_Int32)(6*x2), (sal_Int32)(6*z2) );
1000 static basebmp::Color approachColor( const basebmp::Color& rFrom, const basebmp::Color& rTo )
1002 basebmp::Color aColor;
1003 UINT8 nDiff;
1004 // approach red
1005 if( rFrom.getRed() < rTo.getRed() )
1007 nDiff = rTo.getRed() - rFrom.getRed();
1008 aColor.setRed( rFrom.getRed() + ( nDiff < 10 ? nDiff : 10 ) );
1010 else if( rFrom.getRed() > rTo.getRed() )
1012 nDiff = rFrom.getRed() - rTo.getRed();
1013 aColor.setRed( rFrom.getRed() - ( nDiff < 10 ? nDiff : 10 ) );
1015 else
1016 aColor.setRed( rFrom.getRed() );
1018 // approach Green
1019 if( rFrom.getGreen() < rTo.getGreen() )
1021 nDiff = rTo.getGreen() - rFrom.getGreen();
1022 aColor.setGreen( rFrom.getGreen() + ( nDiff < 10 ? nDiff : 10 ) );
1024 else if( rFrom.getGreen() > rTo.getGreen() )
1026 nDiff = rFrom.getGreen() - rTo.getGreen();
1027 aColor.setGreen( rFrom.getGreen() - ( nDiff < 10 ? nDiff : 10 ) );
1029 else
1030 aColor.setGreen( rFrom.getGreen() );
1032 // approach blue
1033 if( rFrom.getBlue() < rTo.getBlue() )
1035 nDiff = rTo.getBlue() - rFrom.getBlue();
1036 aColor.setBlue( rFrom.getBlue() + ( nDiff < 10 ? nDiff : 10 ) );
1038 else if( rFrom.getBlue() > rTo.getBlue() )
1040 nDiff = rFrom.getBlue() - rTo.getBlue();
1041 aColor.setBlue( rFrom.getBlue() - ( nDiff < 10 ? nDiff : 10 ) );
1043 else
1044 aColor.setBlue( rFrom.getBlue() );
1046 return aColor;
1049 #define DELTA 5.0
1053 void TestWindow::Paint( const Rectangle& /*rRect*/ )
1055 basegfx::B2ISize aTestSize(1000,1000);
1056 basebmp::BitmapDeviceSharedPtr pDevice( basebmp::createBitmapDevice( aTestSize,
1057 false,
1058 basebmp::Format::THIRTYTWO_BIT_TC_MASK ));
1061 OUString aSvg;
1063 basegfx::B2DPolyPolygon aPoly;
1065 basegfx::tools::importFromSvgD( aPoly, OUString( "m0 0 h7 v7 h-7 z" ) );
1067 basegfx::tools::importFromSvgD( aPoly, OUString( "m2 2 h3 v3 h-3 z" ) );
1069 pDevice->fillPolyPolygon( aPoly,
1070 basebmp::Color(0xFFFFFFFF),
1071 basebmp::DrawMode_PAINT );
1075 basebmp::BitmapDeviceSharedPtr pMask( basebmp::createBitmapDevice( aTestSize,
1076 false,
1077 basebmp::Format::ONE_BIT_MSB_GREY ));
1079 const basegfx::B2IPoint aPt111(10,10);
1080 const basegfx::B2IPoint aPt222(0,10);
1081 const basebmp::Color aCol333(0xFFFFFFFF);
1082 pMask->drawLine( aPt111, aPt222, aCol333, basebmp::DrawMode_PAINT );
1085 OUString aSvg( "m 0 0 h5 l5 5 v5 h-5 l-5-5 z" );
1086 basegfx::B2DPolyPolygon aPoly;
1087 basegfx::tools::importFromSvgD( aPoly, aSvg );
1088 pMask->clear(basebmp::Color(0xFFFFFFFF));
1089 pMask->drawPolygon(
1090 aPoly.getB2DPolygon(0),
1091 basebmp::Color(0),
1092 basebmp::DrawMode_PAINT );
1094 basebmp::BitmapDeviceSharedPtr pSubsetDevice =
1095 basebmp::subsetBitmapDevice( pDevice,
1096 basegfx::B2IBox(3,3,7,7) );
1098 const basegfx::B2IPoint aPt1(0,0);
1099 const basegfx::B2IPoint aPt2(1,9);
1100 const basebmp::Color aCol(0xFFFFFFFF);
1101 pDevice->drawLine( aPt1, aPt2, aCol, basebmp::DrawMode_PAINT, pMask );
1105 const basebmp::Color aCol(0xFFFFFFFF);
1106 basegfx::B2DPolygon aRect = basegfx::tools::createPolygonFromRect(
1107 basegfx::B2DRange( 0,0,1001,1001 ));
1108 pDevice->drawPolygon( aRect, aCol, basebmp::DrawMode_PAINT );
1110 const basegfx::B2IPoint aPt1(0,0);
1111 const basegfx::B2IPoint aPt2(0,800);
1112 pDevice->drawLine( aPt1, aPt2, aCol, basebmp::DrawMode_PAINT );
1114 const basegfx::B2IPoint aPt3(0,1001);
1115 pDevice->drawLine( aPt1, aPt3, aCol, basebmp::DrawMode_PAINT );
1119 pDevice->clear(basebmp::Color(0));
1121 basegfx::B2IPoint aCenter( aTestSize.getX()/2,
1122 aTestSize.getY()/2 );
1123 //basegfx::B2IPoint aP1( aTestSize.getX()/48, 0), aP2( aTestSize.getX()/40, 0 ), aPoint;
1124 //basegfx::B2IPoint aP1( aTestSize.getX()/7, 0), aP2( aTestSize.getX()/6, 0 ), aPoint;
1125 //basegfx::B2IPoint aP1( aTestSize.getX()/5, 0), aP2( aTestSize.getX()/4, 0 ), aPoint;
1126 basegfx::B2IPoint aP1( aTestSize.getX()/12, 0), aP2( aTestSize.getX()/11, 0 ), aPoint;
1128 double sind = sin( DELTA*M_PI/180.0 );
1129 double cosd = cos( DELTA*M_PI/180.0 );
1130 double factor = 1 + (DELTA/1000.0);
1131 int n=0;
1132 basebmp::Color aLineColor( 0, 0, 0 );
1133 basebmp::Color aApproachColor( 0, 0, 200 );
1134 while ( aP2.getX() < aCenter.getX() && n++ < 680 )
1136 aLineColor = approachColor( aLineColor, aApproachColor );
1138 // switch aproach color
1139 if( aApproachColor == aLineColor )
1141 if( aApproachColor.getRed() )
1142 aApproachColor = basebmp::Color( 0, 0, 200 );
1143 else if( aApproachColor.getGreen() )
1144 aApproachColor = basebmp::Color( 200, 0, 0 );
1145 else
1146 aApproachColor = basebmp::Color( 0, 200, 0 );
1149 basegfx::B2DPolygon aPoly;
1150 aPoly.append( basegfx::B2DPoint(project( aP1 ) + aCenter) );
1151 aPoly.append( basegfx::B2DPoint(project( aP2 ) + aCenter) );
1152 pDevice->fillPolyPolygon(
1153 basegfx::tools::createAreaGeometry(
1154 aPoly,
1155 // std::max(1,n/30),
1156 // std::max(1,n/60),
1157 std::max(1,n/30),
1158 basegfx::B2DLINEJOIN_NONE),
1159 aLineColor,
1160 basebmp::DrawMode_PAINT);
1162 aPoint.setX( (int)((((double)aP1.getX())*cosd - ((double)aP1.getY())*sind)*factor) );
1163 aPoint.setY( (int)((((double)aP1.getY())*cosd + ((double)aP1.getX())*sind)*factor) );
1164 aP1 = aPoint;
1165 aPoint.setX( (int)((((double)aP2.getX())*cosd - ((double)aP2.getY())*sind)*factor) );
1166 aPoint.setY( (int)((((double)aP2.getY())*cosd + ((double)aP2.getX())*sind)*factor) );
1167 aP2 = aPoint;
1171 Bitmap aBitmap( Size(aTestSize.getX(),
1172 aTestSize.getY()), 24 );
1174 // Fill bitmap with generated content
1176 Bitmap::ScopedWriteAccess pWriteAccess( aBitmap );
1177 for( int y=0; y<aTestSize.getY(); ++y )
1178 for( int x=0; x<aTestSize.getX(); ++x )
1179 pWriteAccess->SetPixel(y,x,
1180 Color(pDevice->getPixelData(basegfx::B2IPoint(x,y))) );
1183 DrawBitmap( Point(), aBitmap );
1186 USHORT TestApp::Exception( USHORT nError )
1188 switch( nError & EXC_MAJORTYPE )
1190 case EXC_RSCNOTLOADED:
1191 Abort( "Error: could not load language resources.\nPlease check your installation.\n" );
1192 break;
1194 return 0;
1197 void TestApp::Main()
1199 //-------------------------------------------------
1200 // create the global service-manager
1201 //-------------------------------------------------
1202 uno::Reference< lang::XMultiServiceFactory > xFactory;
1205 uno::Reference< uno::XComponentContext > xCtx = ::cppu::defaultBootstrap_InitialComponentContext();
1206 xFactory = uno::Reference< lang::XMultiServiceFactory >( xCtx->getServiceManager(),
1207 uno::UNO_QUERY );
1208 if( xFactory.is() )
1209 ::comphelper::setProcessServiceFactory( xFactory );
1211 catch(const uno::Exception& )
1215 if( !xFactory.is() )
1217 OSL_TRACE( "Could not bootstrap UNO, installation must be in disorder. Exiting." );
1218 exit( 1 );
1221 // Create UCB (for backwards compatibility, in case some code still uses
1222 // plain createInstance w/o args directly to obtain an instance):
1223 ::ucb::UniversalContentBroker::create(
1224 comphelper::getProcessComponentContext() );
1226 TestWindow pWindow;
1227 pWindow.Execute();
1230 TestApp aDemoApp;
1232 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */