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 // FIXME: in vigra 23 #if defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x580) 24 #include <math.h> // needed for fabs, hypot 25 #endif 26 #include "basebmp/bitmapdevice.hxx" 27 28 #include "basebmp/compositeiterator.hxx" 29 #include "basebmp/iteratortraits.hxx" 30 31 #include "basebmp/accessor.hxx" 32 #include "basebmp/accessortraits.hxx" 33 #include "basebmp/accessoradapters.hxx" 34 #include "basebmp/colorblendaccessoradapter.hxx" 35 36 #include "basebmp/color.hxx" 37 #include "basebmp/colormisc.hxx" 38 #include "basebmp/colortraits.hxx" 39 40 #include "basebmp/greylevelformats.hxx" 41 #include "basebmp/paletteformats.hxx" 42 #include "basebmp/rgbmaskpixelformats.hxx" 43 #include "basebmp/rgb24pixelformats.hxx" 44 45 #include "basebmp/scanlineformats.hxx" 46 #include "basebmp/fillimage.hxx" 47 #include "basebmp/scaleimage.hxx" 48 #include "basebmp/clippedlinerenderer.hxx" 49 #include "basebmp/polypolygonrenderer.hxx" 50 #include "basebmp/genericcolorimageaccessor.hxx" 51 52 #include "basebmp/tools.hxx" 53 #include "intconversion.hxx" 54 55 #include <rtl/alloc.h> 56 #include <rtl/memory.h> 57 #include <osl/diagnose.h> 58 59 #include <basegfx/tools/tools.hxx> 60 #include <basegfx/range/b2irange.hxx> 61 #include <basegfx/range/b2drange.hxx> 62 #include <basegfx/polygon/b2dpolygon.hxx> 63 #include <basegfx/polygon/b2dpolygontools.hxx> 64 #include <basegfx/polygon/b2dpolypolygontools.hxx> 65 #include <basegfx/point/b2ipoint.hxx> 66 #include <basegfx/vector/b2ivector.hxx> 67 68 #include <vigra/iteratortraits.hxx> 69 #include <vigra/rgbvalue.hxx> 70 #include <vigra/copyimage.hxx> 71 #include <vigra/tuple.hxx> 72 73 namespace vigra 74 { 75 76 // componentwise xor of an RGBValue (missing from rgbvalue.hxx) 77 template< class Value, unsigned int RedIndex, unsigned int BlueIndex, unsigned int GreenIndex > 78 inline RGBValue<Value, RedIndex, GreenIndex, BlueIndex> 79 operator^( RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& lhs, 80 RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& rhs ) 81 { 82 RGBValue<Value, RedIndex, GreenIndex, BlueIndex> res( 83 lhs[0] ^ rhs[0], 84 lhs[1] ^ rhs[1], 85 lhs[2] ^ rhs[2]); 86 return res; 87 } 88 } 89 90 namespace basebmp 91 { 92 93 namespace 94 { 95 /** Create the type for an accessor that takes the (mask,bitmap) 96 input value generated from a JoinImageAccessorAdapter, and 97 pipe that through a mask functor. 98 99 @tpl DestAccessor 100 Destination bitmap accessor 101 102 @tpl JoinedAccessor 103 Input accessor, is expected to generate a std::pair as the 104 value type 105 106 @tpl MaskFunctorMode 107 Either FastMask or NoFastMask, depending on whether the mask 108 is guaranteed to contain only 0s and 1s. 109 */ 110 template< class DestAccessor, 111 class JoinedAccessor, 112 bool polarity, 113 typename MaskFunctorMode > struct masked_input_splitting_accessor 114 { 115 typedef BinarySetterFunctionAccessorAdapter< 116 DestAccessor, 117 BinaryFunctorSplittingWrapper< 118 typename outputMaskFunctorSelector< 119 typename JoinedAccessor::value_type::first_type, 120 typename JoinedAccessor::value_type::second_type, 121 polarity, 122 MaskFunctorMode >::type > > type; 123 }; 124 125 126 127 // Actual BitmapDevice implementation (templatized by accessor and iterator) 128 //-------------------------------------------------------------------------- 129 130 /** Implementation of the BitmapDevice interface 131 132 @tpl DestIterator 133 Iterator to access bitmap memory 134 135 @tpl RawAccessor 136 Raw accessor, to access pixel values directly 137 138 @tpl AccessorSelector 139 Accessor adapter selector, which, when applying the nested 140 template metafunction wrap_accessor to one of the raw bitmap 141 accessors, yields a member type named 'type', which is a 142 wrapped accessor that map color values. 143 144 @tpl Masks 145 Traits template, containing nested traits 146 clipmask_format_traits and alphamask_format_traits, which 147 determine what specialized formats are to be used for clip and 148 alpha masks. With those mask formats, clipping and alpha 149 blending is handled natively. 150 */ 151 template< class DestIterator, 152 class RawAccessor, 153 class AccessorSelector, 154 class Masks > class BitmapRenderer : 155 public BitmapDevice 156 { 157 public: 158 typedef DestIterator dest_iterator_type; 159 typedef RawAccessor raw_accessor_type; 160 typedef AccessorSelector accessor_selector; 161 162 typedef typename Masks::clipmask_format_traits::iterator_type mask_iterator_type; 163 typedef typename Masks::clipmask_format_traits::raw_accessor_type mask_rawaccessor_type; 164 typedef typename Masks::clipmask_format_traits::accessor_selector mask_accessorselector_type; 165 166 typedef typename Masks::alphamask_format_traits::iterator_type alphamask_iterator_type; 167 typedef typename Masks::alphamask_format_traits::raw_accessor_type alphamask_rawaccessor_type; 168 typedef typename Masks::alphamask_format_traits::accessor_selector alphamask_accessorselector_type; 169 170 typedef typename AccessorSelector::template wrap_accessor< 171 raw_accessor_type >::type dest_accessor_type; 172 173 typedef AccessorTraits< dest_accessor_type > accessor_traits; 174 typedef CompositeIterator2D< dest_iterator_type, 175 mask_iterator_type > composite_iterator_type; 176 typedef CompositeIterator2D< vigra::Diff2D, 177 vigra::Diff2D > generic_composite_iterator_type; 178 179 typedef BitmapRenderer<mask_iterator_type, 180 mask_rawaccessor_type, 181 mask_accessorselector_type, 182 Masks> mask_bitmap_type; 183 typedef BitmapRenderer<alphamask_iterator_type, 184 alphamask_rawaccessor_type, 185 alphamask_accessorselector_type, 186 Masks> alphamask_bitmap_type; 187 188 // ------------------------------------------------------- 189 190 typedef AccessorTraits< raw_accessor_type > raw_accessor_traits; 191 typedef typename uInt32Converter< 192 typename raw_accessor_type::value_type>::to to_uint32_functor; 193 194 // ------------------------------------------------------- 195 196 typedef typename raw_accessor_traits::xor_accessor raw_xor_accessor_type; 197 typedef AccessorTraits<raw_xor_accessor_type> raw_xor_accessor_traits; 198 typedef typename accessor_selector::template wrap_accessor< 199 raw_xor_accessor_type >::type xor_accessor_type; 200 typedef AccessorTraits<xor_accessor_type> xor_accessor_traits; 201 202 // ------------------------------------------------------- 203 204 typedef typename raw_accessor_traits::template masked_accessor< 205 mask_rawaccessor_type, 206 dest_iterator_type, 207 mask_iterator_type, 208 Masks::clipmask_polarity>::type raw_maskedaccessor_type; 209 typedef typename accessor_selector::template wrap_accessor< 210 raw_maskedaccessor_type >::type masked_accessor_type; 211 typedef typename AccessorTraits< 212 raw_maskedaccessor_type>::xor_accessor raw_maskedxor_accessor_type; 213 typedef typename accessor_selector::template wrap_accessor< 214 raw_maskedxor_accessor_type >::type masked_xoraccessor_type; 215 216 // ------------------------------------------------------- 217 218 // ((iter,mask),mask) special case (e.g. for clipped 219 // drawMaskedColor()) 220 typedef AccessorTraits< raw_maskedaccessor_type > raw_maskedaccessor_traits; 221 typedef typename raw_maskedaccessor_traits::template masked_accessor< 222 mask_rawaccessor_type, 223 composite_iterator_type, 224 mask_iterator_type, 225 Masks::clipmask_polarity>::type raw_maskedmask_accessor_type; 226 227 typedef CompositeIterator2D< 228 composite_iterator_type, 229 mask_iterator_type> composite_composite_mask_iterator_type; 230 231 // ------------------------------------------------------- 232 233 typedef ConstantColorBlendSetterAccessorAdapter< 234 dest_accessor_type, 235 typename alphamask_rawaccessor_type::value_type, 236 Masks::alphamask_polarity> colorblend_accessor_type; 237 typedef AccessorTraits<colorblend_accessor_type> colorblend_accessor_traits; 238 typedef typename colorblend_accessor_traits::template masked_accessor< 239 mask_rawaccessor_type, 240 dest_iterator_type, 241 mask_iterator_type, 242 Masks::clipmask_polarity>::type masked_colorblend_accessor_type; 243 244 // ------------------------------------------------------- 245 246 typedef ConstantColorBlendSetterAccessorAdapter< 247 dest_accessor_type, 248 Color, 249 Masks::alphamask_polarity> colorblend_generic_accessor_type; 250 typedef AccessorTraits<colorblend_generic_accessor_type> colorblend_generic_accessor_traits; 251 typedef typename colorblend_generic_accessor_traits::template masked_accessor< 252 mask_rawaccessor_type, 253 dest_iterator_type, 254 mask_iterator_type, 255 Masks::clipmask_polarity>::type masked_colorblend_generic_accessor_type; 256 257 // ------------------------------------------------------- 258 259 typedef JoinImageAccessorAdapter< dest_accessor_type, 260 mask_rawaccessor_type > joined_image_accessor_type; 261 typedef JoinImageAccessorAdapter< GenericColorImageAccessor, 262 GenericColorImageAccessor > joined_generic_image_accessor_type; 263 264 // ------------------------------------------------------- 265 266 dest_iterator_type maBegin; 267 typename accessor_traits::color_lookup maColorLookup; 268 to_uint32_functor maToUInt32Converter; 269 dest_accessor_type maAccessor; 270 colorblend_accessor_type maColorBlendAccessor; 271 colorblend_generic_accessor_type maGenericColorBlendAccessor; 272 raw_accessor_type maRawAccessor; 273 xor_accessor_type maXorAccessor; 274 raw_xor_accessor_type maRawXorAccessor; 275 masked_accessor_type maMaskedAccessor; 276 masked_colorblend_accessor_type maMaskedColorBlendAccessor; 277 masked_colorblend_generic_accessor_type maGenericMaskedColorBlendAccessor; 278 masked_xoraccessor_type maMaskedXorAccessor; 279 raw_maskedaccessor_type maRawMaskedAccessor; 280 raw_maskedxor_accessor_type maRawMaskedXorAccessor; 281 raw_maskedmask_accessor_type maRawMaskedMaskAccessor; 282 283 // ------------------------------------------------------- 284 285 BitmapRenderer( const basegfx::B2IRange& rBounds, 286 sal_Int32 nScanlineFormat, 287 sal_Int32 nScanlineStride, 288 sal_uInt8* pFirstScanline, 289 dest_iterator_type begin, 290 raw_accessor_type rawAccessor, 291 dest_accessor_type accessor, 292 const RawMemorySharedArray& rMem, 293 const PaletteMemorySharedVector& rPalette ) : 294 BitmapDevice( rBounds, nScanlineFormat, 295 nScanlineStride, pFirstScanline, rMem, rPalette ), 296 maBegin( begin ), 297 maColorLookup(), 298 maToUInt32Converter(), 299 maAccessor( accessor ), 300 maColorBlendAccessor( accessor ), 301 maGenericColorBlendAccessor( accessor ), 302 maRawAccessor( rawAccessor ), 303 maXorAccessor( accessor ), 304 maRawXorAccessor( rawAccessor ), 305 maMaskedAccessor( accessor ), 306 maMaskedColorBlendAccessor( maColorBlendAccessor ), 307 maGenericMaskedColorBlendAccessor( maGenericColorBlendAccessor ), 308 maMaskedXorAccessor( accessor ), 309 maRawMaskedAccessor( rawAccessor ), 310 maRawMaskedXorAccessor( rawAccessor ), 311 maRawMaskedMaskAccessor( rawAccessor ) 312 {} 313 314 private: 315 boost::shared_ptr<BitmapRenderer> getCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const 316 { 317 return boost::dynamic_pointer_cast< BitmapRenderer >( bmp ); 318 } 319 320 virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const 321 { 322 // TODO(P1): dynamic_cast usually called twice for 323 // compatible formats 324 return getCompatibleBitmap(bmp).get() != NULL; 325 } 326 327 boost::shared_ptr<mask_bitmap_type> getCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const 328 { 329 boost::shared_ptr<mask_bitmap_type> pMask( boost::dynamic_pointer_cast<mask_bitmap_type>( bmp )); 330 331 if( !pMask ) 332 return pMask; 333 334 if( pMask->getSize() != getSize() ) 335 pMask.reset(); 336 337 return pMask; 338 } 339 340 virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const 341 { 342 // TODO(P1): dynamic_cast usually called twice for 343 // compatible formats 344 return boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ).get() != NULL; 345 } 346 347 boost::shared_ptr<alphamask_bitmap_type> getCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const 348 { 349 return boost::dynamic_pointer_cast<alphamask_bitmap_type>( bmp ); 350 } 351 352 virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const 353 { 354 // TODO(P1): dynamic_cast usually called twice for 355 // compatible formats 356 return getCompatibleAlphaMask( bmp ).get() != NULL; 357 } 358 359 virtual void clear_i( Color fillColor, 360 const basegfx::B2IRange& rBounds ) 361 { 362 fillImage(destIterRange(maBegin, 363 maRawAccessor, 364 rBounds), 365 maColorLookup( 366 maAccessor, 367 fillColor) ); 368 } 369 370 virtual void setPixel_i( const basegfx::B2IPoint& rPt, 371 Color pixelColor, 372 DrawMode drawMode ) 373 { 374 const DestIterator pixel( maBegin + 375 vigra::Diff2D(rPt.getX(), 376 rPt.getY()) ); 377 if( drawMode == DrawMode_XOR ) 378 maXorAccessor.set( pixelColor, 379 pixel ); 380 else 381 maAccessor.set( pixelColor, 382 pixel ); 383 } 384 385 virtual void setPixel_i( const basegfx::B2IPoint& rPt, 386 Color pixelColor, 387 DrawMode drawMode, 388 const BitmapDeviceSharedPtr& rClip ) 389 { 390 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) ); 391 OSL_ASSERT( pMask ); 392 393 const vigra::Diff2D offset(rPt.getX(), 394 rPt.getY()); 395 396 const composite_iterator_type aIter( 397 maBegin + offset, 398 pMask->maBegin + offset ); 399 400 if( drawMode == DrawMode_XOR ) 401 maMaskedXorAccessor.set( pixelColor, 402 aIter ); 403 else 404 maMaskedAccessor.set( pixelColor, 405 aIter ); 406 } 407 408 virtual Color getPixel_i(const basegfx::B2IPoint& rPt ) 409 { 410 const DestIterator pixel( maBegin + 411 vigra::Diff2D(rPt.getX(), 412 rPt.getY()) ); 413 return maAccessor(pixel); 414 } 415 416 virtual sal_uInt32 getPixelData_i( const basegfx::B2IPoint& rPt ) 417 { 418 const DestIterator pixel( maBegin + 419 vigra::Diff2D(rPt.getX(), 420 rPt.getY()) ); 421 return maToUInt32Converter(maRawAccessor(pixel)); 422 } 423 424 template< typename Iterator, typename Col, typename RawAcc > 425 void implRenderLine2( const basegfx::B2IPoint& rPt1, 426 const basegfx::B2IPoint& rPt2, 427 const basegfx::B2IRange& rBounds, 428 Col col, 429 const Iterator& begin, 430 const RawAcc& rawAcc ) 431 { 432 renderClippedLine( rPt1, 433 rPt2, 434 rBounds, 435 col, 436 begin, 437 rawAcc ); 438 } 439 440 template< typename Iterator, typename Accessor, typename RawAcc > 441 void implRenderLine( const basegfx::B2IPoint& rPt1, 442 const basegfx::B2IPoint& rPt2, 443 const basegfx::B2IRange& rBounds, 444 Color col, 445 const Iterator& begin, 446 const Accessor& acc, 447 const RawAcc& rawAcc ) 448 { 449 implRenderLine2( rPt1,rPt2,rBounds, 450 maColorLookup( acc, 451 col ), 452 begin, 453 rawAcc ); 454 } 455 456 template< typename Iterator, typename RawAcc, typename XorAcc > 457 void implDrawLine( const basegfx::B2IPoint& rPt1, 458 const basegfx::B2IPoint& rPt2, 459 const basegfx::B2IRange& rBounds, 460 Color col, 461 const Iterator& begin, 462 const RawAcc& rawAcc, 463 const XorAcc& xorAcc, 464 DrawMode drawMode ) 465 { 466 if( drawMode == DrawMode_XOR ) 467 implRenderLine( rPt1, rPt2, rBounds, col, 468 begin, maAccessor, xorAcc ); 469 else 470 implRenderLine( rPt1, rPt2, rBounds, col, 471 begin, maAccessor, rawAcc ); 472 } 473 474 virtual void drawLine_i(const basegfx::B2IPoint& rPt1, 475 const basegfx::B2IPoint& rPt2, 476 const basegfx::B2IRange& rBounds, 477 Color lineColor, 478 DrawMode drawMode ) 479 { 480 implDrawLine(rPt1,rPt2,rBounds,lineColor, 481 maBegin, 482 maRawAccessor,maRawXorAccessor,drawMode); 483 } 484 485 composite_iterator_type getMaskedIter( const BitmapDeviceSharedPtr& rClip ) const 486 { 487 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) ); 488 OSL_ASSERT( pMask ); 489 490 return composite_iterator_type( maBegin, 491 pMask->maBegin ); 492 } 493 494 virtual void drawLine_i(const basegfx::B2IPoint& rPt1, 495 const basegfx::B2IPoint& rPt2, 496 const basegfx::B2IRange& rBounds, 497 Color lineColor, 498 DrawMode drawMode, 499 const BitmapDeviceSharedPtr& rClip ) 500 { 501 implDrawLine(rPt1,rPt2,rBounds,lineColor, 502 getMaskedIter(rClip), 503 maRawMaskedAccessor, 504 maRawMaskedXorAccessor,drawMode); 505 } 506 507 template< typename Iterator, typename RawAcc > 508 void implDrawPolygon( const basegfx::B2DPolygon& rPoly, 509 const basegfx::B2IRange& rBounds, 510 Color col, 511 const Iterator& begin, 512 const RawAcc& acc ) 513 { 514 basegfx::B2DPolygon aPoly( rPoly ); 515 if( rPoly.areControlPointsUsed() ) 516 aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly ); 517 518 const typename dest_iterator_type::value_type colorIndex( maColorLookup( 519 maAccessor, 520 col)); 521 const sal_uInt32 nVertices( aPoly.count() ); 522 for( sal_uInt32 i=1; i<nVertices; ++i ) 523 implRenderLine2( basegfx::fround(aPoly.getB2DPoint(i-1)), 524 basegfx::fround(aPoly.getB2DPoint(i)), 525 rBounds, 526 colorIndex, 527 begin, 528 acc ); 529 530 if( nVertices > 1 && aPoly.isClosed() ) 531 implRenderLine2( basegfx::fround(aPoly.getB2DPoint(nVertices-1)), 532 basegfx::fround(aPoly.getB2DPoint(0)), 533 rBounds, 534 colorIndex, 535 begin, 536 acc ); 537 } 538 539 virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly, 540 const basegfx::B2IRange& rBounds, 541 Color lineColor, 542 DrawMode drawMode ) 543 { 544 if( drawMode == DrawMode_XOR ) 545 implDrawPolygon( rPoly, rBounds, lineColor, 546 maBegin, 547 maRawXorAccessor ); 548 else 549 implDrawPolygon( rPoly, rBounds, lineColor, 550 maBegin, 551 maRawAccessor ); 552 } 553 554 virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly, 555 const basegfx::B2IRange& rBounds, 556 Color lineColor, 557 DrawMode drawMode, 558 const BitmapDeviceSharedPtr& rClip ) 559 { 560 if( drawMode == DrawMode_XOR ) 561 implDrawPolygon( rPoly, rBounds, lineColor, 562 getMaskedIter(rClip), 563 maRawMaskedXorAccessor ); 564 else 565 implDrawPolygon( rPoly, rBounds, lineColor, 566 getMaskedIter(rClip), 567 maRawMaskedAccessor ); 568 } 569 570 template< typename Iterator, typename RawAcc > 571 void implFillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly, 572 Color col, 573 const Iterator& begin, 574 const RawAcc& acc, 575 const basegfx::B2IRange& rBounds ) 576 { 577 basegfx::B2DPolyPolygon aPoly( rPoly ); 578 if( rPoly.areControlPointsUsed() ) 579 aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly ); 580 581 renderClippedPolyPolygon( begin, 582 acc, 583 maColorLookup( maAccessor, 584 col), 585 rBounds, 586 aPoly, 587 basegfx::FillRule_EVEN_ODD ); 588 } 589 590 virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly, 591 Color fillColor, 592 DrawMode drawMode, 593 const basegfx::B2IRange& rBounds ) 594 { 595 if( drawMode == DrawMode_XOR ) 596 implFillPolyPolygon( rPoly, fillColor, 597 maBegin, 598 maRawXorAccessor, 599 rBounds ); 600 else 601 implFillPolyPolygon( rPoly, fillColor, 602 maBegin, 603 maRawAccessor, 604 rBounds ); 605 } 606 607 virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly, 608 Color fillColor, 609 DrawMode drawMode, 610 const basegfx::B2IRange& rBounds, 611 const BitmapDeviceSharedPtr& rClip ) 612 { 613 if( drawMode == DrawMode_XOR ) 614 implFillPolyPolygon( rPoly, fillColor, 615 getMaskedIter(rClip), 616 maRawMaskedXorAccessor, 617 rBounds ); 618 else 619 implFillPolyPolygon( rPoly, fillColor, 620 getMaskedIter(rClip), 621 maRawMaskedAccessor, 622 rBounds ); 623 } 624 625 template< typename Iterator, typename RawAcc > 626 void implDrawBitmap(const BitmapDeviceSharedPtr& rSrcBitmap, 627 const basegfx::B2IRange& rSrcRect, 628 const basegfx::B2IRange& rDstRect, 629 const Iterator& begin, 630 const RawAcc& acc) 631 { 632 boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) ); 633 OSL_ASSERT( pSrcBmp ); 634 635 scaleImage( 636 srcIterRange(pSrcBmp->maBegin, 637 pSrcBmp->maRawAccessor, 638 rSrcRect), 639 destIterRange(begin, 640 acc, 641 rDstRect), 642 rSrcBitmap.get() == this ); 643 } 644 645 template< typename Iterator, typename Acc > 646 void implDrawBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap, 647 const basegfx::B2IRange& rSrcRect, 648 const basegfx::B2IRange& rDstRect, 649 const Iterator& begin, 650 const Acc& acc) 651 { 652 GenericColorImageAccessor aSrcAcc( rSrcBitmap ); 653 654 scaleImage( 655 srcIterRange(vigra::Diff2D(), 656 aSrcAcc, 657 rSrcRect), 658 destIterRange(begin, 659 acc, 660 rDstRect)); 661 } 662 663 virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap, 664 const basegfx::B2IRange& rSrcRect, 665 const basegfx::B2IRange& rDstRect, 666 DrawMode drawMode ) 667 { 668 if( isCompatibleBitmap( rSrcBitmap ) ) 669 { 670 if( drawMode == DrawMode_XOR ) 671 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect, 672 maBegin, 673 maRawXorAccessor); 674 else 675 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect, 676 maBegin, 677 maRawAccessor); 678 } 679 else 680 { 681 if( drawMode == DrawMode_XOR ) 682 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect, 683 maBegin, 684 maXorAccessor); 685 else 686 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect, 687 maBegin, 688 maAccessor); 689 } 690 } 691 692 virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap, 693 const basegfx::B2IRange& rSrcRect, 694 const basegfx::B2IRange& rDstRect, 695 DrawMode drawMode, 696 const BitmapDeviceSharedPtr& rClip ) 697 { 698 if( isCompatibleBitmap( rSrcBitmap ) ) 699 { 700 if( drawMode == DrawMode_XOR ) 701 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect, 702 getMaskedIter(rClip), 703 maRawMaskedXorAccessor); 704 else 705 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect, 706 getMaskedIter(rClip), 707 maRawMaskedAccessor); 708 } 709 else 710 { 711 if( drawMode == DrawMode_XOR ) 712 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect, 713 getMaskedIter(rClip), 714 maMaskedXorAccessor); 715 else 716 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect, 717 getMaskedIter(rClip), 718 maMaskedAccessor); 719 } 720 } 721 722 virtual void drawMaskedColor_i(Color aSrcColor, 723 const BitmapDeviceSharedPtr& rAlphaMask, 724 const basegfx::B2IRange& rSrcRect, 725 const basegfx::B2IPoint& rDstPoint ) 726 { 727 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) ); 728 boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) ); 729 730 if( pAlpha ) 731 { 732 maColorBlendAccessor.setColor( aSrcColor ); 733 734 vigra::copyImage( srcIterRange(pAlpha->maBegin, 735 pAlpha->maRawAccessor, 736 rSrcRect), 737 destIter(maBegin, 738 maColorBlendAccessor, 739 rDstPoint) ); 740 } 741 else if( pMask ) 742 { 743 const composite_iterator_type aBegin( 744 maBegin + vigra::Diff2D(rDstPoint.getX(), 745 rDstPoint.getY()), 746 pMask->maBegin + topLeft(rSrcRect) ); 747 748 fillImage(aBegin, 749 aBegin + vigra::Diff2D(rSrcRect.getWidth(), 750 rSrcRect.getHeight()), 751 maRawMaskedAccessor, 752 maColorLookup( 753 maAccessor, 754 aSrcColor) ); 755 } 756 else 757 { 758 GenericColorImageAccessor aSrcAcc( rAlphaMask ); 759 maGenericColorBlendAccessor.setColor( aSrcColor ); 760 761 vigra::copyImage( srcIterRange(vigra::Diff2D(), 762 aSrcAcc, 763 rSrcRect), 764 destIter(maBegin, 765 maGenericColorBlendAccessor, 766 rDstPoint) ); 767 } 768 } 769 770 virtual void drawMaskedColor_i(Color aSrcColor, 771 const BitmapDeviceSharedPtr& rAlphaMask, 772 const basegfx::B2IRange& rSrcRect, 773 const basegfx::B2IPoint& rDstPoint, 774 const BitmapDeviceSharedPtr& rClip ) 775 { 776 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) ); 777 boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) ); 778 779 if( pAlpha ) 780 { 781 const composite_iterator_type aBegin( getMaskedIter(rClip) ); 782 maMaskedColorBlendAccessor.get1stWrappedAccessor().setColor( 783 aSrcColor ); 784 785 vigra::copyImage( srcIterRange(pAlpha->maBegin, 786 pAlpha->maRawAccessor, 787 rSrcRect), 788 destIter(aBegin, 789 maMaskedColorBlendAccessor, 790 rDstPoint) ); 791 } 792 else if( pMask ) 793 { 794 boost::shared_ptr<mask_bitmap_type> pClipMask( getCompatibleClipMask(rClip) ); 795 OSL_ASSERT( pClipMask ); 796 797 // setup a ((iter,mask),clipMask) composite composite 798 // iterator, to pass both masks (clip and alpha mask) 799 // to the algorithm 800 const composite_composite_mask_iterator_type aBegin( 801 composite_iterator_type( 802 maBegin + vigra::Diff2D(rDstPoint.getX(), 803 rDstPoint.getY()), 804 pMask->maBegin + topLeft(rSrcRect)), 805 pClipMask->maBegin + vigra::Diff2D(rDstPoint.getX(), 806 rDstPoint.getY()) ); 807 808 fillImage(aBegin, 809 aBegin + vigra::Diff2D(rSrcRect.getWidth(), 810 rSrcRect.getHeight()), 811 maRawMaskedMaskAccessor, 812 maColorLookup( 813 maAccessor, 814 aSrcColor) ); 815 } 816 else 817 { 818 GenericColorImageAccessor aSrcAcc( rAlphaMask ); 819 const composite_iterator_type aBegin( getMaskedIter(rClip) ); 820 maGenericMaskedColorBlendAccessor.get1stWrappedAccessor().setColor( 821 aSrcColor ); 822 823 vigra::copyImage( srcIterRange(vigra::Diff2D(), 824 aSrcAcc, 825 rSrcRect), 826 destIter(aBegin, 827 maGenericMaskedColorBlendAccessor, 828 rDstPoint) ); 829 } 830 } 831 832 template< typename Iterator, typename Acc > 833 void implDrawMaskedBitmap(const BitmapDeviceSharedPtr& rSrcBitmap, 834 const BitmapDeviceSharedPtr& rMask, 835 const basegfx::B2IRange& rSrcRect, 836 const basegfx::B2IRange& rDstRect, 837 const Iterator& begin, 838 const Acc& acc) 839 { 840 boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) ); 841 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rMask) ); 842 OSL_ASSERT( pMask && pSrcBmp ); 843 844 scaleImage( 845 srcIterRange(composite_iterator_type( 846 pSrcBmp->maBegin, 847 pMask->maBegin), 848 joined_image_accessor_type( 849 pSrcBmp->maAccessor, 850 pMask->maRawAccessor), 851 rSrcRect), 852 destIterRange(begin, 853 typename masked_input_splitting_accessor< 854 Acc, 855 joined_image_accessor_type, 856 Masks::clipmask_polarity, 857 FastMask >::type(acc), 858 rDstRect), 859 rSrcBitmap.get() == this); 860 } 861 862 template< typename Iterator, typename Acc > 863 void implDrawMaskedBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap, 864 const BitmapDeviceSharedPtr& rMask, 865 const basegfx::B2IRange& rSrcRect, 866 const basegfx::B2IRange& rDstRect, 867 const Iterator& begin, 868 const Acc& acc) 869 { 870 GenericColorImageAccessor aSrcAcc( rSrcBitmap ); 871 GenericColorImageAccessor aMaskAcc( rMask ); 872 873 const vigra::Diff2D aTopLeft(rSrcRect.getMinX(), 874 rSrcRect.getMinY()); 875 const vigra::Diff2D aBottomRight(rSrcRect.getMaxX(), 876 rSrcRect.getMaxY()); 877 scaleImage( 878 vigra::make_triple( 879 generic_composite_iterator_type( 880 aTopLeft,aTopLeft), 881 generic_composite_iterator_type( 882 aBottomRight,aBottomRight), 883 joined_generic_image_accessor_type( 884 aSrcAcc, 885 aMaskAcc)), 886 destIterRange(begin, 887 typename masked_input_splitting_accessor< 888 Acc, 889 joined_generic_image_accessor_type, 890 Masks::clipmask_polarity, 891 NoFastMask >::type(acc), 892 rDstRect)); 893 } 894 895 virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap, 896 const BitmapDeviceSharedPtr& rMask, 897 const basegfx::B2IRange& rSrcRect, 898 const basegfx::B2IRange& rDstRect, 899 DrawMode drawMode ) 900 { 901 if( isCompatibleClipMask(rMask) && 902 isCompatibleBitmap(rSrcBitmap) ) 903 { 904 if( drawMode == DrawMode_XOR ) 905 implDrawMaskedBitmap(rSrcBitmap, rMask, 906 rSrcRect, rDstRect, 907 maBegin, 908 maXorAccessor); 909 else 910 implDrawMaskedBitmap(rSrcBitmap, rMask, 911 rSrcRect, rDstRect, 912 maBegin, 913 maAccessor); 914 } 915 else 916 { 917 if( drawMode == DrawMode_XOR ) 918 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask, 919 rSrcRect, rDstRect, 920 maBegin, 921 maXorAccessor); 922 else 923 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask, 924 rSrcRect, rDstRect, 925 maBegin, 926 maAccessor); 927 } 928 } 929 930 virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap, 931 const BitmapDeviceSharedPtr& rMask, 932 const basegfx::B2IRange& rSrcRect, 933 const basegfx::B2IRange& rDstRect, 934 DrawMode drawMode, 935 const BitmapDeviceSharedPtr& rClip ) 936 { 937 if( isCompatibleClipMask(rMask) && 938 isCompatibleBitmap(rSrcBitmap) ) 939 { 940 if( drawMode == DrawMode_XOR ) 941 implDrawMaskedBitmap(rSrcBitmap, rMask, 942 rSrcRect, rDstRect, 943 getMaskedIter(rClip), 944 maMaskedXorAccessor); 945 else 946 implDrawMaskedBitmap(rSrcBitmap, rMask, 947 rSrcRect, rDstRect, 948 getMaskedIter(rClip), 949 maMaskedAccessor); 950 } 951 else 952 { 953 if( drawMode == DrawMode_XOR ) 954 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask, 955 rSrcRect, rDstRect, 956 getMaskedIter(rClip), 957 maMaskedXorAccessor); 958 else 959 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask, 960 rSrcRect, rDstRect, 961 getMaskedIter(rClip), 962 maMaskedAccessor); 963 } 964 } 965 }; 966 } // namespace 967 968 struct ImplBitmapDevice 969 { 970 /** Bitmap memory plus deleter. 971 972 Always points to the start of the mem 973 */ 974 RawMemorySharedArray mpMem; 975 976 // Palette memory plus deleter (might be NULL) 977 PaletteMemorySharedVector mpPalette; 978 979 /** Bounds of the device. 980 981 maBounds.getWidth()/getHeight() yield the true size of the 982 device (i.e. the rectangle given by maBounds covers the device 983 area under the excluding-bottommost-and-rightmost-pixels fill 984 rule) 985 */ 986 basegfx::B2IRange maBounds; 987 988 /** Bounds of the device. 989 990 maBounds.getWidth()/getHeight() yield the true size of the 991 device minus 1 (i.e. the rectangle given by maBounds covers 992 the device area under the 993 including-the-bottommost-and-rightmost-pixels fill rule). 994 995 The member is used to clip line stroking against the device 996 bounds. 997 */ 998 basegfx::B2IRange maLineClipRect; 999 1000 // Scanline format, as provided at the constructor 1001 sal_Int32 mnScanlineFormat; 1002 1003 // Scanline stride. Negative for bottom-to-top formats 1004 sal_Int32 mnScanlineStride; 1005 1006 // raw ptr to 0th scanline. used for cloning a generic renderer 1007 sal_uInt8* mpFirstScanline; 1008 1009 /** (Optional) device sharing the same memory, and used for input 1010 clip masks/alpha masks/bitmaps that don't match our exact 1011 bitmap format. 1012 1013 This is to avoid the combinatorical explosion when dealing 1014 with n bitmap formats, which could be combined with n clip 1015 masks, alpha masks and bitmap masks (yielding a total of n^4 1016 combinations). Since each BitmapRenderer is specialized for 1017 one specific combination of said formats, a lot of duplicate 1018 code would be generated, most of which probably never 1019 used. Therefore, only the most common combinations are 1020 specialized templates, the remainder gets handled by this 1021 generic renderer (via runtime polymorphism). 1022 */ 1023 BitmapDeviceSharedPtr mpGenericRenderer; 1024 }; 1025 1026 1027 BitmapDevice::BitmapDevice( const basegfx::B2IRange& rBounds, 1028 sal_Int32 nScanlineFormat, 1029 sal_Int32 nScanlineStride, 1030 sal_uInt8* pFirstScanline, 1031 const RawMemorySharedArray& rMem, 1032 const PaletteMemorySharedVector& rPalette ) : 1033 mpImpl( new ImplBitmapDevice ) 1034 { 1035 mpImpl->mpMem = rMem; 1036 mpImpl->mpPalette = rPalette; 1037 mpImpl->maBounds = rBounds; 1038 mpImpl->maLineClipRect = basegfx::B2IRange( rBounds.getMinX(), 1039 rBounds.getMinY(), 1040 rBounds.getMaxX()-1, 1041 rBounds.getMaxY()-1 ); 1042 mpImpl->mnScanlineFormat = nScanlineFormat; 1043 mpImpl->mnScanlineStride = nScanlineStride; 1044 mpImpl->mpFirstScanline = pFirstScanline; 1045 } 1046 1047 BitmapDevice::~BitmapDevice() 1048 { 1049 // outline, because of internal ImplBitmapDevice 1050 } 1051 1052 basegfx::B2IVector BitmapDevice::getSize() const 1053 { 1054 1055 return basegfx::B2IVector( 1056 mpImpl->maBounds.getMaxX() - mpImpl->maBounds.getMinX(), 1057 mpImpl->maBounds.getMaxY() - mpImpl->maBounds.getMinY() ); 1058 } 1059 1060 bool BitmapDevice::isTopDown() const 1061 { 1062 return mpImpl->mnScanlineStride >= 0; 1063 } 1064 1065 sal_Int32 BitmapDevice::getScanlineFormat() const 1066 { 1067 return mpImpl->mnScanlineFormat; 1068 } 1069 1070 sal_Int32 BitmapDevice::getScanlineStride() const 1071 { 1072 return mpImpl->mnScanlineStride < 0 ? 1073 -mpImpl->mnScanlineStride : mpImpl->mnScanlineStride; 1074 } 1075 1076 RawMemorySharedArray BitmapDevice::getBuffer() const 1077 { 1078 return mpImpl->mpMem; 1079 } 1080 1081 PaletteMemorySharedVector BitmapDevice::getPalette() const 1082 { 1083 return mpImpl->mpPalette; 1084 } 1085 1086 sal_Int32 BitmapDevice::getPaletteEntryCount() const 1087 { 1088 return mpImpl->mpPalette ? mpImpl->mpPalette->size() : 0; 1089 } 1090 1091 void BitmapDevice::clear( Color fillColor ) 1092 { 1093 clear_i( fillColor, mpImpl->maBounds ); 1094 } 1095 1096 void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt, 1097 Color lineColor, 1098 DrawMode drawMode ) 1099 { 1100 if( mpImpl->maLineClipRect.isInside(rPt) ) 1101 setPixel_i(rPt,lineColor,drawMode); 1102 } 1103 1104 void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt, 1105 Color lineColor, 1106 DrawMode drawMode, 1107 const BitmapDeviceSharedPtr& rClip ) 1108 { 1109 if( !rClip ) 1110 { 1111 setPixel(rPt,lineColor,drawMode); 1112 return; 1113 } 1114 1115 if( mpImpl->maLineClipRect.isInside(rPt) ) 1116 { 1117 if( isCompatibleClipMask( rClip ) ) 1118 setPixel_i(rPt,lineColor,drawMode,rClip); 1119 else 1120 getGenericRenderer()->setPixel( rPt, lineColor, drawMode, rClip ); 1121 } 1122 } 1123 1124 Color BitmapDevice::getPixel( const basegfx::B2IPoint& rPt ) 1125 { 1126 if( mpImpl->maLineClipRect.isInside(rPt) ) 1127 return getPixel_i(rPt); 1128 1129 return Color(); 1130 } 1131 1132 sal_uInt32 BitmapDevice::getPixelData( const basegfx::B2IPoint& rPt ) 1133 { 1134 if( mpImpl->maLineClipRect.isInside(rPt) ) 1135 return getPixelData_i(rPt); 1136 1137 return 0; 1138 } 1139 1140 void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1, 1141 const basegfx::B2IPoint& rPt2, 1142 Color lineColor, 1143 DrawMode drawMode ) 1144 { 1145 drawLine_i( rPt1, 1146 rPt2, 1147 mpImpl->maLineClipRect, 1148 lineColor, 1149 drawMode ); 1150 } 1151 1152 void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1, 1153 const basegfx::B2IPoint& rPt2, 1154 Color lineColor, 1155 DrawMode drawMode, 1156 const BitmapDeviceSharedPtr& rClip ) 1157 { 1158 if( !rClip ) 1159 { 1160 drawLine(rPt1,rPt2,lineColor,drawMode); 1161 return; 1162 } 1163 1164 if( isCompatibleClipMask( rClip ) ) 1165 drawLine_i( rPt1, 1166 rPt2, 1167 mpImpl->maLineClipRect, 1168 lineColor, 1169 drawMode, 1170 rClip ); 1171 else 1172 getGenericRenderer()->drawLine( rPt1, rPt2, lineColor, 1173 drawMode, rClip ); 1174 } 1175 1176 void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly, 1177 Color lineColor, 1178 DrawMode drawMode ) 1179 { 1180 const sal_uInt32 numVertices( rPoly.count() ); 1181 if( numVertices ) 1182 drawPolygon_i( rPoly, 1183 mpImpl->maLineClipRect, 1184 lineColor, drawMode ); 1185 } 1186 1187 void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly, 1188 Color lineColor, 1189 DrawMode drawMode, 1190 const BitmapDeviceSharedPtr& rClip ) 1191 { 1192 if( !rClip ) 1193 { 1194 drawPolygon(rPoly,lineColor,drawMode); 1195 return; 1196 } 1197 1198 const sal_uInt32 numVertices( rPoly.count() ); 1199 if( numVertices ) 1200 { 1201 if( isCompatibleClipMask( rClip ) ) 1202 drawPolygon_i( rPoly, 1203 mpImpl->maLineClipRect, 1204 lineColor, drawMode, rClip ); 1205 else 1206 getGenericRenderer()->drawPolygon( rPoly, lineColor, 1207 drawMode, rClip ); 1208 } 1209 } 1210 1211 void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly, 1212 Color fillColor, 1213 DrawMode drawMode ) 1214 { 1215 fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds ); 1216 } 1217 1218 void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly, 1219 Color fillColor, 1220 DrawMode drawMode, 1221 const BitmapDeviceSharedPtr& rClip ) 1222 { 1223 if( !rClip ) 1224 { 1225 fillPolyPolygon(rPoly,fillColor,drawMode); 1226 return; 1227 } 1228 1229 if( isCompatibleClipMask( rClip ) ) 1230 fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds, rClip ); 1231 else 1232 getGenericRenderer()->fillPolyPolygon( rPoly, fillColor, 1233 drawMode, rClip ); 1234 } 1235 1236 1237 namespace 1238 { 1239 void assertImagePoint( const basegfx::B2IPoint& rPt, 1240 const basegfx::B2IRange& rPermittedRange ) 1241 { 1242 (void)rPt; (void)rPermittedRange; 1243 OSL_ASSERT( rPermittedRange.isInside(rPt) ); 1244 } 1245 1246 void assertImageRange( const basegfx::B2IRange& rRange, 1247 const basegfx::B2IRange& rPermittedRange ) 1248 { 1249 #if OSL_DEBUG_LEVEL > 0 1250 basegfx::B2IRange aRange( rRange ); 1251 aRange.intersect( rPermittedRange ); 1252 1253 OSL_ASSERT( aRange == rRange ); 1254 #else 1255 (void)rRange; (void)rPermittedRange; 1256 #endif 1257 } 1258 1259 // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down 1260 // to basegfx, and use here! 1261 bool clipAreaImpl( ::basegfx::B2IRange& io_rSourceArea, 1262 ::basegfx::B2IPoint& io_rDestPoint, 1263 const ::basegfx::B2IRange& rSourceBounds, 1264 const ::basegfx::B2IRange& rDestBounds ) 1265 { 1266 const ::basegfx::B2IPoint aSourceTopLeft( 1267 io_rSourceArea.getMinimum() ); 1268 1269 ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea ); 1270 1271 // clip source area (which must be inside rSourceBounds) 1272 aLocalSourceArea.intersect( rSourceBounds ); 1273 1274 if( aLocalSourceArea.isEmpty() ) 1275 return false; 1276 1277 // calc relative new source area points (relative to orig 1278 // source area) 1279 const ::basegfx::B2IVector aUpperLeftOffset( 1280 aLocalSourceArea.getMinimum()-aSourceTopLeft ); 1281 const ::basegfx::B2IVector aLowerRightOffset( 1282 aLocalSourceArea.getMaximum()-aSourceTopLeft ); 1283 1284 ::basegfx::B2IRange aLocalDestArea( io_rDestPoint + aUpperLeftOffset, 1285 io_rDestPoint + aLowerRightOffset ); 1286 1287 // clip dest area (which must be inside rDestBounds) 1288 aLocalDestArea.intersect( rDestBounds ); 1289 1290 if( aLocalDestArea.isEmpty() ) 1291 return false; 1292 1293 // calc relative new dest area points (relative to orig 1294 // source area) 1295 const ::basegfx::B2IVector aDestUpperLeftOffset( 1296 aLocalDestArea.getMinimum()-io_rDestPoint ); 1297 const ::basegfx::B2IVector aDestLowerRightOffset( 1298 aLocalDestArea.getMaximum()-io_rDestPoint ); 1299 1300 io_rSourceArea = ::basegfx::B2IRange( aSourceTopLeft + aDestUpperLeftOffset, 1301 aSourceTopLeft + aDestLowerRightOffset ); 1302 io_rDestPoint = aLocalDestArea.getMinimum(); 1303 1304 return true; 1305 } 1306 1307 // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down 1308 // to basegfx, and use here! 1309 bool clipAreaImpl( ::basegfx::B2IRange& io_rDestArea, 1310 ::basegfx::B2IRange& io_rSourceArea, 1311 const ::basegfx::B2IRange& rDestBounds, 1312 const ::basegfx::B2IRange& rSourceBounds ) 1313 { 1314 // extract inherent scale 1315 const double nScaleX( io_rDestArea.getWidth() / (double)io_rSourceArea.getWidth() ); 1316 const double nScaleY( io_rDestArea.getHeight() / (double)io_rSourceArea.getHeight() ); 1317 1318 // extract range origins 1319 const basegfx::B2IPoint aDestTopLeft( 1320 io_rDestArea.getMinimum() ); 1321 const ::basegfx::B2IPoint aSourceTopLeft( 1322 io_rSourceArea.getMinimum() ); 1323 1324 ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea ); 1325 1326 // clip source area (which must be inside rSourceBounds) 1327 aLocalSourceArea.intersect( rSourceBounds ); 1328 1329 if( aLocalSourceArea.isEmpty() ) 1330 return false; 1331 1332 // calc relative new source area points (relative to orig 1333 // source area) 1334 const ::basegfx::B2IVector aUpperLeftOffset( 1335 aLocalSourceArea.getMinimum()-aSourceTopLeft ); 1336 const ::basegfx::B2IVector aLowerRightOffset( 1337 aLocalSourceArea.getMaximum()-aSourceTopLeft ); 1338 1339 ::basegfx::B2IRange aLocalDestArea( basegfx::fround(aDestTopLeft.getX() + nScaleX*aUpperLeftOffset.getX()), 1340 basegfx::fround(aDestTopLeft.getY() + nScaleY*aUpperLeftOffset.getY()), 1341 basegfx::fround(aDestTopLeft.getX() + nScaleX*aLowerRightOffset.getX()), 1342 basegfx::fround(aDestTopLeft.getY() + nScaleY*aLowerRightOffset.getY()) ); 1343 1344 // clip dest area (which must be inside rDestBounds) 1345 aLocalDestArea.intersect( rDestBounds ); 1346 1347 if( aLocalDestArea.isEmpty() ) 1348 return false; 1349 1350 // calc relative new dest area points (relative to orig 1351 // source area) 1352 const ::basegfx::B2IVector aDestUpperLeftOffset( 1353 aLocalDestArea.getMinimum()-aDestTopLeft ); 1354 const ::basegfx::B2IVector aDestLowerRightOffset( 1355 aLocalDestArea.getMaximum()-aDestTopLeft ); 1356 1357 io_rSourceArea = ::basegfx::B2IRange( basegfx::fround(aSourceTopLeft.getX() + aDestUpperLeftOffset.getX()/nScaleX), 1358 basegfx::fround(aSourceTopLeft.getY() + aDestUpperLeftOffset.getY()/nScaleY), 1359 basegfx::fround(aSourceTopLeft.getX() + aDestLowerRightOffset.getX()/nScaleX), 1360 basegfx::fround(aSourceTopLeft.getY() + aDestLowerRightOffset.getY()/nScaleY) ); 1361 io_rDestArea = aLocalDestArea; 1362 1363 // final source area clip (chopping round-offs) 1364 io_rSourceArea.intersect( rSourceBounds ); 1365 1366 if( io_rSourceArea.isEmpty() ) 1367 return false; 1368 1369 1370 return true; 1371 } 1372 } 1373 1374 void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, 1375 const basegfx::B2IRange& rSrcRect, 1376 const basegfx::B2IRange& rDstRect, 1377 DrawMode drawMode ) 1378 { 1379 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() ); 1380 const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() ); 1381 basegfx::B2IRange aSrcRange( rSrcRect ); 1382 basegfx::B2IRange aDestRange( rDstRect ); 1383 1384 if( clipAreaImpl( aDestRange, 1385 aSrcRange, 1386 mpImpl->maBounds, 1387 aSrcBounds )) 1388 { 1389 assertImageRange(aDestRange,mpImpl->maBounds); 1390 assertImageRange(aSrcRange,aSrcBounds); 1391 1392 drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode ); 1393 } 1394 } 1395 1396 void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, 1397 const basegfx::B2IRange& rSrcRect, 1398 const basegfx::B2IRange& rDstRect, 1399 DrawMode drawMode, 1400 const BitmapDeviceSharedPtr& rClip ) 1401 { 1402 if( !rClip ) 1403 { 1404 drawBitmap(rSrcBitmap,rSrcRect,rDstRect,drawMode); 1405 return; 1406 } 1407 1408 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() ); 1409 const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() ); 1410 basegfx::B2IRange aSrcRange( rSrcRect ); 1411 basegfx::B2IRange aDestRange( rDstRect ); 1412 1413 if( clipAreaImpl( aDestRange, 1414 aSrcRange, 1415 mpImpl->maBounds, 1416 aSrcBounds )) 1417 { 1418 assertImageRange(aDestRange,mpImpl->maBounds); 1419 assertImageRange(aSrcRange,aSrcBounds); 1420 1421 if( isCompatibleClipMask( rClip ) ) 1422 { 1423 drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode, rClip ); 1424 } 1425 else 1426 { 1427 getGenericRenderer()->drawBitmap( rSrcBitmap, rSrcRect, 1428 rDstRect, drawMode, rClip ); 1429 } 1430 } 1431 } 1432 1433 void BitmapDevice::drawMaskedColor( Color aSrcColor, 1434 const BitmapDeviceSharedPtr& rAlphaMask, 1435 const basegfx::B2IRange& rSrcRect, 1436 const basegfx::B2IPoint& rDstPoint ) 1437 { 1438 const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() ); 1439 const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() ); 1440 basegfx::B2IRange aSrcRange( rSrcRect ); 1441 basegfx::B2IPoint aDestPoint( rDstPoint ); 1442 1443 if( clipAreaImpl( aSrcRange, 1444 aDestPoint, 1445 aSrcBounds, 1446 mpImpl->maBounds )) 1447 { 1448 assertImagePoint(aDestPoint,mpImpl->maBounds); 1449 assertImageRange(aSrcRange,aSrcBounds); 1450 1451 if( rAlphaMask.get() == this ) 1452 { 1453 // src == dest, copy rAlphaMask beforehand 1454 // --------------------------------------------------- 1455 1456 const basegfx::B2ITuple aSize( aSrcRange.getWidth(), 1457 aSrcRange.getHeight() ); 1458 BitmapDeviceSharedPtr pAlphaCopy( 1459 cloneBitmapDevice( aSize, 1460 shared_from_this()) ); 1461 basegfx::B2ITuple aGcc3WorkaroundTemporary; 1462 const basegfx::B2IRange aAlphaRange( aGcc3WorkaroundTemporary, 1463 aSize ); 1464 pAlphaCopy->drawBitmap(rAlphaMask, 1465 aSrcRange, 1466 aAlphaRange, 1467 DrawMode_PAINT); 1468 drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint ); 1469 } 1470 else 1471 { 1472 drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint ); 1473 } 1474 } 1475 } 1476 1477 void BitmapDevice::drawMaskedColor( Color aSrcColor, 1478 const BitmapDeviceSharedPtr& rAlphaMask, 1479 const basegfx::B2IRange& rSrcRect, 1480 const basegfx::B2IPoint& rDstPoint, 1481 const BitmapDeviceSharedPtr& rClip ) 1482 { 1483 if( !rClip ) 1484 { 1485 drawMaskedColor(aSrcColor,rAlphaMask,rSrcRect,rDstPoint); 1486 return; 1487 } 1488 1489 const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() ); 1490 const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() ); 1491 basegfx::B2IRange aSrcRange( rSrcRect ); 1492 basegfx::B2IPoint aDestPoint( rDstPoint ); 1493 1494 if( clipAreaImpl( aSrcRange, 1495 aDestPoint, 1496 aSrcBounds, 1497 mpImpl->maBounds )) 1498 { 1499 assertImagePoint(aDestPoint,mpImpl->maBounds); 1500 assertImageRange(aSrcRange,aSrcBounds); 1501 1502 if( isCompatibleClipMask( rClip ) ) 1503 { 1504 if( rAlphaMask.get() == this ) 1505 { 1506 // src == dest, copy rAlphaMask beforehand 1507 // --------------------------------------------------- 1508 1509 const basegfx::B2ITuple aSize( aSrcRange.getWidth(), 1510 aSrcRange.getHeight() ); 1511 BitmapDeviceSharedPtr pAlphaCopy( 1512 cloneBitmapDevice( aSize, 1513 shared_from_this()) ); 1514 basegfx::B2ITuple aGcc3WorkaroundTemporary; 1515 const basegfx::B2IRange aAlphaRange( aGcc3WorkaroundTemporary, 1516 aSize ); 1517 pAlphaCopy->drawBitmap(rAlphaMask, 1518 aSrcRange, 1519 aAlphaRange, 1520 DrawMode_PAINT); 1521 drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint, rClip ); 1522 } 1523 else 1524 { 1525 drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint, rClip ); 1526 } 1527 } 1528 else 1529 { 1530 getGenericRenderer()->drawMaskedColor( aSrcColor, rAlphaMask, 1531 rSrcRect, rDstPoint, rClip ); 1532 } 1533 } 1534 } 1535 1536 void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, 1537 const BitmapDeviceSharedPtr& rMask, 1538 const basegfx::B2IRange& rSrcRect, 1539 const basegfx::B2IRange& rDstRect, 1540 DrawMode drawMode ) 1541 { 1542 OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() ); 1543 1544 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() ); 1545 const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() ); 1546 basegfx::B2IRange aSrcRange( rSrcRect ); 1547 basegfx::B2IRange aDestRange( rDstRect ); 1548 1549 if( clipAreaImpl( aDestRange, 1550 aSrcRange, 1551 mpImpl->maBounds, 1552 aSrcBounds )) 1553 { 1554 assertImageRange(aDestRange,mpImpl->maBounds); 1555 assertImageRange(aSrcRange,aSrcBounds); 1556 1557 drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode ); 1558 } 1559 } 1560 1561 void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, 1562 const BitmapDeviceSharedPtr& rMask, 1563 const basegfx::B2IRange& rSrcRect, 1564 const basegfx::B2IRange& rDstRect, 1565 DrawMode drawMode, 1566 const BitmapDeviceSharedPtr& rClip ) 1567 { 1568 if( !rClip ) 1569 { 1570 drawMaskedBitmap(rSrcBitmap,rMask,rSrcRect,rDstRect,drawMode); 1571 return; 1572 } 1573 1574 OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() ); 1575 1576 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() ); 1577 const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() ); 1578 basegfx::B2IRange aSrcRange( rSrcRect ); 1579 basegfx::B2IRange aDestRange( rDstRect ); 1580 1581 if( clipAreaImpl( aDestRange, 1582 aSrcRange, 1583 mpImpl->maBounds, 1584 aSrcBounds )) 1585 { 1586 assertImageRange(aDestRange,mpImpl->maBounds); 1587 assertImageRange(aSrcRange,aSrcBounds); 1588 1589 if( isCompatibleClipMask( rClip ) ) 1590 { 1591 drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode, rClip ); 1592 } 1593 else 1594 { 1595 getGenericRenderer()->drawMaskedBitmap( rSrcBitmap, rMask, rSrcRect, 1596 rDstRect, drawMode, rClip ); 1597 } 1598 } 1599 } 1600 1601 1602 //---------------------------------------------------------------------------------- 1603 1604 /** Standard clip and alpha masks 1605 */ 1606 struct StdMasks 1607 { 1608 typedef PixelFormatTraits_GREY1_MSB clipmask_format_traits; 1609 typedef PixelFormatTraits_GREY8 alphamask_format_traits; 1610 1611 // Clipmask: 0 means opaque 1612 static const bool clipmask_polarity = false; 1613 1614 // Alpha mask: 0 means fully transparent 1615 static const bool alphamask_polarity = true; 1616 }; 1617 1618 #if 0 1619 /** Clip and alpha masks for the generic renderer (of course, those 1620 need to be generic, too) 1621 */ 1622 struct MaskTraitsGeneric 1623 { 1624 typedef PixelFormatTraits_GenericInteger clipmask_format_traits; 1625 typedef PixelFormatTraits_GenericInteger alphamask_format_traits; 1626 }; 1627 #endif 1628 1629 //---------------------------------------------------------------------------------- 1630 1631 // Some compilers don't like the nested template wrap_accessor 1632 // reference in the parameter list - being slightly less type safe, 1633 // then. 1634 #ifndef BASEBMP_NO_NESTED_TEMPLATE_PARAMETER 1635 1636 // Produces a specialized renderer for the given pixel format 1637 template< class FormatTraits, class MaskTraits > 1638 BitmapDeviceSharedPtr createRenderer( 1639 const basegfx::B2IRange& rBounds, 1640 sal_Int32 nScanlineFormat, 1641 sal_Int32 nScanlineStride, 1642 sal_uInt8* pFirstScanline, 1643 typename FormatTraits::raw_accessor_type const& rRawAccessor, 1644 typename FormatTraits::accessor_selector::template wrap_accessor< 1645 typename FormatTraits::raw_accessor_type>::type const& rAccessor, 1646 boost::shared_array< sal_uInt8 > pMem, 1647 const PaletteMemorySharedVector& pPal ) 1648 1649 #else 1650 1651 template< class FormatTraits, class MaskTraits, class Accessor > 1652 BitmapDeviceSharedPtr createRenderer( 1653 const basegfx::B2IRange& rBounds, 1654 sal_Int32 nScanlineFormat, 1655 sal_Int32 nScanlineStride, 1656 sal_uInt8* pFirstScanline, 1657 typename FormatTraits::raw_accessor_type const& rRawAccessor, 1658 Accessor const& rAccessor, 1659 boost::shared_array< sal_uInt8 > pMem, 1660 const PaletteMemorySharedVector& pPal ) 1661 1662 #endif 1663 { 1664 typedef typename FormatTraits::iterator_type Iterator; 1665 typedef BitmapRenderer< Iterator, 1666 typename FormatTraits::raw_accessor_type, 1667 typename FormatTraits::accessor_selector, 1668 MaskTraits > Renderer; 1669 1670 return BitmapDeviceSharedPtr( 1671 new Renderer( rBounds, 1672 nScanlineFormat, 1673 nScanlineStride, 1674 pFirstScanline, 1675 Iterator( 1676 reinterpret_cast<typename Iterator::value_type*>( 1677 pFirstScanline), 1678 nScanlineStride), 1679 rRawAccessor, 1680 rAccessor, 1681 pMem, 1682 pPal )); 1683 } 1684 1685 // Create standard gray level palette 1686 PaletteMemorySharedVector createStandardPalette( 1687 const PaletteMemorySharedVector& pPal, 1688 sal_Int32 nNumEntries ) 1689 { 1690 if( pPal || nNumEntries <= 0 ) 1691 return pPal; 1692 1693 boost::shared_ptr< std::vector<Color> > pLocalPal( 1694 new std::vector<Color>(nNumEntries) ); 1695 1696 const sal_Int32 nIncrement( 0x00FFFFFF/nNumEntries ); 1697 --nNumEntries; 1698 for( sal_Int32 i=0, c=0; i<nNumEntries; ++i,c+=nIncrement ) 1699 pLocalPal->at(i) = Color(0xFF000000 | c); 1700 1701 pLocalPal->at(nNumEntries) = Color(0xFFFFFFFF); 1702 1703 return pLocalPal; 1704 } 1705 1706 template< class FormatTraits, class MaskTraits > 1707 BitmapDeviceSharedPtr createRenderer( 1708 const basegfx::B2IRange& rBounds, 1709 sal_Int32 nScanlineFormat, 1710 sal_Int32 nScanlineStride, 1711 sal_uInt8* pFirstScanline, 1712 boost::shared_array< sal_uInt8 > pMem, 1713 const PaletteMemorySharedVector& pPal ) 1714 { 1715 return createRenderer<FormatTraits, 1716 MaskTraits>(rBounds, 1717 nScanlineFormat, 1718 nScanlineStride, 1719 pFirstScanline, 1720 typename FormatTraits::raw_accessor_type(), 1721 typename FormatTraits::accessor_selector::template 1722 wrap_accessor< 1723 typename FormatTraits::raw_accessor_type>::type(), 1724 pMem, 1725 pPal); 1726 } 1727 1728 template< class FormatTraits, class MaskTraits > 1729 BitmapDeviceSharedPtr createRenderer( 1730 const basegfx::B2IRange& rBounds, 1731 sal_Int32 nScanlineFormat, 1732 sal_Int32 nScanlineStride, 1733 sal_uInt8* pFirstScanline, 1734 boost::shared_array< sal_uInt8 > pMem, 1735 PaletteMemorySharedVector pPal, 1736 int nBitsPerPixel ) 1737 { 1738 pPal = createStandardPalette(pPal, 1739 1UL << nBitsPerPixel); 1740 1741 OSL_ASSERT(pPal); 1742 return createRenderer<FormatTraits, 1743 MaskTraits>(rBounds, 1744 nScanlineFormat, 1745 nScanlineStride, 1746 pFirstScanline, 1747 typename FormatTraits::raw_accessor_type(), 1748 typename FormatTraits::accessor_selector::template 1749 wrap_accessor< 1750 typename FormatTraits::raw_accessor_type>::type( 1751 &pPal->at(0), 1752 pPal->size()), 1753 pMem, 1754 pPal); 1755 } 1756 1757 //---------------------------------------------------------------------------------- 1758 1759 // TODO(Q3): consolidate with canvas/canvastools.hxx! Best move this 1760 // to o3tl or sal/bithacks.hxx ... 1761 1762 /** Compute the next highest power of 2 of a 32-bit value 1763 1764 Code devised by Sean Anderson, in good ole HAKMEM 1765 tradition. 1766 1767 @return 1 << (lg(x - 1) + 1) 1768 */ 1769 inline sal_uInt32 nextPow2( sal_uInt32 x ) 1770 { 1771 --x; 1772 x |= x >> 1; 1773 x |= x >> 2; 1774 x |= x >> 4; 1775 x |= x >> 8; 1776 x |= x >> 16; 1777 1778 return ++x; 1779 } 1780 1781 //---------------------------------------------------------------------------------- 1782 1783 namespace 1784 { 1785 BitmapDeviceSharedPtr createBitmapDeviceImpl( const basegfx::B2IVector& rSize, 1786 bool bTopDown, 1787 sal_Int32 nScanlineFormat, 1788 boost::shared_array< sal_uInt8 > pMem, 1789 PaletteMemorySharedVector pPal, 1790 const basegfx::B2IRange* pSubset ) 1791 { 1792 if( nScanlineFormat <= Format::NONE || 1793 nScanlineFormat > Format::MAX ) 1794 return BitmapDeviceSharedPtr(); 1795 1796 static const sal_uInt8 bitsPerPixel[] = 1797 { 1798 0, // NONE 1799 1, // ONE_BIT_MSB_GREY 1800 1, // ONE_BIT_LSB_GREY 1801 1, // ONE_BIT_MSB_PAL 1802 1, // ONE_BIT_LSB_PAL 1803 4, // FOUR_BIT_MSB_GREY 1804 4, // FOUR_BIT_LSB_GREY 1805 4, // FOUR_BIT_MSB_PAL 1806 4, // FOUR_BIT_LSB_PAL 1807 8, // EIGHT_BIT_PAL 1808 8, // EIGHT_BIT_GREY 1809 16, // SIXTEEN_BIT_LSB_TC_MASK 1810 16, // SIXTEEN_BIT_MSB_TC_MASK 1811 24, // TWENTYFOUR_BIT_TC_MASK 1812 32, // THIRTYTWO_BIT_TC_MASK 1813 32, // THIRTYTWO_BIT_TC_MASK_ARGB 1814 }; 1815 1816 sal_Int32 nScanlineStride(0); 1817 1818 // round up to full 8 bit, divide by 8 1819 nScanlineStride = (rSize.getX()*bitsPerPixel[nScanlineFormat] + 7) >> 3; 1820 1821 // rounded up to next full power-of-two number of bytes 1822 const sal_uInt32 bytesPerPixel = nextPow2( 1823 (bitsPerPixel[nScanlineFormat] + 7) >> 3); 1824 1825 // now make nScanlineStride a multiple of bytesPerPixel 1826 nScanlineStride = (nScanlineStride + bytesPerPixel - 1) / bytesPerPixel * bytesPerPixel; 1827 1828 // factor in bottom-up scanline order case 1829 nScanlineStride *= bTopDown ? 1 : -1; 1830 1831 const std::size_t nMemSize( 1832 (nScanlineStride < 0 ? -nScanlineStride : nScanlineStride)*rSize.getY() ); 1833 1834 if( !pMem ) 1835 { 1836 pMem.reset( 1837 reinterpret_cast<sal_uInt8*>(rtl_allocateMemory( nMemSize )), 1838 &rtl_freeMemory ); 1839 rtl_zeroMemory(pMem.get(),nMemSize); 1840 } 1841 1842 sal_uInt8* pFirstScanline = nScanlineStride < 0 ? 1843 pMem.get() + nMemSize + nScanlineStride : pMem.get(); 1844 1845 // shrink render area to given subset, if given 1846 basegfx::B2IRange aBounds(0,0,rSize.getX(),rSize.getY()); 1847 if( pSubset ) 1848 aBounds.intersect( *pSubset ); 1849 1850 switch( nScanlineFormat ) 1851 { 1852 // ---------------------------------------------------------------------- 1853 // one bit formats 1854 1855 case Format::ONE_BIT_MSB_GREY: 1856 return createRenderer<PixelFormatTraits_GREY1_MSB,StdMasks>( 1857 aBounds, nScanlineFormat, nScanlineStride, 1858 pFirstScanline, pMem, pPal ); 1859 1860 case Format::ONE_BIT_LSB_GREY: 1861 return createRenderer<PixelFormatTraits_GREY1_LSB,StdMasks>( 1862 aBounds, nScanlineFormat, nScanlineStride, 1863 pFirstScanline, pMem, pPal ); 1864 1865 case Format::ONE_BIT_MSB_PAL: 1866 return createRenderer<PixelFormatTraits_PAL1_MSB,StdMasks>( 1867 aBounds, nScanlineFormat, nScanlineStride, 1868 pFirstScanline, pMem, pPal, 1869 bitsPerPixel[nScanlineFormat] ); 1870 1871 case Format::ONE_BIT_LSB_PAL: 1872 return createRenderer<PixelFormatTraits_PAL1_LSB,StdMasks>( 1873 aBounds, nScanlineFormat, nScanlineStride, 1874 pFirstScanline, pMem, pPal, 1875 bitsPerPixel[nScanlineFormat] ); 1876 1877 1878 // ---------------------------------------------------------------------- 1879 // four bit formats 1880 1881 case Format::FOUR_BIT_MSB_GREY: 1882 return createRenderer<PixelFormatTraits_GREY4_MSB,StdMasks>( 1883 aBounds, nScanlineFormat, nScanlineStride, 1884 pFirstScanline, pMem, pPal ); 1885 1886 case Format::FOUR_BIT_LSB_GREY: 1887 return createRenderer<PixelFormatTraits_GREY4_LSB,StdMasks>( 1888 aBounds, nScanlineFormat, nScanlineStride, 1889 pFirstScanline, pMem, pPal ); 1890 1891 case Format::FOUR_BIT_MSB_PAL: 1892 return createRenderer<PixelFormatTraits_PAL4_MSB,StdMasks>( 1893 aBounds, nScanlineFormat, nScanlineStride, 1894 pFirstScanline, pMem, pPal, 1895 bitsPerPixel[nScanlineFormat] ); 1896 1897 case Format::FOUR_BIT_LSB_PAL: 1898 return createRenderer<PixelFormatTraits_PAL4_LSB,StdMasks>( 1899 aBounds, nScanlineFormat, nScanlineStride, 1900 pFirstScanline, pMem, pPal, 1901 bitsPerPixel[nScanlineFormat] ); 1902 1903 1904 // ---------------------------------------------------------------------- 1905 // eight bit formats 1906 1907 case Format::EIGHT_BIT_GREY: 1908 return createRenderer<PixelFormatTraits_GREY8,StdMasks>( 1909 aBounds, nScanlineFormat, nScanlineStride, 1910 pFirstScanline, pMem, pPal ); 1911 1912 case Format::EIGHT_BIT_PAL: 1913 return createRenderer<PixelFormatTraits_PAL8,StdMasks>( 1914 aBounds, nScanlineFormat, nScanlineStride, 1915 pFirstScanline, pMem, pPal, 1916 bitsPerPixel[nScanlineFormat] ); 1917 1918 1919 // ---------------------------------------------------------------------- 1920 // sixteen bit formats 1921 1922 case Format::SIXTEEN_BIT_LSB_TC_MASK: 1923 return createRenderer<PixelFormatTraits_RGB16_565_LSB,StdMasks>( 1924 aBounds, nScanlineFormat, nScanlineStride, 1925 pFirstScanline, pMem, pPal ); 1926 1927 case Format::SIXTEEN_BIT_MSB_TC_MASK: 1928 return createRenderer<PixelFormatTraits_RGB16_565_MSB,StdMasks>( 1929 aBounds, nScanlineFormat, nScanlineStride, 1930 pFirstScanline, pMem, pPal ); 1931 1932 1933 // ---------------------------------------------------------------------- 1934 // twentyfour bit formats 1935 case Format::TWENTYFOUR_BIT_TC_MASK: 1936 return createRenderer<PixelFormatTraits_BGR24,StdMasks>( 1937 aBounds, nScanlineFormat, nScanlineStride, 1938 pFirstScanline, pMem, pPal ); 1939 1940 1941 // ---------------------------------------------------------------------- 1942 // thirtytwo bit formats 1943 1944 case Format::THIRTYTWO_BIT_TC_MASK: 1945 return createRenderer<PixelFormatTraits_RGB32_888,StdMasks>( 1946 aBounds, nScanlineFormat, nScanlineStride, 1947 pFirstScanline, pMem, pPal ); 1948 1949 case Format::THIRTYTWO_BIT_TC_MASK_ARGB: 1950 return createRenderer<PixelFormatTraits_BGR32_888,StdMasks>( 1951 aBounds, nScanlineFormat, nScanlineStride, 1952 pFirstScanline, pMem, pPal ); 1953 } 1954 1955 // TODO(F3): other formats not yet implemented 1956 return BitmapDeviceSharedPtr(); 1957 } 1958 } // namespace 1959 1960 1961 BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize, 1962 bool bTopDown, 1963 sal_Int32 nScanlineFormat ) 1964 { 1965 return createBitmapDeviceImpl( rSize, 1966 bTopDown, 1967 nScanlineFormat, 1968 boost::shared_array< sal_uInt8 >(), 1969 PaletteMemorySharedVector(), 1970 NULL ); 1971 } 1972 1973 BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize, 1974 bool bTopDown, 1975 sal_Int32 nScanlineFormat, 1976 const PaletteMemorySharedVector& rPalette ) 1977 { 1978 return createBitmapDeviceImpl( rSize, 1979 bTopDown, 1980 nScanlineFormat, 1981 boost::shared_array< sal_uInt8 >(), 1982 rPalette, 1983 NULL ); 1984 } 1985 1986 BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize, 1987 bool bTopDown, 1988 sal_Int32 nScanlineFormat, 1989 const RawMemorySharedArray& rMem, 1990 const PaletteMemorySharedVector& rPalette ) 1991 { 1992 return createBitmapDeviceImpl( rSize, 1993 bTopDown, 1994 nScanlineFormat, 1995 rMem, 1996 rPalette, 1997 NULL ); 1998 } 1999 2000 BitmapDeviceSharedPtr subsetBitmapDevice( const BitmapDeviceSharedPtr& rProto, 2001 const basegfx::B2IRange& rSubset ) 2002 { 2003 return createBitmapDeviceImpl( rProto->getSize(), 2004 rProto->isTopDown(), 2005 rProto->getScanlineFormat(), 2006 rProto->getBuffer(), 2007 rProto->getPalette(), 2008 &rSubset ); 2009 } 2010 2011 BitmapDeviceSharedPtr cloneBitmapDevice( const basegfx::B2IVector& rSize, 2012 const BitmapDeviceSharedPtr& rProto ) 2013 { 2014 return createBitmapDeviceImpl( rSize, 2015 rProto->isTopDown(), 2016 rProto->getScanlineFormat(), 2017 boost::shared_array< sal_uInt8 >(), 2018 rProto->getPalette(), 2019 NULL ); 2020 } 2021 2022 //---------------------------------------------------------------------------------- 2023 2024 // Clone our device, with GenericImageAccessor to handle all formats 2025 BitmapDeviceSharedPtr BitmapDevice::getGenericRenderer() const 2026 { 2027 #if 0 2028 // xxx TODO 2029 typedef BitmapRenderer< PixelFormatTraits_GenericInteger::iterator_type, 2030 PixelFormatTraits_GenericInteger::raw_accessor_type, 2031 PixelFormatTraits_GenericInteger::accessor_selector, 2032 MaskTraitsGeneric > 2033 Renderer; 2034 2035 if( !mpImpl->mpGenericRenderer ) 2036 { 2037 mpImpl->mpGenericRenderer.reset( 2038 new Renderer( 2039 mpImpl->maBounds, 2040 isTopDown(), 2041 getScanlineFormat(), 2042 getScanlineStride(), 2043 mpImpl->mpFirstScanline, 2044 PixelFormatTraits_GenericInteger::iterator_type(), 2045 GenericIntegerImageRawAccessor<Color>( 2046 const_cast<BitmapDevice*>(this)->shared_from_this()), 2047 GenericIntegerImageAccessor<Color>( 2048 const_cast<BitmapDevice*>(this)->shared_from_this()), 2049 getBuffer(), 2050 getPalette() )); 2051 } 2052 #endif 2053 2054 return mpImpl->mpGenericRenderer; 2055 } 2056 2057 } // namespace basebmp 2058 2059 /* vim: set noet sw=4 ts=4: */ 2060