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: 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 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 > 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 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 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 179 void operator++() {current_ += stride_; } 180 void operator++(int) {current_ += stride_; } 181 void operator--() {current_ -= stride_; } 182 void operator--(int) {current_ -= stride_; } 183 void operator+=(int dy) {current_ += dy*stride_; } 184 void operator-=(int dy) {current_ -= dy*stride_; } 185 186 bool operator==(StridedArrayIterator const & rhs) const 187 { return (current_ == rhs.current_); } 188 189 bool operator!=(StridedArrayIterator const & rhs) const 190 { return (current_ != rhs.current_); } 191 192 bool operator<(StridedArrayIterator const & rhs) const 193 { return (current_ < rhs.current_); } 194 195 bool operator<=(StridedArrayIterator const & rhs) const 196 { return (current_ <= rhs.current_); } 197 198 bool operator>(StridedArrayIterator const & rhs) const 199 { return (current_ > rhs.current_); } 200 201 bool operator>=(StridedArrayIterator const & rhs) const 202 { return (current_ >= rhs.current_); } 203 204 int operator-(StridedArrayIterator const & rhs) const 205 { return (current_ - rhs.current_) / stride_; } 206 207 T* operator()() const 208 { return reinterpret_cast<T*>(current_); } 209 210 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 228 template< typename T > inline bool is_negative( T x ) 229 { 230 return x < 0; 231 } 232 233 /// Overload for ints (branch-free) 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 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 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 293 void inc() 294 { 295 ++y; 296 } 297 298 void dec() 299 { 300 --y; 301 } 302 303 bool equal( PackedPixelColumnIterator const & rhs ) const 304 { 305 return rhs.y == y; 306 } 307 308 bool less( PackedPixelColumnIterator const & rhs ) const 309 { 310 return y < rhs.y; 311 } 312 313 public: 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 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 326 PackedPixelColumnIterator& operator+=( difference_type d ) 327 { 328 y += d; 329 return *this; 330 } 331 332 PackedPixelColumnIterator& operator-=( difference_type d ) 333 { 334 y -= d; 335 return *this; 336 } 337 338 PackedPixelColumnIterator operator+( difference_type d ) 339 { 340 PackedPixelColumnIterator res(*this); 341 res += d; 342 return res; 343 } 344 345 PackedPixelColumnIterator operator-( difference_type d ) 346 { 347 PackedPixelColumnIterator res(*this); 348 res -= d; 349 return res; 350 } 351 352 PackedPixelColumnIterator& operator++() 353 { 354 inc(); 355 return *this; 356 } 357 358 PackedPixelColumnIterator& operator--() 359 { 360 dec(); 361 return *this; 362 } 363 364 PackedPixelColumnIterator operator++(int) 365 { 366 PackedPixelColumnIterator res(*this); 367 res.inc(); 368 return res; 369 } 370 371 PackedPixelColumnIterator operator--(int) 372 { 373 PackedPixelColumnIterator res(*this); 374 res.dec(); 375 return res; 376 } 377 378 bool operator==(PackedPixelColumnIterator const & rhs) const 379 { 380 return equal( rhs ); 381 } 382 383 bool operator!=(PackedPixelColumnIterator const & rhs) const 384 { 385 return !equal( rhs ); 386 } 387 388 bool operator<(PackedPixelColumnIterator const & rhs) const 389 { 390 return less(rhs); 391 } 392 393 bool operator<=(PackedPixelColumnIterator const & rhs) const 394 { 395 return !less(rhs); 396 } 397 398 bool operator>(PackedPixelColumnIterator const & rhs) const 399 { 400 return rhs.less(*this); 401 } 402 403 bool operator>=(PackedPixelColumnIterator const & rhs) const 404 { 405 return !rhs.less(*this); 406 } 407 408 difference_type operator-(PackedPixelColumnIterator const & rhs) const 409 { 410 return y - rhs.y; 411 } 412 413 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 420 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 427 void set( value_type v ) const 428 { 429 const value_type pixel_value( (v << shift_) & mask_ ); 430 *y() = (*y() & ~mask_) | pixel_value; 431 } 432 433 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 469 void update_mask() 470 { 471 mask_ = get_mask<data_type, bits_per_pixel, MsbFirst>(remainder_); 472 } 473 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 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 525 bool equal( PackedPixelRowIterator const & rhs ) const 526 { 527 return rhs.data_ == data_ && rhs.remainder_ == remainder_; 528 } 529 530 bool less( PackedPixelRowIterator const & rhs ) const 531 { 532 return data_ == rhs.data_ ? 533 (remainder_ < rhs.remainder_) : 534 (data_ < rhs.data_); 535 } 536 537 public: 538 PackedPixelRowIterator() : 539 data_(0), 540 mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ), 541 remainder_(0) 542 {} 543 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 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 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 581 PackedPixelRowIterator operator+( difference_type d ) 582 { 583 PackedPixelRowIterator res(*this); 584 res += d; 585 return res; 586 } 587 588 PackedPixelRowIterator operator-( difference_type d ) 589 { 590 PackedPixelRowIterator res(*this); 591 res -= d; 592 return res; 593 } 594 595 PackedPixelRowIterator& operator++() 596 { 597 inc(); 598 return *this; 599 } 600 601 PackedPixelRowIterator& operator--() 602 { 603 dec(); 604 return *this; 605 } 606 607 PackedPixelRowIterator operator++(int) 608 { 609 PackedPixelRowIterator res(*this); 610 res.inc(); 611 return res; 612 } 613 614 PackedPixelRowIterator operator--(int) 615 { 616 PackedPixelRowIterator res(*this); 617 res.dec(); 618 return res; 619 } 620 621 bool operator==(PackedPixelRowIterator const & rhs) const 622 { 623 return equal( rhs ); 624 } 625 626 bool operator!=(PackedPixelRowIterator const & rhs) const 627 { 628 return !equal( rhs ); 629 } 630 631 bool operator<(PackedPixelRowIterator const & rhs) const 632 { 633 return less(rhs); 634 } 635 636 bool operator<=(PackedPixelRowIterator const & rhs) const 637 { 638 return !less(rhs); 639 } 640 641 bool operator>(PackedPixelRowIterator const & rhs) const 642 { 643 return rhs.less(*this); 644 } 645 646 bool operator>=(PackedPixelRowIterator const & rhs) const 647 { 648 return !rhs.less(*this); 649 } 650 651 difference_type operator-(PackedPixelRowIterator const & rhs) const 652 { 653 return (data_ - rhs.data_)*num_intraword_positions + (remainder_ - rhs.remainder_); 654 } 655 656 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 664 value_type get(difference_type d) const 665 { 666 PackedPixelRowIterator tmp(*this); 667 tmp += d; 668 return tmp.get(); 669 } 670 671 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 680 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: 725 pointer current() const 726 { 727 return y() + (x / num_intraword_positions); 728 } 729 730 pointer current(int dx, int dy) const 731 { 732 return y(dy) + ((x+dx)/num_intraword_positions); 733 } 734 735 bool equal(PackedPixelIterator const & rhs) const 736 { 737 return (x == rhs.x) && (y == rhs.y); 738 } 739 740 public: 741 PackedPixelIterator() : 742 x(0), 743 y(0) 744 {} 745 746 PackedPixelIterator(pointer base, int ystride) : 747 x(0), 748 y(ystride,base) 749 {} 750 751 bool operator==(PackedPixelIterator const & rhs) const 752 { 753 return equal(rhs); 754 } 755 756 bool operator!=(PackedPixelIterator const & rhs) const 757 { 758 return !equal(rhs); 759 } 760 761 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 769 PackedPixelIterator & operator+=(difference_type const & s) 770 { 771 x += s.x; 772 y += s.y; 773 return *this; 774 } 775 776 PackedPixelIterator & operator-=(difference_type const & s) 777 { 778 x -= s.x; 779 y -= s.y; 780 return *this; 781 } 782 783 PackedPixelIterator operator+(difference_type const & s) const 784 { 785 PackedPixelIterator ret(*this); 786 ret += s; 787 return ret; 788 } 789 790 PackedPixelIterator operator-(difference_type const & s) const 791 { 792 PackedPixelIterator ret(*this); 793 ret -= s; 794 return ret; 795 } 796 797 row_iterator rowIterator() const 798 { 799 return row_iterator(current()); 800 } 801 802 column_iterator columnIterator() const 803 { 804 return column_iterator(MoveY(y, 805 x / num_intraword_positions), 806 x % num_intraword_positions); 807 } 808 809 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 822 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 833 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 845 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 873 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 883 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 912 value_type toCol( BitmapColor const& rCol ) const 913 { 914 return value_type(rCol.GetRed(),rCol.GetGreen(),rCol.GetBlue()); 915 } 916 917 public: 918 PaletteImageAccessor() : 919 palette(0), 920 num_entries(0) 921 {} 922 923 PaletteImageAccessor( const BitmapColor* pPalette, 924 data_type entries ) : 925 palette(pPalette), 926 num_entries(entries) 927 {} 928 929 template< class Iterator > 930 value_type operator()(Iterator const& i) const { return toCol(palette[i.get()]); } 931 value_type operator()(data_type const* i) const { return toCol(palette[*i]); } 932 933 template< class Iterator, class Difference > 934 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 > 940 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 > 948 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: 970 TestWindow() : Dialog( (Window *) NULL ) 971 { 972 SetText( rtl::OUString::createFromAscii( "VIGRA test" ) ); 973 SetSizePixel( Size( 1024, 1024 ) ); 974 EnablePaint( true ); 975 Show(); 976 } 977 virtual ~TestWindow() {} 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 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 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 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 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 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