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, icon_size size, 165 bool create = false); 166 167 bool HaveIconBitmap(IconDrawMode mode, icon_size size) const; 168 bool CanConstructBitmap(IconDrawMode mode, icon_size size) const; 169 static bool AlternateModeForIconConstructing(IconDrawMode requestedMode, 170 IconDrawMode &alternate, icon_size size); 171 BBitmap* ConstructBitmap(BBitmap* constructFrom, 172 IconDrawMode requestedMode, IconDrawMode constructFromMode, 173 icon_size size, LazyBitmapAllocator*); 174 BBitmap* ConstructBitmap(IconDrawMode requestedMode, icon_size size, 175 LazyBitmapAllocator*); 176 // same as above, always uses normal icon as source 177 178 bool IconHitTest(BPoint, IconDrawMode, icon_size) const; 179 // given a point, returns true if a non-transparent pixel was hit 180 181 void RetireIcons(BObjectList<BBitmap>* retiredBitmapList); 182 // can't just delete icons, they may be still drawing 183 // async; instead, put them on the retired list and 184 // only delete the list if it grows too much, way after 185 // the icon finishes drawing 186 // 187 // This could fail if we retire a lot of icons (10 * 1024) 188 // while we are drawing them, shouldn't be a practical problem 189 190 protected: 191 BBitmap* IconForMode(IconDrawMode mode, icon_size size) const; 192 void SetIconForMode(BBitmap* bitmap, IconDrawMode mode, icon_size size); 193 194 // list of most common icons 195 BBitmap* fLargeIcon; 196 BBitmap* fHighlightedLargeIcon; 197 BBitmap* fMiniIcon; 198 BBitmap* fHighlightedMiniIcon; 199 200 const IconCacheEntry* fAliasTo; 201 202 // list of other icon kinds would be added here 203 204 friend class SharedIconCache; 205 friend class NodeIconCache; 206 }; 207 208 209 class SimpleIconCache { 210 public: 211 SimpleIconCache(const char*); 212 virtual ~SimpleIconCache() {} 213 214 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode mode, 215 icon_size size, bool async = false) = 0; 216 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 217 icon_size, void (*)(BView*, BPoint, BBitmap*, void*), 218 void* = NULL) = 0; 219 220 bool Lock(); 221 void Unlock(); 222 bool IsLocked() const; 223 224 private: 225 Benaphore fLock; 226 }; 227 228 229 class SharedCacheEntry : public IconCacheEntry { 230 public: 231 SharedCacheEntry(); 232 SharedCacheEntry(const char* fileType, const char* appSignature = 0); 233 234 void Draw(BView*, BPoint, IconDrawMode mode, icon_size size, 235 bool async = false); 236 237 void Draw(BView*, BPoint, IconDrawMode, icon_size, 238 void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL); 239 240 const char* FileType() const; 241 const char* AppSignature() const; 242 243 public: 244 // hash table support 245 struct TypeAndSignature { 246 const char* type, *signature; 247 TypeAndSignature(const char* t, const char* s) 248 : type(t), signature(s) {} 249 }; 250 typedef TypeAndSignature HashKeyType; 251 static size_t Hash(const TypeAndSignature& typeAndSignature); 252 253 size_t Hash() const; 254 SharedCacheEntry*& HashNext() { return fNext; } 255 bool operator==(const TypeAndSignature& typeAndSignature) const; 256 257 private: 258 SharedCacheEntry* fNext; 259 260 BString fFileType; 261 BString fAppSignature; 262 263 friend class SharedIconCache; 264 }; 265 266 267 class SharedIconCache : public SimpleIconCache { 268 // SharedIconCache is used for icons that come from the mime database 269 public: 270 SharedIconCache(); 271 272 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode mode, 273 icon_size size, bool async = false); 274 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 275 icon_size, void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL); 276 277 SharedCacheEntry* FindItem(const char* fileType, 278 const char* appSignature = 0) const; 279 SharedCacheEntry* AddItem(const char* fileType, 280 const char* appSignature = 0); 281 void IconChanged(SharedCacheEntry*); 282 283 void SetAliasFor(IconCacheEntry* entry, 284 const SharedCacheEntry* original) const; 285 IconCacheEntry* ResolveIfAlias(IconCacheEntry* entry) const; 286 287 void RemoveAliasesTo(SharedCacheEntry* alias); 288 289 private: 290 typedef BOpenHashTable<SelfHashing<SharedCacheEntry> > EntryHashTable; 291 EntryHashTable fHashTable; 292 293 BObjectList<BBitmap> fRetiredBitmaps; 294 // icons are drawn asynchronously, can't just delete them right away, 295 // instead have to place them onto the retired bitmap list and wait 296 // for the next sync to delete them 297 }; 298 299 300 class NodeCacheEntry : public IconCacheEntry { 301 public: 302 NodeCacheEntry(bool permanent = false); 303 NodeCacheEntry(const node_ref*, bool permanent = false); 304 void Draw(BView*, BPoint, IconDrawMode mode, icon_size size, 305 bool async = false); 306 307 void Draw(BView*, BPoint, IconDrawMode, icon_size, 308 void (*)(BView*, BPoint, BBitmap*, void*), void* = NULL); 309 310 const node_ref* Node() const; 311 312 bool Permanent() const; 313 314 public: 315 // hash table support 316 typedef const node_ref* HashKeyType; 317 static size_t Hash(const node_ref* node); 318 319 size_t Hash() const; 320 NodeCacheEntry*& HashNext() { return fNext; } 321 bool operator==(const node_ref* ref) const; 322 323 private: 324 NodeCacheEntry* fNext; 325 326 node_ref fRef; 327 bool fPermanent; 328 // special cache entry that has to be deleted explicitly 329 330 friend class NodeIconCache; 331 }; 332 333 334 class NodeIconCache : public SimpleIconCache { 335 // NodeIconCache is used for nodes that define their own icons 336 public: 337 NodeIconCache(); 338 339 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 340 icon_size, bool async = false); 341 342 virtual void Draw(IconCacheEntry*, BView*, BPoint, IconDrawMode, 343 icon_size, void (*)(BView*, BPoint, BBitmap*, void*), void* = 0); 344 345 NodeCacheEntry* FindItem(const node_ref*) const; 346 NodeCacheEntry* AddItem(const node_ref*, bool permanent = false); 347 void Deleting(const node_ref*); 348 // model for this node is getting deleted 349 // (not necessarily the node itself) 350 void Removing(const node_ref*); 351 // used by permanent NodeIconCache entries, when an entry gets deleted 352 void Deleting(const BView*); 353 void IconChanged(const Model*); 354 355 void RemoveAliasesTo(SharedCacheEntry* alias); 356 357 private: 358 typedef BOpenHashTable<SelfHashing<NodeCacheEntry> > EntryHashTable; 359 EntryHashTable fHashTable; 360 }; 361 362 363 const int32 kColorTransformTableSize = 256; 364 365 366 class IconCache { 367 public: 368 IconCache(); 369 370 void Draw(Model*, BView*, BPoint where, IconDrawMode mode, 371 icon_size size, bool async = false); 372 // draw an icon for a model, load the icon from the appropriate 373 // location if not cached already 374 375 void SyncDraw(Model*, BView*, BPoint, IconDrawMode, 376 icon_size, void (*)(BView*, BPoint, BBitmap*, void*), 377 void* passThruState = 0); 378 // draw an icon for a model, load the icon from the appropriate 379 // location if not cached already; only works for sync draws, 380 // once the call returns, the bitmap may be deleted 381 382 // preload calls used to ensure successive cache hit for the respective 383 // icon, used for common tracker types, etc; Not calling these should only 384 // cause a slowdown 385 void Preload(Model*, IconDrawMode mode, icon_size size, 386 bool permanent = false); 387 status_t Preload(const char* mimeType, IconDrawMode mode, icon_size size); 388 389 void Deleting(const Model*); 390 // hook to manage unloading icons for nodes that are going away 391 void Removing(const Model* model); 392 // used by permanent NodeIconCache entries, when an entry gets 393 // deleted 394 void Deleting(const BView*); 395 // hook to manage deleting draw view caches for views that are 396 // going away 397 398 // icon changed calls, used when a node or a file type has an icon changed 399 // the icons for the node/file type will be flushed and re-cached during 400 // the next draw 401 void IconChanged(Model*); 402 void IconChanged(const char* mimeType, const char* appSignature); 403 404 bool IsIconFrom(const Model*, const char* mimeType, 405 const char* appSignature) const; 406 // called when metamime database changed to figure out which models 407 // to redraw 408 409 bool IconHitTest(BPoint, const Model*, IconDrawMode, icon_size); 410 411 // utility calls for building specialized icons 412 BBitmap* MakeSelectedIcon(const BBitmap* normal, icon_size, 413 LazyBitmapAllocator*); 414 415 static bool NeedsDeletionNotification(IconSource); 416 417 static IconCache* sIconCache; 418 419 private: 420 // shared calls 421 IconCacheEntry* Preload(AutoLock<SimpleIconCache>* nodeCache, 422 AutoLock<SimpleIconCache>* sharedCache, 423 AutoLock<SimpleIconCache>** resultingLockedCache, 424 Model*, IconDrawMode mode, icon_size 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, icon_size size, 432 LazyBitmapAllocator*, IconCacheEntry*); 433 IconCacheEntry* GetIconFromFileTypes(ModelNodeLazyOpener*, 434 IconSource &source, IconDrawMode mode, icon_size size, 435 LazyBitmapAllocator*, IconCacheEntry*); 436 IconCacheEntry* GetIconFromMetaMime(const char* fileType, 437 IconDrawMode mode, icon_size size, LazyBitmapAllocator*, 438 IconCacheEntry*); 439 IconCacheEntry* GetVolumeIcon(AutoLock<SimpleIconCache>* nodeCache, 440 AutoLock<SimpleIconCache>* sharedCache, 441 AutoLock<SimpleIconCache>** resultingLockedCache, 442 Model*, IconSource&, IconDrawMode mode, 443 icon_size size, LazyBitmapAllocator*); 444 IconCacheEntry* GetRootIcon(AutoLock<SimpleIconCache>* nodeCache, 445 AutoLock<SimpleIconCache>* sharedCache, 446 AutoLock<SimpleIconCache>** resultingLockedCache, 447 Model*, IconSource&, IconDrawMode mode, 448 icon_size size, LazyBitmapAllocator*); 449 IconCacheEntry* GetWellKnownIcon(AutoLock<SimpleIconCache> *nodeCache, 450 AutoLock<SimpleIconCache>* sharedCache, 451 AutoLock<SimpleIconCache>** resultingLockedCache, 452 Model*, IconSource&, IconDrawMode mode, 453 icon_size size, LazyBitmapAllocator*); 454 IconCacheEntry* GetNodeIcon(ModelNodeLazyOpener *, 455 AutoLock<SimpleIconCache>* nodeCache, 456 AutoLock<SimpleIconCache>** resultingLockedCache, 457 Model*, IconSource&, IconDrawMode mode, 458 icon_size size, LazyBitmapAllocator*, IconCacheEntry*, 459 bool permanent); 460 IconCacheEntry* GetGenericIcon(AutoLock<SimpleIconCache>* sharedCache, 461 AutoLock<SimpleIconCache>** resultingLockedCache, 462 Model*, IconSource&, IconDrawMode mode, 463 icon_size size, LazyBitmapAllocator*, IconCacheEntry*); 464 IconCacheEntry* GetFallbackIcon( 465 AutoLock<SimpleIconCache>* sharedCacheLocker, 466 AutoLock<SimpleIconCache>** resultingOpenCache, 467 Model* model, IconDrawMode mode, icon_size size, 468 LazyBitmapAllocator* lazyBitmap, IconCacheEntry* entry); 469 470 BBitmap* MakeTransformedIcon(const BBitmap*, icon_size, 471 int32 colorTransformTable [], LazyBitmapAllocator*); 472 473 NodeIconCache fNodeCache; 474 SharedIconCache fSharedCache; 475 476 void InitHighlightTable(); 477 478 int32 fHighlightTable[kColorTransformTableSize]; 479 bool fInitHighlightTable; 480 // whether or not we need to initialize the highlight table 481 482 friend class BPrivate::GenerateThumbnailJob; 483 }; 484 485 486 class LazyBitmapAllocator { 487 // Utility class used when we aren't sure that we will keep a bitmap, 488 // need a bitmap or be able to construct it properly 489 public: 490 LazyBitmapAllocator(icon_size size, 491 color_space colorSpace = kDefaultIconDepth, 492 bool preallocate = false); 493 ~LazyBitmapAllocator(); 494 495 BBitmap* Get(); 496 BBitmap* Adopt(); 497 498 private: 499 BBitmap* fBitmap; 500 icon_size fSize; 501 color_space fColorSpace; 502 }; 503 504 505 // inlines follow 506 507 inline const char* 508 SharedCacheEntry::FileType() const 509 { 510 return fFileType.String(); 511 } 512 513 514 inline const char* 515 SharedCacheEntry::AppSignature() const 516 { 517 return fAppSignature.String(); 518 } 519 520 521 inline bool 522 IconCache::NeedsDeletionNotification(IconSource from) 523 { 524 return from == kNode; 525 } 526 527 528 inline IconCacheEntry* 529 SharedIconCache::ResolveIfAlias(IconCacheEntry* entry) const 530 { 531 if (entry->fAliasTo == NULL) 532 return entry; 533 534 return const_cast<IconCacheEntry*>(entry->fAliasTo); 535 } 536 537 538 } // namespace BPrivate 539 540 using namespace BPrivate; 541 542 543 #endif // _NU_ICON_CACHE_H 544