xref: /haiku/src/apps/haikudepot/model/PackageIconTarRepository.cpp (revision 3538133f9fefc41c557f365f0919f18bd0f0404b)
1f0e491d3SAndrew Lindesay /*
2d75b4d61SAndrew Lindesay  * Copyright 2020-2021, Andrew Lindesay <apl@lindesay.co.nz>.
3f0e491d3SAndrew Lindesay  * All rights reserved. Distributed under the terms of the MIT License.
4f0e491d3SAndrew Lindesay  */
5027d6086SAndrew Lindesay 
6027d6086SAndrew Lindesay 
7f0e491d3SAndrew Lindesay #include "PackageIconTarRepository.h"
8f0e491d3SAndrew Lindesay 
9f0e491d3SAndrew Lindesay #include <Autolock.h>
10f0e491d3SAndrew Lindesay #include <AutoDeleter.h>
11f0e491d3SAndrew Lindesay #include <File.h>
12*3538133fSAndrew Lindesay #include <StopWatch.h>
13f0e491d3SAndrew Lindesay 
14f0e491d3SAndrew Lindesay #include "Logger.h"
15f0e491d3SAndrew Lindesay #include "TarArchiveService.h"
16f0e491d3SAndrew Lindesay 
17f0e491d3SAndrew Lindesay 
18027d6086SAndrew Lindesay #define LIMIT_ICON_CACHE 50
19027d6086SAndrew Lindesay 
20027d6086SAndrew Lindesay 
21f0e491d3SAndrew Lindesay BitmapRef
22f0e491d3SAndrew Lindesay PackageIconTarRepository::sDefaultIcon(new(std::nothrow) SharedBitmap(
23f0e491d3SAndrew Lindesay 	"application/x-vnd.haiku-package"), true);
24f0e491d3SAndrew Lindesay 
25f0e491d3SAndrew Lindesay 
26f0e491d3SAndrew Lindesay /*!	An instance of this class can be provided to the TarArchiveService to
27f0e491d3SAndrew Lindesay 	be called each time a tar entry is found.  This way it is able to capture
28f0e491d3SAndrew Lindesay 	the offsets of the icons in the tar file against the package names.
29f0e491d3SAndrew Lindesay */
30f0e491d3SAndrew Lindesay 
31f0e491d3SAndrew Lindesay class IconTarPtrEntryListener : public TarEntryListener
32f0e491d3SAndrew Lindesay {
33f0e491d3SAndrew Lindesay public:
34f0e491d3SAndrew Lindesay 								IconTarPtrEntryListener(
35f0e491d3SAndrew Lindesay 									PackageIconTarRepository*
36f0e491d3SAndrew Lindesay 									fPackageIconTarRepository);
37f0e491d3SAndrew Lindesay 	virtual						~IconTarPtrEntryListener();
38f0e491d3SAndrew Lindesay 
39f0e491d3SAndrew Lindesay 	virtual status_t			Handle(
40f0e491d3SAndrew Lindesay 									const TarArchiveHeader& header,
41f0e491d3SAndrew Lindesay 									size_t offset,
42f0e491d3SAndrew Lindesay 									BDataIO *data);
43f0e491d3SAndrew Lindesay private:
44f0e491d3SAndrew Lindesay 			status_t			_LeafNameToBitmapSize(BString& leafName,
45f0e491d3SAndrew Lindesay 									BitmapSize* bitmapSize);
46f0e491d3SAndrew Lindesay 
47f0e491d3SAndrew Lindesay private:
48f0e491d3SAndrew Lindesay 			PackageIconTarRepository*
49f0e491d3SAndrew Lindesay 								fPackageIconTarRepository;
50f0e491d3SAndrew Lindesay };
51f0e491d3SAndrew Lindesay 
52f0e491d3SAndrew Lindesay 
53f0e491d3SAndrew Lindesay IconTarPtrEntryListener::IconTarPtrEntryListener(
54f0e491d3SAndrew Lindesay 	PackageIconTarRepository* packageIconTarRepository)
55f0e491d3SAndrew Lindesay 	:
56f0e491d3SAndrew Lindesay 	fPackageIconTarRepository(packageIconTarRepository)
57f0e491d3SAndrew Lindesay {
58f0e491d3SAndrew Lindesay }
59f0e491d3SAndrew Lindesay 
60f0e491d3SAndrew Lindesay 
61f0e491d3SAndrew Lindesay IconTarPtrEntryListener::~IconTarPtrEntryListener()
62f0e491d3SAndrew Lindesay {
63f0e491d3SAndrew Lindesay }
64f0e491d3SAndrew Lindesay 
65f0e491d3SAndrew Lindesay 
66f0e491d3SAndrew Lindesay /*!	The format of the filenames in the archive are of the format;
67f0e491d3SAndrew Lindesay 	\code
68f0e491d3SAndrew Lindesay 	hicn/ardino/icon.hvif
69f0e491d3SAndrew Lindesay 	\endcode
70f0e491d3SAndrew Lindesay 	The leafname (the last part of the path) determines the type of the file as
71f0e491d3SAndrew Lindesay 	it could be either in HVIF format or a PNG of various sizes.
72f0e491d3SAndrew Lindesay */
73f0e491d3SAndrew Lindesay 
74f0e491d3SAndrew Lindesay status_t
75f0e491d3SAndrew Lindesay IconTarPtrEntryListener::Handle(const TarArchiveHeader& header,
76f0e491d3SAndrew Lindesay 	size_t offset, BDataIO *data)
77f0e491d3SAndrew Lindesay {
78f0e491d3SAndrew Lindesay 	if (header.FileType() != TAR_FILE_TYPE_NORMAL)
79f0e491d3SAndrew Lindesay 		return B_OK;
80f0e491d3SAndrew Lindesay 
81f0e491d3SAndrew Lindesay 	BString fileName = header.FileName();
82f0e491d3SAndrew Lindesay 	if (!fileName.StartsWith("hicn/"))
83f0e491d3SAndrew Lindesay 		return B_OK;
84f0e491d3SAndrew Lindesay 
85f0e491d3SAndrew Lindesay 	int32 secondSlashIdx = fileName.FindFirst("/", 5);
86f0e491d3SAndrew Lindesay 	if (secondSlashIdx == B_ERROR || secondSlashIdx == 5)
87f0e491d3SAndrew Lindesay 		return B_OK;
88f0e491d3SAndrew Lindesay 
89f0e491d3SAndrew Lindesay 	BString packageName;
90f0e491d3SAndrew Lindesay 	BString leafName;
91f0e491d3SAndrew Lindesay 	fileName.CopyInto(packageName, 5, secondSlashIdx - 5);
92f0e491d3SAndrew Lindesay 	fileName.CopyInto(leafName, secondSlashIdx + 1,
93f0e491d3SAndrew Lindesay 		fileName.Length() - (secondSlashIdx + 1));
94f0e491d3SAndrew Lindesay 	BitmapSize bitmapSize;
95f0e491d3SAndrew Lindesay 
96f0e491d3SAndrew Lindesay 	if (_LeafNameToBitmapSize(leafName, &bitmapSize) == B_OK) {
97f0e491d3SAndrew Lindesay 		fPackageIconTarRepository->AddIconTarPtr(packageName, bitmapSize,
98f0e491d3SAndrew Lindesay 			offset);
99f0e491d3SAndrew Lindesay 	}
100f0e491d3SAndrew Lindesay 
101f0e491d3SAndrew Lindesay 	return B_OK;
102f0e491d3SAndrew Lindesay }
103f0e491d3SAndrew Lindesay 
104f0e491d3SAndrew Lindesay 
105f0e491d3SAndrew Lindesay status_t
106f0e491d3SAndrew Lindesay IconTarPtrEntryListener::_LeafNameToBitmapSize(BString& leafName,
107f0e491d3SAndrew Lindesay 	BitmapSize* bitmapSize)
108f0e491d3SAndrew Lindesay {
109f0e491d3SAndrew Lindesay 	if (leafName == "icon.hvif") {
110f0e491d3SAndrew Lindesay 		*bitmapSize = BITMAP_SIZE_ANY;
111f0e491d3SAndrew Lindesay 		return B_OK;
112f0e491d3SAndrew Lindesay 	}
113f0e491d3SAndrew Lindesay 	if (leafName == "64.png") {
114f0e491d3SAndrew Lindesay 		*bitmapSize = BITMAP_SIZE_64;
115f0e491d3SAndrew Lindesay 		return B_OK;
116f0e491d3SAndrew Lindesay 	}
117f0e491d3SAndrew Lindesay 	if (leafName == "32.png") {
118f0e491d3SAndrew Lindesay 		*bitmapSize = BITMAP_SIZE_32;
119f0e491d3SAndrew Lindesay 		return B_OK;
120f0e491d3SAndrew Lindesay 	}
121f0e491d3SAndrew Lindesay 	if (leafName == "16.png") {
122f0e491d3SAndrew Lindesay 		*bitmapSize = BITMAP_SIZE_16;
123f0e491d3SAndrew Lindesay 		return B_OK;
124f0e491d3SAndrew Lindesay 	}
125f0e491d3SAndrew Lindesay 	return B_BAD_VALUE;
126f0e491d3SAndrew Lindesay }
127f0e491d3SAndrew Lindesay 
128f0e491d3SAndrew Lindesay 
129f0e491d3SAndrew Lindesay PackageIconTarRepository::PackageIconTarRepository()
130f0e491d3SAndrew Lindesay 	:
131027d6086SAndrew Lindesay 	fTarIo(NULL),
132027d6086SAndrew Lindesay 	fIconCache(LIMIT_ICON_CACHE)
133f0e491d3SAndrew Lindesay {
134f0e491d3SAndrew Lindesay }
135f0e491d3SAndrew Lindesay 
136f0e491d3SAndrew Lindesay 
137f0e491d3SAndrew Lindesay PackageIconTarRepository::~PackageIconTarRepository()
138f0e491d3SAndrew Lindesay {
139f0e491d3SAndrew Lindesay }
140f0e491d3SAndrew Lindesay 
141f0e491d3SAndrew Lindesay 
142d75b4d61SAndrew Lindesay void
143d75b4d61SAndrew Lindesay PackageIconTarRepository::Clear() {
144d75b4d61SAndrew Lindesay 	BAutolock locker(&fLock);
145d75b4d61SAndrew Lindesay 	fIconCache.Clear();
146d75b4d61SAndrew Lindesay }
147d75b4d61SAndrew Lindesay 
148d75b4d61SAndrew Lindesay 
149f0e491d3SAndrew Lindesay /*!	This method will reconfigure itself using the data in the tar file supplied.
150f0e491d3SAndrew Lindesay 	Any existing data will be flushed and the new tar will be scanned for
151f0e491d3SAndrew Lindesay 	offsets to usable files.
152f0e491d3SAndrew Lindesay */
153f0e491d3SAndrew Lindesay 
154f0e491d3SAndrew Lindesay status_t
155f0e491d3SAndrew Lindesay PackageIconTarRepository::Init(BPath& tarPath)
156f0e491d3SAndrew Lindesay {
157f0e491d3SAndrew Lindesay 	BAutolock locker(&fLock);
158f0e491d3SAndrew Lindesay 	_Close();
159f0e491d3SAndrew Lindesay 	status_t result = B_OK;
160f0e491d3SAndrew Lindesay 
161f0e491d3SAndrew Lindesay 	if (tarPath.Path() == NULL) {
162f0e491d3SAndrew Lindesay 		HDINFO("empty path to tar-ball");
163f0e491d3SAndrew Lindesay 		result = B_BAD_VALUE;
164f0e491d3SAndrew Lindesay 	}
165f0e491d3SAndrew Lindesay 
166f0e491d3SAndrew Lindesay 	BFile *tarIo = NULL;
167f0e491d3SAndrew Lindesay 
168f0e491d3SAndrew Lindesay 	if (result == B_OK) {
169f0e491d3SAndrew Lindesay 		HDINFO("will init icon model from tar [%s]", tarPath.Path());
170f0e491d3SAndrew Lindesay 		tarIo = new BFile(tarPath.Path(), O_RDONLY);
171f0e491d3SAndrew Lindesay 
172f0e491d3SAndrew Lindesay 		if (!tarIo->IsReadable()) {
173f0e491d3SAndrew Lindesay 			HDERROR("unable to read the tar [%s]", tarPath.Path());
174f0e491d3SAndrew Lindesay 			result = B_IO_ERROR;
175f0e491d3SAndrew Lindesay 		}
176f0e491d3SAndrew Lindesay 	}
177f0e491d3SAndrew Lindesay 
178f0e491d3SAndrew Lindesay 	// will fill the model up with records from the tar-ball.
179f0e491d3SAndrew Lindesay 
180f0e491d3SAndrew Lindesay 	if (result == B_OK) {
181f0e491d3SAndrew Lindesay 		BStopWatch watch("PackageIconTarRepository::Init", true);
182f0e491d3SAndrew Lindesay 		HDINFO("will read [%s] and collect the tar pointers", tarPath.Path());
183f0e491d3SAndrew Lindesay 
184f0e491d3SAndrew Lindesay 		IconTarPtrEntryListener* listener = new IconTarPtrEntryListener(this);
185f0e491d3SAndrew Lindesay 		ObjectDeleter<IconTarPtrEntryListener> listenerDeleter(listener);
186f0e491d3SAndrew Lindesay 		TarArchiveService::ForEachEntry(*tarIo, listener);
187f0e491d3SAndrew Lindesay 
188f0e491d3SAndrew Lindesay 		double secs = watch.ElapsedTime() / 1000000.0;
189f0e491d3SAndrew Lindesay 		HDINFO("did collect %" B_PRIi32 " tar pointers (%6.3g secs)",
190f0e491d3SAndrew Lindesay 			fIconTarPtrs.Size(), secs);
191f0e491d3SAndrew Lindesay 	}
192f0e491d3SAndrew Lindesay 
193f0e491d3SAndrew Lindesay 	if (result == B_OK)
194f0e491d3SAndrew Lindesay 		fTarIo = tarIo;
195f0e491d3SAndrew Lindesay 	else
196f0e491d3SAndrew Lindesay 		delete tarIo;
197f0e491d3SAndrew Lindesay 
198f0e491d3SAndrew Lindesay 	return result;
199f0e491d3SAndrew Lindesay }
200f0e491d3SAndrew Lindesay 
201f0e491d3SAndrew Lindesay 
202f0e491d3SAndrew Lindesay void
203f0e491d3SAndrew Lindesay PackageIconTarRepository::_Close()
204f0e491d3SAndrew Lindesay {
205d75b4d61SAndrew Lindesay 	fIconCache.Clear();
206f0e491d3SAndrew Lindesay 	delete fTarIo;
207f0e491d3SAndrew Lindesay 	fTarIo = NULL;
208f0e491d3SAndrew Lindesay 	fIconTarPtrs.Clear();
209f0e491d3SAndrew Lindesay }
210f0e491d3SAndrew Lindesay 
211f0e491d3SAndrew Lindesay 
212f0e491d3SAndrew Lindesay /*!	This method should be treated private and only called from a situation
213f0e491d3SAndrew Lindesay 	in which the class's lock is acquired.  It is used to populate data from
214f0e491d3SAndrew Lindesay 	the parsing of the tar headers.  It is called from the listener above.
215f0e491d3SAndrew Lindesay */
216f0e491d3SAndrew Lindesay 
217f0e491d3SAndrew Lindesay void
218f0e491d3SAndrew Lindesay PackageIconTarRepository::AddIconTarPtr(const BString& packageName,
219f0e491d3SAndrew Lindesay 	BitmapSize bitmapSize, off_t offset)
220f0e491d3SAndrew Lindesay {
221f0e491d3SAndrew Lindesay 	IconTarPtrRef tarPtrRef = _GetOrCreateIconTarPtr(packageName);
222f0e491d3SAndrew Lindesay 	tarPtrRef->SetOffset(bitmapSize, offset);
223f0e491d3SAndrew Lindesay }
224f0e491d3SAndrew Lindesay 
225f0e491d3SAndrew Lindesay 
226f0e491d3SAndrew Lindesay bool
227f0e491d3SAndrew Lindesay PackageIconTarRepository::HasAnyIcon(const BString& pkgName)
228f0e491d3SAndrew Lindesay {
229f0e491d3SAndrew Lindesay 	BAutolock locker(&fLock);
230f0e491d3SAndrew Lindesay 	HashString key(pkgName);
231f0e491d3SAndrew Lindesay 	return fIconTarPtrs.ContainsKey(key);
232f0e491d3SAndrew Lindesay }
233f0e491d3SAndrew Lindesay 
234f0e491d3SAndrew Lindesay 
235f0e491d3SAndrew Lindesay status_t
236f0e491d3SAndrew Lindesay PackageIconTarRepository::GetIcon(const BString& pkgName, BitmapSize size,
237f0e491d3SAndrew Lindesay 	BitmapRef& bitmap)
238f0e491d3SAndrew Lindesay {
239f0e491d3SAndrew Lindesay 	BAutolock locker(&fLock);
240f0e491d3SAndrew Lindesay 	status_t result = B_OK;
241f0e491d3SAndrew Lindesay 	BitmapSize actualSize;
242f0e491d3SAndrew Lindesay 	off_t iconDataTarOffset = -1;
243f0e491d3SAndrew Lindesay 	const IconTarPtrRef tarPtrRef = _GetIconTarPtr(pkgName);
244f0e491d3SAndrew Lindesay 
245779ab335SX512 	if (tarPtrRef.IsSet()) {
246f0e491d3SAndrew Lindesay 		iconDataTarOffset = _OffsetToBestRepresentation(tarPtrRef, size,
247f0e491d3SAndrew Lindesay 			&actualSize);
248f0e491d3SAndrew Lindesay 	}
249f0e491d3SAndrew Lindesay 
250f0e491d3SAndrew Lindesay 	if (iconDataTarOffset < 0)
251f0e491d3SAndrew Lindesay 		bitmap.SetTo(sDefaultIcon);
252f0e491d3SAndrew Lindesay 	else {
253f0e491d3SAndrew Lindesay 		HashString key = _ToIconCacheKey(pkgName, actualSize);
254f0e491d3SAndrew Lindesay 
255f0e491d3SAndrew Lindesay 		if (!fIconCache.ContainsKey(key)) {
256f0e491d3SAndrew Lindesay 			result = _CreateIconFromTarOffset(iconDataTarOffset, bitmap);
257f0e491d3SAndrew Lindesay 			if (result == B_OK)
258f0e491d3SAndrew Lindesay 				fIconCache.Put(key, bitmap);
259f0e491d3SAndrew Lindesay 			else {
260f0e491d3SAndrew Lindesay 				HDERROR("failure to read image for package [%s] at offset %"
261dfbcbde1SAndrew Lindesay 					B_PRIdOFF, pkgName.String(), iconDataTarOffset);
262f0e491d3SAndrew Lindesay 				fIconCache.Put(key, sDefaultIcon);
263f0e491d3SAndrew Lindesay 			}
264f0e491d3SAndrew Lindesay 		}
265f0e491d3SAndrew Lindesay 		bitmap.SetTo(fIconCache.Get(key).Get());
266f0e491d3SAndrew Lindesay 	}
267f0e491d3SAndrew Lindesay 	return result;
268f0e491d3SAndrew Lindesay }
269f0e491d3SAndrew Lindesay 
270f0e491d3SAndrew Lindesay 
271f0e491d3SAndrew Lindesay IconTarPtrRef
272f0e491d3SAndrew Lindesay PackageIconTarRepository::_GetIconTarPtr(const BString& pkgName) const
273f0e491d3SAndrew Lindesay {
274f0e491d3SAndrew Lindesay 	return fIconTarPtrs.Get(HashString(pkgName));
275f0e491d3SAndrew Lindesay }
276f0e491d3SAndrew Lindesay 
277f0e491d3SAndrew Lindesay 
278f0e491d3SAndrew Lindesay const char*
279f0e491d3SAndrew Lindesay PackageIconTarRepository::_ToIconCacheKeySuffix(BitmapSize size)
280f0e491d3SAndrew Lindesay {
281f0e491d3SAndrew Lindesay 	switch (size)
282f0e491d3SAndrew Lindesay 	{
283f0e491d3SAndrew Lindesay 		case BITMAP_SIZE_16:
284f0e491d3SAndrew Lindesay 			return "16";
285f0e491d3SAndrew Lindesay 		// note that size 22 is not supported.
286f0e491d3SAndrew Lindesay 		case BITMAP_SIZE_32:
287f0e491d3SAndrew Lindesay 			return "32";
288f0e491d3SAndrew Lindesay 		case BITMAP_SIZE_64:
289f0e491d3SAndrew Lindesay 			return "64";
290f0e491d3SAndrew Lindesay 		case BITMAP_SIZE_ANY:
291f0e491d3SAndrew Lindesay 			return "any";
292f0e491d3SAndrew Lindesay 		default:
29305880d13SAndrew Lindesay 			HDFATAL("unsupported bitmap size");
294f0e491d3SAndrew Lindesay 			break;
295f0e491d3SAndrew Lindesay 	}
296f0e491d3SAndrew Lindesay }
297f0e491d3SAndrew Lindesay 
298f0e491d3SAndrew Lindesay 
299f0e491d3SAndrew Lindesay const HashString
300f0e491d3SAndrew Lindesay PackageIconTarRepository::_ToIconCacheKey(const BString& pkgName,
301f0e491d3SAndrew Lindesay 	BitmapSize size)
302f0e491d3SAndrew Lindesay {
303f0e491d3SAndrew Lindesay 	return HashString(BString(pkgName) << "__x" << _ToIconCacheKeySuffix(size));
304f0e491d3SAndrew Lindesay }
305f0e491d3SAndrew Lindesay 
306f0e491d3SAndrew Lindesay 
307f0e491d3SAndrew Lindesay status_t
308f0e491d3SAndrew Lindesay PackageIconTarRepository::_CreateIconFromTarOffset(off_t offset,
309f0e491d3SAndrew Lindesay 	BitmapRef& bitmap)
310f0e491d3SAndrew Lindesay {
311f0e491d3SAndrew Lindesay 	fTarIo->Seek(offset, SEEK_SET);
312f0e491d3SAndrew Lindesay 	TarArchiveHeader header;
313f0e491d3SAndrew Lindesay 	status_t result = TarArchiveService::GetEntry(*fTarIo, header);
314f0e491d3SAndrew Lindesay 
315f0e491d3SAndrew Lindesay 	if (result == B_OK && header.Length() <= 0)
316f0e491d3SAndrew Lindesay 		result = B_BAD_DATA;
317f0e491d3SAndrew Lindesay 
318f0e491d3SAndrew Lindesay 	if (result == B_OK)
319f0e491d3SAndrew Lindesay 		bitmap.SetTo(new(std::nothrow)SharedBitmap(*fTarIo, header.Length()));
320f0e491d3SAndrew Lindesay 
321f0e491d3SAndrew Lindesay 	return result;
322f0e491d3SAndrew Lindesay }
323f0e491d3SAndrew Lindesay 
324f0e491d3SAndrew Lindesay 
325f0e491d3SAndrew Lindesay /*!	If there is a vector representation (HVIF) then this will be the best
326f0e491d3SAndrew Lindesay 	option.  If there are only bitmap images to choose from then consider what
327f0e491d3SAndrew Lindesay 	the target size is and choose the best image to match.
328f0e491d3SAndrew Lindesay */
329f0e491d3SAndrew Lindesay 
330f0e491d3SAndrew Lindesay /*static*/ off_t
331f0e491d3SAndrew Lindesay PackageIconTarRepository::_OffsetToBestRepresentation(
332f0e491d3SAndrew Lindesay 	const IconTarPtrRef iconTarPtrRef, BitmapSize desiredSize,
333f0e491d3SAndrew Lindesay 	BitmapSize* actualSize)
334f0e491d3SAndrew Lindesay {
335f0e491d3SAndrew Lindesay 	if (iconTarPtrRef->HasOffset(BITMAP_SIZE_ANY)) {
336f0e491d3SAndrew Lindesay 		*actualSize = BITMAP_SIZE_ANY;
337f0e491d3SAndrew Lindesay 		return iconTarPtrRef->Offset(BITMAP_SIZE_ANY);
338f0e491d3SAndrew Lindesay 	}
339f0e491d3SAndrew Lindesay 	if (iconTarPtrRef->HasOffset(BITMAP_SIZE_64)
340f0e491d3SAndrew Lindesay 			&& desiredSize >= BITMAP_SIZE_64) {
341f0e491d3SAndrew Lindesay 		*actualSize = BITMAP_SIZE_64;
342f0e491d3SAndrew Lindesay 		return iconTarPtrRef->Offset(BITMAP_SIZE_64);
343f0e491d3SAndrew Lindesay 	}
344f0e491d3SAndrew Lindesay 	if (iconTarPtrRef->HasOffset(BITMAP_SIZE_32)
345f0e491d3SAndrew Lindesay 			&& desiredSize >= BITMAP_SIZE_32) {
346f0e491d3SAndrew Lindesay 		*actualSize = BITMAP_SIZE_32;
347f0e491d3SAndrew Lindesay 		return iconTarPtrRef->Offset(BITMAP_SIZE_32);
348f0e491d3SAndrew Lindesay 	}
349f0e491d3SAndrew Lindesay 	if (iconTarPtrRef->HasOffset(BITMAP_SIZE_22)
350f0e491d3SAndrew Lindesay 			&& desiredSize >= BITMAP_SIZE_22) {
351f0e491d3SAndrew Lindesay 		*actualSize = BITMAP_SIZE_22;
352f0e491d3SAndrew Lindesay 		return iconTarPtrRef->Offset(BITMAP_SIZE_22);
353f0e491d3SAndrew Lindesay 	}
354f0e491d3SAndrew Lindesay 	if (iconTarPtrRef->HasOffset(BITMAP_SIZE_16)) {
355f0e491d3SAndrew Lindesay 		*actualSize = BITMAP_SIZE_16;
356f0e491d3SAndrew Lindesay 		return iconTarPtrRef->Offset(BITMAP_SIZE_16);
357f0e491d3SAndrew Lindesay 	}
358f0e491d3SAndrew Lindesay 	return -1;
359f0e491d3SAndrew Lindesay }
360f0e491d3SAndrew Lindesay 
361f0e491d3SAndrew Lindesay 
362f0e491d3SAndrew Lindesay IconTarPtrRef
363f0e491d3SAndrew Lindesay PackageIconTarRepository::_GetOrCreateIconTarPtr(const BString& pkgName)
364f0e491d3SAndrew Lindesay {
365f0e491d3SAndrew Lindesay 	BAutolock locker(&fLock);
366f0e491d3SAndrew Lindesay 	HashString key(pkgName);
367f0e491d3SAndrew Lindesay 	if (!fIconTarPtrs.ContainsKey(key)) {
368f0e491d3SAndrew Lindesay 		IconTarPtrRef value(new IconTarPtr(pkgName));
369f0e491d3SAndrew Lindesay 		fIconTarPtrs.Put(key, value);
370f0e491d3SAndrew Lindesay 		return value;
371f0e491d3SAndrew Lindesay 	}
372f0e491d3SAndrew Lindesay 	return fIconTarPtrs.Get(key);
373f0e491d3SAndrew Lindesay }
374f0e491d3SAndrew Lindesay 
375f0e491d3SAndrew Lindesay 
376f0e491d3SAndrew Lindesay /*static*/ void
377f0e491d3SAndrew Lindesay PackageIconTarRepository::CleanupDefaultIcon()
378f0e491d3SAndrew Lindesay {
379f0e491d3SAndrew Lindesay 	sDefaultIcon.Unset();
380f0e491d3SAndrew Lindesay }
381