1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <bmpfast.hxx>
21 #include <vcl/bitmapaccess.hxx>
23 #define FAST_ARGB_BGRA
27 typedef unsigned char PIXBYTE
;
32 explicit BasePixelPtr( PIXBYTE
* p
= nullptr ) : mpPixel( p
) {}
33 void SetRawPtr( PIXBYTE
* pRawPtr
) { mpPixel
= pRawPtr
; }
34 PIXBYTE
* GetRawPtr() const { return mpPixel
; }
35 void AddByteOffset( int nByteOffset
) { mpPixel
+= nByteOffset
; }
41 template <ScanlineFormat PIXFMT
>
42 class TrueColorPixelPtr
: public BasePixelPtr
45 PIXBYTE
GetRed() const;
46 PIXBYTE
GetGreen() const;
47 PIXBYTE
GetBlue() const;
48 PIXBYTE
GetAlpha() const;
50 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const;
51 void SetAlpha( PIXBYTE a
) const;
54 // template specializations for truecolor pixel formats
56 class TrueColorPixelPtr
<ScanlineFormat::N24BitTcRgb
> : public BasePixelPtr
59 void operator++() { mpPixel
+= 3; }
61 PIXBYTE
GetRed() const { return mpPixel
[0]; }
62 PIXBYTE
GetGreen() const { return mpPixel
[1]; }
63 PIXBYTE
GetBlue() const { return mpPixel
[2]; }
64 static PIXBYTE
GetAlpha() { return 0; }
65 static void SetAlpha( PIXBYTE
) {}
67 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
76 class TrueColorPixelPtr
<ScanlineFormat::N24BitTcBgr
> : public BasePixelPtr
79 void operator++() { mpPixel
+= 3; }
81 PIXBYTE
GetRed() const { return mpPixel
[2]; }
82 PIXBYTE
GetGreen() const { return mpPixel
[1]; }
83 PIXBYTE
GetBlue() const { return mpPixel
[0]; }
84 static PIXBYTE
GetAlpha() { return 0; }
85 static void SetAlpha( PIXBYTE
) {}
87 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
96 class TrueColorPixelPtr
<ScanlineFormat::N32BitTcArgb
> : public BasePixelPtr
99 void operator++() { mpPixel
+= 4; }
101 PIXBYTE
GetRed() const { return mpPixel
[1]; }
102 PIXBYTE
GetGreen() const { return mpPixel
[2]; }
103 PIXBYTE
GetBlue() const { return mpPixel
[3]; }
104 PIXBYTE
GetAlpha() const { return mpPixel
[0]; }
105 void SetAlpha( PIXBYTE a
) const { mpPixel
[0] = a
; }
107 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
116 class TrueColorPixelPtr
<ScanlineFormat::N32BitTcAbgr
> : public BasePixelPtr
119 void operator++() { mpPixel
+= 4; }
121 PIXBYTE
GetRed() const { return mpPixel
[3]; }
122 PIXBYTE
GetGreen() const { return mpPixel
[2]; }
123 PIXBYTE
GetBlue() const { return mpPixel
[1]; }
124 PIXBYTE
GetAlpha() const { return mpPixel
[0]; }
125 void SetAlpha( PIXBYTE a
) const { mpPixel
[0] = a
; }
127 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
136 class TrueColorPixelPtr
<ScanlineFormat::N32BitTcRgba
> : public BasePixelPtr
139 void operator++() { mpPixel
+= 4; }
141 PIXBYTE
GetRed() const { return mpPixel
[0]; }
142 PIXBYTE
GetGreen() const { return mpPixel
[1]; }
143 PIXBYTE
GetBlue() const { return mpPixel
[2]; }
144 PIXBYTE
GetAlpha() const { return mpPixel
[3]; }
145 void SetAlpha( PIXBYTE a
) const{ mpPixel
[3] = a
; }
147 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
156 class TrueColorPixelPtr
<ScanlineFormat::N32BitTcBgra
> : public BasePixelPtr
159 void operator++() { mpPixel
+= 4; }
161 PIXBYTE
GetRed() const { return mpPixel
[2]; }
162 PIXBYTE
GetGreen() const { return mpPixel
[1]; }
163 PIXBYTE
GetBlue() const { return mpPixel
[0]; }
164 PIXBYTE
GetAlpha() const { return mpPixel
[3]; }
165 void SetAlpha( PIXBYTE a
) const{ mpPixel
[3] = a
; }
167 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
176 class TrueColorPixelPtr
<ScanlineFormat::N16BitTcMsbMask
> : public BasePixelPtr
179 void operator++() { mpPixel
+= 2; }
182 PIXBYTE
GetRed() const { return (mpPixel
[0] & 0xF8U
); }
183 PIXBYTE
GetGreen() const { return (mpPixel
[0]<<5U) | ((mpPixel
[1]>>3U)&28U); }
184 PIXBYTE
GetBlue() const { return (mpPixel
[1]<<3U); }
185 static PIXBYTE
GetAlpha() { return 0; }
186 static void SetAlpha( PIXBYTE
) {}
188 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
190 mpPixel
[0] = ((g
>> 5U) & 7U) | (r
& 0xF8U
);
191 mpPixel
[1] = ((g
& 28U)<< 3U) | (b
>> 3U);
196 class TrueColorPixelPtr
<ScanlineFormat::N16BitTcLsbMask
> : public BasePixelPtr
199 void operator++() { mpPixel
+= 2; }
202 PIXBYTE
GetRed() const { return (mpPixel
[1] & 0xF8U
); }
203 PIXBYTE
GetGreen() const { return (mpPixel
[1]<<5U) | ((mpPixel
[0]>>3U)&28U); }
204 PIXBYTE
GetBlue() const { return (mpPixel
[0]<<3U); }
205 static PIXBYTE
GetAlpha() { return 0; }
206 static void SetAlpha( PIXBYTE
) {}
208 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
210 mpPixel
[0] = ((g
& 28U)<< 3U) | (b
>> 3U);
211 mpPixel
[1] = ((g
>> 5U) & 7U) | (r
& 0xF8U
);
216 class TrueColorPixelPtr
<ScanlineFormat::N8BitTcMask
> : public BasePixelPtr
219 void operator++() { mpPixel
+= 1; }
220 PIXBYTE
GetAlpha() const { return mpPixel
[0]; }
221 void SetAlpha( PIXBYTE a
) const { mpPixel
[0] = a
; }
224 // TODO: for some reason many Alpha maps are ScanlineFormat::N8BitPal
225 // they should be ScanlineFormat::N8BitTcMask
227 class TrueColorPixelPtr
<ScanlineFormat::N8BitPal
>
228 : public TrueColorPixelPtr
<ScanlineFormat::N8BitTcMask
>
231 // converting truecolor formats
232 template <ScanlineFormat SRCFMT
, ScanlineFormat DSTFMT
>
233 inline void ImplConvertPixel( const TrueColorPixelPtr
<DSTFMT
>& rDst
,
234 const TrueColorPixelPtr
<SRCFMT
>& rSrc
)
236 rDst
.SetColor( rSrc
.GetRed(), rSrc
.GetGreen(), rSrc
.GetBlue() );
237 rDst
.SetAlpha( rSrc
.GetAlpha() );
241 inline void ImplConvertPixel
<ScanlineFormat::N16BitTcLsbMask
, ScanlineFormat::N16BitTcMsbMask
> (
242 const TrueColorPixelPtr
<ScanlineFormat::N16BitTcMsbMask
>& rDst
,
243 const TrueColorPixelPtr
<ScanlineFormat::N16BitTcLsbMask
>& rSrc
)
246 const PIXBYTE
* pSrc
= rSrc
.GetRawPtr();
247 PIXBYTE
* pDst
= rDst
.GetRawPtr();
252 template <ScanlineFormat SRCFMT
, ScanlineFormat DSTFMT
>
253 inline void ImplConvertLine( const TrueColorPixelPtr
<DSTFMT
>& rDst
,
254 const TrueColorPixelPtr
<SRCFMT
>& rSrc
, int nPixelCount
)
256 TrueColorPixelPtr
<DSTFMT
> aDst( rDst
);
257 TrueColorPixelPtr
<SRCFMT
> aSrc( rSrc
);
258 while( --nPixelCount
>= 0 )
260 ImplConvertPixel( aDst
, aSrc
);
266 // alpha blending truecolor pixels
267 template <ScanlineFormat SRCFMT
, ScanlineFormat DSTFMT
>
268 inline void ImplBlendPixels( const TrueColorPixelPtr
<DSTFMT
>& rDst
,
269 const TrueColorPixelPtr
<SRCFMT
>& rSrc
, unsigned nAlphaVal
)
271 static const unsigned nAlphaShift
= 8;
273 ImplConvertPixel( rDst
, rSrc
);
274 else if( nAlphaVal
!= ~(~0U << nAlphaShift
) )
276 int nR
= rDst
.GetRed();
277 int nS
= rSrc
.GetRed();
278 nR
= nS
+ (((nR
- nS
) * nAlphaVal
) >> nAlphaShift
);
280 int nG
= rDst
.GetGreen();
281 nS
= rSrc
.GetGreen();
282 nG
= nS
+ (((nG
- nS
) * nAlphaVal
) >> nAlphaShift
);
284 int nB
= rDst
.GetBlue();
286 nB
= nS
+ (((nB
- nS
) * nAlphaVal
) >> nAlphaShift
);
288 rDst
.SetColor( sal::static_int_cast
<PIXBYTE
>(nR
),
289 sal::static_int_cast
<PIXBYTE
>(nG
),
290 sal::static_int_cast
<PIXBYTE
>(nB
) );
294 template <ScanlineFormat MASKFMT
, ScanlineFormat SRCFMT
, ScanlineFormat DSTFMT
>
295 inline void ImplBlendLines( const TrueColorPixelPtr
<DSTFMT
>& rDst
,
296 const TrueColorPixelPtr
<SRCFMT
>& rSrc
, const TrueColorPixelPtr
<MASKFMT
>& rMsk
,
299 TrueColorPixelPtr
<MASKFMT
> aMsk( rMsk
);
300 TrueColorPixelPtr
<DSTFMT
> aDst( rDst
);
301 TrueColorPixelPtr
<SRCFMT
> aSrc( rSrc
);
302 while( --nPixelCount
>= 0 )
304 ImplBlendPixels(aDst
, aSrc
, aMsk
.GetAlpha());
311 static bool ImplCopyImage( BitmapBuffer
& rDstBuffer
, const BitmapBuffer
& rSrcBuffer
)
313 const int nSrcLinestep
= rSrcBuffer
.mnScanlineSize
;
314 int nDstLinestep
= rDstBuffer
.mnScanlineSize
;
316 const PIXBYTE
* pRawSrc
= rSrcBuffer
.mpBits
;
317 PIXBYTE
* pRawDst
= rDstBuffer
.mpBits
;
319 // source and destination don't match upside down
320 if( ScanlineFormat::TopDown
& (rSrcBuffer
.mnFormat
^ rDstBuffer
.mnFormat
) )
322 pRawDst
+= (rSrcBuffer
.mnHeight
- 1) * nDstLinestep
;
323 nDstLinestep
= -rDstBuffer
.mnScanlineSize
;
325 else if( nSrcLinestep
== nDstLinestep
)
327 memcpy( pRawDst
, pRawSrc
, rSrcBuffer
.mnHeight
* nDstLinestep
);
331 int nByteWidth
= nSrcLinestep
;
332 if( nByteWidth
> rDstBuffer
.mnScanlineSize
)
333 nByteWidth
= rDstBuffer
.mnScanlineSize
;
335 for( int y
= rSrcBuffer
.mnHeight
; --y
>= 0; )
337 memcpy( pRawDst
, pRawSrc
, nByteWidth
);
338 pRawSrc
+= nSrcLinestep
;
339 pRawDst
+= nDstLinestep
;
345 template <ScanlineFormat DSTFMT
,ScanlineFormat SRCFMT
>
346 bool ImplConvertToBitmap( TrueColorPixelPtr
<SRCFMT
>& rSrcLine
,
347 BitmapBuffer
& rDstBuffer
, const BitmapBuffer
& rSrcBuffer
)
349 // help the compiler to avoid instantiations of unneeded conversions
350 SAL_WARN_IF( SRCFMT
== DSTFMT
, "vcl.gdi", "ImplConvertToBitmap into same format");
351 if( SRCFMT
== DSTFMT
)
354 const int nSrcLinestep
= rSrcBuffer
.mnScanlineSize
;
355 int nDstLinestep
= rDstBuffer
.mnScanlineSize
;
357 TrueColorPixelPtr
<DSTFMT
> aDstLine
; aDstLine
.SetRawPtr( rDstBuffer
.mpBits
);
359 // source and destination don't match upside down
360 if( ScanlineFormat::TopDown
& (rSrcBuffer
.mnFormat
^ rDstBuffer
.mnFormat
) )
362 aDstLine
.AddByteOffset( (rSrcBuffer
.mnHeight
- 1) * nDstLinestep
);
363 nDstLinestep
= -nDstLinestep
;
366 for( int y
= rSrcBuffer
.mnHeight
; --y
>= 0; )
368 ImplConvertLine( aDstLine
, rSrcLine
, rSrcBuffer
.mnWidth
);
369 rSrcLine
.AddByteOffset( nSrcLinestep
);
370 aDstLine
.AddByteOffset( nDstLinestep
);
376 template <ScanlineFormat SRCFMT
>
377 inline bool ImplConvertFromBitmap( BitmapBuffer
& rDst
, const BitmapBuffer
& rSrc
)
379 TrueColorPixelPtr
<SRCFMT
> aSrcType
; aSrcType
.SetRawPtr( rSrc
.mpBits
);
381 // select the matching instantiation for the destination's bitmap format
382 switch( rDst
.mnFormat
& ~ScanlineFormat::TopDown
)
384 case ScanlineFormat::N1BitMsbPal
:
385 case ScanlineFormat::N1BitLsbPal
:
386 case ScanlineFormat::N4BitMsnPal
:
387 case ScanlineFormat::N4BitLsnPal
:
388 case ScanlineFormat::N8BitPal
:
391 case ScanlineFormat::N8BitTcMask
:
392 // return ImplConvertToBitmap<ScanlineFormat::N8BitTcMask>( aSrcType, rDst, rSrc );
393 case ScanlineFormat::N32BitTcMask
:
394 // return ImplConvertToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc );
397 case ScanlineFormat::N16BitTcMsbMask
:
398 return ImplConvertToBitmap
<ScanlineFormat::N16BitTcMsbMask
>( aSrcType
, rDst
, rSrc
);
399 case ScanlineFormat::N16BitTcLsbMask
:
400 return ImplConvertToBitmap
<ScanlineFormat::N16BitTcLsbMask
>( aSrcType
, rDst
, rSrc
);
402 case ScanlineFormat::N24BitTcBgr
:
403 return ImplConvertToBitmap
<ScanlineFormat::N24BitTcBgr
>( aSrcType
, rDst
, rSrc
);
404 case ScanlineFormat::N24BitTcRgb
:
405 return ImplConvertToBitmap
<ScanlineFormat::N24BitTcRgb
>( aSrcType
, rDst
, rSrc
);
407 case ScanlineFormat::N32BitTcAbgr
:
408 return ImplConvertToBitmap
<ScanlineFormat::N32BitTcAbgr
>( aSrcType
, rDst
, rSrc
);
409 #ifdef FAST_ARGB_BGRA
410 case ScanlineFormat::N32BitTcArgb
:
411 return ImplConvertToBitmap
<ScanlineFormat::N32BitTcArgb
>( aSrcType
, rDst
, rSrc
);
412 case ScanlineFormat::N32BitTcBgra
:
413 return ImplConvertToBitmap
<ScanlineFormat::N32BitTcBgra
>( aSrcType
, rDst
, rSrc
);
415 case ScanlineFormat::N32BitTcRgba
:
416 return ImplConvertToBitmap
<ScanlineFormat::N32BitTcRgba
>( aSrcType
, rDst
, rSrc
);
420 static int nNotAccelerated
= 0;
421 SAL_WARN_IF( rSrc
.mnWidth
* rSrc
.mnHeight
>= 4000 && ++nNotAccelerated
== 100,
423 "ImplConvertFromBitmap for not accelerated case (" << std::hex
<< (int)rSrc
.mnFormat
<< "->" << (int)rDst
.mnFormat
<< ")" );
428 // A universal stretching conversion is overkill in most common situations
429 // => performance benefits for speeding up the non-stretching cases
430 bool ImplFastBitmapConversion( BitmapBuffer
& rDst
, const BitmapBuffer
& rSrc
,
431 const SalTwoRect
& rTR
)
433 // TODO:horizontal mirroring not implemented yet
434 if( rTR
.mnDestWidth
< 0 )
436 // vertical mirroring
437 if( rTR
.mnDestHeight
< 0 )
438 // TODO: rDst.mnFormat ^= ScanlineFormat::TopDown;
441 // offseted conversion is not implemented yet
442 if( rTR
.mnSrcX
|| rTR
.mnSrcY
)
444 if( rTR
.mnDestX
|| rTR
.mnDestY
)
447 // stretched conversion is not implemented yet
448 if( rTR
.mnDestWidth
!= rTR
.mnSrcWidth
)
450 if( rTR
.mnDestHeight
!= rTR
.mnSrcHeight
)
453 // check source image size
454 if( rSrc
.mnWidth
< rTR
.mnSrcX
+ rTR
.mnSrcWidth
)
456 if( rSrc
.mnHeight
< rTR
.mnSrcY
+ rTR
.mnSrcHeight
)
459 // check dest image size
460 if( rDst
.mnWidth
< rTR
.mnDestX
+ rTR
.mnDestWidth
)
462 if( rDst
.mnHeight
< rTR
.mnDestY
+ rTR
.mnDestHeight
)
465 const ScanlineFormat nSrcFormat
= rSrc
.mnFormat
& ~ScanlineFormat::TopDown
;
466 const ScanlineFormat nDstFormat
= rDst
.mnFormat
& ~ScanlineFormat::TopDown
;
468 // TODO: also implement conversions for 16bit colormasks with non-565 format
469 if( nSrcFormat
& (ScanlineFormat::N16BitTcLsbMask
| ScanlineFormat::N16BitTcMsbMask
) )
470 if( rSrc
.maColorMask
.GetRedMask() != 0xF800
471 || rSrc
.maColorMask
.GetGreenMask()!= 0x07E0
472 || rSrc
.maColorMask
.GetBlueMask() != 0x001F )
474 if( nDstFormat
& (ScanlineFormat::N16BitTcLsbMask
| ScanlineFormat::N16BitTcMsbMask
) )
475 if( rDst
.maColorMask
.GetRedMask() != 0xF800
476 || rDst
.maColorMask
.GetGreenMask()!= 0x07E0
477 || rDst
.maColorMask
.GetBlueMask() != 0x001F )
480 // special handling of trivial cases
481 if( nSrcFormat
== nDstFormat
)
483 // accelerated palette conversions not yet implemented
484 if( rSrc
.maPalette
!= rDst
.maPalette
)
486 return ImplCopyImage( rDst
, rSrc
);
489 // select the matching instantiation for the source's bitmap format
492 case ScanlineFormat::N1BitMsbPal
:
493 case ScanlineFormat::N1BitLsbPal
:
494 case ScanlineFormat::N4BitMsnPal
:
495 case ScanlineFormat::N4BitLsnPal
:
496 case ScanlineFormat::N8BitPal
:
499 case ScanlineFormat::N8BitTcMask
:
500 // return ImplConvertFromBitmap<ScanlineFormat::N8BitTcMask>( rDst, rSrc );
501 case ScanlineFormat::N32BitTcMask
:
502 // return ImplConvertFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
505 case ScanlineFormat::N16BitTcMsbMask
:
506 return ImplConvertFromBitmap
<ScanlineFormat::N16BitTcMsbMask
>( rDst
, rSrc
);
507 case ScanlineFormat::N16BitTcLsbMask
:
508 return ImplConvertFromBitmap
<ScanlineFormat::N16BitTcLsbMask
>( rDst
, rSrc
);
510 case ScanlineFormat::N24BitTcBgr
:
511 return ImplConvertFromBitmap
<ScanlineFormat::N24BitTcBgr
>( rDst
, rSrc
);
512 case ScanlineFormat::N24BitTcRgb
:
513 return ImplConvertFromBitmap
<ScanlineFormat::N24BitTcRgb
>( rDst
, rSrc
);
515 case ScanlineFormat::N32BitTcAbgr
:
516 return ImplConvertFromBitmap
<ScanlineFormat::N32BitTcAbgr
>( rDst
, rSrc
);
517 #ifdef FAST_ARGB_BGRA
518 case ScanlineFormat::N32BitTcArgb
:
519 return ImplConvertFromBitmap
<ScanlineFormat::N32BitTcArgb
>( rDst
, rSrc
);
520 case ScanlineFormat::N32BitTcBgra
:
521 return ImplConvertFromBitmap
<ScanlineFormat::N32BitTcBgra
>( rDst
, rSrc
);
523 case ScanlineFormat::N32BitTcRgba
:
524 return ImplConvertFromBitmap
<ScanlineFormat::N32BitTcRgba
>( rDst
, rSrc
);
528 static int nNotAccelerated
= 0;
529 SAL_WARN_IF( rSrc
.mnWidth
* rSrc
.mnHeight
>= 4000 && ++nNotAccelerated
== 100,
531 "ImplFastBitmapConversion for not accelerated case (" << std::hex
<< (int)rSrc
.mnFormat
<< "->" << (int)rDst
.mnFormat
<< ")" );
536 template <ScanlineFormat DSTFMT
, ScanlineFormat SRCFMT
> //,sal_uLong MSKFMT>
537 bool ImplBlendToBitmap( TrueColorPixelPtr
<SRCFMT
>& rSrcLine
,
538 BitmapBuffer
& rDstBuffer
, const BitmapBuffer
& rSrcBuffer
,
539 const BitmapBuffer
& rMskBuffer
)
541 SAL_WARN_IF( rMskBuffer
.mnFormat
!= ScanlineFormat::N8BitPal
, "vcl.gdi", "FastBmp BlendImage: unusual MSKFMT" );
543 const int nSrcLinestep
= rSrcBuffer
.mnScanlineSize
;
544 int nMskLinestep
= rMskBuffer
.mnScanlineSize
;
545 int nDstLinestep
= rDstBuffer
.mnScanlineSize
;
547 TrueColorPixelPtr
<ScanlineFormat::N8BitPal
> aMskLine
; aMskLine
.SetRawPtr( rMskBuffer
.mpBits
);
548 TrueColorPixelPtr
<DSTFMT
> aDstLine
; aDstLine
.SetRawPtr( rDstBuffer
.mpBits
);
550 // special case for single line masks
551 if( rMskBuffer
.mnHeight
== 1 )
554 // source and mask don't match: upside down
555 if( (rSrcBuffer
.mnFormat
^ rMskBuffer
.mnFormat
) & ScanlineFormat::TopDown
)
557 aMskLine
.AddByteOffset( (rSrcBuffer
.mnHeight
- 1) * nMskLinestep
);
558 nMskLinestep
= -nMskLinestep
;
561 // source and destination don't match: upside down
562 if( (rSrcBuffer
.mnFormat
^ rDstBuffer
.mnFormat
) & ScanlineFormat::TopDown
)
564 aDstLine
.AddByteOffset( (rDstBuffer
.mnHeight
- 1) * nDstLinestep
);
565 nDstLinestep
= -nDstLinestep
;
568 assert(rDstBuffer
.mnHeight
<= rSrcBuffer
.mnHeight
&& "not sure about that?");
569 for (int y
= rDstBuffer
.mnHeight
; --y
>= 0;)
571 ImplBlendLines(aDstLine
, rSrcLine
, aMskLine
, rDstBuffer
.mnWidth
);
572 aDstLine
.AddByteOffset( nDstLinestep
);
573 rSrcLine
.AddByteOffset( nSrcLinestep
);
574 aMskLine
.AddByteOffset( nMskLinestep
);
580 // some specializations to reduce the code size
582 inline bool ImplBlendToBitmap
<ScanlineFormat::N24BitTcBgr
,ScanlineFormat::N24BitTcBgr
>(
583 TrueColorPixelPtr
<ScanlineFormat::N24BitTcBgr
>&,
584 BitmapBuffer
& rDstBuffer
, const BitmapBuffer
& rSrcBuffer
,
585 const BitmapBuffer
& rMskBuffer
)
587 TrueColorPixelPtr
<ScanlineFormat::N24BitTcRgb
> aSrcType
; aSrcType
.SetRawPtr( rSrcBuffer
.mpBits
);
588 return ImplBlendToBitmap
<ScanlineFormat::N24BitTcRgb
>( aSrcType
, rDstBuffer
, rSrcBuffer
, rMskBuffer
);
592 inline bool ImplBlendToBitmap
<ScanlineFormat::N32BitTcAbgr
,ScanlineFormat::N32BitTcAbgr
>(
593 TrueColorPixelPtr
<ScanlineFormat::N32BitTcAbgr
>&,
594 BitmapBuffer
& rDstBuffer
, const BitmapBuffer
& rSrcBuffer
,
595 const BitmapBuffer
& rMskBuffer
)
597 TrueColorPixelPtr
<ScanlineFormat::N32BitTcArgb
> aSrcType
; aSrcType
.SetRawPtr( rSrcBuffer
.mpBits
);
598 return ImplBlendToBitmap
<ScanlineFormat::N32BitTcArgb
>( aSrcType
, rDstBuffer
, rSrcBuffer
, rMskBuffer
);
602 inline bool ImplBlendToBitmap
<ScanlineFormat::N32BitTcBgra
,ScanlineFormat::N32BitTcBgra
>(
603 TrueColorPixelPtr
<ScanlineFormat::N32BitTcBgra
>&,
604 BitmapBuffer
& rDstBuffer
, const BitmapBuffer
& rSrcBuffer
,
605 const BitmapBuffer
& rMskBuffer
)
607 TrueColorPixelPtr
<ScanlineFormat::N32BitTcRgba
> aSrcType
; aSrcType
.SetRawPtr( rSrcBuffer
.mpBits
);
608 return ImplBlendToBitmap
<ScanlineFormat::N32BitTcRgba
>( aSrcType
, rDstBuffer
, rSrcBuffer
, rMskBuffer
);
611 template <ScanlineFormat SRCFMT
>
612 bool ImplBlendFromBitmap( BitmapBuffer
& rDst
, const BitmapBuffer
& rSrc
, const BitmapBuffer
& rMsk
)
614 TrueColorPixelPtr
<SRCFMT
> aSrcType
; aSrcType
.SetRawPtr( rSrc
.mpBits
);
616 // select the matching instantiation for the destination's bitmap format
617 switch( rDst
.mnFormat
& ~ScanlineFormat::TopDown
)
619 case ScanlineFormat::N1BitMsbPal
:
620 case ScanlineFormat::N1BitLsbPal
:
621 case ScanlineFormat::N4BitMsnPal
:
622 case ScanlineFormat::N4BitLsnPal
:
623 case ScanlineFormat::N8BitPal
:
626 case ScanlineFormat::N8BitTcMask
:
627 // return ImplBlendToBitmap<ScanlineFormat::N8BitTcMask>( aSrcType, rDst, rSrc, rMsk );
628 case ScanlineFormat::N32BitTcMask
:
629 // return ImplBlendToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc, rMsk );
632 case ScanlineFormat::N16BitTcMsbMask
:
633 return ImplBlendToBitmap
<ScanlineFormat::N16BitTcMsbMask
>( aSrcType
, rDst
, rSrc
, rMsk
);
634 case ScanlineFormat::N16BitTcLsbMask
:
635 return ImplBlendToBitmap
<ScanlineFormat::N16BitTcLsbMask
>( aSrcType
, rDst
, rSrc
, rMsk
);
637 case ScanlineFormat::N24BitTcBgr
:
638 return ImplBlendToBitmap
<ScanlineFormat::N24BitTcBgr
>( aSrcType
, rDst
, rSrc
, rMsk
);
639 case ScanlineFormat::N24BitTcRgb
:
640 return ImplBlendToBitmap
<ScanlineFormat::N24BitTcRgb
>( aSrcType
, rDst
, rSrc
, rMsk
);
642 case ScanlineFormat::N32BitTcAbgr
:
643 return ImplBlendToBitmap
<ScanlineFormat::N32BitTcAbgr
>( aSrcType
, rDst
, rSrc
, rMsk
);
644 #ifdef FAST_ARGB_BGRA
645 case ScanlineFormat::N32BitTcArgb
:
646 return ImplBlendToBitmap
<ScanlineFormat::N32BitTcArgb
>( aSrcType
, rDst
, rSrc
, rMsk
);
647 case ScanlineFormat::N32BitTcBgra
:
648 return ImplBlendToBitmap
<ScanlineFormat::N32BitTcBgra
>( aSrcType
, rDst
, rSrc
, rMsk
);
650 case ScanlineFormat::N32BitTcRgba
:
651 return ImplBlendToBitmap
<ScanlineFormat::N32BitTcRgba
>( aSrcType
, rDst
, rSrc
, rMsk
);
655 static int nNotAccelerated
= 0;
656 SAL_WARN_IF( rSrc
.mnWidth
* rSrc
.mnHeight
>= 4000 && ++nNotAccelerated
== 100,
658 "ImplBlendFromBitmap for not accelerated case (" << std::hex
<< (int)rSrc
.mnFormat
<< "*" << (int)rMsk
.mnFormat
<< "->" << (int)rDst
.mnFormat
);
662 bool ImplFastBitmapBlending( BitmapWriteAccess
& rDstWA
,
663 const BitmapReadAccess
& rSrcRA
, const BitmapReadAccess
& rMskRA
,
664 const SalTwoRect
& rTR
)
666 // accelerated blending of paletted bitmaps not implemented yet
667 if( rSrcRA
.HasPalette() )
669 if( rDstWA
.HasPalette() )
671 // TODO: either get rid of mask's use of 8BIT_PAL or check the palette
673 // horizontal mirroring not implemented yet
674 if( rTR
.mnDestWidth
< 0 )
676 // vertical mirroring
677 if( rTR
.mnDestHeight
< 0 )
678 // TODO: rDst.mnFormat ^= ScanlineFormat::TopDown;
681 // offseted blending is not implemented yet
682 if( rTR
.mnSrcX
|| rTR
.mnSrcY
)
684 if( rTR
.mnDestX
|| rTR
.mnDestY
)
687 // stretched blending is not implemented yet
688 if( rTR
.mnDestWidth
!= rTR
.mnSrcWidth
)
690 if( rTR
.mnDestHeight
!= rTR
.mnSrcHeight
)
693 // check source image size
694 if( rSrcRA
.Width() < rTR
.mnSrcX
+ rTR
.mnSrcWidth
)
696 if( rSrcRA
.Height() < rTR
.mnSrcY
+ rTR
.mnSrcHeight
)
699 // check mask image size
700 if( rMskRA
.Width() < rTR
.mnSrcX
+ rTR
.mnSrcWidth
)
702 if( rMskRA
.Height() < rTR
.mnSrcY
+ rTR
.mnSrcHeight
)
703 if( rMskRA
.Height() != 1 )
706 // check dest image size
707 if( rDstWA
.Width() < rTR
.mnDestX
+ rTR
.mnDestWidth
)
709 if( rDstWA
.Height() < rTR
.mnDestY
+ rTR
.mnDestHeight
)
712 BitmapBuffer
& rDst
= *rDstWA
.ImplGetBitmapBuffer();
713 const BitmapBuffer
& rSrc
= *rSrcRA
.ImplGetBitmapBuffer();
714 const BitmapBuffer
& rMsk
= *rMskRA
.ImplGetBitmapBuffer();
716 const ScanlineFormat nSrcFormat
= rSrc
.mnFormat
& ~ScanlineFormat::TopDown
;
717 const ScanlineFormat nDstFormat
= rDst
.mnFormat
& ~ScanlineFormat::TopDown
;
719 // accelerated conversions for 16bit colormasks with non-565 format are not yet implemented
720 if( nSrcFormat
& (ScanlineFormat::N16BitTcLsbMask
| ScanlineFormat::N16BitTcMsbMask
) )
721 if( rSrc
.maColorMask
.GetRedMask() != 0xF800
722 || rSrc
.maColorMask
.GetGreenMask()!= 0x07E0
723 || rSrc
.maColorMask
.GetBlueMask() != 0x001F)
725 if( nDstFormat
& (ScanlineFormat::N16BitTcLsbMask
| ScanlineFormat::N16BitTcMsbMask
) )
726 if( rDst
.maColorMask
.GetRedMask() != 0xF800
727 || rDst
.maColorMask
.GetGreenMask()!= 0x07E0
728 || rDst
.maColorMask
.GetBlueMask() != 0x001F)
731 // select the matching instantiation for the source's bitmap format
734 case ScanlineFormat::N1BitMsbPal
:
735 case ScanlineFormat::N1BitLsbPal
:
736 case ScanlineFormat::N4BitMsnPal
:
737 case ScanlineFormat::N4BitLsnPal
:
738 case ScanlineFormat::N8BitPal
:
741 case ScanlineFormat::N8BitTcMask
:
742 // return ImplBlendFromBitmap<ScanlineFormat::N8BitTcMask>( rDst, rSrc );
743 case ScanlineFormat::N32BitTcMask
:
744 // return ImplBlendFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
747 case ScanlineFormat::N16BitTcMsbMask
:
748 return ImplBlendFromBitmap
<ScanlineFormat::N16BitTcMsbMask
>( rDst
, rSrc
, rMsk
);
749 case ScanlineFormat::N16BitTcLsbMask
:
750 return ImplBlendFromBitmap
<ScanlineFormat::N16BitTcLsbMask
>( rDst
, rSrc
, rMsk
);
752 case ScanlineFormat::N24BitTcBgr
:
753 return ImplBlendFromBitmap
<ScanlineFormat::N24BitTcBgr
>( rDst
, rSrc
, rMsk
);
754 case ScanlineFormat::N24BitTcRgb
:
755 return ImplBlendFromBitmap
<ScanlineFormat::N24BitTcRgb
>( rDst
, rSrc
, rMsk
);
757 case ScanlineFormat::N32BitTcAbgr
:
758 return ImplBlendFromBitmap
<ScanlineFormat::N32BitTcAbgr
>( rDst
, rSrc
, rMsk
);
759 #ifdef FAST_ARGB_BGRA
760 case ScanlineFormat::N32BitTcArgb
:
761 return ImplBlendFromBitmap
<ScanlineFormat::N32BitTcArgb
>( rDst
, rSrc
, rMsk
);
762 case ScanlineFormat::N32BitTcBgra
:
763 return ImplBlendFromBitmap
<ScanlineFormat::N32BitTcBgra
>( rDst
, rSrc
, rMsk
);
765 case ScanlineFormat::N32BitTcRgba
:
766 return ImplBlendFromBitmap
<ScanlineFormat::N32BitTcRgba
>( rDst
, rSrc
, rMsk
);
770 static int nNotAccelerated
= 0;
771 SAL_WARN_IF( rSrc
.mnWidth
* rSrc
.mnHeight
>= 4000 && ++nNotAccelerated
== 100,
773 "ImplFastBlend for not accelerated case (" << std::hex
<< (int)rSrc
.mnFormat
<< "*" << (int)rMsk
.mnFormat
<< "->" << (int)rDst
.mnFormat
<< ")" );
778 bool ImplFastEraseBitmap( BitmapBuffer
& rDst
, const BitmapColor
& rColor
)
780 const ScanlineFormat nDstFormat
= rDst
.mnFormat
& ~ScanlineFormat::TopDown
;
782 // erasing a bitmap is often just a byte-wise memory fill
783 bool bByteFill
= true;
788 case ScanlineFormat::N1BitMsbPal
:
789 case ScanlineFormat::N1BitLsbPal
:
790 nFillByte
= rColor
.GetIndex();
791 nFillByte
= static_cast<sal_uInt8
>( -(nFillByte
& 1) ); // 0x00 or 0xFF
793 case ScanlineFormat::N4BitMsnPal
:
794 case ScanlineFormat::N4BitLsnPal
:
795 nFillByte
= rColor
.GetIndex();
797 nFillByte
|= (nFillByte
<< 4);
799 case ScanlineFormat::N8BitPal
:
800 case ScanlineFormat::N8BitTcMask
:
801 nFillByte
= rColor
.GetIndex();
804 case ScanlineFormat::N24BitTcBgr
:
805 case ScanlineFormat::N24BitTcRgb
:
806 nFillByte
= rColor
.GetRed();
807 if( (nFillByte
!= rColor
.GetGreen())
808 || (nFillByte
!= rColor
.GetBlue()) )
820 long nByteCount
= rDst
.mnHeight
* rDst
.mnScanlineSize
;
821 memset( rDst
.mpBits
, nFillByte
, nByteCount
);
825 // TODO: handle other bitmap formats
828 case ScanlineFormat::N32BitTcMask
:
829 case ScanlineFormat::N16BitTcMsbMask
:
830 case ScanlineFormat::N16BitTcLsbMask
:
832 case ScanlineFormat::N24BitTcBgr
:
833 case ScanlineFormat::N24BitTcRgb
:
835 case ScanlineFormat::N32BitTcAbgr
:
836 #ifdef FAST_ARGB_BGRA
837 case ScanlineFormat::N32BitTcArgb
:
838 case ScanlineFormat::N32BitTcBgra
:
840 case ScanlineFormat::N32BitTcRgba
:
850 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */