mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
e3f4a7ba09
Summary: TextInlineViews in Android was incorrectly converting values to from float to int, this produced to loose precision and to render incomplete texts in some components. This diff changed the types from int to float, avoiding loose precision. The impact of this bug is not that high because in the conversion to int we were using Math.ceil(), which was already rounding the result to the next pixel. changeLog: [Android][Fixed] Fix precision of TextInlineViews in Fabric Android Reviewed By: JoshuaGross, shergin Differential Revision: D21541159 fbshipit-source-id: 4741ab96964c35af1c1b7d3e821e505ecef2efce
124 lines
4.1 KiB
C++
124 lines
4.1 KiB
C++
/*
|
|
* 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 <react/attributedstring/conversions.h>
|
|
#include <react/core/conversions.h>
|
|
#include <react/jni/ReadableNativeMap.h>
|
|
|
|
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<jobject> &fabricUIManager =
|
|
contextContainer_->at<jni::global_ref<jobject>>("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<jlong(
|
|
jint,
|
|
jstring,
|
|
ReadableMap::javaobject,
|
|
ReadableMap::javaobject,
|
|
ReadableMap::javaobject,
|
|
jfloat,
|
|
jfloat,
|
|
jfloat,
|
|
jfloat,
|
|
jfloatArray)>("measure");
|
|
|
|
auto minimumSize = layoutConstraints.minimumSize;
|
|
auto maximumSize = layoutConstraints.maximumSize;
|
|
|
|
auto serializedAttributedString = toDynamic(attributedString);
|
|
local_ref<JString> componentName = make_jstring("RCTText");
|
|
local_ref<ReadableNativeMap::javaobject> attributedStringRNM =
|
|
ReadableNativeMap::newObjectCxxArgs(serializedAttributedString);
|
|
local_ref<ReadableNativeMap::javaobject> paragraphAttributesRNM =
|
|
ReadableNativeMap::newObjectCxxArgs(toDynamic(paragraphAttributes));
|
|
|
|
local_ref<ReadableMap::javaobject> attributedStringRM = make_local(
|
|
reinterpret_cast<ReadableMap::javaobject>(attributedStringRNM.get()));
|
|
local_ref<ReadableMap::javaobject> paragraphAttributesRM = make_local(
|
|
reinterpret_cast<ReadableMap::javaobject>(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
|