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