This source file includes following definitions.
- GetExtensionIconResource
- Draw
- blank_image_
- ResetHost
- GetImageForScale
- weak_ptr_factory_
- LoadImageForScaleFactor
- OnImageLoaded
- Observe
#include "chrome/browser/extensions/extension_icon_image.h"
#include <vector>
#include "base/bind.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/image_loader.h"
#include "content/public/browser/notification_service.h"
#include "extensions/common/extension.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/canvas_image_source.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/image/image_skia_source.h"
#include "ui/gfx/size.h"
#include "ui/gfx/size_conversions.h"
namespace {
const int kMatchBiggerTreshold = 32;
extensions::ExtensionResource GetExtensionIconResource(
const extensions::Extension* extension,
const ExtensionIconSet& icons,
int size,
ExtensionIconSet::MatchType match_type) {
std::string path = icons.Get(size, match_type);
if (path.empty())
return extensions::ExtensionResource();
return extension->GetResource(path);
}
class BlankImageSource : public gfx::CanvasImageSource {
public:
explicit BlankImageSource(const gfx::Size& size_in_dip)
: CanvasImageSource(size_in_dip, false) {
}
virtual ~BlankImageSource() {}
private:
virtual void Draw(gfx::Canvas* canvas) OVERRIDE {
canvas->DrawColor(SkColorSetARGB(0, 0, 0, 0));
}
DISALLOW_COPY_AND_ASSIGN(BlankImageSource);
};
}
namespace extensions {
class IconImage::Source : public gfx::ImageSkiaSource {
public:
Source(IconImage* host, const gfx::Size& size_in_dip);
virtual ~Source();
void ResetHost();
private:
virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE;
IconImage* host_;
gfx::ImageSkia blank_image_;
DISALLOW_COPY_AND_ASSIGN(Source);
};
IconImage::Source::Source(IconImage* host, const gfx::Size& size_in_dip)
: host_(host),
blank_image_(new BlankImageSource(size_in_dip), size_in_dip) {
}
IconImage::Source::~Source() {
}
void IconImage::Source::ResetHost() {
host_ = NULL;
}
gfx::ImageSkiaRep IconImage::Source::GetImageForScale(float scale) {
gfx::ImageSkiaRep representation;
if (host_) {
representation =
host_->LoadImageForScaleFactor(ui::GetSupportedScaleFactor(scale));
}
if (!representation.is_null())
return representation;
return blank_image_.GetRepresentation(scale);
}
IconImage::IconImage(
content::BrowserContext* context,
const Extension* extension,
const ExtensionIconSet& icon_set,
int resource_size_in_dip,
const gfx::ImageSkia& default_icon,
Observer* observer)
: browser_context_(context),
extension_(extension),
icon_set_(icon_set),
resource_size_in_dip_(resource_size_in_dip),
observer_(observer),
source_(NULL),
default_icon_(gfx::ImageSkiaOperations::CreateResizedImage(
default_icon,
skia::ImageOperations::RESIZE_BEST,
gfx::Size(resource_size_in_dip, resource_size_in_dip))),
weak_ptr_factory_(this) {
gfx::Size resource_size(resource_size_in_dip, resource_size_in_dip);
source_ = new Source(this, resource_size);
image_skia_ = gfx::ImageSkia(source_, resource_size);
registrar_.Add(this,
chrome::NOTIFICATION_EXTENSION_REMOVED,
content::NotificationService::AllSources());
}
IconImage::~IconImage() {
source_->ResetHost();
}
gfx::ImageSkiaRep IconImage::LoadImageForScaleFactor(
ui::ScaleFactor scale_factor) {
if (!extension_)
return gfx::ImageSkiaRep();
const float scale = ui::GetImageScale(scale_factor);
const int resource_size_in_pixel =
static_cast<int>(resource_size_in_dip_ * scale);
extensions::ExtensionResource resource;
if (resource_size_in_pixel >= kMatchBiggerTreshold) {
resource = GetExtensionIconResource(extension_, icon_set_,
resource_size_in_pixel, ExtensionIconSet::MATCH_BIGGER);
}
if (resource.empty()) {
resource = GetExtensionIconResource(extension_, icon_set_,
resource_size_in_pixel, ExtensionIconSet::MATCH_SMALLER);
}
if (resource.empty())
return default_icon_.GetRepresentation(scale);
std::vector<ImageLoader::ImageRepresentation> info_list;
info_list.push_back(ImageLoader::ImageRepresentation(
resource,
ImageLoader::ImageRepresentation::ALWAYS_RESIZE,
gfx::ToFlooredSize(gfx::ScaleSize(
gfx::Size(resource_size_in_dip_, resource_size_in_dip_), scale)),
scale_factor));
extensions::ImageLoader* loader =
extensions::ImageLoader::Get(browser_context_);
loader->LoadImagesAsync(extension_, info_list,
base::Bind(&IconImage::OnImageLoaded,
weak_ptr_factory_.GetWeakPtr(),
scale));
return gfx::ImageSkiaRep();
}
void IconImage::OnImageLoaded(float scale, const gfx::Image& image_in) {
const gfx::ImageSkia* image =
image_in.IsEmpty() ? &default_icon_ : image_in.ToImageSkia();
if (image->isNull())
return;
gfx::ImageSkiaRep rep = image->GetRepresentation(scale);
DCHECK(!rep.is_null());
DCHECK_EQ(scale, rep.scale());
image_skia_.RemoveRepresentation(scale);
image_skia_.AddRepresentation(rep);
if (observer_)
observer_->OnExtensionIconImageChanged(this);
}
void IconImage::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK_EQ(type, chrome::NOTIFICATION_EXTENSION_REMOVED);
const Extension* extension = content::Details<const Extension>(details).ptr();
if (extension_ == extension)
extension_ = NULL;
}
}