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