Update ooo320-m1
[ooovba.git] / vcl / source / gdi / impimage.cxx
bloba0d2ac7858d5af7f8ccc08c4ac7189e2d74f7c67
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: impimage.cxx,v $
10 * $Revision: 1.25 $
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 <vcl/outdev.hxx>
34 #include <vcl/bitmapex.hxx>
35 #include <vcl/alpha.hxx>
36 #include <vcl/window.hxx>
37 #include <vcl/bmpacc.hxx>
38 #include <vcl/virdev.hxx>
39 #include <vcl/image.h>
40 #include <vcl/image.hxx>
42 // -----------
43 // - Defines -
44 // -----------
46 #define IMPSYSIMAGEITEM_MASK ( 0x01 )
47 #define IMPSYSIMAGEITEM_ALPHA ( 0x02 )
48 #define DISA_ALL ( 0xffff )
50 // ----------------
51 // - ImageAryData -
52 // ----------------
54 ImageAryData::ImageAryData() :
55 maName(),
56 mnId( 0 ),
57 maBitmapEx()
61 // -----------------------------------------------------------------------
63 ImageAryData::ImageAryData( const ImageAryData& rData ) :
64 maName( rData.maName ),
65 mnId( rData.mnId ),
66 maBitmapEx( rData.maBitmapEx )
70 ImageAryData::ImageAryData( const rtl::OUString &aName,
71 USHORT nId, const BitmapEx &aBitmap )
72 : maName( aName ), mnId( nId ), maBitmapEx( aBitmap )
76 // -----------------------------------------------------------------------
78 ImageAryData::~ImageAryData()
82 // -----------------------------------------------------------------------
84 ImageAryData& ImageAryData::operator=( const ImageAryData& rData )
86 maName = rData.maName;
87 mnId = rData.mnId;
88 maBitmapEx = rData.maBitmapEx;
90 return *this;
93 // -----------------
94 // - ImplImageList -
95 // -----------------
97 ImplImageList::ImplImageList()
101 ImplImageList::ImplImageList( const ImplImageList &aSrc ) :
102 maPrefix( aSrc.maPrefix ),
103 maImageSize( aSrc.maImageSize ),
104 mnRefCount( 1 )
106 maImages.reserve( aSrc.maImages.size() );
107 for ( ImageAryDataVec::const_iterator aIt = aSrc.maImages.begin(), aEnd = aSrc.maImages.end(); aIt != aEnd; ++aIt )
109 ImageAryData* pAryData = new ImageAryData( **aIt );
110 maImages.push_back( pAryData );
111 if( pAryData->maName.getLength() )
112 maNameHash [ pAryData->maName ] = pAryData;
116 ImplImageList::~ImplImageList()
118 for ( ImageAryDataVec::iterator aIt = maImages.begin(), aEnd = maImages.end(); aIt != aEnd; ++aIt )
119 delete *aIt;
122 void ImplImageList::AddImage( const ::rtl::OUString &aName,
123 USHORT nId, const BitmapEx &aBitmapEx )
125 ImageAryData *pImg = new ImageAryData( aName, nId, aBitmapEx );
126 maImages.push_back( pImg );
127 if( aName.getLength() )
128 maNameHash [ aName ] = pImg;
131 void ImplImageList::RemoveImage( USHORT nPos )
133 ImageAryData *pImg = maImages[ nPos ];
134 if( pImg->maName.getLength() )
135 maNameHash.erase( pImg->maName );
136 maImages.erase( maImages.begin() + nPos );
139 USHORT ImplImageList::GetImageCount() const
141 return sal::static_int_cast< USHORT >( maImages.size() );
144 // -----------------
145 // - ImplImageData -
146 // -----------------
148 ImplImageData::ImplImageData( const BitmapEx& rBmpEx ) :
149 mpImageBitmap( NULL ),
150 maBmpEx( rBmpEx )
154 // -----------------------------------------------------------------------
156 ImplImageData::~ImplImageData()
158 delete mpImageBitmap;
161 // -----------------
162 // - ImplImageData -
163 // -----------------
165 BOOL ImplImageData::IsEqual( const ImplImageData& rData )
167 return( maBmpEx == rData.maBmpEx );
170 // -------------
171 // - ImplImage -
172 // -------------
174 ImplImage::ImplImage()
178 // ------------------------------------------------------------------------------
180 ImplImage::~ImplImage()
182 switch( meType )
184 case IMAGETYPE_BITMAP:
185 delete static_cast< Bitmap* >( mpData );
186 break;
188 case IMAGETYPE_IMAGE:
189 delete static_cast< ImplImageData* >( mpData );
190 break;
194 // ----------------
195 // - ImplImageBmp -
196 // ----------------
198 ImplImageBmp::ImplImageBmp() :
199 mpDisplayBmp( NULL ),
200 mpInfoAry( NULL ),
201 mnSize( 0 )
205 // -------------
206 // - ImplImage -
207 // -------------
209 ImplImageBmp::~ImplImageBmp()
211 delete[] mpInfoAry;
212 delete mpDisplayBmp;
215 // -----------------------------------------------------------------------
217 void ImplImageBmp::Create( long nItemWidth, long nItemHeight, USHORT nInitSize )
219 const Size aTotalSize( nInitSize * nItemWidth, nItemHeight );
221 maBmpEx = Bitmap( aTotalSize, 24 );
222 maDisabledBmpEx.SetEmpty();
224 delete mpDisplayBmp;
225 mpDisplayBmp = NULL;
227 maSize = Size( nItemWidth, nItemHeight );
228 mnSize = nInitSize;
230 delete[] mpInfoAry;
231 mpInfoAry = new BYTE[ mnSize ];
232 memset( mpInfoAry, 0, mnSize );
235 // -----------------------------------------------------------------------
237 void ImplImageBmp::Create( const BitmapEx& rBmpEx, long nItemWidth, long nItemHeight, USHORT nInitSize )
239 maBmpEx = rBmpEx;
240 maDisabledBmpEx.SetEmpty();
242 delete mpDisplayBmp;
243 mpDisplayBmp = NULL;
245 maSize = Size( nItemWidth, nItemHeight );
246 mnSize = nInitSize;
248 delete[] mpInfoAry;
249 mpInfoAry = new BYTE[ mnSize ];
250 memset( mpInfoAry,
251 rBmpEx.IsAlpha() ? IMPSYSIMAGEITEM_ALPHA : ( rBmpEx.IsTransparent() ? IMPSYSIMAGEITEM_MASK : 0 ),
252 mnSize );
255 // -----------------------------------------------------------------------
257 void ImplImageBmp::Expand( USHORT nGrowSize )
259 const ULONG nDX = nGrowSize * maSize.Width();
260 const USHORT nOldSize = mnSize;
261 BYTE* pNewAry = new BYTE[ mnSize = sal::static_int_cast<USHORT>(mnSize+nGrowSize) ];
263 maBmpEx.Expand( nDX, 0UL );
265 if( !maDisabledBmpEx.IsEmpty() )
266 maDisabledBmpEx.Expand( nDX, 0UL );
268 delete mpDisplayBmp;
269 mpDisplayBmp = NULL;
271 memset( pNewAry, 0, mnSize );
272 memcpy( pNewAry, mpInfoAry, nOldSize );
273 delete[] mpInfoAry;
274 mpInfoAry = pNewAry;
277 // -----------------------------------------------------------------------
279 void ImplImageBmp::Invert()
281 delete mpDisplayBmp;
282 mpDisplayBmp = NULL;
284 maBmpEx.Invert();
287 // -----------------------------------------------------------------------
289 void ImplImageBmp::Replace( USHORT nPos, USHORT nSrcPos )
291 const Point aSrcPos( nSrcPos * maSize.Width(), 0L ), aPos( nPos * maSize.Width(), 0L );
292 const Rectangle aSrcRect( aSrcPos, maSize );
293 const Rectangle aDstRect( aPos, maSize );
295 maBmpEx.CopyPixel( aDstRect, aSrcRect );
297 if( !maDisabledBmpEx.IsEmpty() )
298 maDisabledBmpEx.CopyPixel( aDstRect, aSrcRect );
300 delete mpDisplayBmp;
301 mpDisplayBmp = NULL;
303 mpInfoAry[ nPos ] = mpInfoAry[ nSrcPos ];
306 // -----------------------------------------------------------------------
308 void ImplImageBmp::Replace( USHORT nPos, const ImplImageBmp& rImageBmp, USHORT nSrcPos )
310 const Point aSrcPos( nSrcPos * maSize.Width(), 0L ), aPos( nPos * maSize.Width(), 0L );
311 const Rectangle aSrcRect( aSrcPos, maSize );
312 const Rectangle aDstRect( aPos, maSize );
314 maBmpEx.CopyPixel( aDstRect, aSrcRect, &rImageBmp.maBmpEx );
316 ImplUpdateDisabledBmpEx( nPos );
317 delete mpDisplayBmp;
318 mpDisplayBmp = NULL;
320 mpInfoAry[ nPos ] = rImageBmp.mpInfoAry[ nSrcPos ];
323 // -----------------------------------------------------------------------
325 void ImplImageBmp::Replace( USHORT nPos, const BitmapEx& rBmpEx )
327 const Point aNullPos, aPos( nPos * maSize.Width(), 0L );
328 const Rectangle aSrcRect( aNullPos, maSize );
329 const Rectangle aDstRect( aPos, maSize );
331 maBmpEx.CopyPixel( aDstRect, aSrcRect, &rBmpEx );
333 ImplUpdateDisabledBmpEx( nPos );
334 delete mpDisplayBmp;
335 mpDisplayBmp = NULL;
337 mpInfoAry[ nPos ] &= ~( IMPSYSIMAGEITEM_MASK | IMPSYSIMAGEITEM_ALPHA );
338 mpInfoAry[ nPos ] |= ( rBmpEx.IsAlpha() ? IMPSYSIMAGEITEM_ALPHA : ( rBmpEx.IsTransparent() ? IMPSYSIMAGEITEM_MASK : 0 ) );
341 // -----------------------------------------------------------------------
343 void ImplImageBmp::ReplaceColors( const Color* pSrcColors, const Color* pDstColors, ULONG nColorCount )
345 maBmpEx.Replace( pSrcColors, pDstColors, nColorCount );
346 delete mpDisplayBmp;
347 mpDisplayBmp = NULL;
350 // -----------------------------------------------------------------------
352 void ImplImageBmp::ColorTransform( BmpColorMode eColorMode )
354 maBmpEx = maBmpEx.GetColorTransformedBitmapEx( eColorMode );
355 delete mpDisplayBmp;
356 mpDisplayBmp = NULL;
359 // -----------------------------------------------------------------------
361 BitmapEx ImplImageBmp::GetBitmapEx( USHORT nPosCount, USHORT* pPosAry ) const
363 const Bitmap aNewBmp( Size( nPosCount * maSize.Width(), maSize.Height() ), maBmpEx.GetBitmap().GetBitCount() );
364 BitmapEx aRet;
365 if( maBmpEx.IsAlpha() )
367 // initialize target bitmap with an empty alpha mask
368 // which allows for using an optimized copypixel later on (see AlphaMask::CopyPixel)
369 // that avoids palette lookups
370 AlphaMask aAlpha( Size( nPosCount * maSize.Width(), maSize.Height() ) );
371 aRet = BitmapEx( aNewBmp, aAlpha );
373 else
374 aRet = BitmapEx( aNewBmp );
376 for( USHORT i = 0; i < nPosCount; i++ )
378 const Point aSrcPos( pPosAry[ i ] * maSize.Width(), 0L );
379 const Point aPos( i * maSize.Width(), 0L );
380 const Rectangle aSrcRect( aSrcPos, maSize );
381 const Rectangle aDstRect( aPos, maSize );
383 aRet.CopyPixel( aDstRect, aSrcRect, &maBmpEx );
386 return aRet;
389 // -----------------------------------------------------------------------
391 void ImplImageBmp::Draw( USHORT nPos, OutputDevice* pOutDev,
392 const Point& rPos, USHORT nStyle,
393 const Size* pSize )
395 if( pOutDev->IsDeviceOutputNecessary() )
397 const Point aSrcPos( nPos * maSize.Width(), 0 );
398 Size aOutSize;
400 aOutSize = ( pSize ? *pSize : pOutDev->PixelToLogic( maSize ) );
402 if( nStyle & IMAGE_DRAW_DISABLE )
404 ImplUpdateDisabledBmpEx( nPos);
405 pOutDev->DrawBitmapEx( rPos, aOutSize, aSrcPos, maSize, maDisabledBmpEx );
407 else
409 if( nStyle & ( IMAGE_DRAW_COLORTRANSFORM |
410 IMAGE_DRAW_MONOCHROME_BLACK | IMAGE_DRAW_MONOCHROME_WHITE |
411 IMAGE_DRAW_HIGHLIGHT | IMAGE_DRAW_DEACTIVE | IMAGE_DRAW_SEMITRANSPARENT ) )
413 BitmapEx aTmpBmpEx;
414 const Rectangle aCropRect( aSrcPos, maSize );
416 if( mpInfoAry[ nPos ] & ( IMPSYSIMAGEITEM_MASK | IMPSYSIMAGEITEM_ALPHA ) )
417 aTmpBmpEx = maBmpEx;
418 else
419 aTmpBmpEx = maBmpEx.GetBitmap();
421 aTmpBmpEx.Crop( aCropRect );
423 if( nStyle & ( IMAGE_DRAW_COLORTRANSFORM | IMAGE_DRAW_MONOCHROME_BLACK | IMAGE_DRAW_MONOCHROME_WHITE ) )
425 const BmpColorMode eMode = ( nStyle & IMAGE_DRAW_COLORTRANSFORM ) ? BMP_COLOR_HIGHCONTRAST :
426 ( ( nStyle & IMAGE_DRAW_MONOCHROME_BLACK ) ? BMP_COLOR_MONOCHROME_BLACK : BMP_COLOR_MONOCHROME_WHITE );
428 aTmpBmpEx = aTmpBmpEx.GetColorTransformedBitmapEx( eMode );
431 Bitmap aTmpBmp( aTmpBmpEx.GetBitmap() );
433 if( nStyle & ( IMAGE_DRAW_HIGHLIGHT | IMAGE_DRAW_DEACTIVE ) )
435 BitmapWriteAccess* pAcc = aTmpBmp.AcquireWriteAccess();
437 if( pAcc )
439 const StyleSettings& rSettings = pOutDev->GetSettings().GetStyleSettings();
440 Color aColor;
441 BitmapColor aCol;
442 const long nW = pAcc->Width();
443 const long nH = pAcc->Height();
444 BYTE* pMapR = new BYTE[ 256 ];
445 BYTE* pMapG = new BYTE[ 256 ];
446 BYTE* pMapB = new BYTE[ 256 ];
447 long nX, nY;
449 if( nStyle & IMAGE_DRAW_HIGHLIGHT )
450 aColor = rSettings.GetHighlightColor();
451 else
452 aColor = rSettings.GetDeactiveColor();
454 const BYTE cR = aColor.GetRed();
455 const BYTE cG = aColor.GetGreen();
456 const BYTE cB = aColor.GetBlue();
458 for( nX = 0L; nX < 256L; nX++ )
460 pMapR[ nX ] = (BYTE) ( ( ( nY = ( nX + cR ) >> 1 ) > 255 ) ? 255 : nY );
461 pMapG[ nX ] = (BYTE) ( ( ( nY = ( nX + cG ) >> 1 ) > 255 ) ? 255 : nY );
462 pMapB[ nX ] = (BYTE) ( ( ( nY = ( nX + cB ) >> 1 ) > 255 ) ? 255 : nY );
465 if( pAcc->HasPalette() )
467 for( USHORT i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
469 const BitmapColor& rCol = pAcc->GetPaletteColor( i );
470 aCol.SetRed( pMapR[ rCol.GetRed() ] );
471 aCol.SetGreen( pMapG[ rCol.GetGreen() ] );
472 aCol.SetBlue( pMapB[ rCol.GetBlue() ] );
473 pAcc->SetPaletteColor( i, aCol );
476 else if( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
478 for( nY = 0L; nY < nH; nY++ )
480 Scanline pScan = pAcc->GetScanline( nY );
482 for( nX = 0L; nX < nW; nX++ )
484 *pScan = pMapB[ *pScan ]; pScan++;
485 *pScan = pMapG[ *pScan ]; pScan++;
486 *pScan = pMapR[ *pScan ]; pScan++;
490 else
492 for( nY = 0L; nY < nH; nY++ )
494 for( nX = 0L; nX < nW; nX++ )
496 aCol = pAcc->GetPixel( nY, nX );
497 aCol.SetRed( pMapR[ aCol.GetRed() ] );
498 aCol.SetGreen( pMapG[ aCol.GetGreen() ] );
499 aCol.SetBlue( pMapB[ aCol.GetBlue() ] );
500 pAcc->SetPixel( nY, nX, aCol );
505 delete[] pMapR;
506 delete[] pMapG;
507 delete[] pMapB;
508 aTmpBmp.ReleaseAccess( pAcc );
512 if( nStyle & IMAGE_DRAW_SEMITRANSPARENT )
514 if( aTmpBmpEx.IsTransparent() )
516 Bitmap aAlphaBmp( aTmpBmpEx.GetAlpha().GetBitmap() );
518 aAlphaBmp.Adjust( 50 );
519 aTmpBmpEx = BitmapEx( aTmpBmp, AlphaMask( aAlphaBmp ) );
521 else
523 BYTE cErase = 128;
524 aTmpBmpEx = BitmapEx( aTmpBmp, AlphaMask( aTmpBmp.GetSizePixel(), &cErase ) );
527 else
529 if( aTmpBmpEx.IsAlpha() )
530 aTmpBmpEx = BitmapEx( aTmpBmp, aTmpBmpEx.GetAlpha() );
531 else if( aTmpBmpEx.IsAlpha() )
532 aTmpBmpEx = BitmapEx( aTmpBmp, aTmpBmpEx.GetMask() );
535 pOutDev->DrawBitmapEx( rPos, aOutSize, aTmpBmpEx );
537 else
539 const BitmapEx* pOutputBmp;
541 if( pOutDev->GetOutDevType() == OUTDEV_WINDOW )
543 ImplUpdateDisplayBmp( pOutDev );
544 pOutputBmp = mpDisplayBmp;
546 else
547 pOutputBmp = &maBmpEx;
549 if( pOutputBmp )
550 pOutDev->DrawBitmapEx( rPos, aOutSize, aSrcPos, maSize, *pOutputBmp );
556 // -----------------------------------------------------------------------
558 void ImplImageBmp::ImplUpdateDisplayBmp( OutputDevice*
559 #if defined WIN || defined WNT
560 pOutDev
561 #endif
564 if( !mpDisplayBmp && !maBmpEx.IsEmpty() )
566 #if defined WIN || defined WNT
567 if( maBmpEx.IsAlpha() )
568 mpDisplayBmp = new BitmapEx( maBmpEx );
569 else
571 const Bitmap aBmp( maBmpEx.GetBitmap().CreateDisplayBitmap( pOutDev ) );
573 if( maBmpEx.IsTransparent() )
574 mpDisplayBmp = new BitmapEx( aBmp, maBmpEx.GetMask().CreateDisplayBitmap( pOutDev ) );
575 else
576 mpDisplayBmp = new BitmapEx( aBmp );
578 #else
579 mpDisplayBmp = new BitmapEx( maBmpEx );
580 #endif
584 // -----------------------------------------------------------------------
586 void ImplImageBmp::ImplUpdateDisabledBmpEx( int nPos )
588 const Size aTotalSize( maBmpEx.GetSizePixel() );
590 if( maDisabledBmpEx.IsEmpty() )
592 Bitmap aGrey( aTotalSize, 8, &Bitmap::GetGreyPalette( 256 ) );
593 AlphaMask aGreyAlphaMask( aTotalSize );
595 maDisabledBmpEx = BitmapEx( aGrey, aGreyAlphaMask );
596 nPos = -1;
599 Bitmap aBmp( maBmpEx.GetBitmap() );
600 BitmapReadAccess* pBmp( aBmp.AcquireReadAccess() );
601 AlphaMask aBmpAlphaMask( maBmpEx.GetAlpha() );
602 BitmapReadAccess* pBmpAlphaMask( aBmpAlphaMask.AcquireReadAccess() );
603 Bitmap aGrey( maDisabledBmpEx.GetBitmap() );
604 BitmapWriteAccess* pGrey( aGrey.AcquireWriteAccess() );
605 AlphaMask aGreyAlphaMask( maDisabledBmpEx.GetAlpha() );
606 BitmapWriteAccess* pGreyAlphaMask( aGreyAlphaMask.AcquireWriteAccess() );
608 if( pBmp && pBmpAlphaMask && pGrey && pGreyAlphaMask )
610 BitmapColor aGreyVal( 0 );
611 BitmapColor aGreyAlphaMaskVal( 0 );
612 const Point aPos( ( nPos < 0 ) ? 0 : ( nPos * maSize.Width() ), 0 );
613 const int nLeft = aPos.X(), nRight = nLeft + ( ( nPos < 0 ) ? aTotalSize.Width() : maSize.Width() );
614 const int nTop = aPos.Y(), nBottom = nTop + maSize.Height();
616 for( int nY = nTop; nY < nBottom; ++nY )
618 for( int nX = nLeft; nX < nRight; ++nX )
620 aGreyVal.SetIndex( pBmp->GetLuminance( nY, nX ) );
621 pGrey->SetPixel( nY, nX, aGreyVal );
623 const BitmapColor aBmpAlphaMaskVal( pBmpAlphaMask->GetPixel( nY, nX ) );
625 aGreyAlphaMaskVal.SetIndex( static_cast< sal_uInt8 >( ::std::min( aBmpAlphaMaskVal.GetIndex() + 178ul, 255ul ) ) );
626 pGreyAlphaMask->SetPixel( nY, nX, aGreyAlphaMaskVal );
631 aBmp.ReleaseAccess( pBmp );
632 aBmpAlphaMask.ReleaseAccess( pBmpAlphaMask );
633 aGrey.ReleaseAccess( pGrey );
634 aGreyAlphaMask.ReleaseAccess( pGreyAlphaMask );
636 maDisabledBmpEx = BitmapEx( aGrey, aGreyAlphaMask );