bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / gdi / bmpfast.cxx
blob36423b1e206ea79d143ea9914ed52a266dba0c65
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>
22 #include <vcl/salgtype.hxx>
23 #include <bitmapwriteaccess.hxx>
25 #include <sal/log.hxx>
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 void AddByteOffset( int nByteOffset ) { mpPixel += nByteOffset; }
36 protected:
37 PIXBYTE* mpPixel;
40 template <ScanlineFormat PIXFMT>
41 class TrueColorPixelPtr : public BasePixelPtr
43 public:
44 PIXBYTE GetRed() const;
45 PIXBYTE GetGreen() const;
46 PIXBYTE GetBlue() const;
47 PIXBYTE GetAlpha() const;
49 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const;
50 void SetAlpha( PIXBYTE a ) const;
53 // template specializations for truecolor pixel formats
54 template <>
55 class TrueColorPixelPtr<ScanlineFormat::N24BitTcRgb> : public BasePixelPtr
57 public:
58 void operator++() { mpPixel += 3; }
60 PIXBYTE GetRed() const { return mpPixel[0]; }
61 PIXBYTE GetGreen() const { return mpPixel[1]; }
62 PIXBYTE GetBlue() const { return mpPixel[2]; }
63 static PIXBYTE GetAlpha() { return 0; }
64 static void SetAlpha( PIXBYTE ) {}
66 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
68 mpPixel[0] = r;
69 mpPixel[1] = g;
70 mpPixel[2] = b;
74 template <>
75 class TrueColorPixelPtr<ScanlineFormat::N24BitTcBgr> : public BasePixelPtr
77 public:
78 void operator++() { mpPixel += 3; }
80 PIXBYTE GetRed() const { return mpPixel[2]; }
81 PIXBYTE GetGreen() const { return mpPixel[1]; }
82 PIXBYTE GetBlue() const { return mpPixel[0]; }
83 static PIXBYTE GetAlpha() { return 0; }
84 static void SetAlpha( PIXBYTE ) {}
86 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
88 mpPixel[0] = b;
89 mpPixel[1] = g;
90 mpPixel[2] = r;
94 template <>
95 class TrueColorPixelPtr<ScanlineFormat::N32BitTcArgb> : public BasePixelPtr
97 public:
98 void operator++() { mpPixel += 4; }
100 PIXBYTE GetRed() const { return mpPixel[1]; }
101 PIXBYTE GetGreen() const { return mpPixel[2]; }
102 PIXBYTE GetBlue() const { return mpPixel[3]; }
103 PIXBYTE GetAlpha() const { return mpPixel[0]; }
104 void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; }
106 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
108 mpPixel[1] = r;
109 mpPixel[2] = g;
110 mpPixel[3] = b;
114 template <>
115 class TrueColorPixelPtr<ScanlineFormat::N32BitTcAbgr> : public BasePixelPtr
117 public:
118 void operator++() { mpPixel += 4; }
120 PIXBYTE GetRed() const { return mpPixel[3]; }
121 PIXBYTE GetGreen() const { return mpPixel[2]; }
122 PIXBYTE GetBlue() const { return mpPixel[1]; }
123 PIXBYTE GetAlpha() const { return mpPixel[0]; }
124 void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; }
126 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
128 mpPixel[1] = b;
129 mpPixel[2] = g;
130 mpPixel[3] = r;
134 template <>
135 class TrueColorPixelPtr<ScanlineFormat::N32BitTcRgba> : public BasePixelPtr
137 public:
138 void operator++() { mpPixel += 4; }
140 PIXBYTE GetRed() const { return mpPixel[0]; }
141 PIXBYTE GetGreen() const { return mpPixel[1]; }
142 PIXBYTE GetBlue() const { return mpPixel[2]; }
143 PIXBYTE GetAlpha() const { return mpPixel[3]; }
144 void SetAlpha( PIXBYTE a ) const{ mpPixel[3] = a; }
146 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
148 mpPixel[0] = r;
149 mpPixel[1] = g;
150 mpPixel[2] = b;
154 template <>
155 class TrueColorPixelPtr<ScanlineFormat::N32BitTcBgra> : public BasePixelPtr
157 public:
158 void operator++() { mpPixel += 4; }
160 PIXBYTE GetRed() const { return mpPixel[2]; }
161 PIXBYTE GetGreen() const { return mpPixel[1]; }
162 PIXBYTE GetBlue() const { return mpPixel[0]; }
163 PIXBYTE GetAlpha() const { return mpPixel[3]; }
164 void SetAlpha( PIXBYTE a ) const{ mpPixel[3] = a; }
166 void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
168 mpPixel[0] = b;
169 mpPixel[1] = g;
170 mpPixel[2] = r;
174 template <>
175 class TrueColorPixelPtr<ScanlineFormat::N8BitTcMask> : public BasePixelPtr
177 public:
178 void operator++() { mpPixel += 1; }
179 PIXBYTE GetAlpha() const { return mpPixel[0]; }
180 void SetAlpha( PIXBYTE a ) const { mpPixel[0] = a; }
183 // TODO: for some reason many Alpha maps are ScanlineFormat::N8BitPal
184 // they should be ScanlineFormat::N8BitTcMask
185 template <>
186 class TrueColorPixelPtr<ScanlineFormat::N8BitPal>
187 : public TrueColorPixelPtr<ScanlineFormat::N8BitTcMask>
190 // converting truecolor formats
191 template <ScanlineFormat SRCFMT, ScanlineFormat DSTFMT>
192 static void ImplConvertPixel( const TrueColorPixelPtr<DSTFMT>& rDst,
193 const TrueColorPixelPtr<SRCFMT>& rSrc )
195 rDst.SetColor( rSrc.GetRed(), rSrc.GetGreen(), rSrc.GetBlue() );
196 rDst.SetAlpha( rSrc.GetAlpha() );
199 template <ScanlineFormat SRCFMT, ScanlineFormat DSTFMT>
200 static void ImplConvertLine( const TrueColorPixelPtr<DSTFMT>& rDst,
201 const TrueColorPixelPtr<SRCFMT>& rSrc, int nPixelCount )
203 TrueColorPixelPtr<DSTFMT> aDst( rDst );
204 TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
205 while( --nPixelCount >= 0 )
207 ImplConvertPixel( aDst, aSrc );
208 ++aSrc;
209 ++aDst;
213 // alpha blending truecolor pixels
214 template <ScanlineFormat SRCFMT, ScanlineFormat DSTFMT>
215 static void ImplBlendPixels( const TrueColorPixelPtr<DSTFMT>& rDst,
216 const TrueColorPixelPtr<SRCFMT>& rSrc, unsigned nAlphaVal )
218 static const unsigned nAlphaShift = 8;
219 if( !nAlphaVal )
220 ImplConvertPixel( rDst, rSrc );
221 else if( nAlphaVal != ~(~0U << nAlphaShift) )
223 int nR = rDst.GetRed();
224 int nS = rSrc.GetRed();
225 nR = nS + (((nR - nS) * nAlphaVal) >> nAlphaShift);
227 int nG = rDst.GetGreen();
228 nS = rSrc.GetGreen();
229 nG = nS + (((nG - nS) * nAlphaVal) >> nAlphaShift);
231 int nB = rDst.GetBlue();
232 nS = rSrc.GetBlue();
233 nB = nS + (((nB - nS) * nAlphaVal) >> nAlphaShift);
235 rDst.SetColor( sal::static_int_cast<PIXBYTE>(nR),
236 sal::static_int_cast<PIXBYTE>(nG),
237 sal::static_int_cast<PIXBYTE>(nB) );
241 template <ScanlineFormat MASKFMT, ScanlineFormat SRCFMT, ScanlineFormat DSTFMT>
242 static void ImplBlendLines( const TrueColorPixelPtr<DSTFMT>& rDst,
243 const TrueColorPixelPtr<SRCFMT>& rSrc, const TrueColorPixelPtr<MASKFMT>& rMsk,
244 int nPixelCount )
246 TrueColorPixelPtr<MASKFMT> aMsk( rMsk );
247 TrueColorPixelPtr<DSTFMT> aDst( rDst );
248 TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
249 while( --nPixelCount >= 0 )
251 ImplBlendPixels(aDst, aSrc, aMsk.GetAlpha());
252 ++aDst;
253 ++aSrc;
254 ++aMsk;
258 static bool ImplCopyImage( BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer )
260 const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
261 int nDstLinestep = rDstBuffer.mnScanlineSize;
263 const PIXBYTE* pRawSrc = rSrcBuffer.mpBits;
264 PIXBYTE* pRawDst = rDstBuffer.mpBits;
266 // source and destination don't match upside down
267 if( ScanlineFormat::TopDown & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) )
269 pRawDst += (rSrcBuffer.mnHeight - 1) * nDstLinestep;
270 nDstLinestep = -rDstBuffer.mnScanlineSize;
272 else if( nSrcLinestep == nDstLinestep )
274 memcpy( pRawDst, pRawSrc, rSrcBuffer.mnHeight * nDstLinestep );
275 return true;
278 int nByteWidth = nSrcLinestep;
279 if( nByteWidth > rDstBuffer.mnScanlineSize )
280 nByteWidth = rDstBuffer.mnScanlineSize;
282 for( int y = rSrcBuffer.mnHeight; --y >= 0; )
284 memcpy( pRawDst, pRawSrc, nByteWidth );
285 pRawSrc += nSrcLinestep;
286 pRawDst += nDstLinestep;
289 return true;
292 template <ScanlineFormat DSTFMT,ScanlineFormat SRCFMT>
293 static bool ImplConvertToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
294 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer )
296 // help the compiler to avoid instantiations of unneeded conversions
297 SAL_WARN_IF( SRCFMT == DSTFMT, "vcl.gdi", "ImplConvertToBitmap into same format");
298 if( SRCFMT == DSTFMT )
299 return false;
301 const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
302 int nDstLinestep = rDstBuffer.mnScanlineSize;
304 TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
306 // source and destination don't match upside down
307 if( ScanlineFormat::TopDown & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) )
309 aDstLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nDstLinestep );
310 nDstLinestep = -nDstLinestep;
313 for( int y = rSrcBuffer.mnHeight; --y >= 0; )
315 ImplConvertLine( aDstLine, rSrcLine, rSrcBuffer.mnWidth );
316 rSrcLine.AddByteOffset( nSrcLinestep );
317 aDstLine.AddByteOffset( nDstLinestep );
320 return true;
323 template <ScanlineFormat SRCFMT>
324 static bool ImplConvertFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc )
326 TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
328 // select the matching instantiation for the destination's bitmap format
329 switch (RemoveScanline(rDst.mnFormat))
331 case ScanlineFormat::N1BitMsbPal:
332 case ScanlineFormat::N1BitLsbPal:
333 case ScanlineFormat::N4BitMsnPal:
334 case ScanlineFormat::N4BitLsnPal:
335 case ScanlineFormat::N8BitPal:
336 break;
338 case ScanlineFormat::N8BitTcMask:
339 // return ImplConvertToBitmap<ScanlineFormat::N8BitTcMask>( aSrcType, rDst, rSrc );
340 case ScanlineFormat::N32BitTcMask:
341 // return ImplConvertToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc );
342 break;
344 case ScanlineFormat::N24BitTcBgr:
345 return ImplConvertToBitmap<ScanlineFormat::N24BitTcBgr>( aSrcType, rDst, rSrc );
346 case ScanlineFormat::N24BitTcRgb:
347 return ImplConvertToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDst, rSrc );
349 case ScanlineFormat::N32BitTcAbgr:
350 return ImplConvertToBitmap<ScanlineFormat::N32BitTcAbgr>( aSrcType, rDst, rSrc );
351 case ScanlineFormat::N32BitTcArgb:
352 return ImplConvertToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDst, rSrc );
353 case ScanlineFormat::N32BitTcBgra:
354 return ImplConvertToBitmap<ScanlineFormat::N32BitTcBgra>( aSrcType, rDst, rSrc );
355 case ScanlineFormat::N32BitTcRgba:
356 return ImplConvertToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDst, rSrc );
357 default: break;
360 static int nNotAccelerated = 0;
361 SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
362 "vcl.gdi",
363 "ImplConvertFromBitmap for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) << ")" );
365 return false;
368 // A universal stretching conversion is overkill in most common situations
369 // => performance benefits for speeding up the non-stretching cases
370 bool ImplFastBitmapConversion( BitmapBuffer& rDst, const BitmapBuffer& rSrc,
371 const SalTwoRect& rTR )
373 // TODO:horizontal mirroring not implemented yet
374 if( rTR.mnDestWidth < 0 )
375 return false;
376 // vertical mirroring
377 if( rTR.mnDestHeight < 0 )
378 // TODO: rDst.mnFormat ^= ScanlineFormat::TopDown;
379 return false;
381 // offsetted conversion is not implemented yet
382 if( rTR.mnSrcX || rTR.mnSrcY )
383 return false;
384 if( rTR.mnDestX || rTR.mnDestY )
385 return false;
387 // stretched conversion is not implemented yet
388 if( rTR.mnDestWidth != rTR.mnSrcWidth )
389 return false;
390 if( rTR.mnDestHeight!= rTR.mnSrcHeight )
391 return false;
393 // check source image size
394 if( rSrc.mnWidth < rTR.mnSrcX + rTR.mnSrcWidth )
395 return false;
396 if( rSrc.mnHeight < rTR.mnSrcY + rTR.mnSrcHeight )
397 return false;
399 // check dest image size
400 if( rDst.mnWidth < rTR.mnDestX + rTR.mnDestWidth )
401 return false;
402 if( rDst.mnHeight < rTR.mnDestY + rTR.mnDestHeight )
403 return false;
405 const ScanlineFormat nSrcFormat = RemoveScanline(rSrc.mnFormat);
406 const ScanlineFormat nDstFormat = RemoveScanline(rDst.mnFormat);
408 // special handling of trivial cases
409 if( nSrcFormat == nDstFormat )
411 // accelerated palette conversions not yet implemented
412 if( rSrc.maPalette != rDst.maPalette )
413 return false;
414 return ImplCopyImage( rDst, rSrc );
417 // select the matching instantiation for the source's bitmap format
418 switch( nSrcFormat )
420 case ScanlineFormat::N1BitMsbPal:
421 case ScanlineFormat::N1BitLsbPal:
422 case ScanlineFormat::N4BitMsnPal:
423 case ScanlineFormat::N4BitLsnPal:
424 case ScanlineFormat::N8BitPal:
425 break;
427 case ScanlineFormat::N8BitTcMask:
428 // return ImplConvertFromBitmap<ScanlineFormat::N8BitTcMask>( rDst, rSrc );
429 case ScanlineFormat::N32BitTcMask:
430 // return ImplConvertFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
431 break;
433 case ScanlineFormat::N24BitTcBgr:
434 return ImplConvertFromBitmap<ScanlineFormat::N24BitTcBgr>( rDst, rSrc );
435 case ScanlineFormat::N24BitTcRgb:
436 return ImplConvertFromBitmap<ScanlineFormat::N24BitTcRgb>( rDst, rSrc );
438 case ScanlineFormat::N32BitTcAbgr:
439 return ImplConvertFromBitmap<ScanlineFormat::N32BitTcAbgr>( rDst, rSrc );
440 case ScanlineFormat::N32BitTcArgb:
441 return ImplConvertFromBitmap<ScanlineFormat::N32BitTcArgb>( rDst, rSrc );
442 case ScanlineFormat::N32BitTcBgra:
443 return ImplConvertFromBitmap<ScanlineFormat::N32BitTcBgra>( rDst, rSrc );
444 case ScanlineFormat::N32BitTcRgba:
445 return ImplConvertFromBitmap<ScanlineFormat::N32BitTcRgba>( rDst, rSrc );
446 default: break;
449 static int nNotAccelerated = 0;
450 SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
451 "vcl.gdi",
452 "ImplFastBitmapConversion for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) << ")" );
454 return false;
457 template <ScanlineFormat DSTFMT, ScanlineFormat SRCFMT> //,sal_uLong MSKFMT>
458 static bool ImplBlendToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
459 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
460 const BitmapBuffer& rMskBuffer )
462 SAL_WARN_IF( rMskBuffer.mnFormat != ScanlineFormat::N8BitPal, "vcl.gdi", "FastBmp BlendImage: unusual MSKFMT" );
464 const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
465 int nMskLinestep = rMskBuffer.mnScanlineSize;
466 int nDstLinestep = rDstBuffer.mnScanlineSize;
468 TrueColorPixelPtr<ScanlineFormat::N8BitPal> aMskLine; aMskLine.SetRawPtr( rMskBuffer.mpBits );
469 TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
471 // special case for single line masks
472 if( rMskBuffer.mnHeight == 1 )
473 nMskLinestep = 0;
475 // source and mask don't match: upside down
476 if( (rSrcBuffer.mnFormat ^ rMskBuffer.mnFormat) & ScanlineFormat::TopDown )
478 aMskLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nMskLinestep );
479 nMskLinestep = -nMskLinestep;
482 // source and destination don't match: upside down
483 if( (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) & ScanlineFormat::TopDown )
485 aDstLine.AddByteOffset( (rDstBuffer.mnHeight - 1) * nDstLinestep );
486 nDstLinestep = -nDstLinestep;
489 assert(rDstBuffer.mnHeight <= rSrcBuffer.mnHeight && "not sure about that?");
490 for (int y = rDstBuffer.mnHeight; --y >= 0;)
492 ImplBlendLines(aDstLine, rSrcLine, aMskLine, rDstBuffer.mnWidth);
493 aDstLine.AddByteOffset( nDstLinestep );
494 rSrcLine.AddByteOffset( nSrcLinestep );
495 aMskLine.AddByteOffset( nMskLinestep );
498 return true;
501 // some specializations to reduce the code size
502 template <>
503 bool ImplBlendToBitmap<ScanlineFormat::N24BitTcBgr,ScanlineFormat::N24BitTcBgr>(
504 TrueColorPixelPtr<ScanlineFormat::N24BitTcBgr>&,
505 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
506 const BitmapBuffer& rMskBuffer )
508 TrueColorPixelPtr<ScanlineFormat::N24BitTcRgb> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
509 return ImplBlendToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
512 template <>
513 bool ImplBlendToBitmap<ScanlineFormat::N32BitTcAbgr,ScanlineFormat::N32BitTcAbgr>(
514 TrueColorPixelPtr<ScanlineFormat::N32BitTcAbgr>&,
515 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
516 const BitmapBuffer& rMskBuffer )
518 TrueColorPixelPtr<ScanlineFormat::N32BitTcArgb> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
519 return ImplBlendToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
522 template <>
523 bool ImplBlendToBitmap<ScanlineFormat::N32BitTcBgra,ScanlineFormat::N32BitTcBgra>(
524 TrueColorPixelPtr<ScanlineFormat::N32BitTcBgra>&,
525 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
526 const BitmapBuffer& rMskBuffer )
528 TrueColorPixelPtr<ScanlineFormat::N32BitTcRgba> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
529 return ImplBlendToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
532 template <ScanlineFormat SRCFMT>
533 static bool ImplBlendFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc, const BitmapBuffer& rMsk )
535 TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
537 // select the matching instantiation for the destination's bitmap format
538 switch (RemoveScanline(rDst.mnFormat))
540 case ScanlineFormat::N1BitMsbPal:
541 case ScanlineFormat::N1BitLsbPal:
542 case ScanlineFormat::N4BitMsnPal:
543 case ScanlineFormat::N4BitLsnPal:
544 case ScanlineFormat::N8BitPal:
545 break;
547 case ScanlineFormat::N8BitTcMask:
548 // return ImplBlendToBitmap<ScanlineFormat::N8BitTcMask>( aSrcType, rDst, rSrc, rMsk );
549 case ScanlineFormat::N32BitTcMask:
550 // return ImplBlendToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc, rMsk );
551 break;
553 case ScanlineFormat::N24BitTcBgr:
554 return ImplBlendToBitmap<ScanlineFormat::N24BitTcBgr>( aSrcType, rDst, rSrc, rMsk );
555 case ScanlineFormat::N24BitTcRgb:
556 return ImplBlendToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDst, rSrc, rMsk );
558 case ScanlineFormat::N32BitTcAbgr:
559 return ImplBlendToBitmap<ScanlineFormat::N32BitTcAbgr>( aSrcType, rDst, rSrc, rMsk );
560 case ScanlineFormat::N32BitTcArgb:
561 return ImplBlendToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDst, rSrc, rMsk );
562 case ScanlineFormat::N32BitTcBgra:
563 return ImplBlendToBitmap<ScanlineFormat::N32BitTcBgra>( aSrcType, rDst, rSrc, rMsk );
564 case ScanlineFormat::N32BitTcRgba:
565 return ImplBlendToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDst, rSrc, rMsk );
566 default: break;
569 static int nNotAccelerated = 0;
570 SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
571 "vcl.gdi",
572 "ImplBlendFromBitmap for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "*" << static_cast<int>(rMsk.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) );
573 return false;
576 bool ImplFastBitmapBlending( BitmapWriteAccess const & rDstWA,
577 const BitmapReadAccess& rSrcRA, const BitmapReadAccess& rMskRA,
578 const SalTwoRect& rTR )
580 // accelerated blending of paletted bitmaps not implemented yet
581 if( rSrcRA.HasPalette() )
582 return false;
583 if( rDstWA.HasPalette() )
584 return false;
585 // TODO: either get rid of mask's use of 8BIT_PAL or check the palette
587 // horizontal mirroring not implemented yet
588 if( rTR.mnDestWidth < 0 )
589 return false;
590 // vertical mirroring
591 if( rTR.mnDestHeight < 0 )
592 // TODO: rDst.mnFormat ^= ScanlineFormat::TopDown;
593 return false;
595 // offsetted blending is not implemented yet
596 if( rTR.mnSrcX || rTR.mnSrcY )
597 return false;
598 if( rTR.mnDestX || rTR.mnDestY )
599 return false;
601 // stretched blending is not implemented yet
602 if( rTR.mnDestWidth != rTR.mnSrcWidth )
603 return false;
604 if( rTR.mnDestHeight!= rTR.mnSrcHeight )
605 return false;
607 // check source image size
608 if( rSrcRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
609 return false;
610 if( rSrcRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
611 return false;
613 // check mask image size
614 if( rMskRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
615 return false;
616 if( rMskRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
617 if( rMskRA.Height() != 1 )
618 return false;
620 // check dest image size
621 if( rDstWA.Width() < rTR.mnDestX + rTR.mnDestWidth )
622 return false;
623 if( rDstWA.Height() < rTR.mnDestY + rTR.mnDestHeight )
624 return false;
626 BitmapBuffer& rDst = *rDstWA.ImplGetBitmapBuffer();
627 const BitmapBuffer& rSrc = *rSrcRA.ImplGetBitmapBuffer();
628 const BitmapBuffer& rMsk = *rMskRA.ImplGetBitmapBuffer();
630 const ScanlineFormat nSrcFormat = RemoveScanline(rSrc.mnFormat);
632 // select the matching instantiation for the source's bitmap format
633 switch( nSrcFormat )
635 case ScanlineFormat::N1BitMsbPal:
636 case ScanlineFormat::N1BitLsbPal:
637 case ScanlineFormat::N4BitMsnPal:
638 case ScanlineFormat::N4BitLsnPal:
639 case ScanlineFormat::N8BitPal:
640 break;
642 case ScanlineFormat::N8BitTcMask:
643 // return ImplBlendFromBitmap<ScanlineFormat::N8BitTcMask>( rDst, rSrc );
644 case ScanlineFormat::N32BitTcMask:
645 // return ImplBlendFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
646 break;
648 case ScanlineFormat::N24BitTcBgr:
649 return ImplBlendFromBitmap<ScanlineFormat::N24BitTcBgr>( rDst, rSrc, rMsk );
650 case ScanlineFormat::N24BitTcRgb:
651 return ImplBlendFromBitmap<ScanlineFormat::N24BitTcRgb>( rDst, rSrc, rMsk );
653 case ScanlineFormat::N32BitTcAbgr:
654 return ImplBlendFromBitmap<ScanlineFormat::N32BitTcAbgr>( rDst, rSrc, rMsk );
655 case ScanlineFormat::N32BitTcArgb:
656 return ImplBlendFromBitmap<ScanlineFormat::N32BitTcArgb>( rDst, rSrc, rMsk );
657 case ScanlineFormat::N32BitTcBgra:
658 return ImplBlendFromBitmap<ScanlineFormat::N32BitTcBgra>( rDst, rSrc, rMsk );
659 case ScanlineFormat::N32BitTcRgba:
660 return ImplBlendFromBitmap<ScanlineFormat::N32BitTcRgba>( rDst, rSrc, rMsk );
661 default: break;
664 static int nNotAccelerated = 0;
665 SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
666 "vcl.gdi",
667 "ImplFastBlend for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "*" << static_cast<int>(rMsk.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) << ")" );
669 return false;
672 bool ImplFastEraseBitmap( BitmapBuffer& rDst, const BitmapColor& rColor )
674 const ScanlineFormat nDstFormat = RemoveScanline(rDst.mnFormat);
676 // erasing a bitmap is often just a byte-wise memory fill
677 bool bByteFill = true;
678 sal_uInt8 nFillByte;
680 switch( nDstFormat )
682 case ScanlineFormat::N1BitMsbPal:
683 case ScanlineFormat::N1BitLsbPal:
684 nFillByte = rColor.GetIndex();
685 nFillByte = static_cast<sal_uInt8>( -(nFillByte & 1) ); // 0x00 or 0xFF
686 break;
687 case ScanlineFormat::N4BitMsnPal:
688 case ScanlineFormat::N4BitLsnPal:
689 nFillByte = rColor.GetIndex();
690 nFillByte &= 0x0F;
691 nFillByte |= (nFillByte << 4);
692 break;
693 case ScanlineFormat::N8BitPal:
694 case ScanlineFormat::N8BitTcMask:
695 nFillByte = rColor.GetIndex();
696 break;
698 case ScanlineFormat::N24BitTcBgr:
699 case ScanlineFormat::N24BitTcRgb:
700 nFillByte = rColor.GetRed();
701 if( (nFillByte != rColor.GetGreen())
702 || (nFillByte != rColor.GetBlue()) )
703 bByteFill = false;
704 break;
706 default:
707 bByteFill = false;
708 nFillByte = 0x00;
709 break;
712 if( bByteFill )
714 long nByteCount = rDst.mnHeight * rDst.mnScanlineSize;
715 memset( rDst.mpBits, nFillByte, nByteCount );
716 return true;
719 // TODO: handle other bitmap formats
720 switch( nDstFormat )
722 case ScanlineFormat::N32BitTcMask:
724 case ScanlineFormat::N24BitTcBgr:
725 case ScanlineFormat::N24BitTcRgb:
727 case ScanlineFormat::N32BitTcAbgr:
728 case ScanlineFormat::N32BitTcArgb:
729 case ScanlineFormat::N32BitTcBgra:
730 case ScanlineFormat::N32BitTcRgba:
731 break;
733 default:
734 break;
737 return false;
740 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */