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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_vcl.hxx" 26 27 #include <bmpfast.hxx> 28 29 #ifndef NO_OPTIMIZED_BITMAP_ACCESS 30 31 #include <tools/debug.hxx> 32 #include <vcl/bmpacc.hxx> 33 34 #define FAST_ARGB_BGRA 35 36 #include <stdlib.h> 37 static bool bDisableFastBitops = (getenv( "SAL_DISABLE_BITMAPS_OPTS" ) != NULL); 38 39 typedef unsigned char PIXBYTE; 40 41 class BasePixelPtr 42 { 43 public: 44 BasePixelPtr( PIXBYTE* p = NULL ) : mpPixel( p ) {} 45 void SetRawPtr( PIXBYTE* pRawPtr ) { mpPixel = pRawPtr; } 46 PIXBYTE* GetRawPtr( void ) const { return mpPixel; } 47 void AddByteOffset( int nByteOffset ) { mpPixel += nByteOffset; } 48 bool operator<( const BasePixelPtr& rCmp ) const { return (mpPixel < rCmp.mpPixel); } 49 50 protected: 51 PIXBYTE* mpPixel; 52 }; 53 54 template <sal_uLong PIXFMT> 55 class TrueColorPixelPtr : public BasePixelPtr 56 { 57 public: 58 PIXBYTE GetRed() const; 59 PIXBYTE GetGreen() const; 60 PIXBYTE GetBlue() const; 61 PIXBYTE GetAlpha() const; 62 63 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const; 64 void SetAlpha( PIXBYTE a ) const; 65 void operator++(int); 66 }; 67 68 // ======================================================================= 69 // template specializations for truecolor pixel formats 70 71 template <> 72 class TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_RGB> : public BasePixelPtr 73 { 74 public: 75 void operator++() { mpPixel += 3; } 76 77 PIXBYTE GetRed() const { return mpPixel[0]; } 78 PIXBYTE GetGreen() const { return mpPixel[1]; } 79 PIXBYTE GetBlue() const { return mpPixel[2]; } 80 PIXBYTE GetAlpha() const { return 0; } 81 void SetAlpha( PIXBYTE ) const {} 82 83 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const 84 { 85 mpPixel[0] = r; 86 mpPixel[1] = g; 87 mpPixel[2] = b; 88 } 89 }; 90 91 template <> 92 class TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_BGR> : public BasePixelPtr 93 { 94 public: 95 void operator++() { mpPixel += 3; } 96 97 PIXBYTE GetRed() const { return mpPixel[2]; } 98 PIXBYTE GetGreen() const { return mpPixel[1]; } 99 PIXBYTE GetBlue() const { return mpPixel[0]; } 100 PIXBYTE GetAlpha() const { return 0; } 101 void SetAlpha( PIXBYTE ) const {} 102 103 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const 104 { 105 mpPixel[0] = b; 106 mpPixel[1] = g; 107 mpPixel[2] = r; 108 } 109 }; 110 111 template <> 112 class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ARGB> : public BasePixelPtr 113 { 114 public: 115 void operator++() { mpPixel += 4; } 116 117 PIXBYTE GetRed() const { return mpPixel[1]; } 118 PIXBYTE GetGreen() const { return mpPixel[2]; } 119 PIXBYTE GetBlue() const { return mpPixel[3]; } 120 PIXBYTE GetAlpha() const { return mpPixel[0]; } 121 void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; } 122 123 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const 124 { 125 mpPixel[1] = r; 126 mpPixel[2] = g; 127 mpPixel[3] = b; 128 } 129 }; 130 131 template <> 132 class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ABGR> : public BasePixelPtr 133 { 134 public: 135 void operator++() { mpPixel += 4; } 136 137 PIXBYTE GetRed() const { return mpPixel[3]; } 138 PIXBYTE GetGreen() const { return mpPixel[2]; } 139 PIXBYTE GetBlue() const { return mpPixel[1]; } 140 PIXBYTE GetAlpha() const { return mpPixel[0]; } 141 void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; } 142 143 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const 144 { 145 mpPixel[1] = b; 146 mpPixel[2] = g; 147 mpPixel[3] = r; 148 } 149 }; 150 151 template <> 152 class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_RGBA> : public BasePixelPtr 153 { 154 public: 155 void operator++() { mpPixel += 4; } 156 157 PIXBYTE GetRed() const { return mpPixel[0]; } 158 PIXBYTE GetGreen() const { return mpPixel[1]; } 159 PIXBYTE GetBlue() const { return mpPixel[2]; } 160 PIXBYTE GetAlpha() const { return mpPixel[3]; } 161 void SetAlpha( PIXBYTE a ) const{ mpPixel[3] = a; } 162 163 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const 164 { 165 mpPixel[0] = r; 166 mpPixel[1] = g; 167 mpPixel[2] = b; 168 } 169 }; 170 171 template <> 172 class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_BGRA> : public BasePixelPtr 173 { 174 public: 175 void operator++() { mpPixel += 4; } 176 177 PIXBYTE GetRed() const { return mpPixel[2]; } 178 PIXBYTE GetGreen() const { return mpPixel[1]; } 179 PIXBYTE GetBlue() const { return mpPixel[0]; } 180 PIXBYTE GetAlpha() const { return mpPixel[3]; } 181 void SetAlpha( PIXBYTE a ) const{ mpPixel[3] = a; } 182 183 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const 184 { 185 mpPixel[0] = b; 186 mpPixel[1] = g; 187 mpPixel[2] = r; 188 } 189 }; 190 191 template <> 192 class TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_MSB_MASK> : public BasePixelPtr 193 { 194 public: 195 void operator++() { mpPixel += 2; } 196 197 // TODO: non565-RGB 198 PIXBYTE GetRed() const { return (mpPixel[0] & 0xF8U); } 199 PIXBYTE GetGreen() const { return (mpPixel[0]<<5U) | ((mpPixel[1]>>3U)&28U); } 200 PIXBYTE GetBlue() const { return (mpPixel[1]<<3U); } 201 PIXBYTE GetAlpha() const { return 0; } 202 void SetAlpha( PIXBYTE ) const {} 203 204 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const 205 { 206 mpPixel[0] = ((g >> 5U) & 7U) | (r & 0xF8U); 207 mpPixel[1] = ((g & 28U)<< 3U) | (b >> 3U); 208 } 209 }; 210 211 template <> 212 class TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_LSB_MASK> : public BasePixelPtr 213 { 214 public: 215 void operator++() { mpPixel += 2; } 216 217 // TODO: non565-RGB 218 PIXBYTE GetRed() const { return (mpPixel[1] & 0xF8U); } 219 PIXBYTE GetGreen() const { return (mpPixel[1]<<5U) | ((mpPixel[0]>>3U)&28U); } 220 PIXBYTE GetBlue() const { return (mpPixel[0]<<3U); } 221 PIXBYTE GetAlpha() const { return 0; } 222 void SetAlpha( PIXBYTE ) const {} 223 224 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const 225 { 226 mpPixel[0] = ((g & 28U)<< 3U) | (b >> 3U); 227 mpPixel[1] = ((g >> 5U) & 7U) | (r & 0xF8U); 228 } 229 }; 230 231 // ----------------------------------------------------------------------- 232 233 template <> 234 class TrueColorPixelPtr<BMP_FORMAT_8BIT_TC_MASK> : public BasePixelPtr 235 { 236 public: 237 void operator++() { mpPixel += 1; } 238 PIXBYTE GetAlpha() const { return mpPixel[0]; } 239 void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; } 240 void SetColor( PIXBYTE, PIXBYTE, PIXBYTE ) const {} 241 }; 242 243 // TODO: for some reason many Alpha maps are BMP_FORMAT_8BIT_PAL 244 // they should be BMP_FORMAT_8BIT_TC_MASK 245 template <> 246 class TrueColorPixelPtr<BMP_FORMAT_8BIT_PAL> 247 : public TrueColorPixelPtr<BMP_FORMAT_8BIT_TC_MASK> 248 {}; 249 250 #if 0 251 template <> 252 class TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_MASK> : public BasePixelPtr 253 { 254 public: 255 void operator++() { mpPixel += 3; } 256 257 unsigned GetAlpha() const 258 { 259 unsigned nAlpha = mpPixel[0]; 260 nAlpha |= mpPixel[1] << 8U; 261 nAlpha |= mpPixel[2] << 16U; 262 return nAlpha; 263 } 264 265 void SetAlpha( unsigned nAlpha ) const 266 { 267 mpPixel[0] = nAlpha; 268 mpPixel[1] = nAlpha >> 8U; 269 mpPixel[2] = nAlpha >> 16U; 270 } 271 }; 272 273 template <> 274 class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_MASK> : public BasePixelPtr 275 { 276 public: 277 void operator++() { mpPixel += 4; } 278 279 unsigned GetAlpha() const 280 { 281 #ifdef OSL_BIGENDIAN 282 unsigned nAlpha = *reinterpret_cast<unsigned*>( mpPixel ); 283 #else 284 unsigned nAlpha = mpPixel[0]; 285 nAlpha |= mpPixel[1] << 8U; 286 nAlpha |= mpPixel[2] << 16U; 287 nAlpha |= mpPixel[3] << 24U; 288 #endif 289 return nAlpha; 290 } 291 292 void SetAlpha( unsigned nAlpha ) const 293 { 294 #ifdef OSL_BIGENDIAN 295 *reinterpret_cast<unsigned*>( mpPixel ) = nAlpha; 296 #else 297 mpPixel[0] = nAlpha; 298 mpPixel[1] = nAlpha >> 8U; 299 mpPixel[2] = nAlpha >> 16U; 300 mpPixel[3] = nAlpha >> 24U; 301 #endif 302 } 303 }; 304 305 #endif 306 307 // ======================================================================= 308 // converting truecolor formats 309 310 template <sal_uLong SRCFMT, sal_uLong DSTFMT> 311 inline void ImplConvertPixel( const TrueColorPixelPtr<DSTFMT>& rDst, 312 const TrueColorPixelPtr<SRCFMT>& rSrc ) 313 { 314 rDst.SetColor( rSrc.GetRed(), rSrc.GetGreen(), rSrc.GetBlue() ); 315 rDst.SetAlpha( rSrc.GetAlpha() ); 316 } 317 318 // ----------------------------------------------------------------------- 319 320 template <> 321 inline void ImplConvertPixel<BMP_FORMAT_16BIT_TC_LSB_MASK, BMP_FORMAT_16BIT_TC_MSB_MASK> ( 322 const TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_MSB_MASK>& rDst, 323 const TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_LSB_MASK>& rSrc ) 324 { 325 // byte swapping 326 const PIXBYTE* pSrc = rSrc.GetRawPtr(); 327 PIXBYTE* pDst = rDst.GetRawPtr(); 328 pDst[1] = pSrc[0]; 329 pDst[0] = pSrc[1]; 330 } 331 332 // ----------------------------------------------------------------------- 333 334 template <sal_uLong SRCFMT, sal_uLong DSTFMT> 335 inline void ImplConvertLine( const TrueColorPixelPtr<DSTFMT>& rDst, 336 const TrueColorPixelPtr<SRCFMT>& rSrc, int nPixelCount ) 337 { 338 TrueColorPixelPtr<DSTFMT> aDst( rDst ); 339 TrueColorPixelPtr<SRCFMT> aSrc( rSrc ); 340 while( --nPixelCount >= 0 ) 341 { 342 ImplConvertPixel( aDst, aSrc ); 343 ++aSrc; 344 ++aDst; 345 } 346 } 347 348 // ======================================================================= 349 // alpha blending truecolor pixels 350 351 template <unsigned ALPHABITS, sal_uLong SRCFMT, sal_uLong DSTFMT> 352 inline void ImplBlendPixels( const TrueColorPixelPtr<DSTFMT>& rDst, 353 const TrueColorPixelPtr<SRCFMT>& rSrc, unsigned nAlphaVal ) 354 { 355 if( !nAlphaVal ) 356 ImplConvertPixel( rDst, rSrc ); 357 else if( nAlphaVal != ~(~0 << ALPHABITS) ) 358 { 359 static const unsigned nAlphaShift = (ALPHABITS > 8) ? 8 : ALPHABITS; 360 if( ALPHABITS > nAlphaShift ) 361 nAlphaVal >>= ALPHABITS - nAlphaShift; 362 363 int nR = rDst.GetRed(); 364 int nS = rSrc.GetRed(); 365 nR = nS + (((nR - nS) * nAlphaVal) >> nAlphaShift); 366 367 int nG = rDst.GetGreen(); 368 nS = rSrc.GetGreen(); 369 nG = nS + (((nG - nS) * nAlphaVal) >> nAlphaShift); 370 371 int nB = rDst.GetBlue(); 372 nS = rSrc.GetBlue(); 373 nB = nS + (((nB - nS) * nAlphaVal) >> nAlphaShift); 374 375 rDst.SetColor( sal::static_int_cast<PIXBYTE>(nR), 376 sal::static_int_cast<PIXBYTE>(nG), 377 sal::static_int_cast<PIXBYTE>(nB) ); 378 } 379 } 380 381 // ----------------------------------------------------------------------- 382 383 template <unsigned ALPHABITS, sal_uLong MASKFMT, sal_uLong SRCFMT, sal_uLong DSTFMT> 384 inline void ImplBlendLines( const TrueColorPixelPtr<DSTFMT>& rDst, 385 const TrueColorPixelPtr<SRCFMT>& rSrc, const TrueColorPixelPtr<MASKFMT>& rMsk, 386 int nPixelCount ) 387 { 388 TrueColorPixelPtr<MASKFMT> aMsk( rMsk ); 389 TrueColorPixelPtr<DSTFMT> aDst( rDst ); 390 TrueColorPixelPtr<SRCFMT> aSrc( rSrc ); 391 while( --nPixelCount >= 0 ) 392 { 393 ImplBlendPixels<ALPHABITS>( aDst, aSrc, aMsk.GetAlpha() ); 394 ++aDst; 395 ++aSrc; 396 ++aMsk; 397 } 398 } 399 400 // ----------------------------------------------------------------------- 401 402 template <unsigned ALPHABITS, sal_uLong SRCFMT, sal_uLong DSTFMT> 403 inline void ImplBlendLines( const TrueColorPixelPtr<DSTFMT>& rDst, 404 const TrueColorPixelPtr<SRCFMT>& rSrc, unsigned nAlphaVal, 405 int nPixelCount ) 406 { 407 if( nAlphaVal == ~(~0 << ALPHABITS) ) 408 ImplConvertLine( rDst, rSrc, nPixelCount ); 409 else if( nAlphaVal ) 410 { 411 TrueColorPixelPtr<SRCFMT> aSrc( rSrc ); 412 TrueColorPixelPtr<DSTFMT> aDst( rDst ); 413 while( --nPixelCount >= 0 ) 414 { 415 ImplBlendPixels<ALPHABITS>( aDst, aSrc, nAlphaVal ); 416 ++aDst; 417 ++aSrc; 418 } 419 } 420 } 421 422 // ======================================================================= 423 424 static bool ImplCopyImage( BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer ) 425 { 426 const int nSrcLinestep = rSrcBuffer.mnScanlineSize; 427 int nDstLinestep = rDstBuffer.mnScanlineSize; 428 429 const PIXBYTE* pRawSrc = rSrcBuffer.mpBits; 430 PIXBYTE* pRawDst = rDstBuffer.mpBits; 431 432 // source and destination don't match upside down 433 if( BMP_FORMAT_TOP_DOWN & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) ) 434 { 435 pRawDst += (rSrcBuffer.mnHeight - 1) * nDstLinestep; 436 nDstLinestep = -rDstBuffer.mnScanlineSize; 437 } 438 else if( nSrcLinestep == nDstLinestep ) 439 { 440 memcpy( pRawDst, pRawSrc, rSrcBuffer.mnHeight * nDstLinestep ); 441 return true; 442 } 443 444 int nByteWidth = nSrcLinestep; 445 if( nByteWidth > rDstBuffer.mnScanlineSize ) 446 nByteWidth = rDstBuffer.mnScanlineSize; 447 448 for( int y = rSrcBuffer.mnHeight; --y >= 0; ) 449 { 450 memcpy( pRawDst, pRawSrc, nByteWidth ); 451 pRawSrc += nSrcLinestep; 452 pRawDst += nDstLinestep; 453 } 454 455 return true; 456 } 457 458 // ----------------------------------------------------------------------- 459 460 template <sal_uLong DSTFMT,sal_uLong SRCFMT> 461 bool ImplConvertToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine, 462 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer ) 463 { 464 // help the compiler to avoid instantiations of unneeded conversions 465 DBG_ASSERT( SRCFMT != DSTFMT, "ImplConvertToBitmap into same format"); 466 if( SRCFMT == DSTFMT ) 467 return false; 468 469 const int nSrcLinestep = rSrcBuffer.mnScanlineSize; 470 int nDstLinestep = rDstBuffer.mnScanlineSize; 471 472 TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits ); 473 474 // source and destination don't match upside down 475 if( BMP_FORMAT_TOP_DOWN & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) ) 476 { 477 aDstLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nDstLinestep ); 478 nDstLinestep = -nDstLinestep; 479 } 480 481 for( int y = rSrcBuffer.mnHeight; --y >= 0; ) 482 { 483 ImplConvertLine( aDstLine, rSrcLine, rSrcBuffer.mnWidth ); 484 rSrcLine.AddByteOffset( nSrcLinestep ); 485 aDstLine.AddByteOffset( nDstLinestep ); 486 } 487 488 return true; 489 } 490 491 // ----------------------------------------------------------------------- 492 493 template <sal_uLong SRCFMT> 494 inline bool ImplConvertFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc ) 495 { 496 TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits ); 497 498 // select the matching instantiation for the destination's bitmap format 499 switch( rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN ) 500 { 501 case BMP_FORMAT_1BIT_MSB_PAL: 502 case BMP_FORMAT_1BIT_LSB_PAL: 503 case BMP_FORMAT_4BIT_MSN_PAL: 504 case BMP_FORMAT_4BIT_LSN_PAL: 505 case BMP_FORMAT_8BIT_PAL: 506 break; 507 508 case BMP_FORMAT_8BIT_TC_MASK: 509 // return ImplConvertToBitmap<BMP_FORMAT_8BIT_TC_MASK>( aSrcType, rDst, rSrc ); 510 case BMP_FORMAT_24BIT_TC_MASK: 511 // return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_MASK>( aSrcType, rDst, rSrc ); 512 case BMP_FORMAT_32BIT_TC_MASK: 513 // return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_MASK>( aSrcType, rDst, rSrc ); 514 break; 515 516 case BMP_FORMAT_16BIT_TC_MSB_MASK: 517 return ImplConvertToBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( aSrcType, rDst, rSrc ); 518 case BMP_FORMAT_16BIT_TC_LSB_MASK: 519 return ImplConvertToBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( aSrcType, rDst, rSrc ); 520 521 case BMP_FORMAT_24BIT_TC_BGR: 522 return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_BGR>( aSrcType, rDst, rSrc ); 523 case BMP_FORMAT_24BIT_TC_RGB: 524 return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDst, rSrc ); 525 526 case BMP_FORMAT_32BIT_TC_ABGR: 527 return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_ABGR>( aSrcType, rDst, rSrc ); 528 #ifdef FAST_ARGB_BGRA 529 case BMP_FORMAT_32BIT_TC_ARGB: 530 return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDst, rSrc ); 531 case BMP_FORMAT_32BIT_TC_BGRA: 532 return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_BGRA>( aSrcType, rDst, rSrc ); 533 #endif 534 case BMP_FORMAT_32BIT_TC_RGBA: 535 return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDst, rSrc ); 536 } 537 538 #ifdef DEBUG 539 static int nNotAccelerated = 0; 540 if( rSrc.mnWidth * rSrc.mnHeight >= 4000 ) 541 if( ++nNotAccelerated == 100 ) 542 { 543 int foo = 0; (void)foo; // so no warning is created when building on pro with debug 544 DBG_WARNING2( "ImplConvertFromBitmap for not accelerated case (0x%04X->0x%04X)", 545 rSrc.mnFormat, rDst.mnFormat ); 546 } 547 #endif 548 549 return false; 550 } 551 552 // ======================================================================= 553 554 // an universal stretching conversion is overkill in most common situations 555 // => performance benefits for speeding up the non-stretching cases 556 bool ImplFastBitmapConversion( BitmapBuffer& rDst, const BitmapBuffer& rSrc, 557 const SalTwoRect& rTR ) 558 { 559 if( bDisableFastBitops ) 560 return false; 561 562 // horizontal mirroring not implemented yet 563 if( rTR.mnDestWidth < 0 ) 564 return false; 565 // vertical mirroring 566 if( rTR.mnDestHeight < 0 ) 567 // TODO: rDst.mnFormat ^= BMP_FORMAT_TOP_DOWN; 568 return false; 569 570 // offseted conversion is not implemented yet 571 if( rTR.mnSrcX || rTR.mnSrcY ) 572 return false; 573 if( rTR.mnDestX || rTR.mnDestY ) 574 return false; 575 576 // stretched conversion is not implemented yet 577 if( rTR.mnDestWidth != rTR.mnSrcWidth ) 578 return false; 579 if( rTR.mnDestHeight!= rTR.mnSrcHeight ) 580 return false; 581 582 // check source image size 583 if( rSrc.mnWidth < rTR.mnSrcX + rTR.mnSrcWidth ) 584 return false; 585 if( rSrc.mnHeight < rTR.mnSrcY + rTR.mnSrcHeight ) 586 return false; 587 588 // check dest image size 589 if( rDst.mnWidth < rTR.mnDestX + rTR.mnDestWidth ) 590 return false; 591 if( rDst.mnHeight < rTR.mnDestY + rTR.mnDestHeight ) 592 return false; 593 594 const sal_uLong nSrcFormat = rSrc.mnFormat & ~BMP_FORMAT_TOP_DOWN; 595 const sal_uLong nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN; 596 597 // TODO: also implement conversions for 16bit colormasks with non-565 format 598 if( nSrcFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) ) 599 if( rSrc.maColorMask.GetRedMask() != 0xF800 600 || rSrc.maColorMask.GetGreenMask()!= 0x07E0 601 || rSrc.maColorMask.GetBlueMask() != 0x001F ) 602 return false; 603 if( nDstFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) ) 604 if( rDst.maColorMask.GetRedMask() != 0xF800 605 || rDst.maColorMask.GetGreenMask()!= 0x07E0 606 || rDst.maColorMask.GetBlueMask() != 0x001F ) 607 return false; 608 609 // special handling of trivial cases 610 if( nSrcFormat == nDstFormat ) 611 { 612 // accelerated palette conversions not yet implemented 613 if( rSrc.maPalette != rDst.maPalette ) 614 return false; 615 return ImplCopyImage( rDst, rSrc ); 616 } 617 618 // select the matching instantiation for the source's bitmap format 619 switch( nSrcFormat ) 620 { 621 case BMP_FORMAT_1BIT_MSB_PAL: 622 case BMP_FORMAT_1BIT_LSB_PAL: 623 case BMP_FORMAT_4BIT_MSN_PAL: 624 case BMP_FORMAT_4BIT_LSN_PAL: 625 case BMP_FORMAT_8BIT_PAL: 626 break; 627 628 case BMP_FORMAT_8BIT_TC_MASK: 629 // return ImplConvertFromBitmap<BMP_FORMAT_8BIT_TC_MASK>( rDst, rSrc ); 630 case BMP_FORMAT_24BIT_TC_MASK: 631 // return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_MASK>( rDst, rSrc ); 632 case BMP_FORMAT_32BIT_TC_MASK: 633 // return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_MASK>( rDst, rSrc ); 634 break; 635 636 case BMP_FORMAT_16BIT_TC_MSB_MASK: 637 return ImplConvertFromBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( rDst, rSrc ); 638 case BMP_FORMAT_16BIT_TC_LSB_MASK: 639 return ImplConvertFromBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( rDst, rSrc ); 640 641 case BMP_FORMAT_24BIT_TC_BGR: 642 return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_BGR>( rDst, rSrc ); 643 case BMP_FORMAT_24BIT_TC_RGB: 644 return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_RGB>( rDst, rSrc ); 645 646 case BMP_FORMAT_32BIT_TC_ABGR: 647 return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_ABGR>( rDst, rSrc ); 648 #ifdef FAST_ARGB_BGRA 649 case BMP_FORMAT_32BIT_TC_ARGB: 650 return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_ARGB>( rDst, rSrc ); 651 case BMP_FORMAT_32BIT_TC_BGRA: 652 return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_BGRA>( rDst, rSrc ); 653 #endif 654 case BMP_FORMAT_32BIT_TC_RGBA: 655 return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_RGBA>( rDst, rSrc ); 656 } 657 658 #ifdef DEBUG 659 static int nNotAccelerated = 0; 660 if( rSrc.mnWidth * rSrc.mnHeight >= 4000 ) 661 { 662 if( ++nNotAccelerated == 100 ) 663 { 664 int foo = 0; (void)foo; // so no warning is created when building on pro with debug 665 DBG_WARNING2( "ImplFastBitmapConversion for not accelerated case (0x%04X->0x%04X)", rSrc.mnFormat, rDst.mnFormat ); 666 } 667 } 668 #endif 669 670 return false; 671 } 672 673 // ======================================================================= 674 675 template <sal_uLong DSTFMT,sal_uLong SRCFMT> //,sal_uLong MSKFMT> 676 bool ImplBlendToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine, 677 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer, 678 const BitmapBuffer& rMskBuffer ) 679 { 680 //DBG_ASSERT( rMskBuffer.mnFormat == MSKFMT, "FastBmp BlendImage: wrong MSKFMT" ); 681 DBG_ASSERT( rMskBuffer.mnFormat == BMP_FORMAT_8BIT_PAL, "FastBmp BlendImage: unusual MSKFMT" ); 682 683 const int nSrcLinestep = rSrcBuffer.mnScanlineSize; 684 int nMskLinestep = rMskBuffer.mnScanlineSize; 685 int nDstLinestep = rDstBuffer.mnScanlineSize; 686 687 TrueColorPixelPtr<BMP_FORMAT_8BIT_PAL> aMskLine; aMskLine.SetRawPtr( rMskBuffer.mpBits ); 688 TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits ); 689 690 // special case for single line masks 691 if( rMskBuffer.mnHeight == 1 ) 692 nMskLinestep = 0; 693 694 // source and mask don't match: upside down 695 if( (rSrcBuffer.mnFormat ^ rMskBuffer.mnFormat) & BMP_FORMAT_TOP_DOWN ) 696 { 697 aMskLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nMskLinestep ); 698 nMskLinestep = -nMskLinestep; 699 } 700 701 // source and destination don't match: upside down 702 if( (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) & BMP_FORMAT_TOP_DOWN ) 703 { 704 aDstLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nDstLinestep ); 705 nDstLinestep = -nDstLinestep; 706 } 707 708 for( int y = rSrcBuffer.mnHeight; --y >= 0; ) 709 { 710 ImplBlendLines<8>( aDstLine, rSrcLine, aMskLine, rDstBuffer.mnWidth ); 711 aDstLine.AddByteOffset( nDstLinestep ); 712 rSrcLine.AddByteOffset( nSrcLinestep ); 713 aMskLine.AddByteOffset( nMskLinestep ); 714 } 715 716 return true; 717 } 718 719 // some specializations to reduce the code size 720 template <> 721 inline bool ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_BGR,BMP_FORMAT_24BIT_TC_BGR>( 722 TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_BGR>&, 723 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer, 724 const BitmapBuffer& rMskBuffer ) 725 { 726 TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_RGB> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits ); 727 return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer ); 728 } 729 730 template <> 731 inline bool ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ABGR,BMP_FORMAT_32BIT_TC_ABGR>( 732 TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ABGR>&, 733 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer, 734 const BitmapBuffer& rMskBuffer ) 735 { 736 TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ARGB> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits ); 737 return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer ); 738 } 739 740 template <> 741 inline bool ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_BGRA,BMP_FORMAT_32BIT_TC_BGRA>( 742 TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_BGRA>&, 743 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer, 744 const BitmapBuffer& rMskBuffer ) 745 { 746 TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_RGBA> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits ); 747 return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer ); 748 } 749 750 // ----------------------------------------------------------------------- 751 752 template <sal_uLong SRCFMT> 753 bool ImplBlendFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc, const BitmapBuffer& rMsk ) 754 { 755 TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits ); 756 757 // select the matching instantiation for the destination's bitmap format 758 switch( rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN ) 759 { 760 case BMP_FORMAT_1BIT_MSB_PAL: 761 case BMP_FORMAT_1BIT_LSB_PAL: 762 case BMP_FORMAT_4BIT_MSN_PAL: 763 case BMP_FORMAT_4BIT_LSN_PAL: 764 case BMP_FORMAT_8BIT_PAL: 765 break; 766 767 case BMP_FORMAT_8BIT_TC_MASK: 768 // return ImplBlendToBitmap<BMP_FORMAT_8BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk ); 769 case BMP_FORMAT_24BIT_TC_MASK: 770 // return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk ); 771 case BMP_FORMAT_32BIT_TC_MASK: 772 // return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk ); 773 break; 774 775 case BMP_FORMAT_16BIT_TC_MSB_MASK: 776 return ImplBlendToBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( aSrcType, rDst, rSrc, rMsk ); 777 case BMP_FORMAT_16BIT_TC_LSB_MASK: 778 return ImplBlendToBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( aSrcType, rDst, rSrc, rMsk ); 779 780 case BMP_FORMAT_24BIT_TC_BGR: 781 return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_BGR>( aSrcType, rDst, rSrc, rMsk ); 782 case BMP_FORMAT_24BIT_TC_RGB: 783 return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDst, rSrc, rMsk ); 784 785 case BMP_FORMAT_32BIT_TC_ABGR: 786 return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ABGR>( aSrcType, rDst, rSrc, rMsk ); 787 #ifdef FAST_ARGB_BGRA 788 case BMP_FORMAT_32BIT_TC_ARGB: 789 return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDst, rSrc, rMsk ); 790 case BMP_FORMAT_32BIT_TC_BGRA: 791 return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_BGRA>( aSrcType, rDst, rSrc, rMsk ); 792 #endif 793 case BMP_FORMAT_32BIT_TC_RGBA: 794 return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDst, rSrc, rMsk ); 795 } 796 797 #ifdef DEBUG 798 static int nNotAccelerated = 0; 799 if( rSrc.mnWidth * rSrc.mnHeight >= 4000 ) 800 if( ++nNotAccelerated == 100 ) 801 { 802 int foo = 0; (void)foo; // so no warning is created when building on pro with debug 803 DBG_WARNING3( "ImplBlendFromBitmap for not accelerated case (0x%04X*0x%04X->0x%04X)", 804 rSrc.mnFormat, rMsk.mnFormat, rDst.mnFormat ); 805 } 806 #endif 807 808 return false; 809 } 810 811 // ----------------------------------------------------------------------- 812 813 bool ImplFastBitmapBlending( BitmapWriteAccess& rDstWA, 814 const BitmapReadAccess& rSrcRA, const BitmapReadAccess& rMskRA, 815 const SalTwoRect& rTR ) 816 { 817 if( bDisableFastBitops ) 818 return false; 819 820 // accelerated blending of paletted bitmaps not implemented yet 821 if( rSrcRA.HasPalette() ) 822 return false; 823 if( rDstWA.HasPalette() ) 824 return false; 825 // TODO: either get rid of mask's use of 8BIT_PAL or check the palette 826 827 // horizontal mirroring not implemented yet 828 if( rTR.mnDestWidth < 0 ) 829 return false; 830 // vertical mirroring 831 if( rTR.mnDestHeight < 0 ) 832 // TODO: rDst.mnFormat ^= BMP_FORMAT_TOP_DOWN; 833 return false; 834 835 // offseted blending is not implemented yet 836 if( rTR.mnSrcX || rTR.mnSrcY ) 837 return false; 838 if( rTR.mnDestX || rTR.mnDestY ) 839 return false; 840 841 // stretched blending is not implemented yet 842 if( rTR.mnDestWidth != rTR.mnSrcWidth ) 843 return false; 844 if( rTR.mnDestHeight!= rTR.mnSrcHeight ) 845 return false; 846 847 // check source image size 848 if( rSrcRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth ) 849 return false; 850 if( rSrcRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight ) 851 return false; 852 853 // check mask image size 854 if( rMskRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth ) 855 return false; 856 if( rMskRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight ) 857 if( rMskRA.Height() != 1 ) 858 return false; 859 860 // check dest image size 861 if( rDstWA.Width() < rTR.mnDestX + rTR.mnDestWidth ) 862 return false; 863 if( rDstWA.Height() < rTR.mnDestY + rTR.mnDestHeight ) 864 return false; 865 866 BitmapBuffer& rDst = *rDstWA.ImplGetBitmapBuffer(); 867 const BitmapBuffer& rSrc = *rSrcRA.ImplGetBitmapBuffer(); 868 const BitmapBuffer& rMsk = *rMskRA.ImplGetBitmapBuffer(); 869 870 const sal_uLong nSrcFormat = rSrc.mnFormat & ~BMP_FORMAT_TOP_DOWN; 871 const sal_uLong nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN; 872 873 // accelerated conversions for 16bit colormasks with non-565 format are not yet implemented 874 if( nSrcFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) ) 875 if( rSrc.maColorMask.GetRedMask() != 0xF800 876 || rSrc.maColorMask.GetGreenMask()!= 0x07E0 877 || rSrc.maColorMask.GetBlueMask() != 0x001F) 878 return false; 879 if( nDstFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) ) 880 if( rDst.maColorMask.GetRedMask() != 0xF800 881 || rDst.maColorMask.GetGreenMask()!= 0x07E0 882 || rDst.maColorMask.GetBlueMask() != 0x001F) 883 return false; 884 885 // select the matching instantiation for the source's bitmap format 886 switch( nSrcFormat ) 887 { 888 case BMP_FORMAT_1BIT_MSB_PAL: 889 case BMP_FORMAT_1BIT_LSB_PAL: 890 case BMP_FORMAT_4BIT_MSN_PAL: 891 case BMP_FORMAT_4BIT_LSN_PAL: 892 case BMP_FORMAT_8BIT_PAL: 893 break; 894 895 case BMP_FORMAT_8BIT_TC_MASK: 896 // return ImplBlendFromBitmap<BMP_FORMAT_8BIT_TC_MASK>( rDst, rSrc ); 897 case BMP_FORMAT_24BIT_TC_MASK: 898 // return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_MASK>( rDst, rSrc ); 899 case BMP_FORMAT_32BIT_TC_MASK: 900 // return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_MASK>( rDst, rSrc ); 901 break; 902 903 case BMP_FORMAT_16BIT_TC_MSB_MASK: 904 return ImplBlendFromBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( rDst, rSrc, rMsk ); 905 case BMP_FORMAT_16BIT_TC_LSB_MASK: 906 return ImplBlendFromBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( rDst, rSrc, rMsk ); 907 908 case BMP_FORMAT_24BIT_TC_BGR: 909 return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_BGR>( rDst, rSrc, rMsk ); 910 case BMP_FORMAT_24BIT_TC_RGB: 911 return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_RGB>( rDst, rSrc, rMsk ); 912 913 case BMP_FORMAT_32BIT_TC_ABGR: 914 return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_ABGR>( rDst, rSrc, rMsk ); 915 #ifdef FAST_ARGB_BGRA 916 case BMP_FORMAT_32BIT_TC_ARGB: 917 return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_ARGB>( rDst, rSrc, rMsk ); 918 case BMP_FORMAT_32BIT_TC_BGRA: 919 return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_BGRA>( rDst, rSrc, rMsk ); 920 #endif 921 case BMP_FORMAT_32BIT_TC_RGBA: 922 return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_RGBA>( rDst, rSrc, rMsk ); 923 } 924 925 #ifdef DEBUG 926 static int nNotAccelerated = 0; 927 if( rSrc.mnWidth * rSrc.mnHeight >= 4000 ) 928 if( ++nNotAccelerated == 100 ) 929 { 930 int foo = 0; (void)foo; // so no warning is created when building on pro with debug 931 DBG_WARNING3( "ImplFastBlend for not accelerated case (0x%04X*0x%04X->0x%04X)", 932 rSrc.mnFormat, rMsk.mnFormat, rDst.mnFormat ); 933 } 934 #endif 935 936 return false; 937 } 938 939 bool ImplFastEraseBitmap( BitmapBuffer& rDst, const BitmapColor& rColor ) 940 { 941 if( bDisableFastBitops ) 942 return false; 943 944 const sal_uLong nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN; 945 946 // erasing a bitmap is often just a byte-wise memory fill 947 bool bByteFill = true; 948 sal_uInt8 nFillByte; 949 950 switch( nDstFormat ) 951 { 952 case BMP_FORMAT_1BIT_MSB_PAL: 953 case BMP_FORMAT_1BIT_LSB_PAL: 954 nFillByte = rColor.GetIndex(); 955 nFillByte = static_cast<sal_uInt8>( -(nFillByte & 1) ); // 0x00 or 0xFF 956 break; 957 case BMP_FORMAT_4BIT_MSN_PAL: 958 case BMP_FORMAT_4BIT_LSN_PAL: 959 nFillByte = rColor.GetIndex(); 960 nFillByte &= 0x0F; 961 nFillByte |= (nFillByte << 4); 962 break; 963 case BMP_FORMAT_8BIT_PAL: 964 case BMP_FORMAT_8BIT_TC_MASK: 965 nFillByte = rColor.GetIndex(); 966 break; 967 968 case BMP_FORMAT_24BIT_TC_MASK: 969 case BMP_FORMAT_24BIT_TC_BGR: 970 case BMP_FORMAT_24BIT_TC_RGB: 971 nFillByte = rColor.GetRed(); 972 if( (nFillByte != rColor.GetGreen()) 973 || (nFillByte != rColor.GetBlue()) ) 974 bByteFill = false; 975 break; 976 977 default: 978 bByteFill = false; 979 nFillByte = 0x00; 980 break; 981 } 982 983 if( bByteFill ) 984 { 985 long nByteCount = rDst.mnHeight * rDst.mnScanlineSize; 986 rtl_fillMemory( rDst.mpBits, nByteCount, nFillByte ); 987 return true; 988 } 989 990 // TODO: handle other bitmap formats 991 switch( nDstFormat ) 992 { 993 case BMP_FORMAT_32BIT_TC_MASK: 994 case BMP_FORMAT_16BIT_TC_MSB_MASK: 995 case BMP_FORMAT_16BIT_TC_LSB_MASK: 996 997 case BMP_FORMAT_24BIT_TC_BGR: 998 case BMP_FORMAT_24BIT_TC_RGB: 999 1000 case BMP_FORMAT_32BIT_TC_ABGR: 1001 #ifdef FAST_ARGB_BGRA 1002 case BMP_FORMAT_32BIT_TC_ARGB: 1003 case BMP_FORMAT_32BIT_TC_BGRA: 1004 #endif 1005 case BMP_FORMAT_32BIT_TC_RGBA: 1006 break; 1007 1008 default: 1009 break; 1010 } 1011 1012 return false; 1013 } 1014 1015 // ======================================================================= 1016 1017 #else // NO_OPTIMIZED_BITMAP_ACCESS 1018 1019 bool ImplFastBitmapConversion( BitmapBuffer&, const BitmapBuffer& ) 1020 { 1021 return false; 1022 } 1023 1024 bool ImplFastBitmapBlending( BitmapWriteAccess&, 1025 const BitmapReadAccess&, const BitmapReadAccess&, 1026 const Size&, const Point& ) 1027 { 1028 return false; 1029 } 1030 1031 bool ImplFastEraseBitmap( BitmapBuffer&, const BitmapColor& ) 1032 { 1033 return false; 1034 } 1035 1036 #endif 1037