| 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;
|
| +}
|
|
|