1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bmpfast.cxx,v $
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
44 static bool bDisableFastBitops
= (getenv( "SAL_DISABLE_BITMAPS_OPTS" ) != NULL
);
46 typedef unsigned char PIXBYTE
;
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
); }
61 template <ULONG PIXFMT
>
62 class TrueColorPixelPtr
: public BasePixelPtr
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;
75 // =======================================================================
76 // template specializations for truecolor pixel formats
79 class TrueColorPixelPtr
<BMP_FORMAT_24BIT_TC_RGB
> : public BasePixelPtr
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
99 class TrueColorPixelPtr
<BMP_FORMAT_24BIT_TC_BGR
> : public BasePixelPtr
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
119 class TrueColorPixelPtr
<BMP_FORMAT_32BIT_TC_ARGB
> : public BasePixelPtr
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
139 class TrueColorPixelPtr
<BMP_FORMAT_32BIT_TC_ABGR
> : public BasePixelPtr
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
159 class TrueColorPixelPtr
<BMP_FORMAT_32BIT_TC_RGBA
> : public BasePixelPtr
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
179 class TrueColorPixelPtr
<BMP_FORMAT_32BIT_TC_BGRA
> : public BasePixelPtr
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
199 class TrueColorPixelPtr
<BMP_FORMAT_16BIT_TC_MSB_MASK
> : public BasePixelPtr
202 void operator++() { mpPixel
+= 2; }
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);
219 class TrueColorPixelPtr
<BMP_FORMAT_16BIT_TC_LSB_MASK
> : public BasePixelPtr
222 void operator++() { mpPixel
+= 2; }
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 // -----------------------------------------------------------------------
241 class TrueColorPixelPtr
<BMP_FORMAT_8BIT_TC_MASK
> : public BasePixelPtr
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
253 class TrueColorPixelPtr
<BMP_FORMAT_8BIT_PAL
>
254 : public TrueColorPixelPtr
<BMP_FORMAT_8BIT_TC_MASK
>
259 class TrueColorPixelPtr
<BMP_FORMAT_24BIT_TC_MASK
> : public BasePixelPtr
262 void operator++() { mpPixel
+= 3; }
264 unsigned GetAlpha() const
266 unsigned nAlpha
= mpPixel
[0];
267 nAlpha
|= mpPixel
[1] << 8U;
268 nAlpha
|= mpPixel
[2] << 16U;
272 void SetAlpha( unsigned nAlpha
) const
275 mpPixel
[1] = nAlpha
>> 8U;
276 mpPixel
[2] = nAlpha
>> 16U;
281 class TrueColorPixelPtr
<BMP_FORMAT_32BIT_TC_MASK
> : public BasePixelPtr
284 void operator++() { mpPixel
+= 4; }
286 unsigned GetAlpha() const
289 unsigned nAlpha
= *reinterpret_cast<unsigned*>( mpPixel
);
291 unsigned nAlpha
= mpPixel
[0];
292 nAlpha
|= mpPixel
[1] << 8U;
293 nAlpha
|= mpPixel
[2] << 16U;
294 nAlpha
|= mpPixel
[3] << 24U;
299 void SetAlpha( unsigned nAlpha
) const
302 *reinterpret_cast<unsigned*>( mpPixel
) = nAlpha
;
305 mpPixel
[1] = nAlpha
>> 8U;
306 mpPixel
[2] = nAlpha
>> 16U;
307 mpPixel
[3] = nAlpha
>> 24U;
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 // -----------------------------------------------------------------------
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
)
333 const PIXBYTE
* pSrc
= rSrc
.GetRawPtr();
334 PIXBYTE
* pDst
= rDst
.GetRawPtr();
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
);
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
)
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();
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
,
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() );
407 // -----------------------------------------------------------------------
409 template <unsigned ALPHABITS
, ULONG SRCFMT
, ULONG DSTFMT
>
410 inline void ImplBlendLines( const TrueColorPixelPtr
<DSTFMT
>& rDst
,
411 const TrueColorPixelPtr
<SRCFMT
>& rSrc
, unsigned nAlphaVal
,
414 if( nAlphaVal
== ~(~0 << ALPHABITS
) )
415 ImplConvertLine( rDst
, rSrc
, nPixelCount
);
418 TrueColorPixelPtr
<SRCFMT
> aSrc( rSrc
);
419 TrueColorPixelPtr
<DSTFMT
> aDst( rDst
);
420 while( --nPixelCount
>= 0 )
422 ImplBlendPixels
<ALPHABITS
>( aDst
, aSrc
, nAlphaVal
);
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
);
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
;
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
)
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
);
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
:
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 );
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
);
541 case BMP_FORMAT_32BIT_TC_RGBA
:
542 return ImplConvertToBitmap
<BMP_FORMAT_32BIT_TC_RGBA
>( aSrcType
, rDst
, rSrc
);
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
);
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
)
569 // horizontal mirroring not implemented yet
570 if( rTR
.mnDestWidth
< 0 )
572 // vertical mirroring
573 if( rTR
.mnDestHeight
< 0 )
574 // TODO: rDst.mnFormat ^= BMP_FORMAT_TOP_DOWN;
577 // offseted conversion is not implemented yet
578 if( rTR
.mnSrcX
|| rTR
.mnSrcY
)
580 if( rTR
.mnDestX
|| rTR
.mnDestY
)
583 // stretched conversion is not implemented yet
584 if( rTR
.mnDestWidth
!= rTR
.mnSrcWidth
)
586 if( rTR
.mnDestHeight
!= rTR
.mnSrcHeight
)
589 // check source image size
590 if( rSrc
.mnWidth
< rTR
.mnSrcX
+ rTR
.mnSrcWidth
)
592 if( rSrc
.mnHeight
< rTR
.mnSrcY
+ rTR
.mnSrcHeight
)
595 // check dest image size
596 if( rDst
.mnWidth
< rTR
.mnDestX
+ rTR
.mnDestWidth
)
598 if( rDst
.mnHeight
< rTR
.mnDestY
+ rTR
.mnDestHeight
)
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 )
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 )
616 // special handling of trivial cases
617 if( nSrcFormat
== nDstFormat
)
619 // accelerated palette conversions not yet implemented
620 if( rSrc
.maPalette
!= rDst
.maPalette
)
622 return ImplCopyImage( rDst
, rSrc
);
625 // select the matching instantiation for the source's bitmap format
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
:
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 );
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
);
661 case BMP_FORMAT_32BIT_TC_RGBA
:
662 return ImplConvertFromBitmap
<BMP_FORMAT_32BIT_TC_RGBA
>( rDst
, rSrc
);
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
);
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 )
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
);
726 // some specializations to reduce the code size
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
);
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
);
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
:
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 );
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
);
800 case BMP_FORMAT_32BIT_TC_RGBA
:
801 return ImplBlendToBitmap
<BMP_FORMAT_32BIT_TC_RGBA
>( aSrcType
, rDst
, rSrc
, rMsk
);
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
);
818 // -----------------------------------------------------------------------
820 bool ImplFastBitmapBlending( BitmapWriteAccess
& rDstWA
,
821 const BitmapReadAccess
& rSrcRA
, const BitmapReadAccess
& rMskRA
,
822 const SalTwoRect
& rTR
)
824 if( bDisableFastBitops
)
827 // accelerated blending of paletted bitmaps not implemented yet
828 if( rSrcRA
.HasPalette() )
830 if( rDstWA
.HasPalette() )
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 )
837 // vertical mirroring
838 if( rTR
.mnDestHeight
< 0 )
839 // TODO: rDst.mnFormat ^= BMP_FORMAT_TOP_DOWN;
842 // offseted blending is not implemented yet
843 if( rTR
.mnSrcX
|| rTR
.mnSrcY
)
845 if( rTR
.mnDestX
|| rTR
.mnDestY
)
848 // stretched blending is not implemented yet
849 if( rTR
.mnDestWidth
!= rTR
.mnSrcWidth
)
851 if( rTR
.mnDestHeight
!= rTR
.mnSrcHeight
)
854 // check source image size
855 if( rSrcRA
.Width() < rTR
.mnSrcX
+ rTR
.mnSrcWidth
)
857 if( rSrcRA
.Height() < rTR
.mnSrcY
+ rTR
.mnSrcHeight
)
860 // check mask image size
861 if( rMskRA
.Width() < rTR
.mnSrcX
+ rTR
.mnSrcWidth
)
863 if( rMskRA
.Height() < rTR
.mnSrcY
+ rTR
.mnSrcHeight
)
864 if( rMskRA
.Height() != 1 )
867 // check dest image size
868 if( rDstWA
.Width() < rTR
.mnDestX
+ rTR
.mnDestWidth
)
870 if( rDstWA
.Height() < rTR
.mnDestY
+ rTR
.mnDestHeight
)
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)
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)
892 // select the matching instantiation for the source's bitmap format
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
:
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 );
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
);
928 case BMP_FORMAT_32BIT_TC_RGBA
:
929 return ImplBlendFromBitmap
<BMP_FORMAT_32BIT_TC_RGBA
>( rDst
, rSrc
, rMsk
);
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
);
946 bool ImplFastEraseBitmap( BitmapBuffer
& rDst
, const BitmapColor
& rColor
)
948 if( bDisableFastBitops
)
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;
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
964 case BMP_FORMAT_4BIT_MSN_PAL
:
965 case BMP_FORMAT_4BIT_LSN_PAL
:
966 nFillByte
= rColor
.GetIndex();
968 nFillByte
|= (nFillByte
<< 4);
970 case BMP_FORMAT_8BIT_PAL
:
971 case BMP_FORMAT_8BIT_TC_MASK
:
972 nFillByte
= rColor
.GetIndex();
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()) )
992 long nByteCount
= rDst
.mnHeight
* rDst
.mnScanlineSize
;
993 rtl_fillMemory( rDst
.mpBits
, nByteCount
, nFillByte
);
997 // TODO: handle other bitmap formats
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
:
1012 case BMP_FORMAT_32BIT_TC_RGBA
:
1022 // =======================================================================
1024 #else // NO_OPTIMIZED_BITMAP_ACCESS
1026 bool ImplFastBitmapConversion( BitmapBuffer
&, const BitmapBuffer
& )
1031 bool ImplFastBitmapBlending( BitmapWriteAccess
&,
1032 const BitmapReadAccess
&, const BitmapReadAccess
&,
1033 const Size
&, const Point
& )
1038 bool ImplFastEraseBitmap( BitmapBuffer
&, const BitmapColor
& )