build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / image / ImageList.cxx
blob3dadd1466cfa913324249a19a74a19c83feb9718
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/file.hxx>
21 #include <tools/debug.hxx>
22 #include <tools/stream.hxx>
23 #include <tools/rc.h>
24 #include <tools/rc.hxx>
25 #include <tools/resmgr.hxx>
26 #include <vcl/settings.hxx>
27 #include <vcl/outdev.hxx>
28 #include <vcl/graph.hxx>
29 #include <vcl/graphicfilter.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/image.hxx>
32 #include <vcl/imagerepository.hxx>
33 #include <vcl/ImageTree.hxx>
34 #include <image.h>
36 ImageList::ImageList()
40 ImageList::ImageList(const ResId& rResId)
42 SAL_INFO( "vcl.gdi", "vcl: ImageList::ImageList( const ResId& rResId )" );
44 rResId.SetRT( RSC_IMAGELIST );
46 ResMgr* pResMgr = rResId.GetResMgr();
48 if( pResMgr && pResMgr->GetResource( rResId ) )
50 pResMgr->Increment( sizeof( RSHEADER_TYPE ) );
52 RscImageListFlags nObjMask = (RscImageListFlags)pResMgr->ReadLong();
53 pResMgr->ReadString(); //skip string
55 if( nObjMask & RscImageListFlags::IdList )
57 for( sal_Int32 i = 0, nCount = pResMgr->ReadLong(); i < nCount; ++i )
58 pResMgr->ReadLong();
61 sal_Int32 nCount = pResMgr->ReadLong();
62 ImplInit( static_cast< sal_uInt16 >( nCount ), Size() );
64 BitmapEx aEmpty;
65 for( sal_Int32 i = 0; i < nCount; ++i )
67 OUString aName = pResMgr->ReadString();
68 sal_uInt16 nId = static_cast< sal_uInt16 >( pResMgr->ReadLong() );
69 mpImplData->AddImage( aName, nId, aEmpty );
72 if( nObjMask & RscImageListFlags::IdCount )
73 pResMgr->ReadShort();
77 ImageList::ImageList(const std::vector< OUString >& rNameVector,
78 const OUString& rPrefix)
80 SAL_INFO( "vcl.gdi", "vcl: ImageList::ImageList(const vector< OUString >& ..." );
82 ImplInit( sal::static_int_cast< sal_uInt16 >( rNameVector.size() ), Size() );
84 mpImplData->maPrefix = rPrefix;
85 for( size_t i = 0; i < rNameVector.size(); ++i )
87 mpImplData->AddImage( rNameVector[ i ], static_cast< sal_uInt16 >( i ) + 1, BitmapEx() );
91 void ImageList::ImplInit( sal_uInt16 nItems, const Size &rSize )
93 mpImplData.reset(new ImplImageList);
94 mpImplData->maImages.reserve( nItems );
95 mpImplData->maImageSize = rSize;
98 // FIXME: Rather a performance hazard
99 BitmapEx ImageList::GetAsHorizontalStrip() const
101 Size aSize( mpImplData->maImageSize );
102 sal_uInt16 nCount = GetImageCount();
103 if( !nCount )
104 return BitmapEx();
105 aSize.Width() *= nCount;
107 // Load any stragglers
108 for (sal_uInt16 nIdx = 0; nIdx < nCount; nIdx++)
110 ImageAryData *pData = mpImplData->maImages[ nIdx ];
111 if( pData->IsLoadable() )
112 pData->Load( mpImplData->maPrefix );
115 BitmapEx aTempl = mpImplData->maImages[ 0 ]->maBitmapEx;
116 BitmapEx aResult;
117 Bitmap aPixels( aSize, aTempl.GetBitmap().GetBitCount() );
118 if( aTempl.IsAlpha() )
119 aResult = BitmapEx( aPixels, AlphaMask( aSize ) );
120 else if( aTempl.IsTransparent() )
121 aResult = BitmapEx( aPixels, Bitmap( aSize, aTempl.GetMask().GetBitCount() ) );
122 else
123 aResult = BitmapEx( aPixels );
125 Rectangle aSrcRect( Point( 0, 0 ), mpImplData->maImageSize );
126 for (sal_uInt16 nIdx = 0; nIdx < nCount; nIdx++)
128 Rectangle aDestRect( Point( nIdx * mpImplData->maImageSize.Width(), 0 ),
129 mpImplData->maImageSize );
130 ImageAryData *pData = mpImplData->maImages[ nIdx ];
131 aResult.CopyPixel( aDestRect, aSrcRect, &pData->maBitmapEx);
134 return aResult;
137 void ImageList::InsertFromHorizontalStrip( const BitmapEx &rBitmapEx,
138 const std::vector< OUString > &rNameVector )
140 sal_uInt16 nItems = sal::static_int_cast< sal_uInt16 >( rNameVector.size() );
142 if (!nItems)
143 return;
145 Size aSize( rBitmapEx.GetSizePixel() );
146 DBG_ASSERT (rBitmapEx.GetSizePixel().Width() % nItems == 0,
147 "ImageList::InsertFromHorizontalStrip - very odd size");
148 aSize.Width() /= nItems;
149 ImplInit( nItems, aSize );
151 for (sal_uInt16 nIdx = 0; nIdx < nItems; nIdx++)
153 BitmapEx aBitmap( rBitmapEx, Point( nIdx * aSize.Width(), 0 ), aSize );
154 mpImplData->AddImage( rNameVector[ nIdx ], nIdx + 1, aBitmap );
158 void ImageList::InsertFromHorizontalBitmap( const ResId& rResId,
159 sal_uInt16 nCount,
160 const Color *pMaskColor,
161 const Color *pSearchColors,
162 const Color *pReplaceColors,
163 sal_uLong nColorCount)
165 BitmapEx aBmpEx( rResId );
166 if (!aBmpEx.IsTransparent())
168 if( pMaskColor )
169 aBmpEx = BitmapEx( aBmpEx.GetBitmap(), *pMaskColor );
170 else
171 aBmpEx = BitmapEx( aBmpEx.GetBitmap() );
173 if ( nColorCount && pSearchColors && pReplaceColors )
174 aBmpEx.Replace( pSearchColors, pReplaceColors, nColorCount );
176 std::vector< OUString > aNames( nCount );
177 InsertFromHorizontalStrip( aBmpEx, aNames );
180 sal_uInt16 ImageList::ImplGetImageId( const OUString& rImageName ) const
182 ImageAryData *pImg = mpImplData->maNameHash[ rImageName ];
183 if( pImg )
184 return pImg->mnId;
185 else
186 return 0;
189 void ImageList::AddImage( const OUString& rImageName, const Image& rImage )
191 SAL_WARN_IF( GetImagePos( rImageName ) != IMAGELIST_IMAGE_NOTFOUND, "vcl", "ImageList::AddImage() - ImageName already exists" );
193 if( !mpImplData )
194 ImplInit( 0, rImage.GetSizePixel() );
196 mpImplData->AddImage( rImageName, GetImageCount() + 1,
197 rImage.GetBitmapEx() );
200 void ImageList::ReplaceImage( const OUString& rImageName, const Image& rImage )
202 const sal_uInt16 nId = ImplGetImageId( rImageName );
204 if( nId )
206 //Just replace the bitmap rather than doing RemoveImage / AddImage
207 //which breaks index-based iteration.
208 ImageAryData *pImg = mpImplData->maNameHash[ rImageName ];
209 pImg->maBitmapEx = rImage.GetBitmapEx();
213 void ImageList::RemoveImage( sal_uInt16 nId )
215 for( size_t i = 0; i < mpImplData->maImages.size(); ++i )
217 if( mpImplData->maImages[ i ]->mnId == nId )
219 mpImplData->RemoveImage( static_cast< sal_uInt16 >( i ) );
220 break;
225 Image ImageList::GetImage( sal_uInt16 nId ) const
227 Image aRet;
229 if (mpImplData)
231 for (ImageAryData* pImageData : mpImplData->maImages)
233 if (pImageData->mnId == nId)
235 if (pImageData->IsLoadable())
236 pImageData->Load(mpImplData->maPrefix);
237 aRet = Image(pImageData->maBitmapEx);
242 if (!aRet)
244 BitmapEx rBitmap;
245 bool bResult = vcl::ImageRepository::loadDefaultImage(rBitmap);
246 if (bResult)
247 aRet = Image(rBitmap);
250 return aRet;
253 Image ImageList::GetImage( const OUString& rImageName ) const
255 if( mpImplData )
257 ImageAryData *pImg = mpImplData->maNameHash[ rImageName ];
259 if( pImg )
261 if( pImg->IsLoadable() )
262 pImg->Load( mpImplData->maPrefix );
263 return Image( pImg->maBitmapEx );
267 return Image();
270 sal_uInt16 ImageList::GetImageCount() const
272 return mpImplData ? static_cast< sal_uInt16 >( mpImplData->maImages.size() ) : 0;
275 sal_uInt16 ImageList::GetImagePos( sal_uInt16 nId ) const
278 if( mpImplData && nId )
280 for( size_t i = 0; i < mpImplData->maImages.size(); ++i )
282 if (mpImplData->maImages[ i ]->mnId == nId)
283 return static_cast< sal_uInt16 >( i );
287 return IMAGELIST_IMAGE_NOTFOUND;
290 bool ImageList::HasImageAtPos( sal_uInt16 nId ) const
292 return GetImagePos( nId ) != IMAGELIST_IMAGE_NOTFOUND;
295 sal_uInt16 ImageList::GetImagePos( const OUString& rImageName ) const
297 if( mpImplData && !rImageName.isEmpty() )
299 for( size_t i = 0; i < mpImplData->maImages.size(); i++ )
301 if (mpImplData->maImages[i]->maName == rImageName)
302 return static_cast< sal_uInt16 >( i );
306 return IMAGELIST_IMAGE_NOTFOUND;
309 sal_uInt16 ImageList::GetImageId( sal_uInt16 nPos ) const
311 if( mpImplData && (nPos < GetImageCount()) )
312 return mpImplData->maImages[ nPos ]->mnId;
314 return 0;
317 OUString ImageList::GetImageName( sal_uInt16 nPos ) const
319 if( mpImplData && (nPos < GetImageCount()) )
320 return mpImplData->maImages[ nPos ]->maName;
322 return OUString();
325 void ImageList::GetImageNames( std::vector< OUString >& rNames ) const
327 SAL_INFO( "vcl.gdi", "vcl: ImageList::GetImageNames" );
329 rNames = std::vector< OUString >();
331 if( mpImplData )
333 for(const ImageAryData* pImage : mpImplData->maImages)
335 const OUString& rName( pImage->maName );
336 if( !rName.isEmpty())
337 rNames.push_back( rName );
342 Size ImageList::GetImageSize() const
344 Size aRet;
346 if( mpImplData )
348 aRet = mpImplData->maImageSize;
350 // force load of 1st image to see - uncommon case.
351 if( aRet.Width() == 0 && aRet.Height() == 0 &&
352 !mpImplData->maImages.empty() )
354 Image aTmp = GetImage( mpImplData->maImages[ 0 ]->mnId );
355 aRet = mpImplData->maImageSize = aTmp.GetSizePixel();
358 return aRet;
361 bool ImageList::operator==( const ImageList& rImageList ) const
363 bool bRet = false;
365 if( rImageList.mpImplData == mpImplData )
366 bRet = true;
367 else if( !rImageList.mpImplData || !mpImplData )
368 bRet = false;
369 else if( rImageList.GetImageCount() == GetImageCount() &&
370 rImageList.mpImplData->maImageSize == mpImplData->maImageSize )
371 bRet = true; // strange semantic
373 return bRet;
376 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */