From da5b0f9b3615875b0f987863f88cf133e77d99bc Mon Sep 17 00:00:00 2001 From: Mouad Debbar Date: Tue, 8 Dec 2020 15:22:20 -0800 Subject: [PATCH] [web] Default styles for rich text (#22941) --- .../lib/src/engine/text/canvas_paragraph.dart | 85 +++++++++---------- .../text/canvas_paragraph_builder_test.dart | 53 ++++++++++-- 2 files changed, 84 insertions(+), 54 deletions(-) diff --git a/lib/web_ui/lib/src/engine/text/canvas_paragraph.dart b/lib/web_ui/lib/src/engine/text/canvas_paragraph.dart index f47a8f2565f..03d8175bee1 100644 --- a/lib/web_ui/lib/src/engine/text/canvas_paragraph.dart +++ b/lib/web_ui/lib/src/engine/text/canvas_paragraph.dart @@ -317,13 +317,41 @@ abstract class StyleNode { return ChildStyleNode(parent: this, style: style); } + EngineTextStyle? _cachedStyle; + /// Generates the final text style to be applied to the text span. /// /// The resolved text style is equivalent to the entire ascendent chain of /// parent style nodes. - EngineTextStyle resolveStyle(); + EngineTextStyle resolveStyle() { + final EngineTextStyle? style = _cachedStyle; + if (style == null) { + return _cachedStyle ??= EngineTextStyle( + color: _color, + decoration: _decoration, + decorationColor: _decorationColor, + decorationStyle: _decorationStyle, + decorationThickness: _decorationThickness, + fontWeight: _fontWeight, + fontStyle: _fontStyle, + textBaseline: _textBaseline, + fontFamily: _fontFamily, + fontFamilyFallback: _fontFamilyFallback, + fontFeatures: _fontFeatures, + fontSize: _fontSize, + letterSpacing: _letterSpacing, + wordSpacing: _wordSpacing, + height: _height, + locale: _locale, + background: _background, + foreground: _foreground, + shadows: _shadows, + ); + } + return style; + } - ui.Color? get _color; + ui.Color get _color; ui.TextDecoration? get _decoration; ui.Color? get _decorationColor; ui.TextDecorationStyle? get _decorationStyle; @@ -331,10 +359,10 @@ abstract class StyleNode { ui.FontWeight? get _fontWeight; ui.FontStyle? get _fontStyle; ui.TextBaseline? get _textBaseline; - String? get _fontFamily; + String get _fontFamily; List? get _fontFamilyFallback; List? get _fontFeatures; - double? get _fontSize; + double get _fontSize; double? get _letterSpacing; double? get _wordSpacing; double? get _height; @@ -355,36 +383,11 @@ class ChildStyleNode extends StyleNode { /// The text style associated with the current node. final EngineTextStyle style; - @override - EngineTextStyle resolveStyle() { - return EngineTextStyle( - color: _color, - decoration: _decoration, - decorationColor: _decorationColor, - decorationStyle: _decorationStyle, - decorationThickness: _decorationThickness, - fontWeight: _fontWeight, - fontStyle: _fontStyle, - textBaseline: _textBaseline, - fontFamily: _fontFamily, - fontFamilyFallback: _fontFamilyFallback, - fontFeatures: _fontFeatures, - fontSize: _fontSize, - letterSpacing: _letterSpacing, - wordSpacing: _wordSpacing, - height: _height, - locale: _locale, - background: _background, - foreground: _foreground, - shadows: _shadows, - ); - } - // Read these properties from the TextStyle associated with this node. If the // property isn't defined, go to the parent node. @override - ui.Color? get _color => style._color ?? parent._color; + ui.Color get _color => style._color ?? parent._color; @override ui.TextDecoration? get _decoration => style._decoration ?? parent._decoration; @@ -414,7 +417,7 @@ class ChildStyleNode extends StyleNode { List? get _fontFeatures => style._fontFeatures ?? parent._fontFeatures; @override - double? get _fontSize => style._fontSize ?? parent._fontSize; + double get _fontSize => style._fontSize ?? parent._fontSize; @override double? get _letterSpacing => style._letterSpacing ?? parent._letterSpacing; @@ -441,7 +444,7 @@ class ChildStyleNode extends StyleNode { // never null on the TextStyle object, so we use `_isFontFamilyProvided` to // check if font family is defined or not. @override - String? get _fontFamily => style._isFontFamilyProvided ? style._fontFamily : parent._fontFamily; + String get _fontFamily => style._isFontFamilyProvided ? style._fontFamily : parent._fontFamily; } /// The root style node for the paragraph. @@ -455,20 +458,8 @@ class RootStyleNode extends StyleNode { /// The style of the paragraph being built. final EngineParagraphStyle paragraphStyle; - EngineTextStyle? _cachedStyle; - @override - EngineTextStyle resolveStyle() { - final EngineTextStyle? style = _cachedStyle; - if (style == null) { - return _cachedStyle ??= - EngineTextStyle.fromParagraphStyle(paragraphStyle); - } - return style; - } - - @override - ui.Color? get _color => null; + final ui.Color _color = _defaultTextColor; @override ui.TextDecoration? get _decoration => null; @@ -491,7 +482,7 @@ class RootStyleNode extends StyleNode { ui.TextBaseline? get _textBaseline => null; @override - String? get _fontFamily => paragraphStyle._fontFamily; + String get _fontFamily => paragraphStyle._fontFamily ?? DomRenderer.defaultFontFamily; @override List? get _fontFamilyFallback => null; @@ -500,7 +491,7 @@ class RootStyleNode extends StyleNode { List? get _fontFeatures => null; @override - double? get _fontSize => paragraphStyle._fontSize; + double get _fontSize => paragraphStyle._fontSize ?? DomRenderer.defaultFontSize; @override double? get _letterSpacing => null; diff --git a/lib/web_ui/test/text/canvas_paragraph_builder_test.dart b/lib/web_ui/test/text/canvas_paragraph_builder_test.dart index a0d0e4b8ccc..f5b367efded 100644 --- a/lib/web_ui/test/text/canvas_paragraph_builder_test.dart +++ b/lib/web_ui/test/text/canvas_paragraph_builder_test.dart @@ -35,7 +35,22 @@ void testMain() { expect(span, isA()); final FlatTextSpan textSpan = span as FlatTextSpan; expect(textSpan.textOf(paragraph), 'Hello'); - expect(textSpan.style, TextStyle(fontSize: 13.0)); + expect(textSpan.style, styleWithDefaults(fontSize: 13.0)); + }); + + test('Correct defaults', () { + final EngineParagraphStyle style = EngineParagraphStyle(); + final CanvasParagraphBuilder builder = CanvasParagraphBuilder(style); + + builder.addText('Hello'); + + final CanvasParagraph paragraph = builder.build(); + expect(paragraph.paragraphStyle, style); + expect(paragraph.toPlainText(), 'Hello'); + expect(paragraph.spans, hasLength(1)); + + final FlatTextSpan textSpan = paragraph.spans.single as FlatTextSpan; + expect(textSpan.style, styleWithDefaults()); }); test('Builds a single-span paragraph with complex styles', () { @@ -59,7 +74,7 @@ void testMain() { expect(span.textOf(paragraph), 'Hello'); expect( span.style, - TextStyle( + styleWithDefaults( height: 1.5, fontSize: 9.0, fontWeight: FontWeight.bold, @@ -87,7 +102,7 @@ void testMain() { expect(hello.textOf(paragraph), 'Hello'); expect( hello.style, - TextStyle( + styleWithDefaults( fontSize: 13.0, fontWeight: FontWeight.bold, ), @@ -97,7 +112,7 @@ void testMain() { expect(world.textOf(paragraph), ' world'); expect( world.style, - TextStyle( + styleWithDefaults( fontSize: 13.0, fontStyle: FontStyle.italic, ), @@ -125,14 +140,18 @@ void testMain() { expect(hello.textOf(paragraph), 'Hello'); expect( hello.style, - TextStyle(fontSize: 13.0, fontWeight: FontWeight.bold, height: 2.0), + styleWithDefaults( + fontSize: 13.0, + fontWeight: FontWeight.bold, + height: 2.0, + ), ); final FlatTextSpan world = paragraph.spans[1] as FlatTextSpan; expect(world.textOf(paragraph), ' world'); expect( world.style, - TextStyle( + styleWithDefaults( fontSize: 13.0, fontWeight: FontWeight.bold, fontStyle: FontStyle.italic, @@ -143,7 +162,7 @@ void testMain() { expect(bang.textOf(paragraph), '!'); expect( bang.style, - TextStyle( + styleWithDefaults( fontSize: 13.0, fontWeight: FontWeight.normal, fontStyle: FontStyle.italic, @@ -151,3 +170,23 @@ void testMain() { ); }); } + +TextStyle styleWithDefaults({ + Color color = const Color(0xFFFF0000), + String fontFamily = DomRenderer.defaultFontFamily, + double fontSize = DomRenderer.defaultFontSize, + FontWeight? fontWeight, + FontStyle? fontStyle, + double? height, + double? letterSpacing, +}) { + return TextStyle( + color: color, + fontFamily: fontFamily, + fontSize: fontSize, + fontWeight: fontWeight, + fontStyle: fontStyle, + height: height, + letterSpacing: letterSpacing, + ); +}