Skip to content

Commit 979ea20

Browse files
sherginfacebook-github-bot
authored andcommitted
Fabric: Introducing ImageManager
Summary: @public ImageManager coordinates all work related to loading image bitmaps for <Image> component. The particular iOS implementation uses RCTImageLoader from RCTImage module under the hood. Reviewed By: fkgozali Differential Revision: D8526571 fbshipit-source-id: a0d927972d30113eed6e0cd169fceee17610181d
1 parent eabf29e commit 979ea20

File tree

14 files changed

+637
-0
lines changed

14 files changed

+637
-0
lines changed

React/Fabric/RCTScheduler.mm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77

88
#import "RCTScheduler.h"
99

10+
#import <fabric/imagemanager/ImageManager.h>
1011
#import <fabric/uimanager/ContextContainer.h>
1112
#import <fabric/uimanager/Scheduler.h>
1213
#import <fabric/uimanager/SchedulerDelegate.h>
14+
#import <React/RCTImageLoader.h>
15+
#import <React/RCTBridge+Private.h>
1316

1417
#import "RCTConversions.h"
1518

@@ -44,6 +47,10 @@ - (instancetype)init
4447
_delegateProxy = std::make_shared<SchedulerDelegateProxy>((__bridge void *)self);
4548

4649
SharedContextContainer contextContainer = std::make_shared<ContextContainer>();
50+
51+
void *imageLoader = (__bridge void *)[[RCTBridge currentBridge] imageLoader];
52+
contextContainer->registerInstance(typeid(ImageManager), std::make_shared<ImageManager>(imageLoader));
53+
4754
_scheduler = std::make_shared<Scheduler>(contextContainer);
4855
_scheduler->setDelegate(_delegateProxy.get());
4956
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
load("//configurations/buck/apple:flag_defs.bzl", "OBJC_ARC_PREPROCESSOR_FLAGS", "get_application_ios_flags", "get_debug_preprocessor_flags")
2+
load("//ReactNative:DEFS.bzl", "ANDROID", "APPLE", "IS_OSS_BUILD", "get_apple_inspector_flags", "react_native_xplat_target", "rn_xplat_cxx_library")
3+
4+
APPLE_COMPILER_FLAGS = []
5+
6+
if not IS_OSS_BUILD:
7+
load("@xplat//configurations/buck/apple:flag_defs.bzl", "flags", "get_static_library_ios_flags")
8+
9+
APPLE_COMPILER_FLAGS = flags.get_flag_value(get_static_library_ios_flags(), "compiler_flags")
10+
11+
rn_xplat_cxx_library(
12+
name = "imagemanager",
13+
srcs = glob(
14+
[
15+
"*.cpp",
16+
],
17+
exclude = glob(["tests/**/*.cpp"]),
18+
),
19+
header_namespace = "",
20+
compiler_flags = [
21+
"-fexceptions",
22+
"-frtti",
23+
"-std=c++14",
24+
"-Wall",
25+
],
26+
fbandroid_exported_headers = subdir_glob(
27+
[
28+
("", "*.h"),
29+
],
30+
prefix = "fabric/imagemanager",
31+
),
32+
fbandroid_headers = subdir_glob(
33+
[
34+
("", "*.h"),
35+
("platform/android", "**/*.h"),
36+
],
37+
prefix = "",
38+
),
39+
fbandroid_srcs = glob(
40+
[
41+
"platform/android/**/*.cpp",
42+
],
43+
),
44+
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,
45+
fbobjc_preprocessor_flags = get_debug_preprocessor_flags() + get_apple_inspector_flags(),
46+
fbobjc_tests = [
47+
":tests",
48+
],
49+
force_static = True,
50+
frameworks = [
51+
"$SDKROOT/System/Library/Frameworks/CoreGraphics.framework",
52+
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
53+
"$SDKROOT/System/Library/Frameworks/UIKit.framework",
54+
],
55+
ios_deps = [
56+
"xplat//js:RCTImage",
57+
"xplat//js/react-native-github:RCTCxxBridge",
58+
],
59+
ios_exported_headers = subdir_glob(
60+
[
61+
("", "*.h"),
62+
("platform/ios", "RCTImagePrimitivesConversions.h"),
63+
],
64+
prefix = "fabric/imagemanager",
65+
),
66+
ios_headers = subdir_glob(
67+
[
68+
("", "*.h"),
69+
("platform/ios", "**/*.h"),
70+
],
71+
prefix = "",
72+
),
73+
ios_srcs = glob(
74+
[
75+
"platform/ios/**/*.cpp",
76+
"platform/ios/**/*.mm",
77+
],
78+
),
79+
macosx_tests_override = [],
80+
platforms = (ANDROID, APPLE),
81+
preprocessor_flags = [
82+
"-DLOG_TAG=\"ReactNative\"",
83+
"-DWITH_FBSYSTRACE=1",
84+
],
85+
tests = [],
86+
visibility = ["PUBLIC"],
87+
deps = [
88+
"xplat//fbsystrace:fbsystrace",
89+
"xplat//folly:futures",
90+
"xplat//folly:headers_only",
91+
"xplat//folly:memory",
92+
"xplat//folly:molly",
93+
"xplat//third-party/glog:glog",
94+
"xplat//yoga:yoga",
95+
react_native_xplat_target("fabric/core:core"),
96+
react_native_xplat_target("fabric/debug:debug"),
97+
react_native_xplat_target("fabric/graphics:graphics"),
98+
],
99+
)
100+
101+
if not IS_OSS_BUILD:
102+
load("@xplat//build_defs:fb_xplat_cxx_test.bzl", "fb_xplat_cxx_test")
103+
104+
fb_xplat_cxx_test(
105+
name = "tests",
106+
srcs = glob(["tests/**/*.cpp"]),
107+
headers = glob(["tests/**/*.h"]),
108+
contacts = ["oncall+react_native@xmail.facebook.com"],
109+
compiler_flags = [
110+
"-fexceptions",
111+
"-frtti",
112+
"-std=c++14",
113+
"-Wall",
114+
],
115+
platforms = APPLE,
116+
deps = [
117+
"xplat//folly:molly",
118+
"xplat//third-party/gmock:gtest",
119+
":imagemanager",
120+
],
121+
)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <memory>
11+
12+
#include <fabric/imagemanager/ImageRequest.h>
13+
#include <fabric/imagemanager/primitives.h>
14+
15+
namespace facebook {
16+
namespace react {
17+
18+
class ImageManager;
19+
20+
using SharedImageManager = std::shared_ptr<ImageManager>;
21+
22+
/*
23+
* Cross platform facade for iOS-specific RCTImageManager.
24+
*/
25+
class ImageManager {
26+
public:
27+
28+
ImageManager(void *platformSpecificCounterpart);
29+
~ImageManager();
30+
31+
ImageRequest requestImage(const ImageSource &imageSource) const;
32+
33+
private:
34+
void *self_;
35+
};
36+
37+
} // namespace react
38+
} // namespace facebook
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include "ImageRequest.h"
9+
10+
namespace facebook {
11+
namespace react {
12+
13+
class ImageRequest::ImageNoLongerNeededException:
14+
public std::logic_error {
15+
public:
16+
ImageNoLongerNeededException():
17+
std::logic_error("Image no longer needed.") {}
18+
};
19+
20+
ImageRequest::ImageRequest(const ImageSource &imageSource, folly::Future<ImageResponse> &&responseFuture):
21+
imageSource_(imageSource),
22+
responseFutureSplitter_(folly::splitFuture(std::move(responseFuture))) {}
23+
24+
ImageRequest::ImageRequest(ImageRequest &&other) noexcept:
25+
imageSource_(std::move(other.imageSource_)),
26+
responseFutureSplitter_(std::move(other.responseFutureSplitter_)) {
27+
other.moved_ = true;
28+
};
29+
30+
ImageRequest::~ImageRequest() {
31+
if (!moved_) {
32+
auto future = responseFutureSplitter_.getFuture();
33+
if (!future.isReady()) {
34+
future.raise(ImageNoLongerNeededException());
35+
}
36+
}
37+
}
38+
39+
folly::Future<ImageResponse> ImageRequest::getResponseFuture() const {
40+
if (moved_) {
41+
abort();
42+
}
43+
44+
std::lock_guard<std::mutex> lock(mutex_);
45+
return responseFutureSplitter_.getFuture();
46+
}
47+
48+
} // namespace react
49+
} // namespace facebook
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <mutex>
11+
12+
#include <fabric/imagemanager/ImageResponse.h>
13+
#include <fabric/imagemanager/primitives.h>
14+
#include <folly/futures/Future.h>
15+
#include <folly/futures/FutureSplitter.h>
16+
17+
namespace facebook {
18+
namespace react {
19+
20+
/*
21+
* Represents ongoing request for an image resource.
22+
* The separate object must be constructed for every single separate
23+
* image request. The object cannot be copied because it would make managing of
24+
* event listeners hard and inefficient; the object can be moved though.
25+
* To subscribe for notifications use `getResponseFuture()` method.
26+
* Destroy to cancel the underlying request.
27+
*/
28+
class ImageRequest final {
29+
30+
public:
31+
32+
/*
33+
* The exception which is thrown when `ImageRequest` is being deallocated
34+
* if the future is not ready yet.
35+
*/
36+
class ImageNoLongerNeededException;
37+
38+
/*
39+
* `ImageRequest` is constructed with `ImageSource` and
40+
* `ImageResponse` future which must be moved in inside the object.
41+
*/
42+
ImageRequest(const ImageSource &imageSource, folly::Future<ImageResponse> &&responseFuture);
43+
44+
/*
45+
* The move constructor.
46+
*/
47+
ImageRequest(ImageRequest &&other) noexcept;
48+
49+
/*
50+
* `ImageRequest` does not support copying by design.
51+
*/
52+
ImageRequest(const ImageRequest &) = delete;
53+
54+
~ImageRequest();
55+
56+
/*
57+
* Creates and returns a *new* future object with promised `ImageResponse`
58+
* result. Multiple consumers can call this method many times to create
59+
* their own subscriptions to promised value.
60+
*/
61+
folly::Future<ImageResponse> getResponseFuture() const;
62+
63+
private:
64+
65+
/*
66+
* Mutext to protect an access to the future.
67+
*/
68+
mutable std::mutex mutex_;
69+
70+
/*
71+
* Image source assosiated with the request.
72+
*/
73+
ImageSource imageSource_;
74+
75+
/*
76+
* Future splitter powers factory-like `getResponseFuture()` method.
77+
*/
78+
mutable folly::FutureSplitter<ImageResponse> responseFutureSplitter_;
79+
80+
/*
81+
* Indicates that the object was moved and hence cannot be used anymore.
82+
*/
83+
bool moved_ {false};
84+
};
85+
86+
} // namespace react
87+
} // namespace facebook
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include "ImageResponse.h"
9+
10+
namespace facebook {
11+
namespace react {
12+
13+
ImageResponse::ImageResponse(const std::shared_ptr<void> &image):
14+
image_(image) {}
15+
16+
std::shared_ptr<void> ImageResponse::getImage() const {
17+
return image_;
18+
}
19+
20+
} // namespace react
21+
} // namespace facebook
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import <memory>
9+
10+
namespace facebook {
11+
namespace react {
12+
13+
/*
14+
* Represents retrieved image bitmap and any assotiated platform-specific info.
15+
*/
16+
class ImageResponse final {
17+
18+
public:
19+
ImageResponse(const std::shared_ptr<void> &image);
20+
21+
std::shared_ptr<void> getImage() const;
22+
23+
private:
24+
std::shared_ptr<void> image_;
25+
};
26+
27+
} // namespace react
28+
} // namespace facebook

0 commit comments

Comments
 (0)