Chromium Code Reviews| Index: ui/base/resource/resource_bundle.cc |
| diff --git a/ui/base/resource/resource_bundle.cc b/ui/base/resource/resource_bundle.cc |
| index 294b48a12db25990c3997700c179d9c1ec0d731f..28cb50e20325ea0de7a1a3ac1e8e68a48cec7c1f 100644 |
| --- a/ui/base/resource/resource_bundle.cc |
| +++ b/ui/base/resource/resource_bundle.cc |
| @@ -28,6 +28,7 @@ |
| #include "ui/gfx/codec/png_codec.h" |
| #include "ui/gfx/image/image_skia.h" |
| #include "ui/gfx/image/image_skia_source.h" |
| +#include "ui/gfx/safe_floor_ceil.h" |
| #include "ui/gfx/screen.h" |
| #include "ui/gfx/size_conversions.h" |
| #include "ui/gfx/skbitmap_operations.h" |
| @@ -50,88 +51,66 @@ bool ShouldHighlightMissingScaledResources() { |
| } // namespace |
| -// An ImageSkiaSource that loads bitmaps for requested scale factor from |
| -// ResourceBundle on demand for given resource_id. It falls back |
| -// to the 1x bitmap if the bitmap for the requested scale factor does not |
| -// exist. If the resource for the requested scale factor is not exactly |
| -// |scale_factor| * the size of the 1x resource, it will end up with |
| -// broken UI because it will be drawn as if the bitmap was the correct size. |
| -// When --highlight-missing-scaled-resources flag is specified, it |
| -// will show the scaled image blended with red instead. |
| +// An ImageSkiaSource that loads bitmaps for the requested scale factor from |
| +// ResourceBundle on demand for a given |resource_id|. If the bitmap for the |
| +// requested scale factor does not exist, it will return the 1x bitmap scaled |
| +// by the scale factor. This may lead to broken UI if the correct size of the |
| +// scaled image is not exactly |scale_factor| * the size of the 1x resource. |
| +// When --highlight-missing-scaled-resources flag is specified, scaled 1x images |
| +// are higlighted by blending them with red. |
| class ResourceBundle::ResourceBundleImageSource : public gfx::ImageSkiaSource { |
| public: |
| - ResourceBundleImageSource(ResourceBundle* rb, |
| - int resource_id, |
| - const gfx::Size& size_in_dip) |
| - : rb_(rb), |
| - resource_id_(resource_id), |
| - size_in_dip_(size_in_dip) { |
| - } |
| + ResourceBundleImageSource(ResourceBundle* rb, int resource_id) |
| + : rb_(rb), resource_id_(resource_id) {} |
| virtual ~ResourceBundleImageSource() {} |
| // gfx::ImageSkiaSource overrides: |
| virtual gfx::ImageSkiaRep GetImageForScale( |
| ui::ScaleFactor scale_factor) OVERRIDE { |
| - scoped_ptr<SkBitmap> result(rb_->LoadBitmap(resource_id_, scale_factor)); |
| - float scale = ui::GetScaleFactorScale(scale_factor); |
| - gfx::Size size_in_pixel = gfx::ToFlooredSize(size_in_dip_.Scale(scale)); |
| - |
| - if (scale_factor != SCALE_FACTOR_100P && |
| - (!result.get() || |
| - result->width() != size_in_pixel.width() || |
| - result->height() != size_in_pixel.height())) { |
| - |
| - // If non 1x resource is missing from |image| or is the incorrect |
| - // size and --highlight-missing-scaled-resources is specified, logs |
| - // the resource id and creates a version of the resource at the correct |
| - // size. Blends the created resource with red to make it |
| - // distinguishable from bitmaps in the resource pak. |
| + SkBitmap image; |
| + bool fell_back_to_1x = false; |
| + bool found = rb_->LoadBitmap(resource_id_, scale_factor, |
| + &image, &fell_back_to_1x); |
| + |
| + if (!found) { |
| + // Some images (e.g. wallpapers) exist only at 100%. Return the unscaled |
| + // image with the correct scale factor. |
| + if (scale_factor != SCALE_FACTOR_100P) |
| + found = rb_->LoadBitmap(resource_id_, SCALE_FACTOR_100P, &image, NULL); |
| + if (!found) |
|
oshima
2012/10/11 01:31:54
and you should be able to return just ImageSkiaRep
benrg
2012/10/15 21:58:54
Done.
|
| + return gfx::ImageSkiaRep(); |
| + return gfx::ImageSkiaRep(image, SCALE_FACTOR_100P); |
| + } |
| + |
| + if (fell_back_to_1x) { |
| + // GRIT fell back to the 100% image, so rescale it to the correct size. |
| + float scale = GetScaleFactorScale(scale_factor); |
| + image = skia::ImageOperations::Resize( |
| + image, |
| + skia::ImageOperations::RESIZE_LANCZOS3, |
| + gfx::ToFlooredInt(image.width() * scale), |
| + gfx::ToFlooredInt(image.height() * scale)); |
| + // If --highlight-missing-scaled-resources is specified, log the resource |
| + // id and blend the created resource with red. |
| if (ShouldHighlightMissingScaledResources()) { |
| - if (!result.get()) { |
| - LOG(ERROR) << "Missing " << scale << "x resource. id=" |
| - << resource_id_; |
| - } else { |
| - LOG(ERROR) << "Incorrectly sized " << scale << "x resource. id=" |
| - << resource_id_; |
| - } |
| - |
| - scoped_ptr<SkBitmap> bitmap1x( |
| - rb_->LoadBitmap(resource_id_, SCALE_FACTOR_100P)); |
| - DCHECK(bitmap1x.get()); |
| - SkBitmap bitmap_scaled = skia::ImageOperations::Resize( |
| - *bitmap1x, |
| - skia::ImageOperations::RESIZE_LANCZOS3, |
| - size_in_pixel.width(), |
| - size_in_pixel.height()); |
| + LOG(ERROR) << "Missing " << scale << "x scaled resource. id=" |
| + << resource_id_; |
| SkBitmap mask; |
| mask.setConfig(SkBitmap::kARGB_8888_Config, |
| - bitmap_scaled.width(), |
| - bitmap_scaled.height()); |
| + image.width(), image.height()); |
| mask.allocPixels(); |
| mask.eraseColor(SK_ColorRED); |
| - result.reset(new SkBitmap()); |
| - *result.get() = SkBitmapOperations::CreateBlendedBitmap( |
| - bitmap_scaled, mask, 0.2); |
| - } else if (!result.get() || result->width() == size_in_dip_.width()) { |
| - // The scaled resource pack may have the 1x image if its grd file |
| - // points to 1x image. Fallback to 1x by returning empty image |
| - // in this case. This 1x image will be scaled when drawn. |
| - return gfx::ImageSkiaRep(); |
| + image = SkBitmapOperations::CreateBlendedBitmap(image, mask, 0.2); |
| } |
| - // If the size of scaled image isn't exactly |scale| * 1x version, |
| - // create ImageSkia as usual. This will end up with |
| - // corrupted visual representation as the size of image doesn't |
| - // match the expected size. |
| } |
| - DCHECK(result.get()); |
| - return gfx::ImageSkiaRep(*result.get(), scale_factor); |
| + |
| + return gfx::ImageSkiaRep(image, scale_factor); |
| } |
| private: |
| ResourceBundle* rb_; |
| const int resource_id_; |
| - const gfx::Size size_in_dip_; |
| DISALLOW_COPY_AND_ASSIGN(ResourceBundleImageSource); |
| }; |
| @@ -340,24 +319,20 @@ gfx::Image& ResourceBundle::GetImageNamed(int resource_id) { |
| DCHECK(!delegate_ && !data_packs_.empty()) << |
| "Missing call to SetResourcesDataDLL?"; |
| - // TODO(oshima): Pick the scale factor from currently used scale factors. |
| - scoped_ptr<SkBitmap> bitmap(LoadBitmap(resource_id, SCALE_FACTOR_100P)); |
| - if (!bitmap.get()) { |
| + // TODO(oshima): This should be GetPrimaryDisplay().device_scale_factor(), |
| + // but GetPrimaryDisplay() crashes at startup. |
| + ScaleFactor primary_scale_factor = SCALE_FACTOR_100P; |
| + // ResourceBundle::GetSharedInstance() is destroyed after the |
| + // BrowserMainLoop has finished running. |image_skia| is guaranteed to be |
| + // destroyed before the resource bundle is destroyed. |
| + gfx::ImageSkia image_skia(new ResourceBundleImageSource(this, resource_id), |
| + primary_scale_factor); |
| + if (image_skia.isNull()) { |
| LOG(WARNING) << "Unable to load image with id " << resource_id; |
| NOTREACHED(); // Want to assert in debug mode. |
| // The load failed to retrieve the image; show a debugging red square. |
| return GetEmptyImage(); |
| } |
| - |
| - // ResourceBundle::GetSharedInstance() is destroyed after the |
| - // BrowserMainLoop has finished running. |image_skia| is guaranteed to be |
| - // destroyed before the resource bundle is destroyed. |
| - gfx::Size size_in_dip(bitmap->width(), bitmap->height()); |
| - gfx::ImageSkia image_skia( |
| - new ResourceBundleImageSource(this, resource_id, size_in_dip), |
| - size_in_dip); |
| - image_skia.AddRepresentation(gfx::ImageSkiaRep(*bitmap.get(), |
| - SCALE_FACTOR_100P)); |
| image_skia.SetReadOnly(); |
| image = gfx::Image(image_skia); |
| } |
| @@ -585,40 +560,46 @@ void ResourceBundle::LoadFontsIfNecessary() { |
| } |
| } |
| -SkBitmap* ResourceBundle::LoadBitmap(const ResourceHandle& data_handle, |
| - int resource_id) const { |
| +bool ResourceBundle::LoadBitmap(const ResourceHandle& data_handle, |
| + int resource_id, |
| + SkBitmap* bitmap, |
| + bool* fell_back_to_1x) const { |
| scoped_refptr<base::RefCountedMemory> memory( |
| data_handle.GetStaticMemory(resource_id)); |
| if (!memory) |
| - return NULL; |
| + return false; |
| - SkBitmap bitmap; |
| - if (gfx::PNGCodec::Decode(memory->front(), memory->size(), &bitmap)) |
| - return new SkBitmap(bitmap); |
| + if (gfx::PNGCodec::Decode(memory->front(), memory->size(), |
| + bitmap, fell_back_to_1x)) { |
| + return true; |
| + } |
| #if !defined(OS_IOS) |
| // iOS does not compile or use the JPEG codec. On other platforms, |
| // 99% of our assets are PNGs, however fallback to JPEG. |
| - SkBitmap* allocated_bitmap = |
| - gfx::JPEGCodec::Decode(memory->front(), memory->size()); |
| - if (allocated_bitmap) |
| - return allocated_bitmap; |
| + scoped_ptr<SkBitmap> jpeg_bitmap( |
| + gfx::JPEGCodec::Decode(memory->front(), memory->size())); |
| + if (jpeg_bitmap.get()) { |
| + bitmap->swap(*jpeg_bitmap.get()); |
| + return true; |
| + } |
| #endif |
| NOTREACHED() << "Unable to decode theme image resource " << resource_id; |
| - return NULL; |
| + return false; |
| } |
| -SkBitmap* ResourceBundle::LoadBitmap(int resource_id, |
| - ScaleFactor scale_factor) const { |
| +bool ResourceBundle::LoadBitmap(int resource_id, |
| + ScaleFactor scale_factor, |
| + SkBitmap* bitmap, |
| + bool* fell_back_to_1x) const { |
| for (size_t i = 0; i < data_packs_.size(); ++i) { |
| if (data_packs_[i]->GetScaleFactor() == scale_factor) { |
| - SkBitmap* bitmap = LoadBitmap(*data_packs_[i], resource_id); |
| - if (bitmap) |
| - return bitmap; |
| + if (LoadBitmap(*data_packs_[i], resource_id, bitmap, fell_back_to_1x)) |
| + return true; |
| } |
| } |
| - return NULL; |
| + return false; |
| } |
| gfx::Image& ResourceBundle::GetEmptyImage() { |