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