Add a background paint property to TextStyle (#17586)

See https://github.com/flutter/flutter/issues/11961
diff --git a/packages/flutter/lib/src/painting/basic_types.dart b/packages/flutter/lib/src/painting/basic_types.dart
index 58c3f3f..a3c6e7d 100644
--- a/packages/flutter/lib/src/painting/basic_types.dart
+++ b/packages/flutter/lib/src/painting/basic_types.dart
@@ -14,6 +14,7 @@
   FontStyle,
   FontWeight,
   ImageShader,
+  Locale,
   MaskFilter,
   Offset,
   Paint,
diff --git a/packages/flutter/lib/src/painting/text_style.dart b/packages/flutter/lib/src/painting/text_style.dart
index e93700f..7ddfdc6 100644
--- a/packages/flutter/lib/src/painting/text_style.dart
+++ b/packages/flutter/lib/src/painting/text_style.dart
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:ui' as ui show ParagraphStyle, TextStyle, lerpDouble, Locale;
+import 'dart:ui' as ui show ParagraphStyle, TextStyle, lerpDouble;
 
 import 'package:flutter/foundation.dart';
 
@@ -230,6 +230,7 @@
     this.textBaseline,
     this.height,
     this.locale,
+    this.background,
     this.decoration,
     this.decorationColor,
     this.decorationStyle,
@@ -298,7 +299,15 @@
   final double height;
 
   /// The locale used to select region-specific glyphs.
-  final ui.Locale locale;
+  final Locale locale;
+
+  /// The paint drawn as a background for the text.
+  ///
+  /// The value should ideally be cached and reused each time if multiple text
+  /// styles are created with the same paint settings. Otherwise, each time it
+  /// will appear like the style changed, which will result in unnecessary
+  /// updates all the way through the framework.
+  final Paint background;
 
   /// The decorations to paint near the text (e.g., an underline).
   final TextDecoration decoration;
@@ -334,7 +343,8 @@
     double wordSpacing,
     TextBaseline textBaseline,
     double height,
-    ui.Locale locale,
+    Locale locale,
+    Paint background,
     TextDecoration decoration,
     Color decorationColor,
     TextDecorationStyle decorationStyle,
@@ -358,6 +368,7 @@
       textBaseline: textBaseline ?? this.textBaseline,
       height: height ?? this.height,
       locale: locale ?? this.locale,
+      background: background ?? this.background,
       decoration: decoration ?? this.decoration,
       decorationColor: decorationColor ?? this.decorationColor,
       decorationStyle: decorationStyle ?? this.decorationStyle,
@@ -436,6 +447,7 @@
       textBaseline: textBaseline,
       height: height == null ? null : height * heightFactor + heightDelta,
       locale: locale,
+      background: background,
       decoration: decoration ?? this.decoration,
       decorationColor: decorationColor ?? this.decorationColor,
       decorationStyle: decorationStyle ?? this.decorationStyle,
@@ -481,6 +493,7 @@
       textBaseline: other.textBaseline,
       height: other.height,
       locale: other.locale,
+      background: other.background,
       decoration: other.decoration,
       decorationColor: other.decorationColor,
       decorationStyle: other.decorationStyle,
@@ -529,6 +542,7 @@
         textBaseline: t < 0.5 ? null : b.textBaseline,
         height: t < 0.5 ? null : b.height,
         locale: t < 0.5 ? null : b.locale,
+        background: t < 0.5 ? null : b.background,
         decoration: t < 0.5 ? null : b.decoration,
         decorationColor: Color.lerp(null, b.decorationColor, t),
         decorationStyle: t < 0.5 ? null : b.decorationStyle,
@@ -549,6 +563,7 @@
         textBaseline: t < 0.5 ? a.textBaseline : null,
         height: t < 0.5 ? a.height : null,
         locale: t < 0.5 ? a.locale : null,
+        background: t < 0.5 ? a.background : null,
         decoration: t < 0.5 ? a.decoration : null,
         decorationColor: Color.lerp(a.decorationColor, null, t),
         decorationStyle: t < 0.5 ? a.decorationStyle : null,
@@ -568,6 +583,7 @@
       textBaseline: t < 0.5 ? a.textBaseline : b.textBaseline,
       height: ui.lerpDouble(a.height ?? b.height, b.height ?? a.height, t),
       locale: t < 0.5 ? a.locale : b.locale,
+      background: t < 0.5 ? a.background : b.background,
       decoration: t < 0.5 ? a.decoration : b.decoration,
       decorationColor: Color.lerp(a.decorationColor, b.decorationColor, t),
       decorationStyle: t < 0.5 ? a.decorationStyle : b.decorationStyle,
@@ -591,6 +607,7 @@
       wordSpacing: wordSpacing,
       height: height,
       locale: locale,
+      background: background,
     );
   }
 
