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 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 | 437 |
438 // Shifts an image's HSL values. The caller is responsible for deleting | 438 // Shifts an image's HSL values. The caller is responsible for deleting |
439 // the returned image. | 439 // the returned image. |
440 gfx::Image CreateHSLShiftedImage(const gfx::Image& image, | 440 gfx::Image CreateHSLShiftedImage(const gfx::Image& image, |
441 const color_utils::HSL& hsl_shift) { | 441 const color_utils::HSL& hsl_shift) { |
442 const gfx::ImageSkia* src_image = image.ToImageSkia(); | 442 const gfx::ImageSkia* src_image = image.ToImageSkia(); |
443 return gfx::Image(gfx::ImageSkiaOperations::CreateHSLShiftedImage( | 443 return gfx::Image(gfx::ImageSkiaOperations::CreateHSLShiftedImage( |
444 *src_image, hsl_shift)); | 444 *src_image, hsl_shift)); |
445 } | 445 } |
446 | 446 |
| 447 // Computes a bitmap at one scale from a bitmap at a different scale. |
| 448 SkBitmap CreateLowQualityResizedBitmap(const SkBitmap& source_bitmap, |
| 449 ui::ScaleFactor source_scale_factor, |
| 450 ui::ScaleFactor desired_scale_factor) { |
| 451 gfx::Size scaled_size = gfx::ToCeiledSize( |
| 452 gfx::ScaleSize(gfx::Size(source_bitmap.width(), |
| 453 source_bitmap.height()), |
| 454 ui::GetScaleFactorScale(desired_scale_factor) / |
| 455 ui::GetScaleFactorScale(source_scale_factor))); |
| 456 SkBitmap scaled_bitmap; |
| 457 scaled_bitmap.setConfig(SkBitmap::kARGB_8888_Config, |
| 458 scaled_size.width(), |
| 459 scaled_size.height()); |
| 460 if (!scaled_bitmap.allocPixels()) |
| 461 SK_CRASH(); |
| 462 scaled_bitmap.eraseARGB(0, 0, 0, 0); |
| 463 SkCanvas canvas(scaled_bitmap); |
| 464 SkRect scaled_bounds = RectToSkRect(gfx::Rect(scaled_size)); |
| 465 // Note(oshima): The following scaling code doesn't work with |
| 466 // a mask image. |
| 467 canvas.drawBitmapRect(source_bitmap, NULL, scaled_bounds); |
| 468 return scaled_bitmap; |
| 469 } |
| 470 |
447 // A ImageSkiaSource that scales 100P image to the target scale factor | 471 // A ImageSkiaSource that scales 100P image to the target scale factor |
448 // if the ImageSkiaRep for the target scale factor isn't available. | 472 // if the ImageSkiaRep for the target scale factor isn't available. |
449 class ThemeImageSource: public gfx::ImageSkiaSource { | 473 class ThemeImageSource: public gfx::ImageSkiaSource { |
450 public: | 474 public: |
451 explicit ThemeImageSource(const gfx::ImageSkia& source) : source_(source) { | 475 explicit ThemeImageSource(const gfx::ImageSkia& source) : source_(source) { |
452 } | 476 } |
453 virtual ~ThemeImageSource() {} | 477 virtual ~ThemeImageSource() {} |
454 | 478 |
455 virtual gfx::ImageSkiaRep GetImageForScale( | 479 virtual gfx::ImageSkiaRep GetImageForScale( |
456 ui::ScaleFactor scale_factor) OVERRIDE { | 480 ui::ScaleFactor scale_factor) OVERRIDE { |
457 if (source_.HasRepresentation(scale_factor)) | 481 if (source_.HasRepresentation(scale_factor)) |
458 return source_.GetRepresentation(scale_factor); | 482 return source_.GetRepresentation(scale_factor); |
459 const gfx::ImageSkiaRep& rep_100p = | 483 const gfx::ImageSkiaRep& rep_100p = |
460 source_.GetRepresentation(ui::SCALE_FACTOR_100P); | 484 source_.GetRepresentation(ui::SCALE_FACTOR_100P); |
461 float scale = ui::GetScaleFactorScale(scale_factor); | 485 SkBitmap scaled_bitmap = CreateLowQualityResizedBitmap( |
462 gfx::Size size(rep_100p.GetWidth() * scale, rep_100p.GetHeight() * scale); | 486 rep_100p.sk_bitmap(), |
463 SkBitmap resized_bitmap; | 487 ui::SCALE_FACTOR_100P, |
464 resized_bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), | 488 scale_factor); |
465 size.height()); | 489 return gfx::ImageSkiaRep(scaled_bitmap, scale_factor); |
466 if (!resized_bitmap.allocPixels()) | |
467 SK_CRASH(); | |
468 resized_bitmap.eraseARGB(0, 0, 0, 0); | |
469 SkCanvas canvas(resized_bitmap); | |
470 SkRect resized_bounds = RectToSkRect(gfx::Rect(size)); | |
471 // Note(oshima): The following scaling code doesn't work with | |
472 // a mask image. | |
473 canvas.drawBitmapRect(rep_100p.sk_bitmap(), NULL, resized_bounds); | |
474 return gfx::ImageSkiaRep(resized_bitmap, scale_factor); | |
475 } | 490 } |
476 | 491 |
477 private: | 492 private: |
478 const gfx::ImageSkia source_; | 493 const gfx::ImageSkia source_; |
479 | 494 |
480 DISALLOW_COPY_AND_ASSIGN(ThemeImageSource); | 495 DISALLOW_COPY_AND_ASSIGN(ThemeImageSource); |
481 }; | 496 }; |
482 | 497 |
| 498 // An ImageSkiaSource that delays decoding PNG data into bitmaps until |
| 499 // needed. Missing data for a scale factor is computed by scaling data for an |
| 500 // available scale factor. Computed bitmaps are stored for future look up. |
| 501 class ThemeImagePngSource : public gfx::ImageSkiaSource { |
| 502 public: |
| 503 typedef std::map<ui::ScaleFactor, |
| 504 scoped_refptr<base::RefCountedMemory> > PngMap; |
| 505 |
| 506 explicit ThemeImagePngSource(const PngMap& png_map) : png_map_(png_map) {} |
| 507 |
| 508 virtual ~ThemeImagePngSource() {} |
| 509 |
| 510 private: |
| 511 virtual gfx::ImageSkiaRep GetImageForScale( |
| 512 ui::ScaleFactor scale_factor) OVERRIDE { |
| 513 // Look up the bitmap for |scale factor| in the bitmap map. If found |
| 514 // return it. |
| 515 BitmapMap::const_iterator exact_bitmap_it = bitmap_map_.find(scale_factor); |
| 516 if (exact_bitmap_it != bitmap_map_.end()) |
| 517 return gfx::ImageSkiaRep(exact_bitmap_it->second, scale_factor); |
| 518 |
| 519 // Look up the raw PNG data for |scale_factor| in the png map. If found, |
| 520 // decode it, store the result in the bitmap map and return it. |
| 521 PngMap::const_iterator exact_png_it = png_map_.find(scale_factor); |
| 522 if (exact_png_it != png_map_.end()) { |
| 523 SkBitmap bitmap; |
| 524 if (!gfx::PNGCodec::Decode(exact_png_it->second->front(), |
| 525 exact_png_it->second->size(), |
| 526 &bitmap)) { |
| 527 NOTREACHED(); |
| 528 return gfx::ImageSkiaRep(); |
| 529 } |
| 530 bitmap_map_[scale_factor] = bitmap; |
| 531 return gfx::ImageSkiaRep(bitmap, scale_factor); |
| 532 } |
| 533 |
| 534 // Find an available PNG for another scale factor. We want to use the |
| 535 // highest available scale factor. |
| 536 PngMap::const_iterator available_png_it = png_map_.end(); |
| 537 for (PngMap::const_iterator png_it = png_map_.begin(); |
| 538 png_it != png_map_.end(); ++png_it) { |
| 539 if (available_png_it == png_map_.end() || |
| 540 ui::GetScaleFactorScale(png_it->first) > |
| 541 ui::GetScaleFactorScale(available_png_it->first)) { |
| 542 available_png_it = png_it; |
| 543 } |
| 544 } |
| 545 if (available_png_it == png_map_.end()) |
| 546 return gfx::ImageSkiaRep(); |
| 547 ui::ScaleFactor available_scale_factor = available_png_it->first; |
| 548 |
| 549 // Look up the bitmap for |available_scale_factor| in the bitmap map. |
| 550 // If not found, decode the corresponging png data, store the result |
| 551 // in the bitmap map. |
| 552 BitmapMap::const_iterator available_bitmap_it = |
| 553 bitmap_map_.find(available_scale_factor); |
| 554 if (available_bitmap_it == bitmap_map_.end()) { |
| 555 SkBitmap available_bitmap; |
| 556 if (!gfx::PNGCodec::Decode(available_png_it->second->front(), |
| 557 available_png_it->second->size(), |
| 558 &available_bitmap)) { |
| 559 NOTREACHED(); |
| 560 return gfx::ImageSkiaRep(); |
| 561 } |
| 562 bitmap_map_[available_scale_factor] = available_bitmap; |
| 563 available_bitmap_it = bitmap_map_.find(available_scale_factor); |
| 564 } |
| 565 |
| 566 // Scale the available bitmap to the desired scale factor, store the result |
| 567 // in the bitmap map and return it. |
| 568 SkBitmap scaled_bitmap = CreateLowQualityResizedBitmap( |
| 569 available_bitmap_it->second, |
| 570 available_scale_factor, |
| 571 scale_factor); |
| 572 bitmap_map_[scale_factor] = scaled_bitmap; |
| 573 return gfx::ImageSkiaRep(scaled_bitmap, scale_factor); |
| 574 } |
| 575 |
| 576 PngMap png_map_; |
| 577 |
| 578 typedef std::map<ui::ScaleFactor, SkBitmap> BitmapMap; |
| 579 BitmapMap bitmap_map_; |
| 580 |
| 581 DISALLOW_COPY_AND_ASSIGN(ThemeImagePngSource); |
| 582 }; |
| 583 |
483 class TabBackgroundImageSource: public gfx::CanvasImageSource { | 584 class TabBackgroundImageSource: public gfx::CanvasImageSource { |
484 public: | 585 public: |
485 TabBackgroundImageSource(const gfx::ImageSkia& image_to_tint, | 586 TabBackgroundImageSource(const gfx::ImageSkia& image_to_tint, |
486 const gfx::ImageSkia& overlay, | 587 const gfx::ImageSkia& overlay, |
487 const color_utils::HSL& hsl_shift, | 588 const color_utils::HSL& hsl_shift, |
488 int vertical_offset) | 589 int vertical_offset) |
489 : gfx::CanvasImageSource(image_to_tint.size(), false), | 590 : gfx::CanvasImageSource(image_to_tint.size(), false), |
490 image_to_tint_(image_to_tint), | 591 image_to_tint_(image_to_tint), |
491 overlay_(overlay), | 592 overlay_(overlay), |
492 hsl_shift_(hsl_shift), | 593 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) { | 843 gfx::Image BrowserThemePack::GetImageNamed(int idr_id) { |
743 int prs_id = GetPersistentIDByIDR(idr_id); | 844 int prs_id = GetPersistentIDByIDR(idr_id); |
744 if (prs_id == -1) | 845 if (prs_id == -1) |
745 return gfx::Image(); | 846 return gfx::Image(); |
746 | 847 |
747 // Check if the image is cached. | 848 // Check if the image is cached. |
748 ImageCache::const_iterator image_iter = images_on_ui_thread_.find(prs_id); | 849 ImageCache::const_iterator image_iter = images_on_ui_thread_.find(prs_id); |
749 if (image_iter != images_on_ui_thread_.end()) | 850 if (image_iter != images_on_ui_thread_.end()) |
750 return image_iter->second; | 851 return image_iter->second; |
751 | 852 |
752 // TODO(pkotwicz): Do something better than loading the bitmaps | 853 ThemeImagePngSource::PngMap png_map; |
753 // for all the scale factors associated with |idr_id|. | |
754 // See crbug.com/243831. | |
755 gfx::ImageSkia source_image_skia; | |
756 for (size_t i = 0; i < scale_factors_.size(); ++i) { | 854 for (size_t i = 0; i < scale_factors_.size(); ++i) { |
757 scoped_refptr<base::RefCountedMemory> memory = | 855 scoped_refptr<base::RefCountedMemory> memory = |
758 GetRawData(idr_id, scale_factors_[i]); | 856 GetRawData(idr_id, scale_factors_[i]); |
759 if (memory.get()) { | 857 if (memory.get()) |
760 // Decode the PNG. | 858 png_map[scale_factors_[i]] = memory; |
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; | |
767 } | |
768 source_image_skia.AddRepresentation( | |
769 gfx::ImageSkiaRep(bitmap, scale_factors_[i])); | |
770 } | |
771 } | 859 } |
772 | 860 if (!png_map.empty()) { |
773 if (!source_image_skia.isNull()) { | 861 gfx::ImageSkia image_skia(new ThemeImagePngSource(png_map), |
774 ThemeImageSource* source = new ThemeImageSource(source_image_skia); | 862 ui::SCALE_FACTOR_100P); |
775 gfx::ImageSkia image_skia(source, source_image_skia.size()); | 863 // |image_skia| takes ownership of ThemeImagePngSource. |
776 gfx::Image ret = gfx::Image(image_skia); | 864 gfx::Image ret = gfx::Image(image_skia); |
777 images_on_ui_thread_[prs_id] = ret; | 865 images_on_ui_thread_[prs_id] = ret; |
778 return ret; | 866 return ret; |
779 } | 867 } |
| 868 |
780 return gfx::Image(); | 869 return gfx::Image(); |
781 } | 870 } |
782 | 871 |
783 base::RefCountedMemory* BrowserThemePack::GetRawData( | 872 base::RefCountedMemory* BrowserThemePack::GetRawData( |
784 int idr_id, | 873 int idr_id, |
785 ui::ScaleFactor scale_factor) const { | 874 ui::ScaleFactor scale_factor) const { |
786 base::RefCountedMemory* memory = NULL; | 875 base::RefCountedMemory* memory = NULL; |
787 int prs_id = GetPersistentIDByIDR(idr_id); | 876 int prs_id = GetPersistentIDByIDR(idr_id); |
788 int raw_id = GetRawIDByPersistentID(prs_id, scale_factor); | 877 int raw_id = GetRawIDByPersistentID(prs_id, scale_factor); |
789 | 878 |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1468 int raw_id = GetRawIDByPersistentID(prs_id, scale_factors_[i]); | 1557 int raw_id = GetRawIDByPersistentID(prs_id, scale_factors_[i]); |
1469 if (image_memory_.find(raw_id) == image_memory_.end()) { | 1558 if (image_memory_.find(raw_id) == image_memory_.end()) { |
1470 image_missing = true; | 1559 image_missing = true; |
1471 break; | 1560 break; |
1472 } | 1561 } |
1473 } | 1562 } |
1474 if (!image_missing) | 1563 if (!image_missing) |
1475 return; | 1564 return; |
1476 | 1565 |
1477 // Find available scale factor with highest scale. | 1566 // Find available scale factor with highest scale. |
1478 ui::ScaleFactor available = ui::SCALE_FACTOR_NONE; | 1567 ui::ScaleFactor available_scale_factor = ui::SCALE_FACTOR_NONE; |
1479 for (size_t i = 0; i < scale_factors_.size(); ++i) { | 1568 for (size_t i = 0; i < scale_factors_.size(); ++i) { |
1480 int raw_id = GetRawIDByPersistentID(prs_id, scale_factors_[i]); | 1569 int raw_id = GetRawIDByPersistentID(prs_id, scale_factors_[i]); |
1481 if ((available == ui::SCALE_FACTOR_NONE || | 1570 if ((available_scale_factor == ui::SCALE_FACTOR_NONE || |
1482 (ui::GetScaleFactorScale(scale_factors_[i]) > | 1571 (ui::GetScaleFactorScale(scale_factors_[i]) > |
1483 ui::GetScaleFactorScale(available))) && | 1572 ui::GetScaleFactorScale(available_scale_factor))) && |
1484 image_memory_.find(raw_id) != image_memory_.end()) { | 1573 image_memory_.find(raw_id) != image_memory_.end()) { |
1485 available = scale_factors_[i]; | 1574 available_scale_factor = scale_factors_[i]; |
1486 } | 1575 } |
1487 } | 1576 } |
1488 // If no scale factor is available, we're done. | 1577 // If no scale factor is available, we're done. |
1489 if (available == ui::SCALE_FACTOR_NONE) | 1578 if (available_scale_factor == ui::SCALE_FACTOR_NONE) |
1490 return; | 1579 return; |
1491 | 1580 |
1492 // Get bitmap for the available scale factor. | 1581 // Get bitmap for the available scale factor. |
1493 int available_raw_id = GetRawIDByPersistentID(prs_id, available); | 1582 int available_raw_id = GetRawIDByPersistentID(prs_id, available_scale_factor); |
1494 RawImages::const_iterator it = image_memory_.find(available_raw_id); | 1583 RawImages::const_iterator it = image_memory_.find(available_raw_id); |
1495 SkBitmap available_bitmap; | 1584 SkBitmap available_bitmap; |
1496 if (!gfx::PNGCodec::Decode(it->second->front(), | 1585 if (!gfx::PNGCodec::Decode(it->second->front(), |
1497 it->second->size(), | 1586 it->second->size(), |
1498 &available_bitmap)) { | 1587 &available_bitmap)) { |
1499 NOTREACHED() << "Unable to decode theme image for prs_id=" | 1588 NOTREACHED() << "Unable to decode theme image for prs_id=" |
1500 << prs_id << " for scale_factor=" << available; | 1589 << prs_id << " for scale_factor=" << available_scale_factor; |
1501 return; | 1590 return; |
1502 } | 1591 } |
1503 | 1592 |
1504 // Fill in all missing scale factors by scaling the available bitmap. | 1593 // Fill in all missing scale factors by scaling the available bitmap. |
1505 for (size_t i = 0; i < scale_factors_.size(); ++i) { | 1594 for (size_t i = 0; i < scale_factors_.size(); ++i) { |
1506 int scaled_raw_id = GetRawIDByPersistentID(prs_id, scale_factors_[i]); | 1595 int scaled_raw_id = GetRawIDByPersistentID(prs_id, scale_factors_[i]); |
1507 if (image_memory_.find(scaled_raw_id) != image_memory_.end()) | 1596 if (image_memory_.find(scaled_raw_id) != image_memory_.end()) |
1508 continue; | 1597 continue; |
1509 gfx::Size scaled_size = gfx::ToCeiledSize( | 1598 SkBitmap scaled_bitmap = |
1510 gfx::ScaleSize(gfx::Size(available_bitmap.width(), | 1599 CreateLowQualityResizedBitmap(available_bitmap, |
1511 available_bitmap.height()), | 1600 available_scale_factor, |
1512 ui::GetScaleFactorScale(scale_factors_[i]) / | 1601 scale_factors_[i]); |
1513 ui::GetScaleFactorScale(available))); | |
1514 SkBitmap scaled_bitmap; | |
1515 scaled_bitmap.setConfig(SkBitmap::kARGB_8888_Config, | |
1516 scaled_size.width(), | |
1517 scaled_size.height()); | |
1518 if (!scaled_bitmap.allocPixels()) | |
1519 SK_CRASH(); | |
1520 scaled_bitmap.eraseARGB(0, 0, 0, 0); | |
1521 SkCanvas canvas(scaled_bitmap); | |
1522 SkRect scaled_bounds = RectToSkRect(gfx::Rect(scaled_size)); | |
1523 canvas.drawBitmapRect(available_bitmap, NULL, scaled_bounds); | |
1524 std::vector<unsigned char> bitmap_data; | 1602 std::vector<unsigned char> bitmap_data; |
1525 if (!gfx::PNGCodec::EncodeBGRASkBitmap(scaled_bitmap, | 1603 if (!gfx::PNGCodec::EncodeBGRASkBitmap(scaled_bitmap, |
1526 false, | 1604 false, |
1527 &bitmap_data)) { | 1605 &bitmap_data)) { |
1528 NOTREACHED() << "Unable to encode theme image for prs_id=" | 1606 NOTREACHED() << "Unable to encode theme image for prs_id=" |
1529 << prs_id << " for scale_factor=" << scale_factors_[i]; | 1607 << prs_id << " for scale_factor=" << scale_factors_[i]; |
1530 break; | 1608 break; |
1531 } | 1609 } |
1532 image_memory_[scaled_raw_id] = | 1610 image_memory_[scaled_raw_id] = |
1533 base::RefCountedBytes::TakeVector(&bitmap_data); | 1611 base::RefCountedBytes::TakeVector(&bitmap_data); |
1534 } | 1612 } |
1535 } | 1613 } |
OLD | NEW |