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