update dev300-m58
[ooovba.git] / vcl / source / gdi / bmpfast.cxx
blob1e53a6085724c38a92b29ba5b5844a7d84c88eb7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bmpfast.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <vcl/bmpfast.hxx>
36 #ifndef NO_OPTIMIZED_BITMAP_ACCESS
38 #include <tools/debug.hxx>
39 #include <vcl/bmpacc.hxx>
41 #define FAST_ARGB_BGRA
43 #include <stdlib.h>
44 static bool bDisableFastBitops = (getenv( "SAL_DISABLE_BITMAPS_OPTS" ) != NULL);
46 typedef unsigned char PIXBYTE;
48 class BasePixelPtr
50 public:
51 BasePixelPtr( PIXBYTE* p = NULL ) : mpPixel( p ) {}
52 void SetRawPtr( PIXBYTE* pRawPtr ) { mpPixel = pRawPtr; }
53 PIXBYTE* GetRawPtr( void ) const { return mpPixel; }
54 void AddByteOffset( int nByteOffset ) { mpPixel += nByteOffset; }
55 bool operator<( const BasePixelPtr& rCmp ) const { return (mpPixel < rCmp.mpPixel); }
57 protected:
58 PIXBYTE* mpPixel;
61 template <ULONG PIXFMT>
62 class TrueColorPixelPtr : public BasePixelPtr
64 public:
65 PIXBYTE GetRed() const;
66 PIXBYTE GetGreen() const;
67 PIXBYTE GetBlue() const;
68 PIXBYTE GetAlpha() const;
70 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const;
71 void SetAlpha( PIXBYTE a ) const;
72 void operator++(int);
75 // =======================================================================
76 // template specializations for truecolor pixel formats
78 template <>
79 class TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_RGB> : public BasePixelPtr
81 public:
82 void operator++() { mpPixel += 3; }
84 PIXBYTE GetRed() const { return mpPixel[0]; }
85 PIXBYTE GetGreen() const { return mpPixel[1]; }
86 PIXBYTE GetBlue() const { return mpPixel[2]; }
87 PIXBYTE GetAlpha() const { return 0; }
88 void SetAlpha( PIXBYTE ) const {}
90 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
92 mpPixel[0] = r;
93 mpPixel[1] = g;
94 mpPixel[2] = b;
98 template <>
99 class TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_BGR> : public BasePixelPtr
101 public:
102 void operator++() { mpPixel += 3; }
104 PIXBYTE GetRed() const { return mpPixel[2]; }
105 PIXBYTE GetGreen() const { return mpPixel[1]; }
106 PIXBYTE GetBlue() const { return mpPixel[0]; }
107 PIXBYTE GetAlpha() const { return 0; }
108 void SetAlpha( PIXBYTE ) const {}
110 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
112 mpPixel[0] = b;
113 mpPixel[1] = g;
114 mpPixel[2] = r;
118 template <>
119 class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ARGB> : public BasePixelPtr
121 public:
122 void operator++() { mpPixel += 4; }
124 PIXBYTE GetRed() const { return mpPixel[1]; }
125 PIXBYTE GetGreen() const { return mpPixel[2]; }
126 PIXBYTE GetBlue() const { return mpPixel[3]; }
127 PIXBYTE GetAlpha() const { return mpPixel[0]; }
128 void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; }
130 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
132 mpPixel[1] = r;
133 mpPixel[2] = g;
134 mpPixel[3] = b;
138 template <>
139 class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ABGR> : public BasePixelPtr
141 public:
142 void operator++() { mpPixel += 4; }
144 PIXBYTE GetRed() const { return mpPixel[3]; }
145 PIXBYTE GetGreen() const { return mpPixel[2]; }
146 PIXBYTE GetBlue() const { return mpPixel[1]; }
147 PIXBYTE GetAlpha() const { return mpPixel[0]; }
148 void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; }
150 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
152 mpPixel[1] = b;
153 mpPixel[2] = g;
154 mpPixel[3] = r;
158 template <>
159 class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_RGBA> : public BasePixelPtr
161 public:
162 void operator++() { mpPixel += 4; }
164 PIXBYTE GetRed() const { return mpPixel[0]; }
165 PIXBYTE GetGreen() const { return mpPixel[1]; }
166 PIXBYTE GetBlue() const { return mpPixel[2]; }
167 PIXBYTE GetAlpha() const { return mpPixel[3]; }
168 void SetAlpha( PIXBYTE a ) const{ mpPixel[3] = a; }
170 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
172 mpPixel[0] = r;
173 mpPixel[1] = g;
174 mpPixel[2] = b;
178 template <>
179 class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_BGRA> : public BasePixelPtr
181 public:
182 void operator++() { mpPixel += 4; }
184 PIXBYTE GetRed() const { return mpPixel[2]; }
185 PIXBYTE GetGreen() const { return mpPixel[1]; }
186 PIXBYTE GetBlue() const { return mpPixel[0]; }
187 PIXBYTE GetAlpha() const { return mpPixel[3]; }
188 void SetAlpha( PIXBYTE a ) const{ mpPixel[3] = a; }
190 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
192 mpPixel[0] = b;
193 mpPixel[1] = g;
194 mpPixel[2] = r;
198 template <>
199 class TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_MSB_MASK> : public BasePixelPtr
201 public:
202 void operator++() { mpPixel += 2; }
204 // TODO: non565-RGB
205 PIXBYTE GetRed() const { return (mpPixel[0] & 0xF8U); }
206 PIXBYTE GetGreen() const { return (mpPixel[0]<<5U) | ((mpPixel[1]>>3U)&28U); }
207 PIXBYTE GetBlue() const { return (mpPixel[1]<<3U); }
208 PIXBYTE GetAlpha() const { return 0; }
209 void SetAlpha( PIXBYTE ) const {}
211 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
213 mpPixel[0] = ((g >> 5U) & 7U) | (r & 0xF8U);
214 mpPixel[1] = ((g & 28U)<< 3U) | (b >> 3U);
218 template <>
219 class TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_LSB_MASK> : public BasePixelPtr
221 public:
222 void operator++() { mpPixel += 2; }
224 // TODO: non565-RGB
225 PIXBYTE GetRed() const { return (mpPixel[1] & 0xF8U); }
226 PIXBYTE GetGreen() const { return (mpPixel[1]<<5U) | ((mpPixel[0]>>3U)&28U); }
227 PIXBYTE GetBlue() const { return (mpPixel[0]<<3U); }
228 PIXBYTE GetAlpha() const { return 0; }
229 void SetAlpha( PIXBYTE ) const {}
231 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
233 mpPixel[0] = ((g & 28U)<< 3U) | (b >> 3U);
234 mpPixel[1] = ((g >> 5U) & 7U) | (r & 0xF8U);
238 // -----------------------------------------------------------------------
240 template <>
241 class TrueColorPixelPtr<BMP_FORMAT_8BIT_TC_MASK> : public BasePixelPtr
243 public:
244 void operator++() { mpPixel += 1; }
245 PIXBYTE GetAlpha() const { return mpPixel[0]; }
246 void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; }
247 void SetColor( PIXBYTE, PIXBYTE, PIXBYTE ) const {}
250 // TODO: for some reason many Alpha maps are BMP_FORMAT_8BIT_PAL
251 // they should be BMP_FORMAT_8BIT_TC_MASK
252 template <>
253 class TrueColorPixelPtr<BMP_FORMAT_8BIT_PAL>
254 : public TrueColorPixelPtr<BMP_FORMAT_8BIT_TC_MASK>
257 #if 0
258 template <>
259 class TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_MASK> : public BasePixelPtr
261 public:
262 void operator++() { mpPixel += 3; }
264 unsigned GetAlpha() const
266 unsigned nAlpha = mpPixel[0];
267 nAlpha |= mpPixel[1] << 8U;
268 nAlpha |= mpPixel[2] << 16U;
269 return nAlpha;
272 void SetAlpha( unsigned nAlpha ) const
274 mpPixel[0] = nAlpha;
275 mpPixel[1] = nAlpha >> 8U;
276 mpPixel[2] = nAlpha >> 16U;
280 template <>
281 class TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_MASK> : public BasePixelPtr
283 public:
284 void operator++() { mpPixel += 4; }
286 unsigned GetAlpha() const
288 #ifdef OSL_BIGENDIAN
289 unsigned nAlpha = *reinterpret_cast<unsigned*>( mpPixel );
290 #else
291 unsigned nAlpha = mpPixel[0];
292 nAlpha |= mpPixel[1] << 8U;
293 nAlpha |= mpPixel[2] << 16U;
294 nAlpha |= mpPixel[3] << 24U;
295 #endif
296 return nAlpha;
299 void SetAlpha( unsigned nAlpha ) const
301 #ifdef OSL_BIGENDIAN
302 *reinterpret_cast<unsigned*>( mpPixel ) = nAlpha;
303 #else
304 mpPixel[0] = nAlpha;
305 mpPixel[1] = nAlpha >> 8U;
306 mpPixel[2] = nAlpha >> 16U;
307 mpPixel[3] = nAlpha >> 24U;
308 #endif
312 #endif
314 // =======================================================================
315 // converting truecolor formats
317 template <ULONG SRCFMT, ULONG DSTFMT>
318 inline void ImplConvertPixel( const TrueColorPixelPtr<DSTFMT>& rDst,
319 const TrueColorPixelPtr<SRCFMT>& rSrc )
321 rDst.SetColor( rSrc.GetRed(), rSrc.GetGreen(), rSrc.GetBlue() );
322 rDst.SetAlpha( rSrc.GetAlpha() );
325 // -----------------------------------------------------------------------
327 template <>
328 inline void ImplConvertPixel<BMP_FORMAT_16BIT_TC_LSB_MASK, BMP_FORMAT_16BIT_TC_MSB_MASK> (
329 const TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_MSB_MASK>& rDst,
330 const TrueColorPixelPtr<BMP_FORMAT_16BIT_TC_LSB_MASK>& rSrc )
332 // byte swapping
333 const PIXBYTE* pSrc = rSrc.GetRawPtr();
334 PIXBYTE* pDst = rDst.GetRawPtr();
335 pDst[1] = pSrc[0];
336 pDst[0] = pSrc[1];
339 // -----------------------------------------------------------------------
341 template <ULONG SRCFMT, ULONG DSTFMT>
342 inline void ImplConvertLine( const TrueColorPixelPtr<DSTFMT>& rDst,
343 const TrueColorPixelPtr<SRCFMT>& rSrc, int nPixelCount )
345 TrueColorPixelPtr<DSTFMT> aDst( rDst );
346 TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
347 while( --nPixelCount >= 0 )
349 ImplConvertPixel( aDst, aSrc );
350 ++aSrc;
351 ++aDst;
355 // =======================================================================
356 // alpha blending truecolor pixels
358 template <unsigned ALPHABITS, ULONG SRCFMT, ULONG DSTFMT>
359 inline void ImplBlendPixels( const TrueColorPixelPtr<DSTFMT>& rDst,
360 const TrueColorPixelPtr<SRCFMT>& rSrc, unsigned nAlphaVal )
362 if( !nAlphaVal )
363 ImplConvertPixel( rDst, rSrc );
364 else if( nAlphaVal != ~(~0 << ALPHABITS) )
366 static const unsigned nAlphaShift = (ALPHABITS > 8) ? 8 : ALPHABITS;
367 if( ALPHABITS > nAlphaShift )
368 nAlphaVal >>= ALPHABITS - nAlphaShift;
370 int nR = rDst.GetRed();
371 int nS = rSrc.GetRed();
372 nR = nS + (((nR - nS) * nAlphaVal) >> nAlphaShift);
374 int nG = rDst.GetGreen();
375 nS = rSrc.GetGreen();
376 nG = nS + (((nG - nS) * nAlphaVal) >> nAlphaShift);
378 int nB = rDst.GetBlue();
379 nS = rSrc.GetBlue();
380 nB = nS + (((nB - nS) * nAlphaVal) >> nAlphaShift);
382 rDst.SetColor( sal::static_int_cast<PIXBYTE>(nR),
383 sal::static_int_cast<PIXBYTE>(nG),
384 sal::static_int_cast<PIXBYTE>(nB) );
388 // -----------------------------------------------------------------------
390 template <unsigned ALPHABITS, ULONG MASKFMT, ULONG SRCFMT, ULONG DSTFMT>
391 inline void ImplBlendLines( const TrueColorPixelPtr<DSTFMT>& rDst,
392 const TrueColorPixelPtr<SRCFMT>& rSrc, const TrueColorPixelPtr<MASKFMT>& rMsk,
393 int nPixelCount )
395 TrueColorPixelPtr<MASKFMT> aMsk( rMsk );
396 TrueColorPixelPtr<DSTFMT> aDst( rDst );
397 TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
398 while( --nPixelCount >= 0 )
400 ImplBlendPixels<ALPHABITS>( aDst, aSrc, aMsk.GetAlpha() );
401 ++aDst;
402 ++aSrc;
403 ++aMsk;
407 // -----------------------------------------------------------------------
409 template <unsigned ALPHABITS, ULONG SRCFMT, ULONG DSTFMT>
410 inline void ImplBlendLines( const TrueColorPixelPtr<DSTFMT>& rDst,
411 const TrueColorPixelPtr<SRCFMT>& rSrc, unsigned nAlphaVal,
412 int nPixelCount )
414 if( nAlphaVal == ~(~0 << ALPHABITS) )
415 ImplConvertLine( rDst, rSrc, nPixelCount );
416 else if( nAlphaVal )
418 TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
419 TrueColorPixelPtr<DSTFMT> aDst( rDst );
420 while( --nPixelCount >= 0 )
422 ImplBlendPixels<ALPHABITS>( aDst, aSrc, nAlphaVal );
423 ++aDst;
424 ++aSrc;
429 // =======================================================================
431 static bool ImplCopyImage( BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer )
433 const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
434 int nDstLinestep = rDstBuffer.mnScanlineSize;
436 const PIXBYTE* pRawSrc = rSrcBuffer.mpBits;
437 PIXBYTE* pRawDst = rDstBuffer.mpBits;
439 // source and destination don't match upside down
440 if( BMP_FORMAT_TOP_DOWN & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) )
442 pRawDst += (rSrcBuffer.mnHeight - 1) * nDstLinestep;
443 nDstLinestep = -rDstBuffer.mnScanlineSize;
445 else if( nSrcLinestep == nDstLinestep )
447 memcpy( pRawDst, pRawSrc, rSrcBuffer.mnHeight * nDstLinestep );
448 return true;
451 int nByteWidth = nSrcLinestep;
452 if( nByteWidth > rDstBuffer.mnScanlineSize )
453 nByteWidth = rDstBuffer.mnScanlineSize;
455 for( int y = rSrcBuffer.mnHeight; --y >= 0; )
457 memcpy( pRawDst, pRawSrc, nByteWidth );
458 pRawSrc += nSrcLinestep;
459 pRawDst += nDstLinestep;
462 return true;
465 // -----------------------------------------------------------------------
467 template <ULONG DSTFMT,ULONG SRCFMT>
468 bool ImplConvertToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
469 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer )
471 // help the compiler to avoid instantiations of unneeded conversions
472 DBG_ASSERT( SRCFMT != DSTFMT, "ImplConvertToBitmap into same format");
473 if( SRCFMT == DSTFMT )
474 return false;
476 const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
477 int nDstLinestep = rDstBuffer.mnScanlineSize;
479 TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
481 // source and destination don't match upside down
482 if( BMP_FORMAT_TOP_DOWN & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) )
484 aDstLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nDstLinestep );
485 nDstLinestep = -nDstLinestep;
488 for( int y = rSrcBuffer.mnHeight; --y >= 0; )
490 ImplConvertLine( aDstLine, rSrcLine, rSrcBuffer.mnWidth );
491 rSrcLine.AddByteOffset( nSrcLinestep );
492 aDstLine.AddByteOffset( nDstLinestep );
495 return true;
498 // -----------------------------------------------------------------------
500 template <ULONG SRCFMT>
501 inline bool ImplConvertFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc )
503 TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
505 // select the matching instantiation for the destination's bitmap format
506 switch( rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN )
508 case BMP_FORMAT_1BIT_MSB_PAL:
509 case BMP_FORMAT_1BIT_LSB_PAL:
510 case BMP_FORMAT_4BIT_MSN_PAL:
511 case BMP_FORMAT_4BIT_LSN_PAL:
512 case BMP_FORMAT_8BIT_PAL:
513 break;
515 case BMP_FORMAT_8BIT_TC_MASK:
516 // return ImplConvertToBitmap<BMP_FORMAT_8BIT_TC_MASK>( aSrcType, rDst, rSrc );
517 case BMP_FORMAT_24BIT_TC_MASK:
518 // return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_MASK>( aSrcType, rDst, rSrc );
519 case BMP_FORMAT_32BIT_TC_MASK:
520 // return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_MASK>( aSrcType, rDst, rSrc );
521 break;
523 case BMP_FORMAT_16BIT_TC_MSB_MASK:
524 return ImplConvertToBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( aSrcType, rDst, rSrc );
525 case BMP_FORMAT_16BIT_TC_LSB_MASK:
526 return ImplConvertToBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( aSrcType, rDst, rSrc );
528 case BMP_FORMAT_24BIT_TC_BGR:
529 return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_BGR>( aSrcType, rDst, rSrc );
530 case BMP_FORMAT_24BIT_TC_RGB:
531 return ImplConvertToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDst, rSrc );
533 case BMP_FORMAT_32BIT_TC_ABGR:
534 return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_ABGR>( aSrcType, rDst, rSrc );
535 #ifdef FAST_ARGB_BGRA
536 case BMP_FORMAT_32BIT_TC_ARGB:
537 return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDst, rSrc );
538 case BMP_FORMAT_32BIT_TC_BGRA:
539 return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_BGRA>( aSrcType, rDst, rSrc );
540 #endif
541 case BMP_FORMAT_32BIT_TC_RGBA:
542 return ImplConvertToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDst, rSrc );
545 #ifdef DEBUG
546 static int nNotAccelerated = 0;
547 if( rSrc.mnWidth * rSrc.mnHeight >= 4000 )
548 if( ++nNotAccelerated == 100 )
550 int foo = 0; (void)foo; // so no warning is created when building on pro with debug
551 DBG_WARNING2( "ImplConvertFromBitmap for not accelerated case (0x%04X->0x%04X)",
552 rSrc.mnFormat, rDst.mnFormat );
554 #endif
556 return false;
559 // =======================================================================
561 // an universal stretching conversion is overkill in most common situations
562 // => performance benefits for speeding up the non-stretching cases
563 bool ImplFastBitmapConversion( BitmapBuffer& rDst, const BitmapBuffer& rSrc,
564 const SalTwoRect& rTR )
566 if( bDisableFastBitops )
567 return false;
569 // horizontal mirroring not implemented yet
570 if( rTR.mnDestWidth < 0 )
571 return false;
572 // vertical mirroring
573 if( rTR.mnDestHeight < 0 )
574 // TODO: rDst.mnFormat ^= BMP_FORMAT_TOP_DOWN;
575 return false;
577 // offseted conversion is not implemented yet
578 if( rTR.mnSrcX || rTR.mnSrcY )
579 return false;
580 if( rTR.mnDestX || rTR.mnDestY )
581 return false;
583 // stretched conversion is not implemented yet
584 if( rTR.mnDestWidth != rTR.mnSrcWidth )
585 return false;
586 if( rTR.mnDestHeight!= rTR.mnSrcHeight )
587 return false;
589 // check source image size
590 if( rSrc.mnWidth < rTR.mnSrcX + rTR.mnSrcWidth )
591 return false;
592 if( rSrc.mnHeight < rTR.mnSrcY + rTR.mnSrcHeight )
593 return false;
595 // check dest image size
596 if( rDst.mnWidth < rTR.mnDestX + rTR.mnDestWidth )
597 return false;
598 if( rDst.mnHeight < rTR.mnDestY + rTR.mnDestHeight )
599 return false;
601 const ULONG nSrcFormat = rSrc.mnFormat & ~BMP_FORMAT_TOP_DOWN;
602 const ULONG nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN;
604 // TODO: also implement conversions for 16bit colormasks with non-565 format
605 if( nSrcFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
606 if( rSrc.maColorMask.GetRedMask() != 0xF800
607 || rSrc.maColorMask.GetGreenMask()!= 0x07E0
608 || rSrc.maColorMask.GetBlueMask() != 0x001F )
609 return false;
610 if( nDstFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
611 if( rDst.maColorMask.GetRedMask() != 0xF800
612 || rDst.maColorMask.GetGreenMask()!= 0x07E0
613 || rDst.maColorMask.GetBlueMask() != 0x001F )
614 return false;
616 // special handling of trivial cases
617 if( nSrcFormat == nDstFormat )
619 // accelerated palette conversions not yet implemented
620 if( rSrc.maPalette != rDst.maPalette )
621 return false;
622 return ImplCopyImage( rDst, rSrc );
625 // select the matching instantiation for the source's bitmap format
626 switch( nSrcFormat )
628 case BMP_FORMAT_1BIT_MSB_PAL:
629 case BMP_FORMAT_1BIT_LSB_PAL:
630 case BMP_FORMAT_4BIT_MSN_PAL:
631 case BMP_FORMAT_4BIT_LSN_PAL:
632 case BMP_FORMAT_8BIT_PAL:
633 break;
635 case BMP_FORMAT_8BIT_TC_MASK:
636 // return ImplConvertFromBitmap<BMP_FORMAT_8BIT_TC_MASK>( rDst, rSrc );
637 case BMP_FORMAT_24BIT_TC_MASK:
638 // return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_MASK>( rDst, rSrc );
639 case BMP_FORMAT_32BIT_TC_MASK:
640 // return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_MASK>( rDst, rSrc );
641 break;
643 case BMP_FORMAT_16BIT_TC_MSB_MASK:
644 return ImplConvertFromBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( rDst, rSrc );
645 case BMP_FORMAT_16BIT_TC_LSB_MASK:
646 return ImplConvertFromBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( rDst, rSrc );
648 case BMP_FORMAT_24BIT_TC_BGR:
649 return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_BGR>( rDst, rSrc );
650 case BMP_FORMAT_24BIT_TC_RGB:
651 return ImplConvertFromBitmap<BMP_FORMAT_24BIT_TC_RGB>( rDst, rSrc );
653 case BMP_FORMAT_32BIT_TC_ABGR:
654 return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_ABGR>( rDst, rSrc );
655 #ifdef FAST_ARGB_BGRA
656 case BMP_FORMAT_32BIT_TC_ARGB:
657 return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_ARGB>( rDst, rSrc );
658 case BMP_FORMAT_32BIT_TC_BGRA:
659 return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_BGRA>( rDst, rSrc );
660 #endif
661 case BMP_FORMAT_32BIT_TC_RGBA:
662 return ImplConvertFromBitmap<BMP_FORMAT_32BIT_TC_RGBA>( rDst, rSrc );
665 #ifdef DEBUG
666 static int nNotAccelerated = 0;
667 if( rSrc.mnWidth * rSrc.mnHeight >= 4000 )
669 if( ++nNotAccelerated == 100 )
671 int foo = 0; (void)foo; // so no warning is created when building on pro with debug
672 DBG_WARNING2( "ImplFastBitmapConversion for not accelerated case (0x%04X->0x%04X)", rSrc.mnFormat, rDst.mnFormat );
675 #endif
677 return false;
680 // =======================================================================
682 template <ULONG DSTFMT,ULONG SRCFMT> //,ULONG MSKFMT>
683 bool ImplBlendToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
684 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
685 const BitmapBuffer& rMskBuffer )
687 //DBG_ASSERT( rMskBuffer.mnFormat == MSKFMT, "FastBmp BlendImage: wrong MSKFMT" );
688 DBG_ASSERT( rMskBuffer.mnFormat == BMP_FORMAT_8BIT_PAL, "FastBmp BlendImage: unusual MSKFMT" );
690 const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
691 int nMskLinestep = rMskBuffer.mnScanlineSize;
692 int nDstLinestep = rDstBuffer.mnScanlineSize;
694 TrueColorPixelPtr<BMP_FORMAT_8BIT_PAL> aMskLine; aMskLine.SetRawPtr( rMskBuffer.mpBits );
695 TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
697 // special case for single line masks
698 if( rMskBuffer.mnHeight == 1 )
699 nMskLinestep = 0;
701 // source and mask don't match: upside down
702 if( (rSrcBuffer.mnFormat ^ rMskBuffer.mnFormat) & BMP_FORMAT_TOP_DOWN )
704 aMskLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nMskLinestep );
705 nMskLinestep = -nMskLinestep;
708 // source and destination don't match: upside down
709 if( (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) & BMP_FORMAT_TOP_DOWN )
711 aDstLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nDstLinestep );
712 nDstLinestep = -nDstLinestep;
715 for( int y = rSrcBuffer.mnHeight; --y >= 0; )
717 ImplBlendLines<8>( aDstLine, rSrcLine, aMskLine, rDstBuffer.mnWidth );
718 aDstLine.AddByteOffset( nDstLinestep );
719 rSrcLine.AddByteOffset( nSrcLinestep );
720 aMskLine.AddByteOffset( nMskLinestep );
723 return true;
726 // some specializations to reduce the code size
727 template <>
728 inline bool ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_BGR,BMP_FORMAT_24BIT_TC_BGR>(
729 TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_BGR>&,
730 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
731 const BitmapBuffer& rMskBuffer )
733 TrueColorPixelPtr<BMP_FORMAT_24BIT_TC_RGB> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
734 return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
737 template <>
738 inline bool ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ABGR,BMP_FORMAT_32BIT_TC_ABGR>(
739 TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ABGR>&,
740 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
741 const BitmapBuffer& rMskBuffer )
743 TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_ARGB> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
744 return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
747 template <>
748 inline bool ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_BGRA,BMP_FORMAT_32BIT_TC_BGRA>(
749 TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_BGRA>&,
750 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
751 const BitmapBuffer& rMskBuffer )
753 TrueColorPixelPtr<BMP_FORMAT_32BIT_TC_RGBA> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
754 return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
757 // -----------------------------------------------------------------------
759 template <ULONG SRCFMT>
760 bool ImplBlendFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc, const BitmapBuffer& rMsk )
762 TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
764 // select the matching instantiation for the destination's bitmap format
765 switch( rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN )
767 case BMP_FORMAT_1BIT_MSB_PAL:
768 case BMP_FORMAT_1BIT_LSB_PAL:
769 case BMP_FORMAT_4BIT_MSN_PAL:
770 case BMP_FORMAT_4BIT_LSN_PAL:
771 case BMP_FORMAT_8BIT_PAL:
772 break;
774 case BMP_FORMAT_8BIT_TC_MASK:
775 // return ImplBlendToBitmap<BMP_FORMAT_8BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk );
776 case BMP_FORMAT_24BIT_TC_MASK:
777 // return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk );
778 case BMP_FORMAT_32BIT_TC_MASK:
779 // return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_MASK>( aSrcType, rDst, rSrc, rMsk );
780 break;
782 case BMP_FORMAT_16BIT_TC_MSB_MASK:
783 return ImplBlendToBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( aSrcType, rDst, rSrc, rMsk );
784 case BMP_FORMAT_16BIT_TC_LSB_MASK:
785 return ImplBlendToBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( aSrcType, rDst, rSrc, rMsk );
787 case BMP_FORMAT_24BIT_TC_BGR:
788 return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_BGR>( aSrcType, rDst, rSrc, rMsk );
789 case BMP_FORMAT_24BIT_TC_RGB:
790 return ImplBlendToBitmap<BMP_FORMAT_24BIT_TC_RGB>( aSrcType, rDst, rSrc, rMsk );
792 case BMP_FORMAT_32BIT_TC_ABGR:
793 return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ABGR>( aSrcType, rDst, rSrc, rMsk );
794 #ifdef FAST_ARGB_BGRA
795 case BMP_FORMAT_32BIT_TC_ARGB:
796 return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_ARGB>( aSrcType, rDst, rSrc, rMsk );
797 case BMP_FORMAT_32BIT_TC_BGRA:
798 return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_BGRA>( aSrcType, rDst, rSrc, rMsk );
799 #endif
800 case BMP_FORMAT_32BIT_TC_RGBA:
801 return ImplBlendToBitmap<BMP_FORMAT_32BIT_TC_RGBA>( aSrcType, rDst, rSrc, rMsk );
804 #ifdef DEBUG
805 static int nNotAccelerated = 0;
806 if( rSrc.mnWidth * rSrc.mnHeight >= 4000 )
807 if( ++nNotAccelerated == 100 )
809 int foo = 0; (void)foo; // so no warning is created when building on pro with debug
810 DBG_WARNING3( "ImplBlendFromBitmap for not accelerated case (0x%04X*0x%04X->0x%04X)",
811 rSrc.mnFormat, rMsk.mnFormat, rDst.mnFormat );
813 #endif
815 return false;
818 // -----------------------------------------------------------------------
820 bool ImplFastBitmapBlending( BitmapWriteAccess& rDstWA,
821 const BitmapReadAccess& rSrcRA, const BitmapReadAccess& rMskRA,
822 const SalTwoRect& rTR )
824 if( bDisableFastBitops )
825 return false;
827 // accelerated blending of paletted bitmaps not implemented yet
828 if( rSrcRA.HasPalette() )
829 return false;
830 if( rDstWA.HasPalette() )
831 return false;
832 // TODO: either get rid of mask's use of 8BIT_PAL or check the palette
834 // horizontal mirroring not implemented yet
835 if( rTR.mnDestWidth < 0 )
836 return false;
837 // vertical mirroring
838 if( rTR.mnDestHeight < 0 )
839 // TODO: rDst.mnFormat ^= BMP_FORMAT_TOP_DOWN;
840 return false;
842 // offseted blending is not implemented yet
843 if( rTR.mnSrcX || rTR.mnSrcY )
844 return false;
845 if( rTR.mnDestX || rTR.mnDestY )
846 return false;
848 // stretched blending is not implemented yet
849 if( rTR.mnDestWidth != rTR.mnSrcWidth )
850 return false;
851 if( rTR.mnDestHeight!= rTR.mnSrcHeight )
852 return false;
854 // check source image size
855 if( rSrcRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
856 return false;
857 if( rSrcRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
858 return false;
860 // check mask image size
861 if( rMskRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
862 return false;
863 if( rMskRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
864 if( rMskRA.Height() != 1 )
865 return false;
867 // check dest image size
868 if( rDstWA.Width() < rTR.mnDestX + rTR.mnDestWidth )
869 return false;
870 if( rDstWA.Height() < rTR.mnDestY + rTR.mnDestHeight )
871 return false;
873 BitmapBuffer& rDst = *rDstWA.ImplGetBitmapBuffer();
874 const BitmapBuffer& rSrc = *rSrcRA.ImplGetBitmapBuffer();
875 const BitmapBuffer& rMsk = *rMskRA.ImplGetBitmapBuffer();
877 const ULONG nSrcFormat = rSrc.mnFormat & ~BMP_FORMAT_TOP_DOWN;
878 const ULONG nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN;
880 // accelerated conversions for 16bit colormasks with non-565 format are not yet implemented
881 if( nSrcFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
882 if( rSrc.maColorMask.GetRedMask() != 0xF800
883 || rSrc.maColorMask.GetGreenMask()!= 0x07E0
884 || rSrc.maColorMask.GetBlueMask() != 0x001F)
885 return false;
886 if( nDstFormat & (BMP_FORMAT_16BIT_TC_LSB_MASK | BMP_FORMAT_16BIT_TC_MSB_MASK) )
887 if( rDst.maColorMask.GetRedMask() != 0xF800
888 || rDst.maColorMask.GetGreenMask()!= 0x07E0
889 || rDst.maColorMask.GetBlueMask() != 0x001F)
890 return false;
892 // select the matching instantiation for the source's bitmap format
893 switch( nSrcFormat )
895 case BMP_FORMAT_1BIT_MSB_PAL:
896 case BMP_FORMAT_1BIT_LSB_PAL:
897 case BMP_FORMAT_4BIT_MSN_PAL:
898 case BMP_FORMAT_4BIT_LSN_PAL:
899 case BMP_FORMAT_8BIT_PAL:
900 break;
902 case BMP_FORMAT_8BIT_TC_MASK:
903 // return ImplBlendFromBitmap<BMP_FORMAT_8BIT_TC_MASK>( rDst, rSrc );
904 case BMP_FORMAT_24BIT_TC_MASK:
905 // return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_MASK>( rDst, rSrc );
906 case BMP_FORMAT_32BIT_TC_MASK:
907 // return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_MASK>( rDst, rSrc );
908 break;
910 case BMP_FORMAT_16BIT_TC_MSB_MASK:
911 return ImplBlendFromBitmap<BMP_FORMAT_16BIT_TC_MSB_MASK>( rDst, rSrc, rMsk );
912 case BMP_FORMAT_16BIT_TC_LSB_MASK:
913 return ImplBlendFromBitmap<BMP_FORMAT_16BIT_TC_LSB_MASK>( rDst, rSrc, rMsk );
915 case BMP_FORMAT_24BIT_TC_BGR:
916 return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_BGR>( rDst, rSrc, rMsk );
917 case BMP_FORMAT_24BIT_TC_RGB:
918 return ImplBlendFromBitmap<BMP_FORMAT_24BIT_TC_RGB>( rDst, rSrc, rMsk );
920 case BMP_FORMAT_32BIT_TC_ABGR:
921 return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_ABGR>( rDst, rSrc, rMsk );
922 #ifdef FAST_ARGB_BGRA
923 case BMP_FORMAT_32BIT_TC_ARGB:
924 return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_ARGB>( rDst, rSrc, rMsk );
925 case BMP_FORMAT_32BIT_TC_BGRA:
926 return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_BGRA>( rDst, rSrc, rMsk );
927 #endif
928 case BMP_FORMAT_32BIT_TC_RGBA:
929 return ImplBlendFromBitmap<BMP_FORMAT_32BIT_TC_RGBA>( rDst, rSrc, rMsk );
932 #ifdef DEBUG
933 static int nNotAccelerated = 0;
934 if( rSrc.mnWidth * rSrc.mnHeight >= 4000 )
935 if( ++nNotAccelerated == 100 )
937 int foo = 0; (void)foo; // so no warning is created when building on pro with debug
938 DBG_WARNING3( "ImplFastBlend for not accelerated case (0x%04X*0x%04X->0x%04X)",
939 rSrc.mnFormat, rMsk.mnFormat, rDst.mnFormat );
941 #endif
943 return false;
946 bool ImplFastEraseBitmap( BitmapBuffer& rDst, const BitmapColor& rColor )
948 if( bDisableFastBitops )
949 return false;
951 const ULONG nDstFormat = rDst.mnFormat & ~BMP_FORMAT_TOP_DOWN;
953 // erasing a bitmap is often just a byte-wise memory fill
954 bool bByteFill = true;
955 BYTE nFillByte;
957 switch( nDstFormat )
959 case BMP_FORMAT_1BIT_MSB_PAL:
960 case BMP_FORMAT_1BIT_LSB_PAL:
961 nFillByte = rColor.GetIndex();
962 nFillByte = static_cast<BYTE>( -(nFillByte & 1) ); // 0x00 or 0xFF
963 break;
964 case BMP_FORMAT_4BIT_MSN_PAL:
965 case BMP_FORMAT_4BIT_LSN_PAL:
966 nFillByte = rColor.GetIndex();
967 nFillByte &= 0x0F;
968 nFillByte |= (nFillByte << 4);
969 break;
970 case BMP_FORMAT_8BIT_PAL:
971 case BMP_FORMAT_8BIT_TC_MASK:
972 nFillByte = rColor.GetIndex();
973 break;
975 case BMP_FORMAT_24BIT_TC_MASK:
976 case BMP_FORMAT_24BIT_TC_BGR:
977 case BMP_FORMAT_24BIT_TC_RGB:
978 nFillByte = rColor.GetRed();
979 if( (nFillByte != rColor.GetGreen())
980 || (nFillByte != rColor.GetBlue()) )
981 bByteFill = false;
982 break;
984 default:
985 bByteFill = false;
986 nFillByte = 0x00;
987 break;
990 if( bByteFill )
992 long nByteCount = rDst.mnHeight * rDst.mnScanlineSize;
993 rtl_fillMemory( rDst.mpBits, nByteCount, nFillByte );
994 return true;
997 // TODO: handle other bitmap formats
998 switch( nDstFormat )
1000 case BMP_FORMAT_32BIT_TC_MASK:
1001 case BMP_FORMAT_16BIT_TC_MSB_MASK:
1002 case BMP_FORMAT_16BIT_TC_LSB_MASK:
1004 case BMP_FORMAT_24BIT_TC_BGR:
1005 case BMP_FORMAT_24BIT_TC_RGB:
1007 case BMP_FORMAT_32BIT_TC_ABGR:
1008 #ifdef FAST_ARGB_BGRA
1009 case BMP_FORMAT_32BIT_TC_ARGB:
1010 case BMP_FORMAT_32BIT_TC_BGRA:
1011 #endif
1012 case BMP_FORMAT_32BIT_TC_RGBA:
1013 break;
1015 default:
1016 break;
1019 return false;
1022 // =======================================================================
1024 #else // NO_OPTIMIZED_BITMAP_ACCESS
1026 bool ImplFastBitmapConversion( BitmapBuffer&, const BitmapBuffer& )
1028 return false;
1031 bool ImplFastBitmapBlending( BitmapWriteAccess&,
1032 const BitmapReadAccess&, const BitmapReadAccess&,
1033 const Size&, const Point& )
1035 return false;
1038 bool ImplFastEraseBitmap( BitmapBuffer&, const BitmapColor& )
1040 return false;
1043 #endif