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 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 |