Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@justinmc
Copy link
Contributor

@justinmc justinmc commented Apr 10, 2019

Closes flutter/flutter#26585

Paragraph currently sets its width to be the maximum space allowed for it when it wraps beyond one line. This creates extra empty space when you want to draw something with a tight container:

51184156-82592080-18e4-11e9-8906-2bbce4f6327f

This PR will enable the drawing of a paragraph with a width only as wide as it needs to be to contain wrapping text tightly.

Solution

I propose we add an enum to Text to allow the user to choose how width will be calculated.

TextWidthType.tight will render like a chat bubble:

Text(overflowingString, widthType: TextWidthType.tight),

Screenshot_20190410-125619

TextWidthType.full, the default, will render like it always has:

Text(overflowingString),

Screenshot_20190410-125727

Concerns

The naming was hastily chosen. I worry that users will expect that TextWidthType.full will cause the Text to render full width for a single line of text. Following existing behavior, it will not.

@justinmc justinmc added the Work in progress (WIP) Not ready (yet) for review! label Apr 10, 2019
@justinmc justinmc self-assigned this Apr 10, 2019
@justinmc
Copy link
Contributor Author

Current behavior:
Screenshot_20190410-125428
Screenshot_20190410-125727

PR behavior:
Screenshot_20190410-125619
Screenshot_20190410-125547

@justinmc
Copy link
Contributor Author

Note to self: There is a very similar enum BoxWidthStyle, any possible reuse?

@justinmc justinmc changed the title WIP Tight Paragraph Width Tight Paragraph Width Apr 15, 2019
@justinmc justinmc removed the Work in progress (WIP) Not ready (yet) for review! label Apr 15, 2019
@justinmc
Copy link
Contributor Author

@GaryQian Can you give me a review on my approach here? I'll talk to Hans when he's around as well.
This is the paragraph width thing I was asking you for advice on the other day. Framework PR is here: flutter/flutter#30988

I put the enum inside of the engine, so users will have to import it from dart:ui. Were you also suggesting duplicating the enum in both the framework and the engine?

@justinmc justinmc requested review from GaryQian and HansMuller April 15, 2019 18:28
lib/ui/text.dart Outdated
if (fontFamily != null) {
if (widthType != null) {
result[0] |= 1 << 6;
result[6] = widthType.index;
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this is a binary value, it is possible to compress this into much smaller than the 32 bit int you are using now, but for now, this is OK. The benefit of what you have is that it is consistent and more readable. A more compressed version would be harder to read and maintain.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It looks like I'm going to remove widthType, so this won't be a problem anymore.

lib/ui/text.dart Outdated
FontWeight fontWeight,
FontStyle fontStyle,
StrutStyle strutStyle,
TextWidthType widthType,
Copy link
Contributor

@GaryQian GaryQian Apr 16, 2019

Choose a reason for hiding this comment

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

So since dart:ui is a more base level library, we may want to consider handling the switching between full and tight completely in the framework as an abstraction over dart:ui. At the dart:ui level, I think it makes more sense for both widths to be available in the getter for the width. Either make the width getter property take the enum or make a separate getter for the tight width.

The idea of innately possessing a tight or full width is more of a framework-level issue, and dart:ui (and below) shouldn't really have the paragraph preemptively pick its width as it would now with a setting in ParagraphStyle.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it makes sense for the setting to be in ParagraphStyle, but have the framework consult it or otherwise extract the widthType from the ParagraphStyle to choose with dart:ui method to call.

This would mean it isnt necessary to pass the widthType all the way down into Libtxt in the initial passing of ParagraphStyle into native.

return a.code_units.start < b.code_units.start;
});

if (paragraph_style_.width_type == TextWidthType::tight) {
Copy link
Contributor

Choose a reason for hiding this comment

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

(see above comments for context) LibTxt should be able to indiscriminately provide the metrics for both width types. By making the paragraph "choose" which width to provide, we are artificially hiding a potentially useful metric from the users of this quite low level API.

This hiding makes more sense if done completely in the framework level.

@GaryQian
Copy link
Contributor

The implementation of the libtxt->dart:ui layers seems to be good though!

@justinmc
Copy link
Contributor Author

@GaryQian Ready for re-review. Now I'm setting a textWidth property and reading that from the framework, so the engine doesn't care about TextWidthType anymore.

@GaryQian
Copy link
Contributor

Implementation looks good. Do you think you can add a simple test to txt/tests/paragraph_unittests.cc?

lib/ui/text.dart Outdated
double get height native 'Paragraph_height';

/// The distance from the left edge of the leftmost character to the right
/// edge of the rightmost character in the paragraph.
Copy link
Contributor

Choose a reason for hiding this comment

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

glyph may be a more precise word for this concept

double GetMaxWidth() const;

// Returns the tight width found in Layout(), which is defined as the
// horizontal distance from the left edge of the leftmost character to the
Copy link
Contributor

Choose a reason for hiding this comment

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

glyph (same as above)

// no line perfectly spans the width of the full line, so tight_width_ is less
// than width_.
ASSERT_DOUBLE_EQ(paragraph->width_, available_width);
ASSERT_TRUE(paragraph->tight_width_ < paragraph->width_);
Copy link
Contributor

Choose a reason for hiding this comment

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

You should be able to compare against either hardcoded values or the right edge of the right-most getRectsForRange box.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call.

@justinmc
Copy link
Contributor Author

@GaryQian I used getRectsForRange for the single line case because that's always just the distance between the left edge of the first box and the right edge of the last box. In the multiline case though, I would have to loop through all boxes and find the min and max values, which is just duplicating what the actual code does, so I hardcoded that one. Let me know if you've got a better idea for that.

@GaryQian
Copy link
Contributor

Sounds good!

Copy link
Contributor

@GaryQian GaryQian left a comment

Choose a reason for hiding this comment

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

LGTM!

@justinmc justinmc merged commit a144f17 into flutter:master Apr 18, 2019
@justinmc justinmc deleted the text-wrap-width branch April 18, 2019 16:08
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Apr 18, 2019
engine-flutter-autoroll added a commit to flutter/flutter that referenced this pull request Apr 18, 2019
flutter/engine@06fea14...4b9966f

git log 06fea14..4b9966f --no-merges --oneline
4b9966f Add an adjustment to the line width check in LineBreaker::addWordBreak (flutter/engine#8623)
60bb866 Roll src/third_party/skia a94670bd08cd..2c2240f66805 (2 commits) (flutter/engine#8632)
a144f17 Tight Paragraph Width (flutter/engine#8530)

The AutoRoll server is located here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md

If the roll is causing failures, please contact the current sheriff (cbracken@google.com), and stop
the roller if necessary.
@FlashTang
Copy link

Thank you so much , exactly what I need. I almost gave up on flutter before seeing this.
but what about Textfield ?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Text widget doesn't change it's size when line break happened

4 participants