forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathskottie_mru_resource_provider.cc
123 lines (102 loc) · 4.11 KB
/
skottie_mru_resource_provider.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/paint/skottie_mru_resource_provider.h"
#include <string>
#include <utility>
#include "base/check.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "base/values.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkRefCnt.h"
namespace cc {
namespace {
constexpr base::StringPiece kAssetsKey = "assets";
constexpr base::StringPiece kIdKey = "id";
constexpr base::StringPiece kWidthKey = "w";
constexpr base::StringPiece kHeightKey = "h";
// TODO(fmalita): Remove explicit parsing and pass size param directly from
// Skottie.
base::flat_map</*asset_id*/ std::string, gfx::Size> ParseImageAssetDimensions(
base::StringPiece animation_json) {
base::flat_map<std::string, gfx::Size> image_asset_sizes;
absl::optional<base::Value> animation_dict =
base::JSONReader::Read(animation_json);
if (!animation_dict) {
LOG(ERROR) << "Failed to parse Lottie animation json";
return image_asset_sizes;
}
const base::Value* assets = animation_dict->FindListKey(kAssetsKey);
// An animation may legitimately have no assets in it.
if (!assets)
return image_asset_sizes;
for (const base::Value& asset : assets->GetListDeprecated()) {
const std::string* id = asset.FindStringKey(kIdKey);
absl::optional<int> width = asset.FindIntKey(kWidthKey);
absl::optional<int> height = asset.FindIntKey(kHeightKey);
if (id && width && height && *width > 0 && *height > 0 &&
!image_asset_sizes.emplace(*id, gfx::Size(*width, *height)).second) {
LOG(WARNING) << "Multiple assets found in animation with id " << *id;
}
}
return image_asset_sizes;
}
class ImageAssetImpl : public skresources::ImageAsset {
public:
using FrameData = skresources::ImageAsset::FrameData;
using FrameDataCallback = SkottieWrapper::FrameDataCallback;
ImageAssetImpl(SkottieResourceIdHash asset_id,
FrameDataCallback frame_data_cb)
: asset_id_(asset_id), frame_data_cb_(std::move(frame_data_cb)) {
DCHECK(frame_data_cb_);
}
bool isMultiFrame() override { return true; }
FrameData getFrameData(float t) override {
FrameData new_frame_data;
SkottieWrapper::FrameDataFetchResult result = frame_data_cb_.Run(
asset_id_, t, new_frame_data.image, new_frame_data.sampling);
switch (result) {
case SkottieWrapper::FrameDataFetchResult::NEW_DATA_AVAILABLE:
current_frame_data_ = std::move(new_frame_data);
break;
case SkottieWrapper::FrameDataFetchResult::NO_UPDATE:
break;
}
return current_frame_data_;
}
private:
const SkottieResourceIdHash asset_id_;
const FrameDataCallback frame_data_cb_;
FrameData current_frame_data_;
};
} // namespace
SkottieMRUResourceProvider::SkottieMRUResourceProvider(
FrameDataCallback frame_data_cb,
base::StringPiece animation_json)
: frame_data_cb_(std::move(frame_data_cb)),
image_asset_sizes_(ParseImageAssetDimensions(animation_json)) {}
SkottieMRUResourceProvider::~SkottieMRUResourceProvider() = default;
const SkottieResourceMetadataMap&
SkottieMRUResourceProvider::GetImageAssetMetadata() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return image_asset_metadata_;
}
sk_sp<skresources::ImageAsset> SkottieMRUResourceProvider::loadImageAsset(
const char resource_path[],
const char resource_name[],
const char resource_id[]) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
absl::optional<gfx::Size> size;
if (image_asset_sizes_.contains(resource_id))
size.emplace(image_asset_sizes_.at(resource_id));
if (!image_asset_metadata_.RegisterAsset(resource_path, resource_name,
resource_id, std::move(size))) {
return nullptr;
}
return sk_make_sp<ImageAssetImpl>(HashSkottieResourceId(resource_id),
frame_data_cb_);
}
} // namespace cc