| // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/extensions/extension_icon_manager.h" |
| |
| #include "base/logging.h" |
| #include "base/stl_util-inl.h" |
| #include "chrome/common/extensions/extension.h" |
| #include "chrome/common/extensions/extension_icon_set.h" |
| #include "chrome/common/extensions/extension_resource.h" |
| #include "grit/theme_resources.h" |
| #include "skia/ext/image_operations.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #include "ui/gfx/canvas_skia.h" |
| #include "ui/gfx/color_utils.h" |
| #include "ui/gfx/favicon_size.h" |
| #include "ui/gfx/size.h" |
| #include "ui/gfx/skbitmap_operations.h" |
| |
| namespace { |
| |
| // Helper function to create a new bitmap with |padding| amount of empty space |
| // around the original bitmap. |
| static SkBitmap ApplyPadding(const SkBitmap& source, |
| const gfx::Insets& padding) { |
| scoped_ptr<gfx::CanvasSkia> result( |
| new gfx::CanvasSkia(source.width() + padding.width(), |
| source.height() + padding.height(), false)); |
| result->DrawBitmapInt( |
| source, |
| 0, 0, source.width(), source.height(), |
| padding.left(), padding.top(), source.width(), source.height(), |
| false); |
| return result->ExtractBitmap(); |
| } |
| |
| } // namespace |
| |
| ExtensionIconManager::ExtensionIconManager() |
| : ALLOW_THIS_IN_INITIALIZER_LIST(image_tracker_(this)), |
| monochrome_(false) { |
| } |
| |
| ExtensionIconManager::~ExtensionIconManager() { |
| } |
| |
| void ExtensionIconManager::LoadIcon(const Extension* extension) { |
| ExtensionResource icon_resource = extension->GetIconResource( |
| Extension::EXTENSION_ICON_BITTY, ExtensionIconSet::MATCH_BIGGER); |
| if (!icon_resource.extension_root().empty()) { |
| // Insert into pending_icons_ first because LoadImage can call us back |
| // synchronously if the image is already cached. |
| pending_icons_.insert(extension->id()); |
| image_tracker_.LoadImage(extension, |
| icon_resource, |
| gfx::Size(kFaviconSize, kFaviconSize), |
| ImageLoadingTracker::CACHE); |
| } |
| } |
| |
| const SkBitmap& ExtensionIconManager::GetIcon(const std::string& extension_id) { |
| const SkBitmap* result = NULL; |
| if (ContainsKey(icons_, extension_id)) { |
| result = &icons_[extension_id]; |
| } else { |
| EnsureDefaultIcon(); |
| result = &default_icon_; |
| } |
| DCHECK(result); |
| DCHECK_EQ(kFaviconSize + padding_.width(), result->width()); |
| DCHECK_EQ(kFaviconSize + padding_.height(), result->height()); |
| return *result; |
| } |
| |
| void ExtensionIconManager::RemoveIcon(const std::string& extension_id) { |
| icons_.erase(extension_id); |
| pending_icons_.erase(extension_id); |
| } |
| |
| void ExtensionIconManager::OnImageLoaded(SkBitmap* image, |
| const ExtensionResource& resource, |
| int index) { |
| if (!image) |
| return; |
| |
| const std::string extension_id = resource.extension_id(); |
| |
| // We may have removed the icon while waiting for it to load. In that case, |
| // do nothing. |
| if (!ContainsKey(pending_icons_, extension_id)) |
| return; |
| |
| pending_icons_.erase(extension_id); |
| icons_[extension_id] = ApplyTransforms(*image); |
| } |
| |
| void ExtensionIconManager::EnsureDefaultIcon() { |
| if (default_icon_.empty()) { |
| ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| SkBitmap* src = rb.GetBitmapNamed(IDR_EXTENSIONS_SECTION); |
| default_icon_ = ApplyTransforms(*src); |
| } |
| } |
| |
| SkBitmap ExtensionIconManager::ApplyTransforms(const SkBitmap& source) { |
| SkBitmap result = source; |
| |
| if (result.width() != kFaviconSize || result.height() != kFaviconSize) { |
| result = skia::ImageOperations::Resize( |
| result, skia::ImageOperations::RESIZE_LANCZOS3, |
| kFaviconSize, kFaviconSize); |
| } |
| |
| if (monochrome_) { |
| color_utils::HSL shift = {-1, 0, 0.6}; |
| result = SkBitmapOperations::CreateHSLShiftedBitmap(result, shift); |
| } |
| |
| if (!padding_.empty()) |
| result = ApplyPadding(result, padding_); |
| |
| return result; |
| } |