Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 1 | // Copyright 2018 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Henrique Ferreiro | e52f5941 | 2021-03-25 13:33:16 | [diff] [blame] | 5 | #include "chrome/browser/ash/arc/icon_decode_request.h" |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 6 | |
Qiang Xu | 1bbbdca | 2018-03-15 22:50:40 | [diff] [blame] | 7 | #include <memory> |
| 8 | #include <utility> |
| 9 | #include <vector> |
| 10 | |
Nancy Wang | a75ebc0 | 2021-03-30 05:13:24 | [diff] [blame] | 11 | #include "base/no_destructor.h" |
Vladislav Kaznacheev | 84de1c5 | 2018-11-01 14:38:58 | [diff] [blame] | 12 | #include "chrome/browser/ui/app_list/md_icon_normalizer.h" |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 13 | #include "chrome/grit/component_extension_resources.h" |
| 14 | #include "content/public/browser/browser_thread.h" |
Nancy Wang | a75ebc0 | 2021-03-30 05:13:24 | [diff] [blame] | 15 | #include "services/data_decoder/public/cpp/data_decoder.h" |
Qiang Xu | 1b2a62ded | 2018-04-17 18:55:37 | [diff] [blame] | 16 | #include "ui/base/resource/resource_bundle.h" |
Mitsuru Oshima | 15732bc9 | 2021-08-16 22:59:31 | [diff] [blame] | 17 | #include "ui/base/resource/resource_scale_factor.h" |
Qiang Xu | 1bbbdca | 2018-03-15 22:50:40 | [diff] [blame] | 18 | #include "ui/gfx/codec/png_codec.h" |
| 19 | #include "ui/gfx/image/image_skia.h" |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 20 | #include "ui/gfx/image/image_skia_operations.h" |
| 21 | #include "ui/gfx/image/image_skia_rep.h" |
| 22 | #include "ui/gfx/image/image_skia_source.h" |
| 23 | |
| 24 | using content::BrowserThread; |
| 25 | |
Qiang Xu | 1b2a62ded | 2018-04-17 18:55:37 | [diff] [blame] | 26 | namespace arc { |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 27 | |
| 28 | namespace { |
| 29 | |
Qiang Xu | 1bbbdca | 2018-03-15 22:50:40 | [diff] [blame] | 30 | bool disable_safe_decoding_for_testing = false; |
| 31 | |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 32 | class IconSource : public gfx::ImageSkiaSource { |
| 33 | public: |
Vladislav Kaznacheev | 84de1c5 | 2018-11-01 14:38:58 | [diff] [blame] | 34 | IconSource(const SkBitmap& bitmap, int dimension_dip, bool normalize); |
Peter Boström | 53c6c595 | 2021-09-17 09:41:26 | [diff] [blame^] | 35 | |
| 36 | IconSource(const IconSource&) = delete; |
| 37 | IconSource& operator=(const IconSource&) = delete; |
| 38 | |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 39 | ~IconSource() override = default; |
| 40 | |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 41 | private: |
| 42 | gfx::ImageSkiaRep GetImageForScale(float scale) override; |
| 43 | |
Vladislav Kaznacheev | 84de1c5 | 2018-11-01 14:38:58 | [diff] [blame] | 44 | const SkBitmap bitmap_; |
| 45 | const int dimension_dip_; |
| 46 | const bool normalize_; |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 47 | }; |
| 48 | |
Vladislav Kaznacheev | 84de1c5 | 2018-11-01 14:38:58 | [diff] [blame] | 49 | IconSource::IconSource(const SkBitmap& bitmap, |
| 50 | int dimension_dip, |
| 51 | bool normalize) |
| 52 | : bitmap_(bitmap), dimension_dip_(dimension_dip), normalize_(normalize) {} |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 53 | |
| 54 | gfx::ImageSkiaRep IconSource::GetImageForScale(float scale) { |
| 55 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 56 | |
Vladislav Kaznacheev | 84de1c5 | 2018-11-01 14:38:58 | [diff] [blame] | 57 | const int dimension_px = static_cast<int>(dimension_dip_ * scale + 0.5); |
| 58 | if (bitmap_.isNull()) { |
| 59 | const int resource_id = |
| 60 | dimension_px <= 32 ? IDR_ARC_SUPPORT_ICON_32 : IDR_ARC_SUPPORT_ICON_192; |
| 61 | const gfx::ImageSkia* resource_image = |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 62 | ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id); |
Vladislav Kaznacheev | 84de1c5 | 2018-11-01 14:38:58 | [diff] [blame] | 63 | const gfx::ImageSkia resized_image = |
| 64 | gfx::ImageSkiaOperations::CreateResizedImage( |
| 65 | *resource_image, skia::ImageOperations::RESIZE_LANCZOS3, |
| 66 | gfx::Size(dimension_dip_, dimension_dip_)); |
| 67 | return resized_image.GetRepresentation(scale); |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 68 | } |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 69 | |
Vladislav Kaznacheev | 84de1c5 | 2018-11-01 14:38:58 | [diff] [blame] | 70 | SkBitmap resized_bitmap; |
| 71 | if (normalize_) { |
| 72 | resized_bitmap = bitmap_; |
| 73 | const gfx::Size size_px(dimension_px, dimension_px); |
| 74 | const gfx::Size padding_px = |
| 75 | app_list::GetMdIconPadding(resized_bitmap, size_px); |
| 76 | app_list::MaybeResizeAndPad(size_px, padding_px, &resized_bitmap); |
| 77 | } else { |
| 78 | resized_bitmap = skia::ImageOperations::Resize( |
| 79 | bitmap_, skia::ImageOperations::RESIZE_LANCZOS3, dimension_px, |
| 80 | dimension_px); |
| 81 | } |
| 82 | return gfx::ImageSkiaRep(resized_bitmap, scale); |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 83 | } |
| 84 | |
Nancy Wang | a75ebc0 | 2021-03-30 05:13:24 | [diff] [blame] | 85 | data_decoder::DataDecoder& GetDataDecoder() { |
| 86 | static base::NoDestructor<data_decoder::DataDecoder> data_decoder; |
| 87 | return *data_decoder; |
| 88 | } |
| 89 | |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 90 | } // namespace |
| 91 | |
Qiang Xu | 1bbbdca | 2018-03-15 22:50:40 | [diff] [blame] | 92 | // static |
| 93 | void IconDecodeRequest::DisableSafeDecodingForTesting() { |
| 94 | disable_safe_decoding_for_testing = true; |
| 95 | } |
| 96 | |
Qiang Xu | 1b2a62ded | 2018-04-17 18:55:37 | [diff] [blame] | 97 | IconDecodeRequest::IconDecodeRequest(SetIconCallback set_icon_callback, |
Vladislav Kaznacheev | 84de1c5 | 2018-11-01 14:38:58 | [diff] [blame] | 98 | int dimension_dip) |
Nancy Wang | a75ebc0 | 2021-03-30 05:13:24 | [diff] [blame] | 99 | : ImageRequest(&GetDataDecoder()), |
| 100 | set_icon_callback_(std::move(set_icon_callback)), |
Vladislav Kaznacheev | 84de1c5 | 2018-11-01 14:38:58 | [diff] [blame] | 101 | dimension_dip_(dimension_dip) {} |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 102 | |
| 103 | IconDecodeRequest::~IconDecodeRequest() = default; |
| 104 | |
Qiang Xu | 1bbbdca | 2018-03-15 22:50:40 | [diff] [blame] | 105 | void IconDecodeRequest::StartWithOptions( |
| 106 | const std::vector<uint8_t>& image_data) { |
| 107 | if (disable_safe_decoding_for_testing) { |
| 108 | if (image_data.empty()) { |
| 109 | OnDecodeImageFailed(); |
| 110 | return; |
| 111 | } |
| 112 | SkBitmap bitmap; |
| 113 | if (!gfx::PNGCodec::Decode( |
| 114 | reinterpret_cast<const unsigned char*>(image_data.data()), |
| 115 | image_data.size(), &bitmap)) { |
| 116 | OnDecodeImageFailed(); |
| 117 | return; |
| 118 | } |
| 119 | OnImageDecoded(bitmap); |
| 120 | return; |
| 121 | } |
| 122 | ImageDecoder::StartWithOptions(this, image_data, ImageDecoder::DEFAULT_CODEC, |
| 123 | true, gfx::Size()); |
| 124 | } |
| 125 | |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 126 | void IconDecodeRequest::OnImageDecoded(const SkBitmap& bitmap) { |
| 127 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
Vladislav Kaznacheev | 84de1c5 | 2018-11-01 14:38:58 | [diff] [blame] | 128 | const gfx::ImageSkia icon( |
| 129 | std::make_unique<IconSource>(bitmap, dimension_dip_, normalized_), |
| 130 | gfx::Size(dimension_dip_, dimension_dip_)); |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 131 | icon.EnsureRepsForSupportedScales(); |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 132 | std::move(set_icon_callback_).Run(icon); |
| 133 | } |
| 134 | |
| 135 | void IconDecodeRequest::OnDecodeImageFailed() { |
| 136 | DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 137 | DLOG(ERROR) << "Failed to decode an icon image."; |
Vladislav Kaznacheev | 84de1c5 | 2018-11-01 14:38:58 | [diff] [blame] | 138 | OnImageDecoded(SkBitmap()); |
Qiang Xu | 139f8653 | 2018-03-06 22:14:43 | [diff] [blame] | 139 | } |
| 140 | |
Qiang Xu | 1b2a62ded | 2018-04-17 18:55:37 | [diff] [blame] | 141 | } // namespace arc |