xref: /trunk/main/vcl/source/gdi/bitmapex.cxx (revision 479f2b27)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include <ctype.h>
28 
29 #include <rtl/crc.h>
30 
31 #include <tools/stream.hxx>
32 #include <tools/debug.hxx>
33 #include <tools/rc.h>
34 
35 #include <vcl/salbtype.hxx>
36 #include <vcl/outdev.hxx>
37 #include <vcl/alpha.hxx>
38 #include <vcl/bitmapex.hxx>
39 #include <vcl/pngread.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/bmpacc.hxx>
42 
43 #include <image.h>
44 #include <impimagetree.hxx>
45 
46 // ------------
47 // - BitmapEx -
48 // ------------
49 
50 BitmapEx::BitmapEx() :
51 		eTransparent( TRANSPARENT_NONE ),
52 		bAlpha		( sal_False )
53 {
54 }
55 
56 // ------------------------------------------------------------------
57 
58 BitmapEx::BitmapEx( const BitmapEx& rBitmapEx ) :
59 		aBitmap				( rBitmapEx.aBitmap ),
60 		aMask				( rBitmapEx.aMask ),
61 		aBitmapSize			( rBitmapEx.aBitmapSize ),
62 		aTransparentColor	( rBitmapEx.aTransparentColor ),
63 		eTransparent		( rBitmapEx.eTransparent ),
64 		bAlpha				( rBitmapEx.bAlpha )
65 {
66 }
67 
68 BitmapEx::BitmapEx( const BitmapEx& rBitmapEx, Point aSrc, Size aSize ) :
69 		eTransparent( TRANSPARENT_NONE ),
70 		bAlpha		( sal_False )
71 {
72 	if( rBitmapEx.IsEmpty() )
73 		return;
74 
75 	aBitmap = Bitmap( aSize, rBitmapEx.aBitmap.GetBitCount() );
76 	aBitmapSize = aSize;
77 	if( rBitmapEx.IsAlpha() )
78 	{
79 		bAlpha = sal_True;
80 		aMask = AlphaMask( aSize ).ImplGetBitmap();
81 	}
82 	else if( rBitmapEx.IsTransparent() )
83 		aMask = Bitmap( aSize, rBitmapEx.aMask.GetBitCount() );
84 
85 	Rectangle aDestRect( Point( 0, 0 ), aSize );
86 	Rectangle aSrcRect( aSrc, aSize );
87 	CopyPixel( aDestRect, aSrcRect, &rBitmapEx );
88 }
89 
90 // ------------------------------------------------------------------
91 
92 BitmapEx::BitmapEx( const ResId& rResId ) :
93 		eTransparent( TRANSPARENT_NONE ),
94 		bAlpha		( sal_False )
95 {
96 	static ImplImageTreeSingletonRef	aImageTree;
97 	ResMgr* 							pResMgr = NULL;
98 
99 	ResMgr::GetResourceSkipHeader( rResId.SetRT( RSC_BITMAP ), &pResMgr );
100 	pResMgr->ReadLong();
101 	pResMgr->ReadLong();
102 
103 	const String aFileName( pResMgr->ReadString() );
104 	::rtl::OUString aCurrentSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName();
105 
106 	if( !aImageTree->loadImage( aFileName, aCurrentSymbolsStyle, *this ) )
107 	{
108 #ifdef DBG_UTIL
109 		ByteString aErrorStr( "BitmapEx::BitmapEx( const ResId& rResId ): could not load image <" );
110 		DBG_ERROR( ( ( aErrorStr += ByteString( aFileName, RTL_TEXTENCODING_ASCII_US ) ) += '>' ).GetBuffer() );
111 #endif
112 	}
113 }
114 
115 // ------------------------------------------------------------------
116 
117 BitmapEx::BitmapEx( const Bitmap& rBmp ) :
118 		aBitmap		( rBmp ),
119 		aBitmapSize	( aBitmap.GetSizePixel() ),
120 		eTransparent( TRANSPARENT_NONE ),
121 		bAlpha		( sal_False )
122 {
123 }
124 
125 // ------------------------------------------------------------------
126 
127 BitmapEx::BitmapEx( const Bitmap& rBmp, const Bitmap& rMask ) :
128 		aBitmap			( rBmp ),
129 		aMask			( rMask ),
130 		aBitmapSize		( aBitmap.GetSizePixel() ),
131 		eTransparent	( !rMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
132 		bAlpha			( sal_False )
133 {
134     if(!rMask)
135     {
136         OSL_ENSURE(false, "Empty mask given (!)");
137     }
138     else if(rBmp.GetSizePixel() != rMask.GetSizePixel())
139     {
140         OSL_ENSURE(false, "Mask size differs from Bitmap size, corrected Mask (!)");
141         aMask.Scale(rBmp.GetSizePixel());
142     }
143 
144     // #105489# Ensure a mask is exactly one bit deep
145     if( !!aMask && aMask.GetBitCount() != 1 )
146     {
147         OSL_TRACE("BitmapEx: forced mask to monochrome");
148         aMask.ImplMakeMono( 255 );
149     }
150 }
151 
152 // ------------------------------------------------------------------
153 
154 BitmapEx::BitmapEx( const Bitmap& rBmp, const AlphaMask& rAlphaMask ) :
155 		aBitmap			( rBmp ),
156 		aMask			( rAlphaMask.ImplGetBitmap() ),
157 		aBitmapSize		( aBitmap.GetSizePixel() ),
158 		eTransparent	( !rAlphaMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
159 		bAlpha			( !rAlphaMask ? sal_False : sal_True )
160 {
161     if(!rAlphaMask)
162     {
163         OSL_ENSURE(false, "Empty alpha given (!)");
164     }
165     else if(rBmp.GetSizePixel() != rAlphaMask.GetSizePixel())
166     {
167         OSL_ENSURE(false, "Alpha size differs from Bitmap size, corrected Mask (!)");
168         aMask.Scale(rBmp.GetSizePixel());
169     }
170 
171     // #i75531# the workaround below can go when
172     // X11SalGraphics::drawAlphaBitmap()'s render acceleration
173     // can handle the bitmap depth mismatch directly
174     if( aBitmap.GetBitCount() < aMask.GetBitCount() )
175         aBitmap.Convert( BMP_CONVERSION_24BIT );
176 }
177 
178 // ------------------------------------------------------------------
179 
180 BitmapEx::BitmapEx( const Bitmap& rBmp, const Color& rTransparentColor ) :
181 		aBitmap				( rBmp ),
182 		aBitmapSize			( aBitmap.GetSizePixel() ),
183 		aTransparentColor	( rTransparentColor ),
184 		eTransparent		( TRANSPARENT_BITMAP ),
185 		bAlpha				( sal_False )
186 {
187 	aMask = aBitmap.CreateMask( aTransparentColor );
188 
189     DBG_ASSERT( rBmp.GetSizePixel() == aMask.GetSizePixel(),
190                 "BitmapEx::BitmapEx(): size mismatch for bitmap and alpha mask." );
191 }
192 
193 // ------------------------------------------------------------------
194 
195 BitmapEx::~BitmapEx()
196 {
197 }
198 
199 // ------------------------------------------------------------------
200 
201 // ------------------------------------------------------------------
202 
203 BitmapEx& BitmapEx::operator=( const BitmapEx& rBitmapEx )
204 {
205 	if( &rBitmapEx != this )
206 	{
207 		aBitmap = rBitmapEx.aBitmap;
208 		aMask = rBitmapEx.aMask;
209 		aBitmapSize = rBitmapEx.aBitmapSize;
210 		aTransparentColor = rBitmapEx.aTransparentColor;
211 		eTransparent = rBitmapEx.eTransparent;
212 		bAlpha = rBitmapEx.bAlpha;
213 	}
214 
215 	return *this;
216 }
217 
218 // ------------------------------------------------------------------
219 
220 sal_Bool BitmapEx::operator==( const BitmapEx& rBitmapEx ) const
221 {
222 	if( eTransparent != rBitmapEx.eTransparent )
223 		return sal_False;
224 
225 	if( aBitmap != rBitmapEx.aBitmap )
226 		return sal_False;
227 
228 	if( aBitmapSize != rBitmapEx.aBitmapSize )
229 		return sal_False;
230 
231 	if( eTransparent == TRANSPARENT_NONE )
232 		return sal_True;
233 
234 	if( eTransparent == TRANSPARENT_COLOR )
235 		return aTransparentColor == rBitmapEx.aTransparentColor;
236 
237 	return( ( aMask == rBitmapEx.aMask ) && ( bAlpha == rBitmapEx.bAlpha ) );
238 }
239 
240 // ------------------------------------------------------------------
241 
242 sal_Bool BitmapEx::IsEqual( const BitmapEx& rBmpEx ) const
243 {
244 	return( rBmpEx.eTransparent == eTransparent &&
245 			rBmpEx.bAlpha == bAlpha &&
246 			rBmpEx.aBitmap.IsEqual( aBitmap ) &&
247 			rBmpEx.aMask.IsEqual( aMask ) );
248 }
249 
250 // ------------------------------------------------------------------
251 
252 sal_Bool BitmapEx::IsEmpty() const
253 {
254 	return( aBitmap.IsEmpty() && aMask.IsEmpty() );
255 }
256 
257 // ------------------------------------------------------------------
258 
259 void BitmapEx::SetEmpty()
260 {
261 	aBitmap.SetEmpty();
262 	aMask.SetEmpty();
263 	eTransparent = TRANSPARENT_NONE;
264 	bAlpha = sal_False;
265 }
266 
267 // ------------------------------------------------------------------
268 
269 void BitmapEx::Clear()
270 {
271 	SetEmpty();
272 }
273 
274 // ------------------------------------------------------------------
275 
276 sal_Bool BitmapEx::IsTransparent() const
277 {
278 	return( eTransparent != TRANSPARENT_NONE );
279 }
280 
281 // ------------------------------------------------------------------
282 
283 sal_Bool BitmapEx::IsAlpha() const
284 {
285 	return( IsTransparent() && bAlpha );
286 }
287 
288 // ------------------------------------------------------------------
289 
290 Bitmap BitmapEx::GetBitmap( const Color* pTransReplaceColor ) const
291 {
292 	Bitmap aRetBmp( aBitmap );
293 
294 	if( pTransReplaceColor && ( eTransparent != TRANSPARENT_NONE ) )
295 	{
296 		Bitmap aTempMask;
297 
298 		if( eTransparent == TRANSPARENT_COLOR )
299 			aTempMask = aBitmap.CreateMask( aTransparentColor );
300 		else
301 			aTempMask = aMask;
302 
303 		if( !IsAlpha() )
304 			aRetBmp.Replace( aTempMask, *pTransReplaceColor );
305 		else
306 			aRetBmp.Replace( GetAlpha(), *pTransReplaceColor );
307 	}
308 
309 	return aRetBmp;
310 }
311 
312 // ------------------------------------------------------------------
313 
314 BitmapEx BitmapEx::GetColorTransformedBitmapEx( BmpColorMode eColorMode ) const
315 {
316 	BitmapEx aRet;
317 
318 	if( BMP_COLOR_HIGHCONTRAST == eColorMode )
319 	{
320 		aRet = *this;
321 		aRet.aBitmap = aBitmap.GetColorTransformedBitmap( eColorMode );
322 	}
323 	else if( BMP_COLOR_MONOCHROME_BLACK == eColorMode ||
324 			 BMP_COLOR_MONOCHROME_WHITE == eColorMode )
325 	{
326 		aRet = *this;
327 		aRet.aBitmap = aRet.aBitmap.GetColorTransformedBitmap( eColorMode );
328 
329 		if( !aRet.aMask.IsEmpty() )
330 		{
331 			aRet.aMask.CombineSimple( aRet.aBitmap, BMP_COMBINE_OR );
332 			aRet.aBitmap.Erase( ( BMP_COLOR_MONOCHROME_BLACK == eColorMode ) ? COL_BLACK : COL_WHITE );
333 
334             DBG_ASSERT( aRet.aBitmap.GetSizePixel() == aRet.aMask.GetSizePixel(),
335                         "BitmapEx::GetColorTransformedBitmapEx(): size mismatch for bitmap and alpha mask." );
336 		}
337 	}
338 
339 	return aRet;
340 }
341 
342 // ------------------------------------------------------------------
343 
344 Bitmap BitmapEx::GetMask() const
345 {
346 	Bitmap aRet( aMask );
347 
348 	if( IsAlpha() )
349 		aRet.ImplMakeMono( 255 );
350 
351 	return aRet;
352 }
353 
354 // ------------------------------------------------------------------
355 
356 AlphaMask BitmapEx::GetAlpha() const
357 {
358 	AlphaMask aAlpha;
359 
360 	if( IsAlpha() )
361 		aAlpha.ImplSetBitmap( aMask );
362 	else
363 		aAlpha = aMask;
364 
365 	return aAlpha;
366 }
367 
368 // ------------------------------------------------------------------
369 
370 sal_uLong BitmapEx::GetSizeBytes() const
371 {
372 	sal_uLong nSizeBytes = aBitmap.GetSizeBytes();
373 
374 	if( eTransparent == TRANSPARENT_BITMAP )
375 		nSizeBytes += aMask.GetSizeBytes();
376 
377 	return nSizeBytes;
378 }
379 
380 // ------------------------------------------------------------------
381 
382 sal_uLong BitmapEx::GetChecksum() const
383 {
384 	sal_uInt32	nCrc = aBitmap.GetChecksum();
385 	SVBT32		aBT32;
386 
387 	UInt32ToSVBT32( (long) eTransparent, aBT32 );
388 	nCrc = rtl_crc32( nCrc, aBT32, 4 );
389 
390 	UInt32ToSVBT32( (long) bAlpha, aBT32 );
391 	nCrc = rtl_crc32( nCrc, aBT32, 4 );
392 
393 	if( ( TRANSPARENT_BITMAP == eTransparent ) && !aMask.IsEmpty() )
394 	{
395 		UInt32ToSVBT32( aMask.GetChecksum(), aBT32 );
396 		nCrc = rtl_crc32( nCrc, aBT32, 4 );
397 	}
398 
399 	return nCrc;
400 }
401 
402 // ------------------------------------------------------------------
403 
404 void BitmapEx::SetSizePixel( const Size& rNewSize )
405 {
406 	Scale( rNewSize );
407 }
408 
409 // ------------------------------------------------------------------
410 
411 sal_Bool BitmapEx::Invert()
412 {
413 	sal_Bool bRet = sal_False;
414 
415 	if( !!aBitmap )
416 	{
417 		bRet = aBitmap.Invert();
418 
419 		if( bRet && ( eTransparent == TRANSPARENT_COLOR ) )
420 			aTransparentColor = BitmapColor( aTransparentColor ).Invert();
421 	}
422 
423 	return bRet;
424 }
425 
426 // ------------------------------------------------------------------
427 
428 sal_Bool BitmapEx::Mirror( sal_uLong nMirrorFlags )
429 {
430 	sal_Bool bRet = sal_False;
431 
432 	if( !!aBitmap )
433 	{
434 		bRet = aBitmap.Mirror( nMirrorFlags );
435 
436 		if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
437 			aMask.Mirror( nMirrorFlags );
438 	}
439 
440 	return bRet;
441 }
442 
443 // ------------------------------------------------------------------
444 
445 sal_Bool BitmapEx::Scale( const double& rScaleX, const double& rScaleY, sal_uLong nScaleFlag )
446 {
447 	sal_Bool bRet = sal_False;
448 
449 	if( !!aBitmap )
450 	{
451 		bRet = aBitmap.Scale( rScaleX, rScaleY, nScaleFlag );
452 
453 		if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
454 			aMask.Scale( rScaleX, rScaleY, BMP_SCALE_FAST );
455 
456 		aBitmapSize = aBitmap.GetSizePixel();
457 
458         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
459                     "BitmapEx::Scale(): size mismatch for bitmap and alpha mask." );
460 	}
461 
462 	return bRet;
463 }
464 
465 // ------------------------------------------------------------------------
466 
467 sal_Bool BitmapEx::Scale( const Size& rNewSize, sal_uLong nScaleFlag )
468 {
469 	sal_Bool bRet;
470 
471 	if( aBitmapSize.Width() && aBitmapSize.Height() )
472 	{
473 		bRet = Scale( (double) rNewSize.Width() / aBitmapSize.Width(),
474 					  (double) rNewSize.Height() / aBitmapSize.Height(),
475 					  nScaleFlag );
476 	}
477 	else
478 		bRet = sal_True;
479 
480 	return bRet;
481 }
482 
483 // ------------------------------------------------------------------
484 
485 sal_Bool BitmapEx::Rotate( long nAngle10, const Color& rFillColor )
486 {
487 	sal_Bool bRet = sal_False;
488 
489 	if( !!aBitmap )
490 	{
491 		const sal_Bool bTransRotate = ( Color( COL_TRANSPARENT ) == rFillColor );
492 
493 		if( bTransRotate )
494 		{
495 			if( eTransparent == TRANSPARENT_COLOR )
496 				bRet = aBitmap.Rotate( nAngle10, aTransparentColor );
497 			else
498 			{
499 				bRet = aBitmap.Rotate( nAngle10, COL_BLACK );
500 
501 				if( eTransparent == TRANSPARENT_NONE )
502 				{
503 					aMask = Bitmap( aBitmapSize, 1 );
504 					aMask.Erase( COL_BLACK );
505 					eTransparent = TRANSPARENT_BITMAP;
506 				}
507 
508 				if( bRet && !!aMask )
509 					aMask.Rotate( nAngle10, COL_WHITE );
510 			}
511 		}
512 		else
513 		{
514 			bRet = aBitmap.Rotate( nAngle10, rFillColor );
515 
516 			if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
517 				aMask.Rotate( nAngle10, COL_WHITE );
518 		}
519 
520 		aBitmapSize = aBitmap.GetSizePixel();
521 
522         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
523                     "BitmapEx::Rotate(): size mismatch for bitmap and alpha mask." );
524 	}
525 
526 	return bRet;
527 }
528 
529 // ------------------------------------------------------------------
530 
531 sal_Bool BitmapEx::Crop( const Rectangle& rRectPixel )
532 {
533 	sal_Bool bRet = sal_False;
534 
535 	if( !!aBitmap )
536 	{
537 		bRet = aBitmap.Crop( rRectPixel );
538 
539 		if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
540 			aMask.Crop( rRectPixel );
541 
542 		aBitmapSize = aBitmap.GetSizePixel();
543 
544         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
545                     "BitmapEx::Crop(): size mismatch for bitmap and alpha mask." );
546 	}
547 
548 	return bRet;
549 }
550 
551 // ------------------------------------------------------------------
552 
553 sal_Bool BitmapEx::Convert( BmpConversion eConversion )
554 {
555 	return( !!aBitmap ? aBitmap.Convert( eConversion ) : sal_False );
556 }
557 
558 // ------------------------------------------------------------------
559 
560 sal_Bool BitmapEx::ReduceColors( sal_uInt16 nNewColorCount, BmpReduce eReduce )
561 {
562 	return( !!aBitmap ? aBitmap.ReduceColors( nNewColorCount, eReduce ) : sal_False );
563 }
564 
565 // ------------------------------------------------------------------
566 
567 sal_Bool BitmapEx::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor, sal_Bool bExpandTransparent )
568 {
569 	sal_Bool bRet = sal_False;
570 
571 	if( !!aBitmap )
572 	{
573 		bRet = aBitmap.Expand( nDX, nDY, pInitColor );
574 
575 		if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
576 		{
577 			Color aColor( bExpandTransparent ? COL_WHITE : COL_BLACK );
578 			aMask.Expand( nDX, nDY, &aColor );
579 		}
580 
581 		aBitmapSize = aBitmap.GetSizePixel();
582 
583         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
584                     "BitmapEx::Expand(): size mismatch for bitmap and alpha mask." );
585 	}
586 
587 	return bRet;
588 }
589 
590 // ------------------------------------------------------------------
591 
592 sal_Bool BitmapEx::CopyPixel( const Rectangle& rRectDst, const Rectangle& rRectSrc,
593 						  const BitmapEx* pBmpExSrc )
594 {
595 	sal_Bool bRet = sal_False;
596 
597 	if( !pBmpExSrc || pBmpExSrc->IsEmpty() )
598 	{
599 		if( !aBitmap.IsEmpty() )
600 		{
601 			bRet = aBitmap.CopyPixel( rRectDst, rRectSrc );
602 
603 			if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
604 				aMask.CopyPixel( rRectDst, rRectSrc );
605 		}
606 	}
607 	else
608 	{
609 		if( !aBitmap.IsEmpty() )
610 		{
611 			bRet = aBitmap.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aBitmap );
612 
613 			if( bRet )
614 			{
615 				if( pBmpExSrc->IsAlpha() )
616 				{
617 					if( IsAlpha() )
618                         // cast to use the optimized AlphaMask::CopyPixel
619 						((AlphaMask*) &aMask)->CopyPixel( rRectDst, rRectSrc, (AlphaMask*)&pBmpExSrc->aMask );
620 					else if( IsTransparent() )
621 					{
622 						AlphaMask* pAlpha = new AlphaMask( aMask );
623 
624 						aMask = pAlpha->ImplGetBitmap();
625 						delete pAlpha;
626 						bAlpha = sal_True;
627 						aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
628 					}
629 					else
630 					{
631 						sal_uInt8	cBlack = 0;
632 						AlphaMask*	pAlpha = new AlphaMask( GetSizePixel(), &cBlack );
633 
634 						aMask = pAlpha->ImplGetBitmap();
635 						delete pAlpha;
636 						eTransparent = TRANSPARENT_BITMAP;
637 						bAlpha = sal_True;
638 						aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
639 					}
640 				}
641 				else if( pBmpExSrc->IsTransparent() )
642 				{
643 					if( IsAlpha() )
644 					{
645 						AlphaMask aAlpha( pBmpExSrc->aMask );
646 						aMask.CopyPixel( rRectDst, rRectSrc, &aAlpha.ImplGetBitmap() );
647 					}
648 					else if( IsTransparent() )
649 						aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
650 					else
651 					{
652 						aMask = Bitmap( GetSizePixel(), 1 );
653 						aMask.Erase( Color( COL_BLACK ) );
654 						eTransparent = TRANSPARENT_BITMAP;
655 						aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
656 					}
657 				}
658                 else if( IsAlpha() )
659                 {
660                     sal_uInt8	      cBlack = 0;
661                     const AlphaMask   aAlphaSrc( pBmpExSrc->GetSizePixel(), &cBlack );
662 
663                     aMask.CopyPixel( rRectDst, rRectSrc, &aAlphaSrc.ImplGetBitmap() );
664                 }
665                 else if( IsTransparent() )
666                 {
667                     Bitmap aMaskSrc( pBmpExSrc->GetSizePixel(), 1 );
668 
669                     aMaskSrc.Erase( Color( COL_BLACK ) );
670                     aMask.CopyPixel( rRectDst, rRectSrc, &aMaskSrc );
671                 }
672 			}
673 		}
674 	}
675 
676 	return bRet;
677 }
678 
679 // ------------------------------------------------------------------
680 
681 sal_Bool BitmapEx::Erase( const Color& rFillColor )
682 {
683 	sal_Bool bRet = sal_False;
684 
685 	if( !!aBitmap )
686 	{
687 		bRet = aBitmap.Erase( rFillColor );
688 
689 		if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
690 		{
691             // #104416# Respect transparency on fill color
692             if( rFillColor.GetTransparency() )
693             {
694                 const Color aFill( rFillColor.GetTransparency(), rFillColor.GetTransparency(), rFillColor.GetTransparency() );
695                 aMask.Erase( aFill );
696             }
697             else
698             {
699                 const Color aBlack( COL_BLACK );
700                 aMask.Erase( aBlack );
701             }
702 		}
703 	}
704 
705 	return bRet;
706 }
707 
708 // ------------------------------------------------------------------
709 
710 sal_Bool BitmapEx::Dither( sal_uLong nDitherFlags )
711 {
712 	return( !!aBitmap ? aBitmap.Dither( nDitherFlags ) : sal_False );
713 }
714 
715 // ------------------------------------------------------------------
716 
717 sal_Bool BitmapEx::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol )
718 {
719 	return( !!aBitmap ? aBitmap.Replace( rSearchColor, rReplaceColor, nTol ) : sal_False );
720 }
721 
722 // ------------------------------------------------------------------
723 
724 sal_Bool BitmapEx::Replace( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount, const sal_uLong* pTols )
725 {
726 	return( !!aBitmap ? aBitmap.Replace( pSearchColors, pReplaceColors, nColorCount, (sal_uLong*) pTols ) : sal_False );
727 }
728 
729 // ------------------------------------------------------------------
730 
731 sal_Bool BitmapEx::Adjust( short nLuminancePercent, short nContrastPercent,
732 					   short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
733 					   double fGamma, sal_Bool bInvert )
734 {
735 	return( !!aBitmap ? aBitmap.Adjust( nLuminancePercent, nContrastPercent,
736 										nChannelRPercent, nChannelGPercent, nChannelBPercent,
737 										fGamma, bInvert ) : sal_False );
738 }
739 
740 // ------------------------------------------------------------------
741 
742 sal_Bool BitmapEx::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
743 {
744 	return( !!aBitmap ? aBitmap.Filter( eFilter, pFilterParam, pProgress ) : sal_False );
745 }
746 
747 // ------------------------------------------------------------------
748 
749 void BitmapEx::Draw( OutputDevice* pOutDev, const Point& rDestPt ) const
750 {
751 	pOutDev->DrawBitmapEx( rDestPt, *this );
752 }
753 
754 // ------------------------------------------------------------------
755 
756 void BitmapEx::Draw( OutputDevice* pOutDev,
757 					 const Point& rDestPt, const Size& rDestSize ) const
758 {
759 	pOutDev->DrawBitmapEx( rDestPt, rDestSize, *this );
760 }
761 
762 // ------------------------------------------------------------------
763 
764 void BitmapEx::Draw( OutputDevice* pOutDev,
765 					 const Point& rDestPt, const Size& rDestSize,
766 					 const Point& rSrcPtPixel, const Size& rSrcSizePixel ) const
767 {
768 	pOutDev->DrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, *this );
769 }
770 
771 // ------------------------------------------------------------------
772 
773 sal_uInt8 BitmapEx::GetTransparency(sal_Int32 nX, sal_Int32 nY) const
774 {
775     sal_uInt8 nTransparency(0xff);
776 
777     if(!aBitmap.IsEmpty())
778     {
779         if(nX >= 0 && nX < aBitmapSize.Width() && nY >= 0 && nY < aBitmapSize.Height())
780         {
781             switch(eTransparent)
782             {
783                 case TRANSPARENT_NONE:
784                 {
785                     // not transparent, ergo all covered
786                     nTransparency = 0x00;
787                     break;
788                 }
789                 case TRANSPARENT_COLOR:
790                 {
791                     Bitmap aTestBitmap(aBitmap);
792                     BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess();
793 
794                     if(pRead)
795                     {
796                         const Color aColor = pRead->GetColor(nY, nX);
797 
798                         // if color is not equal to TransparentColor, we are not transparent
799                         if(aColor != aTransparentColor)
800                         {
801                             nTransparency = 0x00;
802                         }
803 
804                         aTestBitmap.ReleaseAccess(pRead);
805                     }
806                     break;
807                 }
808                 case TRANSPARENT_BITMAP:
809                 {
810                     if(!aMask.IsEmpty())
811                     {
812                         Bitmap aTestBitmap(aMask);
813                         BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess();
814 
815                         if(pRead)
816                         {
817                             const BitmapColor aBitmapColor(pRead->GetPixel(nY, nX));
818 
819                             if(bAlpha)
820                             {
821                                 nTransparency = aBitmapColor.GetIndex();
822                             }
823                             else
824                             {
825                                 if(0x00 == aBitmapColor.GetIndex())
826                                 {
827                                     nTransparency = 0x00;
828                                 }
829                             }
830 
831                             aTestBitmap.ReleaseAccess(pRead);
832                         }
833                     }
834                     break;
835                 }
836             }
837         }
838     }
839 
840     return nTransparency;
841 }
842 
843 // ------------------------------------------------------------------
844 
845 SvStream& operator<<( SvStream& rOStm, const BitmapEx& rBitmapEx )
846 {
847 	rBitmapEx.aBitmap.Write( rOStm );
848 
849 	rOStm << (sal_uInt32) 0x25091962;
850 	rOStm << (sal_uInt32) 0xACB20201;
851 	rOStm << (sal_uInt8) rBitmapEx.eTransparent;
852 
853 	if( rBitmapEx.eTransparent == TRANSPARENT_BITMAP )
854 		rBitmapEx.aMask.Write( rOStm );
855 	else if( rBitmapEx.eTransparent == TRANSPARENT_COLOR )
856 		rOStm << rBitmapEx.aTransparentColor;
857 
858 	return rOStm;
859 }
860 
861 // ------------------------------------------------------------------
862 
863 SvStream& operator>>( SvStream& rIStm, BitmapEx& rBitmapEx )
864 {
865 	Bitmap aBmp;
866 
867 	rIStm >> aBmp;
868 
869 	if( !rIStm.GetError() )
870 	{
871 		const sal_uLong nStmPos = rIStm.Tell();
872 		sal_uInt32		nMagic1 = 0;
873 		sal_uInt32		nMagic2 = 0;
874 
875 		rIStm >> nMagic1 >> nMagic2;
876 
877 		if( ( nMagic1 != 0x25091962 ) || ( nMagic2 != 0xACB20201 ) || rIStm.GetError() )
878 		{
879 			rIStm.ResetError();
880 			rIStm.Seek( nStmPos );
881 			rBitmapEx = aBmp;
882 		}
883 		else
884 		{
885 			sal_uInt8 bTransparent = false;
886 
887 			rIStm >> bTransparent;
888 
889 			if( bTransparent == (sal_uInt8) TRANSPARENT_BITMAP )
890 			{
891 				Bitmap aMask;
892 
893 				rIStm >> aMask;
894 
895 				if( !!aMask)
896 				{
897 					// do we have an alpha mask?
898 					if( ( 8 == aMask.GetBitCount() ) && aMask.HasGreyPalette() )
899 					{
900 						AlphaMask aAlpha;
901 
902 						// create alpha mask quickly (without greyscale conversion)
903 						aAlpha.ImplSetBitmap( aMask );
904 						rBitmapEx = BitmapEx( aBmp, aAlpha );
905 					}
906 					else
907 						rBitmapEx = BitmapEx( aBmp, aMask );
908 				}
909 				else
910 					rBitmapEx = aBmp;
911 			}
912 			else if( bTransparent == (sal_uInt8) TRANSPARENT_COLOR )
913 			{
914 				Color aTransparentColor;
915 
916 				rIStm >> aTransparentColor;
917 				rBitmapEx = BitmapEx( aBmp, aTransparentColor );
918 			}
919 			else
920 				rBitmapEx = aBmp;
921 		}
922 	}
923 
924 	return rIStm;
925 }
926