skottie_mru_resource_provider.cc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // Copyright 2021 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. #include "cc/paint/skottie_mru_resource_provider.h"
  5. #include <string>
  6. #include <utility>
  7. #include "base/check.h"
  8. #include "base/json/json_reader.h"
  9. #include "base/logging.h"
  10. #include "base/strings/string_piece.h"
  11. #include "base/values.h"
  12. #include "third_party/abseil-cpp/absl/types/optional.h"
  13. #include "third_party/skia/include/core/SkImage.h"
  14. #include "third_party/skia/include/core/SkRefCnt.h"
  15. namespace cc {
  16. namespace {
  17. constexpr base::StringPiece kAssetsKey = "assets";
  18. constexpr base::StringPiece kIdKey = "id";
  19. constexpr base::StringPiece kWidthKey = "w";
  20. constexpr base::StringPiece kHeightKey = "h";
  21. // TODO(fmalita): Remove explicit parsing and pass size param directly from
  22. // Skottie.
  23. base::flat_map</*asset_id*/ std::string, gfx::Size> ParseImageAssetDimensions(
  24. base::StringPiece animation_json) {
  25. base::flat_map<std::string, gfx::Size> image_asset_sizes;
  26. absl::optional<base::Value> animation_dict =
  27. base::JSONReader::Read(animation_json);
  28. if (!animation_dict) {
  29. LOG(ERROR) << "Failed to parse Lottie animation json";
  30. return image_asset_sizes;
  31. }
  32. const base::Value* assets = animation_dict->FindListKey(kAssetsKey);
  33. // An animation may legitimately have no assets in it.
  34. if (!assets)
  35. return image_asset_sizes;
  36. for (const base::Value& asset : assets->GetListDeprecated()) {
  37. const std::string* id = asset.FindStringKey(kIdKey);
  38. absl::optional<int> width = asset.FindIntKey(kWidthKey);
  39. absl::optional<int> height = asset.FindIntKey(kHeightKey);
  40. if (id && width && height && *width > 0 && *height > 0 &&
  41. !image_asset_sizes.emplace(*id, gfx::Size(*width, *height)).second) {
  42. LOG(WARNING) << "Multiple assets found in animation with id " << *id;
  43. }
  44. }
  45. return image_asset_sizes;
  46. }
  47. class ImageAssetImpl : public skresources::ImageAsset {
  48. public:
  49. using FrameData = skresources::ImageAsset::FrameData;
  50. using FrameDataCallback = SkottieWrapper::FrameDataCallback;
  51. ImageAssetImpl(SkottieResourceIdHash asset_id,
  52. FrameDataCallback frame_data_cb)
  53. : asset_id_(asset_id), frame_data_cb_(std::move(frame_data_cb)) {
  54. DCHECK(frame_data_cb_);
  55. }
  56. bool isMultiFrame() override { return true; }
  57. FrameData getFrameData(float t) override {
  58. FrameData new_frame_data;
  59. SkottieWrapper::FrameDataFetchResult result = frame_data_cb_.Run(
  60. asset_id_, t, new_frame_data.image, new_frame_data.sampling);
  61. switch (result) {
  62. case SkottieWrapper::FrameDataFetchResult::NEW_DATA_AVAILABLE:
  63. current_frame_data_ = std::move(new_frame_data);
  64. break;
  65. case SkottieWrapper::FrameDataFetchResult::NO_UPDATE:
  66. break;
  67. }
  68. return current_frame_data_;
  69. }
  70. private:
  71. const SkottieResourceIdHash asset_id_;
  72. const FrameDataCallback frame_data_cb_;
  73. FrameData current_frame_data_;
  74. };
  75. } // namespace
  76. SkottieMRUResourceProvider::SkottieMRUResourceProvider(
  77. FrameDataCallback frame_data_cb,
  78. base::StringPiece animation_json)
  79. : frame_data_cb_(std::move(frame_data_cb)),
  80. image_asset_sizes_(ParseImageAssetDimensions(animation_json)) {}
  81. SkottieMRUResourceProvider::~SkottieMRUResourceProvider() = default;
  82. const SkottieResourceMetadataMap&
  83. SkottieMRUResourceProvider::GetImageAssetMetadata() const {
  84. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  85. return image_asset_metadata_;
  86. }
  87. sk_sp<skresources::ImageAsset> SkottieMRUResourceProvider::loadImageAsset(
  88. const char resource_path[],
  89. const char resource_name[],
  90. const char resource_id[]) const {
  91. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  92. absl::optional<gfx::Size> size;
  93. if (image_asset_sizes_.contains(resource_id))
  94. size.emplace(image_asset_sizes_.at(resource_id));
  95. if (!image_asset_metadata_.RegisterAsset(resource_path, resource_name,
  96. resource_id, std::move(size))) {
  97. return nullptr;
  98. }
  99. return sk_make_sp<ImageAssetImpl>(HashSkottieResourceId(resource_id),
  100. frame_data_cb_);
  101. }
  102. } // namespace cc