/* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #include "TextLayoutManager.h" #include #include #include using namespace facebook::jni; namespace facebook { namespace react { TextLayoutManager::~TextLayoutManager() {} void *TextLayoutManager::getNativeTextLayoutManager() const { return self_; } TextMeasurement TextLayoutManager::measure( AttributedStringBox attributedStringBox, ParagraphAttributes paragraphAttributes, LayoutConstraints layoutConstraints) const { auto &attributedString = attributedStringBox.getValue(); return measureCache_.get( {attributedString, paragraphAttributes, layoutConstraints}, [&](TextMeasureCacheKey const &key) { return doMeasure( attributedString, paragraphAttributes, layoutConstraints); }); } TextMeasurement TextLayoutManager::doMeasure( AttributedString attributedString, ParagraphAttributes paragraphAttributes, LayoutConstraints layoutConstraints) const { const jni::global_ref &fabricUIManager = contextContainer_->at>("FabricUIManager"); int attachmentsCount = 0; for (auto fragment : attributedString.getFragments()) { if (fragment.isAttachment()) { attachmentsCount++; } } auto env = Environment::current(); auto attachmentPositions = env->NewFloatArray(attachmentsCount * 2); static auto measure = jni::findClassStatic("com/facebook/react/fabric/FabricUIManager") ->getMethod("measure"); auto minimumSize = layoutConstraints.minimumSize; auto maximumSize = layoutConstraints.maximumSize; auto serializedAttributedString = toDynamic(attributedString); local_ref componentName = make_jstring("RCTText"); local_ref attributedStringRNM = ReadableNativeMap::newObjectCxxArgs(serializedAttributedString); local_ref paragraphAttributesRNM = ReadableNativeMap::newObjectCxxArgs(toDynamic(paragraphAttributes)); local_ref attributedStringRM = make_local( reinterpret_cast(attributedStringRNM.get())); local_ref paragraphAttributesRM = make_local( reinterpret_cast(paragraphAttributesRNM.get())); auto size = yogaMeassureToSize(measure( fabricUIManager, -1, componentName.get(), attributedStringRM.get(), paragraphAttributesRM.get(), nullptr, minimumSize.width, maximumSize.width, minimumSize.height, maximumSize.height, attachmentPositions)); jfloat *attachmentData = env->GetFloatArrayElements(attachmentPositions, 0); auto attachments = TextMeasurement::Attachments{}; if (attachmentsCount > 0) { folly::dynamic fragments = serializedAttributedString["fragments"]; int attachmentIndex = 0; for (int i = 0; i < fragments.size(); i++) { folly::dynamic fragment = fragments[i]; if (fragment["isAttachment"] == true) { float top = attachmentData[attachmentIndex * 2]; float left = attachmentData[attachmentIndex * 2 + 1]; float width = (float)fragment["width"].getDouble(); float height = (float)fragment["height"].getDouble(); auto rect = facebook::react::Rect{{left, top}, facebook::react::Size{width, height}}; attachments.push_back(TextMeasurement::Attachment{rect, false}); attachmentIndex++; } } } // DELETE REF env->DeleteLocalRef(attachmentPositions); return TextMeasurement{size, attachments}; } } // namespace react } // namespace facebook