ImageShadowNode.cpp 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  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. #include <cstdlib>
  8. #include <limits>
  9. #include <react/components/image/ImageShadowNode.h>
  10. #include <react/core/LayoutContext.h>
  11. #include "ImageState.h"
  12. namespace facebook {
  13. namespace react {
  14. const char ImageComponentName[] = "Image";
  15. void ImageShadowNode::setImageManager(const SharedImageManager &imageManager) {
  16. ensureUnsealed();
  17. imageManager_ = imageManager;
  18. }
  19. void ImageShadowNode::updateStateIfNeeded() {
  20. ensureUnsealed();
  21. auto const &imageSource = getImageSource();
  22. auto const &currentState = getStateData();
  23. if (currentState.getImageSource() == imageSource) {
  24. return;
  25. }
  26. auto state = ImageState{
  27. imageSource, imageManager_->requestImage(imageSource, getSurfaceId())};
  28. setStateData(std::move(state));
  29. }
  30. ImageSource ImageShadowNode::getImageSource() const {
  31. auto sources = getConcreteProps().sources;
  32. if (sources.size() == 0) {
  33. return {
  34. /* .type = */ ImageSource::Type::Invalid,
  35. };
  36. }
  37. if (sources.size() == 1) {
  38. return sources[0];
  39. }
  40. auto layoutMetrics = getLayoutMetrics();
  41. auto size = layoutMetrics.getContentFrame().size;
  42. auto scale = layoutMetrics.pointScaleFactor;
  43. auto targetImageArea = size.width * size.height * scale * scale;
  44. auto bestFit = std::numeric_limits<Float>::infinity();
  45. auto bestSource = ImageSource{};
  46. for (const auto &source : sources) {
  47. auto sourceSize = source.size;
  48. auto sourceScale = source.scale == 0 ? scale : source.scale;
  49. auto sourceArea =
  50. sourceSize.width * sourceSize.height * sourceScale * sourceScale;
  51. auto fit = std::abs(1 - (sourceArea / targetImageArea));
  52. if (fit < bestFit) {
  53. bestFit = fit;
  54. bestSource = source;
  55. }
  56. }
  57. return bestSource;
  58. }
  59. #pragma mark - LayoutableShadowNode
  60. void ImageShadowNode::layout(LayoutContext layoutContext) {
  61. updateStateIfNeeded();
  62. ConcreteViewShadowNode::layout(layoutContext);
  63. }
  64. } // namespace react
  65. } // namespace facebook