Index: chrome/browser/extensions/image_loading_tracker.cc |
diff --git a/chrome/browser/extensions/image_loading_tracker.cc b/chrome/browser/extensions/image_loading_tracker.cc |
index ea84c34fe5dc55d490b8af4ea2a5971c38ecc3e1..9033142db57f05bf01ca5e277d5f2198567584b2 100644 |
--- a/chrome/browser/extensions/image_loading_tracker.cc |
+++ b/chrome/browser/extensions/image_loading_tracker.cc |
@@ -21,8 +21,9 @@ |
#include "skia/ext/image_operations.h" |
#include "third_party/skia/include/core/SkBitmap.h" |
#include "ui/gfx/image/image.h" |
-#include "ui/gfx/image/image_skia.h" |
#include "ui/gfx/image/image_skia_rep.h" |
+#include "ui/gfx/image/image_skia_source.h" |
+#include "ui/gfx/screen.h" |
#include "webkit/glue/image_decoder.h" |
using content::BrowserThread; |
@@ -37,8 +38,12 @@ ImageLoadingTracker::Observer::~Observer() {} |
// ImageLoadingTracker::ImageInfo |
ImageLoadingTracker::ImageInfo::ImageInfo( |
- const ExtensionResource& resource, gfx::Size max_size) |
- : resource(resource), max_size(max_size) { |
+ const ExtensionResource& resource, |
+ const gfx::Size& max_size, |
+ ui::ScaleFactor scale_factor) |
+ : resource(resource), |
+ max_size(max_size), |
+ scale_factor(scale_factor) { |
} |
ImageLoadingTracker::ImageInfo::~ImageInfo() { |
@@ -49,6 +54,9 @@ ImageLoadingTracker::ImageInfo::~ImageInfo() { |
ImageLoadingTracker::PendingLoadInfo::PendingLoadInfo() |
: extension(NULL), |
+ resource_size_in_dip(ExtensionIconSet::EXTENSION_ICON_INVALID), |
+ resource_match_type(ExtensionIconSet::MATCH_BIGGER), |
+ image_source(NULL), |
cache(CACHE), |
pending_count(0) { |
} |
@@ -76,26 +84,21 @@ class ImageLoadingTracker::ImageLoader |
} |
// Instructs the loader to load a task on the File thread. |
- void LoadImage(const ExtensionResource& resource, |
- const gfx::Size& max_size, |
- int id) { |
+ void LoadImage(const ImageInfo& image_info, int id) { |
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
BrowserThread::PostTask( |
BrowserThread::FILE, FROM_HERE, |
oshima
2012/07/16 17:22:33
this is not the scope of this change, but at some
xiyuan
2012/07/16 20:11:27
Agree. But I'd prefer to do it in a follow up CL s
|
- base::Bind(&ImageLoader::LoadOnFileThread, this, resource, |
- max_size, id)); |
+ base::Bind(&ImageLoader::LoadOnFileThread, this, image_info, id)); |
} |
- void LoadOnFileThread(const ExtensionResource& resource, |
- const gfx::Size& max_size, |
- int id) { |
+ void LoadOnFileThread(const ImageInfo& image_info, int id) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
// Read the file from disk. |
std::string file_contents; |
- FilePath path = resource.GetFilePath(); |
+ FilePath path = image_info.resource.GetFilePath(); |
if (path.empty() || !file_util::ReadFileToString(path, &file_contents)) { |
- ReportBack(NULL, resource, gfx::Size(), id); |
+ ReportBack(NULL, image_info, gfx::Size(), id); |
return; |
} |
@@ -112,61 +115,57 @@ class ImageLoadingTracker::ImageLoader |
// Chrome is therefore decoding images here that were generated by Chrome. |
*decoded = decoder.Decode(data, file_contents.length()); |
if (decoded->empty()) { |
- ReportBack(NULL, resource, gfx::Size(), id); |
+ ReportBack(NULL, image_info, gfx::Size(), id); |
return; // Unable to decode. |
} |
gfx::Size original_size(decoded->width(), decoded->height()); |
- if (decoded->width() > max_size.width() || |
- decoded->height() > max_size.height()) { |
+ if (decoded->width() > image_info.max_size.width() || |
+ decoded->height() > image_info.max_size.height()) { |
// The bitmap is too big, re-sample. |
*decoded = skia::ImageOperations::Resize( |
*decoded, skia::ImageOperations::RESIZE_LANCZOS3, |
- max_size.width(), max_size.height()); |
+ image_info.max_size.width(), image_info.max_size.height()); |
} |
- ReportBack(decoded.release(), resource, original_size, id); |
+ ReportBack(decoded.release(), image_info, original_size, id); |
} |
// Instructs the loader to load a resource on the File thread. |
- void LoadResource(const ExtensionResource& resource, |
- const gfx::Size& max_size, |
- int id, |
- int resource_id) { |
+ void LoadResource(const ImageInfo& image_info, int id, int resource_id) { |
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
BrowserThread::PostTask( |
BrowserThread::FILE, FROM_HERE, |
- base::Bind(&ImageLoader::LoadResourceOnFileThread, this, resource, |
- max_size, id, resource_id)); |
+ base::Bind(&ImageLoader::LoadResourceOnFileThread, this, image_info, |
+ id, resource_id)); |
} |
- void LoadResourceOnFileThread(const ExtensionResource& resource, |
- const gfx::Size& max_size, |
+ void LoadResourceOnFileThread(const ImageInfo& image_info, |
int id, |
int resource_id) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
SkBitmap* image = ExtensionIconSource::LoadImageByResourceId( |
resource_id); |
- ReportBack(image, resource, max_size, id); |
+ ReportBack(image, image_info, image_info.max_size, id); |
} |
- void ReportBack(SkBitmap* image, const ExtensionResource& resource, |
+ void ReportBack(SkBitmap* image, const ImageInfo& image_info, |
const gfx::Size& original_size, int id) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
BrowserThread::PostTask( |
callback_thread_id_, FROM_HERE, |
base::Bind(&ImageLoader::ReportOnUIThread, this, |
- image, resource, original_size, id)); |
+ image, image_info, original_size, id)); |
} |
- void ReportOnUIThread(SkBitmap* image, const ExtensionResource& resource, |
+ void ReportOnUIThread(SkBitmap* image, const ImageInfo& image_info, |
const gfx::Size& original_size, int id) { |
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
if (tracker_) |
- tracker_->OnImageLoaded(image, resource, original_size, id, true); |
+ tracker_->OnImageLoaded(image, image_info, original_size, id, true); |
delete image; |
} |
@@ -186,6 +185,53 @@ class ImageLoadingTracker::ImageLoader |
}; |
//////////////////////////////////////////////////////////////////////////////// |
+// ImageLoadingTracker::ImageSource |
+ |
+// An ImageSkiaSource to load image for additional scale factor. |
pkotwicz
2012/07/16 17:33:52
Nit: factors
xiyuan
2012/07/16 20:11:27
Done.
|
+class ImageLoadingTracker::ImageSource : public gfx::ImageSkiaSource { |
+ public: |
+ ImageSource(ImageLoadingTracker* tracker, int id); |
+ virtual ~ImageSource(); |
+ |
+ void StopTracking(); |
+ |
+ // gfx::ImageSkiaSource overrides: |
+ virtual gfx::ImageSkiaRep GetImageForScale( |
+ ui::ScaleFactor scale_factor) OVERRIDE; |
+ |
+ private: |
+ ImageLoadingTracker* tracker_; |
+ int id_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ImageSource); |
+}; |
+ |
+ImageLoadingTracker::ImageSource::ImageSource(ImageLoadingTracker* tracker, |
+ int id) |
+ : tracker_(tracker), |
+ id_(id) { |
+} |
+ |
+ImageLoadingTracker::ImageSource::~ImageSource() { |
+} |
+ |
+void ImageLoadingTracker::ImageSource::StopTracking() { |
+ tracker_ = NULL; |
+} |
+ |
+gfx::ImageSkiaRep ImageLoadingTracker::ImageSource::GetImageForScale( |
+ ui::ScaleFactor scale_factor) { |
+ // Asks tracker to load new images for |scale_factor|. |
+ if (tracker_) |
+ tracker_->LoadImageForScaleFactor(id_, scale_factor); |
+ |
+ // Returns an empty representation for |scale_factor| here. If |tracker_| is |
+ // valid, it loads image asynchronously. When loading is done, it updates |
+ // existing ImageSkia and notifies its observer. |
+ return gfx::ImageSkiaRep(); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
// ImageLoadingTracker |
ImageLoadingTracker::ImageLoadingTracker(Observer* observer) |
@@ -200,6 +246,11 @@ ImageLoadingTracker::~ImageLoadingTracker() { |
// any valid image load tasks have been posted. |
if (loader_) |
loader_->StopTracking(); |
+ |
+ for (LoadMap::iterator it = load_map_.begin(); it != load_map_.end(); ++it) { |
+ if (it->second.image_source) |
+ it->second.image_source->StopTracking(); |
+ } |
} |
void ImageLoadingTracker::LoadImage(const Extension* extension, |
@@ -207,43 +258,102 @@ void ImageLoadingTracker::LoadImage(const Extension* extension, |
const gfx::Size& max_size, |
CacheParam cache) { |
std::vector<ImageInfo> info_list; |
- info_list.push_back(ImageInfo(resource, max_size)); |
+ info_list.push_back(ImageInfo(resource, max_size, ui::SCALE_FACTOR_NONE)); |
pkotwicz
2012/07/16 17:33:52
Just use SCALE_FACTOR_100P. (SCALE_FACTOR_NONE is
xiyuan
2012/07/16 20:11:27
Done.
|
LoadImages(extension, info_list, cache); |
} |
+void ImageLoadingTracker::LoadImageInDIP( |
+ const Extension* extension, |
+ int resource_size, |
+ ExtensionIconSet::MatchType resource_match_type, |
+ const gfx::Size& max_size, |
+ CacheParam cache) { |
+ typedef std::vector<ui::ScaleFactor> ScaleFactors; |
+ |
+ // TODO(xiyuan): Update the following. |
+ // gfx::Screen::GetScaleFactorsInUse is in peter's pending CL. |
+ // const ScaleFactors scale_factors_in_use = |
+ // gfx::Screen::GetScaleFactorsInUse(); |
oshima
2012/07/16 17:22:33
I thought we're going to load the correct image fo
xiyuan
2012/07/16 20:11:27
You are correct. The code is in comment because ht
|
+ ScaleFactors scale_factors_in_use; |
+ if (gfx::Screen::IsDIPEnabled()) |
+ scale_factors_in_use.push_back(ui::SCALE_FACTOR_200P); |
+ else |
+ scale_factors_in_use.push_back(ui::SCALE_FACTOR_100P); |
+ |
+ std::vector<ImageInfo> info_list; |
+ for (ScaleFactors::const_iterator it = scale_factors_in_use.begin(); |
+ it != scale_factors_in_use.end(); ++it) { |
+ const float scale = ui::GetScaleFactorScale(*it); |
+ |
+ ExtensionResource resource = extension->GetIconResource( |
+ static_cast<int>(resource_size * scale), |
+ resource_match_type); |
+ |
+ info_list.push_back(ImageInfo(resource, max_size.Scale(scale), *it)); |
+ } |
+ |
+ PendingLoadInfo load_info; |
+ load_info.extension = extension; |
+ load_info.extension_id = extension->id(); |
+ load_info.cache = cache; |
+ |
+ load_info.resource_size_in_dip = resource_size; |
+ load_info.resource_match_type = resource_match_type; |
+ load_info.max_size_in_dip = max_size; |
+ |
+ int id = next_id_++; |
+ load_info.image_source = new ImageSource(this, id); |
+ load_info.images = gfx::ImageSkia(load_info.image_source, |
+ load_info.max_size_in_dip); |
pkotwicz
2012/07/16 17:33:52
The loaded bitmap is not always resized to max_siz
xiyuan
2012/07/16 20:11:27
Done.
|
+ |
+ load_map_[id] = load_info; |
+ |
+ DoLoadImages(id, info_list); |
pkotwicz
2012/07/16 17:33:52
Call this DoLoadImage. You are still loading a sin
xiyuan
2012/07/16 20:11:27
Done.
|
+} |
+ |
void ImageLoadingTracker::LoadImages(const Extension* extension, |
const std::vector<ImageInfo>& info_list, |
CacheParam cache) { |
PendingLoadInfo load_info; |
load_info.extension = extension; |
- load_info.cache = cache; |
load_info.extension_id = extension->id(); |
- load_info.pending_count = info_list.size(); |
+ load_info.cache = cache; |
+ |
int id = next_id_++; |
load_map_[id] = load_info; |
+ DoLoadImages(id, info_list); |
+} |
+ |
+void ImageLoadingTracker::DoLoadImages( |
+ int id, |
+ const std::vector<ImageInfo>& info_list) { |
+ LoadMap::iterator load_map_it = load_map_.find(id); |
+ DCHECK(load_map_it != load_map_.end()); |
+ |
+ PendingLoadInfo* load_info = &load_map_it->second; |
+ load_info->pending_count = info_list.size(); |
+ const extensions::Extension* extension = load_info->extension; |
+ |
for (std::vector<ImageInfo>::const_iterator it = info_list.begin(); |
it != info_list.end(); ++it) { |
// Load resources for special component extensions. |
- if (load_info.extension_id == extension_misc::kWebStoreAppId) { |
+ if (load_info->extension_id == extension_misc::kWebStoreAppId) { |
if (!loader_) |
loader_ = new ImageLoader(this); |
- loader_->LoadResource(it->resource, it->max_size, id, IDR_WEBSTORE_ICON); |
+ loader_->LoadResource(*it, id, IDR_WEBSTORE_ICON); |
continue; |
- } else if (load_info.extension_id == extension_misc::kChromeAppId) { |
+ } else if (load_info->extension_id == extension_misc::kChromeAppId) { |
if (!loader_) |
loader_ = new ImageLoader(this); |
- loader_->LoadResource(it->resource, |
- it->max_size, |
- id, |
- IDR_PRODUCT_LOGO_128); |
+ loader_->LoadResource(*it, id, IDR_PRODUCT_LOGO_128); |
continue; |
} |
// If we don't have a path we don't need to do any further work, just |
// respond back. |
if (it->resource.relative_path().empty()) { |
- OnImageLoaded(NULL, it->resource, it->max_size, id, false); |
+ OnImageLoaded(NULL, *it, it->max_size, id, false); |
continue; |
} |
@@ -252,7 +362,7 @@ void ImageLoadingTracker::LoadImages(const Extension* extension, |
// See if the extension has the image already. |
if (extension->HasCachedImage(it->resource, it->max_size)) { |
SkBitmap image = extension->GetCachedImage(it->resource, it->max_size); |
- OnImageLoaded(&image, it->resource, it->max_size, id, false); |
+ OnImageLoaded(&image, *it, it->max_size, id, false); |
pkotwicz
2012/07/16 17:33:52
Rename image->bitmap.
Can you add a TODO to suppor
xiyuan
2012/07/16 20:11:27
Rename done.
Caching is supported on the bitmap/i
|
continue; |
} |
@@ -263,12 +373,38 @@ void ImageLoadingTracker::LoadImages(const Extension* extension, |
int resource_id; |
if (IsComponentExtensionResource(extension, it->resource, resource_id)) |
- loader_->LoadResource(it->resource, it->max_size, id, resource_id); |
+ loader_->LoadResource(*it, id, resource_id); |
else |
- loader_->LoadImage(it->resource, it->max_size, id); |
+ loader_->LoadImage(*it, id); |
} |
} |
+void ImageLoadingTracker::LoadImageForScaleFactor( |
+ int id, |
+ ui::ScaleFactor scale_factor) { |
+ LoadMap::iterator load_map_it = load_map_.find(id); |
+ DCHECK(load_map_it != load_map_.end()); |
+ PendingLoadInfo* load_info = &load_map_it->second; |
+ |
+ // Do nothing if extension is unloaded. |
+ if (load_info->extension == NULL) |
+ return; |
pkotwicz
2012/07/16 17:33:52
You need to check here if |load_info->pending_coun
xiyuan
2012/07/16 20:11:27
Good catch. Think we should allow LoadImageForScal
|
+ |
+ const float scale = ui::GetScaleFactorScale(scale_factor); |
+ const int resource_size_in_pixel = |
+ static_cast<int>(load_info->resource_size_in_dip * scale); |
+ |
+ ExtensionResource resource = load_info->extension->GetIconResource( |
+ resource_size_in_pixel, |
+ load_info->resource_match_type); |
+ |
+ std::vector<ImageInfo> info_list; |
+ info_list.push_back(ImageInfo(resource, |
+ load_info->max_size_in_dip.Scale(scale), |
+ scale_factor)); |
+ DoLoadImages(id, info_list); |
+} |
+ |
bool ImageLoadingTracker::IsComponentExtensionResource( |
const Extension* extension, |
const ExtensionResource& resource, |
@@ -295,7 +431,7 @@ bool ImageLoadingTracker::IsComponentExtensionResource( |
void ImageLoadingTracker::OnImageLoaded( |
SkBitmap* image, |
- const ExtensionResource& resource, |
+ const ImageInfo& image_info, |
const gfx::Size& original_size, |
int id, |
bool should_cache) { |
@@ -306,34 +442,27 @@ void ImageLoadingTracker::OnImageLoaded( |
// Save the pending results. |
DCHECK(info->pending_count > 0); |
info->pending_count--; |
- if (image) |
- info->bitmaps.push_back(*image); |
+ if (image) { |
oshima
2012/07/16 17:22:33
DCHECK(!images.HasRepresentation(image_info.scale_
xiyuan
2012/07/16 20:11:28
This DCHECK actually would fail because ImageLoadi
|
+ info->images.AddRepresentation(gfx::ImageSkiaRep(*image, |
+ image_info.scale_factor)); |
+ } |
// Add to the extension's image cache if requested. |
DCHECK(info->cache != CACHE || info->extension); |
if (should_cache && info->cache == CACHE && |
- !info->extension->HasCachedImage(resource, original_size)) { |
- info->extension->SetCachedImage(resource, image ? *image : SkBitmap(), |
+ !info->extension->HasCachedImage(image_info.resource, original_size)) { |
+ info->extension->SetCachedImage(image_info.resource, |
+ image ? *image : SkBitmap(), |
pkotwicz
2012/07/16 17:33:52
Rename image->bitmap
xiyuan
2012/07/16 20:11:28
Done.
|
original_size); |
} |
// If all pending images are done then report back. |
if (info->pending_count == 0) { |
- gfx::Image image; |
+ gfx::Image image(info->images); |
std::string extension_id = info->extension_id; |
- if (info->bitmaps.size() > 0) { |
- gfx::ImageSkia image_skia; |
- for (std::vector<SkBitmap>::const_iterator it = info->bitmaps.begin(); |
- it != info->bitmaps.end(); ++it) { |
- // TODO(pkotwicz): Do something better but ONLY when DIP is enabled. |
- image_skia.AddRepresentation( |
- gfx::ImageSkiaRep(*it, ui::SCALE_FACTOR_100P)); |
- } |
- image = gfx::Image(image_skia); |
- } |
- |
- load_map_.erase(load_map_it); |
+ if (info->image_source == NULL) |
+ load_map_.erase(load_map_it); |
// ImageLoadingTracker might be deleted after the callback so don't |
// anything after this statement. |