1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: alpha.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <tools/debug.hxx>
34 #include <vcl/bmpacc.hxx>
35 #include <tools/color.hxx>
36 #include <vcl/alpha.hxx>
42 AlphaMask::AlphaMask()
46 // -----------------------------------------------------------------------------
48 AlphaMask::AlphaMask( const Bitmap
& rBitmap
) :
52 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS
);
55 // -----------------------------------------------------------------------------
57 AlphaMask::AlphaMask( const AlphaMask
& rAlphaMask
) :
62 // -----------------------------------------------------------------------------
64 AlphaMask::AlphaMask( const Size
& rSizePixel
, BYTE
* pEraseTransparency
) :
65 Bitmap( rSizePixel
, 8, &Bitmap::GetGreyPalette( 256 ) )
67 if( pEraseTransparency
)
68 Bitmap::Erase( Color( *pEraseTransparency
, *pEraseTransparency
, *pEraseTransparency
) );
71 // -----------------------------------------------------------------------------
73 AlphaMask::~AlphaMask()
77 // -----------------------------------------------------------------------------
79 AlphaMask
& AlphaMask::operator=( const Bitmap
& rBitmap
)
81 *(Bitmap
*) this = rBitmap
;
84 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS
);
89 // -----------------------------------------------------------------------------
91 const Bitmap
& AlphaMask::ImplGetBitmap() const
93 return( (const Bitmap
&) *this );
96 // -----------------------------------------------------------------------------
98 void AlphaMask::ImplSetBitmap( const Bitmap
& rBitmap
)
100 DBG_ASSERT( ( 8 == rBitmap
.GetBitCount() ) && rBitmap
.HasGreyPalette(), "AlphaMask::ImplSetBitmap: invalid bitmap" );
101 *(Bitmap
*) this = rBitmap
;
104 // -----------------------------------------------------------------------------
106 Bitmap
AlphaMask::GetBitmap() const
108 return ImplGetBitmap();
111 // -----------------------------------------------------------------------------
113 BOOL
AlphaMask::Crop( const Rectangle
& rRectPixel
)
115 return Bitmap::Crop( rRectPixel
);
118 // -----------------------------------------------------------------------------
120 BOOL
AlphaMask::Expand( ULONG nDX
, ULONG nDY
, BYTE
* pInitTransparency
)
124 if( pInitTransparency
)
125 aColor
= Color( *pInitTransparency
, *pInitTransparency
, *pInitTransparency
);
127 return Bitmap::Expand( nDX
, nDY
, pInitTransparency
? &aColor
: NULL
);
130 // -----------------------------------------------------------------------------
132 BOOL
AlphaMask::CopyPixel( const Rectangle
& rRectDst
, const Rectangle
& rRectSrc
,
133 const AlphaMask
* pAlphaSrc
)
135 // Note: this code is copied from Bitmap::CopyPixel but avoids any palette lookups
136 // this optimization is possible because the palettes of AlphaMasks are always identical (8bit GreyPalette, see ctor)
138 const Size
aSizePix( GetSizePixel() );
139 Rectangle
aRectDst( rRectDst
);
142 aRectDst
.Intersection( Rectangle( Point(), aSizePix
) );
144 if( !aRectDst
.IsEmpty() )
146 if( pAlphaSrc
&& ( *pAlphaSrc
!= *this ) )
148 Bitmap
* pSrc
= (Bitmap
*) pAlphaSrc
;
149 const Size
aCopySizePix( pSrc
->GetSizePixel() );
150 Rectangle
aRectSrc( rRectSrc
);
152 aRectSrc
.Intersection( Rectangle( Point(), aCopySizePix
) );
154 if( !aRectSrc
.IsEmpty() )
156 BitmapReadAccess
* pReadAcc
= pSrc
->AcquireReadAccess();
160 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
164 const long nWidth
= Min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
165 const long nHeight
= Min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
166 const long nSrcEndX
= aRectSrc
.Left() + nWidth
;
167 const long nSrcEndY
= aRectSrc
.Top() + nHeight
;
168 long nDstY
= aRectDst
.Top();
170 for( long nSrcY
= aRectSrc
.Top(); nSrcY
< nSrcEndY
; nSrcY
++, nDstY
++ )
171 for( long nSrcX
= aRectSrc
.Left(), nDstX
= aRectDst
.Left(); nSrcX
< nSrcEndX
; nSrcX
++, nDstX
++ )
172 pWriteAcc
->SetPixel( nDstY
, nDstX
, pReadAcc
->GetPixel( nSrcY
, nSrcX
) );
174 ReleaseAccess( pWriteAcc
);
175 bRet
= ( nWidth
> 0L ) && ( nHeight
> 0L );
178 pSrc
->ReleaseAccess( pReadAcc
);
184 Rectangle
aRectSrc( rRectSrc
);
186 aRectSrc
.Intersection( Rectangle( Point(), aSizePix
) );
188 if( !aRectSrc
.IsEmpty() && ( aRectSrc
!= aRectDst
) )
190 BitmapWriteAccess
* pWriteAcc
= AcquireWriteAccess();
194 const long nWidth
= Min( aRectSrc
.GetWidth(), aRectDst
.GetWidth() );
195 const long nHeight
= Min( aRectSrc
.GetHeight(), aRectDst
.GetHeight() );
196 const long nSrcX
= aRectSrc
.Left();
197 const long nSrcY
= aRectSrc
.Top();
198 const long nSrcEndX1
= nSrcX
+ nWidth
- 1L;
199 const long nSrcEndY1
= nSrcY
+ nHeight
- 1L;
200 const long nDstX
= aRectDst
.Left();
201 const long nDstY
= aRectDst
.Top();
202 const long nDstEndX1
= nDstX
+ nWidth
- 1L;
203 const long nDstEndY1
= nDstY
+ nHeight
- 1L;
205 if( ( nDstX
<= nSrcX
) && ( nDstY
<= nSrcY
) )
207 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
208 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
209 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
211 else if( ( nDstX
<= nSrcX
) && ( nDstY
>= nSrcY
) )
213 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
214 for( long nX
= nSrcX
, nXN
= nDstX
; nX
<= nSrcEndX1
; nX
++, nXN
++ )
215 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
217 else if( ( nDstX
>= nSrcX
) && ( nDstY
<= nSrcY
) )
219 for( long nY
= nSrcY
, nYN
= nDstY
; nY
<= nSrcEndY1
; nY
++, nYN
++ )
220 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
221 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
225 for( long nY
= nSrcEndY1
, nYN
= nDstEndY1
; nY
>= nSrcY
; nY
--, nYN
-- )
226 for( long nX
= nSrcEndX1
, nXN
= nDstEndX1
; nX
>= nSrcX
; nX
--, nXN
-- )
227 pWriteAcc
->SetPixel( nYN
, nXN
, pWriteAcc
->GetPixel( nY
, nX
) );
230 ReleaseAccess( pWriteAcc
);
241 // -----------------------------------------------------------------------------
243 BOOL
AlphaMask::Erase( BYTE cTransparency
)
245 return Bitmap::Erase( Color( cTransparency
, cTransparency
, cTransparency
) );
248 // -----------------------------------------------------------------------------
250 BOOL
AlphaMask::Invert()
252 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
255 if( pAcc
&& pAcc
->GetBitCount() == 8 )
257 BitmapColor
aCol( 0 );
258 const long nWidth
= pAcc
->Width(), nHeight
= pAcc
->Height();
259 BYTE
* pMap
= new BYTE
[ 256 ];
261 for( long i
= 0; i
< 256; i
++ )
262 pMap
[ i
] = ~(BYTE
) i
;
264 for( long nY
= 0L; nY
< nHeight
; nY
++ )
266 for( long nX
= 0L; nX
< nWidth
; nX
++ )
268 aCol
.SetIndex( pMap
[ pAcc
->GetPixel( nY
, nX
).GetIndex() ] );
269 pAcc
->SetPixel( nY
, nX
, aCol
);
278 ReleaseAccess( pAcc
);
283 // -----------------------------------------------------------------------------
285 BOOL
AlphaMask::Mirror( ULONG nMirrorFlags
)
287 return Bitmap::Mirror( nMirrorFlags
);
290 // -----------------------------------------------------------------------------
292 BOOL
AlphaMask::Scale( const Size
& rNewSize
, ULONG nScaleFlag
)
294 BOOL bRet
= Bitmap::Scale( rNewSize
, nScaleFlag
);
296 if( bRet
&& ( nScaleFlag
== BMP_SCALE_INTERPOLATE
) )
297 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS
);
302 // -----------------------------------------------------------------------------
304 BOOL
AlphaMask::Scale( const double& rScaleX
, const double& rScaleY
, ULONG nScaleFlag
)
306 BOOL bRet
= Bitmap::Scale( rScaleX
, rScaleY
, nScaleFlag
);
308 if( bRet
&& ( nScaleFlag
== BMP_SCALE_INTERPOLATE
) )
309 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS
);
314 // -----------------------------------------------------------------------------
316 BOOL
AlphaMask::Rotate( long nAngle10
, BYTE cFillTransparency
)
318 return Bitmap::Rotate( nAngle10
, Color( cFillTransparency
, cFillTransparency
, cFillTransparency
) );
321 // -----------------------------------------------------------------------------
323 BOOL
AlphaMask::Replace( const Bitmap
& rMask
, BYTE cReplaceTransparency
)
325 BitmapReadAccess
* pMaskAcc
= ( (Bitmap
&) rMask
).AcquireReadAccess();
326 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
329 if( pMaskAcc
&& pAcc
)
331 const BitmapColor
aReplace( cReplaceTransparency
);
332 const long nWidth
= Min( pMaskAcc
->Width(), pAcc
->Width() );
333 const long nHeight
= Min( pMaskAcc
->Height(), pAcc
->Height() );
334 const BitmapColor
aMaskWhite( pMaskAcc
->GetBestMatchingColor( Color( COL_WHITE
) ) );
336 for( long nY
= 0L; nY
< nHeight
; nY
++ )
337 for( long nX
= 0L; nX
< nWidth
; nX
++ )
338 if( pMaskAcc
->GetPixel( nY
, nX
) == aMaskWhite
)
339 pAcc
->SetPixel( nY
, nX
, aReplace
);
342 ( (Bitmap
&) rMask
).ReleaseAccess( pMaskAcc
);
343 ReleaseAccess( pAcc
);
348 // -----------------------------------------------------------------------------
350 BOOL
AlphaMask::Replace( BYTE cSearchTransparency
, BYTE cReplaceTransparency
, ULONG
356 BitmapWriteAccess
* pAcc
= AcquireWriteAccess();
359 DBG_ASSERT( !nTol
, "AlphaMask::Replace: nTol not used yet" );
361 if( pAcc
&& pAcc
->GetBitCount() == 8 )
363 const long nWidth
= pAcc
->Width(), nHeight
= pAcc
->Height();
365 if( pAcc
->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL
)
367 for( long nY
= 0L; nY
< nHeight
; nY
++ )
369 Scanline pScan
= pAcc
->GetScanline( nY
);
371 for( long nX
= 0L; nX
< nWidth
; nX
++, pScan
++ )
373 if( *pScan
== cSearchTransparency
)
374 *pScan
= cReplaceTransparency
;
380 BitmapColor
aReplace( cReplaceTransparency
);
382 for( long nY
= 0L; nY
< nHeight
; nY
++ )
384 for( long nX
= 0L; nX
< nWidth
; nX
++ )
386 if( pAcc
->GetPixel( nY
, nX
).GetIndex() == cSearchTransparency
)
387 pAcc
->SetPixel( nY
, nX
, aReplace
);
396 ReleaseAccess( pAcc
);
401 // -----------------------------------------------------------------------------
403 BOOL
AlphaMask::Replace( BYTE
* pSearchTransparencies
, BYTE
* pReplaceTransparencies
,
404 ULONG nColorCount
, ULONG
* pTols
)
406 Color
* pSearchColors
= new Color
[ nColorCount
];
407 Color
* pReplaceColors
= new Color
[ nColorCount
];
410 for( ULONG i
= 0; i
< nColorCount
; i
++ )
412 const BYTE cSearchTransparency
= pSearchTransparencies
[ i
];
413 const BYTE cReplaceTransparency
= pReplaceTransparencies
[ i
];
415 pSearchColors
[ i
] = Color( cSearchTransparency
, cSearchTransparency
, cSearchTransparency
);
416 pReplaceColors
[ i
] = Color( cReplaceTransparency
, cReplaceTransparency
, cReplaceTransparency
);
419 bRet
= Bitmap::Replace( pSearchColors
, pReplaceColors
, nColorCount
, pTols
) &&
420 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS
);
422 delete[] pSearchColors
;
423 delete[] pReplaceColors
;
428 // -----------------------------------------------------------------------------
430 void AlphaMask::ReleaseAccess( BitmapReadAccess
* pAccess
)
434 Bitmap::ReleaseAccess( pAccess
);
435 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS
);