/** * 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 #include #include #include namespace facebook { namespace react { ComponentName ImageShadowNode::getComponentName() const { return ComponentName("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(currentLocalData)); auto currentImageLocalData = std::static_pointer_cast(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(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