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 <vcl/salgtype.hxx>
21 
23 #include <bitmap/bmpfast.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  {
339  break;
340 
342 // return ImplConvertToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc );
343  break;
344 
346  return ImplConvertToBitmap<ScanlineFormat::N24BitTcBgr>( aSrcType, rDst, rSrc );
348  return ImplConvertToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDst, rSrc );
349 
351  return ImplConvertToBitmap<ScanlineFormat::N32BitTcAbgr>( aSrcType, rDst, rSrc );
353  return ImplConvertToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDst, rSrc );
355  return ImplConvertToBitmap<ScanlineFormat::N32BitTcBgra>( aSrcType, rDst, rSrc );
357  return ImplConvertToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDst, rSrc );
358  default: break;
359  }
360 
361  static int nNotAccelerated = 0;
362  SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
363  "vcl.gdi",
364  "ImplConvertFromBitmap for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) << ")" );
365 
366  return false;
367 }
368 
369 // A universal stretching conversion is overkill in most common situations
370 // => performance benefits for speeding up the non-stretching cases
372  const SalTwoRect& rTR )
373 {
374  // TODO:horizontal mirroring not implemented yet
375  if( rTR.mnDestWidth < 0 )
376  return false;
377  // vertical mirroring
378  if( rTR.mnDestHeight < 0 )
379  // TODO: rDst.mnFormat ^= ScanlineFormat::TopDown;
380  return false;
381 
382  // offsetted conversion is not implemented yet
383  if( rTR.mnSrcX || rTR.mnSrcY )
384  return false;
385  if( rTR.mnDestX || rTR.mnDestY )
386  return false;
387 
388  // stretched conversion is not implemented yet
389  if( rTR.mnDestWidth != rTR.mnSrcWidth )
390  return false;
391  if( rTR.mnDestHeight!= rTR.mnSrcHeight )
392  return false;
393 
394  // check source image size
395  if( rSrc.mnWidth < rTR.mnSrcX + rTR.mnSrcWidth )
396  return false;
397  if( rSrc.mnHeight < rTR.mnSrcY + rTR.mnSrcHeight )
398  return false;
399 
400  // check dest image size
401  if( rDst.mnWidth < rTR.mnDestX + rTR.mnDestWidth )
402  return false;
403  if( rDst.mnHeight < rTR.mnDestY + rTR.mnDestHeight )
404  return false;
405 
406  const ScanlineFormat nSrcFormat = RemoveScanline(rSrc.mnFormat);
407  const ScanlineFormat nDstFormat = RemoveScanline(rDst.mnFormat);
408 
409  // special handling of trivial cases
410  if( nSrcFormat == nDstFormat )
411  {
412  // accelerated palette conversions not yet implemented
413  if( rSrc.maPalette != rDst.maPalette )
414  return false;
415  return ImplCopyImage( rDst, rSrc );
416  }
417 
418  // select the matching instantiation for the source's bitmap format
419  switch( nSrcFormat )
420  {
423  break;
424 
426 // return ImplConvertFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
427  break;
428 
430  if(rSrc.maPalette.IsGreyPalette8Bit())
431  return ImplConvertFromBitmap<ScanlineFormat::N8BitPal>( rDst, rSrc );
432  break;
433 
435  return ImplConvertFromBitmap<ScanlineFormat::N24BitTcBgr>( rDst, rSrc );
437  return ImplConvertFromBitmap<ScanlineFormat::N24BitTcRgb>( rDst, rSrc );
438 
440  return ImplConvertFromBitmap<ScanlineFormat::N32BitTcAbgr>( rDst, rSrc );
442  return ImplConvertFromBitmap<ScanlineFormat::N32BitTcArgb>( rDst, rSrc );
444  return ImplConvertFromBitmap<ScanlineFormat::N32BitTcBgra>( rDst, rSrc );
446  return ImplConvertFromBitmap<ScanlineFormat::N32BitTcRgba>( rDst, rSrc );
447  default: break;
448  }
449 
450  static int nNotAccelerated = 0;
451  SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
452  "vcl.gdi",
453  "ImplFastBitmapConversion for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) << ")" );
454 
455  return false;
456 }
457 
458 static inline ConstScanline ImplGetScanline( const BitmapBuffer& rBuf, tools::Long nY )
459 {
460  if( rBuf.mnFormat & ScanlineFormat::TopDown )
461  return rBuf.mpBits + nY * rBuf.mnScanlineSize;
462  else
463  return rBuf.mpBits + (rBuf.mnHeight - 1 - nY) * rBuf.mnScanlineSize;
464 }
465 
467 {
468  return const_cast<Scanline>(ImplGetScanline( const_cast<const BitmapBuffer&>(rBuf), nY ));
469 }
470 
471 template <ScanlineFormat DSTFMT, ScanlineFormat SRCFMT>
472 static bool ImplCopyToScanline( tools::Long nY, BitmapBuffer& rDst, TrueColorPixelPtr<SRCFMT>& rSrcLine, tools::Long nSrcWidth )
473 {
474  TrueColorPixelPtr<DSTFMT> aDstType;
475  aDstType.SetRawPtr( ImplGetScanline( rDst, nY ));
476  ImplConvertLine( aDstType, rSrcLine, std::min( nSrcWidth, rDst.mnWidth ));
477  return true;
478 }
479 
480 template <ScanlineFormat SRCFMT>
481 static bool ImplCopyFromScanline( tools::Long nY, BitmapBuffer& rDst, ConstScanline aSrcScanline, tools::Long nSrcWidth )
482 {
483  TrueColorPixelPtr<SRCFMT> aSrcType;
484  aSrcType.SetRawPtr( const_cast<Scanline>( aSrcScanline ));
485  // select the matching instantiation for the destination's bitmap format
486  switch( RemoveScanline( rDst.mnFormat ))
487  {
489  return ImplCopyToScanline<ScanlineFormat::N24BitTcBgr>( nY, rDst, aSrcType, nSrcWidth );
491  return ImplCopyToScanline<ScanlineFormat::N24BitTcRgb>( nY, rDst, aSrcType, nSrcWidth );
492 
494  return ImplCopyToScanline<ScanlineFormat::N32BitTcAbgr>( nY, rDst, aSrcType, nSrcWidth );
496  return ImplCopyToScanline<ScanlineFormat::N32BitTcArgb>( nY, rDst, aSrcType, nSrcWidth );
498  return ImplCopyToScanline<ScanlineFormat::N32BitTcBgra>( nY, rDst, aSrcType, nSrcWidth );
500  return ImplCopyToScanline<ScanlineFormat::N32BitTcRgba>( nY, rDst, aSrcType, nSrcWidth );
501  default:
502  break;
503  }
504  return false;
505 
506 }
507 
509  ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize)
510 {
511  if( rDst.mnHeight <= nY )
512  return false;
513 
514  const ScanlineFormat nSrcFormat = RemoveScanline(nSrcScanlineFormat);
515  const ScanlineFormat nDstFormat = RemoveScanline(rDst.mnFormat);
516 
517  // special handling of trivial cases
518  if( nSrcFormat == nDstFormat )
519  {
520  memcpy( ImplGetScanline( rDst, nY ), aSrcScanline, std::min<tools::Long>(nSrcScanlineSize, rDst.mnScanlineSize));
521  return true;
522  }
523 
524  // select the matching instantiation for the source's bitmap format
525  switch( nSrcFormat )
526  {
528  return ImplCopyFromScanline<ScanlineFormat::N24BitTcBgr>( nY, rDst, aSrcScanline, nSrcScanlineSize / 3 );
530  return ImplCopyFromScanline<ScanlineFormat::N24BitTcRgb>( nY, rDst, aSrcScanline, nSrcScanlineSize / 3 );
531 
533  return ImplCopyFromScanline<ScanlineFormat::N32BitTcAbgr>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
535  return ImplCopyFromScanline<ScanlineFormat::N32BitTcArgb>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
537  return ImplCopyFromScanline<ScanlineFormat::N32BitTcBgra>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
539  return ImplCopyFromScanline<ScanlineFormat::N32BitTcRgba>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
540  default:
541  break;
542  }
543  return false;
544 }
545 
547 {
548  if( nY >= rDst.mnHeight )
549  return false;
550  if( rSrc.maPalette != rDst.maPalette )
551  return false;
552  return ImplFastCopyScanline( nY, rDst, ImplGetScanline( rSrc, nY ), rSrc.mnFormat, rSrc.mnScanlineSize);
553 }
554 
555 template <ScanlineFormat DSTFMT, ScanlineFormat SRCFMT> //,sal_uLong MSKFMT>
556 static bool ImplBlendToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
557  BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
558  const BitmapBuffer& rMskBuffer )
559 {
561  "vcl.gdi", "FastBmp BlendImage: unusual MSKFMT" );
562 
563  const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
564  int nMskLinestep = rMskBuffer.mnScanlineSize;
565  int nDstLinestep = rDstBuffer.mnScanlineSize;
566 
567  TrueColorPixelPtr<ScanlineFormat::N8BitPal> aMskLine; aMskLine.SetRawPtr( rMskBuffer.mpBits );
568  TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
569 
570  // special case for single line masks
571  if( rMskBuffer.mnHeight == 1 )
572  nMskLinestep = 0;
573 
574  // source and mask don't match: upside down
575  if( (rSrcBuffer.mnFormat ^ rMskBuffer.mnFormat) & ScanlineFormat::TopDown )
576  {
577  aMskLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nMskLinestep );
578  nMskLinestep = -nMskLinestep;
579  }
580 
581  // source and destination don't match: upside down
582  if( (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) & ScanlineFormat::TopDown )
583  {
584  aDstLine.AddByteOffset( (rDstBuffer.mnHeight - 1) * nDstLinestep );
585  nDstLinestep = -nDstLinestep;
586  }
587 
588  assert(rDstBuffer.mnHeight <= rSrcBuffer.mnHeight && "not sure about that?");
589  for (int y = rDstBuffer.mnHeight; --y >= 0;)
590  {
591  ImplBlendLines(aDstLine, rSrcLine, aMskLine, rDstBuffer.mnWidth);
592  aDstLine.AddByteOffset( nDstLinestep );
593  rSrcLine.AddByteOffset( nSrcLinestep );
594  aMskLine.AddByteOffset( nMskLinestep );
595  }
596 
597  return true;
598 }
599 
600 // some specializations to reduce the code size
601 template <>
602 bool ImplBlendToBitmap<ScanlineFormat::N24BitTcBgr,ScanlineFormat::N24BitTcBgr>(
603  TrueColorPixelPtr<ScanlineFormat::N24BitTcBgr>&,
604  BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
605  const BitmapBuffer& rMskBuffer )
606  {
607  TrueColorPixelPtr<ScanlineFormat::N24BitTcRgb> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
608  return ImplBlendToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
609  }
610 
611 template <>
612 bool ImplBlendToBitmap<ScanlineFormat::N32BitTcAbgr,ScanlineFormat::N32BitTcAbgr>(
613  TrueColorPixelPtr<ScanlineFormat::N32BitTcAbgr>&,
614  BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
615  const BitmapBuffer& rMskBuffer )
616  {
617  TrueColorPixelPtr<ScanlineFormat::N32BitTcArgb> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
618  return ImplBlendToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
619  }
620 
621 template <>
622 bool ImplBlendToBitmap<ScanlineFormat::N32BitTcBgra,ScanlineFormat::N32BitTcBgra>(
623  TrueColorPixelPtr<ScanlineFormat::N32BitTcBgra>&,
624  BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
625  const BitmapBuffer& rMskBuffer )
626  {
627  TrueColorPixelPtr<ScanlineFormat::N32BitTcRgba> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
628  return ImplBlendToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
629  }
630 
631 template <ScanlineFormat SRCFMT>
632 static bool ImplBlendFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc, const BitmapBuffer& rMsk )
633 {
634  TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
635 
636  // select the matching instantiation for the destination's bitmap format
637  switch (RemoveScanline(rDst.mnFormat))
638  {
642  break;
643 
645 // return ImplBlendToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc, rMsk );
646  break;
647 
649  return ImplBlendToBitmap<ScanlineFormat::N24BitTcBgr>( aSrcType, rDst, rSrc, rMsk );
651  return ImplBlendToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDst, rSrc, rMsk );
652 
654  return ImplBlendToBitmap<ScanlineFormat::N32BitTcAbgr>( aSrcType, rDst, rSrc, rMsk );
656  return ImplBlendToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDst, rSrc, rMsk );
658  return ImplBlendToBitmap<ScanlineFormat::N32BitTcBgra>( aSrcType, rDst, rSrc, rMsk );
660  return ImplBlendToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDst, rSrc, rMsk );
661  default: break;
662  }
663 
664  static int nNotAccelerated = 0;
665  SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
666  "vcl.gdi",
667  "ImplBlendFromBitmap for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "*" << static_cast<int>(rMsk.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) );
668  return false;
669 }
670 
672  const BitmapReadAccess& rSrcRA, const BitmapReadAccess& rMskRA,
673  const SalTwoRect& rTR )
674 {
675  // accelerated blending of paletted bitmaps not implemented yet
676  if( rSrcRA.HasPalette() )
677  return false;
678  if( rDstWA.HasPalette() )
679  return false;
680  // TODO: either get rid of mask's use of 8BIT_PAL or check the palette
681 
682  // horizontal mirroring not implemented yet
683  if( rTR.mnDestWidth < 0 )
684  return false;
685  // vertical mirroring
686  if( rTR.mnDestHeight < 0 )
687  // TODO: rDst.mnFormat ^= ScanlineFormat::TopDown;
688  return false;
689 
690  // offsetted blending is not implemented yet
691  if( rTR.mnSrcX || rTR.mnSrcY )
692  return false;
693  if( rTR.mnDestX || rTR.mnDestY )
694  return false;
695 
696  // stretched blending is not implemented yet
697  if( rTR.mnDestWidth != rTR.mnSrcWidth )
698  return false;
699  if( rTR.mnDestHeight!= rTR.mnSrcHeight )
700  return false;
701 
702  // check source image size
703  if( rSrcRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
704  return false;
705  if( rSrcRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
706  return false;
707 
708  // check mask image size
709  if( rMskRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
710  return false;
711  if( rMskRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
712  if( rMskRA.Height() != 1 )
713  return false;
714 
715  // check dest image size
716  if( rDstWA.Width() < rTR.mnDestX + rTR.mnDestWidth )
717  return false;
718  if( rDstWA.Height() < rTR.mnDestY + rTR.mnDestHeight )
719  return false;
720 
721  BitmapBuffer& rDst = *rDstWA.ImplGetBitmapBuffer();
722  const BitmapBuffer& rSrc = *rSrcRA.ImplGetBitmapBuffer();
723  const BitmapBuffer& rMsk = *rMskRA.ImplGetBitmapBuffer();
724 
725  const ScanlineFormat nSrcFormat = RemoveScanline(rSrc.mnFormat);
726 
727  // select the matching instantiation for the source's bitmap format
728  switch( nSrcFormat )
729  {
732  break;
733 
735 // return ImplBlendFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
736  break;
737 
739  if(rSrc.maPalette.IsGreyPalette8Bit())
740  return ImplBlendFromBitmap<ScanlineFormat::N8BitPal>( rDst, rSrc, rMsk );
741  break;
742 
744  return ImplBlendFromBitmap<ScanlineFormat::N24BitTcBgr>( rDst, rSrc, rMsk );
746  return ImplBlendFromBitmap<ScanlineFormat::N24BitTcRgb>( rDst, rSrc, rMsk );
747 
749  return ImplBlendFromBitmap<ScanlineFormat::N32BitTcAbgr>( rDst, rSrc, rMsk );
751  return ImplBlendFromBitmap<ScanlineFormat::N32BitTcArgb>( rDst, rSrc, rMsk );
753  return ImplBlendFromBitmap<ScanlineFormat::N32BitTcBgra>( rDst, rSrc, rMsk );
755  return ImplBlendFromBitmap<ScanlineFormat::N32BitTcRgba>( rDst, rSrc, rMsk );
756  default: break;
757  }
758 
759  static int nNotAccelerated = 0;
760  SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
761  "vcl.gdi",
762  "ImplFastBlend for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "*" << static_cast<int>(rMsk.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) << ")" );
763 
764  return false;
765 }
766 
767 bool ImplFastEraseBitmap( BitmapBuffer& rDst, const BitmapColor& rColor )
768 {
769  const ScanlineFormat nDstFormat = RemoveScanline(rDst.mnFormat);
770 
771  // erasing a bitmap is often just a byte-wise memory fill
772  bool bByteFill = true;
773  sal_uInt8 nFillByte;
774 
775  switch( nDstFormat )
776  {
779  nFillByte = rColor.GetIndex();
780  nFillByte = static_cast<sal_uInt8>( -(nFillByte & 1) ); // 0x00 or 0xFF
781  break;
783  nFillByte = rColor.GetIndex();
784  break;
785 
788  nFillByte = rColor.GetRed();
789  if( (nFillByte != rColor.GetGreen())
790  || (nFillByte != rColor.GetBlue()) )
791  bByteFill = false;
792  break;
793 
794  default:
795  bByteFill = false;
796  nFillByte = 0x00;
797  break;
798  }
799 
800  if( bByteFill )
801  {
802  tools::Long nByteCount = rDst.mnHeight * rDst.mnScanlineSize;
803  memset( rDst.mpBits, nFillByte, nByteCount );
804  return true;
805  }
806 
807  // TODO: handle other bitmap formats
808  switch( nDstFormat )
809  {
811 
814 
819  break;
820 
821  default:
822  break;
823  }
824 
825  return false;
826 }
827 
828 /* 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:70
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:44
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:43
tools::Long mnSrcWidth
Definition: salgtype.hxx:42
SotClipboardFormatId & operator++(SotClipboardFormatId &eFormat)
tools::Long mnDestWidth
Definition: salgtype.hxx:46
ScanlineFormat
Definition: Scanline.hxx:29
static bool ImplCopyToScanline(tools::Long nY, BitmapBuffer &rDst, TrueColorPixelPtr< SRCFMT > &rSrcLine, tools::Long nSrcWidth)
Definition: bmpfast.cxx:472
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:481
tools::Long mnDestHeight
Definition: salgtype.hxx:47
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
bool HasPalette() const
uno_Any a
static bool ImplBlendToBitmap(TrueColorPixelPtr< SRCFMT > &rSrcLine, BitmapBuffer &rDstBuffer, const BitmapBuffer &rSrcBuffer, const BitmapBuffer &rMskBuffer)
Definition: bmpfast.cxx:556
tools::Long Width() const
bool ImplFastBitmapBlending(BitmapWriteAccess const &rDstWA, const BitmapReadAccess &rSrcRA, const BitmapReadAccess &rMskRA, const SalTwoRect &rTR)
Definition: bmpfast.cxx:671
sal_uInt8 * mpBits
tools::Long mnSrcX
Definition: salgtype.hxx:40
tools::Long mnSrcY
Definition: salgtype.hxx:41
const sal_uInt8 * ConstScanline
Definition: Scanline.hxx:27
sal_uInt8 GetGreen() const
static ConstScanline ImplGetScanline(const BitmapBuffer &rBuf, tools::Long nY)
Definition: bmpfast.cxx:458
bool ImplFastCopyScanline(tools::Long nY, BitmapBuffer &rDst, ConstScanline aSrcScanline, ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize)
Definition: bmpfast.cxx:508
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:54
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:632
tools::Long mnDestY
Definition: salgtype.hxx:45
tools::Long mnWidth
bool ImplFastEraseBitmap(BitmapBuffer &rDst, const BitmapColor &rColor)
Definition: bmpfast.cxx:767
bool ImplFastBitmapConversion(BitmapBuffer &rDst, const BitmapBuffer &rSrc, const SalTwoRect &rTR)
Definition: bmpfast.cxx:371