| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:test/bootstrap/browser.dart'; |
| import 'package:test/test.dart'; |
| import 'package:ui/src/engine.dart'; |
| import 'package:ui/ui.dart' as ui; |
| |
| import '../html/paragraph/helper.dart'; |
| |
| const ui.Color white = ui.Color(0xFFFFFFFF); |
| const ui.Color black = ui.Color(0xFF000000); |
| const ui.Color red = ui.Color(0xFFFF0000); |
| const ui.Color green = ui.Color(0xFF00FF00); |
| const ui.Color blue = ui.Color(0xFF0000FF); |
| |
| final EngineParagraphStyle ahemStyle = EngineParagraphStyle( |
| fontFamily: 'ahem', |
| fontSize: 10, |
| ); |
| |
| ui.ParagraphConstraints constrain(double width) { |
| return ui.ParagraphConstraints(width: width); |
| } |
| |
| void main() { |
| internalBootstrapBrowserTest(() => testMain); |
| } |
| |
| Future<void> testMain() async { |
| await ui.webOnlyInitializeTestDomRenderer(); |
| |
| group('$CanvasParagraph.getBoxesForRange', () { |
| test('return empty list for invalid ranges', () { |
| final CanvasParagraph paragraph = rich(ahemStyle, (CanvasParagraphBuilder builder) { |
| builder.addText('Lorem ipsum'); |
| }) |
| ..layout(constrain(double.infinity)); |
| |
| expect(paragraph.getBoxesForRange(-1, 0), <ui.TextBox>[]); |
| expect(paragraph.getBoxesForRange(0, 0), <ui.TextBox>[]); |
| expect(paragraph.getBoxesForRange(11, 11), <ui.TextBox>[]); |
| expect(paragraph.getBoxesForRange(11, 12), <ui.TextBox>[]); |
| expect(paragraph.getBoxesForRange(4, 3), <ui.TextBox>[]); |
| }); |
| |
| test('handles single-line multi-span paragraphs', () { |
| final CanvasParagraph paragraph = rich(ahemStyle, (CanvasParagraphBuilder builder) { |
| builder.pushStyle(EngineTextStyle.only(color: blue)); |
| builder.addText('Lorem '); |
| builder.pushStyle(EngineTextStyle.only(color: green)); |
| builder.addText('ipsum '); |
| builder.pop(); |
| builder.addText('.'); |
| }) |
| ..layout(constrain(double.infinity)); |
| |
| // Within the first span "Lorem ". |
| |
| expect( |
| // "or" |
| paragraph.getBoxesForRange(1, 3), |
| <ui.TextBox>[ |
| box(10, 0, 30, 10), |
| ], |
| ); |
| expect( |
| // "Lorem" |
| paragraph.getBoxesForRange(0, 5), |
| <ui.TextBox>[ |
| box(0, 0, 50, 10), |
| ], |
| ); |
| // Make sure the trailing space is also included in the box. |
| expect( |
| // "Lorem " |
| paragraph.getBoxesForRange(0, 6), |
| <ui.TextBox>[ |
| // "Lorem" |
| box(0, 0, 50, 10), |
| // " " |
| box(50, 0, 60, 10), |
| ], |
| ); |
| |
| // Within the second span "ipsum ". |
| |
| expect( |
| // "psum" |
| paragraph.getBoxesForRange(7, 11), |
| <ui.TextBox>[ |
| box(70, 0, 110, 10), |
| ], |
| ); |
| expect( |
| // "um " |
| paragraph.getBoxesForRange(9, 12), |
| <ui.TextBox>[ |
| // "um" |
| box(90, 0, 110, 10), |
| // " " |
| box(110, 0, 120, 10), |
| ], |
| ); |
| |
| // Across the two spans "Lorem " and "ipsum ". |
| |
| expect( |
| // "rem ipsum" |
| paragraph.getBoxesForRange(2, 11), |
| <ui.TextBox>[ |
| // "rem" |
| box(20, 0, 50, 10), |
| // " " |
| box(50, 0, 60, 10), |
| // "ipsum" |
| box(60, 0, 110, 10), |
| ], |
| ); |
| |
| // Across all spans "Lorem ", "ipsum ", ".". |
| |
| expect( |
| // "Lorem ipsum ." |
| paragraph.getBoxesForRange(0, 13), |
| <ui.TextBox>[ |
| // "Lorem" |
| box(0, 0, 50, 10), |
| // " " |
| box(50, 0, 60, 10), |
| // "ipsum" |
| box(60, 0, 110, 10), |
| // " " |
| box(110, 0, 120, 10), |
| // "." |
| box(120, 0, 130, 10), |
| ], |
| ); |
| }); |
| |
| test('handles multi-line single-span paragraphs', () { |
| final CanvasParagraph paragraph = rich(ahemStyle, (CanvasParagraphBuilder builder) { |
| builder.addText('Lorem ipsum dolor sit'); |
| }) |
| ..layout(constrain(90.0)); |
| |
| // Lines: |
| // "Lorem " |
| // "ipsum " |
| // "dolor sit" |
| |
| // Within the first line "Lorem ". |
| |
| expect( |
| // "or" |
| paragraph.getBoxesForRange(1, 3), |
| <ui.TextBox>[ |
| box(10, 0, 30, 10), |
| ], |
| ); |
| // Make sure the trailing space at the end of line is also included in the |
| // box. |
| expect( |
| // "Lorem " |
| paragraph.getBoxesForRange(0, 6), |
| <ui.TextBox>[ |
| // "Lorem" |
| box(0, 0, 50, 10), |
| // " " |
| box(50, 0, 60, 10), |
| ], |
| ); |
| |
| // Within the second line "ipsum ". |
| |
| expect( |
| // "psum " |
| paragraph.getBoxesForRange(7, 12), |
| <ui.TextBox>[ |
| // "psum" |
| box(10, 10, 50, 20), |
| // " " |
| box(50, 10, 60, 20), |
| ], |
| ); |
| |
| // Across all lines. |
| |
| expect( |
| // "em " |
| // "ipsum " |
| // "dolor s" |
| paragraph.getBoxesForRange(3, 19), |
| <ui.TextBox>[ |
| // "em" |
| box(30, 0, 50, 10), |
| // " " |
| box(50, 0, 60, 10), |
| // "ipsum" |
| box(0, 10, 50, 20), |
| // " " |
| box(50, 10, 60, 20), |
| // "dolor" |
| box(0, 20, 50, 30), |
| // " " |
| box(50, 20, 60, 30), |
| // "s" |
| box(60, 20, 70, 30), |
| ], |
| ); |
| }); |
| |
| test('handles multi-line multi-span paragraphs', () { |
| final CanvasParagraph paragraph = rich(ahemStyle, (CanvasParagraphBuilder builder) { |
| builder.pushStyle(EngineTextStyle.only(color: blue)); |
| builder.addText('Lorem ipsum '); |
| builder.pushStyle(EngineTextStyle.only(color: green)); |
| builder.addText('dolor '); |
| builder.pop(); |
| builder.addText('sit'); |
| }) |
| ..layout(constrain(90.0)); |
| |
| // Lines: |
| // "Lorem " |
| // "ipsum " |
| // "dolor sit" |
| |
| // Within the first line "Lorem ". |
| |
| expect( |
| // "ore" |
| paragraph.getBoxesForRange(1, 4), |
| <ui.TextBox>[ |
| box(10, 0, 40, 10), |
| ], |
| ); |
| expect( |
| // "Lorem " |
| paragraph.getBoxesForRange(0, 6), |
| <ui.TextBox>[ |
| // "Lorem" |
| box(0, 0, 50, 10), |
| // " " |
| box(50, 0, 60, 10), |
| ], |
| ); |
| |
| // Within the second line "ipsum ". |
| |
| expect( |
| // "psum " |
| paragraph.getBoxesForRange(7, 12), |
| <ui.TextBox>[ |
| // "psum" |
| box(10, 10, 50, 20), |
| // " " |
| box(50, 10, 60, 20), |
| ], |
| ); |
| |
| // Within the third line "dolor sit" which is made of 2 spans. |
| |
| expect( |
| // "lor sit" |
| paragraph.getBoxesForRange(14, 21), |
| <ui.TextBox>[ |
| // "lor" |
| box(20, 20, 50, 30), |
| // " " |
| box(50, 20, 60, 30), |
| // "sit" |
| box(60, 20, 90, 30), |
| ], |
| ); |
| |
| // Across all lines. |
| |
| expect( |
| // "em " |
| // "ipsum " |
| // "dolor s" |
| paragraph.getBoxesForRange(3, 19), |
| <ui.TextBox>[ |
| // "em" |
| box(30, 0, 50, 10), |
| // " " |
| box(50, 0, 60, 10), |
| // "ipsum" |
| box(0, 10, 50, 20), |
| // " " |
| box(50, 10, 60, 20), |
| // "dolor" |
| box(0, 20, 50, 30), |
| // " " |
| box(50, 20, 60, 30), |
| // "s" |
| box(60, 20, 70, 30), |
| ], |
| ); |
| }); |
| |
| test('handles spans with varying heights/baselines', () { |
| final CanvasParagraph paragraph = rich(ahemStyle, (CanvasParagraphBuilder builder) { |
| builder.pushStyle(EngineTextStyle.only(fontSize: 20.0)); |
| // width = 20.0 * 6 = 120.0 |
| // baseline = 20.0 * 80% = 16.0 |
| builder.addText('Lorem '); |
| builder.pushStyle(EngineTextStyle.only(fontSize: 40.0)); |
| // width = 40.0 * 6 = 240.0 |
| // baseline = 40.0 * 80% = 32.0 |
| builder.addText('ipsum '); |
| builder.pushStyle(EngineTextStyle.only(fontSize: 10.0)); |
| // width = 10.0 * 6 = 60.0 |
| // baseline = 10.0 * 80% = 8.0 |
| builder.addText('dolor '); |
| builder.pushStyle(EngineTextStyle.only(fontSize: 30.0)); |
| // width = 30.0 * 4 = 120.0 |
| // baseline = 30.0 * 80% = 24.0 |
| builder.addText('sit '); |
| builder.pushStyle(EngineTextStyle.only(fontSize: 20.0)); |
| // width = 20.0 * 4 = 80.0 |
| // baseline = 20.0 * 80% = 16.0 |
| builder.addText('amet'); |
| }) |
| ..layout(constrain(420.0)); |
| |
| // Lines: |
| // "Lorem ipsum dolor " (width: 420, height: 40, baseline: 32) |
| // "sit amet" (width: 200, height: 30, baseline: 24) |
| |
| expect( |
| // "em ipsum dol" |
| paragraph.getBoxesForRange(3, 15), |
| <ui.TextBox>[ |
| // "em" |
| box(60, 16, 100, 36), |
| // " " |
| box(100, 16, 120, 36), |
| // "ipsum" |
| box(120, 0, 320, 40), |
| // " " |
| box(320, 0, 360, 40), |
| // "dol" |
| box(360, 24, 390, 34), |
| ], |
| ); |
| |
| expect( |
| // "sum dolor " |
| // "sit amet" |
| paragraph.getBoxesForRange(8, 26), |
| <ui.TextBox>[ |
| // "sum" |
| box(200, 0, 320, 40), |
| // " " |
| box(320, 0, 360, 40), |
| // "dolor" |
| box(360, 24, 410, 34), |
| // " " |
| box(410, 24, 420, 34), |
| // "sit" |
| box(0, 40, 90, 70), |
| // " " |
| box(90, 40, 120, 70), |
| // "amet" |
| box(120, 48, 200, 68), |
| ], |
| ); |
| }); |
| }); |
| |
| group('$CanvasParagraph.getPositionForOffset', () { |
| test('handles single-line multi-span paragraphs', () { |
| final CanvasParagraph paragraph = rich(ahemStyle, (CanvasParagraphBuilder builder) { |
| builder.pushStyle(EngineTextStyle.only(color: blue)); |
| builder.addText('Lorem '); |
| builder.pushStyle(EngineTextStyle.only(color: green)); |
| builder.addText('ipsum '); |
| builder.pop(); |
| builder.addText('.'); |
| }) |
| ..layout(constrain(double.infinity)); |
| |
| // Above the line, at the beginning. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(0, -5)), |
| pos(0, ui.TextAffinity.downstream), |
| ); |
| // At the top left corner of the line. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(0, 0)), |
| pos(0, ui.TextAffinity.downstream), |
| ); |
| // At the beginning of the line. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(0, 5)), |
| pos(0, ui.TextAffinity.downstream), |
| ); |
| // Below the line, at the end. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(130, 12)), |
| pos(13, ui.TextAffinity.upstream), |
| ); |
| // At the end of the line. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(130, 5)), |
| pos(13, ui.TextAffinity.upstream), |
| ); |
| // On the left half of "p" in "ipsum". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(74, 5)), |
| pos(7, ui.TextAffinity.downstream), |
| ); |
| // On the left half of "p" in "ipsum" (above the line). |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(74, -5)), |
| pos(7, ui.TextAffinity.downstream), |
| ); |
| // On the left half of "p" in "ipsum" (below the line). |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(74, 15)), |
| pos(7, ui.TextAffinity.downstream), |
| ); |
| // On the right half of "p" in "ipsum". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(76, 5)), |
| pos(8, ui.TextAffinity.upstream), |
| ); |
| // At the top of the line, on the left half of "p" in "ipsum". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(74, 0)), |
| pos(7, ui.TextAffinity.downstream), |
| ); |
| // At the top of the line, on the right half of "p" in "ipsum". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(76, 0)), |
| pos(8, ui.TextAffinity.upstream), |
| ); |
| }); |
| |
| test('handles multi-line single-span paragraphs', () { |
| final CanvasParagraph paragraph = rich(ahemStyle, (CanvasParagraphBuilder builder) { |
| builder.addText('Lorem ipsum dolor sit'); |
| }) |
| ..layout(constrain(90.0)); |
| |
| // Lines: |
| // "Lorem " |
| // "ipsum " |
| // "dolor sit" |
| |
| // Above the first line, at the beginning. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(0, -5)), |
| pos(0, ui.TextAffinity.downstream), |
| ); |
| // At the top left corner of the line. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(0, 0)), |
| pos(0, ui.TextAffinity.downstream), |
| ); |
| // At the beginning of the first line. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(0, 5)), |
| pos(0, ui.TextAffinity.downstream), |
| ); |
| // At the end of the first line. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(60, 5)), |
| pos(6, ui.TextAffinity.upstream), |
| ); |
| // At the end of the first line (above the line). |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(60, -5)), |
| pos(6, ui.TextAffinity.upstream), |
| ); |
| // After the end of the first line to the right. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(70, 5)), |
| pos(6, ui.TextAffinity.upstream), |
| ); |
| // On the left half of " " in "Lorem ". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(54, 5)), |
| pos(5, ui.TextAffinity.downstream), |
| ); |
| // On the right half of " " in "Lorem ". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(56, 5)), |
| pos(6, ui.TextAffinity.upstream), |
| ); |
| |
| // At the beginning of the second line "ipsum ". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(0, 15)), |
| pos(6, ui.TextAffinity.downstream), |
| ); |
| // At the end of the second line. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(60, 15)), |
| pos(12, ui.TextAffinity.upstream), |
| ); |
| // After the end of the second line to the right. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(70, 15)), |
| pos(12, ui.TextAffinity.upstream), |
| ); |
| |
| // Below the third line "dolor sit", at the end. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(90, 40)), |
| pos(21, ui.TextAffinity.upstream), |
| ); |
| // At the end of the third line. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(90, 25)), |
| pos(21, ui.TextAffinity.upstream), |
| ); |
| // After the end of the third line to the right. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(100, 25)), |
| pos(21, ui.TextAffinity.upstream), |
| ); |
| // On the left half of " " in "dolor sit". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(54, 25)), |
| pos(17, ui.TextAffinity.downstream), |
| ); |
| // On the right half of " " in "dolor sit". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(56, 25)), |
| pos(18, ui.TextAffinity.upstream), |
| ); |
| }); |
| |
| test('handles multi-line multi-span paragraphs', () { |
| final CanvasParagraph paragraph = rich(ahemStyle, (CanvasParagraphBuilder builder) { |
| builder.pushStyle(EngineTextStyle.only(color: blue)); |
| builder.addText('Lorem ipsum '); |
| builder.pushStyle(EngineTextStyle.only(color: green)); |
| builder.addText('dolor '); |
| builder.pop(); |
| builder.addText('sit'); |
| }) |
| ..layout(constrain(90.0)); |
| |
| // Lines: |
| // "Lorem " |
| // "ipsum " |
| // "dolor sit" |
| |
| // Above the first line, at the beginning. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(0, -5)), |
| pos(0, ui.TextAffinity.downstream), |
| ); |
| // At the beginning of the first line. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(0, 5)), |
| pos(0, ui.TextAffinity.downstream), |
| ); |
| // At the end of the first line. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(60, 5)), |
| pos(6, ui.TextAffinity.upstream), |
| ); |
| // After the end of the first line to the right. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(70, 5)), |
| pos(6, ui.TextAffinity.upstream), |
| ); |
| // On the left half of " " in "Lorem ". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(54, 5)), |
| pos(5, ui.TextAffinity.downstream), |
| ); |
| // On the right half of " " in "Lorem ". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(56, 5)), |
| pos(6, ui.TextAffinity.upstream), |
| ); |
| |
| // At the beginning of the second line "ipsum ". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(0, 15)), |
| pos(6, ui.TextAffinity.downstream), |
| ); |
| // At the end of the second line. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(60, 15)), |
| pos(12, ui.TextAffinity.upstream), |
| ); |
| // After the end of the second line to the right. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(70, 15)), |
| pos(12, ui.TextAffinity.upstream), |
| ); |
| |
| // Below the third line "dolor sit", at the end. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(90, 40)), |
| pos(21, ui.TextAffinity.upstream), |
| ); |
| // At the end of the third line. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(90, 25)), |
| pos(21, ui.TextAffinity.upstream), |
| ); |
| // After the end of the third line to the right. |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(100, 25)), |
| pos(21, ui.TextAffinity.upstream), |
| ); |
| // On the left half of " " in "dolor sit". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(54, 25)), |
| pos(17, ui.TextAffinity.downstream), |
| ); |
| // On the right half of " " in "dolor sit". |
| expect( |
| paragraph.getPositionForOffset(const ui.Offset(56, 25)), |
| pos(18, ui.TextAffinity.upstream), |
| ); |
| }); |
| }); |
| |
| group('$CanvasParagraph.getLineBoundary', () { |
| test('single-line', () { |
| final CanvasParagraph paragraph = rich(ahemStyle, (CanvasParagraphBuilder builder) { |
| builder.addText('One single line'); |
| }) |
| ..layout(constrain(400.0)); |
| |
| // "One single line".length == 15 |
| for (int i = 0; i < 15; i++) { |
| expect( |
| paragraph.getLineBoundary(ui.TextPosition(offset: i)), |
| const ui.TextRange(start: 0, end: 15), |
| reason: 'failed at offset $i', |
| ); |
| } |
| }); |
| |
| test('multi-line', () { |
| final CanvasParagraph paragraph = rich(ahemStyle, (CanvasParagraphBuilder builder) { |
| builder.addText('First line\n'); |
| builder.addText('Second line\n'); |
| builder.addText('Third line'); |
| }) |
| ..layout(constrain(400.0)); |
| |
| // "First line\n".length == 11 |
| for (int i = 0; i < 11; i++) { |
| expect( |
| paragraph.getLineBoundary(ui.TextPosition(offset: i)), |
| const ui.TextRange(start: 0, end: 11), |
| reason: 'failed at offset $i', |
| ); |
| } |
| |
| // "Second line\n".length == 12 |
| for (int i = 11; i < 23; i++) { |
| expect( |
| paragraph.getLineBoundary(ui.TextPosition(offset: i)), |
| const ui.TextRange(start: 11, end: 23), |
| reason: 'failed at offset $i', |
| ); |
| } |
| |
| // "Third line".length == 10 |
| for (int i = 23; i < 33; i++) { |
| expect( |
| paragraph.getLineBoundary(ui.TextPosition(offset: i)), |
| const ui.TextRange(start: 23, end: 33), |
| reason: 'failed at offset $i', |
| ); |
| } |
| }); |
| }); |
| |
| test('$CanvasParagraph.getWordBoundary', () { |
| final ui.Paragraph paragraph = plain(ahemStyle, 'Lorem ipsum dolor'); |
| |
| const ui.TextRange loremRange = ui.TextRange(start: 0, end: 5); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 0)), loremRange); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 1)), loremRange); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 2)), loremRange); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 3)), loremRange); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 4)), loremRange); |
| |
| const ui.TextRange firstSpace = ui.TextRange(start: 5, end: 6); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 5)), firstSpace); |
| |
| const ui.TextRange ipsumRange = ui.TextRange(start: 6, end: 11); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 6)), ipsumRange); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 7)), ipsumRange); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 8)), ipsumRange); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 9)), ipsumRange); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 10)), ipsumRange); |
| |
| const ui.TextRange secondSpace = ui.TextRange(start: 11, end: 12); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 11)), secondSpace); |
| |
| const ui.TextRange dolorRange = ui.TextRange(start: 12, end: 17); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 12)), dolorRange); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 13)), dolorRange); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 14)), dolorRange); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 15)), dolorRange); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 16)), dolorRange); |
| |
| const ui.TextRange endRange = ui.TextRange(start: 17, end: 17); |
| expect(paragraph.getWordBoundary(const ui.TextPosition(offset: 17)), endRange); |
| }); |
| |
| test('$CanvasParagraph.longestLine', () { |
| final ui.Paragraph paragraph = plain(ahemStyle, 'abcd\nabcde abc'); |
| paragraph.layout(const ui.ParagraphConstraints(width: 80.0)); |
| expect(paragraph.longestLine, 50.0); |
| }); |
| |
| test('$CanvasParagraph.width should be a whole integer', () { |
| final ui.Paragraph paragraph = plain(ahemStyle, 'abc'); |
| paragraph.layout(const ui.ParagraphConstraints(width: 30.8)); |
| |
| expect(paragraph.width, 30); |
| expect(paragraph.height, 10); |
| }); |
| } |
| |
| /// Shortcut to create a [ui.TextBox] with an optional [ui.TextDirection]. |
| ui.TextBox box( |
| double left, |
| double top, |
| double right, |
| double bottom, [ |
| ui.TextDirection direction = ui.TextDirection.ltr, |
| ]) { |
| return ui.TextBox.fromLTRBD(left, top, right, bottom, direction); |
| } |
| |
| /// Shortcut to create a [ui.TextPosition]. |
| ui.TextPosition pos(int offset, ui.TextAffinity affinity) { |
| return ui.TextPosition(offset: offset, affinity: affinity); |
| } |