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