未验证 提交 8863afff 编写于 作者: M Mouad Debbar 提交者: GitHub

[web] Use greatest span font size on the parent paragraph (#25513)

上级 398bede5
repository: https://github.com/flutter/goldens.git
revision: 82c1ccb1247f279cfd9f23a3929d13e2f32771ad
revision: f868ee6b6faef13469498e9b160b45fed9fdc567
......@@ -134,6 +134,7 @@ class CanvasParagraph implements EngineParagraph {
// 1. Set paragraph-level styles.
_applyNecessaryParagraphStyles(element: rootElement, style: paragraphStyle);
_applySpanStylesToParagraph(element: rootElement, spans: spans);
final html.CssStyleDeclaration cssStyle = rootElement.style;
cssStyle
..position = 'absolute'
......@@ -284,6 +285,39 @@ void _applyNecessaryParagraphStyles({
}
}
/// Applies some span-level style to a paragraph [element].
///
/// For example, it looks for the greatest font size among spans, and applies it
/// to the paragraph. While this seems to have no effect, it prevents the
/// paragraph from inheriting its font size from the body tag, which leads to
/// incorrect vertical alignment of spans.
void _applySpanStylesToParagraph({
required html.HtmlElement element,
required List<ParagraphSpan> spans,
}) {
double fontSize = 0.0;
String? fontFamily;
for (final ParagraphSpan span in spans) {
if (span is FlatTextSpan) {
final double? spanFontSize = span.style._fontSize;
if (spanFontSize != null && spanFontSize > fontSize) {
fontSize = spanFontSize;
if (span.style._isFontFamilyProvided) {
fontFamily = span.style._effectiveFontFamily;
}
}
}
}
final html.CssStyleDeclaration cssStyle = element.style;
if (fontSize != 0.0) {
cssStyle.fontSize = '${fontSize}px';
}
if (fontFamily != null) {
cssStyle.fontFamily = canonicalizeFontFamily(fontFamily);
}
}
/// 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.
......
......@@ -4,6 +4,7 @@
// @dart = 2.6
import 'dart:async';
import 'dart:html' as html;
import 'dart:math' as math;
import 'package:test/bootstrap/browser.dart';
......@@ -226,6 +227,63 @@ void testMain() async {
return takeScreenshot(canvas, bounds, 'canvas_paragraph_giant_paragraph_style_dom');
});
test('giant font size on the body tag (DOM)', () async {
const Rect bounds = Rect.fromLTWH(0, 0, 600, 200);
// Store the old font size value on the body, and set a gaint font size.
final String oldBodyFontSize = html.document.body.style.fontSize;
html.document.body.style.fontSize = '100px';
final canvas = DomCanvas(domRenderer.createElement('flt-picture'));
Offset offset = Offset(10.0, 10.0);
final CanvasParagraph paragraph = rich(
ParagraphStyle(fontFamily: 'Roboto'),
(CanvasParagraphBuilder builder) {
builder.pushStyle(EngineTextStyle.only(color: yellow, fontSize: 24.0));
builder.addText('Lorem ');
builder.pushStyle(EngineTextStyle.only(color: red, fontSize: 48.0));
builder.addText('ipsum');
},
)..layout(constrain(double.infinity));
final Rect rect = Rect.fromLTWH(offset.dx, offset.dy, paragraph.maxIntrinsicWidth, paragraph.height);
canvas.drawRect(rect, SurfacePaintData()..color = black);
canvas.drawParagraph(paragraph, offset);
offset = offset.translate(paragraph.maxIntrinsicWidth, 0.0);
// Add some extra padding between the two paragraphs.
offset = offset.translate(20.0, 0.0);
// Use the same height as the previous paragraph so that the 2 paragraphs
// look nice in the screenshot.
final double placeholderHeight = paragraph.height;
final double placeholderWidth = paragraph.height * 2;
final CanvasParagraph paragraph2 = rich(
ParagraphStyle(),
(CanvasParagraphBuilder builder) {
builder.addPlaceholder(placeholderWidth, placeholderHeight, PlaceholderAlignment.baseline, baseline: TextBaseline.alphabetic);
},
)..layout(constrain(double.infinity));
final Rect rect2 = Rect.fromLTWH(offset.dx, offset.dy, paragraph2.maxIntrinsicWidth, paragraph2.height);
canvas.drawRect(rect2, SurfacePaintData()..color = black);
canvas.drawParagraph(paragraph2, offset);
// Draw a rect in the placeholder.
// Leave some padding around the placeholder to make the black paragraph
// background visible.
final double padding = 5;
final TextBox placeholderBox = paragraph2.getBoxesForPlaceholders().single;
canvas.drawRect(
placeholderBox.toRect().shift(offset).deflate(padding),
SurfacePaintData()..color = red,
);
await takeScreenshot(canvas, bounds, 'canvas_paragraph_giant_body_font_size_dom');
// Restore the old font size value.
html.document.body.style.fontSize = oldBodyFontSize;
});
test('paints spans with varying heights/baselines', () {
final canvas = BitmapCanvas(bounds, RenderStrategy());
......
......@@ -11,8 +11,8 @@ import 'package:ui/ui.dart';
bool get isIosSafari => browserEngine == BrowserEngine.webkit &&
operatingSystem == OperatingSystem.iOs;
String get defaultFontFamily {
String fontFamily = canonicalizeFontFamily('Ahem')!;
String fontFamilyToAttribute(String fontFamily) {
fontFamily = canonicalizeFontFamily(fontFamily)!;
if (browserEngine == BrowserEngine.firefox) {
fontFamily = fontFamily.replaceAll('"', '&quot;');
} else if (browserEngine == BrowserEngine.blink ||
......@@ -22,6 +22,8 @@ String get defaultFontFamily {
}
return 'font-family: $fontFamily;';
}
final String defaultFontFamily = fontFamilyToAttribute('Ahem');
const String defaultColor = 'color: rgb(255, 0, 0);';
const String defaultFontSize = 'font-size: 14px;';
final String paragraphStyle =
......@@ -52,7 +54,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="$paragraphStyle">'
'<p style="font-size: 13px; $defaultFontFamily $paragraphStyle">'
'<span style="$defaultColor font-size: 13px; $defaultFontFamily">'
'Hello'
'</span>'
......@@ -63,7 +65,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: 39.0));
expect(
paragraph.toDomElement().outerHtml,
'<p style="$paragraphStyle">'
'<p style="font-size: 13px; $defaultFontFamily $paragraphStyle">'
'<span style="$defaultColor font-size: 13px; $defaultFontFamily">'
'Hel<br>lo'
'</span>'
......@@ -91,7 +93,11 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="$paragraphStyle"><span style="$defaultColor $defaultFontSize $defaultFontFamily">Hello</span></p>',
'<p style="$defaultFontSize $defaultFontFamily $paragraphStyle">'
'<span style="$defaultColor $defaultFontSize $defaultFontFamily">'
'Hello'
'</span>'
'</p>',
);
final FlatTextSpan textSpan = paragraph.spans.single as FlatTextSpan;
......@@ -116,7 +122,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="$paragraphStyle overflow-y: hidden; height: ${expectedHeight}px;">'
'<p style="$defaultFontSize $defaultFontFamily $paragraphStyle overflow-y: hidden; height: ${expectedHeight}px;">'
'<span style="$defaultColor $defaultFontSize $defaultFontFamily">'
'Hello'
'</span>'
......@@ -142,7 +148,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="$paragraphStyle overflow: hidden; height: ${expectedHeight}px; text-overflow: ellipsis;">'
'<p style="$defaultFontSize $defaultFontFamily $paragraphStyle overflow: hidden; height: ${expectedHeight}px; text-overflow: ellipsis;">'
'<span style="$defaultColor $defaultFontSize $defaultFontFamily">'
'Hello'
'</span>'
......@@ -170,7 +176,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="line-height: 1.5; $paragraphStyle">'
'<p style="line-height: 1.5; font-size: 9px; $defaultFontFamily $paragraphStyle">'
'<span style="$defaultColor line-height: 1.5; font-size: 9px; font-weight: bold; font-style: italic; $defaultFontFamily letter-spacing: 2px;">'
'Hello'
'</span>'
......@@ -208,7 +214,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="$paragraphStyle">'
'<p style="font-size: 13px; $defaultFontFamily $paragraphStyle">'
'<span style="$defaultColor font-size: 13px; font-weight: bold; $defaultFontFamily">'
'Hello'
'</span>'
......@@ -222,7 +228,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: 75.0));
expect(
paragraph.toDomElement().outerHtml,
'<p style="$paragraphStyle width: 75px;">'
'<p style="font-size: 13px; $defaultFontFamily $paragraphStyle width: 75px;">'
'<span style="$defaultColor font-size: 13px; font-weight: bold; $defaultFontFamily">'
'Hello'
'</span>'
......@@ -273,7 +279,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="$paragraphStyle">'
'<p style="font-size: 13px; $defaultFontFamily $paragraphStyle">'
'<span style="$defaultColor line-height: 2; font-size: 13px; font-weight: bold; $defaultFontFamily">'
'Hello'
'</span>'
......@@ -337,7 +343,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="$paragraphStyle">'
'<p style="font-size: 13px; $defaultFontFamily $paragraphStyle">'
'<span style="$defaultColor font-size: 13px; $defaultFontFamily">'
'First<br>Second '
'</span>'
......@@ -351,7 +357,7 @@ void testMain() async {
paragraph.layout(ParagraphConstraints(width: 180.0));
expect(
paragraph.toDomElement().outerHtml,
'<p style="$paragraphStyle width: 180px;">'
'<p style="font-size: 13px; $defaultFontFamily $paragraphStyle width: 180px;">'
'<span style="$defaultColor font-size: 13px; $defaultFontFamily">'
'First<br>Second <br>'
'</span>'
......@@ -361,6 +367,44 @@ void testMain() async {
'</p>',
);
});
test('various font sizes', () {
// Paragraphs and spans force the Ahem font in test mode. We need to trick
// them into thinking they are not in test mode, so they use the provided
// font family.
debugEmulateFlutterTesterEnvironment = false;
final EngineParagraphStyle style = EngineParagraphStyle(fontSize: 12.0, fontFamily: 'first');
final CanvasParagraphBuilder builder = CanvasParagraphBuilder(style);
builder.addText('First ');
builder.pushStyle(TextStyle(fontSize: 18.0, fontFamily: 'second'));
builder.addText('Second ');
builder.pushStyle(TextStyle(fontSize: 10.0, fontFamily: 'third'));
builder.addText('Third');
final CanvasParagraph paragraph = builder.build();
expect(paragraph.toPlainText(), 'First Second Third');
expect(paragraph.spans, hasLength(3));
// The paragraph should take the font size and family from the span with the
// greatest font size.
paragraph.layout(ParagraphConstraints(width: double.infinity));
expect(
paragraph.toDomElement().outerHtml,
'<p style="font-size: 18px; ${fontFamilyToAttribute('second')} $paragraphStyle">'
'<span style="$defaultColor font-size: 12px; ${fontFamilyToAttribute('first')}">'
'First '
'</span>'
'<span style="$defaultColor font-size: 18px; ${fontFamilyToAttribute('second')}">'
'Second '
'</span>'
'<span style="$defaultColor font-size: 10px; ${fontFamilyToAttribute('third')}">'
'Third'
'</span>'
'</p>',
);
debugEmulateFlutterTesterEnvironment = true;
});
}
TextStyle styleWithDefaults({
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册