1f0e491d3SAndrew Lindesay /* 2*d75b4d61SAndrew 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> 12f0e491d3SAndrew Lindesay #include <support/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 142*d75b4d61SAndrew Lindesay void 143*d75b4d61SAndrew Lindesay PackageIconTarRepository::Clear() { 144*d75b4d61SAndrew Lindesay BAutolock locker(&fLock); 145*d75b4d61SAndrew Lindesay fIconCache.Clear(); 146*d75b4d61SAndrew Lindesay } 147*d75b4d61SAndrew Lindesay 148*d75b4d61SAndrew 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 { 205*d75b4d61SAndrew 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 // TODO; need to implement an LRU cache so that not too many icons are 256f0e491d3SAndrew Lindesay // in memory at the same time. 257f0e491d3SAndrew Lindesay 258f0e491d3SAndrew Lindesay if (!fIconCache.ContainsKey(key)) { 259f0e491d3SAndrew Lindesay result = _CreateIconFromTarOffset(iconDataTarOffset, bitmap); 260f0e491d3SAndrew Lindesay if (result == B_OK) 261f0e491d3SAndrew Lindesay fIconCache.Put(key, bitmap); 262f0e491d3SAndrew Lindesay else { 263f0e491d3SAndrew Lindesay HDERROR("failure to read image for package [%s] at offset %" 264f0e491d3SAndrew Lindesay B_PRIdSSIZE, pkgName.String(), iconDataTarOffset); 265f0e491d3SAndrew Lindesay fIconCache.Put(key, sDefaultIcon); 266f0e491d3SAndrew Lindesay } 267f0e491d3SAndrew Lindesay } 268f0e491d3SAndrew Lindesay bitmap.SetTo(fIconCache.Get(key).Get()); 269f0e491d3SAndrew Lindesay } 270f0e491d3SAndrew Lindesay return result; 271f0e491d3SAndrew Lindesay } 272f0e491d3SAndrew Lindesay 273f0e491d3SAndrew Lindesay 274f0e491d3SAndrew Lindesay IconTarPtrRef 275f0e491d3SAndrew Lindesay PackageIconTarRepository::_GetIconTarPtr(const BString& pkgName) const 276f0e491d3SAndrew Lindesay { 277f0e491d3SAndrew Lindesay return fIconTarPtrs.Get(HashString(pkgName)); 278f0e491d3SAndrew Lindesay } 279f0e491d3SAndrew Lindesay 280f0e491d3SAndrew Lindesay 281f0e491d3SAndrew Lindesay const char* 282f0e491d3SAndrew Lindesay PackageIconTarRepository::_ToIconCacheKeySuffix(BitmapSize size) 283f0e491d3SAndrew Lindesay { 284f0e491d3SAndrew Lindesay switch (size) 285f0e491d3SAndrew Lindesay { 286f0e491d3SAndrew Lindesay case BITMAP_SIZE_16: 287f0e491d3SAndrew Lindesay return "16"; 288f0e491d3SAndrew Lindesay // note that size 22 is not supported. 289f0e491d3SAndrew Lindesay case BITMAP_SIZE_32: 290f0e491d3SAndrew Lindesay return "32"; 291f0e491d3SAndrew Lindesay case BITMAP_SIZE_64: 292f0e491d3SAndrew Lindesay return "64"; 293f0e491d3SAndrew Lindesay case BITMAP_SIZE_ANY: 294f0e491d3SAndrew Lindesay return "any"; 295f0e491d3SAndrew Lindesay default: 29605880d13SAndrew Lindesay HDFATAL("unsupported bitmap size"); 297f0e491d3SAndrew Lindesay break; 298f0e491d3SAndrew Lindesay } 299f0e491d3SAndrew Lindesay } 300f0e491d3SAndrew Lindesay 301f0e491d3SAndrew Lindesay 302f0e491d3SAndrew Lindesay const HashString 303f0e491d3SAndrew Lindesay PackageIconTarRepository::_ToIconCacheKey(const BString& pkgName, 304f0e491d3SAndrew Lindesay BitmapSize size) 305f0e491d3SAndrew Lindesay { 306f0e491d3SAndrew Lindesay return HashString(BString(pkgName) << "__x" << _ToIconCacheKeySuffix(size)); 307f0e491d3SAndrew Lindesay } 308f0e491d3SAndrew Lindesay 309f0e491d3SAndrew Lindesay 310f0e491d3SAndrew Lindesay status_t 311f0e491d3SAndrew Lindesay PackageIconTarRepository::_CreateIconFromTarOffset(off_t offset, 312f0e491d3SAndrew Lindesay BitmapRef& bitmap) 313f0e491d3SAndrew Lindesay { 314f0e491d3SAndrew Lindesay fTarIo->Seek(offset, SEEK_SET); 315f0e491d3SAndrew Lindesay TarArchiveHeader header; 316f0e491d3SAndrew Lindesay status_t result = TarArchiveService::GetEntry(*fTarIo, header); 317f0e491d3SAndrew Lindesay 318f0e491d3SAndrew Lindesay if (result == B_OK && header.Length() <= 0) 319f0e491d3SAndrew Lindesay result = B_BAD_DATA; 320f0e491d3SAndrew Lindesay 321f0e491d3SAndrew Lindesay if (result == B_OK) 322f0e491d3SAndrew Lindesay bitmap.SetTo(new(std::nothrow)SharedBitmap(*fTarIo, header.Length())); 323f0e491d3SAndrew Lindesay 324f0e491d3SAndrew Lindesay return result; 325f0e491d3SAndrew Lindesay } 326f0e491d3SAndrew Lindesay 327f0e491d3SAndrew Lindesay 328f0e491d3SAndrew Lindesay /*! If there is a vector representation (HVIF) then this will be the best 329f0e491d3SAndrew Lindesay option. If there are only bitmap images to choose from then consider what 330f0e491d3SAndrew Lindesay the target size is and choose the best image to match. 331f0e491d3SAndrew Lindesay */ 332f0e491d3SAndrew Lindesay 333f0e491d3SAndrew Lindesay /*static*/ off_t 334f0e491d3SAndrew Lindesay PackageIconTarRepository::_OffsetToBestRepresentation( 335f0e491d3SAndrew Lindesay const IconTarPtrRef iconTarPtrRef, BitmapSize desiredSize, 336f0e491d3SAndrew Lindesay BitmapSize* actualSize) 337f0e491d3SAndrew Lindesay { 338f0e491d3SAndrew Lindesay if (iconTarPtrRef->HasOffset(BITMAP_SIZE_ANY)) { 339f0e491d3SAndrew Lindesay *actualSize = BITMAP_SIZE_ANY; 340f0e491d3SAndrew Lindesay return iconTarPtrRef->Offset(BITMAP_SIZE_ANY); 341f0e491d3SAndrew Lindesay } 342f0e491d3SAndrew Lindesay if (iconTarPtrRef->HasOffset(BITMAP_SIZE_64) 343f0e491d3SAndrew Lindesay && desiredSize >= BITMAP_SIZE_64) { 344f0e491d3SAndrew Lindesay *actualSize = BITMAP_SIZE_64; 345f0e491d3SAndrew Lindesay return iconTarPtrRef->Offset(BITMAP_SIZE_64); 346f0e491d3SAndrew Lindesay } 347f0e491d3SAndrew Lindesay if (iconTarPtrRef->HasOffset(BITMAP_SIZE_32) 348f0e491d3SAndrew Lindesay && desiredSize >= BITMAP_SIZE_32) { 349f0e491d3SAndrew Lindesay *actualSize = BITMAP_SIZE_32; 350f0e491d3SAndrew Lindesay return iconTarPtrRef->Offset(BITMAP_SIZE_32); 351f0e491d3SAndrew Lindesay } 352f0e491d3SAndrew Lindesay if (iconTarPtrRef->HasOffset(BITMAP_SIZE_22) 353f0e491d3SAndrew Lindesay && desiredSize >= BITMAP_SIZE_22) { 354f0e491d3SAndrew Lindesay *actualSize = BITMAP_SIZE_22; 355f0e491d3SAndrew Lindesay return iconTarPtrRef->Offset(BITMAP_SIZE_22); 356f0e491d3SAndrew Lindesay } 357f0e491d3SAndrew Lindesay if (iconTarPtrRef->HasOffset(BITMAP_SIZE_16)) { 358f0e491d3SAndrew Lindesay *actualSize = BITMAP_SIZE_16; 359f0e491d3SAndrew Lindesay return iconTarPtrRef->Offset(BITMAP_SIZE_16); 360f0e491d3SAndrew Lindesay } 361f0e491d3SAndrew Lindesay return -1; 362f0e491d3SAndrew Lindesay } 363f0e491d3SAndrew Lindesay 364f0e491d3SAndrew Lindesay 365f0e491d3SAndrew Lindesay IconTarPtrRef 366f0e491d3SAndrew Lindesay PackageIconTarRepository::_GetOrCreateIconTarPtr(const BString& pkgName) 367f0e491d3SAndrew Lindesay { 368f0e491d3SAndrew Lindesay BAutolock locker(&fLock); 369f0e491d3SAndrew Lindesay HashString key(pkgName); 370f0e491d3SAndrew Lindesay if (!fIconTarPtrs.ContainsKey(key)) { 371f0e491d3SAndrew Lindesay IconTarPtrRef value(new IconTarPtr(pkgName)); 372f0e491d3SAndrew Lindesay fIconTarPtrs.Put(key, value); 373f0e491d3SAndrew Lindesay return value; 374f0e491d3SAndrew Lindesay } 375f0e491d3SAndrew Lindesay return fIconTarPtrs.Get(key); 376f0e491d3SAndrew Lindesay } 377f0e491d3SAndrew Lindesay 378f0e491d3SAndrew Lindesay 379f0e491d3SAndrew Lindesay /*static*/ void 380f0e491d3SAndrew Lindesay PackageIconTarRepository::CleanupDefaultIcon() 381f0e491d3SAndrew Lindesay { 382f0e491d3SAndrew Lindesay sDefaultIcon.Unset(); 383f0e491d3SAndrew Lindesay } 384