Skip to content

Commit

Permalink
[web] Include trailing spaces in text box measurements (flutter#20208)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdebbar authored Aug 3, 2020
1 parent fa16c3d commit c6fba72
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 2 deletions.
5 changes: 5 additions & 0 deletions lib/web_ui/lib/src/engine/text/measurement.dart
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ class DomTextMeasurementService extends TextMeasurementService {
_excludeTrailing(text, 0, text.length, _newlinePredicate),
hardBreak: true,
width: lineWidth,
widthWithTrailingSpaces: lineWidth,
left: alignOffset,
lineNumber: 0,
),
Expand Down Expand Up @@ -804,6 +805,7 @@ class LinesCalculator {
_excludeTrailing(_text!, _chunkStart, chunkEnd, _newlinePredicate),
hardBreak: false,
width: widthOfResultingLine,
widthWithTrailingSpaces: widthOfResultingLine,
left: alignOffset,
lineNumber: lines.length,
));
Expand Down Expand Up @@ -858,6 +860,8 @@ class LinesCalculator {
);
final int lineNumber = lines.length;
final double lineWidth = measureSubstring(_lineStart, endWithoutSpace);
final double lineWidthWithTrailingSpaces =
measureSubstring(_lineStart, endWithoutNewlines);
final double alignOffset = _calculateAlignOffsetForLine(
paragraph: _paragraph,
lineWidth: lineWidth,
Expand All @@ -870,6 +874,7 @@ class LinesCalculator {
endIndexWithoutNewlines: endWithoutNewlines,
hardBreak: isHardBreak,
width: lineWidth,
widthWithTrailingSpaces: lineWidthWithTrailingSpaces,
left: alignOffset,
lineNumber: lineNumber,
);
Expand Down
18 changes: 16 additions & 2 deletions lib/web_ui/lib/src/engine/text/paragraph.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class EngineLineMetrics implements ui.LineMetrics {
}) : displayText = null,
startIndex = -1,
endIndex = -1,
endIndexWithoutNewlines = -1;
endIndexWithoutNewlines = -1,
widthWithTrailingSpaces = width;

EngineLineMetrics.withText(
String this.displayText, {
Expand All @@ -30,6 +31,7 @@ class EngineLineMetrics implements ui.LineMetrics {
required this.endIndexWithoutNewlines,
required this.hardBreak,
required this.width,
required this.widthWithTrailingSpaces,
required this.left,
required this.lineNumber,
}) : assert(displayText != null), // ignore: unnecessary_null_comparison
Expand Down Expand Up @@ -80,6 +82,18 @@ class EngineLineMetrics implements ui.LineMetrics {
@override
final double width;

/// The full width of the line including all trailing space but not new lines.
///
/// The difference between [width] and [widthWithTrailingSpaces] is that
/// [widthWithTrailingSpaces] includes trailing spaces in the width
/// calculation while [width] doesn't.
///
/// For alignment purposes for example, the [width] property is the right one
/// to use because trailing spaces shouldn't affect the centering of text.
/// But for placing cursors in text fields, we do care about trailing
/// spaces so [widthWithTrailingSpaces] is more suitable.
final double widthWithTrailingSpaces;

@override
final double left;

Expand Down Expand Up @@ -453,7 +467,7 @@ class EngineParagraph implements ui.Paragraph {
return ui.TextBox.fromLTRBD(
line.left + widthBeforeBox,
top,
line.left + line.width - widthAfterBox,
line.left + line.widthWithTrailingSpaces - widthAfterBox,
top + _lineHeight,
_textDirection,
);
Expand Down
40 changes: 40 additions & 0 deletions lib/web_ui/test/paragraph_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,46 @@ void main() async {
);
});

testEachMeasurement('getBoxesForRange includes trailing spaces', () {
const String text = 'abcd abcde ';
final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle(
fontFamily: 'Ahem',
fontStyle: FontStyle.normal,
fontWeight: FontWeight.normal,
fontSize: 10,
));
builder.addText(text);
final Paragraph paragraph = builder.build();
paragraph.layout(const ParagraphConstraints(width: double.infinity));
expect(
paragraph.getBoxesForRange(0, text.length),
<TextBox>[
TextBox.fromLTRBD(0.0, 0.0, 120.0, 10.0, TextDirection.ltr),
],
);
});

testEachMeasurement('getBoxesForRange multi-line includes trailing spaces', () {
const String text = 'abcd\nabcde \nabc';
final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle(
fontFamily: 'Ahem',
fontStyle: FontStyle.normal,
fontWeight: FontWeight.normal,
fontSize: 10,
));
builder.addText(text);
final Paragraph paragraph = builder.build();
paragraph.layout(const ParagraphConstraints(width: double.infinity));
expect(
paragraph.getBoxesForRange(0, text.length),
<TextBox>[
TextBox.fromLTRBD(0.0, 0.0, 40.0, 10.0, TextDirection.ltr),
TextBox.fromLTRBD(0.0, 10.0, 70.0, 20.0, TextDirection.ltr),
TextBox.fromLTRBD(0.0, 20.0, 30.0, 30.0, TextDirection.ltr),
],
);
});

test('longestLine', () {
// [Paragraph.longestLine] is only supported by canvas-based measurement.
WebExperiments.instance.useCanvasText = true;
Expand Down

0 comments on commit c6fba72

Please sign in to comment.