diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/text/layout_service.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/text/layout_service.dart index 30bea1fbda2..39ecfa49467 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/text/layout_service.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/text/layout_service.dart @@ -175,6 +175,20 @@ class TextLayoutService { } } + // ************************************************** // + // *** PARAGRAPH BASELINE & HEIGHT & LONGEST LINE *** // + // ************************************************** // + + for (final EngineLineMetrics line in lines) { + height += line.height; + if (alphabeticBaseline == -1.0) { + alphabeticBaseline = line.baseline; + } + if (longestLine < line.width) { + longestLine = line.width; + } + } + // ******************************** // // *** MAX/MIN INTRINSIC WIDTHS *** // // ******************************** // @@ -276,6 +290,7 @@ class LineBuilder { required this.maxWidth, required this.start, required this.lineNumber, + required this.accumulatedHeight, }) : end = start; /// Creates a [LineBuilder] for the first line in a paragraph. @@ -290,6 +305,7 @@ class LineBuilder { maxWidth: maxWidth, lineNumber: 0, start: LineBreakResult.sameIndex(0, LineBreakType.prohibited), + accumulatedHeight: 0.0, ); } @@ -301,6 +317,10 @@ class LineBuilder { final LineBreakResult start; final int lineNumber; + /// The accumulated height of all preceding lines, excluding the current line. + final double accumulatedHeight; + + /// The index of the end of the line so far. LineBreakResult end; /// The width of the line so far, excluding trailing white space. @@ -312,6 +332,12 @@ class LineBuilder { /// The width of trailing white space in the line. double get widthOfTrailingSpace => widthIncludingSpace - width; + /// The alphabetic baseline of the line so far. + double alphabeticBaseline = 0.0; + + /// The height of the line so far. + double height = 0.0; + /// The last segment in this line. LineSegment get lastSegment => _segments.last; @@ -360,6 +386,10 @@ class LineBuilder { 'Cannot extend a line that ends with a hard break.', ); + alphabeticBaseline = + math.max(alphabeticBaseline, spanometer.alphabeticBaseline); + height = math.max(height, spanometer.height); + _addSegment(_createSegment(newEnd)); } @@ -508,23 +538,18 @@ class LineBuilder { availableWidth: availableWidthForSegment, allowEmpty: allowEmpty, ); - extendTo(LineBreakResult.sameIndex(breakingPoint, LineBreakType.prohibited)); + extendTo( + LineBreakResult.sameIndex(breakingPoint, LineBreakType.prohibited)); } /// Builds the [EngineLineMetrics] instance that represents this line. EngineLineMetrics build({String? ellipsis}) { - double ellipsisWidth = 0.0; - String text = paragraph - .toPlainText() - .substring(start.index, end.indexWithoutTrailingNewlines); + final double ellipsisWidth = + ellipsis == null ? 0.0 : spanometer.measureText(ellipsis); - if (ellipsis != null) { - ellipsisWidth = spanometer.measureText(ellipsis); - text += ellipsis; - } - - return EngineLineMetrics.withText( - text, + return EngineLineMetrics.rich( + lineNumber, + ellipsis: ellipsis, startIndex: start.index, endIndex: end.index, endIndexWithoutNewlines: end.indexWithoutTrailingNewlines, @@ -532,7 +557,8 @@ class LineBuilder { width: width + ellipsisWidth, widthWithTrailingSpaces: widthIncludingSpace + ellipsisWidth, left: alignOffset, - lineNumber: lineNumber, + height: height, + baseline: accumulatedHeight + alphabeticBaseline, ); } @@ -549,6 +575,7 @@ class LineBuilder { maxWidth: maxWidth, start: end, lineNumber: lineNumber + 1, + accumulatedHeight: accumulatedHeight + height, ); } } @@ -567,11 +594,18 @@ class Spanometer { final CanvasParagraph paragraph; final html.CanvasRenderingContext2D context; + static RulerHost _rulerHost = RulerHost(); + + static Map _rulers = + {}; + String _cssFontString = ''; double? get letterSpacing => _currentSpan!.style._letterSpacing; + TextHeightRuler? _currentRuler; FlatTextSpan? _currentSpan; + FlatTextSpan? get currentSpan => _currentSpan; set currentSpan(FlatTextSpan? span) { if (span == _currentSpan) { @@ -581,9 +615,20 @@ class Spanometer { // No need to update css font string when `span` is null. if (span == null) { + _currentRuler = null; return; } + // Update the height ruler. + // If the ruler doesn't exist in the cache, create a new one and cache it. + final TextHeightStyle heightStyle = span.style.heightStyle; + TextHeightRuler? ruler = _rulers[heightStyle]; + if (ruler == null) { + ruler = TextHeightRuler(heightStyle, _rulerHost); + _rulers[heightStyle] = ruler; + } + _currentRuler = ruler; + // Update the font string if it's different from the previous span. final String cssFontString = span.style.cssFontString; if (_cssFontString != cssFontString) { @@ -592,6 +637,12 @@ class Spanometer { } } + /// The alphabetic baseline for the current span. + double get alphabeticBaseline => _currentRuler!.alphabeticBaseline; + + /// The line height of the current span. + double get height => _currentRuler!.height; + /// Measures the width of text between two line breaks. /// /// Doesn't include the width of any trailing white space. diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/text/paragraph.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/text/paragraph.dart index 5be563aa7a8..34dde2c94e7 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/text/paragraph.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/text/paragraph.dart @@ -21,6 +21,7 @@ class EngineLineMetrics implements ui.LineMetrics { required this.baseline, required this.lineNumber, }) : displayText = null, + ellipsis = null, startIndex = -1, endIndex = -1, endIndexWithoutNewlines = -1, @@ -44,15 +45,39 @@ class EngineLineMetrics implements ui.LineMetrics { assert(width != null), // ignore: unnecessary_null_comparison assert(left != null), // ignore: unnecessary_null_comparison assert(lineNumber != null && lineNumber >= 0), // ignore: unnecessary_null_comparison + ellipsis = null, ascent = double.infinity, descent = double.infinity, unscaledAscent = double.infinity, height = double.infinity, baseline = double.infinity; + EngineLineMetrics.rich( + this.lineNumber, { + required this.ellipsis, + required this.startIndex, + required this.endIndex, + required this.endIndexWithoutNewlines, + required this.hardBreak, + required this.width, + required this.widthWithTrailingSpaces, + required this.left, + required this.height, + required this.baseline, + }) : displayText = null, + ascent = double.infinity, + descent = double.infinity, + unscaledAscent = double.infinity; + /// The text to be rendered on the screen representing this line. final String? displayText; + /// The string to be displayed as an overflow indicator. + /// + /// When the value is non-null, it means this line is overflowing and the + /// [ellipsis] needs to be displayed at the end of it. + final String? ellipsis; + /// The index (inclusive) in the text where this line begins. final int startIndex; @@ -1035,6 +1060,19 @@ class EngineTextStyle implements ui.TextStyle { ); } + late final TextHeightStyle heightStyle = _createHeightStyle(); + + TextHeightStyle _createHeightStyle() { + return TextHeightStyle( + fontFamily: _effectiveFontFamily, + fontSize: _fontSize ?? DomRenderer.defaultFontSize, + height: _height, + // TODO(mdebbar): Pass the actual value when font features become supported + // https://github.com/flutter/flutter/issues/64595 + fontFeatures: null, + ); + } + @override bool operator ==(Object other) { if (identical(this, other)) { diff --git a/engine/src/flutter/lib/web_ui/test/text/layout_service_helper.dart b/engine/src/flutter/lib/web_ui/test/text/layout_service_helper.dart index 24cb1f6afff..9dbb84e811a 100644 --- a/engine/src/flutter/lib/web_ui/test/text/layout_service_helper.dart +++ b/engine/src/flutter/lib/web_ui/test/text/layout_service_helper.dart @@ -13,9 +13,11 @@ TestLine l( int? endIndex, { int? endIndexWithoutNewlines, bool? hardBreak, + double? height, double? width, double? widthWithTrailingSpaces, double? left, + double? baseline, }) { return TestLine( displayText: displayText, @@ -23,13 +25,16 @@ TestLine l( endIndex: endIndex, endIndexWithoutNewlines: endIndexWithoutNewlines, hardBreak: hardBreak, + height: height, width: width, widthWithTrailingSpaces: widthWithTrailingSpaces, left: left, + baseline: baseline, ); } void expectLines(CanvasParagraph paragraph, List expectedLines) { + final String text = paragraph.toPlainText(); final List lines = paragraph.computeLineMetrics() as List; expect(lines, hasLength(expectedLines.length)); @@ -43,8 +48,11 @@ void expectLines(CanvasParagraph paragraph, List expectedLines) { reason: '${i}th line had the wrong `lineNumber`. Expected: $i. Actual: ${line.lineNumber}', ); if (expectedLine.displayText != null) { + final String substring = + text.substring(line.startIndex, line.endIndexWithoutNewlines); + final String ellipsis = line.ellipsis ?? ''; expect( - line.displayText, + substring + ellipsis, expectedLine.displayText, reason: '${i}th line had a different `displayText` value: "${line.displayText}" vs. "${expectedLine.displayText}"', @@ -128,6 +136,7 @@ class TestLine { this.width, this.widthWithTrailingSpaces, this.left, + this.baseline, }); final String? displayText; @@ -139,4 +148,5 @@ class TestLine { final double? width; final double? widthWithTrailingSpaces; final double? left; -} \ No newline at end of file + final double? baseline; +} diff --git a/engine/src/flutter/lib/web_ui/test/text/layout_service_plain_test.dart b/engine/src/flutter/lib/web_ui/test/text/layout_service_plain_test.dart index 837ada96b51..4187ee3a7bb 100644 --- a/engine/src/flutter/lib/web_ui/test/text/layout_service_plain_test.dart +++ b/engine/src/flutter/lib/web_ui/test/text/layout_service_plain_test.dart @@ -49,7 +49,7 @@ void testMain() async { paragraph = plain(ahemStyle, ' abc')..layout(constrain(double.infinity)); expect(paragraph.maxIntrinsicWidth, 60); expect(paragraph.minIntrinsicWidth, 30); - // expect(paragraph.height, 10); + expect(paragraph.height, 10); expectLines(paragraph, [ l(' abc', 0, 6, hardBreak: true, width: 60.0), ]); @@ -58,7 +58,7 @@ void testMain() async { paragraph = plain(ahemStyle, 'abc ')..layout(constrain(double.infinity)); expect(paragraph.maxIntrinsicWidth, 60); expect(paragraph.minIntrinsicWidth, 30); - // expect(paragraph.height, 10); + expect(paragraph.height, 10); expectLines(paragraph, [ l('abc ', 0, 6, hardBreak: true, width: 30.0), ]); @@ -68,7 +68,7 @@ void testMain() async { ..layout(constrain(double.infinity)); expect(paragraph.maxIntrinsicWidth, 100); expect(paragraph.minIntrinsicWidth, 20); - // expect(paragraph.height, 10); + expect(paragraph.height, 10); expectLines(paragraph, [ l(' ab c ', 0, 10, hardBreak: true, width: 80.0, left: 0.0), ]); @@ -77,7 +77,7 @@ void testMain() async { paragraph = plain(ahemStyle, ' ')..layout(constrain(double.infinity)); expect(paragraph.maxIntrinsicWidth, 10); expect(paragraph.minIntrinsicWidth, 0); - // expect(paragraph.height, 10); + expect(paragraph.height, 10); expectLines(paragraph, [ l(' ', 0, 1, hardBreak: true, width: 0.0, left: 0.0), ]); @@ -86,7 +86,7 @@ void testMain() async { paragraph = plain(ahemStyle, ' ')..layout(constrain(double.infinity)); expect(paragraph.maxIntrinsicWidth, 50); expect(paragraph.minIntrinsicWidth, 0); - // expect(paragraph.height, 10); + expect(paragraph.height, 10); expectLines(paragraph, [ l(' ', 0, 5, hardBreak: true, width: 0.0, left: 0.0), ]); @@ -97,25 +97,27 @@ void testMain() async { ..layout(constrain(50.0)); // Should fit on a single line. + expect(paragraph.alphabeticBaseline, 8); expect(paragraph.maxIntrinsicWidth, 50); expect(paragraph.minIntrinsicWidth, 50); expect(paragraph.width, 50); - // expect(paragraph.height, 10); + expect(paragraph.height, 10); expectLines(paragraph, [ - l('12345', 0, 5, hardBreak: true, width: 50.0, left: 0.0), + l('12345', 0, 5, hardBreak: true, width: 50.0, left: 0.0, height: 10.0, baseline: 8.0), ]); }); test('simple multi-line text', () { final CanvasParagraph paragraph = plain(ahemStyle, 'foo bar baz') ..layout(constrain(70.0)); + expect(paragraph.alphabeticBaseline, 8); expect(paragraph.maxIntrinsicWidth, 110); expect(paragraph.minIntrinsicWidth, 30); expect(paragraph.width, 70); - // expect(paragraph.height, 20); + expect(paragraph.height, 20); expectLines(paragraph, [ - l('foo bar ', 0, 8, hardBreak: false, width: 70.0, left: 0.0), - l('baz', 8, 11, hardBreak: true, width: 30.0, left: 0.0), + l('foo bar ', 0, 8, hardBreak: false, width: 70.0, left: 0.0, height: 10.0, baseline: 8.0), + l('baz', 8, 11, hardBreak: true, width: 30.0, left: 0.0, height: 10.0, baseline: 18.0), ]); }); @@ -124,73 +126,79 @@ void testMain() async { // The long text doesn't fit in 50px of width, so it needs to wrap. paragraph = plain(ahemStyle, '1234567890')..layout(constrain(50.0)); + expect(paragraph.alphabeticBaseline, 8); expect(paragraph.maxIntrinsicWidth, 100); expect(paragraph.minIntrinsicWidth, 100); expect(paragraph.width, 50); - // expect(paragraph.height, 20); + expect(paragraph.height, 20); expectLines(paragraph, [ - l('12345', 0, 5, hardBreak: false, width: 50.0, left: 0.0), - l('67890', 5, 10, hardBreak: true, width: 50.0, left: 0.0), + l('12345', 0, 5, hardBreak: false, width: 50.0, left: 0.0, height: 10.0, baseline: 8.0), + l('67890', 5, 10, hardBreak: true, width: 50.0, left: 0.0, height: 10.0, baseline: 18.0), ]); // The first word is force-broken twice. paragraph = plain(ahemStyle, 'abcdefghijk lm')..layout(constrain(50.0)); + expect(paragraph.alphabeticBaseline, 8); expect(paragraph.maxIntrinsicWidth, 140); expect(paragraph.minIntrinsicWidth, 110); expect(paragraph.width, 50); - // expect(paragraph.height, 30); + expect(paragraph.height, 30); expectLines(paragraph, [ - l('abcde', 0, 5, hardBreak: false, width: 50.0, left: 0.0), - l('fghij', 5, 10, hardBreak: false, width: 50.0, left: 0.0), - l('k lm', 10, 14, hardBreak: true, width: 40.0, left: 0.0), + l('abcde', 0, 5, hardBreak: false, width: 50.0, left: 0.0, height: 10.0, baseline: 8.0), + l('fghij', 5, 10, hardBreak: false, width: 50.0, left: 0.0, height: 10.0, baseline: 18.0), + l('k lm', 10, 14, hardBreak: true, width: 40.0, left: 0.0, height: 10.0, baseline: 28.0), ]); // Constraints enough only for "abcdef" but not for the trailing space. paragraph = plain(ahemStyle, 'abcdef gh')..layout(constrain(60.0)); + expect(paragraph.alphabeticBaseline, 8); expect(paragraph.maxIntrinsicWidth, 90); expect(paragraph.minIntrinsicWidth, 60); expect(paragraph.width, 60); - // expect(paragraph.height, 20); + expect(paragraph.height, 20); expectLines(paragraph, [ - l('abcdef ', 0, 7, hardBreak: false, width: 60.0, left: 0.0), - l('gh', 7, 9, hardBreak: true, width: 20.0, left: 0.0), + l('abcdef ', 0, 7, hardBreak: false, width: 60.0, left: 0.0, height: 10.0, baseline: 8.0), + l('gh', 7, 9, hardBreak: true, width: 20.0, left: 0.0, height: 10.0, baseline: 18.0), ]); // Constraints aren't enough even for a single character. In this case, // we show a minimum of one character per line. paragraph = plain(ahemStyle, 'AA')..layout(constrain(8.0)); + expect(paragraph.alphabeticBaseline, 8); expect(paragraph.maxIntrinsicWidth, 20); expect(paragraph.minIntrinsicWidth, 20); expect(paragraph.width, 8); - // expect(paragraph.height, 20); + expect(paragraph.height, 20); expectLines(paragraph, [ - l('A', 0, 1, hardBreak: false, width: 10.0, left: 0.0), - l('A', 1, 2, hardBreak: true, width: 10.0, left: 0.0), + l('A', 0, 1, hardBreak: false, width: 10.0, left: 0.0, height: 10.0, baseline: 8.0), + l('A', 1, 2, hardBreak: true, width: 10.0, left: 0.0, height: 10.0, baseline: 18.0), ]); // Extremely narrow constraints with new line in the middle. paragraph = plain(ahemStyle, 'AA\nA')..layout(constrain(8.0)); + expect(paragraph.alphabeticBaseline, 8); expect(paragraph.maxIntrinsicWidth, 20); expect(paragraph.minIntrinsicWidth, 20); expect(paragraph.width, 8); - // expect(paragraph.height, 30); + expect(paragraph.height, 30); expectLines(paragraph, [ - l('A', 0, 1, hardBreak: false, width: 10.0, left: 0.0), - l('A', 1, 3, hardBreak: true, width: 10.0, left: 0.0), - l('A', 3, 4, hardBreak: true, width: 10.0, left: 0.0), + l('A', 0, 1, hardBreak: false, width: 10.0, left: 0.0, height: 10.0, baseline: 8.0), + l('A', 1, 3, hardBreak: true, width: 10.0, left: 0.0, height: 10.0, baseline: 18.0), + l('A', 3, 4, hardBreak: true, width: 10.0, left: 0.0, height: 10.0, baseline: 28.0), ]); // Extremely narrow constraints with new line in the end. paragraph = plain(ahemStyle, 'AAA\n')..layout(constrain(8.0)); + expect(paragraph.alphabeticBaseline, 8); expect(paragraph.maxIntrinsicWidth, 30); expect(paragraph.minIntrinsicWidth, 30); expect(paragraph.width, 8); - // expect(paragraph.height, 40); + expect(paragraph.height, 40); expectLines(paragraph, [ - l('A', 0, 1, hardBreak: false, width: 10.0, left: 0.0), - l('A', 1, 2, hardBreak: false, width: 10.0, left: 0.0), - l('A', 2, 4, hardBreak: true, width: 10.0, left: 0.0), - l('', 4, 4, hardBreak: true, width: 0.0, left: 0.0), + l('A', 0, 1, hardBreak: false, width: 10.0, left: 0.0, height: 10.0, baseline: 8.0), + l('A', 1, 2, hardBreak: false, width: 10.0, left: 0.0, height: 10.0, baseline: 18.0), + l('A', 2, 4, hardBreak: true, width: 10.0, left: 0.0, height: 10.0, baseline: 28.0), + l('', 4, 4, hardBreak: true, width: 0.0, left: 0.0, height: 10.0, baseline: 38.0), ]); }); @@ -202,7 +210,7 @@ void testMain() async { expect(paragraph.maxIntrinsicWidth, 20); expect(paragraph.minIntrinsicWidth, 20); expect(paragraph.width, 50); - // expect(paragraph.height, 20); + expect(paragraph.height, 20); expectLines(paragraph, [ l('12', 0, 3, hardBreak: true, width: 20.0, left: 0.0), l('34', 3, 5, hardBreak: true, width: 20.0, left: 0.0), @@ -216,7 +224,7 @@ void testMain() async { paragraph = plain(ahemStyle, '\n\n1234')..layout(constrain(50.0)); expect(paragraph.maxIntrinsicWidth, 40); expect(paragraph.minIntrinsicWidth, 40); - // expect(paragraph.height, 30); + expect(paragraph.height, 30); expectLines(paragraph, [ l('', 0, 1, hardBreak: true, width: 0.0, left: 0.0), l('', 1, 2, hardBreak: true, width: 0.0, left: 0.0), @@ -227,7 +235,7 @@ void testMain() async { paragraph = plain(ahemStyle, '12\n\n345')..layout(constrain(50.0)); expect(paragraph.maxIntrinsicWidth, 30); expect(paragraph.minIntrinsicWidth, 30); - // expect(paragraph.height, 30); + expect(paragraph.height, 30); expectLines(paragraph, [ l('12', 0, 3, hardBreak: true, width: 20.0, left: 0.0), l('', 3, 4, hardBreak: true, width: 0.0, left: 0.0), @@ -238,7 +246,7 @@ void testMain() async { paragraph = plain(ahemStyle, '1234\n\n')..layout(constrain(50.0)); expect(paragraph.maxIntrinsicWidth, 40); expect(paragraph.minIntrinsicWidth, 40); - // expect(paragraph.height, 30); + expect(paragraph.height, 30); expectLines(paragraph, [ l('1234', 0, 5, hardBreak: true, width: 40.0, left: 0.0), l('', 5, 6, hardBreak: true, width: 0.0, left: 0.0), @@ -255,7 +263,7 @@ void testMain() async { expect(paragraph.maxIntrinsicWidth, 70); expect(paragraph.minIntrinsicWidth, 30); expect(paragraph.width, double.infinity); - // expect(paragraph.height, 20); + expect(paragraph.height, 20); expectLines(paragraph, [ l('123', 0, 4, hardBreak: true, width: 30.0, left: 0.0), l('456 789', 4, 11, hardBreak: true, width: 70.0, left: 0.0), @@ -404,7 +412,7 @@ void testMain() async { )..layout(constrain(50.0)); expect(longText.minIntrinsicWidth, 480); expect(longText.maxIntrinsicWidth, 480); - // expect(longText.height, 10); + expect(longText.height, 10); expectLines(longText, [ l('AA...', 0, 2, hardBreak: false, width: 50.0, left: 0.0), ]); @@ -417,7 +425,7 @@ void testMain() async { )..layout(constrain(50.0)); expect(longTextShortPrefix.minIntrinsicWidth, 450); expect(longTextShortPrefix.maxIntrinsicWidth, 450); - // expect(longTextShortPrefix.height, 20); + expect(longTextShortPrefix.height, 20); expectLines(longTextShortPrefix, [ l('AAA', 0, 4, hardBreak: true, width: 30.0, left: 0.0), l('AA...', 4, 6, hardBreak: false, width: 50.0, left: 0.0), @@ -429,7 +437,7 @@ void testMain() async { ..layout(constrain(50.0)); expect(trailingSpace.minIntrinsicWidth, 30); expect(trailingSpace.maxIntrinsicWidth, 60); - // expect(trailingSpace.height, 10); + expect(trailingSpace.height, 10); expectLines(trailingSpace, [ l('AA...', 0, 2, hardBreak: false, width: 50.0, left: 0.0), ]); @@ -439,7 +447,7 @@ void testMain() async { ..layout(constrain(30.0)); expect(paragraph.minIntrinsicWidth, 40); expect(paragraph.maxIntrinsicWidth, 40); - // expect(paragraph.height, 10); + expect(paragraph.height, 10); expectLines(paragraph, [ l('...', 0, 0, hardBreak: false, width: 30.0, left: 0.0), ]); @@ -448,7 +456,7 @@ void testMain() async { paragraph.layout(constrain(10.0)); expect(paragraph.minIntrinsicWidth, 40); expect(paragraph.maxIntrinsicWidth, 40); - // expect(paragraph.height, 10); + expect(paragraph.height, 10); // TODO(flutter_web): https://github.com/flutter/flutter/issues/34346 // expectLines(paragraph, [ @@ -469,7 +477,7 @@ void testMain() async { // The height should be that of a single line. final CanvasParagraph oneline = plain(maxlinesStyle, 'One line') ..layout(constrain(double.infinity)); - // expect(oneline.height, 10); + expect(oneline.height, 10); expectLines(oneline, [ l('One line', 0, 8, hardBreak: true, width: 80.0, left: 0.0), ]); @@ -478,7 +486,7 @@ void testMain() async { final CanvasParagraph threelines = plain(maxlinesStyle, 'First\nSecond\nThird') ..layout(constrain(double.infinity)); - // expect(threelines.height, 20); + expect(threelines.height, 20); expectLines(threelines, [ l('First', 0, 6, hardBreak: true, width: 50.0, left: 0.0), l('Second', 6, 13, hardBreak: true, width: 60.0, left: 0.0), @@ -489,7 +497,7 @@ void testMain() async { maxlinesStyle, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', )..layout(constrain(50.0)); - // expect(veryLong.height, 20); + expect(veryLong.height, 20); expectLines(veryLong, [ l('Lorem ', 0, 6, hardBreak: false, width: 50.0, left: 0.0), l('ipsum ', 6, 12, hardBreak: false, width: 50.0, left: 0.0), @@ -500,7 +508,7 @@ void testMain() async { maxlinesStyle, 'AAA AAAAAAAAAAAAAAAAAAA', )..layout(constrain(50.0)); - // expect(veryLongLastLine.height, 20); + expect(veryLongLastLine.height, 20); expectLines(veryLongLastLine, [ l('AAA ', 0, 4, hardBreak: false, width: 30.0, left: 0.0), l('AAAAA', 4, 9, hardBreak: false, width: 50.0, left: 0.0), @@ -525,21 +533,21 @@ void testMain() async { // Simple no overflow case. paragraph = plain(onelineStyle, 'abcdef')..layout(constrain(60.0)); - // expect(paragraph.height, 10); + expect(paragraph.height, 10); expectLines(paragraph, [ l('abcdef', 0, 6, hardBreak: true, width: 60.0, left: 0.0), ]); // Simple overflow case. paragraph = plain(onelineStyle, 'abcd efg')..layout(constrain(60.0)); - // expect(paragraph.height, 10); + expect(paragraph.height, 10); expectLines(paragraph, [ l('abc...', 0, 3, hardBreak: false, width: 60.0, left: 0.0), ]); // Another simple overflow case. paragraph = plain(onelineStyle, 'a bcde fgh')..layout(constrain(60.0)); - // expect(paragraph.height, 10); + expect(paragraph.height, 10); expectLines(paragraph, [ l('a b...', 0, 3, hardBreak: false, width: 60.0, left: 0.0), ]); @@ -547,7 +555,7 @@ void testMain() async { // The ellipsis is supposed to go on the second line, but because the // 2nd line doesn't overflow, no ellipsis is shown. paragraph = plain(multilineStyle, 'abcdef ghijkl')..layout(constrain(60.0)); - // expect(paragraph.height, 20); + expect(paragraph.height, 20); expectLines(paragraph, [ l('abcdef ', 0, 7, hardBreak: false, width: 60.0, left: 0.0), l('ghijkl', 7, 13, hardBreak: true, width: 60.0, left: 0.0), @@ -555,7 +563,7 @@ void testMain() async { // But when the 2nd line is long enough, the ellipsis is shown. paragraph = plain(multilineStyle, 'abcd efghijkl')..layout(constrain(60.0)); - // expect(paragraph.height, 20); + expect(paragraph.height, 20); expectLines(paragraph, [ l('abcd ', 0, 5, hardBreak: false, width: 40.0, left: 0.0), l('efg...', 5, 8, hardBreak: false, width: 60.0, left: 0.0), @@ -565,7 +573,7 @@ void testMain() async { // insert the ellipsis. paragraph = plain(multilineStyle, 'abcde f gh ijk') ..layout(constrain(60.0)); - // expect(paragraph.height, 20); + expect(paragraph.height, 20); expectLines(paragraph, [ l('abcde ', 0, 6, hardBreak: false, width: 50.0, left: 0.0), l('f g...', 6, 9, hardBreak: false, width: 60.0, left: 0.0), @@ -573,7 +581,7 @@ void testMain() async { // First line overflows but second line doesn't. paragraph = plain(multilineStyle, 'abcdefg hijk')..layout(constrain(60.0)); - // expect(paragraph.height, 20); + expect(paragraph.height, 20); expectLines(paragraph, [ l('abcdef', 0, 6, hardBreak: false, width: 60.0, left: 0.0), l('g hijk', 6, 12, hardBreak: true, width: 60.0, left: 0.0), @@ -582,7 +590,7 @@ void testMain() async { // Both first and second lines overflow. paragraph = plain(multilineStyle, 'abcdefg hijklmnop') ..layout(constrain(60.0)); - // expect(paragraph.height, 20); + expect(paragraph.height, 20); expectLines(paragraph, [ l('abcdef', 0, 6, hardBreak: false, width: 60.0, left: 0.0), l('g h...', 6, 9, hardBreak: false, width: 60.0, left: 0.0),