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/extensions/extension_icon_manager.h" 6 7#include "base/logging.h" 8#include "base/stl_util-inl.h" 9#include "chrome/common/extensions/extension.h" 10#include "chrome/common/extensions/extension_icon_set.h" 11#include "chrome/common/extensions/extension_resource.h" 12#include "grit/theme_resources.h" 13#include "skia/ext/image_operations.h" 14#include "ui/base/resource/resource_bundle.h" 15#include "ui/gfx/canvas_skia.h" 16#include "ui/gfx/color_utils.h" 17#include "ui/gfx/favicon_size.h" 18#include "ui/gfx/size.h" 19#include "ui/gfx/skbitmap_operations.h" 20 21namespace { 22 23// Helper function to create a new bitmap with |padding| amount of empty space 24// around the original bitmap. 25static SkBitmap ApplyPadding(const SkBitmap& source, 26 const gfx::Insets& padding) { 27 scoped_ptr<gfx::CanvasSkia> result( 28 new gfx::CanvasSkia(source.width() + padding.width(), 29 source.height() + padding.height(), false)); 30 result->DrawBitmapInt( 31 source, 32 0, 0, source.width(), source.height(), 33 padding.left(), padding.top(), source.width(), source.height(), 34 false); 35 return result->ExtractBitmap(); 36} 37 38} // namespace 39 40ExtensionIconManager::ExtensionIconManager() 41 : ALLOW_THIS_IN_INITIALIZER_LIST(image_tracker_(this)), 42 monochrome_(false) { 43} 44 45ExtensionIconManager::~ExtensionIconManager() { 46} 47 48void ExtensionIconManager::LoadIcon(const Extension* extension) { 49 ExtensionResource icon_resource = extension->GetIconResource( 50 Extension::EXTENSION_ICON_BITTY, ExtensionIconSet::MATCH_BIGGER); 51 if (!icon_resource.extension_root().empty()) { 52 // Insert into pending_icons_ first because LoadImage can call us back 53 // synchronously if the image is already cached. 54 pending_icons_.insert(extension->id()); 55 image_tracker_.LoadImage(extension, 56 icon_resource, 57 gfx::Size(kFaviconSize, kFaviconSize), 58 ImageLoadingTracker::CACHE); 59 } 60} 61 62const SkBitmap& ExtensionIconManager::GetIcon(const std::string& extension_id) { 63 const SkBitmap* result = NULL; 64 if (ContainsKey(icons_, extension_id)) { 65 result = &icons_[extension_id]; 66 } else { 67 EnsureDefaultIcon(); 68 result = &default_icon_; 69 } 70 DCHECK(result); 71 DCHECK_EQ(kFaviconSize + padding_.width(), result->width()); 72 DCHECK_EQ(kFaviconSize + padding_.height(), result->height()); 73 return *result; 74} 75 76void ExtensionIconManager::RemoveIcon(const std::string& extension_id) { 77 icons_.erase(extension_id); 78 pending_icons_.erase(extension_id); 79} 80 81void ExtensionIconManager::OnImageLoaded(SkBitmap* image, 82 const ExtensionResource& resource, 83 int index) { 84 if (!image) 85 return; 86 87 const std::string extension_id = resource.extension_id(); 88 89 // We may have removed the icon while waiting for it to load. In that case, 90 // do nothing. 91 if (!ContainsKey(pending_icons_, extension_id)) 92 return; 93 94 pending_icons_.erase(extension_id); 95 icons_[extension_id] = ApplyTransforms(*image); 96} 97 98void ExtensionIconManager::EnsureDefaultIcon() { 99 if (default_icon_.empty()) { 100 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 101 SkBitmap* src = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION); 102 default_icon_ = ApplyTransforms(*src); 103 } 104} 105 106SkBitmap ExtensionIconManager::ApplyTransforms(const SkBitmap& source) { 107 SkBitmap result = source; 108 109 if (result.width() != kFaviconSize || result.height() != kFaviconSize) { 110 result = skia::ImageOperations::Resize( 111 result, skia::ImageOperations::RESIZE_LANCZOS3, 112 kFaviconSize, kFaviconSize); 113 } 114 115 if (monochrome_) { 116 color_utils::HSL shift = {-1, 0, 0.6}; 117 result = SkBitmapOperations::CreateHSLShiftedBitmap(result, shift); 118 } 119 120 if (!padding_.empty()) 121 result = ApplyPadding(result, padding_); 122 123 return result; 124} 125