tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / vcl / source / bitmap / bmpfast.cxx
blob15afb55c7ca33f58322962006b30bd703a84c6bc
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 <vcl/salgtype.hxx>
22 #include <vcl/BitmapWriteAccess.hxx>
23 #include <bitmap/bmpfast.hxx>
25 #include <sal/log.hxx>
27 typedef unsigned char PIXBYTE;
29 namespace {
31 class BasePixelPtr
33 public:
34 explicit BasePixelPtr( PIXBYTE* p = nullptr ) : mpPixel( p ) {}
35 void SetRawPtr( PIXBYTE* pRawPtr ) { mpPixel = pRawPtr; }
36 void AddByteOffset( int nByteOffset ) { mpPixel += nByteOffset; }
38 protected:
39 PIXBYTE* mpPixel;
42 template <ScanlineFormat PIXFMT>
43 class TrueColorPixelPtr : public BasePixelPtr
45 public:
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
56 template <>
57 class TrueColorPixelPtr<ScanlineFormat::N24BitTcRgb> : public BasePixelPtr
59 public:
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
70 mpPixel[0] = r;
71 mpPixel[1] = g;
72 mpPixel[2] = b;
76 template <>
77 class TrueColorPixelPtr<ScanlineFormat::N24BitTcBgr> : public BasePixelPtr
79 public:
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
90 mpPixel[0] = b;
91 mpPixel[1] = g;
92 mpPixel[2] = r;
96 template <>
97 class TrueColorPixelPtr<ScanlineFormat::N32BitTcArgb> : public BasePixelPtr
99 public:
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
110 mpPixel[1] = r;
111 mpPixel[2] = g;
112 mpPixel[3] = b;
116 template <>
117 class TrueColorPixelPtr<ScanlineFormat::N32BitTcAbgr> : public BasePixelPtr
119 public:
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
130 mpPixel[1] = b;
131 mpPixel[2] = g;
132 mpPixel[3] = r;
136 template <>
137 class TrueColorPixelPtr<ScanlineFormat::N32BitTcRgba> : public BasePixelPtr
139 public:
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
150 mpPixel[0] = r;
151 mpPixel[1] = g;
152 mpPixel[2] = b;
156 template <>
157 class TrueColorPixelPtr<ScanlineFormat::N32BitTcBgra> : public BasePixelPtr
159 public:
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
170 mpPixel[0] = b;
171 mpPixel[1] = g;
172 mpPixel[2] = r;
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.
180 template <>
181 class TrueColorPixelPtr<ScanlineFormat::N8BitPal> : public BasePixelPtr
183 public:
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 );
212 ++aSrc;
213 ++aDst;
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;
223 if( !nAlphaVal )
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();
236 nS = rSrc.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,
248 int nPixelCount )
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());
257 ++aDst;
258 ++aSrc;
259 ++aMsk;
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 (rSrcBuffer.meDirection != rDstBuffer.meDirection)
274 pRawDst += (rSrcBuffer.mnHeight - 1) * nDstLinestep;
275 nDstLinestep = -rDstBuffer.mnScanlineSize;
277 else if( nSrcLinestep == nDstLinestep )
279 memcpy( pRawDst, pRawSrc, rSrcBuffer.mnHeight * nDstLinestep );
280 return true;
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;
294 return true;
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 )
304 return false;
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 (rSrcBuffer.meDirection != rDstBuffer.meDirection)
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 );
325 return true;
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 (rDst.meFormat)
336 case ScanlineFormat::N1BitMsbPal:
337 case ScanlineFormat::N8BitPal:
338 break;
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 << int(rSrc.meFormat) << "->" << int(rDst.meFormat) << ")" );
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.meDirection != ScanlineDirection::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 = rSrc.meFormat;
406 const ScanlineFormat nDstFormat = rDst.meFormat;
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 break;
423 case ScanlineFormat::N32BitTcMask:
424 // return ImplConvertFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
425 break;
427 case ScanlineFormat::N8BitPal:
428 if(rSrc.maPalette.IsGreyPalette8Bit())
429 return ImplConvertFromBitmap<ScanlineFormat::N8BitPal>( rDst, rSrc );
430 break;
432 case ScanlineFormat::N24BitTcBgr:
433 return ImplConvertFromBitmap<ScanlineFormat::N24BitTcBgr>( rDst, rSrc );
434 case ScanlineFormat::N24BitTcRgb:
435 return ImplConvertFromBitmap<ScanlineFormat::N24BitTcRgb>( rDst, rSrc );
437 case ScanlineFormat::N32BitTcAbgr:
438 return ImplConvertFromBitmap<ScanlineFormat::N32BitTcAbgr>( rDst, rSrc );
439 case ScanlineFormat::N32BitTcArgb:
440 return ImplConvertFromBitmap<ScanlineFormat::N32BitTcArgb>( rDst, rSrc );
441 case ScanlineFormat::N32BitTcBgra:
442 return ImplConvertFromBitmap<ScanlineFormat::N32BitTcBgra>( rDst, rSrc );
443 case ScanlineFormat::N32BitTcRgba:
444 return ImplConvertFromBitmap<ScanlineFormat::N32BitTcRgba>( rDst, rSrc );
445 default: break;
448 static int nNotAccelerated = 0;
449 SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
450 "vcl.gdi",
451 "ImplFastBitmapConversion for not accelerated case (" << std::hex << int(rSrc.meFormat) << "->" << int(rDst.meFormat) << ")" );
453 return false;
456 static inline ConstScanline ImplGetScanline( const BitmapBuffer& rBuf, tools::Long nY )
458 if (rBuf.meDirection == ScanlineDirection::TopDown)
459 return rBuf.mpBits + nY * rBuf.mnScanlineSize;
460 else
461 return rBuf.mpBits + (rBuf.mnHeight - 1 - nY) * rBuf.mnScanlineSize;
464 static inline Scanline ImplGetScanline( BitmapBuffer& rBuf, tools::Long nY )
466 return const_cast<Scanline>(ImplGetScanline( const_cast<const BitmapBuffer&>(rBuf), nY ));
469 template <ScanlineFormat DSTFMT, ScanlineFormat SRCFMT>
470 static bool ImplCopyToScanline( tools::Long nY, BitmapBuffer& rDst, TrueColorPixelPtr<SRCFMT>& rSrcLine, tools::Long nSrcWidth )
472 TrueColorPixelPtr<DSTFMT> aDstType;
473 aDstType.SetRawPtr( ImplGetScanline( rDst, nY ));
474 ImplConvertLine( aDstType, rSrcLine, std::min( nSrcWidth, rDst.mnWidth ));
475 return true;
478 template <ScanlineFormat SRCFMT>
479 static bool ImplCopyFromScanline( tools::Long nY, BitmapBuffer& rDst, ConstScanline aSrcScanline, tools::Long nSrcWidth )
481 TrueColorPixelPtr<SRCFMT> aSrcType;
482 aSrcType.SetRawPtr( const_cast<Scanline>( aSrcScanline ));
483 // select the matching instantiation for the destination's bitmap format
484 switch (rDst.meFormat)
486 case ScanlineFormat::N24BitTcBgr:
487 return ImplCopyToScanline<ScanlineFormat::N24BitTcBgr>( nY, rDst, aSrcType, nSrcWidth );
488 case ScanlineFormat::N24BitTcRgb:
489 return ImplCopyToScanline<ScanlineFormat::N24BitTcRgb>( nY, rDst, aSrcType, nSrcWidth );
491 case ScanlineFormat::N32BitTcAbgr:
492 return ImplCopyToScanline<ScanlineFormat::N32BitTcAbgr>( nY, rDst, aSrcType, nSrcWidth );
493 case ScanlineFormat::N32BitTcArgb:
494 return ImplCopyToScanline<ScanlineFormat::N32BitTcArgb>( nY, rDst, aSrcType, nSrcWidth );
495 case ScanlineFormat::N32BitTcBgra:
496 return ImplCopyToScanline<ScanlineFormat::N32BitTcBgra>( nY, rDst, aSrcType, nSrcWidth );
497 case ScanlineFormat::N32BitTcRgba:
498 return ImplCopyToScanline<ScanlineFormat::N32BitTcRgba>( nY, rDst, aSrcType, nSrcWidth );
499 default:
500 break;
502 return false;
506 bool ImplFastCopyScanline( tools::Long nY, BitmapBuffer& rDst, ConstScanline aSrcScanline,
507 ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize)
509 if( rDst.mnHeight <= nY )
510 return false;
512 const ScanlineFormat nSrcFormat = nSrcScanlineFormat;
513 const ScanlineFormat nDstFormat = rDst.meFormat;
515 // special handling of trivial cases
516 if( nSrcFormat == nDstFormat )
518 memcpy( ImplGetScanline( rDst, nY ), aSrcScanline, std::min<tools::Long>(nSrcScanlineSize, rDst.mnScanlineSize));
519 return true;
522 // select the matching instantiation for the source's bitmap format
523 switch( nSrcFormat )
525 case ScanlineFormat::N24BitTcBgr:
526 return ImplCopyFromScanline<ScanlineFormat::N24BitTcBgr>( nY, rDst, aSrcScanline, nSrcScanlineSize / 3 );
527 case ScanlineFormat::N24BitTcRgb:
528 return ImplCopyFromScanline<ScanlineFormat::N24BitTcRgb>( nY, rDst, aSrcScanline, nSrcScanlineSize / 3 );
530 case ScanlineFormat::N32BitTcAbgr:
531 return ImplCopyFromScanline<ScanlineFormat::N32BitTcAbgr>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
532 case ScanlineFormat::N32BitTcArgb:
533 return ImplCopyFromScanline<ScanlineFormat::N32BitTcArgb>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
534 case ScanlineFormat::N32BitTcBgra:
535 return ImplCopyFromScanline<ScanlineFormat::N32BitTcBgra>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
536 case ScanlineFormat::N32BitTcRgba:
537 return ImplCopyFromScanline<ScanlineFormat::N32BitTcRgba>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
538 default:
539 break;
541 return false;
544 bool ImplFastCopyScanline( tools::Long nY, BitmapBuffer& rDst, const BitmapBuffer& rSrc)
546 if( nY >= rDst.mnHeight )
547 return false;
548 if( rSrc.maPalette != rDst.maPalette )
549 return false;
550 return ImplFastCopyScanline( nY, rDst, ImplGetScanline( rSrc, nY ), rSrc.meFormat, rSrc.mnScanlineSize);
553 template <ScanlineFormat DSTFMT, ScanlineFormat SRCFMT> //,sal_uLong MSKFMT>
554 static bool ImplBlendToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
555 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
556 const BitmapBuffer& rMskBuffer )
558 SAL_WARN_IF(rMskBuffer.meFormat != ScanlineFormat::N8BitPal, "vcl.gdi", "FastBmp BlendImage: unusual MSKFMT");
560 const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
561 int nMskLinestep = rMskBuffer.mnScanlineSize;
562 int nDstLinestep = rDstBuffer.mnScanlineSize;
564 TrueColorPixelPtr<ScanlineFormat::N8BitPal> aMskLine; aMskLine.SetRawPtr( rMskBuffer.mpBits );
565 TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
567 // special case for single line masks
568 if( rMskBuffer.mnHeight == 1 )
569 nMskLinestep = 0;
571 // source and mask don't match: upside down
572 if (rSrcBuffer.meDirection != rMskBuffer.meDirection)
574 aMskLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nMskLinestep );
575 nMskLinestep = -nMskLinestep;
578 // source and destination don't match: upside down
579 if (rSrcBuffer.meDirection != rDstBuffer.meDirection)
581 aDstLine.AddByteOffset( (rDstBuffer.mnHeight - 1) * nDstLinestep );
582 nDstLinestep = -nDstLinestep;
585 assert(rDstBuffer.mnHeight <= rSrcBuffer.mnHeight && "not sure about that?");
586 for (int y = rDstBuffer.mnHeight; --y >= 0;)
588 ImplBlendLines(aDstLine, rSrcLine, aMskLine, rDstBuffer.mnWidth);
589 aDstLine.AddByteOffset( nDstLinestep );
590 rSrcLine.AddByteOffset( nSrcLinestep );
591 aMskLine.AddByteOffset( nMskLinestep );
594 return true;
597 // some specializations to reduce the code size
598 template <>
599 bool ImplBlendToBitmap<ScanlineFormat::N24BitTcBgr,ScanlineFormat::N24BitTcBgr>(
600 TrueColorPixelPtr<ScanlineFormat::N24BitTcBgr>&,
601 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
602 const BitmapBuffer& rMskBuffer )
604 TrueColorPixelPtr<ScanlineFormat::N24BitTcRgb> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
605 return ImplBlendToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
608 template <>
609 bool ImplBlendToBitmap<ScanlineFormat::N32BitTcAbgr,ScanlineFormat::N32BitTcAbgr>(
610 TrueColorPixelPtr<ScanlineFormat::N32BitTcAbgr>&,
611 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
612 const BitmapBuffer& rMskBuffer )
614 TrueColorPixelPtr<ScanlineFormat::N32BitTcArgb> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
615 return ImplBlendToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
618 template <>
619 bool ImplBlendToBitmap<ScanlineFormat::N32BitTcBgra,ScanlineFormat::N32BitTcBgra>(
620 TrueColorPixelPtr<ScanlineFormat::N32BitTcBgra>&,
621 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
622 const BitmapBuffer& rMskBuffer )
624 TrueColorPixelPtr<ScanlineFormat::N32BitTcRgba> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
625 return ImplBlendToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
628 template <ScanlineFormat SRCFMT>
629 static bool ImplBlendFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc, const BitmapBuffer& rMsk )
631 TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
633 // select the matching instantiation for the destination's bitmap format
634 switch (rDst.meFormat)
636 case ScanlineFormat::N1BitMsbPal:
637 case ScanlineFormat::N8BitPal:
638 break;
640 case ScanlineFormat::N32BitTcMask:
641 // return ImplBlendToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc, rMsk );
642 break;
644 case ScanlineFormat::N24BitTcBgr:
645 return ImplBlendToBitmap<ScanlineFormat::N24BitTcBgr>( aSrcType, rDst, rSrc, rMsk );
646 case ScanlineFormat::N24BitTcRgb:
647 return ImplBlendToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDst, rSrc, rMsk );
649 case ScanlineFormat::N32BitTcAbgr:
650 return ImplBlendToBitmap<ScanlineFormat::N32BitTcAbgr>( aSrcType, rDst, rSrc, rMsk );
651 case ScanlineFormat::N32BitTcArgb:
652 return ImplBlendToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDst, rSrc, rMsk );
653 case ScanlineFormat::N32BitTcBgra:
654 return ImplBlendToBitmap<ScanlineFormat::N32BitTcBgra>( aSrcType, rDst, rSrc, rMsk );
655 case ScanlineFormat::N32BitTcRgba:
656 return ImplBlendToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDst, rSrc, rMsk );
657 default: break;
660 static int nNotAccelerated = 0;
661 SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
662 "vcl.gdi",
663 "ImplBlendFromBitmap for not accelerated case (" << std::hex << int(rSrc.meFormat) << "*" << int(rMsk.meFormat) << "->" << int(rDst.meFormat) );
664 return false;
667 bool ImplFastBitmapBlending( BitmapWriteAccess const & rDstWA,
668 const BitmapReadAccess& rSrcRA, const BitmapReadAccess& rMskRA,
669 const SalTwoRect& rTR )
671 // accelerated blending of paletted bitmaps not implemented yet
672 if( rSrcRA.HasPalette() )
673 return false;
674 if( rDstWA.HasPalette() )
675 return false;
676 // TODO: either get rid of mask's use of 8BIT_PAL or check the palette
678 // horizontal mirroring not implemented yet
679 if( rTR.mnDestWidth < 0 )
680 return false;
681 // vertical mirroring
682 if( rTR.mnDestHeight < 0 )
683 // TODO: rDst.meDirection != ScanlineDirection::TopDown;
684 return false;
686 // offsetted blending is not implemented yet
687 if( rTR.mnSrcX || rTR.mnSrcY )
688 return false;
689 if( rTR.mnDestX || rTR.mnDestY )
690 return false;
692 // stretched blending is not implemented yet
693 if( rTR.mnDestWidth != rTR.mnSrcWidth )
694 return false;
695 if( rTR.mnDestHeight!= rTR.mnSrcHeight )
696 return false;
698 // check source image size
699 if( rSrcRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
700 return false;
701 if( rSrcRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
702 return false;
704 // check mask image size
705 if( rMskRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
706 return false;
707 if( rMskRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
708 if( rMskRA.Height() != 1 )
709 return false;
711 // check dest image size
712 if( rDstWA.Width() < rTR.mnDestX + rTR.mnDestWidth )
713 return false;
714 if( rDstWA.Height() < rTR.mnDestY + rTR.mnDestHeight )
715 return false;
717 BitmapBuffer& rDst = *rDstWA.ImplGetBitmapBuffer();
718 const BitmapBuffer& rSrc = *rSrcRA.ImplGetBitmapBuffer();
719 const BitmapBuffer& rMsk = *rMskRA.ImplGetBitmapBuffer();
721 // select the matching instantiation for the source's bitmap format
722 switch (rSrc.meFormat)
724 case ScanlineFormat::N1BitMsbPal:
725 break;
727 case ScanlineFormat::N32BitTcMask:
728 // return ImplBlendFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
729 break;
731 case ScanlineFormat::N8BitPal:
732 if(rSrc.maPalette.IsGreyPalette8Bit())
733 return ImplBlendFromBitmap<ScanlineFormat::N8BitPal>( rDst, rSrc, rMsk );
734 break;
736 case ScanlineFormat::N24BitTcBgr:
737 return ImplBlendFromBitmap<ScanlineFormat::N24BitTcBgr>( rDst, rSrc, rMsk );
738 case ScanlineFormat::N24BitTcRgb:
739 return ImplBlendFromBitmap<ScanlineFormat::N24BitTcRgb>( rDst, rSrc, rMsk );
741 case ScanlineFormat::N32BitTcAbgr:
742 return ImplBlendFromBitmap<ScanlineFormat::N32BitTcAbgr>( rDst, rSrc, rMsk );
743 case ScanlineFormat::N32BitTcArgb:
744 return ImplBlendFromBitmap<ScanlineFormat::N32BitTcArgb>( rDst, rSrc, rMsk );
745 case ScanlineFormat::N32BitTcBgra:
746 return ImplBlendFromBitmap<ScanlineFormat::N32BitTcBgra>( rDst, rSrc, rMsk );
747 case ScanlineFormat::N32BitTcRgba:
748 return ImplBlendFromBitmap<ScanlineFormat::N32BitTcRgba>( rDst, rSrc, rMsk );
749 default: break;
752 static int nNotAccelerated = 0;
753 SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
754 "vcl.gdi",
755 "ImplFastBlend for not accelerated case (" << std::hex << int(rSrc.meFormat) << "*" << int(rMsk.meFormat) << "->" << int(rDst.meFormat) << ")" );
757 return false;
760 bool ImplFastEraseBitmap( BitmapBuffer& rDst, const BitmapColor& rColor )
762 // erasing a bitmap is often just a byte-wise memory fill
763 bool bByteFill = true;
764 sal_uInt8 nFillByte;
766 switch (rDst.meFormat)
768 case ScanlineFormat::N1BitMsbPal:
769 nFillByte = rColor.GetIndex();
770 nFillByte = static_cast<sal_uInt8>( -(nFillByte & 1) ); // 0x00 or 0xFF
771 break;
772 case ScanlineFormat::N8BitPal:
773 nFillByte = rColor.GetIndex();
774 break;
776 case ScanlineFormat::N24BitTcBgr:
777 case ScanlineFormat::N24BitTcRgb:
778 nFillByte = rColor.GetRed();
779 if( (nFillByte != rColor.GetGreen())
780 || (nFillByte != rColor.GetBlue()) )
781 bByteFill = false;
782 break;
784 default:
785 bByteFill = false;
786 nFillByte = 0x00;
787 break;
790 if( bByteFill )
792 tools::Long nByteCount = rDst.mnHeight * rDst.mnScanlineSize;
793 memset( rDst.mpBits, nFillByte, nByteCount );
794 return true;
797 // TODO: handle other bitmap formats
798 switch (rDst.meFormat)
800 case ScanlineFormat::N32BitTcMask:
802 case ScanlineFormat::N24BitTcBgr:
803 case ScanlineFormat::N24BitTcRgb:
805 case ScanlineFormat::N32BitTcAbgr:
806 case ScanlineFormat::N32BitTcArgb:
807 case ScanlineFormat::N32BitTcBgra:
808 case ScanlineFormat::N32BitTcRgba:
809 break;
811 default:
812 break;
815 return false;
818 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */