Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/web_ui/dev/goldens_lock.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
repository: https://github.com/flutter/goldens.git
revision: 6839c709f859a1abe50e6322dfee17a3a3817c5c
revision: 92381b8ca48729e9b21c6b19dd39ed605a98d4ee
27 changes: 26 additions & 1 deletion lib/web_ui/lib/src/engine/text/canvas_paragraph.dart
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class CanvasParagraph implements EngineParagraph {
domRenderer.createElement('p') as html.HtmlElement;

// 1. Set paragraph-level styles.
_applyParagraphStyleToElement(element: rootElement, style: paragraphStyle);
_applyNecessaryParagraphStyles(element: rootElement, style: paragraphStyle);
final html.CssStyleDeclaration cssStyle = rootElement.style;
cssStyle
..position = 'absolute'
Expand Down Expand Up @@ -259,6 +259,31 @@ class CanvasParagraph implements EngineParagraph {
}
}

/// Applies a paragraph [style] to an [element], translating the properties to
/// their corresponding CSS equivalents.
///
/// As opposed to [_applyParagraphStyleToElement], this method only applies
/// styles that are necessary at the paragraph level. Other styles (e.g. font
/// size) are always applied at the span level so they aren't needed at the
/// paragraph level.
void _applyNecessaryParagraphStyles({
required html.HtmlElement element,
required EngineParagraphStyle style,
}) {
final html.CssStyleDeclaration cssStyle = element.style;

if (style._textAlign != null) {
cssStyle.textAlign = textAlignToCssValue(
style._textAlign, style._textDirection ?? ui.TextDirection.ltr);
}
if (style._lineHeight != null) {
cssStyle.lineHeight = '${style._lineHeight}';
}
if (style._textDirection != null) {
cssStyle.direction = _textDirectionToCss(style._textDirection);
}
}

/// 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,15 +334,18 @@ void testMain() async {
// Yellow text should be behind image and rectangle.
// Cyan text should be above everything.
test('Paints text above and below image', () async {
// Use a non-Ahem font so that text is visible.
debugEmulateFlutterTesterEnvironment = false;
final RecordingCanvas rc =
RecordingCanvas(const Rect.fromLTRB(0, 0, 400, 300));
rc.save();
Image testImage = createTestImage();
double testWidth = testImage.width.toDouble();
double testHeight = testImage.height.toDouble();
final Color orange = Color(0xFFFF9800);
final Paragraph paragraph1 = createTestParagraph(
'should be below...............',
color: Color(0xFFFFFF40));
'Should be below below below below below',
color: orange);
paragraph1.layout(const ParagraphConstraints(width: 400.0));
rc.drawParagraph(paragraph1, const Offset(20, 100));
rc.drawImageRect(testImage, Rect.fromLTRB(0, 0, testWidth, testHeight),
Expand All @@ -352,14 +355,19 @@ void testMain() async {
Paint()
..strokeWidth = 3
..color = Color(0xA0000000));
final Color cyan = Color(0xFF0097A7);
final Paragraph paragraph2 = createTestParagraph(
'Should be above...............',
color: Color(0xFF00FFFF));
'Should be above above above above above',
color: cyan);
paragraph2.layout(const ParagraphConstraints(width: 400.0));
rc.drawParagraph(paragraph2, const Offset(20, 150));
rc.restore();
await _checkScreenshot(rc, 'draw_text_composite_order_below',
maxDiffRatePercent: 1.0);
await _checkScreenshot(
rc,
'draw_text_composite_order_below',
maxDiffRatePercent: 1.0,
region: Rect.fromLTWH(0, 0, 350, 300),
);
});

