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); | |
pkotwicz
2013/06/20 02:00:23
After reading through the unittests, I would rathe
| |
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 |