@@ -608,7 +625,7 @@
       double textScaleFactor: 1.0,
       String ellipsis,
       int maxLines,
-      ui.Locale locale,
+      Locale locale,
   }) {
     assert(textScaleFactor != null);
     assert(maxLines == null || maxLines > 0);
@@ -644,7 +661,8 @@
         wordSpacing != other.wordSpacing ||
         textBaseline != other.textBaseline ||
         height != other.height ||
-        locale != other.locale)
+        locale != other.locale ||
+        background != other.background)
       return RenderComparison.layout;
     if (color != other.color ||
         decoration != other.decoration ||
@@ -672,6 +690,7 @@
            textBaseline == typedOther.textBaseline &&
            height == typedOther.height &&
            locale == typedOther.locale &&
+           background == typedOther.background &&
            decoration == typedOther.decoration &&
            decorationColor == typedOther.decorationColor &&
            decorationStyle == typedOther.decorationStyle;
@@ -691,6 +710,7 @@
       textBaseline,
       height,
       locale,
+      background,
       decoration,
       decorationColor,
       decorationStyle
@@ -757,6 +777,7 @@
     styles.add(new EnumProperty<TextBaseline>('${prefix}baseline', textBaseline, defaultValue: null));
     styles.add(new DoubleProperty('${prefix}height', height, unit: 'x', defaultValue: null));
     styles.add(new StringProperty('${prefix}locale', locale?.toString(), defaultValue: null, quoted: false));
+    styles.add(new StringProperty('${prefix}background', background?.toString(), defaultValue: null, quoted: false));
     if (decoration != null || decorationColor != null || decorationStyle != null) {
       final List<String> decorationDescription = <String>[];
       if (decorationStyle != null)
diff --git a/packages/flutter/test/material/theme_test.dart b/packages/flutter/test/material/theme_test.dart
index d25b1a0..8bcfc7b 100644
--- a/packages/flutter/test/material/theme_test.dart
+++ b/packages/flutter/test/material/theme_test.dart
@@ -403,6 +403,8 @@
         expect(style.decorationColor, null);
         expect(style.decorationStyle, null);
         expect(style.debugLabel, isNotNull);
+        expect(style.locale, null);
+        expect(style.background, null);
       }
     }
 
@@ -450,6 +452,7 @@
   @override FontWeight get fontWeight => _delegate.fontWeight;
   @override double get height => _delegate.height;
   @override ui.Locale get locale => _delegate.locale;
+  @override ui.Paint get background => _delegate.background;
   @override bool get inherit => _delegate.inherit;
   @override double get letterSpacing => _delegate.letterSpacing;
   @override TextBaseline get textBaseline => _delegate.textBaseline;
@@ -476,7 +479,7 @@
   }
 
   @override
-  TextStyle copyWith({Color color, String fontFamily, double fontSize, FontWeight fontWeight, FontStyle fontStyle, double letterSpacing, double wordSpacing, TextBaseline textBaseline, double height, ui.Locale locale, TextDecoration decoration, Color decorationColor, TextDecorationStyle decorationStyle, String debugLabel}) {
+  TextStyle copyWith({Color color, String fontFamily, double fontSize, FontWeight fontWeight, FontStyle fontStyle, double letterSpacing, double wordSpacing, TextBaseline textBaseline, double height, ui.Locale locale, ui.Paint background, TextDecoration decoration, Color decorationColor, TextDecorationStyle decorationStyle, String debugLabel}) {
     throw new UnimplementedError();
   }