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 <vcl/salgtype.hxx>
22 #include <bitmap/BitmapWriteAccess.hxx>
23 #include <bitmap/bmpfast.hxx>
25 #include <sal/log.hxx>
27 typedef unsigned char PIXBYTE
;
34 explicit BasePixelPtr( PIXBYTE
* p
= nullptr ) : mpPixel( p
) {}
35 void SetRawPtr( PIXBYTE
* pRawPtr
) { mpPixel
= pRawPtr
; }
36 void AddByteOffset( int nByteOffset
) { mpPixel
+= nByteOffset
; }
42 template <ScanlineFormat PIXFMT
>
43 class TrueColorPixelPtr
: public BasePixelPtr
46 PIXBYTE
GetRed() const;
47 PIXBYTE
GetGreen() const;
48 PIXBYTE
GetBlue() const;
49 PIXBYTE
GetAlpha() const;
51 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const;
52 void SetAlpha( PIXBYTE a
) const;
55 // template specializations for truecolor pixel formats
57 class TrueColorPixelPtr
<ScanlineFormat::N24BitTcRgb
> : public BasePixelPtr
60 void operator++() { mpPixel
+= 3; }
62 PIXBYTE
GetRed() const { return mpPixel
[0]; }
63 PIXBYTE
GetGreen() const { return mpPixel
[1]; }
64 PIXBYTE
GetBlue() const { return mpPixel
[2]; }
65 static PIXBYTE
GetAlpha() { return 255; }
66 static void SetAlpha( PIXBYTE
) {}
68 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
77 class TrueColorPixelPtr
<ScanlineFormat::N24BitTcBgr
> : public BasePixelPtr
80 void operator++() { mpPixel
+= 3; }
82 PIXBYTE
GetRed() const { return mpPixel
[2]; }
83 PIXBYTE
GetGreen() const { return mpPixel
[1]; }
84 PIXBYTE
GetBlue() const { return mpPixel
[0]; }
85 static PIXBYTE
GetAlpha() { return 255; }
86 static void SetAlpha( PIXBYTE
) {}
88 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
97 class TrueColorPixelPtr
<ScanlineFormat::N32BitTcArgb
> : public BasePixelPtr
100 void operator++() { mpPixel
+= 4; }
102 PIXBYTE
GetRed() const { return mpPixel
[1]; }
103 PIXBYTE
GetGreen() const { return mpPixel
[2]; }
104 PIXBYTE
GetBlue() const { return mpPixel
[3]; }
105 PIXBYTE
GetAlpha() const { return mpPixel
[0]; }
106 void SetAlpha( PIXBYTE a
) const { mpPixel
[0] = a
; }
108 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
117 class TrueColorPixelPtr
<ScanlineFormat::N32BitTcAbgr
> : public BasePixelPtr
120 void operator++() { mpPixel
+= 4; }
122 PIXBYTE
GetRed() const { return mpPixel
[3]; }
123 PIXBYTE
GetGreen() const { return mpPixel
[2]; }
124 PIXBYTE
GetBlue() const { return mpPixel
[1]; }
125 PIXBYTE
GetAlpha() const { return mpPixel
[0]; }
126 void SetAlpha( PIXBYTE a
) const { mpPixel
[0] = a
; }
128 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
137 class TrueColorPixelPtr
<ScanlineFormat::N32BitTcRgba
> : public BasePixelPtr
140 void operator++() { mpPixel
+= 4; }
142 PIXBYTE
GetRed() const { return mpPixel
[0]; }
143 PIXBYTE
GetGreen() const { return mpPixel
[1]; }
144 PIXBYTE
GetBlue() const { return mpPixel
[2]; }
145 PIXBYTE
GetAlpha() const { return mpPixel
[3]; }
146 void SetAlpha( PIXBYTE a
) const{ mpPixel
[3] = a
; }
148 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
157 class TrueColorPixelPtr
<ScanlineFormat::N32BitTcBgra
> : public BasePixelPtr
160 void operator++() { mpPixel
+= 4; }
162 PIXBYTE
GetRed() const { return mpPixel
[2]; }
163 PIXBYTE
GetGreen() const { return mpPixel
[1]; }
164 PIXBYTE
GetBlue() const { return mpPixel
[0]; }
165 PIXBYTE
GetAlpha() const { return mpPixel
[3]; }
166 void SetAlpha( PIXBYTE a
) const{ mpPixel
[3] = a
; }
168 void SetColor( PIXBYTE r
, PIXBYTE g
, PIXBYTE b
) const
176 // This assumes the content uses the grayscale palette (needs to be checked
177 // by code allowing the use of the format).
178 // Only reading color is implemented, since e.g. 24bpp input couldn't be
179 // easily guaranteed to be grayscale.
181 class TrueColorPixelPtr
<ScanlineFormat::N8BitPal
> : public BasePixelPtr
184 void operator++() { mpPixel
+= 1; }
186 PIXBYTE
GetRed() const { return mpPixel
[0]; }
187 PIXBYTE
GetGreen() const { return mpPixel
[0]; }
188 PIXBYTE
GetBlue() const { return mpPixel
[0]; }
189 static PIXBYTE
GetAlpha() { return 255; }
194 // converting truecolor formats
195 template <ScanlineFormat SRCFMT
, ScanlineFormat DSTFMT
>
196 static void ImplConvertPixel( const TrueColorPixelPtr
<DSTFMT
>& rDst
,
197 const TrueColorPixelPtr
<SRCFMT
>& rSrc
)
199 rDst
.SetColor( rSrc
.GetRed(), rSrc
.GetGreen(), rSrc
.GetBlue() );
200 rDst
.SetAlpha( rSrc
.GetAlpha() );
203 template <ScanlineFormat SRCFMT
, ScanlineFormat DSTFMT
>
204 static void ImplConvertLine( const TrueColorPixelPtr
<DSTFMT
>& rDst
,
205 const TrueColorPixelPtr
<SRCFMT
>& rSrc
, int nPixelCount
)
207 TrueColorPixelPtr
<DSTFMT
> aDst( rDst
);
208 TrueColorPixelPtr
<SRCFMT
> aSrc( rSrc
);
209 while( --nPixelCount
>= 0 )
211 ImplConvertPixel( aDst
, aSrc
);
217 // alpha blending truecolor pixels
218 template <ScanlineFormat SRCFMT
, ScanlineFormat DSTFMT
>
219 static void ImplBlendPixels( const TrueColorPixelPtr
<DSTFMT
>& rDst
,
220 const TrueColorPixelPtr
<SRCFMT
>& rSrc
, unsigned nAlphaVal
)
222 static const unsigned nAlphaShift
= 8;
224 ImplConvertPixel( rDst
, rSrc
);
225 else if( nAlphaVal
!= ~(~0U << nAlphaShift
) )
227 int nR
= rDst
.GetRed();
228 int nS
= rSrc
.GetRed();
229 nR
= nS
+ (((nR
- nS
) * nAlphaVal
) >> nAlphaShift
);
231 int nG
= rDst
.GetGreen();
232 nS
= rSrc
.GetGreen();
233 nG
= nS
+ (((nG
- nS
) * nAlphaVal
) >> nAlphaShift
);
235 int nB
= rDst
.GetBlue();
237 nB
= nS
+ (((nB
- nS
) * nAlphaVal
) >> nAlphaShift
);
239 rDst
.SetColor( sal::static_int_cast
<PIXBYTE
>(nR
),
240 sal::static_int_cast
<PIXBYTE
>(nG
),
241 sal::static_int_cast
<PIXBYTE
>(nB
) );
245 template <ScanlineFormat MASKFMT
, ScanlineFormat SRCFMT
, ScanlineFormat DSTFMT
>
246 static void ImplBlendLines( const TrueColorPixelPtr
<DSTFMT
>& rDst
,
247 const TrueColorPixelPtr
<SRCFMT
>& rSrc
, const TrueColorPixelPtr
<MASKFMT
>& rMsk
,
250 TrueColorPixelPtr
<MASKFMT
> aMsk( rMsk
);
251 TrueColorPixelPtr
<DSTFMT
> aDst( rDst
);
252 TrueColorPixelPtr
<SRCFMT
> aSrc( rSrc
);
253 while( --nPixelCount
>= 0 )
255 // VCL masks store alpha as color, hence the GetRed() and not GetAlpha().
256 ImplBlendPixels(aDst
, aSrc
, aMsk
.GetRed());
263 static bool ImplCopyImage( BitmapBuffer
& rDstBuffer
, const BitmapBuffer
& rSrcBuffer
)
265 const int nSrcLinestep
= rSrcBuffer
.mnScanlineSize
;
266 int nDstLinestep
= rDstBuffer
.mnScanlineSize
;
268 const PIXBYTE
* pRawSrc
= rSrcBuffer
.mpBits
;
269 PIXBYTE
* pRawDst
= rDstBuffer
.mpBits
;
271 // source and destination don't match upside down
272 if( ScanlineFormat::TopDown
& (rSrcBuffer
.mnFormat
^ rDstBuffer
.mnFormat
) )
274 pRawDst
+= (rSrcBuffer
.mnHeight
- 1) * nDstLinestep
;
275 nDstLinestep
= -rDstBuffer
.mnScanlineSize
;
277 else if( nSrcLinestep
== nDstLinestep
)
279 memcpy( pRawDst
, pRawSrc
, rSrcBuffer
.mnHeight
* nDstLinestep
);
283 int nByteWidth
= nSrcLinestep
;
284 if( nByteWidth
> rDstBuffer
.mnScanlineSize
)
285 nByteWidth
= rDstBuffer
.mnScanlineSize
;
287 for( int y
= rSrcBuffer
.mnHeight
; --y
>= 0; )
289 memcpy( pRawDst
, pRawSrc
, nByteWidth
);
290 pRawSrc
+= nSrcLinestep
;
291 pRawDst
+= nDstLinestep
;
297 template <ScanlineFormat DSTFMT
,ScanlineFormat SRCFMT
>
298 static bool ImplConvertToBitmap( TrueColorPixelPtr
<SRCFMT
>& rSrcLine
,
299 BitmapBuffer
& rDstBuffer
, const BitmapBuffer
& rSrcBuffer
)
301 // help the compiler to avoid instantiations of unneeded conversions
302 SAL_WARN_IF( SRCFMT
== DSTFMT
, "vcl.gdi", "ImplConvertToBitmap into same format");
303 if( SRCFMT
== DSTFMT
)
306 const int nSrcLinestep
= rSrcBuffer
.mnScanlineSize
;
307 int nDstLinestep
= rDstBuffer
.mnScanlineSize
;
309 TrueColorPixelPtr
<DSTFMT
> aDstLine
; aDstLine
.SetRawPtr( rDstBuffer
.mpBits
);
311 // source and destination don't match upside down
312 if( ScanlineFormat::TopDown
& (rSrcBuffer
.mnFormat
^ rDstBuffer
.mnFormat
) )
314 aDstLine
.AddByteOffset( (rSrcBuffer
.mnHeight
- 1) * nDstLinestep
);
315 nDstLinestep
= -nDstLinestep
;
318 for( int y
= rSrcBuffer
.mnHeight
; --y
>= 0; )
320 ImplConvertLine( aDstLine
, rSrcLine
, rSrcBuffer
.mnWidth
);
321 rSrcLine
.AddByteOffset( nSrcLinestep
);
322 aDstLine
.AddByteOffset( nDstLinestep
);
328 template <ScanlineFormat SRCFMT
>
329 static bool ImplConvertFromBitmap( BitmapBuffer
& rDst
, const BitmapBuffer
& rSrc
)
331 TrueColorPixelPtr
<SRCFMT
> aSrcType
; aSrcType
.SetRawPtr( rSrc
.mpBits
);
333 // select the matching instantiation for the destination's bitmap format
334 switch (RemoveScanline(rDst
.mnFormat
))
336 case ScanlineFormat::N1BitMsbPal
:
337 case ScanlineFormat::N1BitLsbPal
:
338 case ScanlineFormat::N8BitPal
:
341 case ScanlineFormat::N32BitTcMask
:
342 // return ImplConvertToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc );
345 case ScanlineFormat::N24BitTcBgr
:
346 return ImplConvertToBitmap
<ScanlineFormat::N24BitTcBgr
>( aSrcType
, rDst
, rSrc
);
347 case ScanlineFormat::N24BitTcRgb
:
348 return ImplConvertToBitmap
<ScanlineFormat::N24BitTcRgb
>( aSrcType
, rDst
, rSrc
);
350 case ScanlineFormat::N32BitTcAbgr
:
351 return ImplConvertToBitmap
<ScanlineFormat::N32BitTcAbgr
>( aSrcType
, rDst
, rSrc
);
352 case ScanlineFormat::N32BitTcArgb
:
353 return ImplConvertToBitmap
<ScanlineFormat::N32BitTcArgb
>( aSrcType
, rDst
, rSrc
);
354 case ScanlineFormat::N32BitTcBgra
:
355 return ImplConvertToBitmap
<ScanlineFormat::N32BitTcBgra
>( aSrcType
, rDst
, rSrc
);
356 case ScanlineFormat::N32BitTcRgba
:
357 return ImplConvertToBitmap
<ScanlineFormat::N32BitTcRgba
>( aSrcType
, rDst
, rSrc
);
361 static int nNotAccelerated
= 0;
362 SAL_WARN_IF( rSrc
.mnWidth
* rSrc
.mnHeight
>= 4000 && ++nNotAccelerated
== 100,
364 "ImplConvertFromBitmap for not accelerated case (" << std::hex
<< static_cast<int>(rSrc
.mnFormat
) << "->" << static_cast<int>(rDst
.mnFormat
) << ")" );
369 // A universal stretching conversion is overkill in most common situations
370 // => performance benefits for speeding up the non-stretching cases
371 bool ImplFastBitmapConversion( BitmapBuffer
& rDst
, const BitmapBuffer
& rSrc
,
372 const SalTwoRect
& rTR
)
374 // TODO:horizontal mirroring not implemented yet
375 if( rTR
.mnDestWidth
< 0 )
377 // vertical mirroring
378 if( rTR
.mnDestHeight
< 0 )
379 // TODO: rDst.mnFormat ^= ScanlineFormat::TopDown;
382 // offsetted conversion is not implemented yet
383 if( rTR
.mnSrcX
|| rTR
.mnSrcY
)
385 if( rTR
.mnDestX
|| rTR
.mnDestY
)
388 // stretched conversion is not implemented yet
389 if( rTR
.mnDestWidth
!= rTR
.mnSrcWidth
)
391 if( rTR
.mnDestHeight
!= rTR
.mnSrcHeight
)
394 // check source image size
395 if( rSrc
.mnWidth
< rTR
.mnSrcX
+ rTR
.mnSrcWidth
)
397 if( rSrc
.mnHeight
< rTR
.mnSrcY
+ rTR
.mnSrcHeight
)
400 // check dest image size
401 if( rDst
.mnWidth
< rTR
.mnDestX
+ rTR
.mnDestWidth
)
403 if( rDst
.mnHeight
< rTR
.mnDestY
+ rTR
.mnDestHeight
)
406 const ScanlineFormat nSrcFormat
= RemoveScanline(rSrc
.mnFormat
);
407 const ScanlineFormat nDstFormat
= RemoveScanline(rDst
.mnFormat
);
409 // special handling of trivial cases
410 if( nSrcFormat
== nDstFormat
)
412 // accelerated palette conversions not yet implemented
413 if( rSrc
.maPalette
!= rDst
.maPalette
)
415 return ImplCopyImage( rDst
, rSrc
);
418 // select the matching instantiation for the source's bitmap format
421 case ScanlineFormat::N1BitMsbPal
:
422 case ScanlineFormat::N1BitLsbPal
:
425 case ScanlineFormat::N32BitTcMask
:
426 // return ImplConvertFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
429 case ScanlineFormat::N8BitPal
:
430 if(rSrc
.maPalette
.IsGreyPalette8Bit())
431 return ImplConvertFromBitmap
<ScanlineFormat::N8BitPal
>( rDst
, rSrc
);
434 case ScanlineFormat::N24BitTcBgr
:
435 return ImplConvertFromBitmap
<ScanlineFormat::N24BitTcBgr
>( rDst
, rSrc
);
436 case ScanlineFormat::N24BitTcRgb
:
437 return ImplConvertFromBitmap
<ScanlineFormat::N24BitTcRgb
>( rDst
, rSrc
);
439 case ScanlineFormat::N32BitTcAbgr
:
440 return ImplConvertFromBitmap
<ScanlineFormat::N32BitTcAbgr
>( rDst
, rSrc
);
441 case ScanlineFormat::N32BitTcArgb
:
442 return ImplConvertFromBitmap
<ScanlineFormat::N32BitTcArgb
>( rDst
, rSrc
);
443 case ScanlineFormat::N32BitTcBgra
:
444 return ImplConvertFromBitmap
<ScanlineFormat::N32BitTcBgra
>( rDst
, rSrc
);
445 case ScanlineFormat::N32BitTcRgba
:
446 return ImplConvertFromBitmap
<ScanlineFormat::N32BitTcRgba
>( rDst
, rSrc
);
450 static int nNotAccelerated
= 0;
451 SAL_WARN_IF( rSrc
.mnWidth
* rSrc
.mnHeight
>= 4000 && ++nNotAccelerated
== 100,
453 "ImplFastBitmapConversion for not accelerated case (" << std::hex
<< static_cast<int>(rSrc
.mnFormat
) << "->" << static_cast<int>(rDst
.mnFormat
) << ")" );
458 static inline ConstScanline
ImplGetScanline( const BitmapBuffer
& rBuf
, tools::Long nY
)
460 if( rBuf
.mnFormat
& ScanlineFormat::TopDown
)
461 return rBuf
.mpBits
+ nY
* rBuf
.mnScanlineSize
;
463 return rBuf
.mpBits
+ (rBuf
.mnHeight
- 1 - nY
) * rBuf
.mnScanlineSize
;
466 static inline Scanline
ImplGetScanline( BitmapBuffer
& rBuf
, tools::Long nY
)
468 return const_cast<Scanline
>(ImplGetScanline( const_cast<const BitmapBuffer
&>(rBuf
), nY
));
471 template <ScanlineFormat DSTFMT
, ScanlineFormat SRCFMT
>
472 static bool ImplCopyToScanline( tools::Long nY
, BitmapBuffer
& rDst
, TrueColorPixelPtr
<SRCFMT
>& rSrcLine
, tools::Long nSrcWidth
)
474 TrueColorPixelPtr
<DSTFMT
> aDstType
;
475 aDstType
.SetRawPtr( ImplGetScanline( rDst
, nY
));
476 ImplConvertLine( aDstType
, rSrcLine
, std::min( nSrcWidth
, rDst
.mnWidth
));
480 template <ScanlineFormat SRCFMT
>
481 static bool ImplCopyFromScanline( tools::Long nY
, BitmapBuffer
& rDst
, ConstScanline aSrcScanline
, tools::Long nSrcWidth
)
483 TrueColorPixelPtr
<SRCFMT
> aSrcType
;
484 aSrcType
.SetRawPtr( const_cast<Scanline
>( aSrcScanline
));
485 // select the matching instantiation for the destination's bitmap format
486 switch( RemoveScanline( rDst
.mnFormat
))
488 case ScanlineFormat::N24BitTcBgr
:
489 return ImplCopyToScanline
<ScanlineFormat::N24BitTcBgr
>( nY
, rDst
, aSrcType
, nSrcWidth
);
490 case ScanlineFormat::N24BitTcRgb
:
491 return ImplCopyToScanline
<ScanlineFormat::N24BitTcRgb
>( nY
, rDst
, aSrcType
, nSrcWidth
);
493 case ScanlineFormat::N32BitTcAbgr
:
494 return ImplCopyToScanline
<ScanlineFormat::N32BitTcAbgr
>( nY
, rDst
, aSrcType
, nSrcWidth
);
495 case ScanlineFormat::N32BitTcArgb
:
496 return ImplCopyToScanline
<ScanlineFormat::N32BitTcArgb
>( nY
, rDst
, aSrcType
, nSrcWidth
);
497 case ScanlineFormat::N32BitTcBgra
:
498 return ImplCopyToScanline
<ScanlineFormat::N32BitTcBgra
>( nY
, rDst
, aSrcType
, nSrcWidth
);
499 case ScanlineFormat::N32BitTcRgba
:
500 return ImplCopyToScanline
<ScanlineFormat::N32BitTcRgba
>( nY
, rDst
, aSrcType
, nSrcWidth
);
508 bool ImplFastCopyScanline( tools::Long nY
, BitmapBuffer
& rDst
, ConstScanline aSrcScanline
,
509 ScanlineFormat nSrcScanlineFormat
, sal_uInt32 nSrcScanlineSize
)
511 if( rDst
.mnHeight
<= nY
)
514 const ScanlineFormat nSrcFormat
= RemoveScanline(nSrcScanlineFormat
);
515 const ScanlineFormat nDstFormat
= RemoveScanline(rDst
.mnFormat
);
517 // special handling of trivial cases
518 if( nSrcFormat
== nDstFormat
)
520 memcpy( ImplGetScanline( rDst
, nY
), aSrcScanline
, std::min
<tools::Long
>(nSrcScanlineSize
, rDst
.mnScanlineSize
));
524 // select the matching instantiation for the source's bitmap format
527 case ScanlineFormat::N24BitTcBgr
:
528 return ImplCopyFromScanline
<ScanlineFormat::N24BitTcBgr
>( nY
, rDst
, aSrcScanline
, nSrcScanlineSize
/ 3 );
529 case ScanlineFormat::N24BitTcRgb
:
530 return ImplCopyFromScanline
<ScanlineFormat::N24BitTcRgb
>( nY
, rDst
, aSrcScanline
, nSrcScanlineSize
/ 3 );
532 case ScanlineFormat::N32BitTcAbgr
:
533 return ImplCopyFromScanline
<ScanlineFormat::N32BitTcAbgr
>( nY
, rDst
, aSrcScanline
, nSrcScanlineSize
/ 4 );
534 case ScanlineFormat::N32BitTcArgb
:
535 return ImplCopyFromScanline
<ScanlineFormat::N32BitTcArgb
>( nY
, rDst
, aSrcScanline
, nSrcScanlineSize
/ 4 );
536 case ScanlineFormat::N32BitTcBgra
:
537 return ImplCopyFromScanline
<ScanlineFormat::N32BitTcBgra
>( nY
, rDst
, aSrcScanline
, nSrcScanlineSize
/ 4 );
538 case ScanlineFormat::N32BitTcRgba
:
539 return ImplCopyFromScanline
<ScanlineFormat::N32BitTcRgba
>( nY
, rDst
, aSrcScanline
, nSrcScanlineSize
/ 4 );
546 bool ImplFastCopyScanline( tools::Long nY
, BitmapBuffer
& rDst
, const BitmapBuffer
& rSrc
)
548 if( nY
>= rDst
.mnHeight
)
550 if( rSrc
.maPalette
!= rDst
.maPalette
)
552 return ImplFastCopyScanline( nY
, rDst
, ImplGetScanline( rSrc
, nY
), rSrc
.mnFormat
, rSrc
.mnScanlineSize
);
555 template <ScanlineFormat DSTFMT
, ScanlineFormat SRCFMT
> //,sal_uLong MSKFMT>
556 static bool ImplBlendToBitmap( TrueColorPixelPtr
<SRCFMT
>& rSrcLine
,
557 BitmapBuffer
& rDstBuffer
, const BitmapBuffer
& rSrcBuffer
,
558 const BitmapBuffer
& rMskBuffer
)
560 SAL_WARN_IF(( rMskBuffer
.mnFormat
& ~ScanlineFormat::TopDown
) != ScanlineFormat::N8BitPal
,
561 "vcl.gdi", "FastBmp BlendImage: unusual MSKFMT" );
563 const int nSrcLinestep
= rSrcBuffer
.mnScanlineSize
;
564 int nMskLinestep
= rMskBuffer
.mnScanlineSize
;
565 int nDstLinestep
= rDstBuffer
.mnScanlineSize
;
567 TrueColorPixelPtr
<ScanlineFormat::N8BitPal
> aMskLine
; aMskLine
.SetRawPtr( rMskBuffer
.mpBits
);
568 TrueColorPixelPtr
<DSTFMT
> aDstLine
; aDstLine
.SetRawPtr( rDstBuffer
.mpBits
);
570 // special case for single line masks
571 if( rMskBuffer
.mnHeight
== 1 )
574 // source and mask don't match: upside down
575 if( (rSrcBuffer
.mnFormat
^ rMskBuffer
.mnFormat
) & ScanlineFormat::TopDown
)
577 aMskLine
.AddByteOffset( (rSrcBuffer
.mnHeight
- 1) * nMskLinestep
);
578 nMskLinestep
= -nMskLinestep
;
581 // source and destination don't match: upside down
582 if( (rSrcBuffer
.mnFormat
^ rDstBuffer
.mnFormat
) & ScanlineFormat::TopDown
)
584 aDstLine
.AddByteOffset( (rDstBuffer
.mnHeight
- 1) * nDstLinestep
);
585 nDstLinestep
= -nDstLinestep
;
588 assert(rDstBuffer
.mnHeight
<= rSrcBuffer
.mnHeight
&& "not sure about that?");
589 for (int y
= rDstBuffer
.mnHeight
; --y
>= 0;)
591 ImplBlendLines(aDstLine
, rSrcLine
, aMskLine
, rDstBuffer
.mnWidth
);
592 aDstLine
.AddByteOffset( nDstLinestep
);
593 rSrcLine
.AddByteOffset( nSrcLinestep
);
594 aMskLine
.AddByteOffset( nMskLinestep
);
600 // some specializations to reduce the code size
602 bool ImplBlendToBitmap
<ScanlineFormat::N24BitTcBgr
,ScanlineFormat::N24BitTcBgr
>(
603 TrueColorPixelPtr
<ScanlineFormat::N24BitTcBgr
>&,
604 BitmapBuffer
& rDstBuffer
, const BitmapBuffer
& rSrcBuffer
,
605 const BitmapBuffer
& rMskBuffer
)
607 TrueColorPixelPtr
<ScanlineFormat::N24BitTcRgb
> aSrcType
; aSrcType
.SetRawPtr( rSrcBuffer
.mpBits
);
608 return ImplBlendToBitmap
<ScanlineFormat::N24BitTcRgb
>( aSrcType
, rDstBuffer
, rSrcBuffer
, rMskBuffer
);
612 bool ImplBlendToBitmap
<ScanlineFormat::N32BitTcAbgr
,ScanlineFormat::N32BitTcAbgr
>(
613 TrueColorPixelPtr
<ScanlineFormat::N32BitTcAbgr
>&,
614 BitmapBuffer
& rDstBuffer
, const BitmapBuffer
& rSrcBuffer
,
615 const BitmapBuffer
& rMskBuffer
)
617 TrueColorPixelPtr
<ScanlineFormat::N32BitTcArgb
> aSrcType
; aSrcType
.SetRawPtr( rSrcBuffer
.mpBits
);
618 return ImplBlendToBitmap
<ScanlineFormat::N32BitTcArgb
>( aSrcType
, rDstBuffer
, rSrcBuffer
, rMskBuffer
);
622 bool ImplBlendToBitmap
<ScanlineFormat::N32BitTcBgra
,ScanlineFormat::N32BitTcBgra
>(
623 TrueColorPixelPtr
<ScanlineFormat::N32BitTcBgra
>&,
624 BitmapBuffer
& rDstBuffer
, const BitmapBuffer
& rSrcBuffer
,
625 const BitmapBuffer
& rMskBuffer
)
627 TrueColorPixelPtr
<ScanlineFormat::N32BitTcRgba
> aSrcType
; aSrcType
.SetRawPtr( rSrcBuffer
.mpBits
);
628 return ImplBlendToBitmap
<ScanlineFormat::N32BitTcRgba
>( aSrcType
, rDstBuffer
, rSrcBuffer
, rMskBuffer
);
631 template <ScanlineFormat SRCFMT
>
632 static bool ImplBlendFromBitmap( BitmapBuffer
& rDst
, const BitmapBuffer
& rSrc
, const BitmapBuffer
& rMsk
)
634 TrueColorPixelPtr
<SRCFMT
> aSrcType
; aSrcType
.SetRawPtr( rSrc
.mpBits
);
636 // select the matching instantiation for the destination's bitmap format
637 switch (RemoveScanline(rDst
.mnFormat
))
639 case ScanlineFormat::N1BitMsbPal
:
640 case ScanlineFormat::N1BitLsbPal
:
641 case ScanlineFormat::N8BitPal
:
644 case ScanlineFormat::N32BitTcMask
:
645 // return ImplBlendToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc, rMsk );
648 case ScanlineFormat::N24BitTcBgr
:
649 return ImplBlendToBitmap
<ScanlineFormat::N24BitTcBgr
>( aSrcType
, rDst
, rSrc
, rMsk
);
650 case ScanlineFormat::N24BitTcRgb
:
651 return ImplBlendToBitmap
<ScanlineFormat::N24BitTcRgb
>( aSrcType
, rDst
, rSrc
, rMsk
);
653 case ScanlineFormat::N32BitTcAbgr
:
654 return ImplBlendToBitmap
<ScanlineFormat::N32BitTcAbgr
>( aSrcType
, rDst
, rSrc
, rMsk
);
655 case ScanlineFormat::N32BitTcArgb
:
656 return ImplBlendToBitmap
<ScanlineFormat::N32BitTcArgb
>( aSrcType
, rDst
, rSrc
, rMsk
);
657 case ScanlineFormat::N32BitTcBgra
:
658 return ImplBlendToBitmap
<ScanlineFormat::N32BitTcBgra
>( aSrcType
, rDst
, rSrc
, rMsk
);
659 case ScanlineFormat::N32BitTcRgba
:
660 return ImplBlendToBitmap
<ScanlineFormat::N32BitTcRgba
>( aSrcType
, rDst
, rSrc
, rMsk
);
664 static int nNotAccelerated
= 0;
665 SAL_WARN_IF( rSrc
.mnWidth
* rSrc
.mnHeight
>= 4000 && ++nNotAccelerated
== 100,
667 "ImplBlendFromBitmap for not accelerated case (" << std::hex
<< static_cast<int>(rSrc
.mnFormat
) << "*" << static_cast<int>(rMsk
.mnFormat
) << "->" << static_cast<int>(rDst
.mnFormat
) );
671 bool ImplFastBitmapBlending( BitmapWriteAccess
const & rDstWA
,
672 const BitmapReadAccess
& rSrcRA
, const BitmapReadAccess
& rMskRA
,
673 const SalTwoRect
& rTR
)
675 // accelerated blending of paletted bitmaps not implemented yet
676 if( rSrcRA
.HasPalette() )
678 if( rDstWA
.HasPalette() )
680 // TODO: either get rid of mask's use of 8BIT_PAL or check the palette
682 // horizontal mirroring not implemented yet
683 if( rTR
.mnDestWidth
< 0 )
685 // vertical mirroring
686 if( rTR
.mnDestHeight
< 0 )
687 // TODO: rDst.mnFormat ^= ScanlineFormat::TopDown;
690 // offsetted blending is not implemented yet
691 if( rTR
.mnSrcX
|| rTR
.mnSrcY
)
693 if( rTR
.mnDestX
|| rTR
.mnDestY
)
696 // stretched blending is not implemented yet
697 if( rTR
.mnDestWidth
!= rTR
.mnSrcWidth
)
699 if( rTR
.mnDestHeight
!= rTR
.mnSrcHeight
)
702 // check source image size
703 if( rSrcRA
.Width() < rTR
.mnSrcX
+ rTR
.mnSrcWidth
)
705 if( rSrcRA
.Height() < rTR
.mnSrcY
+ rTR
.mnSrcHeight
)
708 // check mask image size
709 if( rMskRA
.Width() < rTR
.mnSrcX
+ rTR
.mnSrcWidth
)
711 if( rMskRA
.Height() < rTR
.mnSrcY
+ rTR
.mnSrcHeight
)
712 if( rMskRA
.Height() != 1 )
715 // check dest image size
716 if( rDstWA
.Width() < rTR
.mnDestX
+ rTR
.mnDestWidth
)
718 if( rDstWA
.Height() < rTR
.mnDestY
+ rTR
.mnDestHeight
)
721 BitmapBuffer
& rDst
= *rDstWA
.ImplGetBitmapBuffer();
722 const BitmapBuffer
& rSrc
= *rSrcRA
.ImplGetBitmapBuffer();
723 const BitmapBuffer
& rMsk
= *rMskRA
.ImplGetBitmapBuffer();
725 const ScanlineFormat nSrcFormat
= RemoveScanline(rSrc
.mnFormat
);
727 // select the matching instantiation for the source's bitmap format
730 case ScanlineFormat::N1BitMsbPal
:
731 case ScanlineFormat::N1BitLsbPal
:
734 case ScanlineFormat::N32BitTcMask
:
735 // return ImplBlendFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
738 case ScanlineFormat::N8BitPal
:
739 if(rSrc
.maPalette
.IsGreyPalette8Bit())
740 return ImplBlendFromBitmap
<ScanlineFormat::N8BitPal
>( rDst
, rSrc
, rMsk
);
743 case ScanlineFormat::N24BitTcBgr
:
744 return ImplBlendFromBitmap
<ScanlineFormat::N24BitTcBgr
>( rDst
, rSrc
, rMsk
);
745 case ScanlineFormat::N24BitTcRgb
:
746 return ImplBlendFromBitmap
<ScanlineFormat::N24BitTcRgb
>( rDst
, rSrc
, rMsk
);
748 case ScanlineFormat::N32BitTcAbgr
:
749 return ImplBlendFromBitmap
<ScanlineFormat::N32BitTcAbgr
>( rDst
, rSrc
, rMsk
);
750 case ScanlineFormat::N32BitTcArgb
:
751 return ImplBlendFromBitmap
<ScanlineFormat::N32BitTcArgb
>( rDst
, rSrc
, rMsk
);
752 case ScanlineFormat::N32BitTcBgra
:
753 return ImplBlendFromBitmap
<ScanlineFormat::N32BitTcBgra
>( rDst
, rSrc
, rMsk
);
754 case ScanlineFormat::N32BitTcRgba
:
755 return ImplBlendFromBitmap
<ScanlineFormat::N32BitTcRgba
>( rDst
, rSrc
, rMsk
);
759 static int nNotAccelerated
= 0;
760 SAL_WARN_IF( rSrc
.mnWidth
* rSrc
.mnHeight
>= 4000 && ++nNotAccelerated
== 100,
762 "ImplFastBlend for not accelerated case (" << std::hex
<< static_cast<int>(rSrc
.mnFormat
) << "*" << static_cast<int>(rMsk
.mnFormat
) << "->" << static_cast<int>(rDst
.mnFormat
) << ")" );
767 bool ImplFastEraseBitmap( BitmapBuffer
& rDst
, const BitmapColor
& rColor
)
769 const ScanlineFormat nDstFormat
= RemoveScanline(rDst
.mnFormat
);
771 // erasing a bitmap is often just a byte-wise memory fill
772 bool bByteFill
= true;
777 case ScanlineFormat::N1BitMsbPal
:
778 case ScanlineFormat::N1BitLsbPal
:
779 nFillByte
= rColor
.GetIndex();
780 nFillByte
= static_cast<sal_uInt8
>( -(nFillByte
& 1) ); // 0x00 or 0xFF
782 case ScanlineFormat::N8BitPal
:
783 nFillByte
= rColor
.GetIndex();
786 case ScanlineFormat::N24BitTcBgr
:
787 case ScanlineFormat::N24BitTcRgb
:
788 nFillByte
= rColor
.GetRed();
789 if( (nFillByte
!= rColor
.GetGreen())
790 || (nFillByte
!= rColor
.GetBlue()) )
802 tools::Long nByteCount
= rDst
.mnHeight
* rDst
.mnScanlineSize
;
803 memset( rDst
.mpBits
, nFillByte
, nByteCount
);
807 // TODO: handle other bitmap formats
810 case ScanlineFormat::N32BitTcMask
:
812 case ScanlineFormat::N24BitTcBgr
:
813 case ScanlineFormat::N24BitTcRgb
:
815 case ScanlineFormat::N32BitTcAbgr
:
816 case ScanlineFormat::N32BitTcArgb
:
817 case ScanlineFormat::N32BitTcBgra
:
818 case ScanlineFormat::N32BitTcRgba
:
828 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */