[web] Default styles for rich text (#22941)

This commit is contained in:
Mouad Debbar 2020-12-08 15:22:20 -08:00 committed by GitHub
parent 1002b2ce03
commit da5b0f9b36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 84 additions and 54 deletions

View File

@ -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<String>? get _fontFamilyFallback;
List<ui.FontFeature>? 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<ui.FontFeature>? 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<String>? get _fontFamilyFallback => null;
@ -500,7 +491,7 @@ class RootStyleNode extends StyleNode {
List<ui.FontFeature>? get _fontFeatures => null;
@override
double? get _fontSize => paragraphStyle._fontSize;
double get _fontSize => paragraphStyle._fontSize ?? DomRenderer.defaultFontSize;
@override
double? get _letterSpacing => null;

View File

@ -35,7 +35,22 @@ void testMain() {
expect(span, isA<FlatTextSpan>());
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,
);
}