Skip to content

Commit 587c023

Browse files
authored
[web] Add new line break type (prohibited) (flutter#22771)
1 parent 609307d commit 587c023

File tree

3 files changed

+34
-8
lines changed

3 files changed

+34
-8
lines changed

lib/web_ui/lib/src/engine/text/line_breaker.dart

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ enum LineBreakType {
1010
/// Indicates that a line break is possible but not mandatory.
1111
opportunity,
1212

13+
/// Indicates that a line break isn't possible.
14+
prohibited,
15+
1316
/// Indicates that this is a hard line break that can't be skipped.
1417
mandatory,
1518

@@ -74,6 +77,9 @@ class LineBreakResult {
7477
/// to decide whether to take the line break or not.
7578
final LineBreakType type;
7679

80+
bool get isHard =>
81+
type == LineBreakType.mandatory || type == LineBreakType.endOfText;
82+
7783
@override
7884
int get hashCode => ui.hashValues(
7985
index,
@@ -160,7 +166,7 @@ bool _hasEastAsianWidthFWH(int charCode) {
160166
///
161167
/// * https://www.unicode.org/reports/tr14/tr14-45.html#Algorithm
162168
/// * https://www.unicode.org/Public/11.0.0/ucd/LineBreak.txt
163-
LineBreakResult nextLineBreak(String text, int index) {
169+
LineBreakResult nextLineBreak(String text, int index, {int? maxEnd}) {
164170
int? codePoint = getCodePoint(text, index);
165171
LineCharProperty curr = lineLookup.findForChar(codePoint);
166172

@@ -199,6 +205,15 @@ LineBreakResult nextLineBreak(String text, int index) {
199205
// Always break at the end of text.
200206
// LB3: ! eot
201207
while (index < text.length) {
208+
if (index == maxEnd) {
209+
return LineBreakResult(
210+
index,
211+
lastNonNewlineIndex,
212+
lastNonSpaceIndex,
213+
LineBreakType.prohibited,
214+
);
215+
}
216+
202217
// Keep count of the RI (regional indicator) sequence.
203218
if (curr == LineCharProperty.RI) {
204219
regionalIndicatorCount++;

lib/web_ui/lib/src/engine/text/measurement.dart

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -771,8 +771,6 @@ class LinesCalculator {
771771
/// This method should be called for every line break. As soon as it reaches
772772
/// the maximum number of lines required
773773
void update(LineBreakResult brk) {
774-
final bool isHardBreak = brk.type == LineBreakType.mandatory ||
775-
brk.type == LineBreakType.endOfText;
776774
final int chunkEnd = brk.index;
777775
final int chunkEndWithoutNewlines = brk.indexWithoutTrailingNewlines;
778776
final int chunkEndWithoutSpace = brk.indexWithoutTrailingSpaces;
@@ -855,7 +853,7 @@ class LinesCalculator {
855853
return;
856854
}
857855

858-
if (isHardBreak) {
856+
if (brk.isHard) {
859857
_addLineBreak(brk);
860858
}
861859
_lastBreak = brk;
@@ -872,15 +870,13 @@ class LinesCalculator {
872870
lineWidth: lineWidth,
873871
maxWidth: _maxWidth,
874872
);
875-
final bool isHardBreak = brk.type == LineBreakType.mandatory ||
876-
brk.type == LineBreakType.endOfText;
877873

878874
final EngineLineMetrics metrics = EngineLineMetrics.withText(
879875
_text!.substring(_lineStart, brk.indexWithoutTrailingNewlines),
880876
startIndex: _lineStart,
881877
endIndex: brk.index,
882878
endIndexWithoutNewlines: brk.indexWithoutTrailingNewlines,
883-
hardBreak: isHardBreak,
879+
hardBreak: brk.isHard,
884880
width: lineWidth,
885881
widthWithTrailingSpaces: lineWidthWithTrailingSpaces,
886882
left: alignOffset,
@@ -995,7 +991,7 @@ class MaxIntrinsicCalculator {
995991
/// intrinsic width calculated so far. When the whole text is consumed,
996992
/// [value] will contain the final maximum intrinsic width.
997993
void update(LineBreakResult brk) {
998-
if (brk.type == LineBreakType.opportunity) {
994+
if (!brk.isHard) {
999995
return;
1000996
}
1001997

lib/web_ui/test/text/line_breaker_test.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,14 @@ void testMain() {
252252
'"$text"\n'
253253
'\nExpected line break at {$lastLineBreak - $i} but found line break at {$lastLineBreak - ${result.index}}.',
254254
);
255+
256+
// Since this is a line break, passing a `maxEnd` that's greater
257+
// should return the same line break.
258+
final LineBreakResult maxEndResult =
259+
nextLineBreak(text, lastLineBreak, maxEnd: i + 1);
260+
expect(maxEndResult.index, i);
261+
expect(maxEndResult.type, isNot(LineBreakType.prohibited));
262+
255263
lastLineBreak = i;
256264
} else {
257265
// This isn't a line break opportunity so the line break should be
@@ -264,6 +272,13 @@ void testMain() {
264272
'"$text"\n'
265273
'\nUnexpected line break found at {$lastLineBreak - $i}.',
266274
);
275+
276+
// Since this isn't a line break, passing it as a `maxEnd` should
277+
// return `maxEnd` as a prohibited line break type.
278+
final LineBreakResult maxEndResult =
279+
nextLineBreak(text, lastLineBreak, maxEnd: i);
280+
expect(maxEndResult.index, i);
281+
expect(maxEndResult.type, LineBreakType.prohibited);
267282
}
268283
}
269284
}

0 commit comments

Comments
 (0)