Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / vcl / source / gdi / bmpfast.cxx
bloba610394cf1a62e6400d54922cc1e893bbeb90021
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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
25 #include <stdlib.h>
27 typedef unsigned char PIXBYTE;
29 class BasePixelPtr
31 public:
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; }
37 protected:
38 PIXBYTE* mpPixel;
41 template <ScanlineFormat PIXFMT>
42 class TrueColorPixelPtr : public BasePixelPtr
44 public:
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
55 template <>
56 class TrueColorPixelPtr<ScanlineFormat::N24BitTcRgb> : public BasePixelPtr
58 public:
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
69 mpPixel[0] = r;
70 mpPixel[1] = g;
71 mpPixel[2] = b;
75 template <>
76 class TrueColorPixelPtr<ScanlineFormat::N24BitTcBgr> : public BasePixelPtr
78 public:
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
89 mpPixel[0] = b;
90 mpPixel[1] = g;
91 mpPixel[2] = r;
95 template <>
96 class TrueColorPixelPtr<ScanlineFormat::N32BitTcArgb> : public BasePixelPtr
98 public:
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
109 mpPixel[1] = r;
110 mpPixel[2] = g;
111 mpPixel[3] = b;
115 template <>
116 class TrueColorPixelPtr<ScanlineFormat::N32BitTcAbgr> : public BasePixelPtr
118 public:
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
129 mpPixel[1] = b;
130 mpPixel[2] = g;
131 mpPixel[3] = r;
135 template <>
136 class TrueColorPixelPtr<ScanlineFormat::N32BitTcRgba> : public BasePixelPtr
138 public:
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
149 mpPixel[0] = r;
150 mpPixel[1] = g;
151 mpPixel[2] = b;
155 template <>
156 class TrueColorPixelPtr<ScanlineFormat::N32BitTcBgra> : public BasePixelPtr
158 public:
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
169 mpPixel[0] = b;
170 mpPixel[1] = g;
171 mpPixel[2] = r;
175 template <>
176 class TrueColorPixelPtr<ScanlineFormat::N16BitTcMsbMask> : public BasePixelPtr
178 public:
179 void operator++() { mpPixel += 2; }
181 // TODO: non565-RGB
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);
195 template <>
196 class TrueColorPixelPtr<ScanlineFormat::N16BitTcLsbMask> : public BasePixelPtr
198 public:
199 void operator++() { mpPixel += 2; }
201 // TODO: non565-RGB
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);
215 template <>
216 class TrueColorPixelPtr<ScanlineFormat::N8BitTcMask> : public BasePixelPtr
218 public:
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
226 template <>
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() );
240 template <>
241 inline void ImplConvertPixel<ScanlineFormat::N16BitTcLsbMask, ScanlineFormat::N16BitTcMsbMask> (
242 const TrueColorPixelPtr<ScanlineFormat::N16BitTcMsbMask>& rDst,
243 const TrueColorPixelPtr<ScanlineFormat::N16BitTcLsbMask>& rSrc )
245 // byte swapping
246 const PIXBYTE* pSrc = rSrc.GetRawPtr();
247 PIXBYTE* pDst = rDst.GetRawPtr();
248 pDst[1] = pSrc[0];
249 pDst[0] = pSrc[1];
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 );
261 ++aSrc;
262 ++aDst;
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;
272 if( !nAlphaVal )
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();
285 nS = rSrc.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,
297 int nPixelCount )
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());
305 ++aDst;
306 ++aSrc;
307 ++aMsk;
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 );
328 return true;
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;
342 return true;
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 )
352 return false;
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 );
373 return true;
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:
389 break;
391 case ScanlineFormat::N8BitTcMask:
392 // return ImplConvertToBitmap<ScanlineFormat::N8BitTcMask>( aSrcType, rDst, rSrc );
393 case ScanlineFormat::N32BitTcMask:
394 // return ImplConvertToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc );
395 break;
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 );
414 #endif
415 case ScanlineFormat::N32BitTcRgba:
416 return ImplConvertToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDst, rSrc );
417 default: break;
420 static int nNotAccelerated = 0;
421 SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
422 "vcl.gdi",
423 "ImplConvertFromBitmap for not accelerated case (" << std::hex << (int)rSrc.mnFormat << "->" << (int)rDst.mnFormat << ")" );
425 return false;
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 )
435 return false;
436 // vertical mirroring
437 if( rTR.mnDestHeight < 0 )
438 // TODO: rDst.mnFormat ^= ScanlineFormat::TopDown;
439 return false;
441 // offseted conversion is not implemented yet
442 if( rTR.mnSrcX || rTR.mnSrcY )
443 return false;
444 if( rTR.mnDestX || rTR.mnDestY )
445 return false;
447 // stretched conversion is not implemented yet
448 if( rTR.mnDestWidth != rTR.mnSrcWidth )
449 return false;
450 if( rTR.mnDestHeight!= rTR.mnSrcHeight )
451 return false;
453 // check source image size
454 if( rSrc.mnWidth < rTR.mnSrcX + rTR.mnSrcWidth )
455 return false;
456 if( rSrc.mnHeight < rTR.mnSrcY + rTR.mnSrcHeight )
457 return false;
459 // check dest image size
460 if( rDst.mnWidth < rTR.mnDestX + rTR.mnDestWidth )
461 return false;
462 if( rDst.mnHeight < rTR.mnDestY + rTR.mnDestHeight )
463 return false;
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 )
473 return false;
474 if( nDstFormat & (ScanlineFormat::N16BitTcLsbMask | ScanlineFormat::N16BitTcMsbMask) )
475 if( rDst.maColorMask.GetRedMask() != 0xF800
476 || rDst.maColorMask.GetGreenMask()!= 0x07E0
477 || rDst.maColorMask.GetBlueMask() != 0x001F )
478 return false;
480 // special handling of trivial cases
481 if( nSrcFormat == nDstFormat )
483 // accelerated palette conversions not yet implemented
484 if( rSrc.maPalette != rDst.maPalette )
485 return false;
486 return ImplCopyImage( rDst, rSrc );
489 // select the matching instantiation for the source's bitmap format
490 switch( nSrcFormat )
492 case ScanlineFormat::N1BitMsbPal:
493 case ScanlineFormat::N1BitLsbPal:
494 case ScanlineFormat::N4BitMsnPal:
495 case ScanlineFormat::N4BitLsnPal:
496 case ScanlineFormat::N8BitPal:
497 break;
499 case ScanlineFormat::N8BitTcMask:
500 // return ImplConvertFromBitmap<ScanlineFormat::N8BitTcMask>( rDst, rSrc );
501 case ScanlineFormat::N32BitTcMask:
502 // return ImplConvertFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
503 break;
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 );
522 #endif
523 case ScanlineFormat::N32BitTcRgba:
524 return ImplConvertFromBitmap<ScanlineFormat::N32BitTcRgba>( rDst, rSrc );
525 default: break;
528 static int nNotAccelerated = 0;
529 SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
530 "vcl.gdi",
531 "ImplFastBitmapConversion for not accelerated case (" << std::hex << (int)rSrc.mnFormat << "->" << (int)rDst.mnFormat << ")" );
533 return false;
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 )
552 nMskLinestep = 0;
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 );
577 return true;
580 // some specializations to reduce the code size
581 template <>
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 );
591 template <>
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 );
601 template <>
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:
624 break;
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 );
630 break;
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 );
649 #endif
650 case ScanlineFormat::N32BitTcRgba:
651 return ImplBlendToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDst, rSrc, rMsk );
652 default: break;
655 static int nNotAccelerated = 0;
656 SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
657 "vcl.gdi",
658 "ImplBlendFromBitmap for not accelerated case (" << std::hex << (int)rSrc.mnFormat << "*" << (int)rMsk.mnFormat << "->" << (int)rDst.mnFormat );
659 return false;
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() )
668 return false;
669 if( rDstWA.HasPalette() )
670 return false;
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 )
675 return false;
676 // vertical mirroring
677 if( rTR.mnDestHeight < 0 )
678 // TODO: rDst.mnFormat ^= ScanlineFormat::TopDown;
679 return false;
681 // offseted blending is not implemented yet
682 if( rTR.mnSrcX || rTR.mnSrcY )
683 return false;
684 if( rTR.mnDestX || rTR.mnDestY )
685 return false;
687 // stretched blending is not implemented yet
688 if( rTR.mnDestWidth != rTR.mnSrcWidth )
689 return false;
690 if( rTR.mnDestHeight!= rTR.mnSrcHeight )
691 return false;
693 // check source image size
694 if( rSrcRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
695 return false;
696 if( rSrcRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
697 return false;
699 // check mask image size
700 if( rMskRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
701 return false;
702 if( rMskRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
703 if( rMskRA.Height() != 1 )
704 return false;
706 // check dest image size
707 if( rDstWA.Width() < rTR.mnDestX + rTR.mnDestWidth )
708 return false;
709 if( rDstWA.Height() < rTR.mnDestY + rTR.mnDestHeight )
710 return false;
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)
724 return false;
725 if( nDstFormat & (ScanlineFormat::N16BitTcLsbMask | ScanlineFormat::N16BitTcMsbMask) )
726 if( rDst.maColorMask.GetRedMask() != 0xF800
727 || rDst.maColorMask.GetGreenMask()!= 0x07E0
728 || rDst.maColorMask.GetBlueMask() != 0x001F)
729 return false;
731 // select the matching instantiation for the source's bitmap format
732 switch( nSrcFormat )
734 case ScanlineFormat::N1BitMsbPal:
735 case ScanlineFormat::N1BitLsbPal:
736 case ScanlineFormat::N4BitMsnPal:
737 case ScanlineFormat::N4BitLsnPal:
738 case ScanlineFormat::N8BitPal:
739 break;
741 case ScanlineFormat::N8BitTcMask:
742 // return ImplBlendFromBitmap<ScanlineFormat::N8BitTcMask>( rDst, rSrc );
743 case ScanlineFormat::N32BitTcMask:
744 // return ImplBlendFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
745 break;
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 );
764 #endif
765 case ScanlineFormat::N32BitTcRgba:
766 return ImplBlendFromBitmap<ScanlineFormat::N32BitTcRgba>( rDst, rSrc, rMsk );
767 default: break;
770 static int nNotAccelerated = 0;
771 SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
772 "vcl.gdi",
773 "ImplFastBlend for not accelerated case (" << std::hex << (int)rSrc.mnFormat << "*" << (int)rMsk.mnFormat << "->" << (int)rDst.mnFormat << ")" );
775 return false;
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;
784 sal_uInt8 nFillByte;
786 switch( nDstFormat )
788 case ScanlineFormat::N1BitMsbPal:
789 case ScanlineFormat::N1BitLsbPal:
790 nFillByte = rColor.GetIndex();
791 nFillByte = static_cast<sal_uInt8>( -(nFillByte & 1) ); // 0x00 or 0xFF
792 break;
793 case ScanlineFormat::N4BitMsnPal:
794 case ScanlineFormat::N4BitLsnPal:
795 nFillByte = rColor.GetIndex();
796 nFillByte &= 0x0F;
797 nFillByte |= (nFillByte << 4);
798 break;
799 case ScanlineFormat::N8BitPal:
800 case ScanlineFormat::N8BitTcMask:
801 nFillByte = rColor.GetIndex();
802 break;
804 case ScanlineFormat::N24BitTcBgr:
805 case ScanlineFormat::N24BitTcRgb:
806 nFillByte = rColor.GetRed();
807 if( (nFillByte != rColor.GetGreen())
808 || (nFillByte != rColor.GetBlue()) )
809 bByteFill = false;
810 break;
812 default:
813 bByteFill = false;
814 nFillByte = 0x00;
815 break;
818 if( bByteFill )
820 long nByteCount = rDst.mnHeight * rDst.mnScanlineSize;
821 memset( rDst.mpBits, nFillByte, nByteCount );
822 return true;
825 // TODO: handle other bitmap formats
826 switch( nDstFormat )
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:
839 #endif
840 case ScanlineFormat::N32BitTcRgba:
841 break;
843 default:
844 break;
847 return false;
850 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */