From b846709f1490a8c010548588a8515e4649562acc Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Tue, 26 Nov 2024 10:55:14 -0800 Subject: [PATCH] Add Android-specific ImageRequestParams (#47930) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/47930 This diff adds a list of props that will be used by the Android `ImagePrefetcher` to create an `ImageRequest`. This list is derived from all the props that `ReactImageView` uses to create its `ImageOptions` and `ImageRequest` objects. Changelog: [Internal] Reviewed By: javache Differential Revision: D66453306 --- .../components/image/ImageShadowNode.cpp | 19 +++- .../renderer/imagemanager/CMakeLists.txt | 4 +- .../platform/android/ImageRequestParams.h | 30 ------ .../renderer/imagemanager}/ImageManager.cpp | 0 .../imagemanager/ImageRequestParams.h | 94 ++++++++++++++++ .../react/renderer/imagemanager/conversions.h | 100 ++++++++++++++++++ 6 files changed, 214 insertions(+), 33 deletions(-) delete mode 100644 packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/ImageRequestParams.h rename packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/{ => react/renderer/imagemanager}/ImageManager.cpp (100%) create mode 100644 packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageRequestParams.h create mode 100644 packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/conversions.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/image/ImageShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/image/ImageShadowNode.cpp index b67fe6ed34043e..5fda3ac141ab3f 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/image/ImageShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/image/ImageShadowNode.cpp @@ -30,7 +30,24 @@ void ImageShadowNode::updateStateIfNeeded() { auto newImageSource = getImageSource(); const auto& oldImageRequestParams = savedState.getImageRequestParams(); const auto& imageProps = getConcreteProps(); - const auto& newImageRequestParams = ImageRequestParams(imageProps.blurRadius); + const auto& newImageRequestParams = ImageRequestParams( + imageProps.blurRadius +#ifdef ANDROID + , + imageProps.defaultSource, + imageProps.resizeMode, + imageProps.resizeMethod, + // TODO: should we resizeMultiplier * imageSource.scale ? + imageProps.resizeMultiplier, + imageProps.shouldNotify, + imageProps.overlayColor, + imageProps.tintColor, + imageProps.fadeDuration, + imageProps.progressiveRenderingEnabled, + imageProps.loadingIndicatorSource, + imageProps.internal_analyticTag +#endif + ); if (oldImageSource == newImageSource && oldImageRequestParams == newImageRequestParams) { diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/CMakeLists.txt b/packages/react-native/ReactCommon/react/renderer/imagemanager/CMakeLists.txt index d51ddc1caf1047..3275af2c7cf565 100644 --- a/packages/react-native/ReactCommon/react/renderer/imagemanager/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/renderer/imagemanager/CMakeLists.txt @@ -16,7 +16,7 @@ add_compile_options( file(GLOB react_render_imagemanager_SRC CONFIGURE_DEPENDS *.cpp - platform/cxx/react/renderer/imagemanager/*.cpp) + platform/android/react/renderer/imagemanager/*.cpp) add_library(react_render_imagemanager OBJECT @@ -25,7 +25,7 @@ add_library(react_render_imagemanager target_include_directories(react_render_imagemanager PUBLIC ${REACT_COMMON_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/platform/cxx/ + ${CMAKE_CURRENT_SOURCE_DIR}/platform/android/ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/ImageRequestParams.h b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/ImageRequestParams.h deleted file mode 100644 index 84f3eba1750e4c..00000000000000 --- a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/ImageRequestParams.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * 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 - -namespace facebook::react { - -class ImageRequestParams { - public: - ImageRequestParams() = default; - ImageRequestParams(Float blurRadius) : blurRadius(blurRadius) {} - - Float blurRadius{}; - - bool operator==(const ImageRequestParams& rhs) const { - return this->blurRadius == rhs.blurRadius; - } - - bool operator!=(const ImageRequestParams& rhs) const { - return !(*this == rhs); - } -}; - -} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/ImageManager.cpp b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageManager.cpp similarity index 100% rename from packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/ImageManager.cpp rename to packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageManager.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageRequestParams.h b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageRequestParams.h new file mode 100644 index 00000000000000..6036262de2e525 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageRequestParams.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * 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 + +#include +#include +#include + +namespace facebook::react { + +class ImageRequestParams { + public: + ImageRequestParams() = default; + ImageRequestParams( + Float blurRadius, + ImageSource defaultSource, + ImageResizeMode resizeMode, + std::string resizeMethod, + Float resizeMultiplier, + bool shouldNotify, + SharedColor overlayColor, + SharedColor tintColor, + Float fadeDuration, + bool progressiveRenderingEnabled, + ImageSource loadingIndicatorSource, + std::string analyticTag) + : blurRadius(blurRadius), + defaultSource(std::move(defaultSource)), + resizeMode(resizeMode), + resizeMethod(std::move(resizeMethod)), + resizeMultiplier(resizeMultiplier), + shouldNotify(shouldNotify), + overlayColor(overlayColor), + tintColor(tintColor), + fadeDuration(fadeDuration), + progressiveRenderingEnabled(progressiveRenderingEnabled), + loadingIndicatorSource(std::move(loadingIndicatorSource)), + analyticTag(std::move(analyticTag)) {} + + Float blurRadius{}; + ImageSource defaultSource{}; + ImageResizeMode resizeMode{ImageResizeMode::Stretch}; + std::string resizeMethod{}; + Float resizeMultiplier{}; + bool shouldNotify{}; + SharedColor overlayColor{}; + SharedColor tintColor{}; + Float fadeDuration{}; + bool progressiveRenderingEnabled{}; + ImageSource loadingIndicatorSource{}; + std::string analyticTag{}; + + bool operator==(const ImageRequestParams& rhs) const { + return std::tie( + this->blurRadius, + this->defaultSource, + this->resizeMode, + this->resizeMethod, + this->resizeMultiplier, + this->shouldNotify, + this->overlayColor, + this->tintColor, + this->fadeDuration, + this->progressiveRenderingEnabled, + this->loadingIndicatorSource, + this->analyticTag) == + std::tie( + rhs.blurRadius, + rhs.defaultSource, + rhs.resizeMode, + rhs.resizeMethod, + rhs.resizeMultiplier, + rhs.shouldNotify, + rhs.overlayColor, + rhs.tintColor, + rhs.fadeDuration, + rhs.progressiveRenderingEnabled, + rhs.loadingIndicatorSource, + rhs.analyticTag); + } + + bool operator!=(const ImageRequestParams& rhs) const { + return !(*this == rhs); + } +}; + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/conversions.h b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/conversions.h new file mode 100644 index 00000000000000..1eac2a62398dd2 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/conversions.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * 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 + +#include +#include +#include +#include +#include + +namespace facebook::react { + +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"; + case ImageResizeMode::None: + return "none"; + } +} + +constexpr static MapBuffer::Key IS_KEY_URI = 0; +constexpr static MapBuffer::Key IS_KEY_DEFAULT_SRC = 1; +constexpr static MapBuffer::Key IS_KEY_RESIZE_MODE = 2; +constexpr static MapBuffer::Key IS_KEY_RESIZE_METHOD = 3; +constexpr static MapBuffer::Key IS_KEY_BLUR_RADIUS = 4; +constexpr static MapBuffer::Key IS_KEY_VIEW_WIDTH = 5; +constexpr static MapBuffer::Key IS_KEY_VIEW_HEIGHT = 6; +constexpr static MapBuffer::Key IS_KEY_RESIZE_MULTIPLIER = 7; +constexpr static MapBuffer::Key IS_KEY_SHOULD_NOTIFY_LOAD_EVENTS = 8; +constexpr static MapBuffer::Key IS_KEY_OVERLAY_COLOR = 9; +constexpr static MapBuffer::Key IS_KEY_TINT_COLOR = 10; +constexpr static MapBuffer::Key IS_KEY_FADE_DURATION = 11; +constexpr static MapBuffer::Key IS_KEY_PROGRESSIVE_RENDERING_ENABLED = 12; +constexpr static MapBuffer::Key IS_KEY_LOADING_INDICATOR_SRC = 13; +constexpr static MapBuffer::Key IS_KEY_ANALYTIC_TAG = 14; + +inline void serializeImageSource( + MapBufferBuilder& builder, + const ImageSource& imageSource) { + builder.putString(IS_KEY_URI, imageSource.uri); + builder.putDouble(IS_KEY_VIEW_WIDTH, imageSource.size.width); + builder.putDouble(IS_KEY_VIEW_HEIGHT, imageSource.size.height); +} + +inline void serializeImageRequestParams( + MapBufferBuilder& builder, + const ImageRequestParams& imageRequestParams) { + builder.putString(IS_KEY_DEFAULT_SRC, imageRequestParams.defaultSource.uri); + builder.putString( + IS_KEY_RESIZE_MODE, toString(imageRequestParams.resizeMode)); + builder.putString(IS_KEY_RESIZE_METHOD, imageRequestParams.resizeMethod); + builder.putDouble(IS_KEY_BLUR_RADIUS, imageRequestParams.blurRadius); + builder.putDouble( + IS_KEY_RESIZE_MULTIPLIER, imageRequestParams.resizeMultiplier); + builder.putBool( + IS_KEY_SHOULD_NOTIFY_LOAD_EVENTS, imageRequestParams.shouldNotify); + if (isColorMeaningful(imageRequestParams.overlayColor)) { + builder.putInt( + IS_KEY_OVERLAY_COLOR, toAndroidRepr(imageRequestParams.overlayColor)); + } + if (isColorMeaningful(imageRequestParams.tintColor)) { + builder.putInt( + IS_KEY_TINT_COLOR, toAndroidRepr(imageRequestParams.tintColor)); + } + builder.putDouble(IS_KEY_FADE_DURATION, imageRequestParams.fadeDuration); + builder.putBool( + IS_KEY_PROGRESSIVE_RENDERING_ENABLED, + imageRequestParams.progressiveRenderingEnabled); + builder.putString( + IS_KEY_LOADING_INDICATOR_SRC, + imageRequestParams.loadingIndicatorSource.uri); + builder.putString(IS_KEY_ANALYTIC_TAG, imageRequestParams.analyticTag); +} + +inline MapBuffer serializeImageRequest( + const ImageSource& imageSource, + const ImageRequestParams& imageRequestParams) { + auto builder = MapBufferBuilder(); + serializeImageSource(builder, imageSource); + serializeImageRequestParams(builder, imageRequestParams); + return builder.build(); +} + +} // namespace facebook::react