1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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>
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
)
61 sal_Int32 nCount
= pResMgr
->ReadLong();
62 ImplInit( static_cast< sal_uInt16
>( nCount
), Size() );
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
)
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();
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
;
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() ) );
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
);
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() );
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
,
160 const Color
*pMaskColor
,
161 const Color
*pSearchColors
,
162 const Color
*pReplaceColors
,
163 sal_uLong nColorCount
)
165 BitmapEx
aBmpEx( rResId
);
166 if (!aBmpEx
.IsTransparent())
169 aBmpEx
= BitmapEx( aBmpEx
.GetBitmap(), *pMaskColor
);
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
];
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" );
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
);
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
) );
225 Image
ImageList::GetImage( sal_uInt16 nId
) const
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
);
245 bool bResult
= vcl::ImageRepository::loadDefaultImage(rBitmap
);
247 aRet
= Image(rBitmap
);
253 Image
ImageList::GetImage( const OUString
& rImageName
) const
257 ImageAryData
*pImg
= mpImplData
->maNameHash
[ rImageName
];
261 if( pImg
->IsLoadable() )
262 pImg
->Load( mpImplData
->maPrefix
);
263 return Image( pImg
->maBitmapEx
);
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
;
317 OUString
ImageList::GetImageName( sal_uInt16 nPos
) const
319 if( mpImplData
&& (nPos
< GetImageCount()) )
320 return mpImplData
->maImages
[ nPos
]->maName
;
325 void ImageList::GetImageNames( std::vector
< OUString
>& rNames
) const
327 SAL_INFO( "vcl.gdi", "vcl: ImageList::GetImageNames" );
329 rNames
= std::vector
< OUString
>();
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
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();
361 bool ImageList::operator==( const ImageList
& rImageList
) const
365 if( rImageList
.mpImplData
== mpImplData
)
367 else if( !rImageList
.mpImplData
|| !mpImplData
)
369 else if( rImageList
.GetImageCount() == GetImageCount() &&
370 rImageList
.mpImplData
->maImageSize
== mpImplData
->maImageSize
)
371 bRet
= true; // strange semantic
376 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */