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