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
This commit is contained in:
parent
eabf29e320
commit
979ea2094e
|
@ -7,9 +7,12 @@
|
|||
|
||||
#import "RCTScheduler.h"
|
||||
|
||||
#import <fabric/imagemanager/ImageManager.h>
|
||||
#import <fabric/uimanager/ContextContainer.h>
|
||||
#import <fabric/uimanager/Scheduler.h>
|
||||
#import <fabric/uimanager/SchedulerDelegate.h>
|
||||
#import <React/RCTImageLoader.h>
|
||||
#import <React/RCTBridge+Private.h>
|
||||
|
||||
#import "RCTConversions.h"
|
||||
|
||||
|
@ -44,6 +47,10 @@ private:
|
|||
_delegateProxy = std::make_shared<SchedulerDelegateProxy>((__bridge void *)self);
|
||||
|
||||
SharedContextContainer contextContainer = std::make_shared<ContextContainer>();
|
||||
|
||||
void *imageLoader = (__bridge void *)[[RCTBridge currentBridge] imageLoader];
|
||||
contextContainer->registerInstance(typeid(ImageManager), std::make_shared<ImageManager>(imageLoader));
|
||||
|
||||
_scheduler = std::make_shared<Scheduler>(contextContainer);
|
||||
_scheduler->setDelegate(_delegateProxy.get());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
load("//configurations/buck/apple:flag_defs.bzl", "OBJC_ARC_PREPROCESSOR_FLAGS", "get_application_ios_flags", "get_debug_preprocessor_flags")
|
||||
load("//ReactNative:DEFS.bzl", "ANDROID", "APPLE", "IS_OSS_BUILD", "get_apple_inspector_flags", "react_native_xplat_target", "rn_xplat_cxx_library")
|
||||
|
||||
APPLE_COMPILER_FLAGS = []
|
||||
|
||||
if not IS_OSS_BUILD:
|
||||
load("@xplat//configurations/buck/apple:flag_defs.bzl", "flags", "get_static_library_ios_flags")
|
||||
|
||||
APPLE_COMPILER_FLAGS = flags.get_flag_value(get_static_library_ios_flags(), "compiler_flags")
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "imagemanager",
|
||||
srcs = glob(
|
||||
[
|
||||
"*.cpp",
|
||||
],
|
||||
exclude = glob(["tests/**/*.cpp"]),
|
||||
),
|
||||
header_namespace = "",
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
"-std=c++14",
|
||||
"-Wall",
|
||||
],
|
||||
fbandroid_exported_headers = subdir_glob(
|
||||
[
|
||||
("", "*.h"),
|
||||
],
|
||||
prefix = "fabric/imagemanager",
|
||||
),
|
||||
fbandroid_headers = subdir_glob(
|
||||
[
|
||||
("", "*.h"),
|
||||
("platform/android", "**/*.h"),
|
||||
],
|
||||
prefix = "",
|
||||
),
|
||||
fbandroid_srcs = glob(
|
||||
[
|
||||
"platform/android/**/*.cpp",
|
||||
],
|
||||
),
|
||||
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,
|
||||
fbobjc_preprocessor_flags = get_debug_preprocessor_flags() + get_apple_inspector_flags(),
|
||||
fbobjc_tests = [
|
||||
":tests",
|
||||
],
|
||||
force_static = True,
|
||||
frameworks = [
|
||||
"$SDKROOT/System/Library/Frameworks/CoreGraphics.framework",
|
||||
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
|
||||
"$SDKROOT/System/Library/Frameworks/UIKit.framework",
|
||||
],
|
||||
ios_deps = [
|
||||
"xplat//js:RCTImage",
|
||||
"xplat//js/react-native-github:RCTCxxBridge",
|
||||
],
|
||||
ios_exported_headers = subdir_glob(
|
||||
[
|
||||
("", "*.h"),
|
||||
("platform/ios", "RCTImagePrimitivesConversions.h"),
|
||||
],
|
||||
prefix = "fabric/imagemanager",
|
||||
),
|
||||
ios_headers = subdir_glob(
|
||||
[
|
||||
("", "*.h"),
|
||||
("platform/ios", "**/*.h"),
|
||||
],
|
||||
prefix = "",
|
||||
),
|
||||
ios_srcs = glob(
|
||||
[
|
||||
"platform/ios/**/*.cpp",
|
||||
"platform/ios/**/*.mm",
|
||||
],
|
||||
),
|
||||
macosx_tests_override = [],
|
||||
platforms = (ANDROID, APPLE),
|
||||
preprocessor_flags = [
|
||||
"-DLOG_TAG=\"ReactNative\"",
|
||||
"-DWITH_FBSYSTRACE=1",
|
||||
],
|
||||
tests = [],
|
||||
visibility = ["PUBLIC"],
|
||||
deps = [
|
||||
"xplat//fbsystrace:fbsystrace",
|
||||
"xplat//folly:futures",
|
||||
"xplat//folly:headers_only",
|
||||
"xplat//folly:memory",
|
||||
"xplat//folly:molly",
|
||||
"xplat//third-party/glog:glog",
|
||||
"xplat//yoga:yoga",
|
||||
react_native_xplat_target("fabric/core:core"),
|
||||
react_native_xplat_target("fabric/debug:debug"),
|
||||
react_native_xplat_target("fabric/graphics:graphics"),
|
||||
],
|
||||
)
|
||||
|
||||
if not IS_OSS_BUILD:
|
||||
load("@xplat//build_defs:fb_xplat_cxx_test.bzl", "fb_xplat_cxx_test")
|
||||
|
||||
fb_xplat_cxx_test(
|
||||
name = "tests",
|
||||
srcs = glob(["tests/**/*.cpp"]),
|
||||
headers = glob(["tests/**/*.h"]),
|
||||
contacts = ["oncall+react_native@xmail.facebook.com"],
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
"-std=c++14",
|
||||
"-Wall",
|
||||
],
|
||||
platforms = APPLE,
|
||||
deps = [
|
||||
"xplat//folly:molly",
|
||||
"xplat//third-party/gmock:gtest",
|
||||
":imagemanager",
|
||||
],
|
||||
)
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <fabric/imagemanager/ImageRequest.h>
|
||||
#include <fabric/imagemanager/primitives.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class ImageManager;
|
||||
|
||||
using SharedImageManager = std::shared_ptr<ImageManager>;
|
||||
|
||||
/*
|
||||
* Cross platform facade for iOS-specific RCTImageManager.
|
||||
*/
|
||||
class ImageManager {
|
||||
public:
|
||||
|
||||
ImageManager(void *platformSpecificCounterpart);
|
||||
~ImageManager();
|
||||
|
||||
ImageRequest requestImage(const ImageSource &imageSource) const;
|
||||
|
||||
private:
|
||||
void *self_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "ImageRequest.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class ImageRequest::ImageNoLongerNeededException:
|
||||
public std::logic_error {
|
||||
public:
|
||||
ImageNoLongerNeededException():
|
||||
std::logic_error("Image no longer needed.") {}
|
||||
};
|
||||
|
||||
ImageRequest::ImageRequest(const ImageSource &imageSource, folly::Future<ImageResponse> &&responseFuture):
|
||||
imageSource_(imageSource),
|
||||
responseFutureSplitter_(folly::splitFuture(std::move(responseFuture))) {}
|
||||
|
||||
ImageRequest::ImageRequest(ImageRequest &&other) noexcept:
|
||||
imageSource_(std::move(other.imageSource_)),
|
||||
responseFutureSplitter_(std::move(other.responseFutureSplitter_)) {
|
||||
other.moved_ = true;
|
||||
};
|
||||
|
||||
ImageRequest::~ImageRequest() {
|
||||
if (!moved_) {
|
||||
auto future = responseFutureSplitter_.getFuture();
|
||||
if (!future.isReady()) {
|
||||
future.raise(ImageNoLongerNeededException());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
folly::Future<ImageResponse> ImageRequest::getResponseFuture() const {
|
||||
if (moved_) {
|
||||
abort();
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
return responseFutureSplitter_.getFuture();
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <fabric/imagemanager/ImageResponse.h>
|
||||
#include <fabric/imagemanager/primitives.h>
|
||||
#include <folly/futures/Future.h>
|
||||
#include <folly/futures/FutureSplitter.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Represents ongoing request for an image resource.
|
||||
* The separate object must be constructed for every single separate
|
||||
* image request. The object cannot be copied because it would make managing of
|
||||
* event listeners hard and inefficient; the object can be moved though.
|
||||
* To subscribe for notifications use `getResponseFuture()` method.
|
||||
* Destroy to cancel the underlying request.
|
||||
*/
|
||||
class ImageRequest final {
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
* The exception which is thrown when `ImageRequest` is being deallocated
|
||||
* if the future is not ready yet.
|
||||
*/
|
||||
class ImageNoLongerNeededException;
|
||||
|
||||
/*
|
||||
* `ImageRequest` is constructed with `ImageSource` and
|
||||
* `ImageResponse` future which must be moved in inside the object.
|
||||
*/
|
||||
ImageRequest(const ImageSource &imageSource, folly::Future<ImageResponse> &&responseFuture);
|
||||
|
||||
/*
|
||||
* The move constructor.
|
||||
*/
|
||||
ImageRequest(ImageRequest &&other) noexcept;
|
||||
|
||||
/*
|
||||
* `ImageRequest` does not support copying by design.
|
||||
*/
|
||||
ImageRequest(const ImageRequest &) = delete;
|
||||
|
||||
~ImageRequest();
|
||||
|
||||
/*
|
||||
* Creates and returns a *new* future object with promised `ImageResponse`
|
||||
* result. Multiple consumers can call this method many times to create
|
||||
* their own subscriptions to promised value.
|
||||
*/
|
||||
folly::Future<ImageResponse> getResponseFuture() const;
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
* Mutext to protect an access to the future.
|
||||
*/
|
||||
mutable std::mutex mutex_;
|
||||
|
||||
/*
|
||||
* Image source assosiated with the request.
|
||||
*/
|
||||
ImageSource imageSource_;
|
||||
|
||||
/*
|
||||
* Future splitter powers factory-like `getResponseFuture()` method.
|
||||
*/
|
||||
mutable folly::FutureSplitter<ImageResponse> responseFutureSplitter_;
|
||||
|
||||
/*
|
||||
* Indicates that the object was moved and hence cannot be used anymore.
|
||||
*/
|
||||
bool moved_ {false};
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "ImageResponse.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
ImageResponse::ImageResponse(const std::shared_ptr<void> &image):
|
||||
image_(image) {}
|
||||
|
||||
std::shared_ptr<void> ImageResponse::getImage() const {
|
||||
return image_;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <memory>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Represents retrieved image bitmap and any assotiated platform-specific info.
|
||||
*/
|
||||
class ImageResponse final {
|
||||
|
||||
public:
|
||||
ImageResponse(const std::shared_ptr<void> &image);
|
||||
|
||||
std::shared_ptr<void> getImage() const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<void> image_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "ImageManager.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
ImageManager::ImageManager(void *platformSpecificCounterpart) {
|
||||
// Not implemented.
|
||||
}
|
||||
|
||||
ImageManager::~ImageManager() {
|
||||
// Not implemented.
|
||||
}
|
||||
|
||||
ImageRequest ImageManager::requestImage(const ImageSource &imageSource) const {
|
||||
// Not implemented.
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "ImageManager.h"
|
||||
|
||||
#import <React/RCTImageLoader.h>
|
||||
|
||||
#import "RCTImageManager.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
ImageManager::ImageManager(void *platformSpecificCounterpart) {
|
||||
self_ = (__bridge_retained void *)[[RCTImageManager alloc] initWithImageLoader:(__bridge_transfer RCTImageLoader *)platformSpecificCounterpart];
|
||||
}
|
||||
|
||||
ImageManager::~ImageManager() {
|
||||
CFRelease(self_);
|
||||
self_ = nullptr;
|
||||
}
|
||||
|
||||
ImageRequest ImageManager::requestImage(const ImageSource &imageSource) const {
|
||||
RCTImageManager *imageManager = (__bridge RCTImageManager *)self_;
|
||||
return [imageManager requestImage:imageSource];
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <fabric/imagemanager/ImageRequest.h>
|
||||
#import <fabric/imagemanager/primitives.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class RCTImageLoader;
|
||||
|
||||
/**
|
||||
* iOS-specific ImageManager.
|
||||
*/
|
||||
@interface RCTImageManager : NSObject
|
||||
|
||||
- (instancetype)initWithImageLoader:(RCTImageLoader *)imageLoader;
|
||||
|
||||
- (facebook::react::ImageRequest)requestImage:(const facebook::react::ImageSource &)imageSource;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTImageManager.h"
|
||||
|
||||
#import <folly/futures/Future.h>
|
||||
#import <folly/futures/Promise.h>
|
||||
|
||||
#import <React/RCTImageLoader.h>
|
||||
|
||||
#import "RCTImagePrimitivesConversions.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@implementation RCTImageManager
|
||||
{
|
||||
RCTImageLoader *_imageLoader;
|
||||
}
|
||||
|
||||
- (instancetype)initWithImageLoader:(RCTImageLoader *)imageLoader
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_imageLoader = imageLoader;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (ImageRequest)requestImage:(const ImageSource &)imageSource
|
||||
{
|
||||
__block auto promise = folly::Promise<ImageResponse>();
|
||||
|
||||
NSURLRequest *request = NSURLRequestFromImageSource(imageSource);
|
||||
|
||||
auto completionBlock = ^(NSError *error, UIImage *image) {
|
||||
auto imageResponse = ImageResponse(std::shared_ptr<void>((__bridge_retained void *)image, CFRelease));
|
||||
promise.setValue(std::move(imageResponse));
|
||||
};
|
||||
|
||||
auto interruptBlock = ^(const folly::exception_wrapper &exceptionWrapper) {
|
||||
if (!promise.isFulfilled()) {
|
||||
promise.setException(exceptionWrapper);
|
||||
}
|
||||
};
|
||||
|
||||
RCTImageLoaderCancellationBlock cancellationBlock =
|
||||
[_imageLoader loadImageWithURLRequest:request
|
||||
size:CGSizeMake(imageSource.size.width, imageSource.size.height)
|
||||
scale:imageSource.scale
|
||||
clipped:YES
|
||||
resizeMode:RCTResizeModeStretch
|
||||
progressBlock:nil
|
||||
partialLoadBlock:nil
|
||||
completionBlock:completionBlock];
|
||||
|
||||
promise.setInterruptHandler([cancellationBlock, interruptBlock](const folly::exception_wrapper &exceptionWrapper) {
|
||||
cancellationBlock();
|
||||
interruptBlock(exceptionWrapper);
|
||||
});
|
||||
|
||||
return ImageRequest(imageSource, promise.getFuture());
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <fabric/imagemanager/primitives.h>
|
||||
#import <React/RCTImageLoader.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
inline static RCTResizeMode RCTResizeModeFromImageResizeMode(ImageResizeMode imageResizeMode) {
|
||||
switch (imageResizeMode) {
|
||||
case ImageResizeMode::Cover: return RCTResizeModeCover;
|
||||
case ImageResizeMode::Contain: return RCTResizeModeContain;
|
||||
case ImageResizeMode::Stretch: return RCTResizeModeStretch;
|
||||
case ImageResizeMode::Center: return RCTResizeModeCenter;
|
||||
case ImageResizeMode::Repeat: return RCTResizeModeRepeat;
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string toString(const ImageResizeMode &value) {
|
||||
switch (value) {
|
||||
case ImageResizeMode::Cover: return "cover";
|
||||
case ImageResizeMode::Contain: return "contain";
|
||||
case ImageResizeMode::Stretch: return "stretch";
|
||||
case ImageResizeMode::Center: return "center";
|
||||
case ImageResizeMode::Repeat: return "repeat";
|
||||
}
|
||||
}
|
||||
|
||||
inline static NSURLRequest *NSURLRequestFromImageSource(const ImageSource &imageSource) {
|
||||
|
||||
NSString *urlString = [NSString stringWithCString:imageSource.uri.c_str()
|
||||
encoding:NSASCIIStringEncoding];
|
||||
|
||||
if (!imageSource.bundle.empty()) {
|
||||
NSString *bundle = [NSString stringWithCString:imageSource.bundle.c_str()
|
||||
encoding:NSASCIIStringEncoding];
|
||||
urlString = [NSString stringWithFormat:@"%@.bundle/%@", bundle, urlString];
|
||||
}
|
||||
|
||||
NSURL *url = [[NSURL alloc] initWithString:urlString];
|
||||
|
||||
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
|
||||
|
||||
/*
|
||||
// TODO(shergin): To be implemented.
|
||||
request.HTTPBody = ...;
|
||||
request.HTTPMethod = ...;
|
||||
request.cachePolicy = ...;
|
||||
request.allHTTPHeaderFields = ...;
|
||||
*/
|
||||
|
||||
return [request copy];
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <fabric/graphics/Geometry.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class ImageSource {
|
||||
|
||||
public:
|
||||
enum class Type {
|
||||
Invalid,
|
||||
Remote,
|
||||
Local
|
||||
};
|
||||
|
||||
Type type {};
|
||||
std::string uri {};
|
||||
std::string bundle {};
|
||||
Float scale {3};
|
||||
Size size {0};
|
||||
|
||||
bool operator==(const ImageSource &rhs) const {
|
||||
return
|
||||
std::tie(this->type, this->uri) ==
|
||||
std::tie(rhs.type, rhs.uri);
|
||||
}
|
||||
|
||||
bool operator!=(const ImageSource &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
using ImageSources = std::vector<ImageSource>;
|
||||
|
||||
enum class ImageResizeMode {
|
||||
Cover,
|
||||
Contain,
|
||||
Stretch,
|
||||
Center,
|
||||
Repeat,
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <fabric/imagemanager/ImageManager.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
TEST(ImageManagerTest, testSomething) {
|
||||
// TODO:
|
||||
}
|
Loading…
Reference in New Issue