未验证 提交 730ad860 编写于 作者: M Mouad Debbar 提交者: GitHub

[web] Calculate height and baseline for rich text (#23064)

上级 66fcb104
......@@ -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);
if (ellipsis != null) {
ellipsisWidth = spanometer.measureText(ellipsis);
text += ellipsis;
}
final double ellipsisWidth =
ellipsis == null ? 0.0 : spanometer.measureText(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<TextHeightStyle, TextHeightRuler> _rulers =
<TextHeightStyle, TextHeightRuler>{};
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.
......
......@@ -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)) {
......
......@@ -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<TestLine> expectedLines) {
final String text = paragraph.toPlainText();
final List<EngineLineMetrics> lines =
paragraph.computeLineMetrics() as List<EngineLineMetrics>;
expect(lines, hasLength(expectedLines.length));
......@@ -43,8 +48,11 @@ void expectLines(CanvasParagraph paragraph, List<TestLine> 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;
}
......@@ -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),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册