Files
react-native/ReactCommon/fabric/textlayoutmanager/platform/ios/TextLayoutManager.mm
T
Valentin Shergin c9b9c93c90 Fabric: Text Measuring: Doing clamping outside of caching
Summary:
Here the deal with the clamp thing:
A layout engine asks nodes to measure their content providing layout constraints (min and max size) and that would be kind from nodes to return a result that in space of those constraints. Sometimes, satisfying that is an additional separate step of that operation, e.g. if we know that the intrinsic size of some node is `{100, 100}`, we need to clamp that to satisfy constraint `[min: {200, 200}, max: {inf, inf}]`.

In case when we need to cache measure information, it becomes tricky enough when we need to make the cache work most efficiently. For the case of measuring Text, we have an insight: the available maximum width is important, the rest three metrics (maximum height and minimum size) are not.

That means that any changes in those three metrics don't affect the actual measurement result but will affect the final value because the actual value will be clamped by constraints that didn't influence measuring in the first place.
That's why moving clamping outside of a cache is the first step into making it more efficient.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: sammy-SC

Differential Revision: D18848584

fbshipit-source-id: 8feeb3f1a9d0e9691abac8be43639487a626fec3
2019-12-06 10:54:12 -08:00

72 lines
2.1 KiB
Plaintext

/*
* 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/utils/ManagedObjectWrapper.h>
#import "RCTTextLayoutManager.h"
namespace facebook {
namespace react {
TextLayoutManager::TextLayoutManager(ContextContainer::Shared const &contextContainer)
{
self_ = (__bridge_retained void *)[RCTTextLayoutManager new];
}
TextLayoutManager::~TextLayoutManager()
{
CFRelease(self_);
self_ = nullptr;
}
void *TextLayoutManager::getNativeTextLayoutManager() const
{
assert(self_ && "Stored NativeTextLayoutManager must not be null.");
return self_;
}
Size TextLayoutManager::measure(
AttributedStringBox attributedStringBox,
ParagraphAttributes paragraphAttributes,
LayoutConstraints layoutConstraints) const
{
RCTTextLayoutManager *textLayoutManager = (__bridge RCTTextLayoutManager *)self_;
auto size = Size{};
switch (attributedStringBox.getMode()) {
case AttributedStringBox::Mode::Value: {
auto &attributedString = attributedStringBox.getValue();
size = measureCache_.get(
{attributedString, paragraphAttributes, layoutConstraints}, [&](TextMeasureCacheKey const &key) {
return [textLayoutManager measureAttributedString:attributedString
paragraphAttributes:paragraphAttributes
layoutConstraints:layoutConstraints];
});
break;
}
case AttributedStringBox::Mode::OpaquePointer: {
NSAttributedString *nsAttributedString =
(NSAttributedString *)unwrapManagedObject(attributedStringBox.getOpaquePointer());
size = [textLayoutManager measureNSAttributedString:nsAttributedString
paragraphAttributes:paragraphAttributes
layoutConstraints:layoutConstraints];
break;
}
}
return layoutConstraints.clamp(size);
}
} // namespace react
} // namespace facebook