xref: /aoo41x/main/vcl/source/gdi/bitmapex.cxx (revision 54628ca4)
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(!!aBitmap && !!aMask && aBitmap.GetSizePixel() != aMask.GetSizePixel())
135     {
136         OSL_ENSURE(false, "Mask size differs from Bitmap size, corrected Mask (!)");
137         aMask.Scale(aBitmap.GetSizePixel());
138     }
139 
140     // #105489# Ensure a mask is exactly one bit deep
141     if( !!aMask && aMask.GetBitCount() != 1 )
142     {
143         OSL_TRACE("BitmapEx: forced mask to monochrome");
144         aMask.ImplMakeMono( 255 );
145     }
146 }
147 
148 // ------------------------------------------------------------------
149 
150 BitmapEx::BitmapEx( const Bitmap& rBmp, const AlphaMask& rAlphaMask ) :
151 		aBitmap			( rBmp ),
152 		aMask			( rAlphaMask.ImplGetBitmap() ),
153 		aBitmapSize		( aBitmap.GetSizePixel() ),
154 		eTransparent	( !rAlphaMask ? TRANSPARENT_NONE : TRANSPARENT_BITMAP ),
155 		bAlpha			( !rAlphaMask ? sal_False : sal_True )
156 {
157     if(!!aBitmap && !!aMask && aBitmap.GetSizePixel() != aMask.GetSizePixel())
158     {
159         OSL_ENSURE(false, "Alpha size differs from Bitmap size, corrected Mask (!)");
160         aMask.Scale(rBmp.GetSizePixel());
161     }
162 
163     // #i75531# the workaround below can go when
164     // X11SalGraphics::drawAlphaBitmap()'s render acceleration
165     // can handle the bitmap depth mismatch directly
166     if( aBitmap.GetBitCount() < aMask.GetBitCount() )
167         aBitmap.Convert( BMP_CONVERSION_24BIT );
168 }
169 
170 // ------------------------------------------------------------------
171 
172 BitmapEx::BitmapEx( const Bitmap& rBmp, const Color& rTransparentColor ) :
173 		aBitmap				( rBmp ),
174 		aBitmapSize			( aBitmap.GetSizePixel() ),
175 		aTransparentColor	( rTransparentColor ),
176 		eTransparent		( TRANSPARENT_BITMAP ),
177 		bAlpha				( sal_False )
178 {
179 	aMask = aBitmap.CreateMask( aTransparentColor );
180 
181     DBG_ASSERT( rBmp.GetSizePixel() == aMask.GetSizePixel(),
182                 "BitmapEx::BitmapEx(): size mismatch for bitmap and alpha mask." );
183 }
184 
185 // ------------------------------------------------------------------
186 
187 BitmapEx::~BitmapEx()
188 {
189 }
190 
191 // ------------------------------------------------------------------
192 
193 // ------------------------------------------------------------------
194 
195 BitmapEx& BitmapEx::operator=( const BitmapEx& rBitmapEx )
196 {
197 	if( &rBitmapEx != this )
198 	{
199 		aBitmap = rBitmapEx.aBitmap;
200 		aMask = rBitmapEx.aMask;
201 		aBitmapSize = rBitmapEx.aBitmapSize;
202 		aTransparentColor = rBitmapEx.aTransparentColor;
203 		eTransparent = rBitmapEx.eTransparent;
204 		bAlpha = rBitmapEx.bAlpha;
205 	}
206 
207 	return *this;
208 }
209 
210 // ------------------------------------------------------------------
211 
212 sal_Bool BitmapEx::operator==( const BitmapEx& rBitmapEx ) const
213 {
214 	if( eTransparent != rBitmapEx.eTransparent )
215 		return sal_False;
216 
217 	if( aBitmap != rBitmapEx.aBitmap )
218 		return sal_False;
219 
220 	if( aBitmapSize != rBitmapEx.aBitmapSize )
221 		return sal_False;
222 
223 	if( eTransparent == TRANSPARENT_NONE )
224 		return sal_True;
225 
226 	if( eTransparent == TRANSPARENT_COLOR )
227 		return aTransparentColor == rBitmapEx.aTransparentColor;
228 
229 	return( ( aMask == rBitmapEx.aMask ) && ( bAlpha == rBitmapEx.bAlpha ) );
230 }
231 
232 // ------------------------------------------------------------------
233 
234 sal_Bool BitmapEx::IsEqual( const BitmapEx& rBmpEx ) const
235 {
236 	return( rBmpEx.eTransparent == eTransparent &&
237 			rBmpEx.bAlpha == bAlpha &&
238 			rBmpEx.aBitmap.IsEqual( aBitmap ) &&
239 			rBmpEx.aMask.IsEqual( aMask ) );
240 }
241 
242 // ------------------------------------------------------------------
243 
244 sal_Bool BitmapEx::IsEmpty() const
245 {
246 	return( aBitmap.IsEmpty() && aMask.IsEmpty() );
247 }
248 
249 // ------------------------------------------------------------------
250 
251 void BitmapEx::SetEmpty()
252 {
253 	aBitmap.SetEmpty();
254 	aMask.SetEmpty();
255 	eTransparent = TRANSPARENT_NONE;
256 	bAlpha = sal_False;
257 }
258 
259 // ------------------------------------------------------------------
260 
261 void BitmapEx::Clear()
262 {
263 	SetEmpty();
264 }
265 
266 // ------------------------------------------------------------------
267 
268 sal_Bool BitmapEx::IsTransparent() const
269 {
270 	return( eTransparent != TRANSPARENT_NONE );
271 }
272 
273 // ------------------------------------------------------------------
274 
275 sal_Bool BitmapEx::IsAlpha() const
276 {
277 	return( IsTransparent() && bAlpha );
278 }
279 
280 // ------------------------------------------------------------------
281 
282 Bitmap BitmapEx::GetBitmap( const Color* pTransReplaceColor ) const
283 {
284 	Bitmap aRetBmp( aBitmap );
285 
286 	if( pTransReplaceColor && ( eTransparent != TRANSPARENT_NONE ) )
287 	{
288 		Bitmap aTempMask;
289 
290 		if( eTransparent == TRANSPARENT_COLOR )
291 			aTempMask = aBitmap.CreateMask( aTransparentColor );
292 		else
293 			aTempMask = aMask;
294 
295 		if( !IsAlpha() )
296 			aRetBmp.Replace( aTempMask, *pTransReplaceColor );
297 		else
298 			aRetBmp.Replace( GetAlpha(), *pTransReplaceColor );
299 	}
300 
301 	return aRetBmp;
302 }
303 
304 // ------------------------------------------------------------------
305 
306 BitmapEx BitmapEx::GetColorTransformedBitmapEx( BmpColorMode eColorMode ) const
307 {
308 	BitmapEx aRet;
309 
310 	if( BMP_COLOR_HIGHCONTRAST == eColorMode )
311 	{
312 		aRet = *this;
313 		aRet.aBitmap = aBitmap.GetColorTransformedBitmap( eColorMode );
314 	}
315 	else if( BMP_COLOR_MONOCHROME_BLACK == eColorMode ||
316 			 BMP_COLOR_MONOCHROME_WHITE == eColorMode )
317 	{
318 		aRet = *this;
319 		aRet.aBitmap = aRet.aBitmap.GetColorTransformedBitmap( eColorMode );
320 
321 		if( !aRet.aMask.IsEmpty() )
322 		{
323 			aRet.aMask.CombineSimple( aRet.aBitmap, BMP_COMBINE_OR );
324 			aRet.aBitmap.Erase( ( BMP_COLOR_MONOCHROME_BLACK == eColorMode ) ? COL_BLACK : COL_WHITE );
325 
326             DBG_ASSERT( aRet.aBitmap.GetSizePixel() == aRet.aMask.GetSizePixel(),
327                         "BitmapEx::GetColorTransformedBitmapEx(): size mismatch for bitmap and alpha mask." );
328 		}
329 	}
330 
331 	return aRet;
332 }
333 
334 // ------------------------------------------------------------------
335 
336 Bitmap BitmapEx::GetMask() const
337 {
338 	Bitmap aRet( aMask );
339 
340 	if( IsAlpha() )
341 		aRet.ImplMakeMono( 255 );
342 
343 	return aRet;
344 }
345 
346 // ------------------------------------------------------------------
347 
348 AlphaMask BitmapEx::GetAlpha() const
349 {
350 	AlphaMask aAlpha;
351 
352 	if( IsAlpha() )
353 		aAlpha.ImplSetBitmap( aMask );
354 	else
355 		aAlpha = aMask;
356 
357 	return aAlpha;
358 }
359 
360 // ------------------------------------------------------------------
361 
362 sal_uLong BitmapEx::GetSizeBytes() const
363 {
364 	sal_uLong nSizeBytes = aBitmap.GetSizeBytes();
365 
366 	if( eTransparent == TRANSPARENT_BITMAP )
367 		nSizeBytes += aMask.GetSizeBytes();
368 
369 	return nSizeBytes;
370 }
371 
372 // ------------------------------------------------------------------
373 
374 sal_uLong BitmapEx::GetChecksum() const
375 {
376 	sal_uInt32	nCrc = aBitmap.GetChecksum();
377 	SVBT32		aBT32;
378 
379 	UInt32ToSVBT32( (long) eTransparent, aBT32 );
380 	nCrc = rtl_crc32( nCrc, aBT32, 4 );
381 
382 	UInt32ToSVBT32( (long) bAlpha, aBT32 );
383 	nCrc = rtl_crc32( nCrc, aBT32, 4 );
384 
385 	if( ( TRANSPARENT_BITMAP == eTransparent ) && !aMask.IsEmpty() )
386 	{
387 		UInt32ToSVBT32( aMask.GetChecksum(), aBT32 );
388 		nCrc = rtl_crc32( nCrc, aBT32, 4 );
389 	}
390 
391 	return nCrc;
392 }
393 
394 // ------------------------------------------------------------------
395 
396 void BitmapEx::SetSizePixel( const Size& rNewSize, sal_uInt32 nScaleFlag )
397 {
398     if(GetSizePixel() != rNewSize)
399     {
400         Scale( rNewSize, nScaleFlag );
401     }
402 }
403 
404 // ------------------------------------------------------------------
405 
406 sal_Bool BitmapEx::Invert()
407 {
408 	sal_Bool bRet = sal_False;
409 
410 	if( !!aBitmap )
411 	{
412 		bRet = aBitmap.Invert();
413 
414 		if( bRet && ( eTransparent == TRANSPARENT_COLOR ) )
415 			aTransparentColor = BitmapColor( aTransparentColor ).Invert();
416 	}
417 
418 	return bRet;
419 }
420 
421 // ------------------------------------------------------------------
422 
423 sal_Bool BitmapEx::Mirror( sal_uLong nMirrorFlags )
424 {
425 	sal_Bool bRet = sal_False;
426 
427 	if( !!aBitmap )
428 	{
429 		bRet = aBitmap.Mirror( nMirrorFlags );
430 
431 		if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
432 			aMask.Mirror( nMirrorFlags );
433 	}
434 
435 	return bRet;
436 }
437 
438 // ------------------------------------------------------------------
439 
440 sal_Bool BitmapEx::Scale( const double& rScaleX, const double& rScaleY, sal_uInt32 nScaleFlag )
441 {
442 	sal_Bool bRet = sal_False;
443 
444 	if( !!aBitmap )
445 	{
446 		bRet = aBitmap.Scale( rScaleX, rScaleY, nScaleFlag );
447 
448 		if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
449         {
450 			aMask.Scale( rScaleX, rScaleY, nScaleFlag );
451         }
452 
453 		aBitmapSize = aBitmap.GetSizePixel();
454 
455         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
456                     "BitmapEx::Scale(): size mismatch for bitmap and alpha mask." );
457 	}
458 
459 	return bRet;
460 }
461 
462 // ------------------------------------------------------------------------
463 
464 sal_Bool BitmapEx::Scale( const Size& rNewSize, sal_uInt32 nScaleFlag )
465 {
466 	sal_Bool bRet;
467 
468 	if( aBitmapSize.Width() && aBitmapSize.Height() )
469 	{
470 		bRet = Scale( (double) rNewSize.Width() / aBitmapSize.Width(),
471 					  (double) rNewSize.Height() / aBitmapSize.Height(),
472 					  nScaleFlag );
473 	}
474 	else
475 		bRet = sal_True;
476 
477 	return bRet;
478 }
479 
480 // ------------------------------------------------------------------
481 
482 sal_Bool BitmapEx::Rotate( long nAngle10, const Color& rFillColor )
483 {
484 	sal_Bool bRet = sal_False;
485 
486 	if( !!aBitmap )
487 	{
488 		const sal_Bool bTransRotate = ( Color( COL_TRANSPARENT ) == rFillColor );
489 
490 		if( bTransRotate )
491 		{
492 			if( eTransparent == TRANSPARENT_COLOR )
493 				bRet = aBitmap.Rotate( nAngle10, aTransparentColor );
494 			else
495 			{
496 				bRet = aBitmap.Rotate( nAngle10, COL_BLACK );
497 
498 				if( eTransparent == TRANSPARENT_NONE )
499 				{
500 					aMask = Bitmap( aBitmapSize, 1 );
501 					aMask.Erase( COL_BLACK );
502 					eTransparent = TRANSPARENT_BITMAP;
503 				}
504 
505 				if( bRet && !!aMask )
506 					aMask.Rotate( nAngle10, COL_WHITE );
507 			}
508 		}
509 		else
510 		{
511 			bRet = aBitmap.Rotate( nAngle10, rFillColor );
512 
513 			if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
514 				aMask.Rotate( nAngle10, COL_WHITE );
515 		}
516 
517 		aBitmapSize = aBitmap.GetSizePixel();
518 
519         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
520                     "BitmapEx::Rotate(): size mismatch for bitmap and alpha mask." );
521 	}
522 
523 	return bRet;
524 }
525 
526 // ------------------------------------------------------------------
527 
528 sal_Bool BitmapEx::Crop( const Rectangle& rRectPixel )
529 {
530 	sal_Bool bRet = sal_False;
531 
532 	if( !!aBitmap )
533 	{
534 		bRet = aBitmap.Crop( rRectPixel );
535 
536 		if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
537 			aMask.Crop( rRectPixel );
538 
539 		aBitmapSize = aBitmap.GetSizePixel();
540 
541         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
542                     "BitmapEx::Crop(): size mismatch for bitmap and alpha mask." );
543 	}
544 
545 	return bRet;
546 }
547 
548 // ------------------------------------------------------------------
549 
550 sal_Bool BitmapEx::Convert( BmpConversion eConversion )
551 {
552 	return( !!aBitmap ? aBitmap.Convert( eConversion ) : sal_False );
553 }
554 
555 // ------------------------------------------------------------------
556 
557 sal_Bool BitmapEx::ReduceColors( sal_uInt16 nNewColorCount, BmpReduce eReduce )
558 {
559 	return( !!aBitmap ? aBitmap.ReduceColors( nNewColorCount, eReduce ) : sal_False );
560 }
561 
562 // ------------------------------------------------------------------
563 
564 sal_Bool BitmapEx::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor, sal_Bool bExpandTransparent )
565 {
566 	sal_Bool bRet = sal_False;
567 
568 	if( !!aBitmap )
569 	{
570 		bRet = aBitmap.Expand( nDX, nDY, pInitColor );
571 
572 		if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
573 		{
574 			Color aColor( bExpandTransparent ? COL_WHITE : COL_BLACK );
575 			aMask.Expand( nDX, nDY, &aColor );
576 		}
577 
578 		aBitmapSize = aBitmap.GetSizePixel();
579 
580         DBG_ASSERT( !aMask || aBitmap.GetSizePixel() == aMask.GetSizePixel(),
581                     "BitmapEx::Expand(): size mismatch for bitmap and alpha mask." );
582 	}
583 
584 	return bRet;
585 }
586 
587 // ------------------------------------------------------------------
588 
589 sal_Bool BitmapEx::CopyPixel( const Rectangle& rRectDst, const Rectangle& rRectSrc,
590 						  const BitmapEx* pBmpExSrc )
591 {
592 	sal_Bool bRet = sal_False;
593 
594 	if( !pBmpExSrc || pBmpExSrc->IsEmpty() )
595 	{
596 		if( !aBitmap.IsEmpty() )
597 		{
598 			bRet = aBitmap.CopyPixel( rRectDst, rRectSrc );
599 
600 			if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
601 				aMask.CopyPixel( rRectDst, rRectSrc );
602 		}
603 	}
604 	else
605 	{
606 		if( !aBitmap.IsEmpty() )
607 		{
608 			bRet = aBitmap.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aBitmap );
609 
610 			if( bRet )
611 			{
612 				if( pBmpExSrc->IsAlpha() )
613 				{
614 					if( IsAlpha() )
615                         // cast to use the optimized AlphaMask::CopyPixel
616 						((AlphaMask*) &aMask)->CopyPixel( rRectDst, rRectSrc, (AlphaMask*)&pBmpExSrc->aMask );
617 					else if( IsTransparent() )
618 					{
619 						AlphaMask* pAlpha = new AlphaMask( aMask );
620 
621 						aMask = pAlpha->ImplGetBitmap();
622 						delete pAlpha;
623 						bAlpha = sal_True;
624 						aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
625 					}
626 					else
627 					{
628 						sal_uInt8	cBlack = 0;
629 						AlphaMask*	pAlpha = new AlphaMask( GetSizePixel(), &cBlack );
630 
631 						aMask = pAlpha->ImplGetBitmap();
632 						delete pAlpha;
633 						eTransparent = TRANSPARENT_BITMAP;
634 						bAlpha = sal_True;
635 						aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
636 					}
637 				}
638 				else if( pBmpExSrc->IsTransparent() )
639 				{
640 					if( IsAlpha() )
641 					{
642 						AlphaMask aAlpha( pBmpExSrc->aMask );
643 						aMask.CopyPixel( rRectDst, rRectSrc, &aAlpha.ImplGetBitmap() );
644 					}
645 					else if( IsTransparent() )
646 						aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
647 					else
648 					{
649 						aMask = Bitmap( GetSizePixel(), 1 );
650 						aMask.Erase( Color( COL_BLACK ) );
651 						eTransparent = TRANSPARENT_BITMAP;
652 						aMask.CopyPixel( rRectDst, rRectSrc, &pBmpExSrc->aMask );
653 					}
654 				}
655                 else if( IsAlpha() )
656                 {
657                     sal_uInt8	      cBlack = 0;
658                     const AlphaMask   aAlphaSrc( pBmpExSrc->GetSizePixel(), &cBlack );
659 
660                     aMask.CopyPixel( rRectDst, rRectSrc, &aAlphaSrc.ImplGetBitmap() );
661                 }
662                 else if( IsTransparent() )
663                 {
664                     Bitmap aMaskSrc( pBmpExSrc->GetSizePixel(), 1 );
665 
666                     aMaskSrc.Erase( Color( COL_BLACK ) );
667                     aMask.CopyPixel( rRectDst, rRectSrc, &aMaskSrc );
668                 }
669 			}
670 		}
671 	}
672 
673 	return bRet;
674 }
675 
676 // ------------------------------------------------------------------
677 
678 sal_Bool BitmapEx::Erase( const Color& rFillColor )
679 {
680 	sal_Bool bRet = sal_False;
681 
682 	if( !!aBitmap )
683 	{
684 		bRet = aBitmap.Erase( rFillColor );
685 
686 		if( bRet && ( eTransparent == TRANSPARENT_BITMAP ) && !!aMask )
687 		{
688             // #104416# Respect transparency on fill color
689             if( rFillColor.GetTransparency() )
690             {
691                 const Color aFill( rFillColor.GetTransparency(), rFillColor.GetTransparency(), rFillColor.GetTransparency() );
692                 aMask.Erase( aFill );
693             }
694             else
695             {
696                 const Color aBlack( COL_BLACK );
697                 aMask.Erase( aBlack );
698             }
699 		}
700 	}
701 
702 	return bRet;
703 }
704 
705 // ------------------------------------------------------------------
706 
707 sal_Bool BitmapEx::Dither( sal_uLong nDitherFlags )
708 {
709 	return( !!aBitmap ? aBitmap.Dither( nDitherFlags ) : sal_False );
710 }
711 
712 // ------------------------------------------------------------------
713 
714 sal_Bool BitmapEx::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol )
715 {
716 	return( !!aBitmap ? aBitmap.Replace( rSearchColor, rReplaceColor, nTol ) : sal_False );
717 }
718 
719 // ------------------------------------------------------------------
720 
721 sal_Bool BitmapEx::Replace( const Color* pSearchColors, const Color* pReplaceColors, sal_uLong nColorCount, const sal_uLong* pTols )
722 {
723 	return( !!aBitmap ? aBitmap.Replace( pSearchColors, pReplaceColors, nColorCount, (sal_uLong*) pTols ) : sal_False );
724 }
725 
726 // ------------------------------------------------------------------
727 
728 sal_Bool BitmapEx::Adjust( short nLuminancePercent, short nContrastPercent,
729 					   short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
730 					   double fGamma, sal_Bool bInvert )
731 {
732 	return( !!aBitmap ? aBitmap.Adjust( nLuminancePercent, nContrastPercent,
733 										nChannelRPercent, nChannelGPercent, nChannelBPercent,
734 										fGamma, bInvert ) : sal_False );
735 }
736 
737 // ------------------------------------------------------------------
738 
739 sal_Bool BitmapEx::Filter( BmpFilter eFilter, const BmpFilterParam* pFilterParam, const Link* pProgress )
740 {
741 	return( !!aBitmap ? aBitmap.Filter( eFilter, pFilterParam, pProgress ) : sal_False );
742 }
743 
744 // ------------------------------------------------------------------
745 
746 void BitmapEx::Draw( OutputDevice* pOutDev, const Point& rDestPt ) const
747 {
748 	pOutDev->DrawBitmapEx( rDestPt, *this );
749 }
750 
751 // ------------------------------------------------------------------
752 
753 void BitmapEx::Draw( OutputDevice* pOutDev,
754 					 const Point& rDestPt, const Size& rDestSize ) const
755 {
756 	pOutDev->DrawBitmapEx( rDestPt, rDestSize, *this );
757 }
758 
759 // ------------------------------------------------------------------
760 
761 void BitmapEx::Draw( OutputDevice* pOutDev,
762 					 const Point& rDestPt, const Size& rDestSize,
763 					 const Point& rSrcPtPixel, const Size& rSrcSizePixel ) const
764 {
765 	pOutDev->DrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, *this );
766 }
767 
768 // ------------------------------------------------------------------
769 
770 sal_uInt8 BitmapEx::GetTransparency(sal_Int32 nX, sal_Int32 nY) const
771 {
772     sal_uInt8 nTransparency(0xff);
773 
774     if(!aBitmap.IsEmpty())
775     {
776         if(nX >= 0 && nX < aBitmapSize.Width() && nY >= 0 && nY < aBitmapSize.Height())
777         {
778             switch(eTransparent)
779             {
780                 case TRANSPARENT_NONE:
781                 {
782                     // not transparent, ergo all covered
783                     nTransparency = 0x00;
784                     break;
785                 }
786                 case TRANSPARENT_COLOR:
787                 {
788                     Bitmap aTestBitmap(aBitmap);
789                     BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess();
790 
791                     if(pRead)
792                     {
793                         const Color aColor = pRead->GetColor(nY, nX);
794 
795                         // if color is not equal to TransparentColor, we are not transparent
796                         if(aColor != aTransparentColor)
797                         {
798                             nTransparency = 0x00;
799                         }
800 
801                         aTestBitmap.ReleaseAccess(pRead);
802                     }
803                     break;
804                 }
805                 case TRANSPARENT_BITMAP:
806                 {
807                     if(!aMask.IsEmpty())
808                     {
809                         Bitmap aTestBitmap(aMask);
810                         BitmapReadAccess* pRead = aTestBitmap.AcquireReadAccess();
811 
812                         if(pRead)
813                         {
814                             const BitmapColor aBitmapColor(pRead->GetPixel(nY, nX));
815 
816                             if(bAlpha)
817                             {
818                                 nTransparency = aBitmapColor.GetIndex();
819                             }
820                             else
821                             {
822                                 if(0x00 == aBitmapColor.GetIndex())
823                                 {
824                                     nTransparency = 0x00;
825                                 }
826                             }
827 
828                             aTestBitmap.ReleaseAccess(pRead);
829                         }
830                     }
831                     break;
832                 }
833             }
834         }
835     }
836 
837     return nTransparency;
838 }
839 
840 // ------------------------------------------------------------------
841 
842 SvStream& operator<<( SvStream& rOStm, const BitmapEx& rBitmapEx )
843 {
844 	rBitmapEx.aBitmap.Write( rOStm );
845 
846 	rOStm << (sal_uInt32) 0x25091962;
847 	rOStm << (sal_uInt32) 0xACB20201;
848 	rOStm << (sal_uInt8) rBitmapEx.eTransparent;
849 
850 	if( rBitmapEx.eTransparent == TRANSPARENT_BITMAP )
851 		rBitmapEx.aMask.Write( rOStm );
852 	else if( rBitmapEx.eTransparent == TRANSPARENT_COLOR )
853 		rOStm << rBitmapEx.aTransparentColor;
854 
855 	return rOStm;
856 }
857 
858 // ------------------------------------------------------------------
859 
860 SvStream& operator>>( SvStream& rIStm, BitmapEx& rBitmapEx )
861 {
862 	Bitmap aBmp;
863 
864 	rIStm >> aBmp;
865 
866 	if( !rIStm.GetError() )
867 	{
868 		const sal_uLong nStmPos = rIStm.Tell();
869 		sal_uInt32		nMagic1 = 0;
870 		sal_uInt32		nMagic2 = 0;
871 
872 		rIStm >> nMagic1 >> nMagic2;
873 
874 		if( ( nMagic1 != 0x25091962 ) || ( nMagic2 != 0xACB20201 ) || rIStm.GetError() )
875 		{
876 			rIStm.ResetError();
877 			rIStm.Seek( nStmPos );
878 			rBitmapEx = aBmp;
879 		}
880 		else
881 		{
882 			sal_uInt8 bTransparent = false;
883 
884 			rIStm >> bTransparent;
885 
886 			if( bTransparent == (sal_uInt8) TRANSPARENT_BITMAP )
887 			{
888 				Bitmap aMask;
889 
890 				rIStm >> aMask;
891 
892 				if( !!aMask)
893 				{
894 					// do we have an alpha mask?
895 					if( ( 8 == aMask.GetBitCount() ) && aMask.HasGreyPalette() )
896 					{
897 						AlphaMask aAlpha;
898 
899 						// create alpha mask quickly (without greyscale conversion)
900 						aAlpha.ImplSetBitmap( aMask );
901 						rBitmapEx = BitmapEx( aBmp, aAlpha );
902 					}
903 					else
904 						rBitmapEx = BitmapEx( aBmp, aMask );
905 				}
906 				else
907 					rBitmapEx = aBmp;
908 			}
909 			else if( bTransparent == (sal_uInt8) TRANSPARENT_COLOR )
910 			{
911 				Color aTransparentColor;
912 
913 				rIStm >> aTransparentColor;
914 				rBitmapEx = BitmapEx( aBmp, aTransparentColor );
915 			}
916 			else
917 				rBitmapEx = aBmp;
918 		}
919 	}
920 
921 	return rIStm;
922 }
923