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" |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 473 canvas.drawBitmapRect(rep_100p.sk_bitmap(), NULL, resized_bounds); | 473 canvas.drawBitmapRect(rep_100p.sk_bitmap(), NULL, resized_bounds); |
| 474 return gfx::ImageSkiaRep(resized_bitmap, scale_factor); | 474 return gfx::ImageSkiaRep(resized_bitmap, scale_factor); |
| 475 } | 475 } |
| 476 | 476 |
| 477 private: | 477 private: |
| 478 const gfx::ImageSkia source_; | 478 const gfx::ImageSkia source_; |
| 479 | 479 |
| 480 DISALLOW_COPY_AND_ASSIGN(ThemeImageSource); | 480 DISALLOW_COPY_AND_ASSIGN(ThemeImageSource); |
| 481 }; | 481 }; |
| 482 | 482 |
| 483 // An ImageSkiaSouce that delays decoding PNG data into bitmaps until needed | |
| 484 // and, if necessary, generates bitmaps for scale factors for which no PNG was | |
| 485 // provided. The first PNG will be used to compute the DIP size and will | |
| 486 // therefore be decoded when added. Once a PNG is decoded the resulting bitmap | |
| 487 // is stored for later use. | |
| 488 class ThemeImagePngSource : public gfx::ImageSkiaSource { | |
| 489 public: | |
| 490 ThemeImagePngSource() {} | |
|
pkotwicz
2013/06/14 18:23:05
Ideally we should not even cache the PNG data for
| |
| 491 | |
| 492 void AddPng(scoped_refptr<base::RefCountedMemory> png_memory, | |
| 493 ui::ScaleFactor scale_factor) { | |
| 494 png_map_[scale_factor] = png_memory; | |
| 495 if (bitmap_map_.empty()) | |
| 496 init(png_memory, scale_factor); | |
| 497 } | |
| 498 | |
| 499 gfx::Size size() const { return dip_size_; } | |
| 500 | |
| 501 private: | |
| 502 void init(scoped_refptr<base::RefCountedMemory> png_memory, | |
| 503 ui::ScaleFactor scale_factor) { | |
| 504 SkBitmap bitmap; | |
| 505 if (!gfx::PNGCodec::Decode(png_memory->front(), | |
| 506 png_memory->size(), | |
| 507 &bitmap)) { | |
| 508 NOTREACHED(); | |
| 509 return; | |
| 510 } | |
| 511 bitmap_map_[scale_factor] = bitmap; | |
| 512 dip_size_ = gfx::Size( | |
| 513 static_cast<int>(bitmap.width() / | |
| 514 ui::GetScaleFactorScale(scale_factor)), | |
| 515 static_cast<int>(bitmap.height() / | |
| 516 ui::GetScaleFactorScale(scale_factor))); | |
| 517 } | |
| 518 | |
| 519 virtual gfx::ImageSkiaRep GetImageForScale( | |
| 520 ui::ScaleFactor scale_factor) OVERRIDE { | |
| 521 // Look up the scale factor in the bitmap map. If found, use the bitmap and | |
| 522 // return it. | |
| 523 BitmapMap::const_iterator exact_bitmap = bitmap_map_.find(scale_factor); | |
| 524 if (exact_bitmap != bitmap_map_.end()) { | |
| 525 return gfx::ImageSkiaRep(exact_bitmap->second, scale_factor); | |
| 526 } | |
| 527 | |
| 528 // Look up the scale factor in the png map. If found, decode it, | |
| 529 // store the result in the bitmap map and return it. | |
| 530 PngMap::const_iterator exact_png = png_map_.find(scale_factor); | |
| 531 if (exact_png != png_map_.end()) { | |
| 532 SkBitmap bitmap; | |
| 533 if (!gfx::PNGCodec::Decode(exact_png->second->front(), | |
| 534 exact_png->second->size(), | |
| 535 &bitmap)) { | |
| 536 NOTREACHED(); | |
| 537 return gfx::ImageSkiaRep(SkBitmap(), scale_factor); | |
| 538 } | |
| 539 bitmap_map_[scale_factor] = bitmap; | |
| 540 return gfx::ImageSkiaRep(bitmap, scale_factor); | |
| 541 } | |
| 542 | |
| 543 // No exact match was found, find the scale factor with highest scale. | |
| 544 PngMap::const_iterator available_png = png_map_.end(); | |
| 545 for (PngMap::const_iterator it = png_map_.begin(); it != png_map_.end(); | |
| 546 ++it) { | |
| 547 if (available_png == png_map_.end() || | |
| 548 (ui::GetScaleFactorScale(it->first) > | |
| 549 ui::GetScaleFactorScale(available_png->first))) { | |
| 550 available_png = it; | |
| 551 } | |
| 552 } | |
| 553 if (available_png == png_map_.end()) { | |
| 554 NOTREACHED(); | |
| 555 return gfx::ImageSkiaRep(SkBitmap(), scale_factor); | |
| 556 } | |
| 557 | |
| 558 // Look up the found scale factor in the bitmap map. If not found, decode | |
| 559 // the corresponding png and store the result in bitmap map. | |
| 560 BitmapMap::const_iterator available_bitmap = | |
| 561 bitmap_map_.find(available_png->first); | |
| 562 if (available_bitmap == bitmap_map_.end()) { | |
| 563 SkBitmap bitmap; | |
| 564 if (!gfx::PNGCodec::Decode(available_png->second->front(), | |
| 565 available_png->second->size(), | |
| 566 &bitmap)) { | |
| 567 NOTREACHED(); | |
| 568 return gfx::ImageSkiaRep(SkBitmap(), scale_factor); | |
| 569 } | |
| 570 bitmap_map_[available_png->first] = bitmap; | |
| 571 available_bitmap = bitmap_map_.find(available_png->first); | |
| 572 } | |
| 573 | |
| 574 // Use available bitmap to create bitmap for desired scale factor by | |
| 575 // scaling, store the result in the bitmap map and return it. | |
| 576 gfx::Size scaled_size = gfx::ToCeiledSize( | |
| 577 gfx::ScaleSize(gfx::Size(available_bitmap->second.width(), | |
| 578 available_bitmap->second.height()), | |
| 579 ui::GetScaleFactorScale(scale_factor) / | |
| 580 ui::GetScaleFactorScale(available_bitmap->first))); | |
| 581 SkBitmap scaled_bitmap; | |
| 582 scaled_bitmap.setConfig(SkBitmap::kARGB_8888_Config, | |
| 583 scaled_size.width(), | |
| 584 scaled_size.height()); | |
| 585 if (!scaled_bitmap.allocPixels()) | |
| 586 SK_CRASH(); | |
| 587 scaled_bitmap.eraseARGB(0, 0, 0, 0); | |
| 588 SkCanvas canvas(scaled_bitmap); | |
| 589 SkRect scaled_bounds = RectToSkRect(gfx::Rect(scaled_size)); | |
| 590 canvas.drawBitmapRect(available_bitmap->second, NULL, scaled_bounds); | |
| 591 bitmap_map_[scale_factor] = scaled_bitmap; | |
| 592 return gfx::ImageSkiaRep(scaled_bitmap, scale_factor); | |
| 593 } | |
| 594 | |
| 595 private: | |
| 596 typedef std::map<ui::ScaleFactor, | |
| 597 scoped_refptr<base::RefCountedMemory> > PngMap; | |
| 598 typedef std::map<ui::ScaleFactor, SkBitmap> BitmapMap; | |
| 599 PngMap png_map_; | |
| 600 BitmapMap bitmap_map_; | |
| 601 gfx::Size dip_size_; | |
| 602 }; | |
| 603 | |
| 483 class TabBackgroundImageSource: public gfx::CanvasImageSource { | 604 class TabBackgroundImageSource: public gfx::CanvasImageSource { |
| 484 public: | 605 public: |
| 485 TabBackgroundImageSource(const gfx::ImageSkia& image_to_tint, | 606 TabBackgroundImageSource(const gfx::ImageSkia& image_to_tint, |
| 486 const gfx::ImageSkia& overlay, | 607 const gfx::ImageSkia& overlay, |
| 487 const color_utils::HSL& hsl_shift, | 608 const color_utils::HSL& hsl_shift, |
| 488 int vertical_offset) | 609 int vertical_offset) |
| 489 : gfx::CanvasImageSource(image_to_tint.size(), false), | 610 : gfx::CanvasImageSource(image_to_tint.size(), false), |
| 490 image_to_tint_(image_to_tint), | 611 image_to_tint_(image_to_tint), |
| 491 overlay_(overlay), | 612 overlay_(overlay), |
| 492 hsl_shift_(hsl_shift), | 613 hsl_shift_(hsl_shift), |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 742 gfx::Image BrowserThemePack::GetImageNamed(int idr_id) { | 863 gfx::Image BrowserThemePack::GetImageNamed(int idr_id) { |
| 743 int prs_id = GetPersistentIDByIDR(idr_id); | 864 int prs_id = GetPersistentIDByIDR(idr_id); |
| 744 if (prs_id == -1) | 865 if (prs_id == -1) |
| 745 return gfx::Image(); | 866 return gfx::Image(); |
| 746 | 867 |
| 747 // Check if the image is cached. | 868 // Check if the image is cached. |
| 748 ImageCache::const_iterator image_iter = images_on_ui_thread_.find(prs_id); | 869 ImageCache::const_iterator image_iter = images_on_ui_thread_.find(prs_id); |
| 749 if (image_iter != images_on_ui_thread_.end()) | 870 if (image_iter != images_on_ui_thread_.end()) |
| 750 return image_iter->second; | 871 return image_iter->second; |
| 751 | 872 |
| 752 // TODO(pkotwicz): Do something better than loading the bitmaps | 873 ThemeImagePngSource* png_source = NULL; |
| 753 // for all the scale factors associated with |idr_id|. | 874 for (int pass = 0; pass < 2; ++pass) { |
| 754 // See crbug.com/243831. | 875 // Two passes: In the first pass, we process only scale factor 100%, if |
| 755 gfx::ImageSkia source_image_skia; | 876 // available, and in the second pass all other scale factors. The reason is |
| 756 for (size_t i = 0; i < scale_factors_.size(); ++i) { | 877 // that the first png added, determines the DIP size. |
| 757 scoped_refptr<base::RefCountedMemory> memory = | 878 for (size_t i = 0; i < scale_factors_.size(); ++i) { |
| 758 GetRawData(idr_id, scale_factors_[i]); | 879 if ((pass == 0 && scale_factors_[i] != ui::SCALE_FACTOR_100P) || |
| 759 if (memory.get()) { | 880 (pass == 1 && scale_factors_[i] == ui::SCALE_FACTOR_100P)) { |
| 760 // Decode the PNG. | |
| 761 SkBitmap bitmap; | |
| 762 if (!gfx::PNGCodec::Decode(memory->front(), memory->size(), | |
| 763 &bitmap)) { | |
| 764 NOTREACHED() << "Unable to decode theme image resource " << idr_id | |
| 765 << " from saved DataPack."; | |
| 766 continue; | 881 continue; |
| 767 } | 882 } |
| 768 source_image_skia.AddRepresentation( | 883 scoped_refptr<base::RefCountedMemory> memory = |
| 769 gfx::ImageSkiaRep(bitmap, scale_factors_[i])); | 884 GetRawData(idr_id, scale_factors_[i]); |
| 885 if (memory.get()) { | |
| 886 if (!png_source) | |
| 887 png_source = new ThemeImagePngSource; | |
| 888 png_source->AddPng(memory, scale_factors_[i]); | |
| 889 } | |
| 770 } | 890 } |
| 771 } | 891 } |
| 772 | 892 |
| 773 if (!source_image_skia.isNull()) { | 893 if (png_source) { |
| 774 ThemeImageSource* source = new ThemeImageSource(source_image_skia); | 894 // |image_skia| owns png_source. |
| 775 gfx::ImageSkia image_skia(source, source_image_skia.size()); | 895 gfx::ImageSkia image_skia(png_source, png_source->size()); |
| 776 gfx::Image ret = gfx::Image(image_skia); | 896 gfx::Image ret = gfx::Image(image_skia); |
| 777 images_on_ui_thread_[prs_id] = ret; | 897 images_on_ui_thread_[prs_id] = ret; |
| 778 return ret; | 898 return ret; |
| 779 } | 899 } |
| 900 | |
| 780 return gfx::Image(); | 901 return gfx::Image(); |
| 781 } | 902 } |
| 782 | 903 |
| 783 base::RefCountedMemory* BrowserThemePack::GetRawData( | 904 base::RefCountedMemory* BrowserThemePack::GetRawData( |
| 784 int idr_id, | 905 int idr_id, |
| 785 ui::ScaleFactor scale_factor) const { | 906 ui::ScaleFactor scale_factor) const { |
| 786 base::RefCountedMemory* memory = NULL; | 907 base::RefCountedMemory* memory = NULL; |
| 787 int prs_id = GetPersistentIDByIDR(idr_id); | 908 int prs_id = GetPersistentIDByIDR(idr_id); |
| 788 int raw_id = GetRawIDByPersistentID(prs_id, scale_factor); | 909 int raw_id = GetRawIDByPersistentID(prs_id, scale_factor); |
| 789 | 910 |
| (...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1526 false, | 1647 false, |
| 1527 &bitmap_data)) { | 1648 &bitmap_data)) { |
| 1528 NOTREACHED() << "Unable to encode theme image for prs_id=" | 1649 NOTREACHED() << "Unable to encode theme image for prs_id=" |
| 1529 << prs_id << " for scale_factor=" << scale_factors_[i]; | 1650 << prs_id << " for scale_factor=" << scale_factors_[i]; |
| 1530 break; | 1651 break; |
| 1531 } | 1652 } |
| 1532 image_memory_[scaled_raw_id] = | 1653 image_memory_[scaled_raw_id] = |
| 1533 base::RefCountedBytes::TakeVector(&bitmap_data); | 1654 base::RefCountedBytes::TakeVector(&bitmap_data); |
| 1534 } | 1655 } |
| 1535 } | 1656 } |
| OLD | NEW |