Skip to content

Commit 3ee16a3

Browse files
tomekzawclaude
andcommitted
Don't reuse paragraph layouts prepared at another pixel density
Measured layouts are now carried over to clones with no new props or children, including the ones configureYogaTree makes when the pixel density changes. measureContent and findUsableLayout matched them only by constraints or size, so the paragraph reused a layout prepared at the old density and, with fixTextLayoutOnPixelDensityChange, never updated its state to the new density. Only reuse layouts prepared at the current pointScaleFactor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent d97e572 commit 3ee16a3

2 files changed

Lines changed: 13 additions & 7 deletions

File tree

‎packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.cpp‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,8 @@ void ParagraphShadowNode::updateStateIfNeeded(const Content& content) {
221221
textLayoutManager_});
222222
}
223223

224-
MeasuredPreparedTextLayout* ParagraphShadowNode::findUsableLayout() {
224+
MeasuredPreparedTextLayout* ParagraphShadowNode::findUsableLayout(
225+
Float pointScaleFactor) {
225226
MeasuredPreparedTextLayout* ret = nullptr;
226227

227228
if constexpr (TextLayoutManagerExtended::supportsPreparedTextLayout()) {
@@ -233,7 +234,8 @@ MeasuredPreparedTextLayout* ParagraphShadowNode::findUsableLayout() {
233234
// adjusted by a constraint (like min-size).
234235
auto expectedSize = rawContentSize();
235236
for (auto& prevLayout : measuredLayouts_) {
236-
if (floatEquality(
237+
if (prevLayout.pointScaleFactor == pointScaleFactor &&
238+
floatEquality(
237239
prevLayout.measurement.size.width, expectedSize.width) &&
238240
floatEquality(
239241
prevLayout.measurement.size.height, expectedSize.height)) {
@@ -262,8 +264,11 @@ Size ParagraphShadowNode::measureContent(
262264
const LayoutContext& layoutContext,
263265
const LayoutConstraints& layoutConstraints) const {
264266
if constexpr (TextLayoutManagerExtended::supportsPreparedTextLayout()) {
267+
// Layouts carried over from a previous revision may have been prepared
268+
// at another pixel density, which they can't be reused for.
265269
for (const auto& layout : measuredLayouts_) {
266-
if (layout.layoutConstraints == layoutConstraints) {
270+
if (layout.layoutConstraints == layoutConstraints &&
271+
layout.pointScaleFactor == layoutContext.pointScaleFactor) {
267272
return layout.measurement.size;
268273
}
269274
}
@@ -353,7 +358,7 @@ void ParagraphShadowNode::layout(LayoutContext layoutContext) {
353358
auto content =
354359
getContentWithMeasuredAttachments(layoutContext, layoutConstraints);
355360

356-
auto measuredLayout = findUsableLayout();
361+
auto measuredLayout = findUsableLayout(layoutContext.pointScaleFactor);
357362

358363
if constexpr (
359364
TextLayoutManagerExtended::supportsPreparedTextLayout() &&
@@ -370,7 +375,7 @@ void ParagraphShadowNode::layout(LayoutContext layoutContext) {
370375
// culled
371376
if (measuredLayout == nullptr) {
372377
measureContent(layoutContext, layoutConstraints);
373-
measuredLayout = findUsableLayout();
378+
measuredLayout = findUsableLayout(layoutContext.pointScaleFactor);
374379
}
375380
react_native_assert(measuredLayout);
376381
updateStateIfNeeded<ParagraphState>(content, *measuredLayout);

‎packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.h‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,10 @@ class ParagraphShadowNode
117117

118118
/**
119119
* Returns any previously prepared layout, generated for measurement, which
120-
* may be used, given the currently assigned layout to the ShadowNode
120+
* may be used, given the currently assigned layout to the ShadowNode and
121+
* the current pixel density
121122
*/
122-
MeasuredPreparedTextLayout *findUsableLayout();
123+
MeasuredPreparedTextLayout *findUsableLayout(Float pointScaleFactor);
123124

124125
/**
125126
* Returns the final measure of the content frame, before layout rounding

0 commit comments

Comments
 (0)