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
27typedef unsigned char PIXBYTE;
28
29namespace {
30
31class BasePixelPtr
32{
33public:
34 explicit BasePixelPtr( PIXBYTE* p = nullptr ) : mpPixel( p ) {}
35 void SetRawPtr( PIXBYTE* pRawPtr ) { mpPixel = pRawPtr; }
36 void AddByteOffset( int nByteOffset ) { mpPixel += nByteOffset; }
37
38protected:
39 PIXBYTE* mpPixel;
40};
41
42template <ScanlineFormat PIXFMT>
43class TrueColorPixelPtr : public BasePixelPtr
44{
45public:
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
56template <>
57class TrueColorPixelPtr<ScanlineFormat::N24BitTcRgb> : public BasePixelPtr
58{
59public:
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
76template <>
77class TrueColorPixelPtr<ScanlineFormat::N24BitTcBgr> : public BasePixelPtr
78{
79public:
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
96template <>
97class TrueColorPixelPtr<ScanlineFormat::N32BitTcArgb> : public BasePixelPtr
98{
99public:
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
116template <>
117class TrueColorPixelPtr<ScanlineFormat::N32BitTcAbgr> : public BasePixelPtr
118{
119public:
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
136template <>
137class TrueColorPixelPtr<ScanlineFormat::N32BitTcRgba> : public BasePixelPtr
138{
139public:
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
156template <>
157class TrueColorPixelPtr<ScanlineFormat::N32BitTcBgra> : public BasePixelPtr
158{
159public:
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.
180template <>
181class TrueColorPixelPtr<ScanlineFormat::N8BitPal> : public BasePixelPtr
182{
183public:
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
195template <ScanlineFormat SRCFMT, ScanlineFormat DSTFMT>
196static 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
203template <ScanlineFormat SRCFMT, ScanlineFormat DSTFMT>
204static 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
218template <ScanlineFormat SRCFMT, ScanlineFormat DSTFMT>
219static 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
245template <ScanlineFormat MASKFMT, ScanlineFormat SRCFMT, ScanlineFormat DSTFMT>
246static 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
263static 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
297template <ScanlineFormat DSTFMT,ScanlineFormat SRCFMT>
298static 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
328template <ScanlineFormat SRCFMT>
329static 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 {
338 break;
339
341// return ImplConvertToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc );
342 break;
343
345 return ImplConvertToBitmap<ScanlineFormat::N24BitTcBgr>( aSrcType, rDst, rSrc );
347 return ImplConvertToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDst, rSrc );
348
350 return ImplConvertToBitmap<ScanlineFormat::N32BitTcAbgr>( aSrcType, rDst, rSrc );
352 return ImplConvertToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDst, rSrc );
354 return ImplConvertToBitmap<ScanlineFormat::N32BitTcBgra>( aSrcType, rDst, rSrc );
356 return ImplConvertToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDst, rSrc );
357 default: break;
358 }
359
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) << ")" );
364
365 return false;
366}
367
368// A universal stretching conversion is overkill in most common situations
369// => performance benefits for speeding up the non-stretching cases
371 const SalTwoRect& rTR )
372{
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;
380
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;
386
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;
392
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;
398
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;
404
405 const ScanlineFormat nSrcFormat = RemoveScanline(rSrc.mnFormat);
406 const ScanlineFormat nDstFormat = RemoveScanline(rDst.mnFormat);
407
408 // special handling of trivial cases
409 if( nSrcFormat == nDstFormat )
410 {
411 // accelerated palette conversions not yet implemented
412 if( rSrc.maPalette != rDst.maPalette )
413 return false;
414 return ImplCopyImage( rDst, rSrc );
415 }
416
417 // select the matching instantiation for the source's bitmap format
418 switch( nSrcFormat )
419 {
421 break;
422
424// return ImplConvertFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
425 break;
426
429 return ImplConvertFromBitmap<ScanlineFormat::N8BitPal>( rDst, rSrc );
430 break;
431
433 return ImplConvertFromBitmap<ScanlineFormat::N24BitTcBgr>( rDst, rSrc );
435 return ImplConvertFromBitmap<ScanlineFormat::N24BitTcRgb>( rDst, rSrc );
436
438 return ImplConvertFromBitmap<ScanlineFormat::N32BitTcAbgr>( rDst, rSrc );
440 return ImplConvertFromBitmap<ScanlineFormat::N32BitTcArgb>( rDst, rSrc );
442 return ImplConvertFromBitmap<ScanlineFormat::N32BitTcBgra>( rDst, rSrc );
444 return ImplConvertFromBitmap<ScanlineFormat::N32BitTcRgba>( rDst, rSrc );
445 default: break;
446 }
447
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 << static_cast<int>(rSrc.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) << ")" );
452
453 return false;
454}
455
457{
459 return rBuf.mpBits + nY * rBuf.mnScanlineSize;
460 else
461 return rBuf.mpBits + (rBuf.mnHeight - 1 - nY) * rBuf.mnScanlineSize;
462}
463
465{
466 return const_cast<Scanline>(ImplGetScanline( const_cast<const BitmapBuffer&>(rBuf), nY ));
467}
468
469template <ScanlineFormat DSTFMT, ScanlineFormat SRCFMT>
470static bool ImplCopyToScanline( tools::Long nY, BitmapBuffer& rDst, TrueColorPixelPtr<SRCFMT>& rSrcLine, tools::Long nSrcWidth )
471{
472 TrueColorPixelPtr<DSTFMT> aDstType;
473 aDstType.SetRawPtr( ImplGetScanline( rDst, nY ));
474 ImplConvertLine( aDstType, rSrcLine, std::min( nSrcWidth, rDst.mnWidth ));
475 return true;
476}
477
478template <ScanlineFormat SRCFMT>
479static bool ImplCopyFromScanline( tools::Long nY, BitmapBuffer& rDst, ConstScanline aSrcScanline, tools::Long nSrcWidth )
480{
481 TrueColorPixelPtr<SRCFMT> aSrcType;
482 aSrcType.SetRawPtr( const_cast<Scanline>( aSrcScanline ));
483 // select the matching instantiation for the destination's bitmap format
484 switch( RemoveScanline( rDst.mnFormat ))
485 {
487 return ImplCopyToScanline<ScanlineFormat::N24BitTcBgr>( nY, rDst, aSrcType, nSrcWidth );
489 return ImplCopyToScanline<ScanlineFormat::N24BitTcRgb>( nY, rDst, aSrcType, nSrcWidth );
490
492 return ImplCopyToScanline<ScanlineFormat::N32BitTcAbgr>( nY, rDst, aSrcType, nSrcWidth );
494 return ImplCopyToScanline<ScanlineFormat::N32BitTcArgb>( nY, rDst, aSrcType, nSrcWidth );
496 return ImplCopyToScanline<ScanlineFormat::N32BitTcBgra>( nY, rDst, aSrcType, nSrcWidth );
498 return ImplCopyToScanline<ScanlineFormat::N32BitTcRgba>( nY, rDst, aSrcType, nSrcWidth );
499 default:
500 break;
501 }
502 return false;
503
504}
505
507 ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize)
508{
509 if( rDst.mnHeight <= nY )
510 return false;
511
512 const ScanlineFormat nSrcFormat = RemoveScanline(nSrcScanlineFormat);
513 const ScanlineFormat nDstFormat = RemoveScanline(rDst.mnFormat);
514
515 // special handling of trivial cases
516 if( nSrcFormat == nDstFormat )
517 {
518 memcpy( ImplGetScanline( rDst, nY ), aSrcScanline, std::min<tools::Long>(nSrcScanlineSize, rDst.mnScanlineSize));
519 return true;
520 }
521
522 // select the matching instantiation for the source's bitmap format
523 switch( nSrcFormat )
524 {
526 return ImplCopyFromScanline<ScanlineFormat::N24BitTcBgr>( nY, rDst, aSrcScanline, nSrcScanlineSize / 3 );
528 return ImplCopyFromScanline<ScanlineFormat::N24BitTcRgb>( nY, rDst, aSrcScanline, nSrcScanlineSize / 3 );
529
531 return ImplCopyFromScanline<ScanlineFormat::N32BitTcAbgr>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
533 return ImplCopyFromScanline<ScanlineFormat::N32BitTcArgb>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
535 return ImplCopyFromScanline<ScanlineFormat::N32BitTcBgra>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
537 return ImplCopyFromScanline<ScanlineFormat::N32BitTcRgba>( nY, rDst, aSrcScanline, nSrcScanlineSize / 4 );
538 default:
539 break;
540 }
541 return false;
542}
543
545{
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.mnFormat, rSrc.mnScanlineSize);
551}
552
553template <ScanlineFormat DSTFMT, ScanlineFormat SRCFMT> //,sal_uLong MSKFMT>
554static bool ImplBlendToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
555 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
556 const BitmapBuffer& rMskBuffer )
557{
559 "vcl.gdi", "FastBmp BlendImage: unusual MSKFMT" );
560
561 const int nSrcLinestep = rSrcBuffer.mnScanlineSize;
562 int nMskLinestep = rMskBuffer.mnScanlineSize;
563 int nDstLinestep = rDstBuffer.mnScanlineSize;
564
565 TrueColorPixelPtr<ScanlineFormat::N8BitPal> aMskLine; aMskLine.SetRawPtr( rMskBuffer.mpBits );
566 TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
567
568 // special case for single line masks
569 if( rMskBuffer.mnHeight == 1 )
570 nMskLinestep = 0;
571
572 // source and mask don't match: upside down
573 if( (rSrcBuffer.mnFormat ^ rMskBuffer.mnFormat) & ScanlineFormat::TopDown )
574 {
575 aMskLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nMskLinestep );
576 nMskLinestep = -nMskLinestep;
577 }
578
579 // source and destination don't match: upside down
580 if( (rSrcBuffer.mnFormat ^ rDstBuffer.mnFormat) & ScanlineFormat::TopDown )
581 {
582 aDstLine.AddByteOffset( (rDstBuffer.mnHeight - 1) * nDstLinestep );
583 nDstLinestep = -nDstLinestep;
584 }
585
586 assert(rDstBuffer.mnHeight <= rSrcBuffer.mnHeight && "not sure about that?");
587 for (int y = rDstBuffer.mnHeight; --y >= 0;)
588 {
589 ImplBlendLines(aDstLine, rSrcLine, aMskLine, rDstBuffer.mnWidth);
590 aDstLine.AddByteOffset( nDstLinestep );
591 rSrcLine.AddByteOffset( nSrcLinestep );
592 aMskLine.AddByteOffset( nMskLinestep );
593 }
594
595 return true;
596}
597
598// some specializations to reduce the code size
599template <>
600bool ImplBlendToBitmap<ScanlineFormat::N24BitTcBgr,ScanlineFormat::N24BitTcBgr>(
601 TrueColorPixelPtr<ScanlineFormat::N24BitTcBgr>&,
602 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
603 const BitmapBuffer& rMskBuffer )
604 {
605 TrueColorPixelPtr<ScanlineFormat::N24BitTcRgb> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
606 return ImplBlendToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
607 }
608
609template <>
610bool ImplBlendToBitmap<ScanlineFormat::N32BitTcAbgr,ScanlineFormat::N32BitTcAbgr>(
611 TrueColorPixelPtr<ScanlineFormat::N32BitTcAbgr>&,
612 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
613 const BitmapBuffer& rMskBuffer )
614 {
615 TrueColorPixelPtr<ScanlineFormat::N32BitTcArgb> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
616 return ImplBlendToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
617 }
618
619template <>
620bool ImplBlendToBitmap<ScanlineFormat::N32BitTcBgra,ScanlineFormat::N32BitTcBgra>(
621 TrueColorPixelPtr<ScanlineFormat::N32BitTcBgra>&,
622 BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuffer,
623 const BitmapBuffer& rMskBuffer )
624 {
625 TrueColorPixelPtr<ScanlineFormat::N32BitTcRgba> aSrcType; aSrcType.SetRawPtr( rSrcBuffer.mpBits );
626 return ImplBlendToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDstBuffer, rSrcBuffer, rMskBuffer );
627 }
628
629template <ScanlineFormat SRCFMT>
630static bool ImplBlendFromBitmap( BitmapBuffer& rDst, const BitmapBuffer& rSrc, const BitmapBuffer& rMsk )
631{
632 TrueColorPixelPtr<SRCFMT> aSrcType; aSrcType.SetRawPtr( rSrc.mpBits );
633
634 // select the matching instantiation for the destination's bitmap format
635 switch (RemoveScanline(rDst.mnFormat))
636 {
639 break;
640
642// return ImplBlendToBitmap<ScanlineFormat::N32BitTcMask>( aSrcType, rDst, rSrc, rMsk );
643 break;
644
646 return ImplBlendToBitmap<ScanlineFormat::N24BitTcBgr>( aSrcType, rDst, rSrc, rMsk );
648 return ImplBlendToBitmap<ScanlineFormat::N24BitTcRgb>( aSrcType, rDst, rSrc, rMsk );
649
651 return ImplBlendToBitmap<ScanlineFormat::N32BitTcAbgr>( aSrcType, rDst, rSrc, rMsk );
653 return ImplBlendToBitmap<ScanlineFormat::N32BitTcArgb>( aSrcType, rDst, rSrc, rMsk );
655 return ImplBlendToBitmap<ScanlineFormat::N32BitTcBgra>( aSrcType, rDst, rSrc, rMsk );
657 return ImplBlendToBitmap<ScanlineFormat::N32BitTcRgba>( aSrcType, rDst, rSrc, rMsk );
658 default: break;
659 }
660
661 static int nNotAccelerated = 0;
662 SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
663 "vcl.gdi",
664 "ImplBlendFromBitmap for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "*" << static_cast<int>(rMsk.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) );
665 return false;
666}
667
669 const BitmapReadAccess& rSrcRA, const BitmapReadAccess& rMskRA,
670 const SalTwoRect& rTR )
671{
672 // accelerated blending of paletted bitmaps not implemented yet
673 if( rSrcRA.HasPalette() )
674 return false;
675 if( rDstWA.HasPalette() )
676 return false;
677 // TODO: either get rid of mask's use of 8BIT_PAL or check the palette
678
679 // horizontal mirroring not implemented yet
680 if( rTR.mnDestWidth < 0 )
681 return false;
682 // vertical mirroring
683 if( rTR.mnDestHeight < 0 )
684 // TODO: rDst.mnFormat ^= ScanlineFormat::TopDown;
685 return false;
686
687 // offsetted blending is not implemented yet
688 if( rTR.mnSrcX || rTR.mnSrcY )
689 return false;
690 if( rTR.mnDestX || rTR.mnDestY )
691 return false;
692
693 // stretched blending is not implemented yet
694 if( rTR.mnDestWidth != rTR.mnSrcWidth )
695 return false;
696 if( rTR.mnDestHeight!= rTR.mnSrcHeight )
697 return false;
698
699 // check source image size
700 if( rSrcRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
701 return false;
702 if( rSrcRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
703 return false;
704
705 // check mask image size
706 if( rMskRA.Width() < rTR.mnSrcX + rTR.mnSrcWidth )
707 return false;
708 if( rMskRA.Height() < rTR.mnSrcY + rTR.mnSrcHeight )
709 if( rMskRA.Height() != 1 )
710 return false;
711
712 // check dest image size
713 if( rDstWA.Width() < rTR.mnDestX + rTR.mnDestWidth )
714 return false;
715 if( rDstWA.Height() < rTR.mnDestY + rTR.mnDestHeight )
716 return false;
717
718 BitmapBuffer& rDst = *rDstWA.ImplGetBitmapBuffer();
719 const BitmapBuffer& rSrc = *rSrcRA.ImplGetBitmapBuffer();
720 const BitmapBuffer& rMsk = *rMskRA.ImplGetBitmapBuffer();
721
722 const ScanlineFormat nSrcFormat = RemoveScanline(rSrc.mnFormat);
723
724 // select the matching instantiation for the source's bitmap format
725 switch( nSrcFormat )
726 {
728 break;
729
731// return ImplBlendFromBitmap<ScanlineFormat::N32BitTcMask>( rDst, rSrc );
732 break;
733
736 return ImplBlendFromBitmap<ScanlineFormat::N8BitPal>( rDst, rSrc, rMsk );
737 break;
738
740 return ImplBlendFromBitmap<ScanlineFormat::N24BitTcBgr>( rDst, rSrc, rMsk );
742 return ImplBlendFromBitmap<ScanlineFormat::N24BitTcRgb>( rDst, rSrc, rMsk );
743
745 return ImplBlendFromBitmap<ScanlineFormat::N32BitTcAbgr>( rDst, rSrc, rMsk );
747 return ImplBlendFromBitmap<ScanlineFormat::N32BitTcArgb>( rDst, rSrc, rMsk );
749 return ImplBlendFromBitmap<ScanlineFormat::N32BitTcBgra>( rDst, rSrc, rMsk );
751 return ImplBlendFromBitmap<ScanlineFormat::N32BitTcRgba>( rDst, rSrc, rMsk );
752 default: break;
753 }
754
755 static int nNotAccelerated = 0;
756 SAL_WARN_IF( rSrc.mnWidth * rSrc.mnHeight >= 4000 && ++nNotAccelerated == 100,
757 "vcl.gdi",
758 "ImplFastBlend for not accelerated case (" << std::hex << static_cast<int>(rSrc.mnFormat) << "*" << static_cast<int>(rMsk.mnFormat) << "->" << static_cast<int>(rDst.mnFormat) << ")" );
759
760 return false;
761}
762
763bool ImplFastEraseBitmap( BitmapBuffer& rDst, const BitmapColor& rColor )
764{
765 const ScanlineFormat nDstFormat = RemoveScanline(rDst.mnFormat);
766
767 // erasing a bitmap is often just a byte-wise memory fill
768 bool bByteFill = true;
769 sal_uInt8 nFillByte;
770
771 switch( nDstFormat )
772 {
774 nFillByte = rColor.GetIndex();
775 nFillByte = static_cast<sal_uInt8>( -(nFillByte & 1) ); // 0x00 or 0xFF
776 break;
778 nFillByte = rColor.GetIndex();
779 break;
780
783 nFillByte = rColor.GetRed();
784 if( (nFillByte != rColor.GetGreen())
785 || (nFillByte != rColor.GetBlue()) )
786 bByteFill = false;
787 break;
788
789 default:
790 bByteFill = false;
791 nFillByte = 0x00;
792 break;
793 }
794
795 if( bByteFill )
796 {
797 tools::Long nByteCount = rDst.mnHeight * rDst.mnScanlineSize;
798 memset( rDst.mpBits, nFillByte, nByteCount );
799 return true;
800 }
801
802 // TODO: handle other bitmap formats
803 switch( nDstFormat )
804 {
806
809
814 break;
815
816 default:
817 break;
818 }
819
820 return false;
821}
822
823/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const sal_uInt8 * ConstScanline
Definition: Scanline.hxx:27
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
ScanlineFormat
Definition: Scanline.hxx:29
ScanlineFormat RemoveScanline(ScanlineFormat nFormat)
Definition: Scanline.hxx:53
static bool ImplCopyImage(BitmapBuffer &rDstBuffer, const BitmapBuffer &rSrcBuffer)
Definition: bmpfast.cxx:263
bool ImplFastEraseBitmap(BitmapBuffer &rDst, const BitmapColor &rColor)
Definition: bmpfast.cxx:763
static bool ImplCopyToScanline(tools::Long nY, BitmapBuffer &rDst, TrueColorPixelPtr< SRCFMT > &rSrcLine, tools::Long nSrcWidth)
Definition: bmpfast.cxx:470
static bool ImplCopyFromScanline(tools::Long nY, BitmapBuffer &rDst, ConstScanline aSrcScanline, tools::Long nSrcWidth)
Definition: bmpfast.cxx:479
bool ImplFastBitmapBlending(BitmapWriteAccess const &rDstWA, const BitmapReadAccess &rSrcRA, const BitmapReadAccess &rMskRA, const SalTwoRect &rTR)
Definition: bmpfast.cxx:668
static void ImplConvertPixel(const TrueColorPixelPtr< DSTFMT > &rDst, const TrueColorPixelPtr< SRCFMT > &rSrc)
Definition: bmpfast.cxx:196
static void ImplBlendLines(const TrueColorPixelPtr< DSTFMT > &rDst, const TrueColorPixelPtr< SRCFMT > &rSrc, const TrueColorPixelPtr< MASKFMT > &rMsk, int nPixelCount)
Definition: bmpfast.cxx:246
static bool ImplBlendToBitmap(TrueColorPixelPtr< SRCFMT > &rSrcLine, BitmapBuffer &rDstBuffer, const BitmapBuffer &rSrcBuffer, const BitmapBuffer &rMskBuffer)
Definition: bmpfast.cxx:554
static bool ImplConvertFromBitmap(BitmapBuffer &rDst, const BitmapBuffer &rSrc)
Definition: bmpfast.cxx:329
static bool ImplBlendFromBitmap(BitmapBuffer &rDst, const BitmapBuffer &rSrc, const BitmapBuffer &rMsk)
Definition: bmpfast.cxx:630
unsigned char PIXBYTE
Definition: bmpfast.cxx:27
static void ImplBlendPixels(const TrueColorPixelPtr< DSTFMT > &rDst, const TrueColorPixelPtr< SRCFMT > &rSrc, unsigned nAlphaVal)
Definition: bmpfast.cxx:219
bool ImplFastBitmapConversion(BitmapBuffer &rDst, const BitmapBuffer &rSrc, const SalTwoRect &rTR)
Definition: bmpfast.cxx:370
static ConstScanline ImplGetScanline(const BitmapBuffer &rBuf, tools::Long nY)
Definition: bmpfast.cxx:456
static bool ImplConvertToBitmap(TrueColorPixelPtr< SRCFMT > &rSrcLine, BitmapBuffer &rDstBuffer, const BitmapBuffer &rSrcBuffer)
Definition: bmpfast.cxx:298
static void ImplConvertLine(const TrueColorPixelPtr< DSTFMT > &rDst, const TrueColorPixelPtr< SRCFMT > &rSrc, int nPixelCount)
Definition: bmpfast.cxx:204
bool ImplFastCopyScanline(tools::Long nY, BitmapBuffer &rDst, ConstScanline aSrcScanline, ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize)
Definition: bmpfast.cxx:506
sal_uInt8 GetIndex() const
Definition: BitmapColor.hxx:70
tools::Long Height() const
tools::Long Width() const
bool HasPalette() const
bool IsGreyPalette8Bit() const
Returns true if the palette is 8-bit grey palette.
BitmapBuffer * ImplGetBitmapBuffer() const
sal_uInt8 GetBlue() const
sal_uInt8 GetRed() const
sal_uInt8 GetGreen() const
float y
SotClipboardFormatId & operator++(SotClipboardFormatId &eFormat)
void * p
uno_Any a
#define SAL_WARN_IF(condition, area, stream)
long Long
BitmapPalette maPalette
tools::Long mnWidth
sal_uInt8 * mpBits
tools::Long mnScanlineSize
ScanlineFormat mnFormat
tools::Long mnHeight
tools::Long mnDestY
Definition: salgtype.hxx:44
tools::Long mnSrcX
Definition: salgtype.hxx:39
tools::Long mnDestWidth
Definition: salgtype.hxx:45
tools::Long mnSrcHeight
Definition: salgtype.hxx:42
tools::Long mnSrcWidth
Definition: salgtype.hxx:41
tools::Long mnSrcY
Definition: salgtype.hxx:40
tools::Long mnDestHeight
Definition: salgtype.hxx:46
tools::Long mnDestX
Definition: salgtype.hxx:43
unsigned char sal_uInt8