[web] Some cleanup for text tests (flutter/engine#36425)

This commit is contained in:
Mouad Debbar
2022-10-19 12:04:56 -04:00
committed by GitHub
parent 77b980740f
commit 93585f2cd2
20 changed files with 97 additions and 224 deletions

View File

@@ -264,7 +264,7 @@ DomElement drawParagraphElement(
}) {
assert(paragraph.isLaidOut);
final DomHTMLElement paragraphElement = paragraph.toDomElement();
final DomElement paragraphElement = paragraph.toDomElement();
if (transform != null) {
setElementTransform(

View File

@@ -1246,7 +1246,7 @@ class PaintDrawParagraph extends DrawCommand {
@override
String toString() {
if (assertionsEnabled) {
return 'DrawParagraph(${paragraph.toPlainText()}, $offset)';
return 'DrawParagraph(${paragraph.plainText}, $offset)';
} else {
return super.toString();
}

View File

@@ -17,7 +17,7 @@ import 'word_breaker.dart';
const ui.Color _defaultTextColor = ui.Color(0xFFFF0000);
final String _placeholderChar = String.fromCharCode(0xFFFC);
final String placeholderChar = String.fromCharCode(0xFFFC);
/// A paragraph made up of a flat list of text spans and placeholders.
///
@@ -33,7 +33,6 @@ class CanvasParagraph implements ui.Paragraph {
this.spans, {
required this.paragraphStyle,
required this.plainText,
required this.placeholderCount,
required this.canDrawOnCanvas,
}) : assert(spans.isNotEmpty);
@@ -46,9 +45,6 @@ class CanvasParagraph implements ui.Paragraph {
/// The full textual content of the paragraph.
late String plainText;
/// The number of placeholders in this paragraph.
final int placeholderCount;
/// Whether this paragraph can be drawn on a bitmap canvas.
///
/// Some text features cannot be rendered into a 2D canvas and must use HTML,
@@ -87,8 +83,6 @@ class CanvasParagraph implements ui.Paragraph {
/// Whether this paragraph has been laid out or not.
bool isLaidOut = false;
bool get isRtl => paragraphStyle.effectiveTextDirection == ui.TextDirection.rtl;
ui.ParagraphConstraints? _lastUsedConstraints;
late final TextLayoutService _layoutService = TextLayoutService(this);
@@ -138,27 +132,23 @@ class CanvasParagraph implements ui.Paragraph {
_paintService.paint(canvas, offset);
}
/// Generates a flat string computed from all the spans of the paragraph.
String toPlainText() => plainText;
DomHTMLElement? _cachedDomElement;
DomElement? _cachedDomElement;
/// Returns a DOM element that represents the entire paragraph and its
/// children.
///
/// Generates a new DOM element on every invocation.
DomHTMLElement toDomElement() {
DomElement toDomElement() {
assert(isLaidOut);
final DomHTMLElement? domElement = _cachedDomElement;
final DomElement? domElement = _cachedDomElement;
if (domElement == null) {
return _cachedDomElement ??= _createDomElement();
}
return domElement.cloneNode(true) as DomHTMLElement;
return domElement.cloneNode(true) as DomElement;
}
DomHTMLElement _createDomElement() {
final DomHTMLElement rootElement =
domDocument.createElement('flt-paragraph') as DomHTMLElement;
DomElement _createDomElement() {
final DomElement rootElement = domDocument.createElement('flt-paragraph');
// 1. Set paragraph-level styles.
@@ -183,12 +173,8 @@ class CanvasParagraph implements ui.Paragraph {
continue;
}
final DomHTMLElement spanElement = domDocument.createElement('flt-span') as DomHTMLElement;
applyTextStyleToElement(
element: spanElement,
style: fragment.style,
isSpan: true,
);
final DomElement spanElement = domDocument.createElement('flt-span');
applyTextStyleToElement(element: spanElement, style: fragment.style);
_positionSpanElement(spanElement, line, fragment);
spanElement.appendText(text);
@@ -221,7 +207,6 @@ class CanvasParagraph implements ui.Paragraph {
@override
ui.TextRange getWordBoundary(ui.TextPosition position) {
final String text = toPlainText();
final int characterPosition;
switch (position.affinity) {
case ui.TextAffinity.upstream:
@@ -231,8 +216,8 @@ class CanvasParagraph implements ui.Paragraph {
characterPosition = position.offset;
break;
}
final int start = WordBreaker.prevBreakIndex(text, characterPosition + 1);
final int end = WordBreaker.nextBreakIndex(text, characterPosition);
final int start = WordBreaker.prevBreakIndex(plainText, characterPosition + 1);
final int end = WordBreaker.nextBreakIndex(plainText, characterPosition);
return ui.TextRange(start: start, end: end);
}
@@ -288,51 +273,30 @@ void _positionSpanElement(DomElement element, ParagraphLine line, LayoutFragment
..lineHeight = '${boxRect.height}px';
}
/// A common interface for all types of spans that make up a paragraph.
///
/// These spans are stored as a flat list in the paragraph object.
abstract class ParagraphSpan {
/// The index of the beginning of the range of text represented by this span.
int get start;
/// The index of the end of the range of text represented by this span.
int get end;
/// The resolved style of the span.
EngineTextStyle get style;
}
/// Represent a span of text in the paragraph.
///
/// It's a "flat" text span as opposed to the framework text spans that are
/// hierarchical.
/// Represents a span in the paragraph.
///
/// Instead of keeping spans and styles in a tree hierarchy like the framework
/// does, we flatten the structure and resolve/merge all the styles from parent
/// nodes.
class FlatTextSpan implements ParagraphSpan {
/// Creates a [FlatTextSpan] with the given [style], representing the span of
///
/// These spans are stored as a flat list in the paragraph object.
class ParagraphSpan {
/// Creates a [ParagraphSpan] with the given [style], representing the span of
/// text in the range between [start] and [end].
FlatTextSpan({
ParagraphSpan({
required this.style,
required this.start,
required this.end,
});
@override
/// The resolved style of the span.
final EngineTextStyle style;
@override
/// The index of the beginning of the range of text represented by this span.
final int start;
@override
/// The index of the end of the range of text represented by this span.
final int end;
String textOf(CanvasParagraph paragraph) {
final String text = paragraph.toPlainText();
assert(end <= text.length);
return text.substring(start, end);
}
}
class PlaceholderSpan extends ParagraphPlaceholder implements ParagraphSpan {
@@ -622,16 +586,13 @@ class CanvasParagraphBuilder implements ui.ParagraphBuilder {
double? baselineOffset,
ui.TextBaseline? baseline,
}) {
// TODO(mdebbar): for measurement of placeholders, look at:
// - https://github.com/flutter/engine/blob/c0f7e8acf9318d264ad6a235facd097de597ffcc/third_party/txt/src/txt/paragraph_txt.cc#L325-L350
// Require a baseline to be specified if using a baseline-based alignment.
assert(!(alignment == ui.PlaceholderAlignment.aboveBaseline ||
alignment == ui.PlaceholderAlignment.belowBaseline ||
alignment == ui.PlaceholderAlignment.baseline) || baseline != null);
final int start = _plainTextBuffer.length;
_plainTextBuffer.write(_placeholderChar);
_plainTextBuffer.write(placeholderChar);
final int end = _plainTextBuffer.length;
final EngineTextStyle style = _currentStyleNode.resolveStyle();
@@ -674,7 +635,7 @@ class CanvasParagraphBuilder implements ui.ParagraphBuilder {
final EngineTextStyle style = _currentStyleNode.resolveStyle();
_updateCanDrawOnCanvas(style);
_spans.add(FlatTextSpan(style: style, start: start, end: end));
_spans.add(ParagraphSpan(style: style, start: start, end: end));
}
void _updateCanDrawOnCanvas(EngineTextStyle style) {
@@ -708,18 +669,15 @@ class CanvasParagraphBuilder implements ui.ParagraphBuilder {
//
// We want the paragraph to always have a non-empty list of spans to match
// the expectations of the [LayoutFragmenter].
_spans.add(FlatTextSpan(
style: _rootStyleNode.resolveStyle(),
start: 0,
end: 0,
));
_spans.add(
ParagraphSpan(style: _rootStyleNode.resolveStyle(), start: 0, end: 0),
);
}
return CanvasParagraph(
_spans,
paragraphStyle: _paragraphStyle,
plainText: _plainTextBuffer.toString(),
placeholderCount: _placeholderCount,
canDrawOnCanvas: _canDrawOnCanvas,
);
}

View File

@@ -360,7 +360,7 @@ class TextLayoutService {
return <ui.TextBox>[];
}
final int length = paragraph.toPlainText().length;
final int length = paragraph.plainText.length;
// Ranges that are out of bounds should return an empty list.
if (start > length || end > length) {
return <ui.TextBox>[];
@@ -1046,10 +1046,9 @@ class Spanometer {
assert(start >= currentSpan.start && start <= currentSpan.end);
assert(end >= currentSpan.start && end <= currentSpan.end);
final String text = paragraph.toPlainText();
return measureSubstring(
context,
text,
paragraph.plainText,
start,
end,
letterSpacing: letterSpacing,

View File

@@ -36,15 +36,16 @@ class TextPaintService {
ui.Offset offset,
LayoutFragment fragment,
) {
final ParagraphSpan span = fragment.span;
if (span is FlatTextSpan) {
// Paint the background of the box, if the span has a background.
final SurfacePaint? background = span.style.background as SurfacePaint?;
if (background != null) {
final ui.Rect rect = fragment.toPaintingTextBox().toRect();
if (!rect.isEmpty) {
canvas.drawRect(rect.shift(offset), background.paintData);
}
if (fragment.isPlaceholder) {
return;
}
// Paint the background of the box, if the span has a background.
final SurfacePaint? background = fragment.style.background as SurfacePaint?;
if (background != null) {
final ui.Rect rect = fragment.toPaintingTextBox().toRect();
if (!rect.isEmpty) {
canvas.drawRect(rect.shift(offset), background.paintData);
}
}
}

View File

@@ -774,13 +774,9 @@ String fontWeightIndexToCss({int fontWeightIndex = 3}) {
/// Applies a text [style] to an [element], translating the properties to their
/// corresponding CSS equivalents.
///
/// If [isSpan] is true, the text element is a span within richtext and
/// should not assign effectiveFontFamily if fontFamily was not specified.
void applyTextStyleToElement({
required DomHTMLElement element,
required DomElement element,
required EngineTextStyle style,
bool isSpan = false,
}) {
assert(element != null);
assert(style != null);
@@ -822,10 +818,10 @@ void applyTextStyleToElement({
}
// For test environment use effectiveFontFamily since we need to
// consistently use Ahem font.
if (isSpan && !ui.debugEmulateFlutterTesterEnvironment) {
cssStyle.fontFamily = canonicalizeFontFamily(style.fontFamily)!;
} else {
if (ui.debugEmulateFlutterTesterEnvironment) {
cssStyle.fontFamily = canonicalizeFontFamily(style.effectiveFontFamily)!;
} else {
cssStyle.fontFamily = canonicalizeFontFamily(style.fontFamily)!;
}
if (style.letterSpacing != null) {
cssStyle.letterSpacing = '${style.letterSpacing}px';

View File

@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
@@ -12,8 +10,6 @@ import 'package:ui/ui.dart' hide window;
import '../screenshot.dart';
import 'helper.dart';
typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);
const String _rtlWord1 = 'واحد';
const String _rtlWord2 = 'اثنان';

View File

@@ -13,8 +13,6 @@ import 'package:ui/ui.dart' hide window;
import '../screenshot.dart';
import 'helper.dart';
typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);
const Rect bounds = Rect.fromLTWH(0, 0, 800, 600);
void main() {

View File

@@ -2,10 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart';
import 'package:web_engine_tester/golden_tester.dart';
typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);
const LineBreakType prohibited = LineBreakType.prohibited;
const LineBreakType opportunity = LineBreakType.opportunity;
const LineBreakType mandatory = LineBreakType.mandatory;
@@ -32,6 +36,11 @@ const Color blue = Color(0xFF0000FF);
const Color yellow = Color(0xFFFFEB3B);
const Color lightPurple = Color(0xFFE1BEE7);
final EngineParagraphStyle ahemStyle = EngineParagraphStyle(
fontFamily: 'ahem',
fontSize: 10,
);
ParagraphConstraints constrain(double width) {
return ParagraphConstraints(width: width);
}
@@ -73,10 +82,7 @@ Future<void> takeScreenshot(
try {
sceneElement.append(canvas.rootElement);
domDocument.body!.append(sceneElement);
await matchGoldenFile(
'$fileName.png',
region: region,
);
await matchGoldenFile('$fileName.png', region: region);
} finally {
// The page is reused across tests, so remove the element after taking the
// Scuba screenshot.
@@ -109,3 +115,7 @@ void fillBoxes(EngineCanvas canvas, Offset offset, List<TextBox> boxes, Color co
canvas.drawRect(rect, SurfacePaintData()..color = color);
}
}
String getSpanText(CanvasParagraph paragraph, ParagraphSpan span) {
return paragraph.plainText.substring(span.start, span.end);
}

View File

@@ -12,8 +12,6 @@ import 'package:ui/ui.dart' hide window;
import '../screenshot.dart';
import 'helper.dart';
typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);
void main() {
internalBootstrapBrowserTest(() => testMain);
}

View File

@@ -12,8 +12,6 @@ import 'package:ui/ui.dart' hide window;
import '../screenshot.dart';
import 'helper.dart';
typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);
const Rect bounds = Rect.fromLTWH(0, 0, 800, 600);
void main() {

View File

@@ -11,8 +11,6 @@ import 'package:ui/ui.dart' hide window;
import '../screenshot.dart';
import 'text_scuba.dart';
typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);
const String threeLines = 'First\nSecond\nThird';
const String veryLong =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.';

View File

@@ -7,19 +7,13 @@ import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart';
import '../screenshot.dart';
import 'helper.dart';
import 'text_scuba.dart';
typedef PaintTest = void Function(RecordingCanvas recordingCanvas);
void main() {
internalBootstrapBrowserTest(() => testMain);
}
/// Whether we are running on iOS Safari.
// TODO(mdebbar): https://github.com/flutter/flutter/issues/66656
bool get isIosSafari => browserEngine == BrowserEngine.webkit &&
operatingSystem == OperatingSystem.iOs;
Future<void> testMain() async {
final EngineScubaTester scuba = await EngineScubaTester.initialize(
viewportSize: const Size(600, 600),
@@ -46,9 +40,7 @@ Future<void> testMain() async {
}
recordingCanvas.endRecording();
recordingCanvas.apply(canvas, screenRect);
if (!isIosSafari) {
return scuba.diffCanvasScreenshot(canvas, 'text_with_placeholders');
}
return scuba.diffCanvasScreenshot(canvas, 'text_with_placeholders');
});
testEachCanvas('text alignment and placeholders', (EngineCanvas canvas) {
@@ -85,10 +77,6 @@ Future<void> testMain() async {
});
}
const Color black = Color(0xFF000000);
const Color blue = Color(0xFF0000FF);
const Color red = Color(0xFFFF0000);
const Size placeholderSize = Size(80.0, 50.0);
void _paintTextWithPlaceholder(

View File

@@ -10,6 +10,8 @@ import 'package:ui/ui.dart' as ui;
import 'package:web_engine_tester/golden_tester.dart';
import 'helper.dart';
/// Class that controls some details of how screenshotting is made.
///
/// (For Googlers: Not really related with internal Scuba anymore)
@@ -85,8 +87,6 @@ class EngineScubaTester {
}
}
typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);
/// Runs the given test [body] with each type of canvas.
void testEachCanvas(String description, CanvasTest body) {
const ui.Rect bounds = ui.Rect.fromLTWH(0, 0, 600, 800);

View File

@@ -9,10 +9,6 @@ import 'package:ui/ui.dart';
import '../html/paragraph/helper.dart';
bool get isIosSafari =>
browserEngine == BrowserEngine.webkit &&
operatingSystem == OperatingSystem.iOs;
/// Some text measurements are sensitive to browser implementations. Position
/// info in the following tests only pass in Chrome, they are slightly different
/// on each browser. So we need to ignore position info on non-Chrome browsers
@@ -67,7 +63,7 @@ Future<void> testMain() async {
final CanvasParagraph paragraph = builder.build();
expect(paragraph.paragraphStyle, style);
expect(paragraph.toPlainText(), 'Hello');
expect(paragraph.plainText, 'Hello');
expect(paragraph.spans, hasLength(1));
paragraph.layout(const ParagraphConstraints(width: double.infinity));
@@ -97,10 +93,8 @@ Future<void> testMain() async {
);
final ParagraphSpan span = paragraph.spans.single;
expect(span, isA<FlatTextSpan>());
final FlatTextSpan textSpan = span as FlatTextSpan;
expect(textSpan.textOf(paragraph), 'Hello');
expect(textSpan.style, styleWithDefaults(fontSize: 13.0));
expect(getSpanText(paragraph, span), 'Hello');
expect(span.style, styleWithDefaults(fontSize: 13.0));
});
test('Correct defaults', () {
@@ -111,7 +105,7 @@ Future<void> testMain() async {
final CanvasParagraph paragraph = builder.build();
expect(paragraph.paragraphStyle, style);
expect(paragraph.toPlainText(), 'Hello');
expect(paragraph.plainText, 'Hello');
expect(paragraph.spans, hasLength(1));
paragraph.layout(const ParagraphConstraints(width: double.infinity));
@@ -125,8 +119,8 @@ Future<void> testMain() async {
ignorePositions: !isBlink,
);
final FlatTextSpan textSpan = paragraph.spans.single as FlatTextSpan;
expect(textSpan.style, styleWithDefaults());
final ParagraphSpan span = paragraph.spans.single;
expect(span.style, styleWithDefaults());
});
test('Sets correct styles for max-lines', () {
@@ -137,7 +131,7 @@ Future<void> testMain() async {
final CanvasParagraph paragraph = builder.build();
expect(paragraph.paragraphStyle, style);
expect(paragraph.toPlainText(), 'Hello');
expect(paragraph.plainText, 'Hello');
paragraph.layout(const ParagraphConstraints(width: double.infinity));
expectOuterHtml(
@@ -159,7 +153,7 @@ Future<void> testMain() async {
final CanvasParagraph paragraph = builder.build();
expect(paragraph.paragraphStyle, style);
expect(paragraph.toPlainText(), 'HelloWorld');
expect(paragraph.plainText, 'HelloWorld');
paragraph.layout(const ParagraphConstraints(width: 100.0));
expectOuterHtml(
@@ -190,7 +184,7 @@ Future<void> testMain() async {
builder.addText('Hello');
final CanvasParagraph paragraph = builder.build();
expect(paragraph.toPlainText(), 'Hello');
expect(paragraph.plainText, 'Hello');
expect(paragraph.spans, hasLength(1));
paragraph.layout(const ParagraphConstraints(width: double.infinity));
@@ -204,8 +198,8 @@ Future<void> testMain() async {
ignorePositions: !isBlink,
);
final FlatTextSpan span = paragraph.spans.single as FlatTextSpan;
expect(span.textOf(paragraph), 'Hello');
final ParagraphSpan span = paragraph.spans.single;
expect(getSpanText(paragraph, span), 'Hello');
expect(
span.style,
styleWithDefaults(
@@ -229,7 +223,7 @@ Future<void> testMain() async {
builder.addText(' world');
final CanvasParagraph paragraph = builder.build();
expect(paragraph.toPlainText(), 'Hello world');
expect(paragraph.plainText, 'Hello world');
expect(paragraph.spans, hasLength(2));
paragraph.layout(const ParagraphConstraints(width: double.infinity));
@@ -267,8 +261,8 @@ Future<void> testMain() async {
ignorePositions: !isBlink,
);
final FlatTextSpan hello = paragraph.spans.first as FlatTextSpan;
expect(hello.textOf(paragraph), 'Hello');
final ParagraphSpan hello = paragraph.spans.first;
expect(getSpanText(paragraph, hello), 'Hello');
expect(
hello.style,
styleWithDefaults(
@@ -277,8 +271,8 @@ Future<void> testMain() async {
),
);
final FlatTextSpan world = paragraph.spans.last as FlatTextSpan;
expect(world.textOf(paragraph), ' world');
final ParagraphSpan world = paragraph.spans.last;
expect(getSpanText(paragraph, world), ' world');
expect(
world.style,
styleWithDefaults(
@@ -302,7 +296,7 @@ Future<void> testMain() async {
builder.addText('!');
final CanvasParagraph paragraph = builder.build();
expect(paragraph.toPlainText(), 'Hello world!');
expect(paragraph.plainText, 'Hello world!');
expect(paragraph.spans, hasLength(3));
paragraph.layout(const ParagraphConstraints(width: double.infinity));
@@ -325,8 +319,8 @@ Future<void> testMain() async {
ignorePositions: !isBlink,
);
final FlatTextSpan hello = paragraph.spans[0] as FlatTextSpan;
expect(hello.textOf(paragraph), 'Hello');
final ParagraphSpan hello = paragraph.spans[0];
expect(getSpanText(paragraph, hello), 'Hello');
expect(
hello.style,
styleWithDefaults(
@@ -336,8 +330,8 @@ Future<void> testMain() async {
),
);
final FlatTextSpan world = paragraph.spans[1] as FlatTextSpan;
expect(world.textOf(paragraph), ' world');
final ParagraphSpan world = paragraph.spans[1];
expect(getSpanText(paragraph, world), ' world');
expect(
world.style,
styleWithDefaults(
@@ -347,8 +341,8 @@ Future<void> testMain() async {
),
);
final FlatTextSpan bang = paragraph.spans[2] as FlatTextSpan;
expect(bang.textOf(paragraph), '!');
final ParagraphSpan bang = paragraph.spans[2];
expect(getSpanText(paragraph, bang), '!');
expect(
bang.style,
styleWithDefaults(
@@ -368,7 +362,7 @@ Future<void> testMain() async {
builder.addText('ThirdLongLine');
final CanvasParagraph paragraph = builder.build();
expect(paragraph.toPlainText(), 'First\nSecond ThirdLongLine');
expect(paragraph.plainText, 'First\nSecond ThirdLongLine');
expect(paragraph.spans, hasLength(2));
// There's a new line between "First" and "Second", but "Second" and
@@ -430,7 +424,7 @@ Future<void> testMain() async {
builder.addText('Third');
final CanvasParagraph paragraph = builder.build();
expect(paragraph.toPlainText(), 'First Second Third');
expect(paragraph.plainText, 'First Second Third');
expect(paragraph.spans, hasLength(3));
// The paragraph should take the font size and family from the span with the

View File

@@ -9,21 +9,6 @@ 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);
}

View File

@@ -207,21 +207,19 @@ Future<void> testMain() async {
},
);
final String placeholderChar = String.fromCharCode(0xFFFC);
expect(split(paragraph), <_Fragment>[
_Fragment(placeholderChar, opportunity, ltr, ffLtr, null),
_Fragment(placeholderChar, opportunity, ltr, ffLtr, style1),
_Fragment('Lorem', opportunity, ltr, ffLtr, style1),
_Fragment(placeholderChar, opportunity, ltr, ffLtr, null),
_Fragment(placeholderChar, opportunity, ltr, ffLtr, style1),
_Fragment('ipsum', prohibited, ltr, ffLtr, style1),
_Fragment('\n', mandatory, null, ffSandwich, style1, nl: 1, sp: 1),
_Fragment(placeholderChar, opportunity, ltr, ffLtr, null),
_Fragment(placeholderChar, opportunity, ltr, ffLtr, style1),
_Fragment(rtlWord1, prohibited, rtl, ffRtl, style2),
_Fragment(' ', opportunity, null, ffSandwich, style2, sp: 1),
_Fragment(placeholderChar, prohibited, ltr, ffLtr, null),
_Fragment(placeholderChar, prohibited, ltr, ffLtr, style2),
_Fragment('\n', mandatory, null, ffSandwich, style2, nl: 1, sp: 1),
_Fragment('sit', opportunity, ltr, ffLtr, style2),
_Fragment(placeholderChar, endOfText, ltr, ffLtr, null),
_Fragment(placeholderChar, endOfText, ltr, ffLtr, defaultStyle),
]);
});
});
@@ -235,13 +233,12 @@ class _Fragment {
});
factory _Fragment._fromLayoutFragment(String text, LayoutFragment layoutFragment) {
final ParagraphSpan span = layoutFragment.span;
return _Fragment(
text.substring(layoutFragment.start, layoutFragment.end),
layoutFragment.type,
layoutFragment.textDirection,
layoutFragment.fragmentFlow,
span is FlatTextSpan ? span.style : null,
layoutFragment.style,
nl: layoutFragment.trailingNewlines,
sp: layoutFragment.trailingSpaces,
);
@@ -251,7 +248,7 @@ class _Fragment {
final LineBreakType type;
final TextDirection? textDirection;
final FragmentFlow fragmentFlow;
final EngineTextStyle? style;
final EngineTextStyle style;
/// The number of trailing new line characters.
final int nl;

View File

@@ -7,32 +7,11 @@ import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import '../html/paragraph/helper.dart';
import 'layout_service_helper.dart';
const bool skipWordSpacing = true;
final EngineParagraphStyle ahemStyle = EngineParagraphStyle(
fontFamily: 'ahem',
fontSize: 10,
);
ui.ParagraphConstraints constrain(double width) {
return ui.ParagraphConstraints(width: width);
}
CanvasParagraph plain(
EngineParagraphStyle style,
String text, {
EngineTextStyle? textStyle,
}) {
final CanvasParagraphBuilder builder = CanvasParagraphBuilder(style);
if (textStyle != null) {
builder.pushStyle(textStyle);
}
builder.addText(text);
return builder.build();
}
void main() {
internalBootstrapBrowserTest(() => testMain);
}

View File

@@ -11,19 +11,6 @@ import 'package:ui/ui.dart' as ui;
import '../html/paragraph/helper.dart';
import 'layout_service_helper.dart';
final String placeholderChar = String.fromCharCode(0xFFFC);
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,
);
void main() {
internalBootstrapBrowserTest(() => testMain);
}

View File

@@ -12,8 +12,6 @@ import '../html/paragraph/helper.dart';
import 'line_breaker_test_helper.dart';
import 'line_breaker_test_raw_data.dart';
final String placeholderChar = String.fromCharCode(0xFFFC);
void main() {
internalBootstrapBrowserTest(() => testMain);
}
@@ -237,7 +235,7 @@ void testMain() {
final String placeholderChar = String.fromCharCode(0xFFFC);
expect(splitParagraph(paragraph), <Line>[
expect(split(paragraph.plainText), <Line>[
Line(placeholderChar, opportunity),
Line('Lorem', opportunity),
Line(placeholderChar, opportunity),
@@ -260,7 +258,7 @@ void testMain() {
final String placeholderChar = String.fromCharCode(0xFFFC);
expect(splitParagraph(paragraph), <Line>[
expect(split(paragraph.plainText), <Line>[
Line(placeholderChar, endOfText),
]);
});
@@ -279,7 +277,7 @@ void testMain() {
},
);
expect(splitParagraph(paragraph), <Line>[
expect(split(paragraph.plainText), <Line>[
Line('$placeholderChar ', opportunity, sp: 2),
Line('Lorem ', opportunity, sp: 2),
Line('$placeholderChar \n', mandatory, nl: 1, sp: 3),
@@ -456,10 +454,3 @@ List<Line> split(String text) {
Line.fromLineBreakFragment(text, fragment)
];
}
List<Line> splitParagraph(CanvasParagraph paragraph) {
return <Line>[
for (final LineBreakFragment fragment in LineBreakFragmenter(paragraph.plainText).fragment())
Line.fromLineBreakFragment(paragraph.toPlainText(), fragment)
];
}