Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/themes/browser_theme_pack.h" | 5 #include "chrome/browser/themes/browser_theme_pack.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/memory/ref_counted_memory.h" | 9 #include "base/memory/ref_counted_memory.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
| 13 #include "base/threading/thread_restrictions.h" | 13 #include "base/threading/thread_restrictions.h" |
| 14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
| 15 #include "base/values.h" | 15 #include "base/values.h" |
| 16 #include "chrome/browser/themes/theme_service.h" | 16 #include "chrome/browser/themes/theme_service.h" |
| 17 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
| 18 #include "grit/theme_resources.h" | 18 #include "grit/theme_resources.h" |
| 19 #include "grit/ui_resources.h" | 19 #include "grit/ui_resources.h" |
| 20 #include "net/base/file_stream.h" | 20 #include "net/base/file_stream.h" |
| 21 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" |
| 22 #include "third_party/skia/include/core/SkCanvas.h" | 22 #include "third_party/skia/include/core/SkCanvas.h" |
| 23 #include "ui/base/resource/data_pack.h" | 23 #include "ui/base/resource/data_pack.h" |
| 24 #include "ui/base/resource/resource_bundle.h" | 24 #include "ui/base/resource/resource_bundle.h" |
| 25 #include "ui/gfx/canvas.h" | 25 #include "ui/gfx/canvas.h" |
| 26 #include "ui/gfx/codec/png_codec.h" | 26 #include "ui/gfx/codec/png_codec.h" |
| 27 #include "ui/gfx/image/canvas_image_source.h" | |
| 27 #include "ui/gfx/image/image.h" | 28 #include "ui/gfx/image/image.h" |
| 28 #include "ui/gfx/image/image_skia.h" | 29 #include "ui/gfx/image/image_skia.h" |
| 29 #include "ui/gfx/skbitmap_operations.h" | 30 #include "ui/gfx/image/image_skia_operations.h" |
| 31 #include "ui/gfx/screen.h" | |
| 30 | 32 |
| 31 using content::BrowserThread; | 33 using content::BrowserThread; |
| 32 using extensions::Extension; | 34 using extensions::Extension; |
| 33 | 35 |
| 34 namespace { | 36 namespace { |
| 35 | 37 |
| 36 // Version number of the current theme pack. We just throw out and rebuild | 38 // Version number of the current theme pack. We just throw out and rebuild |
| 37 // theme packs that aren't int-equal to this. Increment this number if you | 39 // theme packs that aren't int-equal to this. Increment this number if you |
| 38 // change default theme assets. | 40 // change default theme assets. |
| 39 const int kThemePackVersion = 24; | 41 const int kThemePackVersion = 24; |
|
Elliot Glaysher
2012/07/20 18:17:14
Do you need to rev this? You're adding members to
pkotwicz
2012/07/20 20:00:45
You're right I don't need to. Line 503 will force
| |
| 40 | 42 |
| 41 // IDs that are in the DataPack won't clash with the positive integer | 43 // IDs that are in the DataPack won't clash with the positive integer |
| 42 // uint16. kHeaderID should always have the maximum value because we want the | 44 // uint16. kHeaderID should always have the maximum value because we want the |
| 43 // "header" to be written last. That way we can detect whether the pack was | 45 // "header" to be written last. That way we can detect whether the pack was |
| 44 // successfully written and ignore and regenerate if it was only partially | 46 // successfully written and ignore and regenerate if it was only partially |
| 45 // written (i.e. chrome crashed on a different thread while writing the pack). | 47 // written (i.e. chrome crashed on a different thread while writing the pack). |
| 46 const int kMaxID = 0x0000FFFF; // Max unsigned 16-bit int. | 48 const int kMaxID = 0x0000FFFF; // Max unsigned 16-bit int. |
| 47 const int kHeaderID = kMaxID - 1; | 49 const int kHeaderID = kMaxID - 1; |
| 48 const int kTintsID = kMaxID - 2; | 50 const int kTintsID = kMaxID - 2; |
| 49 const int kColorsID = kMaxID - 3; | 51 const int kColorsID = kMaxID - 3; |
| 50 const int kDisplayPropertiesID = kMaxID - 4; | 52 const int kDisplayPropertiesID = kMaxID - 4; |
| 51 const int kSourceImagesID = kMaxID - 5; | 53 const int kSourceImagesID = kMaxID - 5; |
| 54 const int kScaleFactorsID = kMaxID - 6; | |
| 52 | 55 |
| 53 // Static size of the tint/color/display property arrays that are mmapped. | 56 // Static size of the tint/color/display property arrays that are mmapped. |
| 54 const int kTintArraySize = 6; | 57 const int kTintArraySize = 6; |
| 55 const int kColorArraySize = 19; | 58 const int kColorArraySize = 19; |
| 56 const int kDisplayPropertySize = 3; | 59 const int kDisplayPropertySize = 3; |
| 57 | 60 |
| 58 // The sum of kFrameBorderThickness and kNonClientRestoredExtraThickness from | 61 // The sum of kFrameBorderThickness and kNonClientRestoredExtraThickness from |
| 59 // OpaqueBrowserFrameView. | 62 // OpaqueBrowserFrameView. |
| 60 const int kRestoredTabVerticalOffset = 15; | 63 const int kRestoredTabVerticalOffset = 15; |
| 61 | 64 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 { 37, IDR_BROWSER_ACTIONS_OVERFLOW_H, NULL }, | 153 { 37, IDR_BROWSER_ACTIONS_OVERFLOW_H, NULL }, |
| 151 { 38, IDR_BROWSER_ACTIONS_OVERFLOW_P, NULL }, | 154 { 38, IDR_BROWSER_ACTIONS_OVERFLOW_P, NULL }, |
| 152 { 39, IDR_TOOLS, NULL }, | 155 { 39, IDR_TOOLS, NULL }, |
| 153 { 40, IDR_TOOLS_H, NULL }, | 156 { 40, IDR_TOOLS_H, NULL }, |
| 154 { 41, IDR_TOOLS_P, NULL }, | 157 { 41, IDR_TOOLS_P, NULL }, |
| 155 { 42, IDR_MENU_DROPARROW, NULL }, | 158 { 42, IDR_MENU_DROPARROW, NULL }, |
| 156 { 43, IDR_THROBBER, NULL }, | 159 { 43, IDR_THROBBER, NULL }, |
| 157 { 44, IDR_THROBBER_WAITING, NULL }, | 160 { 44, IDR_THROBBER_WAITING, NULL }, |
| 158 { 45, IDR_THROBBER_LIGHT, NULL }, | 161 { 45, IDR_THROBBER_LIGHT, NULL }, |
| 159 }; | 162 }; |
| 163 size_t kPersistingImagesLength = arraysize(kPersistingImages); | |
| 160 | 164 |
| 161 int GetPersistentIDByName(const std::string& key) { | 165 int GetPersistentIDByName(const std::string& key) { |
| 162 for (size_t i = 0; i < arraysize(kPersistingImages); ++i) { | 166 for (size_t i = 0; i < kPersistingImagesLength; ++i) { |
| 163 if (kPersistingImages[i].key != NULL && | 167 if (kPersistingImages[i].key != NULL && |
| 164 base::strcasecmp(key.c_str(), kPersistingImages[i].key) == 0) { | 168 base::strcasecmp(key.c_str(), kPersistingImages[i].key) == 0) { |
| 165 return kPersistingImages[i].persistent_id; | 169 return kPersistingImages[i].persistent_id; |
| 166 } | 170 } |
| 167 } | 171 } |
| 168 | 172 |
| 169 return -1; | 173 return -1; |
| 170 } | 174 } |
| 171 | 175 |
| 172 int GetPersistentIDByIDR(int idr) { | 176 int GetPersistentIDByIDR(int idr) { |
| 173 for (size_t i = 0; i < arraysize(kPersistingImages); ++i) { | 177 static std::map<int,int>* lookup_table = new std::map<int,int>(); |
| 174 if (kPersistingImages[i].idr_id == idr) { | 178 if (lookup_table->empty()) { |
| 175 return kPersistingImages[i].persistent_id; | 179 for (size_t i = 0; i < kPersistingImagesLength; ++i) { |
| 180 int idr = kPersistingImages[i].idr_id; | |
| 181 int prs_id = kPersistingImages[i].persistent_id; | |
| 182 (*lookup_table)[idr] = prs_id; | |
| 176 } | 183 } |
| 177 } | 184 } |
| 185 std::map<int,int>::iterator it = lookup_table->find(idr); | |
| 186 return (it == lookup_table->end()) ? -1 : it->second; | |
| 187 } | |
| 178 | 188 |
| 179 return -1; | 189 // Returns true if the scales in |input| match those in |expected|. |
| 190 // The order must match as the index is used in determining the raw id. | |
| 191 bool InputScalesValid(char* input, | |
| 192 const std::vector<ui::ScaleFactor>& expected) { | |
| 193 float* scales = reinterpret_cast<float*>(input); | |
| 194 size_t index = 0; | |
| 195 for (float* end = scales; *end != -1.0f; ++end) { | |
| 196 if (index >= expected.size()) | |
| 197 return false; | |
| 198 if (*end != ui::GetScaleFactorScale(expected[index])) | |
| 199 return false; | |
| 200 index++; | |
| 201 } | |
| 202 return (index == expected.size()); | |
| 203 } | |
| 204 | |
| 205 // Returns |scale_factors| as a string to be written to disk. | |
| 206 base::StringPiece GetScaleFactorsAsString( | |
| 207 const std::vector<ui::ScaleFactor>& scale_factors) { | |
| 208 size_t scales_size = scale_factors.size() + 1; | |
| 209 float scales[scales_size]; | |
| 210 for (size_t i = 0; i < scale_factors.size(); ++i) | |
| 211 scales[i] = ui::GetScaleFactorScale(scale_factors[i]); | |
| 212 scales[scales_size - 1] = -1.0f; | |
| 213 return base::StringPiece( | |
| 214 reinterpret_cast<const char*>(&scales), | |
| 215 scales_size * sizeof(float)); | |
| 180 } | 216 } |
| 181 | 217 |
| 182 struct StringToIntTable { | 218 struct StringToIntTable { |
| 183 const char* key; | 219 const char* key; |
| 184 int id; | 220 int id; |
| 185 }; | 221 }; |
| 186 | 222 |
| 187 // Strings used by themes to identify tints in the JSON. | 223 // Strings used by themes to identify tints in the JSON. |
| 188 StringToIntTable kTintTable[] = { | 224 StringToIntTable kTintTable[] = { |
| 189 { "buttons", ThemeService::TINT_BUTTONS }, | 225 { "buttons", ThemeService::TINT_BUTTONS }, |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 char* data = reinterpret_cast<char*>(&(raw_data.front())); | 337 char* data = reinterpret_cast<char*>(&(raw_data.front())); |
| 302 if (file.ReadUntilComplete(data, size) == avail) | 338 if (file.ReadUntilComplete(data, size) == avail) |
| 303 return base::RefCountedBytes::TakeVector(&raw_data); | 339 return base::RefCountedBytes::TakeVector(&raw_data); |
| 304 } | 340 } |
| 305 } | 341 } |
| 306 } | 342 } |
| 307 | 343 |
| 308 return NULL; | 344 return NULL; |
| 309 } | 345 } |
| 310 | 346 |
| 311 // Shifts a bitmap's HSL values. The caller is responsible for deleting | 347 // Shifts an image's HSL values. The caller is responsible for deleting |
| 312 // the returned image. | 348 // the returned image. |
| 313 gfx::Image* CreateHSLShiftedImage(const gfx::Image& image, | 349 gfx::Image* CreateHSLShiftedImage(const gfx::Image& image, |
| 314 const color_utils::HSL& hsl_shift) { | 350 const color_utils::HSL& hsl_shift) { |
| 315 const gfx::ImageSkia* src_image = image.ToImageSkia(); | 351 const gfx::ImageSkia* src_image = image.ToImageSkia(); |
| 316 std::vector<gfx::ImageSkiaRep> src_image_reps = src_image->image_reps(); | 352 return new gfx::Image(gfx::ImageSkiaOperations::CreateHSLShiftedImage( |
| 317 gfx::ImageSkia dst_image; | 353 *src_image, hsl_shift)); |
| 318 for (size_t i = 0; i < src_image_reps.size(); ++i) { | 354 } |
| 319 const gfx::ImageSkiaRep& image_rep = src_image_reps[i]; | 355 |
| 320 SkBitmap dst_bitmap = SkBitmapOperations::CreateHSLShiftedBitmap( | 356 class TabBackgroundImageSource: public gfx::CanvasImageSource { |
| 321 image_rep.sk_bitmap(), hsl_shift); | 357 public: |
| 322 dst_image.AddRepresentation(gfx::ImageSkiaRep(dst_bitmap, | 358 TabBackgroundImageSource(const gfx::ImageSkia& image_to_tint, |
| 323 image_rep.scale_factor())); | 359 const gfx::ImageSkia& overlay, |
| 360 const color_utils::HSL& hsl_shift, | |
| 361 int vertical_offset) | |
| 362 : gfx::CanvasImageSource(image_to_tint.size(), false), | |
| 363 image_to_tint_(image_to_tint), | |
| 364 overlay_(overlay), | |
| 365 hsl_shift_(hsl_shift), | |
| 366 vertical_offset_(vertical_offset) { | |
| 324 } | 367 } |
| 325 return new gfx::Image(dst_image); | 368 |
| 326 } | 369 ~TabBackgroundImageSource() { |
| 370 } | |
| 371 | |
| 372 // Overridden from CanvasImageSource: | |
| 373 virtual void Draw(gfx::Canvas* canvas) OVERRIDE { | |
| 374 gfx::ImageSkia bg_tint = | |
| 375 gfx::ImageSkiaOperations::CreateHSLShiftedImage(image_to_tint_, | |
| 376 hsl_shift_); | |
| 377 canvas->TileImageInt(bg_tint, 0, vertical_offset_, 0, 0, | |
| 378 size().width(), size().height()); | |
| 379 | |
| 380 // If they've provided a custom image, overlay it. | |
| 381 if (!overlay_.isNull()) { | |
| 382 canvas->TileImageInt(overlay_, 0, 0, size().width(), | |
| 383 overlay_.height()); | |
| 384 } | |
| 385 } | |
| 386 | |
| 387 private: | |
| 388 const gfx::ImageSkia image_to_tint_; | |
| 389 const gfx::ImageSkia overlay_; | |
| 390 const color_utils::HSL hsl_shift_; | |
| 391 const int vertical_offset_; | |
| 392 | |
| 393 DISALLOW_COPY_AND_ASSIGN(TabBackgroundImageSource); | |
| 394 }; | |
| 327 | 395 |
| 328 } // namespace | 396 } // namespace |
| 329 | 397 |
| 330 BrowserThemePack::~BrowserThemePack() { | 398 BrowserThemePack::~BrowserThemePack() { |
| 331 if (!data_pack_.get()) { | 399 if (!data_pack_.get()) { |
| 332 delete header_; | 400 delete header_; |
| 333 delete [] tints_; | 401 delete [] tints_; |
| 334 delete [] colors_; | 402 delete [] colors_; |
| 335 delete [] display_properties_; | 403 delete [] display_properties_; |
| 336 delete [] source_images_; | 404 delete [] source_images_; |
| 337 } | 405 } |
| 338 | 406 |
| 339 STLDeleteValues(&prepared_images_); | 407 STLDeleteValues(&images_on_ui_thread_); |
| 340 STLDeleteValues(&loaded_images_); | 408 STLDeleteValues(&images_on_file_thread_); |
| 341 } | 409 } |
| 342 | 410 |
| 343 // static | 411 // static |
| 344 scoped_refptr<BrowserThemePack> BrowserThemePack::BuildFromExtension( | 412 scoped_refptr<BrowserThemePack> BrowserThemePack::BuildFromExtension( |
| 345 const Extension* extension) { | 413 const Extension* extension) { |
| 346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 414 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 347 DCHECK(extension); | 415 DCHECK(extension); |
| 348 DCHECK(extension->is_theme()); | 416 DCHECK(extension->is_theme()); |
| 349 | 417 |
| 350 scoped_refptr<BrowserThemePack> pack(new BrowserThemePack); | 418 scoped_refptr<BrowserThemePack> pack(new BrowserThemePack); |
| 351 pack->BuildHeader(extension); | 419 pack->BuildHeader(extension); |
| 352 pack->BuildTintsFromJSON(extension->GetThemeTints()); | 420 pack->BuildTintsFromJSON(extension->GetThemeTints()); |
| 353 pack->BuildColorsFromJSON(extension->GetThemeColors()); | 421 pack->BuildColorsFromJSON(extension->GetThemeColors()); |
| 354 pack->BuildDisplayPropertiesFromJSON(extension->GetThemeDisplayProperties()); | 422 pack->BuildDisplayPropertiesFromJSON(extension->GetThemeDisplayProperties()); |
| 355 | 423 |
| 356 // Builds the images. (Image building is dependent on tints). | 424 // Builds the images. (Image building is dependent on tints). |
| 357 FilePathMap file_paths; | 425 FilePathMap file_paths; |
| 358 pack->ParseImageNamesFromJSON(extension->GetThemeImages(), | 426 pack->ParseImageNamesFromJSON(extension->GetThemeImages(), |
| 359 extension->path(), | 427 extension->path(), |
| 360 &file_paths); | 428 &file_paths); |
| 361 pack->BuildSourceImagesArray(file_paths); | 429 pack->BuildSourceImagesArray(file_paths); |
| 362 | 430 |
| 363 if (!pack->LoadRawBitmapsTo(file_paths, &pack->prepared_images_)) | 431 if (!pack->LoadRawBitmapsTo(file_paths, &pack->images_on_ui_thread_)) |
| 364 return NULL; | 432 return NULL; |
| 365 | 433 |
| 366 pack->GenerateFrameImages(&pack->prepared_images_); | 434 pack->CopyImagesTo(pack->images_on_ui_thread_, &pack->images_on_file_thread_); |
| 367 | 435 |
| 368 pack->GenerateTintedButtons( | 436 pack->CreateImages(&pack->images_on_ui_thread_); |
| 369 pack->GetTintInternal(ThemeService::TINT_BUTTONS), | 437 pack->CreateImages(&pack->images_on_file_thread_); |
| 370 &pack->prepared_images_); | |
| 371 | 438 |
| 372 pack->GenerateTabBackgroundImages(&pack->prepared_images_); | 439 pack->GenerateImageReps(gfx::Screen::GetScaleFactorsInUse()); |
| 373 | 440 |
| 374 // The BrowserThemePack is now in a consistent state. | 441 // The BrowserThemePack is now in a consistent state. |
| 375 return pack; | 442 return pack; |
| 376 } | 443 } |
| 377 | 444 |
| 378 // static | 445 // static |
| 379 scoped_refptr<BrowserThemePack> BrowserThemePack::BuildFromDataPack( | 446 scoped_refptr<BrowserThemePack> BrowserThemePack::BuildFromDataPack( |
| 380 FilePath path, const std::string& expected_id) { | 447 FilePath path, const std::string& expected_id) { |
| 381 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 448 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 382 // Allow IO on UI thread due to deep-seated theme design issues. | 449 // Allow IO on UI thread due to deep-seated theme design issues. |
| 383 // (see http://crbug.com/80206) | 450 // (see http://crbug.com/80206) |
| 384 base::ThreadRestrictions::ScopedAllowIO allow_io; | 451 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 385 scoped_refptr<BrowserThemePack> pack(new BrowserThemePack); | 452 scoped_refptr<BrowserThemePack> pack(new BrowserThemePack); |
| 453 // Scale factor parameter is moot as data pack has image resources for all | |
| 454 // supported scale factors. | |
| 386 pack->data_pack_.reset( | 455 pack->data_pack_.reset( |
| 387 new ui::DataPack(ui::SCALE_FACTOR_100P)); | 456 new ui::DataPack(ui::SCALE_FACTOR_NONE)); |
| 388 | 457 |
| 389 if (!pack->data_pack_->LoadFromPath(path)) { | 458 if (!pack->data_pack_->LoadFromPath(path)) { |
| 390 LOG(ERROR) << "Failed to load theme data pack."; | 459 LOG(ERROR) << "Failed to load theme data pack."; |
| 391 return NULL; | 460 return NULL; |
| 392 } | 461 } |
| 393 | 462 |
| 394 base::StringPiece pointer; | 463 base::StringPiece pointer; |
| 395 if (!pack->data_pack_->GetStringPiece(kHeaderID, &pointer)) | 464 if (!pack->data_pack_->GetStringPiece(kHeaderID, &pointer)) |
| 396 return NULL; | 465 return NULL; |
| 397 pack->header_ = reinterpret_cast<BrowserThemePackHeader*>(const_cast<char*>( | 466 pack->header_ = reinterpret_cast<BrowserThemePackHeader*>(const_cast<char*>( |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 423 if (!pack->data_pack_->GetStringPiece(kDisplayPropertiesID, &pointer)) | 492 if (!pack->data_pack_->GetStringPiece(kDisplayPropertiesID, &pointer)) |
| 424 return NULL; | 493 return NULL; |
| 425 pack->display_properties_ = reinterpret_cast<DisplayPropertyPair*>( | 494 pack->display_properties_ = reinterpret_cast<DisplayPropertyPair*>( |
| 426 const_cast<char*>(pointer.data())); | 495 const_cast<char*>(pointer.data())); |
| 427 | 496 |
| 428 if (!pack->data_pack_->GetStringPiece(kSourceImagesID, &pointer)) | 497 if (!pack->data_pack_->GetStringPiece(kSourceImagesID, &pointer)) |
| 429 return NULL; | 498 return NULL; |
| 430 pack->source_images_ = reinterpret_cast<int*>( | 499 pack->source_images_ = reinterpret_cast<int*>( |
| 431 const_cast<char*>(pointer.data())); | 500 const_cast<char*>(pointer.data())); |
| 432 | 501 |
| 502 if (!pack->data_pack_->GetStringPiece(kScaleFactorsID, &pointer)) | |
| 503 return NULL; | |
| 504 | |
| 505 if (!InputScalesValid(const_cast<char*>(pointer.data()), | |
| 506 pack->scale_factors_)) { | |
| 507 DLOG(ERROR) << "BuildFromDataPack failure! The pack scale factors differ " | |
| 508 << "from those supported by platform."; | |
| 509 } | |
| 510 | |
| 433 return pack; | 511 return pack; |
| 434 } | 512 } |
| 435 | 513 |
| 436 bool BrowserThemePack::WriteToDisk(const FilePath& path) const { | 514 bool BrowserThemePack::WriteToDisk(const FilePath& path) const { |
| 437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 515 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 438 // Add resources for each of the property arrays. | 516 // Add resources for each of the property arrays. |
| 439 RawDataForWriting resources; | 517 RawDataForWriting resources; |
| 440 resources[kHeaderID] = base::StringPiece( | 518 resources[kHeaderID] = base::StringPiece( |
| 441 reinterpret_cast<const char*>(header_), sizeof(BrowserThemePackHeader)); | 519 reinterpret_cast<const char*>(header_), sizeof(BrowserThemePackHeader)); |
| 442 resources[kTintsID] = base::StringPiece( | 520 resources[kTintsID] = base::StringPiece( |
| 443 reinterpret_cast<const char*>(tints_), sizeof(TintEntry[kTintArraySize])); | 521 reinterpret_cast<const char*>(tints_), sizeof(TintEntry[kTintArraySize])); |
| 444 resources[kColorsID] = base::StringPiece( | 522 resources[kColorsID] = base::StringPiece( |
| 445 reinterpret_cast<const char*>(colors_), | 523 reinterpret_cast<const char*>(colors_), |
| 446 sizeof(ColorPair[kColorArraySize])); | 524 sizeof(ColorPair[kColorArraySize])); |
| 447 resources[kDisplayPropertiesID] = base::StringPiece( | 525 resources[kDisplayPropertiesID] = base::StringPiece( |
| 448 reinterpret_cast<const char*>(display_properties_), | 526 reinterpret_cast<const char*>(display_properties_), |
| 449 sizeof(DisplayPropertyPair[kDisplayPropertySize])); | 527 sizeof(DisplayPropertyPair[kDisplayPropertySize])); |
| 450 | 528 |
| 451 int source_count = 1; | 529 int source_count = 1; |
| 452 int* end = source_images_; | 530 int* end = source_images_; |
| 453 for (; *end != -1 ; end++) | 531 for (; *end != -1 ; end++) |
| 454 source_count++; | 532 source_count++; |
| 455 resources[kSourceImagesID] = base::StringPiece( | 533 resources[kSourceImagesID] = base::StringPiece( |
| 456 reinterpret_cast<const char*>(source_images_), | 534 reinterpret_cast<const char*>(source_images_), |
| 457 source_count * sizeof(*source_images_)); | 535 source_count * sizeof(*source_images_)); |
| 458 | 536 |
| 537 resources[kScaleFactorsID] = GetScaleFactorsAsString(scale_factors_); | |
| 538 | |
| 459 AddRawImagesTo(image_memory_, &resources); | 539 AddRawImagesTo(image_memory_, &resources); |
| 460 | 540 |
| 461 RawImages reencoded_images; | 541 RawImages reencoded_images; |
| 462 RepackImages(prepared_images_, &reencoded_images); | 542 RepackImages(images_on_file_thread_, &reencoded_images); |
| 463 AddRawImagesTo(reencoded_images, &resources); | 543 AddRawImagesTo(reencoded_images, &resources); |
| 464 | 544 |
| 465 return ui::DataPack::WritePack(path, resources, ui::DataPack::BINARY); | 545 return ui::DataPack::WritePack(path, resources, ui::DataPack::BINARY); |
| 466 } | 546 } |
| 467 | 547 |
| 468 bool BrowserThemePack::GetTint(int id, color_utils::HSL* hsl) const { | 548 bool BrowserThemePack::GetTint(int id, color_utils::HSL* hsl) const { |
| 469 if (tints_) { | 549 if (tints_) { |
| 470 for (int i = 0; i < kTintArraySize; ++i) { | 550 for (int i = 0; i < kTintArraySize; ++i) { |
| 471 if (tints_[i].id == id) { | 551 if (tints_[i].id == id) { |
| 472 hsl->h = tints_[i].h; | 552 hsl->h = tints_[i].h; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 515 // to avoid changing the BrowserThemePack::GetBitmapNamed API. Once we | 595 // to avoid changing the BrowserThemePack::GetBitmapNamed API. Once we |
| 516 // switch to using gfx::Image everywhere this can be removed. | 596 // switch to using gfx::Image everywhere this can be removed. |
| 517 return const_cast<SkBitmap*>(image->ToSkBitmap()); | 597 return const_cast<SkBitmap*>(image->ToSkBitmap()); |
| 518 } | 598 } |
| 519 | 599 |
| 520 const gfx::Image* BrowserThemePack::GetImageNamed(int idr_id) const { | 600 const gfx::Image* BrowserThemePack::GetImageNamed(int idr_id) const { |
| 521 int prs_id = GetPersistentIDByIDR(idr_id); | 601 int prs_id = GetPersistentIDByIDR(idr_id); |
| 522 if (prs_id == -1) | 602 if (prs_id == -1) |
| 523 return NULL; | 603 return NULL; |
| 524 | 604 |
| 525 // Check our cache of prepared images, first. | 605 // Check if the image is cached. |
| 526 ImageCache::const_iterator image_iter = prepared_images_.find(prs_id); | 606 ImageCache::const_iterator image_iter = images_on_ui_thread_.find(prs_id); |
| 527 if (image_iter != prepared_images_.end()) | 607 if (image_iter != images_on_ui_thread_.end()) |
| 528 return image_iter->second; | 608 return image_iter->second; |
| 529 | 609 |
| 530 // Check if we've already loaded this image. | 610 // TODO(pkotwicz): Do something better than loading the bitmaps |
| 531 image_iter = loaded_images_.find(prs_id); | 611 // for all the scale factors associated with |idr_id|. |
| 532 if (image_iter != loaded_images_.end()) | 612 gfx::ImageSkia image_skia; |
| 533 return image_iter->second; | 613 for (size_t i = 0; i < scale_factors_.size(); ++i) { |
| 614 scoped_refptr<base::RefCountedMemory> memory = | |
| 615 GetRawData(idr_id, scale_factors_[i]); | |
| 534 | 616 |
| 535 scoped_refptr<base::RefCountedMemory> memory; | 617 if (memory.get()) { |
| 536 if (data_pack_.get()) { | 618 // Decode the PNG. |
| 537 memory = data_pack_->GetStaticMemory(prs_id); | 619 SkBitmap bitmap; |
| 538 } else { | 620 if (!gfx::PNGCodec::Decode(memory->front(), memory->size(), |
| 539 RawImages::const_iterator it = image_memory_.find(prs_id); | 621 &bitmap)) { |
| 540 if (it != image_memory_.end()) { | 622 NOTREACHED() << "Unable to decode theme image resource " << idr_id |
| 541 memory = it->second; | 623 << " from saved DataPack."; |
| 624 return NULL; | |
| 625 } | |
| 626 image_skia.AddRepresentation( | |
| 627 gfx::ImageSkiaRep(bitmap, scale_factors_[i])); | |
| 542 } | 628 } |
| 543 } | 629 } |
| 544 | 630 |
| 545 if (memory.get()) { | 631 if (!image_skia.isNull()) { |
| 546 // Decode the PNG. | 632 gfx::Image* ret = new gfx::Image(image_skia); |
| 547 SkBitmap bitmap; | 633 images_on_ui_thread_[prs_id] = ret; |
| 548 if (!gfx::PNGCodec::Decode(memory->front(), memory->size(), | |
| 549 &bitmap)) { | |
| 550 NOTREACHED() << "Unable to decode theme image resource " << idr_id | |
| 551 << " from saved DataPack."; | |
| 552 return NULL; | |
| 553 } | |
| 554 | |
| 555 gfx::Image* ret = new gfx::Image(bitmap); | |
| 556 loaded_images_[prs_id] = ret; | |
| 557 | |
| 558 return ret; | 634 return ret; |
| 559 } | 635 } |
| 560 | 636 |
| 561 return NULL; | 637 return NULL; |
| 562 } | 638 } |
| 563 | 639 |
| 564 base::RefCountedMemory* BrowserThemePack::GetRawData(int idr_id) const { | 640 base::RefCountedMemory* BrowserThemePack::GetRawData( |
| 641 int idr_id, | |
| 642 ui::ScaleFactor scale_factor) const { | |
| 565 base::RefCountedMemory* memory = NULL; | 643 base::RefCountedMemory* memory = NULL; |
| 566 int prs_id = GetPersistentIDByIDR(idr_id); | 644 int prs_id = GetPersistentIDByIDR(idr_id); |
| 645 int raw_id = GetRawIDByPersistentID(prs_id, scale_factor); | |
| 567 | 646 |
| 568 if (prs_id != -1) { | 647 if (raw_id != -1) { |
| 569 if (data_pack_.get()) { | 648 if (data_pack_.get()) { |
| 570 memory = data_pack_->GetStaticMemory(prs_id); | 649 memory = data_pack_->GetStaticMemory(raw_id); |
| 571 } else { | 650 } else { |
| 572 RawImages::const_iterator it = image_memory_.find(prs_id); | 651 RawImages::const_iterator it = image_memory_.find(raw_id); |
| 573 if (it != image_memory_.end()) { | 652 if (it != image_memory_.end()) { |
| 574 memory = it->second; | 653 memory = it->second; |
| 575 } | 654 } |
| 576 } | 655 } |
| 577 } | 656 } |
| 578 | 657 |
| 579 return memory; | 658 return memory; |
| 580 } | 659 } |
| 581 | 660 |
| 582 bool BrowserThemePack::HasCustomImage(int idr_id) const { | 661 bool BrowserThemePack::HasCustomImage(int idr_id) const { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 593 return false; | 672 return false; |
| 594 } | 673 } |
| 595 | 674 |
| 596 // private: | 675 // private: |
| 597 | 676 |
| 598 BrowserThemePack::BrowserThemePack() | 677 BrowserThemePack::BrowserThemePack() |
| 599 : header_(NULL), | 678 : header_(NULL), |
| 600 tints_(NULL), | 679 tints_(NULL), |
| 601 colors_(NULL), | 680 colors_(NULL), |
| 602 display_properties_(NULL), | 681 display_properties_(NULL), |
| 603 source_images_(NULL) { | 682 source_images_(NULL), |
| 683 scale_factors_(ui::GetSupportedScaleFactors()) { | |
| 604 } | 684 } |
| 605 | 685 |
| 606 void BrowserThemePack::BuildHeader(const Extension* extension) { | 686 void BrowserThemePack::BuildHeader(const Extension* extension) { |
| 607 header_ = new BrowserThemePackHeader; | 687 header_ = new BrowserThemePackHeader; |
| 608 header_->version = kThemePackVersion; | 688 header_->version = kThemePackVersion; |
| 609 | 689 |
| 610 // TODO(erg): Need to make this endian safe on other computers. Prerequisite | 690 // TODO(erg): Need to make this endian safe on other computers. Prerequisite |
| 611 // is that ui::DataPack removes this same check. | 691 // is that ui::DataPack removes this same check. |
| 612 #if defined(__BYTE_ORDER) | 692 #if defined(__BYTE_ORDER) |
| 613 // Linux check | 693 // Linux check |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 860 ids.push_back(it->first); | 940 ids.push_back(it->first); |
| 861 } | 941 } |
| 862 | 942 |
| 863 source_images_ = new int[ids.size() + 1]; | 943 source_images_ = new int[ids.size() + 1]; |
| 864 std::copy(ids.begin(), ids.end(), source_images_); | 944 std::copy(ids.begin(), ids.end(), source_images_); |
| 865 source_images_[ids.size()] = -1; | 945 source_images_[ids.size()] = -1; |
| 866 } | 946 } |
| 867 | 947 |
| 868 bool BrowserThemePack::LoadRawBitmapsTo( | 948 bool BrowserThemePack::LoadRawBitmapsTo( |
| 869 const FilePathMap& file_paths, | 949 const FilePathMap& file_paths, |
| 870 ImageCache* raw_bitmaps) { | 950 ImageCache* image_cache) { |
| 871 // Themes should be loaded on the file thread, not the UI thread. | 951 // Themes should be loaded on the file thread, not the UI thread. |
| 872 // http://crbug.com/61838 | 952 // http://crbug.com/61838 |
| 873 base::ThreadRestrictions::ScopedAllowIO allow_io; | 953 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 874 | 954 |
| 875 for (FilePathMap::const_iterator it = file_paths.begin(); | 955 for (FilePathMap::const_iterator it = file_paths.begin(); |
| 876 it != file_paths.end(); ++it) { | 956 it != file_paths.end(); ++it) { |
| 877 scoped_refptr<base::RefCountedMemory> raw_data(ReadFileData(it->second)); | 957 scoped_refptr<base::RefCountedMemory> raw_data(ReadFileData(it->second)); |
| 878 if (!raw_data.get()) { | 958 if (!raw_data.get()) { |
| 879 LOG(ERROR) << "Could not load theme image"; | 959 LOG(ERROR) << "Could not load theme image"; |
| 880 return false; | 960 return false; |
| 881 } | 961 } |
| 882 | 962 |
| 883 int id = it->first; | 963 int prs_id = it->first; |
| 884 | 964 |
| 885 // Some images need to go directly into |image_memory_|. No modification is | 965 // Some images need to go directly into |image_memory_|. No modification is |
| 886 // necessary or desirable. | 966 // necessary or desirable. |
| 887 bool is_copyable = false; | 967 bool is_copyable = false; |
| 888 for (size_t i = 0; i < arraysize(kPreloadIDs); ++i) { | 968 for (size_t i = 0; i < arraysize(kPreloadIDs); ++i) { |
| 889 if (kPreloadIDs[i] == id) { | 969 if (kPreloadIDs[i] == prs_id) { |
| 890 is_copyable = true; | 970 is_copyable = true; |
| 891 break; | 971 break; |
| 892 } | 972 } |
| 893 } | 973 } |
| 894 | 974 |
| 895 if (is_copyable) { | 975 if (is_copyable) { |
| 896 image_memory_[id] = raw_data; | 976 int raw_id = GetRawIDByPersistentID(prs_id, ui::SCALE_FACTOR_100P); |
| 977 image_memory_[raw_id] = raw_data; | |
| 897 } else if (raw_data.get() && raw_data->size()) { | 978 } else if (raw_data.get() && raw_data->size()) { |
| 898 // Decode the PNG. | 979 // Decode the PNG. |
| 899 SkBitmap bitmap; | 980 SkBitmap bitmap; |
| 900 if (gfx::PNGCodec::Decode(raw_data->front(), raw_data->size(), | 981 if (gfx::PNGCodec::Decode(raw_data->front(), raw_data->size(), |
| 901 &bitmap)) { | 982 &bitmap)) { |
| 902 (*raw_bitmaps)[it->first] = new gfx::Image(bitmap); | 983 (*image_cache)[prs_id] = new gfx::Image(bitmap); |
| 903 } else { | 984 } else { |
| 904 NOTREACHED() << "Unable to decode theme image resource " << it->first; | 985 NOTREACHED() << "Unable to decode theme image resource " << it->first; |
| 905 } | 986 } |
| 906 } | 987 } |
| 907 } | 988 } |
| 908 | 989 |
| 909 return true; | 990 return true; |
| 910 } | 991 } |
| 911 | 992 |
| 912 void BrowserThemePack::GenerateFrameImages(ImageCache* bitmaps) const { | 993 void BrowserThemePack::CreateImages(ImageCache* images) const { |
| 994 CreateFrameImages(images); | |
| 995 CreateTintedButtons(GetTintInternal(ThemeService::TINT_BUTTONS), images); | |
| 996 CreateTabBackgroundImages(images); | |
| 997 } | |
| 998 | |
| 999 void BrowserThemePack::CreateFrameImages(ImageCache* images) const { | |
| 913 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 1000 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 914 | 1001 |
| 915 // Create all the output bitmaps in a separate cache and move them back into | 1002 // Create all the output images in a separate cache and move them back into |
| 916 // the input bitmaps because there can be name collisions. | 1003 // the input images because there can be name collisions. |
| 917 ImageCache temp_output; | 1004 ImageCache temp_output; |
| 918 | 1005 |
| 919 for (size_t i = 0; i < arraysize(kFrameTintMap); ++i) { | 1006 for (size_t i = 0; i < arraysize(kFrameTintMap); ++i) { |
| 920 int prs_id = kFrameTintMap[i].key; | 1007 int prs_id = kFrameTintMap[i].key; |
| 921 const gfx::Image* frame = NULL; | 1008 const gfx::Image* frame = NULL; |
| 922 // If there's no frame image provided for the specified id, then load | 1009 // If there's no frame image provided for the specified id, then load |
| 923 // the default provided frame. If that's not provided, skip this whole | 1010 // the default provided frame. If that's not provided, skip this whole |
| 924 // thing and just use the default images. | 1011 // thing and just use the default images. |
| 925 int prs_base_id; | 1012 int prs_base_id; |
| 926 | 1013 |
| 927 if (prs_id == PRS_THEME_FRAME_INCOGNITO_INACTIVE) { | 1014 if (prs_id == PRS_THEME_FRAME_INCOGNITO_INACTIVE) { |
| 928 prs_base_id = bitmaps->count(PRS_THEME_FRAME_INCOGNITO) ? | 1015 prs_base_id = images->count(PRS_THEME_FRAME_INCOGNITO) ? |
| 929 PRS_THEME_FRAME_INCOGNITO : PRS_THEME_FRAME; | 1016 PRS_THEME_FRAME_INCOGNITO : PRS_THEME_FRAME; |
| 930 } else if (prs_id == PRS_THEME_FRAME_OVERLAY_INACTIVE) { | 1017 } else if (prs_id == PRS_THEME_FRAME_OVERLAY_INACTIVE) { |
| 931 prs_base_id = PRS_THEME_FRAME_OVERLAY; | 1018 prs_base_id = PRS_THEME_FRAME_OVERLAY; |
| 932 } else if (prs_id == PRS_THEME_FRAME_INACTIVE) { | 1019 } else if (prs_id == PRS_THEME_FRAME_INACTIVE) { |
| 933 prs_base_id = PRS_THEME_FRAME; | 1020 prs_base_id = PRS_THEME_FRAME; |
| 934 } else if (prs_id == PRS_THEME_FRAME_INCOGNITO && | 1021 } else if (prs_id == PRS_THEME_FRAME_INCOGNITO && |
| 935 !bitmaps->count(PRS_THEME_FRAME_INCOGNITO)) { | 1022 !images->count(PRS_THEME_FRAME_INCOGNITO)) { |
| 936 prs_base_id = PRS_THEME_FRAME; | 1023 prs_base_id = PRS_THEME_FRAME; |
| 937 } else { | 1024 } else { |
| 938 prs_base_id = prs_id; | 1025 prs_base_id = prs_id; |
| 939 } | 1026 } |
| 940 | 1027 |
| 941 if (bitmaps->count(prs_id)) { | 1028 if (images->count(prs_id)) { |
| 942 frame = (*bitmaps)[prs_id]; | 1029 frame = (*images)[prs_id]; |
| 943 } else if (prs_base_id != prs_id && bitmaps->count(prs_base_id)) { | 1030 } else if (prs_base_id != prs_id && images->count(prs_base_id)) { |
| 944 frame = (*bitmaps)[prs_base_id]; | 1031 frame = (*images)[prs_base_id]; |
| 945 } else if (prs_base_id == PRS_THEME_FRAME_OVERLAY && | 1032 } else if (prs_base_id == PRS_THEME_FRAME_OVERLAY && |
| 946 bitmaps->count(PRS_THEME_FRAME)) { | 1033 images->count(PRS_THEME_FRAME)) { |
| 947 // If there is no theme overlay, don't tint the default frame, | 1034 // If there is no theme overlay, don't tint the default frame, |
| 948 // because it will overwrite the custom frame image when we cache and | 1035 // because it will overwrite the custom frame image when we cache and |
| 949 // reload from disk. | 1036 // reload from disk. |
| 950 frame = NULL; | 1037 frame = NULL; |
| 951 } else { | 1038 } else { |
| 952 // If the theme doesn't specify an image, then apply the tint to | 1039 // If the theme doesn't specify an image, then apply the tint to |
| 953 // the default frame. | 1040 // the default frame. |
| 954 frame = &rb.GetImageNamed(IDR_THEME_FRAME); | 1041 frame = &rb.GetImageNamed(IDR_THEME_FRAME); |
| 955 } | 1042 } |
| 956 | 1043 |
| 957 if (frame) { | 1044 if (frame) { |
| 958 temp_output[prs_id] = CreateHSLShiftedImage( | 1045 temp_output[prs_id] = CreateHSLShiftedImage( |
| 959 *frame, GetTintInternal(kFrameTintMap[i].value)); | 1046 *frame, GetTintInternal(kFrameTintMap[i].value)); |
| 960 } | 1047 } |
| 961 } | 1048 } |
| 962 | 1049 MergeImageCaches(temp_output, images); |
| 963 MergeImageCaches(temp_output, bitmaps); | |
| 964 } | 1050 } |
| 965 | 1051 |
| 966 void BrowserThemePack::GenerateTintedButtons( | 1052 void BrowserThemePack::CreateTintedButtons( |
| 967 const color_utils::HSL& button_tint, | 1053 const color_utils::HSL& button_tint, |
| 968 ImageCache* processed_bitmaps) const { | 1054 ImageCache* processed_images) const { |
| 969 if (button_tint.h != -1 || button_tint.s != -1 || button_tint.l != -1) { | 1055 if (button_tint.h != -1 || button_tint.s != -1 || button_tint.l != -1) { |
| 970 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 1056 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 971 const std::set<int>& idr_ids = | 1057 const std::set<int>& idr_ids = |
| 972 ThemeService::GetTintableToolbarButtons(); | 1058 ThemeService::GetTintableToolbarButtons(); |
| 973 for (std::set<int>::const_iterator it = idr_ids.begin(); | 1059 for (std::set<int>::const_iterator it = idr_ids.begin(); |
| 974 it != idr_ids.end(); ++it) { | 1060 it != idr_ids.end(); ++it) { |
| 975 int prs_id = GetPersistentIDByIDR(*it); | 1061 int prs_id = GetPersistentIDByIDR(*it); |
| 976 DCHECK(prs_id > 0); | 1062 DCHECK(prs_id > 0); |
| 977 | 1063 |
| 978 // Fetch the image by IDR... | 1064 // Fetch the image by IDR... |
| 979 gfx::Image& button = rb.GetImageNamed(*it); | 1065 gfx::Image& button = rb.GetImageNamed(*it); |
| 980 | 1066 |
| 981 // but save a version with the persistent ID. | 1067 // but save a version with the persistent ID. |
| 982 (*processed_bitmaps)[prs_id] = | 1068 (*processed_images)[prs_id] = |
| 983 CreateHSLShiftedImage(button, button_tint); | 1069 CreateHSLShiftedImage(button, button_tint); |
| 984 } | 1070 } |
| 985 } | 1071 } |
| 986 } | 1072 } |
| 987 | 1073 |
| 988 void BrowserThemePack::GenerateTabBackgroundImages(ImageCache* bitmaps) const { | 1074 void BrowserThemePack::CreateTabBackgroundImages(ImageCache* images) const { |
| 989 ImageCache temp_output; | 1075 ImageCache temp_output; |
| 990 for (size_t i = 0; i < arraysize(kTabBackgroundMap); ++i) { | 1076 for (size_t i = 0; i < arraysize(kTabBackgroundMap); ++i) { |
| 991 int prs_id = kTabBackgroundMap[i].key; | 1077 int prs_id = kTabBackgroundMap[i].key; |
| 992 int prs_base_id = kTabBackgroundMap[i].value; | 1078 int prs_base_id = kTabBackgroundMap[i].value; |
| 993 | 1079 |
| 994 // We only need to generate the background tab images if we were provided | 1080 // We only need to generate the background tab images if we were provided |
| 995 // with a PRS_THEME_FRAME. | 1081 // with a PRS_THEME_FRAME. |
| 996 ImageCache::const_iterator it = bitmaps->find(prs_base_id); | 1082 ImageCache::const_iterator it = images->find(prs_base_id); |
| 997 if (it != bitmaps->end()) { | 1083 if (it != images->end()) { |
| 998 const gfx::ImageSkia* image_to_tint = (it->second)->ToImageSkia(); | 1084 const gfx::ImageSkia* image_to_tint = (it->second)->ToImageSkia(); |
| 999 const std::vector<gfx::ImageSkiaRep> image_reps_to_tint = | 1085 color_utils::HSL hsl_shift = GetTintInternal( |
| 1000 image_to_tint->image_reps(); | 1086 ThemeService::TINT_BACKGROUND_TAB); |
| 1001 gfx::ImageSkia tinted_image; | 1087 int vertical_offset = images->count(prs_id) |
| 1002 for (size_t j = 0; j < image_reps_to_tint.size(); ++j) { | 1088 ? kRestoredTabVerticalOffset : 0; |
| 1003 gfx::ImageSkiaRep image_rep_to_tint = image_reps_to_tint[j]; | |
| 1004 SkBitmap bg_tint = SkBitmapOperations::CreateHSLShiftedBitmap( | |
| 1005 image_rep_to_tint.sk_bitmap(), GetTintInternal( | |
| 1006 ThemeService::TINT_BACKGROUND_TAB)); | |
| 1007 gfx::Size bg_tint_dip_size(image_rep_to_tint.GetWidth(), | |
| 1008 image_rep_to_tint.GetHeight()); | |
| 1009 int vertical_offset = bitmaps->count(prs_id) | |
| 1010 ? kRestoredTabVerticalOffset : 0; | |
| 1011 gfx::Canvas canvas(gfx::Size(bg_tint.width(), bg_tint.height()), | |
| 1012 false); | |
| 1013 SkScalar image_rep_to_tint_scale = | |
| 1014 SkFloatToScalar(image_rep_to_tint.GetScale()); | |
| 1015 canvas.sk_canvas()->scale(image_rep_to_tint_scale, | |
| 1016 image_rep_to_tint_scale); | |
| 1017 canvas.TileImageInt(bg_tint, 0, vertical_offset, 0, 0, | |
| 1018 bg_tint_dip_size.width(), bg_tint_dip_size.height()); | |
| 1019 | 1089 |
| 1020 // If they've provided a custom image, overlay it. | 1090 gfx::ImageSkia overlay; |
| 1021 ImageCache::const_iterator overlay_it = bitmaps->find(prs_id); | 1091 ImageCache::const_iterator overlay_it = images->find(prs_id); |
| 1022 if (overlay_it != bitmaps->end()) { | 1092 if (overlay_it != images->end()) |
| 1023 const gfx::ImageSkia* overlay = overlay_it->second->ToImageSkia(); | 1093 overlay = *overlay_it->second->ToImageSkia(); |
| 1024 canvas.TileImageInt(*overlay, 0, 0, bg_tint_dip_size.width(), | |
| 1025 overlay->height()); | |
| 1026 } | |
| 1027 SkBitmap bg_tab = canvas.ExtractBitmap(); | |
| 1028 tinted_image.AddRepresentation(gfx::ImageSkiaRep(bg_tab, | |
| 1029 image_rep_to_tint.scale_factor())); | |
| 1030 } | |
| 1031 | 1094 |
| 1032 temp_output[prs_id] = new gfx::Image(tinted_image); | 1095 gfx::ImageSkiaSource* source = new TabBackgroundImageSource( |
| 1096 *image_to_tint, overlay, hsl_shift, vertical_offset); | |
| 1097 // ImageSkia takes ownership of |source|. | |
| 1098 temp_output[prs_id] = new gfx::Image(gfx::ImageSkia(source, | |
| 1099 image_to_tint->size())); | |
| 1033 } | 1100 } |
| 1034 } | 1101 } |
| 1035 | 1102 MergeImageCaches(temp_output, images); |
| 1036 MergeImageCaches(temp_output, bitmaps); | |
| 1037 } | 1103 } |
| 1038 | 1104 |
| 1039 void BrowserThemePack::RepackImages(const ImageCache& images, | 1105 void BrowserThemePack::RepackImages(const ImageCache& images, |
| 1040 RawImages* reencoded_images) const { | 1106 RawImages* reencoded_images) const { |
| 1107 | |
| 1041 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 1108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 1109 | |
| 1110 typedef std::vector<ui::ScaleFactor> ScaleFactors; | |
| 1111 ScaleFactors scale_factors = ui::GetSupportedScaleFactors(); | |
| 1112 | |
| 1042 for (ImageCache::const_iterator it = images.begin(); | 1113 for (ImageCache::const_iterator it = images.begin(); |
| 1043 it != images.end(); ++it) { | 1114 it != images.end(); ++it) { |
| 1044 std::vector<unsigned char> image_data; | 1115 gfx::ImageSkia image_skia = *it->second->ToImageSkia(); |
| 1045 if (!gfx::PNGCodec::EncodeBGRASkBitmap(*it->second->ToSkBitmap(), false, | 1116 |
| 1046 &image_data)) { | 1117 // Attempt to generate image reps for all supported scale factors. |
| 1118 for (ScaleFactors::iterator factor_it = scale_factors.begin(); | |
| 1119 factor_it != scale_factors.end(); ++factor_it) { | |
| 1120 // Ask for representation to force the reprsentation to be generated | |
| 1121 // if it hasn't already. | |
| 1122 image_skia.GetRepresentation(*factor_it); | |
| 1123 } | |
| 1124 | |
| 1125 typedef std::vector<gfx::ImageSkiaRep> ImageSkiaReps; | |
| 1126 ImageSkiaReps image_reps = image_skia.image_reps(); | |
| 1127 if (image_reps.empty()) { | |
| 1047 NOTREACHED() << "Image file for resource " << it->first | 1128 NOTREACHED() << "Image file for resource " << it->first |
| 1048 << " could not be encoded."; | 1129 << " could not be encoded."; |
| 1049 } else { | 1130 } |
| 1050 (*reencoded_images)[it->first] = | 1131 for (ImageSkiaReps::iterator rep_it = image_reps.begin(); |
| 1132 rep_it != image_reps.end(); ++rep_it) { | |
| 1133 std::vector<unsigned char> image_data; | |
| 1134 CHECK(gfx::PNGCodec::EncodeBGRASkBitmap(rep_it->sk_bitmap(), false, | |
| 1135 &image_data)); | |
| 1136 int raw_id = GetRawIDByPersistentID(it->first, rep_it->scale_factor()); | |
| 1137 (*reencoded_images)[raw_id] = | |
| 1051 base::RefCountedBytes::TakeVector(&image_data); | 1138 base::RefCountedBytes::TakeVector(&image_data); |
| 1052 } | 1139 } |
| 1053 } | 1140 } |
| 1054 } | 1141 } |
| 1055 | 1142 |
| 1143 void BrowserThemePack::GenerateImageReps( | |
| 1144 const std::vector<ui::ScaleFactor>& scale_factors) { | |
|
Elliot Glaysher
2012/07/20 18:17:14
Could you add a thread dcheck here? I see you modi
pkotwicz
2012/07/20 20:00:45
Will do! It is supposed to run on the UI thread
| |
| 1145 for (ImageCache::const_iterator it = images_on_ui_thread_.begin(); | |
| 1146 it != images_on_ui_thread_.end(); | |
| 1147 ++it) { | |
| 1148 const gfx::ImageSkia* image1 = it->second->ToImageSkia(); | |
| 1149 const gfx::ImageSkia* image2 = | |
| 1150 images_on_file_thread_[it->first]->ToImageSkia(); | |
| 1151 | |
| 1152 // Ensure that image reps are generated and cached in |image1| by | |
| 1153 // calling GetRepresentation(). | |
| 1154 for (size_t i = 0; i < scale_factors.size(); ++i) | |
| 1155 image1->GetRepresentation(scale_factors[i]); | |
| 1156 | |
| 1157 // |image1| and |image2| have ImageSkiaSources which produce pixel | |
| 1158 // equivalent output. Instead of regenerating again, copy the image reps | |
| 1159 // which were generated for |image1| into |image2|. | |
| 1160 // Don't do a deep copy of the SkBitmaps as SkBitmap is thread safe. | |
| 1161 std::vector<gfx::ImageSkiaRep> image1_reps = image1->image_reps(); | |
| 1162 for (size_t i = 0; i < image1_reps.size(); ++i) { | |
| 1163 gfx::ImageSkiaRep image1_rep = image1_reps[i]; | |
| 1164 const_cast<gfx::ImageSkia*>(image2)->AddRepresentation(gfx::ImageSkiaRep( | |
| 1165 image1_rep.sk_bitmap(), image1_rep.scale_factor())); | |
| 1166 } | |
| 1167 } | |
| 1168 } | |
| 1169 | |
| 1056 void BrowserThemePack::MergeImageCaches( | 1170 void BrowserThemePack::MergeImageCaches( |
| 1057 const ImageCache& source, ImageCache* destination) const { | 1171 const ImageCache& source, ImageCache* destination) const { |
| 1058 for (ImageCache::const_iterator it = source.begin(); it != source.end(); | 1172 for (ImageCache::const_iterator it = source.begin(); it != source.end(); |
| 1059 ++it) { | 1173 ++it) { |
| 1060 ImageCache::const_iterator bitmap_it = destination->find(it->first); | 1174 ImageCache::const_iterator image_it = destination->find(it->first); |
| 1061 if (bitmap_it != destination->end()) | 1175 if (image_it != destination->end()) |
| 1062 delete bitmap_it->second; | 1176 delete image_it->second; |
| 1063 | 1177 |
| 1064 (*destination)[it->first] = it->second; | 1178 (*destination)[it->first] = it->second; |
| 1065 } | 1179 } |
| 1066 } | 1180 } |
| 1067 | 1181 |
| 1182 void BrowserThemePack::CopyImagesTo(const ImageCache& source, | |
| 1183 ImageCache* destination) const { | |
| 1184 for (ImageCache::const_iterator it = source.begin(); it != source.end(); | |
| 1185 ++it) { | |
| 1186 (*destination)[it->first] = new gfx::Image(*it->second); | |
| 1187 } | |
| 1188 } | |
| 1189 | |
| 1068 void BrowserThemePack::AddRawImagesTo(const RawImages& images, | 1190 void BrowserThemePack::AddRawImagesTo(const RawImages& images, |
| 1069 RawDataForWriting* out) const { | 1191 RawDataForWriting* out) const { |
| 1070 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 1192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 1071 for (RawImages::const_iterator it = images.begin(); it != images.end(); | 1193 for (RawImages::const_iterator it = images.begin(); it != images.end(); |
| 1072 ++it) { | 1194 ++it) { |
| 1073 (*out)[it->first] = base::StringPiece( | 1195 (*out)[it->first] = base::StringPiece( |
| 1074 reinterpret_cast<const char*>(it->second->front()), it->second->size()); | 1196 reinterpret_cast<const char*>(it->second->front()), it->second->size()); |
| 1075 } | 1197 } |
| 1076 } | 1198 } |
| 1077 | 1199 |
| 1078 color_utils::HSL BrowserThemePack::GetTintInternal(int id) const { | 1200 color_utils::HSL BrowserThemePack::GetTintInternal(int id) const { |
| 1079 if (tints_) { | 1201 if (tints_) { |
| 1080 for (int i = 0; i < kTintArraySize; ++i) { | 1202 for (int i = 0; i < kTintArraySize; ++i) { |
| 1081 if (tints_[i].id == id) { | 1203 if (tints_[i].id == id) { |
| 1082 color_utils::HSL hsl; | 1204 color_utils::HSL hsl; |
| 1083 hsl.h = tints_[i].h; | 1205 hsl.h = tints_[i].h; |
| 1084 hsl.s = tints_[i].s; | 1206 hsl.s = tints_[i].s; |
| 1085 hsl.l = tints_[i].l; | 1207 hsl.l = tints_[i].l; |
| 1086 return hsl; | 1208 return hsl; |
| 1087 } | 1209 } |
| 1088 } | 1210 } |
| 1089 } | 1211 } |
| 1090 | 1212 |
| 1091 return ThemeService::GetDefaultTint(id); | 1213 return ThemeService::GetDefaultTint(id); |
| 1092 } | 1214 } |
| 1215 | |
| 1216 int BrowserThemePack::GetRawIDByPersistentID( | |
| 1217 int prs_id, | |
| 1218 ui::ScaleFactor scale_factor) const { | |
| 1219 if (prs_id < 0) | |
| 1220 return -1; | |
| 1221 | |
| 1222 for (size_t i = 0; i < scale_factors_.size(); ++i) { | |
| 1223 if (scale_factors_[i] == scale_factor) | |
| 1224 return static_cast<int>(kPersistingImagesLength * i) + prs_id; | |
| 1225 } | |
| 1226 return -1; | |
| 1227 } | |
| OLD | NEW |