diff options
author | sschmitz@chromium.org <sschmitz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-21 06:07:53 +0000 |
---|---|---|
committer | sschmitz@chromium.org <sschmitz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-21 06:07:53 +0000 |
commit | 66e1628c1f57a8052cbd70faea8c45c3dad7f61c (patch) | |
tree | bde68c596d71983b649a221069f20cb4c39b813a /chrome/browser/themes | |
parent | 73834c3f661a6c071211b849c5525352e78cdc9a (diff) | |
download | chromium_src-66e1628c1f57a8052cbd70faea8c45c3dad7f61c.zip chromium_src-66e1628c1f57a8052cbd70faea8c45c3dad7f61c.tar.gz chromium_src-66e1628c1f57a8052cbd70faea8c45c3dad7f61c.tar.bz2 |
Only load theme images for the scale factors that use them
This CL implements delayed decoding of PNG data for some theme images and delayed
scaling for other scale factors until needed. Created new child of ImageSkiaSource
in BrowserThemePack for this purpose.
BUG=243831
R=pkotwicz@chromium.org
TEST=manual
out/Debug/unit_tests --gtest_filter='BrowserThemePackTest.HiDpiThemeTest'
Review URL: https://chromiumcodereview.appspot.com/16977007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207727 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/themes')
-rw-r--r-- | chrome/browser/themes/browser_theme_pack.cc | 190 |
1 files changed, 134 insertions, 56 deletions
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc index 3a8fb68..d6340cb 100644 --- a/chrome/browser/themes/browser_theme_pack.cc +++ b/chrome/browser/themes/browser_theme_pack.cc @@ -444,6 +444,30 @@ gfx::Image CreateHSLShiftedImage(const gfx::Image& image, *src_image, hsl_shift)); } +// Computes a bitmap at one scale from a bitmap at a different scale. +SkBitmap CreateLowQualityResizedBitmap(const SkBitmap& source_bitmap, + ui::ScaleFactor source_scale_factor, + ui::ScaleFactor desired_scale_factor) { + gfx::Size scaled_size = gfx::ToCeiledSize( + gfx::ScaleSize(gfx::Size(source_bitmap.width(), + source_bitmap.height()), + ui::GetScaleFactorScale(desired_scale_factor) / + ui::GetScaleFactorScale(source_scale_factor))); + 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)); + // Note(oshima): The following scaling code doesn't work with + // a mask image. + canvas.drawBitmapRect(source_bitmap, NULL, scaled_bounds); + return scaled_bitmap; +} + // A ImageSkiaSource that scales 100P image to the target scale factor // if the ImageSkiaRep for the target scale factor isn't available. class ThemeImageSource: public gfx::ImageSkiaSource { @@ -458,20 +482,11 @@ class ThemeImageSource: public gfx::ImageSkiaSource { return source_.GetRepresentation(scale_factor); const gfx::ImageSkiaRep& rep_100p = source_.GetRepresentation(ui::SCALE_FACTOR_100P); - float scale = ui::GetScaleFactorScale(scale_factor); - gfx::Size size(rep_100p.GetWidth() * scale, rep_100p.GetHeight() * scale); - SkBitmap resized_bitmap; - resized_bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), - size.height()); - if (!resized_bitmap.allocPixels()) - SK_CRASH(); - resized_bitmap.eraseARGB(0, 0, 0, 0); - SkCanvas canvas(resized_bitmap); - SkRect resized_bounds = RectToSkRect(gfx::Rect(size)); - // Note(oshima): The following scaling code doesn't work with - // a mask image. - canvas.drawBitmapRect(rep_100p.sk_bitmap(), NULL, resized_bounds); - return gfx::ImageSkiaRep(resized_bitmap, scale_factor); + SkBitmap scaled_bitmap = CreateLowQualityResizedBitmap( + rep_100p.sk_bitmap(), + ui::SCALE_FACTOR_100P, + scale_factor); + return gfx::ImageSkiaRep(scaled_bitmap, scale_factor); } private: @@ -480,6 +495,92 @@ class ThemeImageSource: public gfx::ImageSkiaSource { DISALLOW_COPY_AND_ASSIGN(ThemeImageSource); }; +// An ImageSkiaSource that delays decoding PNG data into bitmaps until +// needed. Missing data for a scale factor is computed by scaling data for an +// available scale factor. Computed bitmaps are stored for future look up. +class ThemeImagePngSource : public gfx::ImageSkiaSource { + public: + typedef std::map<ui::ScaleFactor, + scoped_refptr<base::RefCountedMemory> > PngMap; + + explicit ThemeImagePngSource(const PngMap& png_map) : png_map_(png_map) {} + + virtual ~ThemeImagePngSource() {} + + private: + virtual gfx::ImageSkiaRep GetImageForScale( + ui::ScaleFactor scale_factor) OVERRIDE { + // Look up the bitmap for |scale factor| in the bitmap map. If found + // return it. + BitmapMap::const_iterator exact_bitmap_it = bitmap_map_.find(scale_factor); + if (exact_bitmap_it != bitmap_map_.end()) + return gfx::ImageSkiaRep(exact_bitmap_it->second, scale_factor); + + // Look up the raw PNG data for |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_it = png_map_.find(scale_factor); + if (exact_png_it != png_map_.end()) { + SkBitmap bitmap; + if (!gfx::PNGCodec::Decode(exact_png_it->second->front(), + exact_png_it->second->size(), + &bitmap)) { + NOTREACHED(); + return gfx::ImageSkiaRep(); + } + bitmap_map_[scale_factor] = bitmap; + return gfx::ImageSkiaRep(bitmap, scale_factor); + } + + // Find an available PNG for another scale factor. We want to use the + // highest available scale factor. + PngMap::const_iterator available_png_it = png_map_.end(); + for (PngMap::const_iterator png_it = png_map_.begin(); + png_it != png_map_.end(); ++png_it) { + if (available_png_it == png_map_.end() || + ui::GetScaleFactorScale(png_it->first) > + ui::GetScaleFactorScale(available_png_it->first)) { + available_png_it = png_it; + } + } + if (available_png_it == png_map_.end()) + return gfx::ImageSkiaRep(); + ui::ScaleFactor available_scale_factor = available_png_it->first; + + // Look up the bitmap for |available_scale_factor| in the bitmap map. + // If not found, decode the corresponging png data, store the result + // in the bitmap map. + BitmapMap::const_iterator available_bitmap_it = + bitmap_map_.find(available_scale_factor); + if (available_bitmap_it == bitmap_map_.end()) { + SkBitmap available_bitmap; + if (!gfx::PNGCodec::Decode(available_png_it->second->front(), + available_png_it->second->size(), + &available_bitmap)) { + NOTREACHED(); + return gfx::ImageSkiaRep(); + } + bitmap_map_[available_scale_factor] = available_bitmap; + available_bitmap_it = bitmap_map_.find(available_scale_factor); + } + + // Scale the available bitmap to the desired scale factor, store the result + // in the bitmap map and return it. + SkBitmap scaled_bitmap = CreateLowQualityResizedBitmap( + available_bitmap_it->second, + available_scale_factor, + scale_factor); + bitmap_map_[scale_factor] = scaled_bitmap; + return gfx::ImageSkiaRep(scaled_bitmap, scale_factor); + } + + PngMap png_map_; + + typedef std::map<ui::ScaleFactor, SkBitmap> BitmapMap; + BitmapMap bitmap_map_; + + DISALLOW_COPY_AND_ASSIGN(ThemeImagePngSource); +}; + class TabBackgroundImageSource: public gfx::CanvasImageSource { public: TabBackgroundImageSource(const gfx::ImageSkia& image_to_tint, @@ -749,34 +850,22 @@ 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; + ThemeImagePngSource::PngMap png_map; 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."; - continue; - } - source_image_skia.AddRepresentation( - gfx::ImageSkiaRep(bitmap, scale_factors_[i])); - } + if (memory.get()) + png_map[scale_factors_[i]] = memory; } - - if (!source_image_skia.isNull()) { - ThemeImageSource* source = new ThemeImageSource(source_image_skia); - gfx::ImageSkia image_skia(source, source_image_skia.size()); + if (!png_map.empty()) { + gfx::ImageSkia image_skia(new ThemeImagePngSource(png_map), + ui::SCALE_FACTOR_100P); + // |image_skia| takes ownership of ThemeImagePngSource. gfx::Image ret = gfx::Image(image_skia); images_on_ui_thread_[prs_id] = ret; return ret; } + return gfx::Image(); } @@ -1475,29 +1564,29 @@ void BrowserThemePack::GenerateRawImageForAllSupportedScales(int prs_id) { return; // Find available scale factor with highest scale. - ui::ScaleFactor available = ui::SCALE_FACTOR_NONE; + ui::ScaleFactor available_scale_factor = ui::SCALE_FACTOR_NONE; for (size_t i = 0; i < scale_factors_.size(); ++i) { int raw_id = GetRawIDByPersistentID(prs_id, scale_factors_[i]); - if ((available == ui::SCALE_FACTOR_NONE || + if ((available_scale_factor == ui::SCALE_FACTOR_NONE || (ui::GetScaleFactorScale(scale_factors_[i]) > - ui::GetScaleFactorScale(available))) && + ui::GetScaleFactorScale(available_scale_factor))) && image_memory_.find(raw_id) != image_memory_.end()) { - available = scale_factors_[i]; + available_scale_factor = scale_factors_[i]; } } // If no scale factor is available, we're done. - if (available == ui::SCALE_FACTOR_NONE) + if (available_scale_factor == ui::SCALE_FACTOR_NONE) return; // Get bitmap for the available scale factor. - int available_raw_id = GetRawIDByPersistentID(prs_id, available); + int available_raw_id = GetRawIDByPersistentID(prs_id, available_scale_factor); RawImages::const_iterator it = image_memory_.find(available_raw_id); SkBitmap available_bitmap; if (!gfx::PNGCodec::Decode(it->second->front(), it->second->size(), &available_bitmap)) { NOTREACHED() << "Unable to decode theme image for prs_id=" - << prs_id << " for scale_factor=" << available; + << prs_id << " for scale_factor=" << available_scale_factor; return; } @@ -1506,21 +1595,10 @@ void BrowserThemePack::GenerateRawImageForAllSupportedScales(int prs_id) { int scaled_raw_id = GetRawIDByPersistentID(prs_id, scale_factors_[i]); if (image_memory_.find(scaled_raw_id) != image_memory_.end()) continue; - gfx::Size scaled_size = gfx::ToCeiledSize( - gfx::ScaleSize(gfx::Size(available_bitmap.width(), - available_bitmap.height()), - ui::GetScaleFactorScale(scale_factors_[i]) / - ui::GetScaleFactorScale(available))); - 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, NULL, scaled_bounds); + SkBitmap scaled_bitmap = + CreateLowQualityResizedBitmap(available_bitmap, + available_scale_factor, + scale_factors_[i]); std::vector<unsigned char> bitmap_data; if (!gfx::PNGCodec::EncodeBGRASkBitmap(scaled_bitmap, false, |