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