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