LibreOffice Module vcl (master)  1
bmpfast.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <bmpfast.hxx>
21 #include <vcl/bitmapaccess.hxx>
22 #include <vcl/salgtype.hxx>
23 #include <bitmapwriteaccess.hxx>
24 
25 #include <sal/log.hxx>
26 
27 typedef unsigned char PIXBYTE;
28 
29 namespace {
30 
31 class BasePixelPtr
32 {
33 public:
34  explicit BasePixelPtr( PIXBYTE* p = nullptr ) : mpPixel( p ) {}
35  void SetRawPtr( PIXBYTE* pRawPtr ) { mpPixel = pRawPtr; }
36  void AddByteOffset( int nByteOffset ) { mpPixel += nByteOffset; }
37 
38 protected:
39  PIXBYTE* mpPixel;
40 };
41 
42 template <ScanlineFormat PIXFMT>
43 class TrueColorPixelPtr : public BasePixelPtr
44 {
45 public:
46  PIXBYTE GetRed() const;
47  PIXBYTE GetGreen() const;
48  PIXBYTE GetBlue() const;
49  PIXBYTE GetAlpha() const;
50 
51  void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const;
52  void SetAlpha( PIXBYTE a ) const;
53 };
54 
55 // template specializations for truecolor pixel formats
56 template <>
57 class TrueColorPixelPtr<ScanlineFormat::N24BitTcRgb> : public BasePixelPtr
58 {
59 public:
60  void operator++() { mpPixel += 3; }
61 
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 ) {}
67 
68  void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
69  {
70  mpPixel[0] = r;
71  mpPixel[1] = g;
72  mpPixel[2] = b;
73  }
74 };
75 
76 template <>
77 class TrueColorPixelPtr<ScanlineFormat::N24BitTcBgr> : public BasePixelPtr
78 {
79 public:
80  void operator++() { mpPixel += 3; }
81 
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 ) {}
87 
88  void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
89  {
90  mpPixel[0] = b;
91  mpPixel[1] = g;
92  mpPixel[2] = r;
93  }
94 };
95 
96 template <>
97 class TrueColorPixelPtr<ScanlineFormat::N32BitTcArgb> : public BasePixelPtr
98 {
99 public:
100  void operator++() { mpPixel += 4; }
101 
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; }
107 
108  void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
109  {
110  mpPixel[1] = r;
111  mpPixel[2] = g;
112  mpPixel[3] = b;
113  }
114 };
115 
116 template <>
117 class TrueColorPixelPtr<ScanlineFormat::N32BitTcAbgr> : public BasePixelPtr
118 {
119 public:
120  void operator++() { mpPixel += 4; }
121 
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; }
127 
128  void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
129  {
130  mpPixel[1] = b;
131  mpPixel[2] = g;
132  mpPixel[3] = r;
133  }
134 };
135 
136 template <>
137 class TrueColorPixelPtr<ScanlineFormat::N32BitTcRgba> : public BasePixelPtr
138 {
139 public:
140  void operator++() { mpPixel += 4; }
141 
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; }
147 
148  void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
149  {
150  mpPixel[0] = r;
151  mpPixel[1] = g;
152  mpPixel[2] = b;
153  }
154 };
155 
156 template <>
157 class TrueColorPixelPtr<ScanlineFormat::N32BitTcBgra> : public BasePixelPtr
158 {
159 public:
160  void operator++() { mpPixel += 4; }
161 
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; }
167 
168  void SetColor( PIXBYTE r, PIXBYTE g, PIXBYTE b ) const
169  {
170  mpPixel[0] = b;
171  mpPixel[1] = g;
172  mpPixel[2] = r;
173  }
174 };
175 
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
182 {
183 public:
184  void operator++() { mpPixel += 1; }
185 
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; }
190 };
191 
192 }
193 
194 // converting truecolor formats
195 template <ScanlineFormat SRCFMT, ScanlineFormat DSTFMT>
196 static void ImplConvertPixel( const TrueColorPixelPtr<DSTFMT>& rDst,
197  const TrueColorPixelPtr<SRCFMT>& rSrc )
198 {
199  rDst.SetColor( rSrc.GetRed(), rSrc.GetGreen(), rSrc.GetBlue() );
200  rDst.SetAlpha( rSrc.GetAlpha() );
201 }
202 
203 template <ScanlineFormat SRCFMT, ScanlineFormat DSTFMT>
204 static void ImplConvertLine( const TrueColorPixelPtr<DSTFMT>& rDst,
205  const TrueColorPixelPtr<SRCFMT>& rSrc, int nPixelCount )
206 {
207  TrueColorPixelPtr<DSTFMT> aDst( rDst );
208  TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
209  while( --nPixelCount >= 0 )
210  {
211  ImplConvertPixel( aDst, aSrc );
212  ++aSrc;
213  ++aDst;
214  }
215 }
216 
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 )
221 {
222  static const unsigned nAlphaShift = 8;
223  if( !nAlphaVal )
224  ImplConvertPixel( rDst, rSrc );
225  else if( nAlphaVal != ~(~0U << nAlphaShift) )
226  {
227  int nR = rDst.GetRed();
228  int nS = rSrc.GetRed();
229  nR = nS + (((nR - nS) * nAlphaVal) >> nAlphaShift);
230 
231  int nG = rDst.GetGreen();
232  nS = rSrc.GetGreen();
233  nG = nS + (((nG - nS) * nAlphaVal) >> nAlphaShift);
234 
235  int nB = rDst.GetBlue();
236  nS = rSrc.GetBlue();
237  nB = nS + (((nB - nS) * nAlphaVal) >> nAlphaShift);
238 
239  rDst.SetColor( sal::static_int_cast<PIXBYTE>(nR),
240  sal::static_int_cast<PIXBYTE>(nG),
241  sal::static_int_cast<PIXBYTE>(nB) );
242  }
243 }
244 
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 )
249 {
250  TrueColorPixelPtr<MASKFMT> aMsk( rMsk );
251  TrueColorPixelPtr<DSTFMT> aDst( rDst );
252  TrueColorPixelPtr<SRCFMT> aSrc( rSrc );
253  while( --nPixelCount >= 0 )
254  {
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;
260  }
261 }
262 
263 static bool ImplCopyImage( BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer )
264 {
265  const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
266  int nDstLinestep = rDstBuffer.mnScanlineSize;
267 
268  const PIXBYTE* pRawSrc = rSrcBuffer.mpBits;
269  PIXBYTE* pRawDst = rDstBuffer.mpBits;
270 
271  // source and destination don't match upside down
272  if( ScanlineFormat::TopDown & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) )
273  {
274  pRawDst += (rSrcBuffer.mnHeight - 1) * nDstLinestep;
275  nDstLinestep = -rDstBuffer.mnScanlineSize;
276  }
277  else if( nSrcLinestep == nDstLinestep )
278  {
279  memcpy( pRawDst, pRawSrc, rSrcBuffer.mnHeight * nDstLinestep );
280  return true;
281  }
282 
283  int nByteWidth = nSrcLinestep;
284  if( nByteWidth > rDstBuffer.mnScanlineSize )
285  nByteWidth = rDstBuffer.mnScanlineSize;
286 
287  for( int y = rSrcBuffer.mnHeight; --y >= 0; )
288  {
289  memcpy( pRawDst, pRawSrc, nByteWidth );
290  pRawSrc += nSrcLinestep;
291  pRawDst += nDstLinestep;
292  }
293 
294  return true;
295 }
296 
297 template <ScanlineFormat DSTFMT,ScanlineFormat SRCFMT>
298 static bool ImplConvertToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
299  BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer )
300 {
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;
305 
306  const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
307  int nDstLinestep = rDstBuffer.mnScanlineSize;
308 
309  TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
310 
311  // source and destination don't match upside down
312  if( ScanlineFormat::TopDown & (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) )
313  {
314  aDstLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nDstLinestep );
315  nDstLinestep = -nDstLinestep;
316  }
317 
318  for( int y = rSrcBuffer.mnHeight; --y >= 0; )
319  {
320  ImplConvertLine( aDstLine, rSrcLine, rSrcBuffer.mnWidth );
321  rSrcLine.AddByteOffset( nSrcLinestep );
322  aDstLine.AddByteOffset( nDstLinestep );
323  }
324 
325  return true;
326 }
327 
328 template <ScanlineFormat SRCFMT>
329 static bool ImplConvertFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc )
330 {
331  TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
332 
333  // select the matching instantiation for the destination's bitmap format
334  switch (RemoveScanline(rDst.mnFormat))
335  {
341  break;
342 
344 // return ImplConvertToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc );
345  break;
346 
348  return ImplConvertToBitmap<ScanlineFormat::N24BitTcBgr>( aSrcType, rDst, rSrc );
350  return ImplConvertToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDst, rSrc );
351 
353  return ImplConvertToBitmap<ScanlineFormat::N32BitTcAbgr>( aSrcType, rDst, rSrc );
355  return ImplConvertToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDst, rSrc );
357  return ImplConvertToBitmap<ScanlineFormat::N32BitTcBgra>( aSrcType, rDst, rSrc );
359  return ImplConvertToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDst, rSrc );
360  default: break;
361  }
362 
363  static int nNotAccelerated = 0;
364  SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
365  "vcl.gdi",
366  "ImplConvertFromBitmap for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) << ")" );
367 
368  return false;
369 }
370 
371 // A universal stretching conversion is overkill in most common situations
372 // => performance benefits for speeding up the non-stretching cases
374  const SalTwoRect& rTR )
375 {
376  // TODO:horizontal mirroring not implemented yet
377  if( rTR.mnDestWidth < 0 )
378  return false;
379  // vertical mirroring
380  if( rTR.mnDestHeight < 0 )
381  // TODO: rDst.mnFormat ^= ScanlineFormat::TopDown;
382  return false;
383 
384  // offsetted conversion is not implemented yet
385  if( rTR.mnSrcX || rTR.mnSrcY )
386  return false;
387  if( rTR.mnDestX || rTR.mnDestY )
388  return false;
389 
390  // stretched conversion is not implemented yet
391  if( rTR.mnDestWidth != rTR.mnSrcWidth )
392  return false;
393  if( rTR.mnDestHeight!= rTR.mnSrcHeight )
394  return false;
395 
396  // check source image size
397  if( rSrc.mnWidth < rTR.mnSrcX + rTR.mnSrcWidth )
398  return false;
399  if( rSrc.mnHeight < rTR.mnSrcY + rTR.mnSrcHeight )
400  return false;
401 
402  // check dest image size
403  if( rDst.mnWidth < rTR.mnDestX + rTR.mnDestWidth )
404  return false;
405  if( rDst.mnHeight < rTR.mnDestY + rTR.mnDestHeight )
406  return false;
407 
408  const ScanlineFormat nSrcFormat = RemoveScanline(rSrc.mnFormat);
409  const ScanlineFormat nDstFormat = RemoveScanline(rDst.mnFormat);
410 
411  // special handling of trivial cases
412  if( nSrcFormat == nDstFormat )
413  {
414  // accelerated palette conversions not yet implemented
415  if( rSrc.maPalette != rDst.maPalette )
416  return false;
417  return ImplCopyImage( rDst, rSrc );
418  }
419 
420  // select the matching instantiation for the source's bitmap format
421  switch( nSrcFormat )
422  {
427  break;
428 
430 // return ImplConvertFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
431  break;
432 
434  if(rSrc.maPalette.IsGreyPalette8Bit())
435  return ImplConvertFromBitmap<ScanlineFormat::N8BitPal>( rDst, rSrc );
436  break;
437 
439  return ImplConvertFromBitmap<ScanlineFormat::N24BitTcBgr>( rDst, rSrc );
441  return ImplConvertFromBitmap<ScanlineFormat::N24BitTcRgb>( rDst, rSrc );
442 
444  return ImplConvertFromBitmap<ScanlineFormat::N32BitTcAbgr>( rDst, rSrc );
446  return ImplConvertFromBitmap<ScanlineFormat::N32BitTcArgb>( rDst, rSrc );
448  return ImplConvertFromBitmap<ScanlineFormat::N32BitTcBgra>( rDst, rSrc );
450  return ImplConvertFromBitmap<ScanlineFormat::N32BitTcRgba>( rDst, rSrc );
451  default: break;
452  }
453 
454  static int nNotAccelerated = 0;
455  SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
456  "vcl.gdi",
457  "ImplFastBitmapConversion for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) << ")" );
458 
459  return false;
460 }
461 
462 static inline ConstScanline ImplGetScanline( const BitmapBuffer& rBuf, tools::Long nY )
463 {
464  if( rBuf.mnFormat & ScanlineFormat::TopDown )
465  return rBuf.mpBits + nY * rBuf.mnScanlineSize;
466  else
467  return rBuf.mpBits + (rBuf.mnHeight - 1 - nY) * rBuf.mnScanlineSize;
468 }
469 
471 {
472  return const_cast<Scanline>(ImplGetScanline( const_cast<const BitmapBuffer&>(rBuf), nY ));
473 }
474 
475 template <ScanlineFormat DSTFMT, ScanlineFormat SRCFMT>
476 static bool ImplCopyToScanline( tools::Long nY, BitmapBuffer& rDst, TrueColorPixelPtr<SRCFMT>& rSrcLine, tools::Long nSrcWidth )
477 {
478  TrueColorPixelPtr<DSTFMT> aDstType;
479  aDstType.SetRawPtr( ImplGetScanline( rDst, nY ));
480  ImplConvertLine( aDstType, rSrcLine, std::min( nSrcWidth, rDst.mnWidth ));
481  return true;
482 }
483 
484 template <ScanlineFormat SRCFMT>
485 static bool ImplCopyFromScanline( tools::Long nY, BitmapBuffer& rDst, ConstScanline aSrcScanline, tools::Long nSrcWidth )
486 {
487  TrueColorPixelPtr<SRCFMT> aSrcType;
488  aSrcType.SetRawPtr( const_cast<Scanline>( aSrcScanline ));
489  // select the matching instantiation for the destination's bitmap format
490  switch( RemoveScanline( rDst.mnFormat ))
491  {
493  return ImplCopyToScanline<ScanlineFormat::N24BitTcBgr>( nY, rDst, aSrcType, nSrcWidth );
495  return ImplCopyToScanline<ScanlineFormat::N24BitTcRgb>( nY, rDst, aSrcType, nSrcWidth );
496 
498  return ImplCopyToScanline<ScanlineFormat::N32BitTcAbgr>( nY, rDst, aSrcType, nSrcWidth );
500  return ImplCopyToScanline<ScanlineFormat::N32BitTcArgb>( nY, rDst, aSrcType, nSrcWidth );
502  return ImplCopyToScanline<ScanlineFormat::N32BitTcBgra>( nY, rDst, aSrcType, nSrcWidth );
504  return ImplCopyToScanline<ScanlineFormat::N32BitTcRgba>( nY, rDst, aSrcType, nSrcWidth );
505  default:
506  break;
507  }
508  return false;
509 
510 }
511 
513  ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize)
514 {
515  if( rDst.mnHeight <= nY )
516  return false;
517 
518  const ScanlineFormat nSrcFormat = RemoveScanline(nSrcScanlineFormat);
519  const ScanlineFormat nDstFormat = RemoveScanline(rDst.mnFormat);
520 
521  // special handling of trivial cases
522  if( nSrcFormat == nDstFormat )
523  {
524  memcpy( ImplGetScanline( rDst, nY ), aSrcScanline, std::min<tools::Long>(nSrcScanlineSize, rDst.mnScanlineSize));
525  return true;
526  }
527 
528  // select the matching instantiation for the source's bitmap format
529  switch( nSrcFormat )
530  {
532  return ImplCopyFromScanline<ScanlineFormat::N24BitTcBgr>( nY, rDst, aSrcScanline, nSrcScanlineSize / 3 );
534  return ImplCopyFromScanline<ScanlineFormat::N24BitTcRgb>( nY, rDst, aSrcScanline, nSrcScanlineSize / 3 );
535 
537  return ImplCopyFromScanline<ScanlineFormat::N32BitTcAbgr>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
539  return ImplCopyFromScanline<ScanlineFormat::N32BitTcArgb>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
541  return ImplCopyFromScanline<ScanlineFormat::N32BitTcBgra>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
543  return ImplCopyFromScanline<ScanlineFormat::N32BitTcRgba>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
544  default:
545  break;
546  }
547  return false;
548 }
549 
551 {
552  if( nY >= rDst.mnHeight )
553  return false;
554  if( rSrc.maPalette != rDst.maPalette )
555  return false;
556  return ImplFastCopyScanline( nY, rDst, ImplGetScanline( rSrc, nY ), rSrc.mnFormat, rSrc.mnScanlineSize);
557 }
558 
559 template <ScanlineFormat DSTFMT, ScanlineFormat SRCFMT> //,sal_uLong MSKFMT>
560 static bool ImplBlendToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
561  BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
562  const BitmapBuffer& rMskBuffer )
563 {
565  "vcl.gdi", "FastBmp BlendImage: unusual MSKFMT" );
566 
567  const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
568  int nMskLinestep = rMskBuffer.mnScanlineSize;
569  int nDstLinestep = rDstBuffer.mnScanlineSize;
570 
571  TrueColorPixelPtr<ScanlineFormat::N8BitPal> aMskLine; aMskLine.SetRawPtr( rMskBuffer.mpBits );
572  TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
573 
574  // special case for single line masks
575  if( rMskBuffer.mnHeight == 1 )
576  nMskLinestep = 0;
577 
578  // source and mask don't match: upside down
579  if( (rSrcBuffer.mnFormat ^ rMskBuffer.mnFormat) & ScanlineFormat::TopDown )
580  {
581  aMskLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nMskLinestep );
582  nMskLinestep = -nMskLinestep;
583  }
584 
585  // source and destination don't match: upside down
586  if( (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) & ScanlineFormat::TopDown )
587  {
588  aDstLine.AddByteOffset( (rDstBuffer.mnHeight - 1) * nDstLinestep );
589  nDstLinestep = -nDstLinestep;
590  }
591 
592  assert(rDstBuffer.mnHeight <= rSrcBuffer.mnHeight && "not sure about that?");
593  for (int y = rDstBuffer.mnHeight; --y >= 0;)
594  {
595  ImplBlendLines(aDstLine, rSrcLine, aMskLine, rDstBuffer.mnWidth);
596  aDstLine.AddByteOffset( nDstLinestep );
597  rSrcLine.AddByteOffset( nSrcLinestep );
598  aMskLine.AddByteOffset( nMskLinestep );
599  }
600 
601  return true;
602 }
603 
604 // some specializations to reduce the code size
605 template <>
606 bool ImplBlendToBitmap<ScanlineFormat::N24BitTcBgr,ScanlineFormat::N24BitTcBgr>(
607  TrueColorPixelPtr<ScanlineFormat::N24BitTcBgr>&,
608  BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
609  const BitmapBuffer& rMskBuffer )
610  {
611  TrueColorPixelPtr<ScanlineFormat::N24BitTcRgb> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
612  return ImplBlendToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
613  }
614 
615 template <>
616 bool ImplBlendToBitmap<ScanlineFormat::N32BitTcAbgr,ScanlineFormat::N32BitTcAbgr>(
617  TrueColorPixelPtr<ScanlineFormat::N32BitTcAbgr>&,
618  BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
619  const BitmapBuffer& rMskBuffer )
620  {
621  TrueColorPixelPtr<ScanlineFormat::N32BitTcArgb> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
622  return ImplBlendToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
623  }
624 
625 template <>
626 bool ImplBlendToBitmap<ScanlineFormat::N32BitTcBgra,ScanlineFormat::N32BitTcBgra>(
627  TrueColorPixelPtr<ScanlineFormat::N32BitTcBgra>&,
628  BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
629  const BitmapBuffer& rMskBuffer )
630  {
631  TrueColorPixelPtr<ScanlineFormat::N32BitTcRgba> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
632  return ImplBlendToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
633  }
634 
635 template <ScanlineFormat SRCFMT>
636 static bool ImplBlendFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc, const BitmapBuffer& rMsk )
637 {
638  TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
639 
640  // select the matching instantiation for the destination's bitmap format
641  switch (RemoveScanline(rDst.mnFormat))
642  {
648  break;
649 
651 // return ImplBlendToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc, rMsk );
652  break;
653 
655  return ImplBlendToBitmap<ScanlineFormat::N24BitTcBgr>( aSrcType, rDst, rSrc, rMsk );
657  return ImplBlendToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDst, rSrc, rMsk );
658 
660  return ImplBlendToBitmap<ScanlineFormat::N32BitTcAbgr>( aSrcType, rDst, rSrc, rMsk );
662  return ImplBlendToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDst, rSrc, rMsk );
664  return ImplBlendToBitmap<ScanlineFormat::N32BitTcBgra>( aSrcType, rDst, rSrc, rMsk );
666  return ImplBlendToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDst, rSrc, rMsk );
667  default: break;
668  }
669 
670  static int nNotAccelerated = 0;
671  SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
672  "vcl.gdi",
673  "ImplBlendFromBitmap for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "*" << static_cast<int>(rMsk.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) );
674  return false;
675 }
676 
678  const BitmapReadAccess& rSrcRA, const BitmapReadAccess& rMskRA,
679  const SalTwoRect& rTR )
680 {
681  // accelerated blending of paletted bitmaps not implemented yet
682  if( rSrcRA.HasPalette() )
683  return false;
684  if( rDstWA.HasPalette() )
685  return false;
686  // TODO: either get rid of mask's use of 8BIT_PAL or check the palette
687 
688  // horizontal mirroring not implemented yet
689  if( rTR.mnDestWidth < 0 )
690  return false;
691  // vertical mirroring
692  if( rTR.mnDestHeight < 0 )
693  // TODO: rDst.mnFormat ^= ScanlineFormat::TopDown;
694  return false;
695 
696  // offsetted blending is not implemented yet
697  if( rTR.mnSrcX || rTR.mnSrcY )
698  return false;
699  if( rTR.mnDestX || rTR.mnDestY )
700  return false;
701 
702  // stretched blending is not implemented yet
703  if( rTR.mnDestWidth != rTR.mnSrcWidth )
704  return false;
705  if( rTR.mnDestHeight!= rTR.mnSrcHeight )
706  return false;
707 
708  // check source image size
709  if( rSrcRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
710  return false;
711  if( rSrcRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
712  return false;
713 
714  // check mask image size
715  if( rMskRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
716  return false;
717  if( rMskRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
718  if( rMskRA.Height() != 1 )
719  return false;
720 
721  // check dest image size
722  if( rDstWA.Width() < rTR.mnDestX + rTR.mnDestWidth )
723  return false;
724  if( rDstWA.Height() < rTR.mnDestY + rTR.mnDestHeight )
725  return false;
726 
727  BitmapBuffer& rDst = *rDstWA.ImplGetBitmapBuffer();
728  const BitmapBuffer& rSrc = *rSrcRA.ImplGetBitmapBuffer();
729  const BitmapBuffer& rMsk = *rMskRA.ImplGetBitmapBuffer();
730 
731  const ScanlineFormat nSrcFormat = RemoveScanline(rSrc.mnFormat);
732 
733  // select the matching instantiation for the source's bitmap format
734  switch( nSrcFormat )
735  {
740  break;
741 
743 // return ImplBlendFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
744  break;
745 
747  if(rSrc.maPalette.IsGreyPalette8Bit())
748  return ImplBlendFromBitmap<ScanlineFormat::N8BitPal>( rDst, rSrc, rMsk );
749  break;
750 
752  return ImplBlendFromBitmap<ScanlineFormat::N24BitTcBgr>( rDst, rSrc, rMsk );
754  return ImplBlendFromBitmap<ScanlineFormat::N24BitTcRgb>( rDst, rSrc, rMsk );
755 
757  return ImplBlendFromBitmap<ScanlineFormat::N32BitTcAbgr>( rDst, rSrc, rMsk );
759  return ImplBlendFromBitmap<ScanlineFormat::N32BitTcArgb>( rDst, rSrc, rMsk );
761  return ImplBlendFromBitmap<ScanlineFormat::N32BitTcBgra>( rDst, rSrc, rMsk );
763  return ImplBlendFromBitmap<ScanlineFormat::N32BitTcRgba>( rDst, rSrc, rMsk );
764  default: break;
765  }
766 
767  static int nNotAccelerated = 0;
768  SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
769  "vcl.gdi",
770  "ImplFastBlend for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "*" << static_cast<int>(rMsk.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) << ")" );
771 
772  return false;
773 }
774 
775 bool ImplFastEraseBitmap( BitmapBuffer& rDst, const BitmapColor& rColor )
776 {
777  const ScanlineFormat nDstFormat = RemoveScanline(rDst.mnFormat);
778 
779  // erasing a bitmap is often just a byte-wise memory fill
780  bool bByteFill = true;
781  sal_uInt8 nFillByte;
782 
783  switch( nDstFormat )
784  {
787  nFillByte = rColor.GetIndex();
788  nFillByte = static_cast<sal_uInt8>( -(nFillByte & 1) ); // 0x00 or 0xFF
789  break;
792  nFillByte = rColor.GetIndex();
793  nFillByte &= 0x0F;
794  nFillByte |= (nFillByte << 4);
795  break;
797  nFillByte = rColor.GetIndex();
798  break;
799 
802  nFillByte = rColor.GetRed();
803  if( (nFillByte != rColor.GetGreen())
804  || (nFillByte != rColor.GetBlue()) )
805  bByteFill = false;
806  break;
807 
808  default:
809  bByteFill = false;
810  nFillByte = 0x00;
811  break;
812  }
813 
814  if( bByteFill )
815  {
816  tools::Long nByteCount = rDst.mnHeight * rDst.mnScanlineSize;
817  memset( rDst.mpBits, nFillByte, nByteCount );
818  return true;
819  }
820 
821  // TODO: handle other bitmap formats
822  switch( nDstFormat )
823  {
825 
828 
833  break;
834 
835  default:
836  break;
837  }
838 
839  return false;
840 }
841 
842 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsGreyPalette8Bit() const
Returns true if the palette is 8-bit grey palette.
sal_uInt8 GetIndex() const
Definition: BitmapColor.hxx:61
tools::Long Height() const
sal_uInt8 GetRed() const
static void ImplConvertPixel(const TrueColorPixelPtr< DSTFMT > &rDst, const TrueColorPixelPtr< SRCFMT > &rSrc)
Definition: bmpfast.cxx:196
tools::Long mnHeight
tools::Long mnDestX
Definition: salgtype.hxx:45
long Long
static void ImplBlendPixels(const TrueColorPixelPtr< DSTFMT > &rDst, const TrueColorPixelPtr< SRCFMT > &rSrc, unsigned nAlphaVal)
Definition: bmpfast.cxx:219
tools::Long mnSrcHeight
Definition: salgtype.hxx:44
tools::Long mnSrcWidth
Definition: salgtype.hxx:43
SotClipboardFormatId & operator++(SotClipboardFormatId &eFormat)
tools::Long mnDestWidth
Definition: salgtype.hxx:47
ScanlineFormat
Definition: Scanline.hxx:28
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
static bool ImplCopyToScanline(tools::Long nY, BitmapBuffer &rDst, TrueColorPixelPtr< SRCFMT > &rSrcLine, tools::Long nSrcWidth)
Definition: bmpfast.cxx:476
static bool ImplCopyImage(BitmapBuffer &rDstBuffer, const BitmapBuffer &rSrcBuffer)
Definition: bmpfast.cxx:263
static void ImplBlendLines(const TrueColorPixelPtr< DSTFMT > &rDst, const TrueColorPixelPtr< SRCFMT > &rSrc, const TrueColorPixelPtr< MASKFMT > &rMsk, int nPixelCount)
Definition: bmpfast.cxx:246
SAL_DLLPRIVATE BitmapBuffer * ImplGetBitmapBuffer() const
sal_uInt8 GetBlue() const
ScanlineFormat mnFormat
float y
static bool ImplCopyFromScanline(tools::Long nY, BitmapBuffer &rDst, ConstScanline aSrcScanline, tools::Long nSrcWidth)
Definition: bmpfast.cxx:485
tools::Long mnDestHeight
Definition: salgtype.hxx:48
sal_uInt8 * Scanline
Definition: Scanline.hxx:25
bool HasPalette() const
uno_Any a
static bool ImplBlendToBitmap(TrueColorPixelPtr< SRCFMT > &rSrcLine, BitmapBuffer &rDstBuffer, const BitmapBuffer &rSrcBuffer, const BitmapBuffer &rMskBuffer)
Definition: bmpfast.cxx:560
tools::Long Width() const
bool ImplFastBitmapBlending(BitmapWriteAccess const &rDstWA, const BitmapReadAccess &rSrcRA, const BitmapReadAccess &rMskRA, const SalTwoRect &rTR)
Definition: bmpfast.cxx:677
sal_uInt8 * mpBits
tools::Long mnSrcX
Definition: salgtype.hxx:41
tools::Long mnSrcY
Definition: salgtype.hxx:42
const sal_uInt8 * ConstScanline
Definition: Scanline.hxx:26
sal_uInt8 GetGreen() const
static ConstScanline ImplGetScanline(const BitmapBuffer &rBuf, tools::Long nY)
Definition: bmpfast.cxx:462
bool ImplFastCopyScanline(tools::Long nY, BitmapBuffer &rDst, ConstScanline aSrcScanline, ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize)
Definition: bmpfast.cxx:512
tools::Long mnScanlineSize
unsigned char PIXBYTE
Definition: bmpfast.cxx:27
#define SAL_WARN_IF(condition, area, stream)
unsigned char sal_uInt8
static bool ImplConvertToBitmap(TrueColorPixelPtr< SRCFMT > &rSrcLine, BitmapBuffer &rDstBuffer, const BitmapBuffer &rSrcBuffer)
Definition: bmpfast.cxx:298
void * p
static bool ImplConvertFromBitmap(BitmapBuffer &rDst, const BitmapBuffer &rSrc)
Definition: bmpfast.cxx:329
ScanlineFormat RemoveScanline(ScanlineFormat nFormat)
Definition: Scanline.hxx:56
BitmapPalette maPalette
static void ImplConvertLine(const TrueColorPixelPtr< DSTFMT > &rDst, const TrueColorPixelPtr< SRCFMT > &rSrc, int nPixelCount)
Definition: bmpfast.cxx:204
static bool ImplBlendFromBitmap(BitmapBuffer &rDst, const BitmapBuffer &rSrc, const BitmapBuffer &rMsk)
Definition: bmpfast.cxx:636
tools::Long mnDestY
Definition: salgtype.hxx:46
tools::Long mnWidth
bool ImplFastEraseBitmap(BitmapBuffer &rDst, const BitmapColor &rColor)
Definition: bmpfast.cxx:775
bool ImplFastBitmapConversion(BitmapBuffer &rDst, const BitmapBuffer &rSrc, const SalTwoRect &rTR)
Definition: bmpfast.cxx:373