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 cb7aba49a21e199e9fd0022c8283dcee01e47e03..41c69fcc3ca225b9e8e6516295f4a84dedcef097 100644 |
--- a/chrome/browser/themes/browser_theme_pack.cc |
+++ b/chrome/browser/themes/browser_theme_pack.cc |
@@ -24,9 +24,11 @@ |
#include "ui/base/resource/resource_bundle.h" |
#include "ui/gfx/canvas.h" |
#include "ui/gfx/codec/png_codec.h" |
+#include "ui/gfx/image/canvas_image_source.h" |
#include "ui/gfx/image/image.h" |
#include "ui/gfx/image/image_skia.h" |
-#include "ui/gfx/skbitmap_operations.h" |
+#include "ui/gfx/image/image_skia_operations.h" |
+#include "ui/gfx/screen.h" |
using content::BrowserThread; |
using extensions::Extension; |
@@ -49,6 +51,7 @@ const int kTintsID = kMaxID - 2; |
const int kColorsID = kMaxID - 3; |
const int kDisplayPropertiesID = kMaxID - 4; |
const int kSourceImagesID = kMaxID - 5; |
+const int kScaleFactorsID = kMaxID - 6; |
// Static size of the tint/color/display property arrays that are mmapped. |
const int kTintArraySize = 6; |
@@ -157,9 +160,10 @@ PersistingImagesTable kPersistingImages[] = { |
{ 44, IDR_THROBBER_WAITING, NULL }, |
{ 45, IDR_THROBBER_LIGHT, NULL }, |
}; |
+size_t kPersistingImagesLength = arraysize(kPersistingImages); |
int GetPersistentIDByName(const std::string& key) { |
- for (size_t i = 0; i < arraysize(kPersistingImages); ++i) { |
+ for (size_t i = 0; i < kPersistingImagesLength; ++i) { |
if (kPersistingImages[i].key != NULL && |
base::strcasecmp(key.c_str(), kPersistingImages[i].key) == 0) { |
return kPersistingImages[i].persistent_id; |
@@ -170,13 +174,47 @@ int GetPersistentIDByName(const std::string& key) { |
} |
int GetPersistentIDByIDR(int idr) { |
- for (size_t i = 0; i < arraysize(kPersistingImages); ++i) { |
- if (kPersistingImages[i].idr_id == idr) { |
- return kPersistingImages[i].persistent_id; |
+ static std::map<int,int>* lookup_table = new std::map<int,int>(); |
+ if (lookup_table->empty()) { |
+ for (size_t i = 0; i < kPersistingImagesLength; ++i) { |
+ int idr = kPersistingImages[i].idr_id; |
+ int prs_id = kPersistingImages[i].persistent_id; |
+ (*lookup_table)[idr] = prs_id; |
} |
} |
+ std::map<int,int>::iterator it = lookup_table->find(idr); |
+ return (it == lookup_table->end()) ? -1 : it->second; |
+} |
- return -1; |
+// Returns true if the scales in |input| match those in |expected|. |
+// The order must match as the index is used in determining the raw id. |
+bool InputScalesValid(const char* input, |
+ const std::vector<ui::ScaleFactor>& expected) { |
+ const float* scales = reinterpret_cast<const float*>(input); |
+ size_t index = 0; |
+ for (const float* end = scales; *end != -1.0f; ++end) { |
+ if (index >= expected.size()) |
+ return false; |
+ if (*end != ui::GetScaleFactorScale(expected[index])) |
+ return false; |
+ index++; |
+ } |
+ return (index == expected.size()); |
+} |
+ |
+// Returns |scale_factors| as a string to be written to disk. |
+base::StringPiece GetScaleFactorsAsString( |
+ const std::vector<ui::ScaleFactor>& scale_factors) { |
+ size_t scales_size = scale_factors.size() + 1; |
+ float* scales = new float[scales_size]; |
+ for (size_t i = 0; i < scale_factors.size(); ++i) |
+ scales[i] = ui::GetScaleFactorScale(scale_factors[i]); |
+ scales[scales_size - 1] = -1.0f; |
+ base::StringPiece out_string = base::StringPiece( |
+ reinterpret_cast<const char*>(&scales), |
+ scales_size * sizeof(float)); |
+ delete[] scales; |
+ return out_string; |
} |
struct StringToIntTable { |
@@ -308,23 +346,55 @@ base::RefCountedMemory* ReadFileData(const FilePath& path) { |
return NULL; |
} |
-// Shifts a bitmap's HSL values. The caller is responsible for deleting |
+// Shifts an image's HSL values. The caller is responsible for deleting |
// the returned image. |
gfx::Image* CreateHSLShiftedImage(const gfx::Image& image, |
const color_utils::HSL& hsl_shift) { |
const gfx::ImageSkia* src_image = image.ToImageSkia(); |
- std::vector<gfx::ImageSkiaRep> src_image_reps = src_image->image_reps(); |
- gfx::ImageSkia dst_image; |
- for (size_t i = 0; i < src_image_reps.size(); ++i) { |
- const gfx::ImageSkiaRep& image_rep = src_image_reps[i]; |
- SkBitmap dst_bitmap = SkBitmapOperations::CreateHSLShiftedBitmap( |
- image_rep.sk_bitmap(), hsl_shift); |
- dst_image.AddRepresentation(gfx::ImageSkiaRep(dst_bitmap, |
- image_rep.scale_factor())); |
- } |
- return new gfx::Image(dst_image); |
+ return new gfx::Image(gfx::ImageSkiaOperations::CreateHSLShiftedImage( |
+ *src_image, hsl_shift)); |
} |
+class TabBackgroundImageSource: public gfx::CanvasImageSource { |
+ public: |
+ TabBackgroundImageSource(const gfx::ImageSkia& image_to_tint, |
+ const gfx::ImageSkia& overlay, |
+ const color_utils::HSL& hsl_shift, |
+ int vertical_offset) |
+ : gfx::CanvasImageSource(image_to_tint.size(), false), |
+ image_to_tint_(image_to_tint), |
+ overlay_(overlay), |
+ hsl_shift_(hsl_shift), |
+ vertical_offset_(vertical_offset) { |
+ } |
+ |
+ virtual ~TabBackgroundImageSource() { |
+ } |
+ |
+ // Overridden from CanvasImageSource: |
+ virtual void Draw(gfx::Canvas* canvas) OVERRIDE { |
+ gfx::ImageSkia bg_tint = |
+ gfx::ImageSkiaOperations::CreateHSLShiftedImage(image_to_tint_, |
+ hsl_shift_); |
+ canvas->TileImageInt(bg_tint, 0, vertical_offset_, 0, 0, |
+ size().width(), size().height()); |
+ |
+ // If they've provided a custom image, overlay it. |
+ if (!overlay_.isNull()) { |
+ canvas->TileImageInt(overlay_, 0, 0, size().width(), |
+ overlay_.height()); |
+ } |
+ } |
+ |
+ private: |
+ const gfx::ImageSkia image_to_tint_; |
+ const gfx::ImageSkia overlay_; |
+ const color_utils::HSL hsl_shift_; |
+ const int vertical_offset_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TabBackgroundImageSource); |
+}; |
+ |
} // namespace |
BrowserThemePack::~BrowserThemePack() { |
@@ -336,8 +406,8 @@ BrowserThemePack::~BrowserThemePack() { |
delete [] source_images_; |
} |
- STLDeleteValues(&prepared_images_); |
- STLDeleteValues(&loaded_images_); |
+ STLDeleteValues(&images_on_ui_thread_); |
+ STLDeleteValues(&images_on_file_thread_); |
} |
// static |
@@ -360,16 +430,19 @@ scoped_refptr<BrowserThemePack> BrowserThemePack::BuildFromExtension( |
&file_paths); |
pack->BuildSourceImagesArray(file_paths); |
- if (!pack->LoadRawBitmapsTo(file_paths, &pack->prepared_images_)) |
+ if (!pack->LoadRawBitmapsTo(file_paths, &pack->images_on_ui_thread_)) |
return NULL; |
- pack->GenerateFrameImages(&pack->prepared_images_); |
+ pack->CopyImagesTo(pack->images_on_ui_thread_, &pack->images_on_file_thread_); |
- pack->GenerateTintedButtons( |
- pack->GetTintInternal(ThemeService::TINT_BUTTONS), |
- &pack->prepared_images_); |
+ pack->CreateImages(&pack->images_on_ui_thread_); |
+ pack->CreateImages(&pack->images_on_file_thread_); |
- pack->GenerateTabBackgroundImages(&pack->prepared_images_); |
+ // For M22, as it is not possible to easily determine which scale factors are |
+ // in use, assume that the 1x scale factor is in use. |
+ std::vector<ui::ScaleFactor> scale_factors_in_use; |
+ scale_factors_in_use.push_back(ui::SCALE_FACTOR_100P); |
+ pack->GenerateImageReps(scale_factors_in_use); |
// The BrowserThemePack is now in a consistent state. |
return pack; |
@@ -383,8 +456,10 @@ scoped_refptr<BrowserThemePack> BrowserThemePack::BuildFromDataPack( |
// (see http://crbug.com/80206) |
base::ThreadRestrictions::ScopedAllowIO allow_io; |
scoped_refptr<BrowserThemePack> pack(new BrowserThemePack); |
+ // Scale factor parameter is moot as data pack has image resources for all |
+ // supported scale factors. |
pack->data_pack_.reset( |
- new ui::DataPack(ui::SCALE_FACTOR_100P)); |
+ new ui::DataPack(ui::SCALE_FACTOR_NONE)); |
if (!pack->data_pack_->LoadFromPath(path)) { |
LOG(ERROR) << "Failed to load theme data pack."; |
@@ -430,6 +505,15 @@ scoped_refptr<BrowserThemePack> BrowserThemePack::BuildFromDataPack( |
pack->source_images_ = reinterpret_cast<int*>( |
const_cast<char*>(pointer.data())); |
+ if (!pack->data_pack_->GetStringPiece(kScaleFactorsID, &pointer)) |
+ return NULL; |
+ |
+ if (!InputScalesValid(const_cast<char*>(pointer.data()), |
+ pack->scale_factors_)) { |
+ DLOG(ERROR) << "BuildFromDataPack failure! The pack scale factors differ " |
+ << "from those supported by platform."; |
+ } |
+ |
return pack; |
} |
@@ -456,10 +540,12 @@ bool BrowserThemePack::WriteToDisk(const FilePath& path) const { |
reinterpret_cast<const char*>(source_images_), |
source_count * sizeof(*source_images_)); |
+ resources[kScaleFactorsID] = GetScaleFactorsAsString(scale_factors_); |
+ |
AddRawImagesTo(image_memory_, &resources); |
RawImages reencoded_images; |
- RepackImages(prepared_images_, &reencoded_images); |
+ RepackImages(images_on_file_thread_, &reencoded_images); |
AddRawImagesTo(reencoded_images, &resources); |
return ui::DataPack::WritePack(path, resources, ui::DataPack::BINARY); |
@@ -522,54 +608,53 @@ const gfx::Image* BrowserThemePack::GetImageNamed(int idr_id) const { |
if (prs_id == -1) |
return NULL; |
- // Check our cache of prepared images, first. |
- ImageCache::const_iterator image_iter = prepared_images_.find(prs_id); |
- if (image_iter != prepared_images_.end()) |
+ // Check if the image is cached. |
+ ImageCache::const_iterator image_iter = images_on_ui_thread_.find(prs_id); |
+ if (image_iter != images_on_ui_thread_.end()) |
return image_iter->second; |
- // Check if we've already loaded this image. |
- image_iter = loaded_images_.find(prs_id); |
- if (image_iter != loaded_images_.end()) |
- return image_iter->second; |
+ // TODO(pkotwicz): Do something better than loading the bitmaps |
+ // for all the scale factors associated with |idr_id|. |
+ gfx::ImageSkia image_skia; |
+ for (size_t i = 0; i < scale_factors_.size(); ++i) { |
+ scoped_refptr<base::RefCountedMemory> memory = |
+ GetRawData(idr_id, scale_factors_[i]); |
- scoped_refptr<base::RefCountedMemory> memory; |
- if (data_pack_.get()) { |
- memory = data_pack_->GetStaticMemory(prs_id); |
- } else { |
- RawImages::const_iterator it = image_memory_.find(prs_id); |
- if (it != image_memory_.end()) { |
- memory = it->second; |
+ 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."; |
+ return NULL; |
+ } |
+ image_skia.AddRepresentation( |
+ gfx::ImageSkiaRep(bitmap, 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."; |
- return NULL; |
- } |
- |
- gfx::Image* ret = new gfx::Image(bitmap); |
- loaded_images_[prs_id] = ret; |
- |
+ if (!image_skia.isNull()) { |
+ gfx::Image* ret = new gfx::Image(image_skia); |
+ images_on_ui_thread_[prs_id] = ret; |
return ret; |
} |
return NULL; |
} |
-base::RefCountedMemory* BrowserThemePack::GetRawData(int idr_id) const { |
+base::RefCountedMemory* BrowserThemePack::GetRawData( |
+ int idr_id, |
+ ui::ScaleFactor scale_factor) const { |
base::RefCountedMemory* memory = NULL; |
int prs_id = GetPersistentIDByIDR(idr_id); |
+ int raw_id = GetRawIDByPersistentID(prs_id, scale_factor); |
- if (prs_id != -1) { |
+ if (raw_id != -1) { |
if (data_pack_.get()) { |
- memory = data_pack_->GetStaticMemory(prs_id); |
+ memory = data_pack_->GetStaticMemory(raw_id); |
} else { |
- RawImages::const_iterator it = image_memory_.find(prs_id); |
+ RawImages::const_iterator it = image_memory_.find(raw_id); |
if (it != image_memory_.end()) { |
memory = it->second; |
} |
@@ -601,6 +686,11 @@ BrowserThemePack::BrowserThemePack() |
colors_(NULL), |
display_properties_(NULL), |
source_images_(NULL) { |
+#if defined(OS_MACOSX) |
+ scale_factors_ = ui::GetSupportedScaleFactors(); |
+#else |
+ scale_factors_.push_back(ui::SCALE_FACTOR_100P); |
+#endif |
} |
void BrowserThemePack::BuildHeader(const Extension* extension) { |
@@ -867,7 +957,7 @@ void BrowserThemePack::BuildSourceImagesArray(const FilePathMap& file_paths) { |
bool BrowserThemePack::LoadRawBitmapsTo( |
const FilePathMap& file_paths, |
- ImageCache* raw_bitmaps) { |
+ ImageCache* image_cache) { |
// Themes should be loaded on the file thread, not the UI thread. |
// http://crbug.com/61838 |
base::ThreadRestrictions::ScopedAllowIO allow_io; |
@@ -880,26 +970,27 @@ bool BrowserThemePack::LoadRawBitmapsTo( |
return false; |
} |
- int id = it->first; |
+ int prs_id = it->first; |
// Some images need to go directly into |image_memory_|. No modification is |
// necessary or desirable. |
bool is_copyable = false; |
for (size_t i = 0; i < arraysize(kPreloadIDs); ++i) { |
- if (kPreloadIDs[i] == id) { |
+ if (kPreloadIDs[i] == prs_id) { |
is_copyable = true; |
break; |
} |
} |
if (is_copyable) { |
- image_memory_[id] = raw_data; |
+ int raw_id = GetRawIDByPersistentID(prs_id, ui::SCALE_FACTOR_100P); |
+ image_memory_[raw_id] = raw_data; |
} else if (raw_data.get() && raw_data->size()) { |
// Decode the PNG. |
SkBitmap bitmap; |
if (gfx::PNGCodec::Decode(raw_data->front(), raw_data->size(), |
&bitmap)) { |
- (*raw_bitmaps)[it->first] = new gfx::Image(bitmap); |
+ (*image_cache)[prs_id] = new gfx::Image(bitmap); |
} else { |
NOTREACHED() << "Unable to decode theme image resource " << it->first; |
} |
@@ -909,11 +1000,17 @@ bool BrowserThemePack::LoadRawBitmapsTo( |
return true; |
} |
-void BrowserThemePack::GenerateFrameImages(ImageCache* bitmaps) const { |
+void BrowserThemePack::CreateImages(ImageCache* images) const { |
+ CreateFrameImages(images); |
+ CreateTintedButtons(GetTintInternal(ThemeService::TINT_BUTTONS), images); |
+ CreateTabBackgroundImages(images); |
+} |
+ |
+void BrowserThemePack::CreateFrameImages(ImageCache* images) const { |
ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
- // Create all the output bitmaps in a separate cache and move them back into |
- // the input bitmaps because there can be name collisions. |
+ // Create all the output images in a separate cache and move them back into |
+ // the input images because there can be name collisions. |
ImageCache temp_output; |
for (size_t i = 0; i < arraysize(kFrameTintMap); ++i) { |
@@ -925,25 +1022,25 @@ void BrowserThemePack::GenerateFrameImages(ImageCache* bitmaps) const { |
int prs_base_id; |
if (prs_id == PRS_THEME_FRAME_INCOGNITO_INACTIVE) { |
- prs_base_id = bitmaps->count(PRS_THEME_FRAME_INCOGNITO) ? |
+ prs_base_id = images->count(PRS_THEME_FRAME_INCOGNITO) ? |
PRS_THEME_FRAME_INCOGNITO : PRS_THEME_FRAME; |
} else if (prs_id == PRS_THEME_FRAME_OVERLAY_INACTIVE) { |
prs_base_id = PRS_THEME_FRAME_OVERLAY; |
} else if (prs_id == PRS_THEME_FRAME_INACTIVE) { |
prs_base_id = PRS_THEME_FRAME; |
} else if (prs_id == PRS_THEME_FRAME_INCOGNITO && |
- !bitmaps->count(PRS_THEME_FRAME_INCOGNITO)) { |
+ !images->count(PRS_THEME_FRAME_INCOGNITO)) { |
prs_base_id = PRS_THEME_FRAME; |
} else { |
prs_base_id = prs_id; |
} |
- if (bitmaps->count(prs_id)) { |
- frame = (*bitmaps)[prs_id]; |
- } else if (prs_base_id != prs_id && bitmaps->count(prs_base_id)) { |
- frame = (*bitmaps)[prs_base_id]; |
+ if (images->count(prs_id)) { |
+ frame = (*images)[prs_id]; |
+ } else if (prs_base_id != prs_id && images->count(prs_base_id)) { |
+ frame = (*images)[prs_base_id]; |
} else if (prs_base_id == PRS_THEME_FRAME_OVERLAY && |
- bitmaps->count(PRS_THEME_FRAME)) { |
+ images->count(PRS_THEME_FRAME)) { |
// If there is no theme overlay, don't tint the default frame, |
// because it will overwrite the custom frame image when we cache and |
// reload from disk. |
@@ -959,13 +1056,12 @@ void BrowserThemePack::GenerateFrameImages(ImageCache* bitmaps) const { |
*frame, GetTintInternal(kFrameTintMap[i].value)); |
} |
} |
- |
- MergeImageCaches(temp_output, bitmaps); |
+ MergeImageCaches(temp_output, images); |
} |
-void BrowserThemePack::GenerateTintedButtons( |
+void BrowserThemePack::CreateTintedButtons( |
const color_utils::HSL& button_tint, |
- ImageCache* processed_bitmaps) const { |
+ ImageCache* processed_images) const { |
if (button_tint.h != -1 || button_tint.s != -1 || button_tint.l != -1) { |
ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
const std::set<int>& idr_ids = |
@@ -979,13 +1075,13 @@ void BrowserThemePack::GenerateTintedButtons( |
gfx::Image& button = rb.GetImageNamed(*it); |
// but save a version with the persistent ID. |
- (*processed_bitmaps)[prs_id] = |
+ (*processed_images)[prs_id] = |
CreateHSLShiftedImage(button, button_tint); |
} |
} |
} |
-void BrowserThemePack::GenerateTabBackgroundImages(ImageCache* bitmaps) const { |
+void BrowserThemePack::CreateTabBackgroundImages(ImageCache* images) const { |
ImageCache temp_output; |
for (size_t i = 0; i < arraysize(kTabBackgroundMap); ++i) { |
int prs_id = kTabBackgroundMap[i].key; |
@@ -993,57 +1089,91 @@ void BrowserThemePack::GenerateTabBackgroundImages(ImageCache* bitmaps) const { |
// We only need to generate the background tab images if we were provided |
// with a PRS_THEME_FRAME. |
- ImageCache::const_iterator it = bitmaps->find(prs_base_id); |
- if (it != bitmaps->end()) { |
+ ImageCache::const_iterator it = images->find(prs_base_id); |
+ if (it != images->end()) { |
const gfx::ImageSkia* image_to_tint = (it->second)->ToImageSkia(); |
- const std::vector<gfx::ImageSkiaRep> image_reps_to_tint = |
- image_to_tint->image_reps(); |
- gfx::ImageSkia tinted_image; |
- for (size_t j = 0; j < image_reps_to_tint.size(); ++j) { |
- gfx::ImageSkiaRep image_rep_to_tint = image_reps_to_tint[j]; |
- SkBitmap bg_tint = SkBitmapOperations::CreateHSLShiftedBitmap( |
- image_rep_to_tint.sk_bitmap(), GetTintInternal( |
- ThemeService::TINT_BACKGROUND_TAB)); |
- gfx::Size bg_tint_dip_size(image_rep_to_tint.GetWidth(), |
- image_rep_to_tint.GetHeight()); |
- int vertical_offset = bitmaps->count(prs_id) |
- ? kRestoredTabVerticalOffset : 0; |
- gfx::Canvas canvas(gfx::Size(bg_tint.width(), bg_tint.height()), |
- image_rep_to_tint.scale_factor(), |
- false); |
- canvas.TileImageInt(bg_tint, 0, vertical_offset, 0, 0, |
- bg_tint_dip_size.width(), bg_tint_dip_size.height()); |
- |
- // If they've provided a custom image, overlay it. |
- ImageCache::const_iterator overlay_it = bitmaps->find(prs_id); |
- if (overlay_it != bitmaps->end()) { |
- const gfx::ImageSkia* overlay = overlay_it->second->ToImageSkia(); |
- canvas.TileImageInt(*overlay, 0, 0, bg_tint_dip_size.width(), |
- overlay->height()); |
- } |
- tinted_image.AddRepresentation(canvas.ExtractImageRep()); |
- } |
- |
- temp_output[prs_id] = new gfx::Image(tinted_image); |
+ color_utils::HSL hsl_shift = GetTintInternal( |
+ ThemeService::TINT_BACKGROUND_TAB); |
+ int vertical_offset = images->count(prs_id) |
+ ? kRestoredTabVerticalOffset : 0; |
+ |
+ gfx::ImageSkia overlay; |
+ ImageCache::const_iterator overlay_it = images->find(prs_id); |
+ if (overlay_it != images->end()) |
+ overlay = *overlay_it->second->ToImageSkia(); |
+ |
+ gfx::ImageSkiaSource* source = new TabBackgroundImageSource( |
+ *image_to_tint, overlay, hsl_shift, vertical_offset); |
+ // ImageSkia takes ownership of |source|. |
+ temp_output[prs_id] = new gfx::Image(gfx::ImageSkia(source, |
+ image_to_tint->size())); |
} |
} |
- |
- MergeImageCaches(temp_output, bitmaps); |
+ MergeImageCaches(temp_output, images); |
} |
void BrowserThemePack::RepackImages(const ImageCache& images, |
RawImages* reencoded_images) const { |
+ |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
+ |
+ typedef std::vector<ui::ScaleFactor> ScaleFactors; |
for (ImageCache::const_iterator it = images.begin(); |
it != images.end(); ++it) { |
- std::vector<unsigned char> image_data; |
- if (!gfx::PNGCodec::EncodeBGRASkBitmap(*it->second->ToSkBitmap(), false, |
- &image_data)) { |
- NOTREACHED() << "Image file for resource " << it->first |
- << " could not be encoded."; |
- } else { |
- (*reencoded_images)[it->first] = |
- base::RefCountedBytes::TakeVector(&image_data); |
+ gfx::ImageSkia image_skia = *it->second->ToImageSkia(); |
+ |
+ // Attempt to generate image reps for all supported scale factors. |
+ for (ScaleFactors::const_iterator factor_it = scale_factors_.begin(); |
+ factor_it != scale_factors_.end(); ++factor_it) { |
+ // Ask for representation to force the representation to be generated |
+ // if it wasn't already. |
+ image_skia.GetRepresentation(*factor_it); |
+ } |
+ |
+ typedef std::vector<gfx::ImageSkiaRep> ImageSkiaReps; |
+ ImageSkiaReps image_reps = image_skia.image_reps(); |
+ if (image_reps.empty()) { |
+ NOTREACHED() << "No image reps for resource " << it->first << "."; |
+ } |
+ for (ImageSkiaReps::iterator rep_it = image_reps.begin(); |
+ rep_it != image_reps.end(); ++rep_it) { |
+ std::vector<unsigned char> bitmap_data; |
+ if (!gfx::PNGCodec::EncodeBGRASkBitmap(rep_it->sk_bitmap(), false, |
+ &bitmap_data)) { |
+ NOTREACHED() << "Image file for resource " << it->first |
+ << " could not be encoded."; |
+ } |
+ int raw_id = GetRawIDByPersistentID(it->first, rep_it->scale_factor()); |
+ (*reencoded_images)[raw_id] = |
+ base::RefCountedBytes::TakeVector(&bitmap_data); |
+ } |
+ } |
+} |
+ |
+void BrowserThemePack::GenerateImageReps( |
+ const std::vector<ui::ScaleFactor>& scale_factors) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ for (ImageCache::const_iterator it = images_on_ui_thread_.begin(); |
+ it != images_on_ui_thread_.end(); |
+ ++it) { |
+ const gfx::ImageSkia* image1 = it->second->ToImageSkia(); |
+ const gfx::ImageSkia* image2 = |
+ images_on_file_thread_[it->first]->ToImageSkia(); |
+ |
+ // Ensure that image reps are generated and cached in |image1| by |
+ // calling GetRepresentation(). |
+ for (size_t i = 0; i < scale_factors.size(); ++i) |
+ image1->GetRepresentation(scale_factors[i]); |
+ |
+ // |image1| and |image2| have ImageSkiaSources which produce pixel |
+ // equivalent output. Instead of regenerating again, copy the image reps |
+ // which were generated for |image1| into |image2|. |
+ // Don't do a deep copy of the SkBitmaps as SkBitmap is thread safe. |
+ std::vector<gfx::ImageSkiaRep> image1_reps = image1->image_reps(); |
+ for (size_t i = 0; i < image1_reps.size(); ++i) { |
+ gfx::ImageSkiaRep image1_rep = image1_reps[i]; |
+ const_cast<gfx::ImageSkia*>(image2)->AddRepresentation(gfx::ImageSkiaRep( |
+ image1_rep.sk_bitmap(), image1_rep.scale_factor())); |
} |
} |
} |
@@ -1052,14 +1182,22 @@ void BrowserThemePack::MergeImageCaches( |
const ImageCache& source, ImageCache* destination) const { |
for (ImageCache::const_iterator it = source.begin(); it != source.end(); |
++it) { |
- ImageCache::const_iterator bitmap_it = destination->find(it->first); |
- if (bitmap_it != destination->end()) |
- delete bitmap_it->second; |
+ ImageCache::const_iterator image_it = destination->find(it->first); |
+ if (image_it != destination->end()) |
+ delete image_it->second; |
(*destination)[it->first] = it->second; |
} |
} |
+void BrowserThemePack::CopyImagesTo(const ImageCache& source, |
+ ImageCache* destination) const { |
+ for (ImageCache::const_iterator it = source.begin(); it != source.end(); |
+ ++it) { |
+ (*destination)[it->first] = new gfx::Image(*it->second); |
+ } |
+} |
+ |
void BrowserThemePack::AddRawImagesTo(const RawImages& images, |
RawDataForWriting* out) const { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
@@ -1085,3 +1223,16 @@ color_utils::HSL BrowserThemePack::GetTintInternal(int id) const { |
return ThemeService::GetDefaultTint(id); |
} |
+ |
+int BrowserThemePack::GetRawIDByPersistentID( |
+ int prs_id, |
+ ui::ScaleFactor scale_factor) const { |
+ if (prs_id < 0) |
+ return -1; |
+ |
+ for (size_t i = 0; i < scale_factors_.size(); ++i) { |
+ if (scale_factors_[i] == scale_factor) |
+ return static_cast<int>(kPersistingImagesLength * i) + prs_id; |
+ } |
+ return -1; |
+} |