1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 #ifndef _NU_ICON_CACHE_H 35 #define _NU_ICON_CACHE_H 36 37 38 // Icon cache is used for drawing node icons; it caches icons 39 // and reuses them for successive draws 40 41 42 #include <Bitmap.h> 43 #include <ObjectList.h> 44 #include <Mime.h> 45 #include <String.h> 46 47 #include "AutoLock.h" 48 #include "HashSet.h" 49 #include "Utilities.h" 50 51 52 // Icon cache splits icons into two caches - the shared cache, likely to 53 // get the most hits and the node cache. Every icon that is found in a 54 // mime-based structure goes into the shared cache, only files that have 55 // their own private icon use the node cache; 56 // Entries are only deleted from the shared cache if an icon for a mime type 57 // changes, this makes async icon drawing easier. Node cache deletes it's 58 // entries whenever a file gets deleted. 59 60 // if a view ever uses the cache to draw in async mode, it needs to call 61 // it when it is being destroyed 62 63 namespace BPrivate { 64 65 class Model; 66 class ModelNodeLazyOpener; 67 class LazyBitmapAllocator; 68 class SharedIconCache; 69 class SharedCacheEntry; 70 class GenerateThumbnailJob; 71 72 enum IconDrawMode { 73 // Different states of icon drawing 74 kSelected = 0x01, 75 kNotFocused = 0x02, // Tracker window 76 kOpen = 0x04, // open folder, trash 77 kNotEmpty = 0x08, // full trash 78 kDisabled = 0x10, // inactive nav menu entry 79 kActive = 0x20, // active home dir, boot volume 80 kLink = 0x40, // symbolic link 81 kTrackerSpecialized = 0x80, 82 83 // some common combinations 84 kNormalIcon = 0, 85 kSelectedIcon = kSelected, 86 kSelectedInBackgroundIcon = kSelected | kNotFocused, 87 kOpenIcon = kOpen, 88 kOpenSelectedIcon = kSelected | kOpen, 89 kOpenSelectedInBackgroundIcon = kSelected | kNotFocused | kOpen, 90 kFullIcon = kNotEmpty, 91 kFullSelectedIcon = kNotEmpty | kOpen, 92 kDimmedIcon 93 }; 94 95 96 #define NORMAL_ICON_ONLY kNormalIcon 97 // replace use of these defines with mode once the respective getters 98 // can get non-plain icons 99 100 101 // Where did an icon come from 102 enum IconSource { 103 kUnknownSource, 104 kUnknownNotFromNode, // icon origin not known but determined not 105 // to be from the node itself 106 kTrackerDefault, // file has no type, Tracker provides generic, 107 // folder, symlink or app 108 kTrackerSupplied, // home directory, boot volume, trash, etc. 109 kMetaMime, // from BMimeType 110 kPreferredAppForType, // have a preferred application for a type, 111 // has an icon 112 kPreferredAppForNode, // have a preferred application for this node, 113 // has an icon 114 kVolume, 115 kNode 116 }; 117 118 119 template<typename Class> 120 struct SelfHashing { 121 typedef typename Class::HashKeyType KeyType; 122 typedef Class ValueType; 123 124 size_t HashKey(KeyType key) const 125 { 126 return Class::Hash(key); 127 } 128 129 size_t Hash(ValueType* value) const 130 { 131 return value->Hash(); 132 } 133 134 bool Compare(KeyType key, ValueType* value) const 135 { 136 return *value == key; 137 } 138 139 ValueType*& GetLink(ValueType* value) const 140 { 141 return value->HashNext(); 142 } 143 }; 144 145 146 class IconCacheEntry { 147 // aliased entries don't own their icons, just point 148 // to some other entry that does 149 150 // This is used for icons that are defined by a preferred app for 151 // a metamime, types that do not have an icon get to point to 152 // generic, etc. 153 154 public: 155 IconCacheEntry(); 156 ~IconCacheEntry(); 157 158 void SetAliasFor(const SharedIconCache* sharedCache, 159 const SharedCacheEntry* entry); 160 static IconCacheEntry* ResolveIfAlias(const SharedIconCache* sharedCache, 161 IconCacheEntry* entry); 162 IconCacheEntry* ResolveIfAlias(const SharedIconCache* sharedCache); 163 164 void SetIcon(BBitmap* bitmap, IconDrawMode mode, BSize size); 165 166 bool HaveIconBitmap(IconDrawMode mode, BSize size) const; 167 bool CanConstructBitmap(IconDrawMode mode, BSize size) const; 168 static bool AlternateModeForIconConstructing(IconDrawMode requestedMode, 169 IconDrawMode &alternate, BSize size); 170 BBitmap* ConstructBitmap(BBitmap* constructFrom, 171 IconDrawMode requestedMode, IconDrawMode constructFromMode, 172 BSize size, LazyBitmapAllocator*); 173 BBitmap* ConstructBitmap(IconDrawMode requestedMode, BSize size, 174 LazyBitmapAllocator*); 175 // same as above, always uses normal icon as source 176 177 bool IconHitTest(BPoint, IconDrawMode, BSize) const; 178 // given a point, returns true if a non-transparent pixel was hit 179 180 void RetireIcons(BObjectList<BBitmap>* retiredBitmapList); 181 // can't just delete icons, they may be still drawing 182 // async; instead, put them on the retired list and 183 // only delete the list if it grows too much, way after 184 // the icon finishes drawing 185 // 186 // This could fail if we retire a lot of icons (10 * 1024) 187 // while we are drawing them, shouldn't be a practical problem 188 189 protected: 190 BBitmap* IconForMode(IconDrawMode mode, BSize size) const; 191 void SetIconForMode(BBitmap* bitmap, IconDrawMode mode, BSize size); 192 193 // list of most common icons 194 BBitmap* fLargeIcon; 195 BBitmap* fHighlightedLargeIcon; 196 BBitmap* fMiniIcon; 197 BBitmap* fHighlightedMiniIcon; 198 199 const IconCacheEntry* fAliasTo; 200 201 // list of other icon kinds would be added here 202 203 friend class SharedIconCache; 204 friend class NodeIconCache; 205 }; 206 207 208 class SimpleIconCache { 209 public: 210 SimpleIconCache(const char*); 211 virtual ~SimpleIconCache() {} 212 213 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode mode, 214 BSize size, bool async = false) = 0; 215 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 216 BSize, void (*)(BView*, BPoint, BBitmap*, void*), 217 void* = NULL) = 0; 218 219 bool Lock(); 220 void Unlock(); 221 bool IsLocked() const; 222 223 private: 224 Benaphore fLock; 225 }; 226 227 228 class SharedCacheEntry : public IconCacheEntry { 229 public: 230 SharedCacheEntry(); 231 SharedCacheEntry(const char* fileType, const char* appSignature = 0); 232 233 void Draw(BView*, BPoint, IconDrawMode mode, BSize size, 234 bool async = false); 235 236 void Draw(BView*, BPoint, IconDrawMode, BSize, 237 void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL); 238 239 const char* FileType() const; 240 const char* AppSignature() const; 241 242 public: 243 // hash table support 244 struct TypeAndSignature { 245 const char* type, *signature; 246 TypeAndSignature(const char* t, const char* s) 247 : type(t), signature(s) {} 248 }; 249 typedef TypeAndSignature HashKeyType; 250 static size_t Hash(const TypeAndSignature& typeAndSignature); 251 252 size_t Hash() const; 253 SharedCacheEntry*& HashNext() { return fNext; } 254 bool operator==(const TypeAndSignature& typeAndSignature) const; 255 256 private: 257 SharedCacheEntry* fNext; 258 259 BString fFileType; 260 BString fAppSignature; 261 262 friend class SharedIconCache; 263 }; 264 265 266 class SharedIconCache : public SimpleIconCache { 267 // SharedIconCache is used for icons that come from the mime database 268 public: 269 SharedIconCache(); 270 271 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode mode, 272 BSize size, bool async = false); 273 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 274 BSize, void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL); 275 276 SharedCacheEntry* FindItem(const char* fileType, 277 const char* appSignature = 0) const; 278 SharedCacheEntry* AddItem(const char* fileType, 279 const char* appSignature = 0); 280 void IconChanged(SharedCacheEntry*); 281 282 void SetAliasFor(IconCacheEntry* entry, 283 const SharedCacheEntry* original) const; 284 IconCacheEntry* ResolveIfAlias(IconCacheEntry* entry) const; 285 286 void RemoveAliasesTo(SharedCacheEntry* alias); 287 288 private: 289 typedef BOpenHashTable<SelfHashing<SharedCacheEntry> > EntryHashTable; 290 EntryHashTable fHashTable; 291 292 BObjectList<BBitmap> fRetiredBitmaps; 293 // icons are drawn asynchronously, can't just delete them right away, 294 // instead have to place them onto the retired bitmap list and wait 295 // for the next sync to delete them 296 }; 297 298 299 class NodeCacheEntry : public IconCacheEntry { 300 public: 301 NodeCacheEntry(bool permanent = false); 302 NodeCacheEntry(const node_ref*, bool permanent = false); 303 void Draw(BView*, BPoint, IconDrawMode mode, BSize size, 304 bool async = false); 305 306 void Draw(BView*, BPoint, IconDrawMode, BSize, 307 void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL); 308 309 const node_ref* Node() const; 310 311 bool Permanent() const; 312 313 public: 314 // hash table support 315 typedef const node_ref* HashKeyType; 316 static size_t Hash(const node_ref* node); 317 318 size_t Hash() const; 319 NodeCacheEntry*& HashNext() { return fNext; } 320 bool operator==(const node_ref* ref) const; 321 322 private: 323 NodeCacheEntry* fNext; 324 325 node_ref fRef; 326 bool fPermanent; 327 // special cache entry that has to be deleted explicitly 328 329 friend class NodeIconCache; 330 }; 331 332 333 class NodeIconCache : public SimpleIconCache { 334 // NodeIconCache is used for nodes that define their own icons 335 public: 336 NodeIconCache(); 337 338 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 339 BSize, bool async = false); 340 341 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 342 BSize, void (*)(BView*, BPoint, BBitmap*, void*), void* = 0); 343 344 NodeCacheEntry* FindItem(const node_ref*) const; 345 NodeCacheEntry* AddItem(const node_ref*, bool permanent = false); 346 void Deleting(const node_ref*); 347 // model for this node is getting deleted 348 // (not necessarily the node itself) 349 void Removing(const node_ref*); 350 // used by permanent NodeIconCache entries, when an entry gets deleted 351 void Deleting(const BView*); 352 void IconChanged(const Model*); 353 354 void RemoveAliasesTo(SharedCacheEntry* alias); 355 356 private: 357 typedef BOpenHashTable<SelfHashing<NodeCacheEntry> > EntryHashTable; 358 EntryHashTable fHashTable; 359 }; 360 361 362 const int32 kColorTransformTableSize = 256; 363 364 365 class IconCache { 366 public: 367 IconCache(); 368 369 void Draw(Model*, BView*, BPoint where, IconDrawMode mode, 370 BSize size, bool async = false); 371 // draw an icon for a model, load the icon from the appropriate 372 // location if not cached already 373 374 void SyncDraw(Model*, BView*, BPoint, IconDrawMode, 375 BSize, void (*)(BView*, BPoint, BBitmap*, void*), 376 void* passThruState = 0); 377 // draw an icon for a model, load the icon from the appropriate 378 // location if not cached already; only works for sync draws, 379 // once the call returns, the bitmap may be deleted 380 381 // preload calls used to ensure successive cache hit for the respective 382 // icon, used for common tracker types, etc; Not calling these should only 383 // cause a slowdown 384 void Preload(Model*, IconDrawMode mode, BSize size, 385 bool permanent = false); 386 status_t Preload(const char* mimeType, IconDrawMode mode, BSize size); 387 388 void Deleting(const Model*); 389 // hook to manage unloading icons for nodes that are going away 390 void Removing(const Model* model); 391 // used by permanent NodeIconCache entries, when an entry gets 392 // deleted 393 void Deleting(const BView*); 394 // hook to manage deleting draw view caches for views that are 395 // going away 396 397 // icon changed calls, used when a node or a file type has an icon changed 398 // the icons for the node/file type will be flushed and re-cached during 399 // the next draw 400 void IconChanged(Model*); 401 void IconChanged(const char* mimeType, const char* appSignature); 402 403 bool IsIconFrom(const Model*, const char* mimeType, 404 const char* appSignature) const; 405 // called when metamime database changed to figure out which models 406 // to redraw 407 408 bool IconHitTest(BPoint, const Model*, IconDrawMode, BSize); 409 410 // utility calls for building specialized icons 411 BBitmap* MakeSelectedIcon(const BBitmap* normal, BSize, 412 LazyBitmapAllocator*); 413 414 static bool NeedsDeletionNotification(IconSource); 415 416 static IconCache* sIconCache; 417 static BSize sMiniIconSize; 418 419 private: 420 // shared calls 421 IconCacheEntry* Preload(AutoLock<SimpleIconCache>* nodeCache, 422 AutoLock<SimpleIconCache>* sharedCache, 423 AutoLock<SimpleIconCache>** resultingLockedCache, 424 Model*, IconDrawMode mode, BSize size, bool permanent); 425 // preload uses lazy locking, returning the cache we decided 426 // to use to get the icon 427 // <resultingLockedCache> may be null if we don't care 428 429 // shared mime-based icon retrieval calls 430 IconCacheEntry* GetIconForPreferredApp(const char* mimeTypeSignature, 431 const char* preferredApp, IconDrawMode mode, BSize size, 432 LazyBitmapAllocator*, IconCacheEntry*); 433 IconCacheEntry* GetIconFromFileTypes(ModelNodeLazyOpener*, 434 IconSource &source, IconDrawMode mode, BSize size, 435 LazyBitmapAllocator*, IconCacheEntry*); 436 IconCacheEntry* GetIconFromMetaMime(const char* fileType, 437 IconDrawMode mode, BSize size, LazyBitmapAllocator*, 438 IconCacheEntry*); 439 IconCacheEntry* GetVolumeIcon(AutoLock<SimpleIconCache>* nodeCache, 440 AutoLock<SimpleIconCache>* sharedCache, 441 AutoLock<SimpleIconCache>** resultingLockedCache, 442 Model*, IconSource&, IconDrawMode mode, 443 BSize size, LazyBitmapAllocator*); 444 IconCacheEntry* GetRootIcon(AutoLock<SimpleIconCache>* nodeCache, 445 AutoLock<SimpleIconCache>* sharedCache, 446 AutoLock<SimpleIconCache>** resultingLockedCache, 447 Model*, IconSource&, IconDrawMode mode, 448 BSize size, LazyBitmapAllocator*); 449 IconCacheEntry* GetWellKnownIcon(AutoLock<SimpleIconCache> *nodeCache, 450 AutoLock<SimpleIconCache>* sharedCache, 451 AutoLock<SimpleIconCache>** resultingLockedCache, 452 Model*, IconSource&, IconDrawMode mode, 453 BSize size, LazyBitmapAllocator*); 454 IconCacheEntry* GetNodeIcon(ModelNodeLazyOpener *, 455 AutoLock<SimpleIconCache>* nodeCache, 456 AutoLock<SimpleIconCache>** resultingLockedCache, 457 Model*, IconSource&, IconDrawMode mode, 458 BSize size, LazyBitmapAllocator*, IconCacheEntry*, 459 bool permanent); 460 IconCacheEntry* GetGenericIcon(AutoLock<SimpleIconCache>* sharedCache, 461 AutoLock<SimpleIconCache>** resultingLockedCache, 462 Model*, IconSource&, IconDrawMode mode, 463 BSize size, LazyBitmapAllocator*, IconCacheEntry*); 464 IconCacheEntry* GetFallbackIcon( 465 AutoLock<SimpleIconCache>* sharedCacheLocker, 466 AutoLock<SimpleIconCache>** resultingOpenCache, 467 Model* model, IconDrawMode mode, BSize size, 468 LazyBitmapAllocator* lazyBitmap, IconCacheEntry* entry); 469 470 BBitmap* MakeTransformedIcon(const BBitmap*, BSize, 471 int32 colorTransformTable [], LazyBitmapAllocator*); 472 473 private: 474 NodeIconCache fNodeCache; 475 SharedIconCache fSharedCache; 476 477 void InitHighlightTable(); 478 479 int32 fHighlightTable[kColorTransformTableSize]; 480 bool fInitHighlightTable; 481 // whether or not we need to initialize the highlight table 482 483 friend class BPrivate::GenerateThumbnailJob; 484 }; 485 486 487 class LazyBitmapAllocator { 488 // Utility class used when we aren't sure that we will keep a bitmap, 489 // need a bitmap or be able to construct it properly 490 public: 491 LazyBitmapAllocator(BSize size, 492 color_space colorSpace = kDefaultIconDepth, 493 bool preallocate = false); 494 ~LazyBitmapAllocator(); 495 496 BBitmap* Get(); 497 BBitmap* Adopt(); 498 499 private: 500 BBitmap* fBitmap; 501 BSize fSize; 502 color_space fColorSpace; 503 }; 504 505 506 // inlines follow 507 508 inline const char* 509 SharedCacheEntry::FileType() const 510 { 511 return fFileType.String(); 512 } 513 514 515 inline const char* 516 SharedCacheEntry::AppSignature() const 517 { 518 return fAppSignature.String(); 519 } 520 521 522 inline bool 523 IconCache::NeedsDeletionNotification(IconSource from) 524 { 525 return from == kNode; 526 } 527 528 529 inline IconCacheEntry* 530 SharedIconCache::ResolveIfAlias(IconCacheEntry* entry) const 531 { 532 if (entry->fAliasTo == NULL) 533 return entry; 534 535 return const_cast<IconCacheEntry*>(entry->fAliasTo); 536 } 537 538 539 } // namespace BPrivate 540 541 using namespace BPrivate; 542 543 544 #endif // _NU_ICON_CACHE_H 545