Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 33b31a4

Browse files
committed
[web] Some cleanup for text tests
1 parent d5f36ae commit 33b31a4

20 files changed

+97
-224
lines changed

lib/web_ui/lib/src/engine/engine_canvas.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ DomElement drawParagraphElement(
264264
}) {
265265
assert(paragraph.isLaidOut);
266266

267-
final DomHTMLElement paragraphElement = paragraph.toDomElement();
267+
final DomElement paragraphElement = paragraph.toDomElement();
268268

269269
if (transform != null) {
270270
setElementTransform(

lib/web_ui/lib/src/engine/html/recording_canvas.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1246,7 +1246,7 @@ class PaintDrawParagraph extends DrawCommand {
12461246
@override
12471247
String toString() {
12481248
if (assertionsEnabled) {
1249-
return 'DrawParagraph(${paragraph.toPlainText()}, $offset)';
1249+
return 'DrawParagraph(${paragraph.plainText}, $offset)';
12501250
} else {
12511251
return super.toString();
12521252
}

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

Lines changed: 25 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import 'word_breaker.dart';
1717

1818
const ui.Color _defaultTextColor = ui.Color(0xFFFF0000);
1919

20-
final String _placeholderChar = String.fromCharCode(0xFFFC);
20+
final String placeholderChar = String.fromCharCode(0xFFFC);
2121

2222
/// A paragraph made up of a flat list of text spans and placeholders.
2323
///
@@ -33,7 +33,6 @@ class CanvasParagraph implements ui.Paragraph {
3333
this.spans, {
3434
required this.paragraphStyle,
3535
required this.plainText,
36-
required this.placeholderCount,
3736
required this.canDrawOnCanvas,
3837
}) : assert(spans.isNotEmpty);
3938

@@ -46,9 +45,6 @@ class CanvasParagraph implements ui.Paragraph {
4645
/// The full textual content of the paragraph.
4746
late String plainText;
4847

49-
/// The number of placeholders in this paragraph.
50-
final int placeholderCount;
51-
5248
/// Whether this paragraph can be drawn on a bitmap canvas.
5349
///
5450
/// Some text features cannot be rendered into a 2D canvas and must use HTML,
@@ -87,8 +83,6 @@ class CanvasParagraph implements ui.Paragraph {
8783
/// Whether this paragraph has been laid out or not.
8884
bool isLaidOut = false;
8985

90-
bool get isRtl => paragraphStyle.effectiveTextDirection == ui.TextDirection.rtl;
91-
9286
ui.ParagraphConstraints? _lastUsedConstraints;
9387

9488
late final TextLayoutService _layoutService = TextLayoutService(this);
@@ -138,27 +132,23 @@ class CanvasParagraph implements ui.Paragraph {
138132
_paintService.paint(canvas, offset);
139133
}
140134

141-
/// Generates a flat string computed from all the spans of the paragraph.
142-
String toPlainText() => plainText;
143-
144-
DomHTMLElement? _cachedDomElement;
135+
DomElement? _cachedDomElement;
145136

146137
/// Returns a DOM element that represents the entire paragraph and its
147138
/// children.
148139
///
149140
/// Generates a new DOM element on every invocation.
150-
DomHTMLElement toDomElement() {
141+
DomElement toDomElement() {
151142
assert(isLaidOut);
152-
final DomHTMLElement? domElement = _cachedDomElement;
143+
final DomElement? domElement = _cachedDomElement;
153144
if (domElement == null) {
154145
return _cachedDomElement ??= _createDomElement();
155146
}
156-
return domElement.cloneNode(true) as DomHTMLElement;
147+
return domElement.cloneNode(true) as DomElement;
157148
}
158149

159-
DomHTMLElement _createDomElement() {
160-
final DomHTMLElement rootElement =
161-
domDocument.createElement('flt-paragraph') as DomHTMLElement;
150+
DomElement _createDomElement() {
151+
final DomElement rootElement = domDocument.createElement('flt-paragraph');
162152

163153
// 1. Set paragraph-level styles.
164154

@@ -183,12 +173,8 @@ class CanvasParagraph implements ui.Paragraph {
183173
continue;
184174
}
185175

186-
final DomHTMLElement spanElement = domDocument.createElement('flt-span') as DomHTMLElement;
187-
applyTextStyleToElement(
188-
element: spanElement,
189-
style: fragment.style,
190-
isSpan: true,
191-
);
176+
final DomElement spanElement = domDocument.createElement('flt-span');
177+
applyTextStyleToElement(element: spanElement, style: fragment.style);
192178
_positionSpanElement(spanElement, line, fragment);
193179

194180
spanElement.appendText(text);
@@ -221,7 +207,6 @@ class CanvasParagraph implements ui.Paragraph {
221207

222208
@override
223209
ui.TextRange getWordBoundary(ui.TextPosition position) {
224-
final String text = toPlainText();
225210
final int characterPosition;
226211
switch (position.affinity) {
227212
case ui.TextAffinity.upstream:
@@ -231,8 +216,8 @@ class CanvasParagraph implements ui.Paragraph {
231216
characterPosition = position.offset;
232217
break;
233218
}
234-
final int start = WordBreaker.prevBreakIndex(text, characterPosition + 1);
235-
final int end = WordBreaker.nextBreakIndex(text, characterPosition);
219+
final int start = WordBreaker.prevBreakIndex(plainText, characterPosition + 1);
220+
final int end = WordBreaker.nextBreakIndex(plainText, characterPosition);
236221
return ui.TextRange(start: start, end: end);
237222
}
238223

@@ -288,51 +273,30 @@ void _positionSpanElement(DomElement element, ParagraphLine line, LayoutFragment
288273
..lineHeight = '${boxRect.height}px';
289274
}
290275

291-
/// A common interface for all types of spans that make up a paragraph.
292-
///
293-
/// These spans are stored as a flat list in the paragraph object.
294-
abstract class ParagraphSpan {
295-
/// The index of the beginning of the range of text represented by this span.
296-
int get start;
297-
298-
/// The index of the end of the range of text represented by this span.
299-
int get end;
300-
301-
/// The resolved style of the span.
302-
EngineTextStyle get style;
303-
}
304-
305-
/// Represent a span of text in the paragraph.
306-
///
307-
/// It's a "flat" text span as opposed to the framework text spans that are
308-
/// hierarchical.
276+
/// Represents a span in the paragraph.
309277
///
310278
/// Instead of keeping spans and styles in a tree hierarchy like the framework
311279
/// does, we flatten the structure and resolve/merge all the styles from parent
312280
/// nodes.
313-
class FlatTextSpan implements ParagraphSpan {
314-
/// Creates a [FlatTextSpan] with the given [style], representing the span of
281+
///
282+
/// These spans are stored as a flat list in the paragraph object.
283+
class ParagraphSpan {
284+
/// Creates a [ParagraphSpan] with the given [style], representing the span of
315285
/// text in the range between [start] and [end].
316-
FlatTextSpan({
286+
ParagraphSpan({
317287
required this.style,
318288
required this.start,
319289
required this.end,
320290
});
321291

322-
@override
292+
/// The resolved style of the span.
323293
final EngineTextStyle style;
324294

325-
@override
295+
/// The index of the beginning of the range of text represented by this span.
326296
final int start;
327297

328-
@override
298+
/// The index of the end of the range of text represented by this span.
329299
final int end;
330-
331-
String textOf(CanvasParagraph paragraph) {
332-
final String text = paragraph.toPlainText();
333-
assert(end <= text.length);
334-
return text.substring(start, end);
335-
}
336300
}
337301

338302
class PlaceholderSpan extends ParagraphPlaceholder implements ParagraphSpan {
@@ -622,16 +586,13 @@ class CanvasParagraphBuilder implements ui.ParagraphBuilder {
622586
double? baselineOffset,
623587
ui.TextBaseline? baseline,
624588
}) {
625-
// TODO(mdebbar): for measurement of placeholders, look at:
626-
// - https://github.com/flutter/engine/blob/c0f7e8acf9318d264ad6a235facd097de597ffcc/third_party/txt/src/txt/paragraph_txt.cc#L325-L350
627-
628589
// Require a baseline to be specified if using a baseline-based alignment.
629590
assert(!(alignment == ui.PlaceholderAlignment.aboveBaseline ||
630591
alignment == ui.PlaceholderAlignment.belowBaseline ||
631592
alignment == ui.PlaceholderAlignment.baseline) || baseline != null);
632593

633594
final int start = _plainTextBuffer.length;
634-
_plainTextBuffer.write(_placeholderChar);
595+
_plainTextBuffer.write(placeholderChar);
635596
final int end = _plainTextBuffer.length;
636597

637598
final EngineTextStyle style = _currentStyleNode.resolveStyle();
@@ -674,7 +635,7 @@ class CanvasParagraphBuilder implements ui.ParagraphBuilder {
674635
final EngineTextStyle style = _currentStyleNode.resolveStyle();
675636
_updateCanDrawOnCanvas(style);
676637

677-
_spans.add(FlatTextSpan(style: style, start: start, end: end));
638+
_spans.add(ParagraphSpan(style: style, start: start, end: end));
678639
}
679640

680641
void _updateCanDrawOnCanvas(EngineTextStyle style) {
@@ -708,18 +669,15 @@ class CanvasParagraphBuilder implements ui.ParagraphBuilder {
708669
//
709670
// We want the paragraph to always have a non-empty list of spans to match
710671
// the expectations of the [LayoutFragmenter].
711-
_spans.add(FlatTextSpan(
712-
style: _rootStyleNode.resolveStyle(),
713-
start: 0,
714-
end: 0,
715-
));
672+
_spans.add(
673+
ParagraphSpan(style: _rootStyleNode.resolveStyle(), start: 0, end: 0),
674+
);
716675
}
717676

718677
return CanvasParagraph(
719678
_spans,
720679
paragraphStyle: _paragraphStyle,
721680
plainText: _plainTextBuffer.toString(),
722-
placeholderCount: _placeholderCount,
723681
canDrawOnCanvas: _canDrawOnCanvas,
724682
);
725683
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ class TextLayoutService {
360360
return <ui.TextBox>[];
361361
}
362362

363-
final int length = paragraph.toPlainText().length;
363+
final int length = paragraph.plainText.length;
364364
// Ranges that are out of bounds should return an empty list.
365365
if (start > length || end > length) {
366366
return <ui.TextBox>[];
@@ -1046,10 +1046,9 @@ class Spanometer {
10461046
assert(start >= currentSpan.start && start <= currentSpan.end);
10471047
assert(end >= currentSpan.start && end <= currentSpan.end);
10481048

1049-
final String text = paragraph.toPlainText();
10501049
return measureSubstring(
10511050
context,
1052-
text,
1051+
paragraph.plainText,
10531052
start,
10541053
end,
10551054
letterSpacing: letterSpacing,

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

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,16 @@ class TextPaintService {
3636
ui.Offset offset,
3737
LayoutFragment fragment,
3838
) {
39-
final ParagraphSpan span = fragment.span;
40-
if (span is FlatTextSpan) {
41-
// Paint the background of the box, if the span has a background.
42-
final SurfacePaint? background = span.style.background as SurfacePaint?;
43-
if (background != null) {
44-
final ui.Rect rect = fragment.toPaintingTextBox().toRect();
45-
if (!rect.isEmpty) {
46-
canvas.drawRect(rect.shift(offset), background.paintData);
47-
}
39+
if (fragment.isPlaceholder) {
40+
return;
41+
}
42+
43+
// Paint the background of the box, if the span has a background.
44+
final SurfacePaint? background = fragment.style.background as SurfacePaint?;
45+
if (background != null) {
46+
final ui.Rect rect = fragment.toPaintingTextBox().toRect();
47+
if (!rect.isEmpty) {
48+
canvas.drawRect(rect.shift(offset), background.paintData);
4849
}
4950
}
5051
}

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -774,13 +774,9 @@ String fontWeightIndexToCss({int fontWeightIndex = 3}) {
774774

775775
/// Applies a text [style] to an [element], translating the properties to their
776776
/// corresponding CSS equivalents.
777-
///
778-
/// If [isSpan] is true, the text element is a span within richtext and
779-
/// should not assign effectiveFontFamily if fontFamily was not specified.
780777
void applyTextStyleToElement({
781-
required DomHTMLElement element,
778+
required DomElement element,
782779
required EngineTextStyle style,
783-
bool isSpan = false,
784780
}) {
785781
assert(element != null);
786782
assert(style != null);
@@ -822,10 +818,10 @@ void applyTextStyleToElement({
822818
}
823819
// For test environment use effectiveFontFamily since we need to
824820
// consistently use Ahem font.
825-
if (isSpan && !ui.debugEmulateFlutterTesterEnvironment) {
826-
cssStyle.fontFamily = canonicalizeFontFamily(style.fontFamily)!;
827-
} else {
821+
if (ui.debugEmulateFlutterTesterEnvironment) {
828822
cssStyle.fontFamily = canonicalizeFontFamily(style.effectiveFontFamily)!;
823+
} else {
824+
cssStyle.fontFamily = canonicalizeFontFamily(style.fontFamily)!;
829825
}
830826
if (style.letterSpacing != null) {
831827
cssStyle.letterSpacing = '${style.letterSpacing}px';

lib/web_ui/test/html/paragraph/bidi_golden_test.dart

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
import 'dart:async';
6-
75
import 'package:test/bootstrap/browser.dart';
86
import 'package:test/test.dart';
97
import 'package:ui/src/engine.dart';
@@ -12,8 +10,6 @@ import 'package:ui/ui.dart' hide window;
1210
import '../screenshot.dart';
1311
import 'helper.dart';
1412

15-
typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);
16-
1713
const String _rtlWord1 = 'واحد';
1814
const String _rtlWord2 = 'اثنان';
1915

lib/web_ui/test/html/paragraph/general_golden_test.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ import 'package:ui/ui.dart' hide window;
1313
import '../screenshot.dart';
1414
import 'helper.dart';
1515

16-
typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);
17-
1816
const Rect bounds = Rect.fromLTWH(0, 0, 800, 600);
1917

2018
void main() {

lib/web_ui/test/html/paragraph/helper.dart

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'dart:async';
6+
57
import 'package:ui/src/engine.dart';
68
import 'package:ui/ui.dart';
79
import 'package:web_engine_tester/golden_tester.dart';
810

11+
typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);
12+
913
const LineBreakType prohibited = LineBreakType.prohibited;
1014
const LineBreakType opportunity = LineBreakType.opportunity;
1115
const LineBreakType mandatory = LineBreakType.mandatory;
@@ -32,6 +36,11 @@ const Color blue = Color(0xFF0000FF);
3236
const Color yellow = Color(0xFFFFEB3B);
3337
const Color lightPurple = Color(0xFFE1BEE7);
3438

39+
final EngineParagraphStyle ahemStyle = EngineParagraphStyle(
40+
fontFamily: 'ahem',
41+
fontSize: 10,
42+
);
43+
3544
ParagraphConstraints constrain(double width) {
3645
return ParagraphConstraints(width: width);
3746
}
@@ -73,10 +82,7 @@ Future<void> takeScreenshot(
7382
try {
7483
sceneElement.append(canvas.rootElement);
7584
domDocument.body!.append(sceneElement);
76-
await matchGoldenFile(
77-
'$fileName.png',
78-
region: region,
79-
);
85+
await matchGoldenFile('$fileName.png', region: region);
8086
} finally {
8187
// The page is reused across tests, so remove the element after taking the
8288
// Scuba screenshot.
@@ -109,3 +115,7 @@ void fillBoxes(EngineCanvas canvas, Offset offset, List<TextBox> boxes, Color co
109115
canvas.drawRect(rect, SurfacePaintData()..color = color);
110116
}
111117
}
118+
119+
String getSpanText(CanvasParagraph paragraph, ParagraphSpan span) {
120+
return paragraph.plainText.substring(span.start, span.end);
121+
}

lib/web_ui/test/html/paragraph/overflow_golden_test.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ import 'package:ui/ui.dart' hide window;
1212
import '../screenshot.dart';
1313
import 'helper.dart';
1414

15-
typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);
16-
1715
void main() {
1816
internalBootstrapBrowserTest(() => testMain);
1917
}

lib/web_ui/test/html/paragraph/placeholders_golden_test.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ import 'package:ui/ui.dart' hide window;
1212
import '../screenshot.dart';
1313
import 'helper.dart';
1414

15-
typedef CanvasTest = FutureOr<void> Function(EngineCanvas canvas);
16-
1715
const Rect bounds = Rect.fromLTWH(0, 0, 800, 600);
1816

1917
void main() {

0 commit comments

Comments
 (0)