xref: /aoo41x/main/vcl/source/gdi/image.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 // MARKER(update_precomp.py): autogen include statement, do not remove
28 #include "precompiled_vcl.hxx"
29 
30 #include <boost/scoped_ptr.hpp>
31 #include <boost/scoped_array.hpp>
32 
33 #include <rtl/logfile.hxx>
34 
35 #include <tools/debug.hxx>
36 #include <tools/stream.hxx>
37 #include <tools/rc.h>
38 #include <tools/rc.hxx>
39 #include <tools/resmgr.hxx>
40 
41 #include <vcl/settings.hxx>
42 #include <vcl/outdev.hxx>
43 #include <vcl/graph.hxx>
44 #include <vcl/svapp.hxx>
45 #include <vcl/image.hxx>
46 
47 #include <impimagetree.hxx>
48 #include <image.h>
49 
50 #if OSL_DEBUG_LEVEL > 0
51 #include <rtl/strbuf.hxx>
52 #endif
53 
54 DBG_NAME( Image )
55 DBG_NAME( ImageList )
56 
57 #define IMAGE_FILE_VERSION 100
58 
59 using namespace ::com::sun::star;
60 
61 // ---------
62 // - Image -
63 // ---------
64 
65 Image::Image() :
66 	mpImplData( NULL )
67 {
68 	DBG_CTOR( Image, NULL );
69 }
70 
71 // -----------------------------------------------------------------------
72 
73 Image::Image( const ResId& rResId ) :
74 	mpImplData( NULL )
75 {
76 	DBG_CTOR( Image, NULL );
77 
78 	rResId.SetRT( RSC_IMAGE );
79 
80 	ResMgr* pResMgr = rResId.GetResMgr();
81 	if( pResMgr && pResMgr->GetResource( rResId ) )
82 	{
83 		pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
84 
85 		BitmapEx	aBmpEx;
86 		sal_uLong 		nObjMask = pResMgr->ReadLong();
87 
88 		if( nObjMask & RSC_IMAGE_IMAGEBITMAP )
89 		{
90 			aBmpEx = BitmapEx( ResId( (RSHEADER_TYPE*)pResMgr->GetClass(), *pResMgr ) );
91 			pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
92 		}
93 
94         if( nObjMask & RSC_IMAGE_MASKBITMAP )
95         {
96             if( !aBmpEx.IsEmpty() && aBmpEx.GetTransparentType() == TRANSPARENT_NONE )
97             {
98                 const Bitmap aMaskBitmap( ResId( (RSHEADER_TYPE*)pResMgr->GetClass(), *pResMgr ) );
99                 aBmpEx = BitmapEx( aBmpEx.GetBitmap(), aMaskBitmap );
100             }
101 
102             pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
103         }
104 
105         if( nObjMask & RSC_IMAGE_MASKCOLOR )
106         {
107             if( !aBmpEx.IsEmpty() && aBmpEx.GetTransparentType() == TRANSPARENT_NONE )
108             {
109                 const Color aMaskColor( ResId( (RSHEADER_TYPE*)pResMgr->GetClass(), *pResMgr ) );
110                 aBmpEx = BitmapEx( aBmpEx.GetBitmap(), aMaskColor );
111             }
112 
113             pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
114         }
115         if( ! aBmpEx.IsEmpty() )
116 			ImplInit( aBmpEx );
117 	}
118 }
119 
120 // -----------------------------------------------------------------------
121 
122 Image::Image( const Image& rImage ) :
123 	mpImplData( rImage.mpImplData )
124 {
125 	DBG_CTOR( Image, NULL );
126 
127 	if( mpImplData )
128 		++mpImplData->mnRefCount;
129 }
130 
131 // -----------------------------------------------------------------------
132 
133 Image::Image( const BitmapEx& rBitmapEx ) :
134 	mpImplData( NULL )
135 {
136 	DBG_CTOR( Image, NULL );
137 
138 	ImplInit( rBitmapEx );
139 }
140 
141 // -----------------------------------------------------------------------
142 
143 Image::Image( const Bitmap& rBitmap ) :
144 	mpImplData( NULL )
145 {
146 	DBG_CTOR( Image, NULL );
147 
148 	ImplInit( rBitmap );
149 }
150 
151 // -----------------------------------------------------------------------
152 
153 Image::Image( const Bitmap& rBitmap, const Bitmap& rMaskBitmap ) :
154 	mpImplData( NULL )
155 {
156 	DBG_CTOR( Image, NULL );
157 
158 	const BitmapEx aBmpEx( rBitmap, rMaskBitmap );
159 
160 	ImplInit( aBmpEx );
161 }
162 
163 // -----------------------------------------------------------------------
164 
165 Image::Image( const Bitmap& rBitmap, const Color& rColor ) :
166 	mpImplData( NULL )
167 {
168 	DBG_CTOR( Image, NULL );
169 
170 	const BitmapEx aBmpEx( rBitmap, rColor );
171 
172 	ImplInit( aBmpEx );
173 }
174 
175 // -----------------------------------------------------------------------
176 
177 Image::Image( const uno::Reference< graphic::XGraphic >& rxGraphic ) :
178 	mpImplData( NULL )
179 {
180 	DBG_CTOR( Image, NULL );
181 
182 	const Graphic aGraphic( rxGraphic );
183 	ImplInit( aGraphic.GetBitmapEx() );
184 }
185 
186 // -----------------------------------------------------------------------
187 
188 Image::~Image()
189 {
190 	DBG_DTOR( Image, NULL );
191 
192 	if( mpImplData && ( 0 == --mpImplData->mnRefCount ) )
193 		delete mpImplData;
194 }
195 
196 // -----------------------------------------------------------------------
197 
198 void Image::ImplInit( const BitmapEx& rBmpEx )
199 {
200 	if( !rBmpEx.IsEmpty() )
201 	{
202 		mpImplData = new ImplImage;
203 		mpImplData->mnRefCount = 1;
204 
205 		if( rBmpEx.GetTransparentType() == TRANSPARENT_NONE )
206 		{
207 			mpImplData->meType = IMAGETYPE_BITMAP;
208 			mpImplData->mpData = new Bitmap( rBmpEx.GetBitmap() );
209 		}
210 		else
211 		{
212 			mpImplData->meType = IMAGETYPE_IMAGE;
213 			mpImplData->mpData = new ImplImageData( rBmpEx );
214 		}
215 	}
216 }
217 
218 // -----------------------------------------------------------------------
219 
220 Size Image::GetSizePixel() const
221 {
222 	DBG_CHKTHIS( Image, NULL );
223 
224 	Size aRet;
225 
226 	if( mpImplData )
227 	{
228 		switch( mpImplData->meType )
229 		{
230 			case IMAGETYPE_BITMAP:
231 				aRet = static_cast< Bitmap* >( mpImplData->mpData )->GetSizePixel();
232 			break;
233 
234 			case IMAGETYPE_IMAGE:
235 				aRet = static_cast< ImplImageData* >( mpImplData->mpData )->maBmpEx.GetSizePixel();
236 			break;
237 		}
238 	}
239 
240 	return aRet;
241 }
242 
243 // -----------------------------------------------------------------------
244 
245 BitmapEx Image::GetBitmapEx() const
246 {
247 	DBG_CHKTHIS( Image, NULL );
248 
249 	BitmapEx aRet;
250 
251 	if( mpImplData )
252 	{
253 		switch( mpImplData->meType )
254 		{
255 			case IMAGETYPE_BITMAP:
256 				aRet = *static_cast< Bitmap* >( mpImplData->mpData );
257 			break;
258 
259 			case IMAGETYPE_IMAGE:
260 				aRet = static_cast< ImplImageData* >( mpImplData->mpData )->maBmpEx;
261 			break;
262 		}
263 	}
264 
265 	return aRet;
266 }
267 
268 // -----------------------------------------------------------------------
269 
270 uno::Reference< graphic::XGraphic > Image::GetXGraphic() const
271 {
272 	const Graphic aGraphic( GetBitmapEx() );
273 
274 	return aGraphic.GetXGraphic();
275 }
276 
277 // -----------------------------------------------------------------------
278 
279 Image Image::GetColorTransformedImage( ImageColorTransform eColorTransform ) const
280 {
281 	DBG_CHKTHIS( Image, NULL );
282 
283     Image aRet;
284 
285     if( IMAGECOLORTRANSFORM_HIGHCONTRAST == eColorTransform )
286     {
287         BitmapEx aBmpEx( GetBitmapEx() );
288 
289         if( !aBmpEx.IsEmpty() )
290         {
291             Color*  pSrcColors = NULL;
292             Color*  pDstColors = NULL;
293             sal_uLong   nColorCount = 0;
294 
295             Image::GetColorTransformArrays( eColorTransform, pSrcColors, pDstColors, nColorCount );
296 
297             if( nColorCount && pSrcColors && pDstColors )
298             {
299                 aBmpEx.Replace( pSrcColors, pDstColors, nColorCount );
300 				aRet = Image( aBmpEx );
301             }
302 
303             delete[] pSrcColors;
304             delete[] pDstColors;
305         }
306     }
307 	else if( IMAGECOLORTRANSFORM_MONOCHROME_BLACK == eColorTransform ||
308 			 IMAGECOLORTRANSFORM_MONOCHROME_WHITE == eColorTransform  )
309 	{
310         BitmapEx aBmpEx( GetBitmapEx() );
311 
312         if( !aBmpEx.IsEmpty() )
313 			aRet = Image( aBmpEx.GetColorTransformedBitmapEx( ( BmpColorMode )( eColorTransform ) ) );
314 	}
315 
316     if( !aRet )
317         aRet = *this;
318 
319     return aRet;
320 }
321 
322 // -----------------------------------------------------------------------
323 
324 void Image::Invert()
325 {
326     BitmapEx aInvertedBmp( GetBitmapEx() );
327     aInvertedBmp.Invert();
328     *this = aInvertedBmp;
329 }
330 
331 // -----------------------------------------------------------------------
332 
333 void Image::GetColorTransformArrays( ImageColorTransform eColorTransform,
334                                      Color*& rpSrcColor, Color*& rpDstColor, sal_uLong& rColorCount )
335 {
336     if( IMAGECOLORTRANSFORM_HIGHCONTRAST == eColorTransform )
337     {
338         rpSrcColor = new Color[ 4 ];
339         rpDstColor = new Color[ 4 ];
340         rColorCount = 4;
341 
342         rpSrcColor[ 0 ] = Color( COL_BLACK );
343         rpDstColor[ 0 ] = Color( COL_WHITE );
344 
345         rpSrcColor[ 1 ] = Color( COL_WHITE );
346         rpDstColor[ 1 ] = Color( COL_BLACK );
347 
348         rpSrcColor[ 2 ] = Color( COL_BLUE );
349         rpDstColor[ 2 ] = Color( COL_WHITE );
350 
351         rpSrcColor[ 3 ] = Color( COL_LIGHTBLUE );
352         rpDstColor[ 3 ] = Color( COL_WHITE );
353     }
354     else
355     {
356         rpSrcColor = rpDstColor = NULL;
357         rColorCount = 0;
358     }
359 }
360 
361 // -----------------------------------------------------------------------
362 
363 Image& Image::operator=( const Image& rImage )
364 {
365 	DBG_CHKTHIS( Image, NULL );
366 	DBG_CHKOBJ( &rImage, Image, NULL );
367 
368 	if( rImage.mpImplData )
369 		++rImage.mpImplData->mnRefCount;
370 
371 	if( mpImplData && ( 0 == --mpImplData->mnRefCount ) )
372 		delete mpImplData;
373 
374 	mpImplData = rImage.mpImplData;
375 
376 	return *this;
377 }
378 
379 // -----------------------------------------------------------------------
380 
381 sal_Bool Image::operator==( const Image& rImage ) const
382 {
383 	DBG_CHKTHIS( Image, NULL );
384 	DBG_CHKOBJ( &rImage, Image, NULL );
385 
386 	bool bRet = false;
387 
388 	if( rImage.mpImplData == mpImplData )
389 		bRet = true;
390 	else if( !rImage.mpImplData || !mpImplData )
391 		bRet = false;
392 	else if( rImage.mpImplData->mpData == mpImplData->mpData )
393 		bRet = true;
394 	else if( rImage.mpImplData->meType == mpImplData->meType )
395 	{
396 		switch( mpImplData->meType )
397 		{
398 			case IMAGETYPE_BITMAP:
399 				bRet = ( *static_cast< Bitmap* >( rImage.mpImplData->mpData ) == *static_cast< Bitmap* >( mpImplData->mpData ) );
400 			break;
401 
402 			case IMAGETYPE_IMAGE:
403 				bRet = static_cast< ImplImageData* >( rImage.mpImplData->mpData )->IsEqual( *static_cast< ImplImageData* >( mpImplData->mpData ) );
404 			break;
405 
406 			default:
407 				bRet = false;
408 			break;
409 		}
410 	}
411 
412 	return bRet;
413 }
414 
415 // -------------
416 // - ImageList -
417 // -------------
418 
419 ImageList::ImageList( sal_uInt16 nInit, sal_uInt16 nGrow ) :
420 	mpImplData( NULL ),
421 	mnInitSize( nInit ),
422 	mnGrowSize( nGrow )
423 {
424 	DBG_CTOR( ImageList, NULL );
425 }
426 
427 // -----------------------------------------------------------------------
428 
429 ImageList::ImageList( const ResId& rResId ) :
430 	mpImplData( NULL ),
431 	mnInitSize( 1 ),
432 	mnGrowSize( 4 )
433 {
434     RTL_LOGFILE_CONTEXT( aLog, "vcl: ImageList::ImageList( const ResId& rResId )" );
435 
436 	DBG_CTOR( ImageList, NULL );
437 
438 	rResId.SetRT( RSC_IMAGELIST );
439 
440 	ResMgr* pResMgr = rResId.GetResMgr();
441 
442 	if( pResMgr && pResMgr->GetResource( rResId ) )
443 	{
444 		pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
445 
446 		sal_uLong 								nObjMask = pResMgr->ReadLong();
447 		const String						aPrefix( pResMgr->ReadString() );
448         ::boost::scoped_ptr< Color >        spMaskColor;
449 
450 		if( nObjMask & RSC_IMAGE_MASKCOLOR )
451             spMaskColor.reset( new Color( ResId( (RSHEADER_TYPE*)pResMgr->GetClass(), *pResMgr ) ) );
452 
453 		pResMgr->Increment( pResMgr->GetObjSize( (RSHEADER_TYPE*)pResMgr->GetClass() ) );
454 
455 		if( nObjMask & RSC_IMAGELIST_IDLIST )
456 		{
457 			for( sal_Int32 i = 0, nCount = pResMgr->ReadLong(); i < nCount; ++i )
458 				pResMgr->ReadLong();
459 		}
460 
461 		sal_Int32 nCount = pResMgr->ReadLong();
462 		ImplInit( static_cast< sal_uInt16 >( nCount ), Size() );
463 
464 		BitmapEx aEmpty;
465 		for( sal_Int32 i = 0; i < nCount; ++i )
466 		{
467 			rtl::OUString aName = pResMgr->ReadString();
468 			sal_uInt16 nId = static_cast< sal_uInt16 >( pResMgr->ReadLong() );
469 			mpImplData->AddImage( aName, nId, aEmpty );
470 		}
471 
472 		if( nObjMask & RSC_IMAGELIST_IDCOUNT )
473 			pResMgr->ReadShort();
474 	}
475 }
476 
477 // -----------------------------------------------------------------------
478 
479 ImageList::ImageList( const ::std::vector< ::rtl::OUString >& rNameVector,
480 					  const ::rtl::OUString& rPrefix,
481 					  const Color* ) :
482 	mpImplData( NULL ),
483 	mnInitSize( 1 ),
484 	mnGrowSize( 4 )
485 {
486     RTL_LOGFILE_CONTEXT( aLog, "vcl: ImageList::ImageList(const vector< OUString >& ..." );
487 
488 	DBG_CTOR( ImageList, NULL );
489 
490     ImplInit( sal::static_int_cast< sal_uInt16 >( rNameVector.size() ), Size() );
491 
492 	mpImplData->maPrefix = rPrefix;
493 	for( sal_uInt32 i = 0; i < rNameVector.size(); ++i )
494 	{
495 //		fprintf (stderr, "List %p [%d]: '%s'\n",
496 //				 this, i, rtl::OUStringToOString( rNameVector[i], RTL_TEXTENCODING_UTF8 ).getStr() );
497 		mpImplData->AddImage( rNameVector[ i ], static_cast< sal_uInt16 >( i ) + 1, BitmapEx() );
498 	}
499 }
500 
501 // -----------------------------------------------------------------------
502 
503 ImageList::ImageList( const ImageList& rImageList ) :
504 	mpImplData( rImageList.mpImplData ),
505 	mnInitSize( rImageList.mnInitSize ),
506 	mnGrowSize( rImageList.mnGrowSize )
507 {
508 	DBG_CTOR( ImageList, NULL );
509 
510 	if( mpImplData )
511 		++mpImplData->mnRefCount;
512 }
513 
514 // -----------------------------------------------------------------------
515 
516 ImageList::~ImageList()
517 {
518 	DBG_DTOR( ImageList, NULL );
519 
520 	if( mpImplData && ( 0 == --mpImplData->mnRefCount ) )
521 		delete mpImplData;
522 }
523 
524 void ImageList::ImplInit( sal_uInt16 nItems, const Size &rSize )
525 {
526 	mpImplData = new ImplImageList;
527 	mpImplData->mnRefCount = 1;
528 	mpImplData->maImages.reserve( nItems );
529 	mpImplData->maImageSize = rSize;
530 }
531 
532 // -----------------------------------------------------------------------
533 
534 void ImageAryData::Load(const rtl::OUString &rPrefix)
535 {
536     static ImplImageTreeSingletonRef aImageTree;
537 
538 	::rtl::OUString aSymbolsStyle = Application::GetSettings().GetStyleSettings().GetCurrentSymbolsStyleName();
539 
540 	BitmapEx aBmpEx;
541 
542 //	fprintf (stderr, "Attempt load of '%s'\n",
543 //			 rtl::OUStringToOString( maName, RTL_TEXTENCODING_UTF8 ).getStr() );
544 
545 	rtl::OUString aFileName = rPrefix;
546 	aFileName += maName;
547 #if OSL_DEBUG_LEVEL > 0
548 	bool bSuccess =
549 #endif
550         aImageTree->loadImage( aFileName, aSymbolsStyle, maBitmapEx, true );
551 #if OSL_DEBUG_LEVEL > 0
552     if ( !bSuccess )
553     {
554         ::rtl::OStringBuffer aMessage;
555         aMessage.append( "ImageAryData::Load: failed to load image '" );
556         aMessage.append( ::rtl::OUStringToOString( aFileName, RTL_TEXTENCODING_UTF8 ).getStr() );
557         aMessage.append( "'" );
558         OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() );
559     }
560 #endif
561 }
562 
563 // -----------------------------------------------------------------------
564 
565 void ImageList::ImplMakeUnique()
566 {
567 	if( mpImplData && mpImplData->mnRefCount > 1 )
568 	{
569 		--mpImplData->mnRefCount;
570 		mpImplData = new ImplImageList( *mpImplData ) ;
571 	}
572 }
573 
574 // -----------------------------------------------------------------------
575 // Rather a performance hazard:
576 BitmapEx ImageList::GetAsHorizontalStrip() const
577 {
578 	Size aSize( mpImplData->maImageSize );
579     sal_uInt16 nCount = GetImageCount();
580 	if( !nCount )
581 		return BitmapEx();
582 	aSize.Width() *= nCount;
583 
584 	// Load any stragglers
585     for (sal_uInt16 nIdx = 0; nIdx < nCount; nIdx++)
586 	{
587 		ImageAryData *pData = mpImplData->maImages[ nIdx ];
588 		if( pData->IsLoadable() )
589 			pData->Load( mpImplData->maPrefix );
590 	}
591 
592 	BitmapEx aTempl = mpImplData->maImages[ 0 ]->maBitmapEx;
593 	BitmapEx aResult;
594 	Bitmap aPixels( aSize, aTempl.GetBitmap().GetBitCount() );
595 	if( aTempl.IsAlpha() )
596 		aResult = BitmapEx( aPixels, AlphaMask( aSize ) );
597 	else if( aTempl.IsTransparent() )
598 		aResult = BitmapEx( aPixels, Bitmap( aSize, aTempl.GetMask().GetBitCount() ) );
599 	else
600 		aResult = BitmapEx( aPixels );
601 
602 	Rectangle aSrcRect( Point( 0, 0 ), mpImplData->maImageSize );
603     for (sal_uInt16 nIdx = 0; nIdx < nCount; nIdx++)
604 	{
605 		Rectangle aDestRect( Point( nIdx * mpImplData->maImageSize.Width(), 0 ),
606 							 mpImplData->maImageSize );
607 		ImageAryData *pData = mpImplData->maImages[ nIdx ];
608 		aResult.CopyPixel( aDestRect, aSrcRect, &pData->maBitmapEx);
609 	}
610 
611 	return aResult;
612 }
613 
614 // -----------------------------------------------------------------------
615 
616 void ImageList::InsertFromHorizontalStrip( const BitmapEx &rBitmapEx,
617 										   const std::vector< rtl::OUString > &rNameVector )
618 {
619     sal_uInt16 nItems = sal::static_int_cast< sal_uInt16 >( rNameVector.size() );
620 
621 //	fprintf (stderr, "InsertFromHorizontalStrip (1) [%d items]\n", nItems);
622 
623 	if (!nItems)
624 			return;
625 
626 	Size aSize( rBitmapEx.GetSizePixel() );
627 	DBG_ASSERT (rBitmapEx.GetSizePixel().Width() % nItems == 0,
628 				"ImageList::InsertFromHorizontalStrip - very odd size");
629 	aSize.Width() /= nItems;
630 	ImplInit( nItems, aSize );
631 
632     for (sal_uInt16 nIdx = 0; nIdx < nItems; nIdx++)
633 	{
634 		BitmapEx aBitmap( rBitmapEx, Point( nIdx * aSize.Width(), 0 ), aSize );
635 		mpImplData->AddImage( rNameVector[ nIdx ], nIdx + 1, aBitmap );
636 	}
637 }
638 
639 // -----------------------------------------------------------------------
640 
641 void ImageList::InsertFromHorizontalBitmap( const ResId& rResId,
642 											sal_uInt16       nCount,
643 											const Color *pMaskColor,
644 											const Color *pSearchColors,
645 											const Color *pReplaceColors,
646 											sal_uLong        nColorCount)
647 {
648 	BitmapEx aBmpEx( rResId );
649 	if (!aBmpEx.IsTransparent())
650 	{
651         if( pMaskColor )
652             aBmpEx = BitmapEx( aBmpEx.GetBitmap(), *pMaskColor );
653         else
654             aBmpEx = BitmapEx( aBmpEx.GetBitmap() );
655     }
656 	if ( nColorCount && pSearchColors && pReplaceColors )
657 		aBmpEx.Replace( pSearchColors, pReplaceColors, nColorCount );
658 
659 	std::vector< rtl::OUString > aNames( nCount );
660 	InsertFromHorizontalStrip( aBmpEx, aNames );
661 }
662 
663 // -----------------------------------------------------------------------
664 
665 sal_uInt16 ImageList::ImplGetImageId( const ::rtl::OUString& rImageName ) const
666 {
667 	DBG_CHKTHIS( ImageList, NULL );
668 
669 	ImageAryData *pImg = mpImplData->maNameHash[ rImageName ];
670 	if( pImg )
671 		return pImg->mnId;
672 	else
673 		return 0;
674 }
675 
676 // -----------------------------------------------------------------------
677 
678 void ImageList::AddImage( sal_uInt16 nId, const Image& rImage )
679 {
680 	DBG_CHKTHIS( ImageList, NULL );
681 	DBG_CHKOBJ( &rImage, Image, NULL );
682 	DBG_ASSERT( nId, "ImageList::AddImage(): ImageId == 0" );
683 	DBG_ASSERT( GetImagePos( nId ) == IMAGELIST_IMAGE_NOTFOUND, "ImageList::AddImage() - ImageId already exists" );
684 	DBG_ASSERT( rImage.mpImplData, "ImageList::AddImage(): Wrong Size" );
685 	DBG_ASSERT( !mpImplData || (rImage.GetSizePixel() == mpImplData->maImageSize), "ImageList::AddImage(): Wrong Size" );
686 
687 	if( !mpImplData )
688 		ImplInit( 0, rImage.GetSizePixel() );
689 
690 	mpImplData->AddImage( rtl::OUString(), nId, rImage.GetBitmapEx());
691 }
692 
693 // -----------------------------------------------------------------------
694 
695 void ImageList::AddImage( const ::rtl::OUString& rImageName, const Image& rImage )
696 {
697 	DBG_ASSERT( GetImagePos( rImageName ) == IMAGELIST_IMAGE_NOTFOUND, "ImageList::AddImage() - ImageName already exists" );
698 
699 	if( !mpImplData )
700 		ImplInit( 0, rImage.GetSizePixel() );
701 
702     mpImplData->AddImage( rImageName, GetImageCount() + 1,
703 						  rImage.GetBitmapEx() );
704 }
705 
706 // -----------------------------------------------------------------------
707 
708 void ImageList::ReplaceImage( sal_uInt16 nId, const Image& rImage )
709 {
710 	DBG_CHKTHIS( ImageList, NULL );
711 	DBG_CHKOBJ( &rImage, Image, NULL );
712 	DBG_ASSERT( GetImagePos( nId ) != IMAGELIST_IMAGE_NOTFOUND, "ImageList::ReplaceImage(): Unknown nId" );
713 
714 	RemoveImage( nId );
715 	AddImage( nId, rImage );
716 }
717 
718 // -----------------------------------------------------------------------
719 
720 void ImageList::ReplaceImage( const ::rtl::OUString& rImageName, const Image& rImage )
721 {
722     const sal_uInt16 nId = ImplGetImageId( rImageName );
723 
724 	if( nId )
725     {
726         RemoveImage( nId );
727 
728         if( !mpImplData )
729 		    ImplInit( 0, rImage.GetSizePixel() );
730         mpImplData->AddImage( rImageName, nId, rImage.GetBitmapEx());
731     }
732 }
733 
734 // -----------------------------------------------------------------------
735 
736 void ImageList::ReplaceImage( sal_uInt16 nId, sal_uInt16 nReplaceId )
737 {
738 	DBG_CHKTHIS( ImageList, NULL );
739 	DBG_ASSERT( GetImagePos( nId ) != IMAGELIST_IMAGE_NOTFOUND, "ImageList::ReplaceImage(): Unknown nId" );
740 	DBG_ASSERT( GetImagePos( nReplaceId ) != IMAGELIST_IMAGE_NOTFOUND, "ImageList::ReplaceImage(): Unknown nReplaceId" );
741 
742 	sal_uLong nPosDest = GetImagePos( nId );
743 	sal_uLong nPosSrc = GetImagePos( nReplaceId );
744 	if( nPosDest != IMAGELIST_IMAGE_NOTFOUND &&
745 		nPosSrc != IMAGELIST_IMAGE_NOTFOUND )
746 	{
747 		ImplMakeUnique();
748 		mpImplData->maImages[nPosDest] = mpImplData->maImages[nPosSrc];
749 	}
750 }
751 
752 // -----------------------------------------------------------------------
753 
754 void ImageList::ReplaceImage( const ::rtl::OUString& rImageName, const ::rtl::OUString& rReplaceName )
755 {
756     const sal_uInt16 nId1 = ImplGetImageId( rImageName ), nId2 = ImplGetImageId( rReplaceName );
757 
758 	if( nId1 && nId2 )
759         ReplaceImage( nId1, nId2 );
760 }
761 
762 // -----------------------------------------------------------------------
763 
764 void ImageList::RemoveImage( sal_uInt16 nId )
765 {
766 	DBG_CHKTHIS( ImageList, NULL );
767 
768 	for( sal_uInt32 i = 0; i < mpImplData->maImages.size(); ++i )
769 	{
770 		if( mpImplData->maImages[ i ]->mnId == nId )
771 		{
772 			mpImplData->RemoveImage( static_cast< sal_uInt16 >( i ) );
773 			break;
774 		}
775 	}
776 }
777 
778 // -----------------------------------------------------------------------
779 
780 void ImageList::RemoveImage( const ::rtl::OUString& rImageName )
781 {
782     const sal_uInt16 nId = ImplGetImageId( rImageName );
783 
784     if( nId )
785         RemoveImage( nId );
786 }
787 
788 // -----------------------------------------------------------------------
789 
790 Image ImageList::GetImage( sal_uInt16 nId ) const
791 {
792 	DBG_CHKTHIS( ImageList, NULL );
793 
794 //	fprintf (stderr, "GetImage %d\n", nId);
795 
796 	Image aRet;
797 
798 	if( mpImplData )
799 	{
800 		std::vector<ImageAryData *>::iterator aIter;
801 		for( aIter = mpImplData->maImages.begin();
802 			 aIter != mpImplData->maImages.end(); aIter++)
803 		{
804 			if ((*aIter)->mnId == nId)
805 			{
806 				if( (*aIter)->IsLoadable() )
807 					(*aIter)->Load( mpImplData->maPrefix );
808 
809 				aRet = Image( (*aIter)->maBitmapEx );
810 			}
811 		}
812 	}
813 
814 	return aRet;
815 }
816 
817 // -----------------------------------------------------------------------
818 
819 Image ImageList::GetImage( const ::rtl::OUString& rImageName ) const
820 {
821 //	fprintf (stderr, "GetImage '%s'\n",
822 //			 rtl::OUStringToOString( rImageName, RTL_TEXTENCODING_UTF8 ).getStr() );
823 
824 	if( mpImplData )
825 	{
826 		ImageAryData *pImg = mpImplData->maNameHash[ rImageName ];
827 
828 		if( pImg )
829 		{
830 			if( pImg->IsLoadable() )
831 				pImg->Load( mpImplData->maPrefix );
832 			return Image( pImg->maBitmapEx );
833 		}
834 	}
835 //	fprintf (stderr, "no such image\n");
836 
837 	return Image();
838 }
839 
840 // -----------------------------------------------------------------------
841 
842 void ImageList::Clear()
843 {
844 	DBG_CHKTHIS( ImageList, NULL );
845 
846 	if( mpImplData && ( 0 == --mpImplData->mnRefCount ) )
847 		delete mpImplData;
848 
849 	mpImplData = NULL;
850 }
851 
852 // -----------------------------------------------------------------------
853 
854 sal_uInt16 ImageList::GetImageCount() const
855 {
856 	DBG_CHKTHIS( ImageList, NULL );
857 
858 	return mpImplData ? static_cast< sal_uInt16 >( mpImplData->maImages.size() ) : 0;
859 }
860 
861 // -----------------------------------------------------------------------
862 
863 sal_uInt16 ImageList::GetImagePos( sal_uInt16 nId ) const
864 {
865 	DBG_CHKTHIS( ImageList, NULL );
866 
867 	if( mpImplData && nId )
868 	{
869 		for( sal_uInt32 i = 0; i < mpImplData->maImages.size(); ++i )
870 		{
871 			if (mpImplData->maImages[ i ]->mnId == nId)
872 				return static_cast< sal_uInt16 >( i );
873 		}
874 	}
875 
876 	return IMAGELIST_IMAGE_NOTFOUND;
877 }
878 
879 bool ImageList::HasImageAtPos( sal_uInt16 nId ) const
880 {
881 	return GetImagePos( nId ) != IMAGELIST_IMAGE_NOTFOUND;
882 }
883 
884 // -----------------------------------------------------------------------
885 
886 sal_uInt16 ImageList::GetImagePos( const ::rtl::OUString& rImageName ) const
887 {
888 	DBG_CHKTHIS( ImageList, NULL );
889 
890 	if( mpImplData && rImageName.getLength() )
891 	{
892 		for( sal_uInt32 i = 0; i < mpImplData->maImages.size(); i++ )
893 		{
894 			if (mpImplData->maImages[i]->maName == rImageName)
895 				return static_cast< sal_uInt16 >( i );
896 		}
897 	}
898 
899 	return IMAGELIST_IMAGE_NOTFOUND;
900 }
901 
902 // -----------------------------------------------------------------------
903 
904 sal_uInt16 ImageList::GetImageId( sal_uInt16 nPos ) const
905 {
906 	DBG_CHKTHIS( ImageList, NULL );
907 
908     if( mpImplData && (nPos < GetImageCount()) )
909 		return mpImplData->maImages[ nPos ]->mnId;
910 
911 	return 0;
912 }
913 
914 // -----------------------------------------------------------------------
915 
916 void ImageList::GetImageIds( ::std::vector< sal_uInt16 >& rIds ) const
917 {
918     RTL_LOGFILE_CONTEXT( aLog, "vcl: ImageList::GetImageIds" );
919 
920 	DBG_CHKTHIS( ImageList, NULL );
921 
922 	rIds = ::std::vector< sal_uInt16 >();
923 
924 	if( mpImplData )
925 	{
926 		for( sal_uInt32 i = 0; i < mpImplData->maImages.size(); i++ )
927 			rIds.push_back( mpImplData->maImages[i]->mnId );
928 	}
929 }
930 
931 // -----------------------------------------------------------------------
932 
933 ::rtl::OUString	ImageList::GetImageName( sal_uInt16 nPos ) const
934 {
935 	DBG_CHKTHIS( ImageList, NULL );
936 
937     if( mpImplData && (nPos < GetImageCount()) )
938 		return mpImplData->maImages[ nPos ]->maName;
939 
940 	return ::rtl::OUString();
941 }
942 
943 // -----------------------------------------------------------------------
944 
945 void ImageList::GetImageNames( ::std::vector< ::rtl::OUString >& rNames ) const
946 {
947     RTL_LOGFILE_CONTEXT( aLog, "vcl: ImageList::GetImageNames" );
948 
949 	DBG_CHKTHIS( ImageList, NULL );
950 
951 	rNames = ::std::vector< ::rtl::OUString >();
952 
953 	if( mpImplData )
954 	{
955 		for( sal_uInt32 i = 0; i < mpImplData->maImages.size(); i++ )
956         {
957             const rtl::OUString& rName( mpImplData->maImages[ i ]->maName );
958             if( rName.getLength() != 0 )
959                 rNames.push_back( rName );
960         }
961 	}
962 }
963 
964 // -----------------------------------------------------------------------
965 
966 Size ImageList::GetImageSize() const
967 {
968 	DBG_CHKTHIS( ImageList, NULL );
969 
970 	Size aRet;
971 
972 	if( mpImplData )
973 	{
974 		aRet = mpImplData->maImageSize;
975 
976 		// force load of 1st image to see - uncommon case.
977 		if( aRet.Width() == 0 && aRet.Height() == 0 &&
978             !mpImplData->maImages.empty() )
979 		{
980 			Image aTmp = GetImage( mpImplData->maImages[ 0 ]->mnId );
981 			aRet = mpImplData->maImageSize = aTmp.GetSizePixel();
982 		}
983 	}
984 //	fprintf (stderr, "GetImageSize returns %d, %d\n",
985 //			 aRet.Width(), aRet.Height());
986 
987 	return aRet;
988 }
989 
990 // -----------------------------------------------------------------------
991 
992 ImageList& ImageList::operator=( const ImageList& rImageList )
993 {
994 	DBG_CHKTHIS( ImageList, NULL );
995 	DBG_CHKOBJ( &rImageList, ImageList, NULL );
996 
997 	if( rImageList.mpImplData )
998 		++rImageList.mpImplData->mnRefCount;
999 
1000 	if( mpImplData && ( 0 == --mpImplData->mnRefCount ) )
1001 		delete mpImplData;
1002 
1003 	mpImplData = rImageList.mpImplData;
1004 
1005 	return *this;
1006 }
1007 
1008 // -----------------------------------------------------------------------
1009 
1010 sal_Bool ImageList::operator==( const ImageList& rImageList ) const
1011 {
1012 	DBG_CHKTHIS( ImageList, NULL );
1013 	DBG_CHKOBJ( &rImageList, ImageList, NULL );
1014 
1015 	bool bRet = false;
1016 
1017 	if( rImageList.mpImplData == mpImplData )
1018 		bRet = true;
1019 	else if( !rImageList.mpImplData || !mpImplData )
1020 		bRet = false;
1021 	else if( rImageList.GetImageCount() == GetImageCount() &&
1022 		 	 rImageList.mpImplData->maImageSize == mpImplData->maImageSize )
1023 		bRet = true; // strange semantic
1024 
1025 	return bRet;
1026 }
1027