Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6286)

Unified Diff: chrome/browser/themes/browser_theme_pack.cc

Issue 16977007: Only load theme images for the scale factors that use them (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/themes/browser_theme_pack.cc
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index 3a8fb68df6d7987446647d55572ff96063c37d1f..ff1c56ba77ef7f89155f439c643a4763349f0c46 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -480,6 +480,127 @@ class ThemeImageSource: public gfx::ImageSkiaSource {
DISALLOW_COPY_AND_ASSIGN(ThemeImageSource);
};
+// An ImageSkiaSouce that delays decoding PNG data into bitmaps until needed
+// and, if necessary, generates bitmaps for scale factors for which no PNG was
+// provided. The first PNG will be used to compute the DIP size and will
+// therefore be decoded when added. Once a PNG is decoded the resulting bitmap
+// is stored for later use.
+class ThemeImagePngSource : public gfx::ImageSkiaSource {
+ public:
+ ThemeImagePngSource() {}
pkotwicz 2013/06/14 18:23:05 Ideally we should not even cache the PNG data for
+
+ void AddPng(scoped_refptr<base::RefCountedMemory> png_memory,
+ ui::ScaleFactor scale_factor) {
+ png_map_[scale_factor] = png_memory;
+ if (bitmap_map_.empty())
+ init(png_memory, scale_factor);
+ }
+
+ gfx::Size size() const { return dip_size_; }
+
+ private:
+ void init(scoped_refptr<base::RefCountedMemory> png_memory,
+ ui::ScaleFactor scale_factor) {
+ SkBitmap bitmap;
+ if (!gfx::PNGCodec::Decode(png_memory->front(),
+ png_memory->size(),
+ &bitmap)) {
+ NOTREACHED();
+ return;
+ }
+ bitmap_map_[scale_factor] = bitmap;
+ dip_size_ = gfx::Size(
+ static_cast<int>(bitmap.width() /
+ ui::GetScaleFactorScale(scale_factor)),
+ static_cast<int>(bitmap.height() /
+ ui::GetScaleFactorScale(scale_factor)));
+ }
+
+ virtual gfx::ImageSkiaRep GetImageForScale(
+ ui::ScaleFactor scale_factor) OVERRIDE {
+ // Look up the scale factor in the bitmap map. If found, use the bitmap and
+ // return it.
+ BitmapMap::const_iterator exact_bitmap = bitmap_map_.find(scale_factor);
+ if (exact_bitmap != bitmap_map_.end()) {
+ return gfx::ImageSkiaRep(exact_bitmap->second, scale_factor);
+ }
+
+ // Look up the scale factor in the png map. If found, decode it,
+ // store the result in the bitmap map and return it.
+ PngMap::const_iterator exact_png = png_map_.find(scale_factor);
+ if (exact_png != png_map_.end()) {
+ SkBitmap bitmap;
+ if (!gfx::PNGCodec::Decode(exact_png->second->front(),
+ exact_png->second->size(),
+ &bitmap)) {
+ NOTREACHED();
+ return gfx::ImageSkiaRep(SkBitmap(), scale_factor);
+ }
+ bitmap_map_[scale_factor] = bitmap;
+ return gfx::ImageSkiaRep(bitmap, scale_factor);
+ }
+
+ // No exact match was found, find the scale factor with highest scale.
+ PngMap::const_iterator available_png = png_map_.end();
+ for (PngMap::const_iterator it = png_map_.begin(); it != png_map_.end();
+ ++it) {
+ if (available_png == png_map_.end() ||
+ (ui::GetScaleFactorScale(it->first) >
+ ui::GetScaleFactorScale(available_png->first))) {
+ available_png = it;
+ }
+ }
+ if (available_png == png_map_.end()) {
+ NOTREACHED();
+ return gfx::ImageSkiaRep(SkBitmap(), scale_factor);
+ }
+
+ // Look up the found scale factor in the bitmap map. If not found, decode
+ // the corresponding png and store the result in bitmap map.
+ BitmapMap::const_iterator available_bitmap =
+ bitmap_map_.find(available_png->first);
+ if (available_bitmap == bitmap_map_.end()) {
+ SkBitmap bitmap;
+ if (!gfx::PNGCodec::Decode(available_png->second->front(),
+ available_png->second->size(),
+ &bitmap)) {
+ NOTREACHED();
+ return gfx::ImageSkiaRep(SkBitmap(), scale_factor);
+ }
+ bitmap_map_[available_png->first] = bitmap;
+ available_bitmap = bitmap_map_.find(available_png->first);
+ }
+
+ // Use available bitmap to create bitmap for desired scale factor by
+ // scaling, store the result in the bitmap map and return it.
+ gfx::Size scaled_size = gfx::ToCeiledSize(
+ gfx::ScaleSize(gfx::Size(available_bitmap->second.width(),
+ available_bitmap->second.height()),
+ ui::GetScaleFactorScale(scale_factor) /
+ ui::GetScaleFactorScale(available_bitmap->first)));
+ SkBitmap scaled_bitmap;
+ scaled_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ scaled_size.width(),
+ scaled_size.height());
+ if (!scaled_bitmap.allocPixels())
+ SK_CRASH();
+ scaled_bitmap.eraseARGB(0, 0, 0, 0);
+ SkCanvas canvas(scaled_bitmap);
+ SkRect scaled_bounds = RectToSkRect(gfx::Rect(scaled_size));
+ canvas.drawBitmapRect(available_bitmap->second, NULL, scaled_bounds);
+ bitmap_map_[scale_factor] = scaled_bitmap;
+ return gfx::ImageSkiaRep(scaled_bitmap, scale_factor);
+ }
+
+ private:
+ typedef std::map<ui::ScaleFactor,
+ scoped_refptr<base::RefCountedMemory> > PngMap;
+ typedef std::map<ui::ScaleFactor, SkBitmap> BitmapMap;
+ PngMap png_map_;
+ BitmapMap bitmap_map_;
+ gfx::Size dip_size_;
+};
+
class TabBackgroundImageSource: public gfx::CanvasImageSource {
public:
TabBackgroundImageSource(const gfx::ImageSkia& image_to_tint,
@@ -749,34 +870,34 @@ gfx::Image BrowserThemePack::GetImageNamed(int idr_id) {
if (image_iter != images_on_ui_thread_.end())
return image_iter->second;
- // TODO(pkotwicz): Do something better than loading the bitmaps
- // for all the scale factors associated with |idr_id|.
- // See crbug.com/243831.
- gfx::ImageSkia source_image_skia;
- for (size_t i = 0; i < scale_factors_.size(); ++i) {
- scoped_refptr<base::RefCountedMemory> memory =
- GetRawData(idr_id, scale_factors_[i]);
- if (memory.get()) {
- // Decode the PNG.
- SkBitmap bitmap;
- if (!gfx::PNGCodec::Decode(memory->front(), memory->size(),
- &bitmap)) {
- NOTREACHED() << "Unable to decode theme image resource " << idr_id
- << " from saved DataPack.";
+ ThemeImagePngSource* png_source = NULL;
+ for (int pass = 0; pass < 2; ++pass) {
+ // Two passes: In the first pass, we process only scale factor 100%, if
+ // available, and in the second pass all other scale factors. The reason is
+ // that the first png added, determines the DIP size.
+ for (size_t i = 0; i < scale_factors_.size(); ++i) {
+ if ((pass == 0 && scale_factors_[i] != ui::SCALE_FACTOR_100P) ||
+ (pass == 1 && scale_factors_[i] == ui::SCALE_FACTOR_100P)) {
continue;
}
- source_image_skia.AddRepresentation(
- gfx::ImageSkiaRep(bitmap, scale_factors_[i]));
+ scoped_refptr<base::RefCountedMemory> memory =
+ GetRawData(idr_id, scale_factors_[i]);
+ if (memory.get()) {
+ if (!png_source)
+ png_source = new ThemeImagePngSource;
+ png_source->AddPng(memory, scale_factors_[i]);
+ }
}
}
- if (!source_image_skia.isNull()) {
- ThemeImageSource* source = new ThemeImageSource(source_image_skia);
- gfx::ImageSkia image_skia(source, source_image_skia.size());
+ if (png_source) {
+ // |image_skia| owns png_source.
+ gfx::ImageSkia image_skia(png_source, png_source->size());
gfx::Image ret = gfx::Image(image_skia);
images_on_ui_thread_[prs_id] = ret;
return ret;
}
+
return gfx::Image();
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698