diff options
Diffstat (limited to 'chrome/browser/themes/browser_theme_pack.cc')
-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, |