Skip to content

[TextPainter] Don't invalidate layout cache for paint only changes #89515

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

LongCatIsLooong
Copy link
Contributor

Defers the rebuilding and the relayout of the ui.Paragraph object to
paint if there are no layout changes (e.g. only the font color
changed) and the width constraints are the same.

Additionally if the TextPainter is used to help compute the dry layout
of a render object, and thus never needs to paint, then color changes
alone no longer triggers relayout.

Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.

List which issues are fixed by this PR. You must list at least one issue.

If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I signed the CLA.
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test-exempt.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@flutter-dashboard flutter-dashboard bot added the framework flutter/packages/flutter repository. See also f: labels. label Sep 5, 2021
@google-cla google-cla bot added the cla: yes label Sep 5, 2021
- Fixes flutter#85108

Defers the rebuilding and the relayout of the ui.Paragraph object to
`paint` if there are no layout changes (e.g. only the font color
changed) and the width constraints are the same.

Additionally if the `TextPainter` is used to help compute the dry layout
of a render object, and thus never needs to paint, then color changes
alone no longer triggers relayout.
@LongCatIsLooong LongCatIsLooong force-pushed the lazier-textpainter-layout branch from 5802117 to a354cd6 Compare September 6, 2021 01:43
Copy link
Member

@goderbauer goderbauer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

bool _needsLayout = true;
// Whether _paragraph contains outdated paint information and needs to be
// rebuilt.
bool _needsPaint = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a little confusing that the property is called needsPaint, but the comment talks about needing rebuild...

Comment on lines +591 to +592
if (text == null) {
throw StateError('TextPainter.text must be set to a non-null value before using the TextPainter.');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not an assert?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For promoting text to non-null for the rest of the function scope. The code would have crashed anyways since we were using ! on _text.

);
}

if (_needsPaint) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the name _needsPaint seems confusing to me. The TextPainter is drawing/painting the paragraph in line 682 even when this is false.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_needsRebuildDuringPaint, maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_rebuildParagraphForLayout (a getter) and _rebuildParagraphForPaint ?

@@ -196,7 +200,7 @@ class TextPainter {
/// in framework will automatically invoke this method.
void markNeedsLayout() {
_paragraph = null;
_needsLayout = true;
_needsPaint = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe, technically setting _paragraph to null here is probably enough?

@@ -496,23 +511,23 @@ class TextPainter {
///
/// Valid only after [layout] has been called.
double get minIntrinsicWidth {
assert(!_needsLayout);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe slightly more readable to define a getter bool get _needsLayout => _paragraph != null and use it here and elsewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I can do that. Do we still need these asserts with NNBD?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_paragraph is declared nullable, so even with NNBD these could be null at this point and that would be a bug.

// since we've created a new ui.Paragraph. But there's no extra work being
// done: if _needsPaint is true and _paragraph is not null, the previous
// `layout` call didn't invoke _layoutParagraph.
_layoutParagraph(minWidth, maxWidth);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we assert that the size calculated by the new paragraph is the same as the size before?

@LongCatIsLooong LongCatIsLooong force-pushed the lazier-textpainter-layout branch from bed9828 to e90c6a6 Compare September 9, 2021 16:36
@LongCatIsLooong LongCatIsLooong force-pushed the lazier-textpainter-layout branch from e90c6a6 to 4c0cfb2 Compare September 10, 2021 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unhandled Exception: 'package:flutter/src/painting/text_painter.dart': Failed assertion: line 881 pos 12: '!_needsLayout': is not true.
3 participants