1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/cocoa/table_row_nsimage_cache.h" 6 7 #include "base/logging.h" 8 #include "skia/ext/skia_utils_mac.h" 9 #include "third_party/skia/include/core/SkBitmap.h" 10 11 TableRowNSImageCache::TableRowNSImageCache(Table* model) 12 : model_(model), 13 icon_images_([[NSPointerArray alloc] initWithOptions: 14 NSPointerFunctionsStrongMemory | 15 NSPointerFunctionsObjectPersonality]) { 16 int count = model_->RowCount(); 17 [icon_images_ setCount:count]; 18 } 19 20 TableRowNSImageCache::~TableRowNSImageCache() {} 21 22 void TableRowNSImageCache::OnModelChanged() { 23 int count = model_->RowCount(); 24 [icon_images_ setCount:0]; 25 [icon_images_ setCount:count]; 26 } 27 28 void TableRowNSImageCache::OnItemsChanged(int start, int length) { 29 DCHECK_LE(start + length, static_cast<int>([icon_images_ count])); 30 for (int i = start; i < (start + length); ++i) { 31 [icon_images_ replacePointerAtIndex:i withPointer:NULL]; 32 } 33 DCHECK_EQ(model_->RowCount(), 34 static_cast<int>([icon_images_ count])); 35 } 36 37 void TableRowNSImageCache::OnItemsAdded(int start, int length) { 38 DCHECK_LE(start, static_cast<int>([icon_images_ count])); 39 40 // -[NSPointerArray insertPointer:atIndex:] throws if index == count. 41 // Instead expand the array with NULLs. 42 if (start == static_cast<int>([icon_images_ count])) { 43 [icon_images_ setCount:start + length]; 44 } else { 45 for (int i = 0; i < length; ++i) { 46 [icon_images_ insertPointer:NULL atIndex:start]; // Values slide up. 47 } 48 } 49 DCHECK_EQ(model_->RowCount(), 50 static_cast<int>([icon_images_ count])); 51 } 52 53 void TableRowNSImageCache::OnItemsRemoved(int start, int length) { 54 DCHECK_LE(start + length, static_cast<int>([icon_images_ count])); 55 for (int i = 0; i < length; ++i) { 56 [icon_images_ removePointerAtIndex:start]; // Values slide down. 57 } 58 DCHECK_EQ(model_->RowCount(), 59 static_cast<int>([icon_images_ count])); 60 } 61 62 NSImage* TableRowNSImageCache::GetImageForRow(int row) { 63 DCHECK_EQ(model_->RowCount(), 64 static_cast<int>([icon_images_ count])); 65 DCHECK_GE(row, 0); 66 DCHECK_LT(row, static_cast<int>([icon_images_ count])); 67 NSImage* image = static_cast<NSImage*>([icon_images_ pointerAtIndex:row]); 68 if (!image) { 69 const SkBitmap bitmap_icon = 70 model_->GetIcon(row); 71 // This means GetIcon() will get called until it returns a non-empty bitmap. 72 // Empty bitmaps are intentionally not cached. 73 if (!bitmap_icon.isNull()) { 74 image = gfx::SkBitmapToNSImage(bitmap_icon); 75 DCHECK(image); 76 [icon_images_ replacePointerAtIndex:row withPointer:image]; 77 } 78 } 79 return image; 80 } 81 82