mirror of
https://github.com/status-im/react-native.git
synced 2025-01-17 21:11:45 +00:00
67a79010ca
Summary: @public Previously, all ConcreteShadowNode subclasses had to override `getComponentName()` function to specialize a name of the component. And often it was all that those subclasses do. Now, it's a template argument; and many ShadowNode classes can be created as oneliners via *just* specializing ConcreteShadowNode template. Unfortunately, C++ does not allow to use `std::string`s or string literals as template arguments, but it allows to use pointers. Moreover, those pointers must point to some linked data, hence, those values must be declared in .cpp (not .h) files. For simplicity, we put those constants in Props classes, (but this is not a strong requirement). Reviewed By: mdvacca Differential Revision: D8942826 fbshipit-source-id: 4fd517e2485eb8f8c20a51df9b3496941856d8a5
90 lines
2.4 KiB
C++
90 lines
2.4 KiB
C++
/**
|
|
* 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 <cstdlib>
|
|
|
|
#include <fabric/components/image/ImageShadowNode.h>
|
|
#include <fabric/components/image/ImageLocalData.h>
|
|
#include <fabric/core/LayoutContext.h>
|
|
|
|
namespace facebook {
|
|
namespace react {
|
|
|
|
const char ImageComponentName[] = "Image";
|
|
|
|
void ImageShadowNode::setImageManager(const SharedImageManager &imageManager) {
|
|
ensureUnsealed();
|
|
imageManager_ = imageManager;
|
|
}
|
|
|
|
void ImageShadowNode::updateLocalData() {
|
|
const auto &imageSource = getImageSource();
|
|
const auto ¤tLocalData = getLocalData();
|
|
if (currentLocalData) {
|
|
assert(std::dynamic_pointer_cast<const ImageLocalData>(currentLocalData));
|
|
auto currentImageLocalData = std::static_pointer_cast<const ImageLocalData>(currentLocalData);
|
|
if (currentImageLocalData->getImageSource() == imageSource) {
|
|
// Same `imageSource` is already in `localData`,
|
|
// no need to (re)request an image resource.
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Now we are about to mutate the Shadow Node.
|
|
ensureUnsealed();
|
|
|
|
auto imageRequest = imageManager_->requestImage(imageSource);
|
|
auto imageLocalData = std::make_shared<ImageLocalData>(imageSource, std::move(imageRequest));
|
|
setLocalData(imageLocalData);
|
|
}
|
|
|
|
ImageSource ImageShadowNode::getImageSource() const {
|
|
auto sources = getProps()->sources;
|
|
|
|
if (sources.size() == 0) {
|
|
return {.type = ImageSource::Type::Invalid};
|
|
}
|
|
|
|
if (sources.size() == 1) {
|
|
return sources[0];
|
|
}
|
|
|
|
auto layoutMetrics = getLayoutMetrics();
|
|
auto size = layoutMetrics.getContentFrame().size;
|
|
auto scale = layoutMetrics.pointScaleFactor;
|
|
auto targetImageArea = size.width * size.height * scale * scale;
|
|
auto bestFit = kFloatMax;
|
|
|
|
ImageSource bestSource;
|
|
|
|
for (const auto &source : sources) {
|
|
auto sourceSize = source.size;
|
|
auto sourceScale = source.scale == 0 ? scale : source.scale;
|
|
auto sourceArea =
|
|
sourceSize.width * sourceSize.height * sourceScale * sourceScale;
|
|
|
|
auto fit = std::abs(1 - (sourceArea / targetImageArea));
|
|
|
|
if (fit < bestFit) {
|
|
bestFit = fit;
|
|
bestSource = source;
|
|
}
|
|
}
|
|
|
|
return bestSource;
|
|
}
|
|
|
|
#pragma mark - LayoutableShadowNode
|
|
|
|
void ImageShadowNode::layout(LayoutContext layoutContext) {
|
|
updateLocalData();
|
|
ConcreteViewShadowNode::layout(layoutContext);
|
|
}
|
|
|
|
} // namespace react
|
|
} // namespace facebook
|