// Creates a picture
Expand Down Expand Up @@ -723,7 +731,7 @@ HtmlImage createTestImage({int width = 100, int height = 50}) {
Paragraph createTestParagraph(String text,
{Color color = const Color(0xFF000000)}) {
final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle(
fontFamily: 'Ahem',
fontFamily: 'Roboto',
fontStyle: FontStyle.normal,
fontWeight: FontWeight.normal,
fontSize: 14.0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ void testMain() async {
canvas.drawParagraph(paragraph, offset);
offset = offset.translate(0, paragraph.height + 10);

return takeScreenshot(canvas, bounds, 'canvas_paragraph_align_dom');
return takeScreenshot(canvas, bounds, 'canvas_paragraph_align_dom', maxDiffRatePercent: 0.3);
});

void testAlignAndTransform(EngineCanvas canvas) {
Expand All @@ -174,8 +174,7 @@ void testMain() async {
canvas.save();
canvas.translate(offset.dx, offset.dy);
canvas.rotate(math.pi / 4);
final Rect rect =
Rect.fromLTRB(0.0, 0.0, 150.0, paragraph.height);
final Rect rect = Rect.fromLTRB(0.0, 0.0, 150.0, paragraph.height);
canvas.drawRect(rect, SurfacePaintData()..color = black);
canvas.drawParagraph(paragraph, Offset.zero);
canvas.restore();
Expand All @@ -198,6 +197,35 @@ void testMain() async {
return takeScreenshot(canvas, bounds, 'canvas_paragraph_align_transform_dom');
});

void testGiantParagraphStyles(EngineCanvas canvas) {
final CanvasParagraph paragraph = rich(
ParagraphStyle(fontFamily: 'Roboto', fontSize: 80.0),
(CanvasParagraphBuilder builder) {
builder.pushStyle(EngineTextStyle.only(color: yellow, fontSize: 24.0));
builder.addText('Lorem ');
builder.pushStyle(EngineTextStyle.only(color: red, fontSize: 32.0));
builder.addText('ipsum');
},
)..layout(constrain(double.infinity));
final Rect rect = Rect.fromLTRB(0.0, 0.0, paragraph.maxIntrinsicWidth, paragraph.height);
canvas.drawRect(rect, SurfacePaintData()..color = black);
canvas.drawParagraph(paragraph, Offset.zero);
}

test('giant paragraph style', () {
const Rect bounds = Rect.fromLTWH(0, 0, 300, 200);
final canvas = BitmapCanvas(bounds, RenderStrategy());
testGiantParagraphStyles(canvas);
return takeScreenshot(canvas, bounds, 'canvas_paragraph_giant_paragraph_style');
});

test('giant paragraph style (DOM)', () {
const Rect bounds = Rect.fromLTWH(0, 0, 300, 200);
final canvas = DomCanvas(domRenderer.createElement('flt-picture'));
testGiantParagraphStyles(canvas);
return takeScreenshot(canvas, bounds, 'canvas_paragraph_giant_paragraph_style_dom');
});

test('paints spans with varying heights/baselines', () {
final canvas = BitmapCanvas(bounds, RenderStrategy());

Expand Down
18 changes: 9 additions & 9 deletions lib/web_ui/test/text/canvas_paragraph_builder_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ String get defaultFontFamily {
const String defaultColor = 'color: rgb(255, 0, 0);';
const String defaultFontSize = 'font-size: 14px;';
final String paragraphStyle =
'$defaultFontFamily position: absolute; white-space: pre;';
'position: absolute; white-space: pre;';

void main() {
internalBootstrapBrowserTest(() => testMain);
Expand All @@ -50,7 +50,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="font-size: 13px; $paragraphStyle">'
'<p style="$paragraphStyle">'
'<span style="$defaultColor font-size: 13px; $defaultFontFamily">'
'Hello'
'</span>'
Expand All @@ -61,7 +61,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: 39.0));
expect(
paragraph.toDomElement().outerHtml,
'<p style="font-size: 13px; $paragraphStyle">'
'<p style="$paragraphStyle">'
'<span style="$defaultColor font-size: 13px; $defaultFontFamily">'
'Hel<br>lo'
'</span>'
Expand Down Expand Up @@ -168,7 +168,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="line-height: 1.5; font-size: 13px; $paragraphStyle">'
'<p style="line-height: 1.5; $paragraphStyle">'
'<span style="$defaultColor line-height: 1.5; font-size: 9px; font-weight: bold; font-style: italic; $defaultFontFamily letter-spacing: 2px;">'
'Hello'
'</span>'
Expand Down Expand Up @@ -206,7 +206,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="font-size: 13px; $paragraphStyle">'
'<p style="$paragraphStyle">'
'<span style="$defaultColor font-size: 13px; font-weight: bold; $defaultFontFamily">'
'Hello'
'</span>'
Expand All @@ -220,7 +220,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: 75.0));
expect(
paragraph.toDomElement().outerHtml,
'<p style="font-size: 13px; $paragraphStyle width: 75px;">'
'<p style="$paragraphStyle width: 75px;">'
'<span style="$defaultColor font-size: 13px; font-weight: bold; $defaultFontFamily">'
'Hello'
'</span>'
Expand Down Expand Up @@ -271,7 +271,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="font-size: 13px; $paragraphStyle">'
'<p style="$paragraphStyle">'
'<span style="$defaultColor line-height: 2; font-size: 13px; font-weight: bold; $defaultFontFamily">'
'Hello'
'</span>'
Expand Down Expand Up @@ -335,7 +335,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="font-size: 13px; $paragraphStyle">'
'<p style="$paragraphStyle">'
'<span style="$defaultColor font-size: 13px; $defaultFontFamily">'
'First<br>Second '
'</span>'
Expand All @@ -349,7 +349,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: 180.0));
expect(
paragraph.toDomElement().outerHtml,
'<p style="font-size: 13px; $paragraphStyle width: 180px;">'
'<p style="$paragraphStyle width: 180px;">'
'<span style="$defaultColor font-size: 13px; $defaultFontFamily">'
'First<br>Second <br>'
'</span>'
Expand Down