Bring TextTheme into alignment with the current Material spec (#22330)


diff --git a/dev/tools/gen_localizations.dart b/dev/tools/gen_localizations.dart
index 7419912..2142d6d 100644
--- a/dev/tools/gen_localizations.dart
+++ b/dev/tools/gen_localizations.dart
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// This program generates a Dart "localizations" Map definition that combines
-// the contents of the arb files. The map can be used to lookup a localized
-// string: `localizations[localeString][resourceId]`.
+// This program generates a getTranslation() function that looks up the
+// translations contained by the arb files. The returned value is an
+// instance of GlobalMaterialLocalizations that corresponds to a single
+// locale.
 //
 // The *.arb files are in packages/flutter_localizations/lib/src/l10n.
 //
@@ -273,6 +274,8 @@
     switch (attributes['x-flutter-type']) {
       case 'icuShortTimePattern':
         return 'TimeOfDayFormat';
+      case 'scriptCategory':
+        return 'ScriptCategory';
     }
   }
   return 'String';
@@ -308,6 +311,12 @@
   'ah:mm': 'TimeOfDayFormat.a_space_h_colon_mm',
 };
 
+const Map<String, String> _scriptCategoryToEnum = <String, String>{
+  'English-like': 'ScriptCategory.englishLike',
+  'dense': 'ScriptCategory.dense',
+  'tall': 'ScriptCategory.tall',
+};
+
 /// Returns the literal that describes the value returned by getters
 /// with the given attributes.
 ///
@@ -330,6 +339,15 @@
           );
         }
         return _icuTimeOfDayToEnum[value];
+      case 'scriptCategory':
+        if (!_scriptCategoryToEnum.containsKey(value)) {
+          throw Exception(
+            '"$value" is not one of the scriptCategory values supported '
+            'by the material library. Here is the list of supported '
+            'values:\n  ' + _scriptCategoryToEnum.keys.join('\n  ')
+          );
+        }
+        return _scriptCategoryToEnum[value];
     }
   }
   return generateString(value);
diff --git a/examples/flutter_gallery/lib/demo/typography_demo.dart b/examples/flutter_gallery/lib/demo/typography_demo.dart
index fd2013d..a1e0314 100644
--- a/examples/flutter_gallery/lib/demo/typography_demo.dart
+++ b/examples/flutter_gallery/lib/demo/typography_demo.dart
@@ -57,7 +57,7 @@
       TextStyleItem(name: 'Body 2', style: textTheme.body2, text: 'Medium 14sp'),
       TextStyleItem(name: 'Body 1', style: textTheme.body1, text: 'Regular 14sp'),
       TextStyleItem(name: 'Caption', style: textTheme.caption, text: 'Regular 12sp'),
-      TextStyleItem(name: 'Button', style: textTheme.button, text: 'MEDIUM (ALL CAPS) 14sp')
+      TextStyleItem(name: 'Button', style: textTheme.button, text: 'MEDIUM (ALL CAPS) 14sp'),
     ];
 
     if (MediaQuery.of(context).size.width > 500.0) {
diff --git a/packages/flutter/lib/material.dart b/packages/flutter/lib/material.dart
index 6240c90..1abaa73 100644
--- a/packages/flutter/lib/material.dart
+++ b/packages/flutter/lib/material.dart
@@ -97,6 +97,7 @@
 export 'src/material/text_field.dart';
 export 'src/material/text_form_field.dart';
 export 'src/material/text_selection.dart';
+export 'src/material/text_theme.dart';
 export 'src/material/theme.dart';
 export 'src/material/theme_data.dart';
 export 'src/material/time.dart';
diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart
index dec704f..b3883ae 100644
--- a/packages/flutter/lib/src/material/app_bar.dart
+++ b/packages/flutter/lib/src/material/app_bar.dart
@@ -19,8 +19,8 @@
 import 'material_localizations.dart';
 import 'scaffold.dart';
 import 'tabs.dart';
+import 'text_theme.dart';
 import 'theme.dart';
-import 'typography.dart';
 
 // Examples can assume:
 // void _airDress() { }
diff --git a/packages/flutter/lib/src/material/bottom_navigation_bar.dart b/packages/flutter/lib/src/material/bottom_navigation_bar.dart
index 9024b53..8ebfedf 100644
--- a/packages/flutter/lib/src/material/bottom_navigation_bar.dart
+++ b/packages/flutter/lib/src/material/bottom_navigation_bar.dart
@@ -14,8 +14,8 @@
 import 'ink_well.dart';
 import 'material.dart';
 import 'material_localizations.dart';
+import 'text_theme.dart';
 import 'theme.dart';
-import 'typography.dart';
 
 const double _kActiveFontSize = 14.0;
 const double _kInactiveFontSize = 12.0;
diff --git a/packages/flutter/lib/src/material/date_picker.dart b/packages/flutter/lib/src/material/date_picker.dart
index 8f5e6b9..17ca03c 100644
--- a/packages/flutter/lib/src/material/date_picker.dart
+++ b/packages/flutter/lib/src/material/date_picker.dart
@@ -21,8 +21,8 @@
 import 'ink_well.dart';
 import 'material.dart';
 import 'material_localizations.dart';
+import 'text_theme.dart';
 import 'theme.dart';
-import 'typography.dart';
 
 /// Initial display mode of the date picker dialog.
 ///
diff --git a/packages/flutter/lib/src/material/material_localizations.dart b/packages/flutter/lib/src/material/material_localizations.dart
index 19eaa08..5927243 100644
--- a/packages/flutter/lib/src/material/material_localizations.dart
+++ b/packages/flutter/lib/src/material/material_localizations.dart
@@ -7,6 +7,7 @@
 import 'package:flutter/foundation.dart';
 import 'package:flutter/widgets.dart';
 
+import 'text_theme.dart';
 import 'time.dart';
 import 'typography.dart';
 
@@ -34,6 +35,10 @@
 //
 // 5. If you are a Google employee, you should then also follow the instructions
 //    at go/flutter-l10n. If you're not, don't worry about it.
+//
+// 6. If you're adding a String for the sake of Flutter, not for an app-specific
+//    version of this interface, you are making a breaking API change. See
+//    https://flutter.io/design-principles/#handling-breaking-changes.
 
 /// Defines the localized resource values used by the Material widgets.
 ///
@@ -168,22 +173,17 @@
   /// each supported layout.
   TimeOfDayFormat timeOfDayFormat({ bool alwaysUse24HourFormat = false });
 
-  /// Provides geometric text preferences for the current locale.
+  /// Defines the localized [TextStyle] geometry for [ThemeData.textTheme].
   ///
-  /// This text theme is incomplete. For example, it lacks text color
-  /// information. This theme must be merged with another text theme that
-  /// provides the missing values.
+  /// The [scriptCategory] defines the overall geometry of a [TextTheme] for
+  /// the static [MaterialTextGeometry.localizedFor] method in terms of the
+  /// three language categories defined in https://material.io/go/design-typography.
   ///
-  /// Typically a complete theme is obtained via [Theme.of], which can be
-  /// localized using the [Localizations] widget.
-  ///
-  /// The text styles provided by this theme are expected to have their
-  /// [TextStyle.inherit] property set to false, so that the [ThemeData]
-  /// obtained from [Theme.of] no longer inherits text style properties and
-  /// contains a complete set of properties needed to style a [Text] widget.
-  ///
-  /// See also: https://material.io/go/design-typography
-  TextTheme get localTextGeometry;
+  /// Generally speaking, font sizes for [ScriptCategory.tall] and
+  /// [ScriptCategory.dense] scripts - for text styles that are smaller than the
+  /// title style - are one unit larger than they are for
+  /// [ScriptCategory.englishLike] scripts.
+  ScriptCategory get scriptCategory;
 
   /// Formats [number] as a decimal, inserting locale-appropriate thousands
   /// separators as necessary.
@@ -653,16 +653,15 @@
   String get modalBarrierDismissLabel => 'Dismiss';
 
   @override
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
+
+  @override
   TimeOfDayFormat timeOfDayFormat({ bool alwaysUse24HourFormat = false }) {
     return alwaysUse24HourFormat
       ? TimeOfDayFormat.HH_colon_mm
       : TimeOfDayFormat.h_colon_mm_space_a;
   }
 
-  /// Looks up text geometry defined in [MaterialTextGeometry].
-  @override
-  TextTheme get localTextGeometry => MaterialTextGeometry.englishLike;
-
   @override
   String get signedInLabel => 'Signed in';
 
diff --git a/packages/flutter/lib/src/material/stepper.dart b/packages/flutter/lib/src/material/stepper.dart
index ccce366..d091855 100644
--- a/packages/flutter/lib/src/material/stepper.dart
+++ b/packages/flutter/lib/src/material/stepper.dart
@@ -12,8 +12,8 @@
 import 'ink_well.dart';
 import 'material.dart';
 import 'material_localizations.dart';
+import 'text_theme.dart';
 import 'theme.dart';
-import 'typography.dart';
 
 // TODO(dragostis): Missing functionality:
 //   * mobile horizontal mode with adding/removing steps
diff --git a/packages/flutter/lib/src/material/text_theme.dart b/packages/flutter/lib/src/material/text_theme.dart
new file mode 100644
index 0000000..9d21e5e
--- /dev/null
+++ b/packages/flutter/lib/src/material/text_theme.dart
@@ -0,0 +1,540 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/painting.dart';
+
+import 'typography.dart';
+
+/// Material design text theme.
+///
+/// Definitions for the various typographical styles found in material design
+/// (e.g., button, caption). Rather than creating a [TextTheme] directly,
+/// you can obtain an instance as [Typography.black] or [Typography.white].
+///
+/// To obtain the current text theme, call [Theme.of] with the current
+/// [BuildContext] and read the [ThemeData.textTheme] property.
+///
+/// The Material Design typography scheme was signficantly changed in the
+/// current (2018) version of the specification
+/// (https://material.io/design/typography).
+///
+/// The 2018 spec has thirteen text styles:
+/// ```
+/// NAME         SIZE  WEIGHT  SPACING
+/// headline1    96.0  light   -1.5
+/// headline2    60.0  light   -0.5
+/// headline3    48.0  normal   0.0
+/// headline4    34.0  normal   0.25
+/// headline5    24.0  normal   0.0
+/// headline6    20.0  medium   0.15
+/// subtitle1    16.0  normal   0.15
+/// subtitle2    14.0  medium   0.1
+/// body1        16.0  normal   0.5
+/// body2        14.0  normal   0.25
+/// button       14.0  medium   0.75
+/// caption      12.0  normal   0.4
+/// overline     10.0  normal   1.5
+///
+/// ```
+/// Where "light" is `FontWeight.w300`, "normal" is `FontWeight.w400` and
+/// "medium" is `FontWeight.w500`.
+///
+/// The [TextTheme] API is based on the original material (2014)
+/// design spec, which used different text style names. For backwards
+/// compatability's sake, this API continues to use the original
+/// names. The table below should help with understanding the API in
+/// terms of the 2018 material spec.
+///
+/// Each of the [TextTheme] text styles corresponds to one of the
+/// styles from 2018 spec. By default, the font sizes, font weights
+/// and letter spacings have not changed from their original,
+/// 2014, values.
+/// ```
+/// NAME       SIZE   WEIGHT   SPACING  2018 NAME
+/// display4   112.0  thin     0.0      headline1
+/// display3   56.0   normal   0.0      headline2
+/// display2   45.0   normal   0.0      headline3
+/// display1   34.0   normal   0.0      headline4
+/// headline   24.0   normal   0.0      headline5
+/// title      20.0   medium   0.0      headline6
+/// subhead    16.0   normal   0.0      subtitle1
+/// body2      14.0   medium   0.0      body1
+/// body1      14.0   normal   0.0      body2
+/// caption    12.0   normal   0.0      caption
+/// button     14.0   medium   0.0      button
+/// subtitle   14.0   medium   0.0      subtitle2
+/// overline   10.0   normal   0.0      overline
+/// ```
+///
+/// Where "thin" is `FontWeight.w100`, "normal" is `FontWeight.w400` and
+/// "medium" is `FontWeight.w500`. Letter spacing for all of the original
+/// text styles was 0.0.
+///
+/// To configure a [Theme] for the new sizes, weights, and letter spacings,
+/// initialize its [ThemeData.typography] value with a [Typography] that
+/// object that specifies the 2018 versions of the geometry themes:
+/// [Typography.englishLike2018], [Typography.dense2018],
+/// and [Typography.tall2018].
+///
+/// The following image [from the material design
+/// specification](https://material.io/go/design-typography#typography-styles)
+/// shows the recommended styles for each of the properties of a [TextTheme].
+/// This image uses the `Roboto` font, which is the font used on Android. On
+/// iOS, the [San Francisco
+/// font](https://developer.apple.com/ios/human-interface-guidelines/visual-design/typography/)
+/// is automatically used instead.
+///
+/// ![To see the image, visit the typography site referenced below.](https://storage.googleapis.com/material-design/publish/material_v_11/assets/0Bzhp5Z4wHba3alhXZ2pPWGk3Zjg/style_typography_styles_scale.png)
+///
+/// See also:
+///
+///  * [Typography], the class that generates [TextTheme]s appropriate for a platform.
+///  * [Theme], for other aspects of a material design application that can be
+///    globally adjusted, such as the color scheme.
+///  * <http://material.google.com/style/typography.html>
+@immutable
+class TextTheme extends Diagnosticable {
+  /// Creates a text theme that uses the given values.
+  ///
+  /// Rather than creating a new text theme, consider using [Typography.black]
+  /// or [Typography.white], which implement the typography styles in the
+  /// material design specification:
+  ///
+  /// <https://material.google.com/style/typography.html#typography-styles>
+  ///
+  /// If you do decide to create your own text theme, consider using one of
+  /// those predefined themes as a starting point for [copyWith] or [apply].
+  const TextTheme({
+    this.display4,
+    this.display3,
+    this.display2,
+    this.display1,
+    this.headline,
+    this.title,
+    this.subhead,
+    this.body2,
+    this.body1,
+    this.caption,
+    this.button,
+    this.subtitle,
+    this.overline,
+  });
+
+  /// Extremely large text.
+  ///
+  /// The font size is 112 pixels.
+  final TextStyle display4;
+
+  /// Very, very large text.
+  ///
+  /// Used for the date in the dialog shown by [showDatePicker].
+  final TextStyle display3;
+
+  /// Very large text.
+  final TextStyle display2;
+
+  /// Large text.
+  final TextStyle display1;
+
+  /// Used for large text in dialogs (e.g., the month and year in the dialog
+  /// shown by [showDatePicker]).
+  final TextStyle headline;
+
+  /// Used for the primary text in app bars and dialogs (e.g., [AppBar.title]
+  /// and [AlertDialog.title]).
+  final TextStyle title;
+
+  /// Used for the primary text in lists (e.g., [ListTile.title]).
+  final TextStyle subhead;
+
+  /// Used for emphasizing text that would otherwise be [body1].
+  final TextStyle body2;
+
+  /// Used for the default text style for [Material].
+  final TextStyle body1;
+
+  /// Used for auxiliary text associated with images.
+  final TextStyle caption;
+
+  /// Used for text on [RaisedButton] and [FlatButton].
+  final TextStyle button;
+
+  /// For medium emphasis text that's a little smaller than [subhead].
+  final TextStyle subtitle;
+
+  /// The smallest style,
+  ///
+  /// Typically used for captions or to introduce a (larger) headline.
+  final TextStyle overline;
+
+  /// Creates a copy of this text theme but with the given fields replaced with
+  /// the new values.
+  ///
+  /// Consider using [Typography.black] or [Typography.white], which implement
+  /// the typography styles in the material design specification, as a starting
+  /// point.
+  ///
+  /// ## Sample code
+  ///
+  /// ```dart
+  /// /// A Widget that sets the ambient theme's title text color for its
+  /// /// descendants, while leaving other ambient theme attributes alone.
+  /// class TitleColorThemeCopy extends StatelessWidget {
+  ///   TitleColorThemeCopy({Key key, this.child, this.titleColor}) : super(key: key);
+  ///
+  ///   final Color titleColor;
+  ///   final Widget child;
+  ///
+  ///   @override
+  ///   Widget build(BuildContext context) {
+  ///     final ThemeData theme = Theme.of(context);
+  ///     return Theme(
+  ///       data: theme.copyWith(
+  ///         textTheme: theme.textTheme.copyWith(
+  ///           title: theme.textTheme.title.copyWith(
+  ///             color: titleColor,
+  ///           ),
+  ///         ),
+  ///       ),
+  ///       child: child,
+  ///     );
+  ///   }
+  /// }
+  /// ```
+  ///
+  /// See also:
+  ///
+  ///   * [merge] is used instead of [copyWith] when you want to merge all
+  ///     of the fields of a TextTheme instead of individual fields.
+  TextTheme copyWith({
+    TextStyle display4,
+    TextStyle display3,
+    TextStyle display2,
+    TextStyle display1,
+    TextStyle headline,
+    TextStyle title,
+    TextStyle subhead,
+    TextStyle body2,
+    TextStyle body1,
+    TextStyle caption,
+    TextStyle button,
+    TextStyle subtitle,
+    TextStyle overline,
+  }) {
+    return TextTheme(
+      display4: display4 ?? this.display4,
+      display3: display3 ?? this.display3,
+      display2: display2 ?? this.display2,
+      display1: display1 ?? this.display1,
+      headline: headline ?? this.headline,
+      title: title ?? this.title,
+      subhead: subhead ?? this.subhead,
+      body2: body2 ?? this.body2,
+      body1: body1 ?? this.body1,
+      caption: caption ?? this.caption,
+      button: button ?? this.button,
+      subtitle: subtitle ?? this.subtitle,
+      overline: overline ?? this.overline,
+    );
+  }
+
+  /// Creates a new [TextTheme] where each text style from this object has been
+  /// merged with the matching text style from the `other` object.
+  ///
+  /// The merging is done by calling [TextStyle.merge] on each respective pair
+  /// of text styles from this and the [other] text themes and is subject to
+  /// the value of [TextStyle.inherit] flag. For more details, see the
+  /// documentation on [TextStyle.merge] and [TextStyle.inherit].
+  ///
+  /// If this theme, or the `other` theme has members that are null, then the
+  /// non-null one (if any) is used. If the `other` theme is itself null, then
+  /// this [TextTheme] is returned unchanged. If values in both are set, then
+  /// the values are merged using [TextStyle.merge].
+  ///
+  /// This is particularly useful if one [TextTheme] defines one set of
+  /// properties and another defines a different set, e.g. having colors
+  /// defined in one text theme and font sizes in another, or when one
+  /// [TextTheme] has only some fields defined, and you want to define the rest
+  /// by merging it with a default theme.
+  ///
+  /// ## Sample code
+  ///
+  /// ```dart
+  /// /// A Widget that sets the ambient theme's title text color for its
+  /// /// descendants, while leaving other ambient theme attributes alone.
+  /// class TitleColorTheme extends StatelessWidget {
+  ///   TitleColorTheme({Key key, this.child, this.titleColor}) : super(key: key);
+  ///
+  ///   final Color titleColor;
+  ///   final Widget child;
+  ///
+  ///   @override
+  ///   Widget build(BuildContext context) {
+  ///     ThemeData theme = Theme.of(context);
+  ///     // This partialTheme is incomplete: it only has the title style
+  ///     // defined. Just replacing theme.textTheme with partialTheme would
+  ///     // set the title, but everything else would be null. This isn't very
+  ///     // useful, so merge it with the existing theme to keep all of the
+  ///     // preexisting definitions for the other styles.
+  ///     TextTheme partialTheme = TextTheme(title: TextStyle(color: titleColor));
+  ///     theme = theme.copyWith(textTheme: theme.textTheme.merge(partialTheme));
+  ///     return Theme(data: theme, child: child);
+  ///   }
+  /// }
+  /// ```
+  ///
+  /// See also:
+  ///
+  ///   * [copyWith] is used instead of [merge] when you wish to override
+  ///     individual fields in the [TextTheme] instead of merging all of the
+  ///     fields of two [TextTheme]s.
+  TextTheme merge(TextTheme other) {
+    if (other == null)
+      return this;
+    return copyWith(
+      display4: display4?.merge(other.display4) ?? other.display4,
+      display3: display3?.merge(other.display3) ?? other.display3,
+      display2: display2?.merge(other.display2) ?? other.display2,
+      display1: display1?.merge(other.display1) ?? other.display1,
+      headline: headline?.merge(other.headline) ?? other.headline,
+      title: title?.merge(other.title) ?? other.title,
+      subhead: subhead?.merge(other.subhead) ?? other.subhead,
+      body2: body2?.merge(other.body2) ?? other.body2,
+      body1: body1?.merge(other.body1) ?? other.body1,
+      caption: caption?.merge(other.caption) ?? other.caption,
+      button: button?.merge(other.button) ?? other.button,
+      subtitle: subtitle?.merge(other.subtitle) ?? other.subtitle,
+      overline: overline?.merge(other.overline) ?? other.overline,
+    );
+  }
+
+  /// Creates a copy of this text theme but with the given field replaced in
+  /// each of the individual text styles.
+  ///
+  /// The `displayColor` is applied to [display4], [display3], [display2],
+  /// [display1], and [caption]. The `bodyColor` is applied to the remaining
+  /// text styles.
+  ///
+  /// Consider using [Typography.black] or [Typography.white], which implement
+  /// the typography styles in the material design specification, as a starting
+  /// point.
+  TextTheme apply({
+    String fontFamily,
+    double fontSizeFactor = 1.0,
+    double fontSizeDelta = 0.0,
+    Color displayColor,
+    Color bodyColor,
+    TextDecoration decoration,
+    Color decorationColor,
+    TextDecorationStyle decorationStyle,
+  }) {
+    return TextTheme(
+      display4: display4.apply(
+        color: displayColor,
+        decoration: decoration,
+        decorationColor: decorationColor,
+        decorationStyle: decorationStyle,
+        fontFamily: fontFamily,
+        fontSizeFactor: fontSizeFactor,
+        fontSizeDelta: fontSizeDelta,
+      ),
+      display3: display3.apply(
+        color: displayColor,
+        decoration: decoration,
+        decorationColor: decorationColor,
+        decorationStyle: decorationStyle,
+        fontFamily: fontFamily,
+        fontSizeFactor: fontSizeFactor,
+        fontSizeDelta: fontSizeDelta,
+      ),
+      display2: display2.apply(
+        color: displayColor,
+        decoration: decoration,
+        decorationColor: decorationColor,
+        decorationStyle: decorationStyle,
+        fontFamily: fontFamily,
+        fontSizeFactor: fontSizeFactor,
+        fontSizeDelta: fontSizeDelta,
+      ),
+      display1: display1.apply(
+        color: displayColor,
+        decoration: decoration,
+        decorationColor: decorationColor,
+        decorationStyle: decorationStyle,
+        fontFamily: fontFamily,
+        fontSizeFactor: fontSizeFactor,
+        fontSizeDelta: fontSizeDelta,
+      ),
+      headline: headline.apply(
+        color: displayColor,
+        decoration: decoration,
+        decorationColor: decorationColor,
+        decorationStyle: decorationStyle,
+        fontFamily: fontFamily,
+        fontSizeFactor: fontSizeFactor,
+        fontSizeDelta: fontSizeDelta,
+      ),
+      title: title.apply(
+        color: displayColor,
+        decoration: decoration,
+        decorationColor: decorationColor,
+        decorationStyle: decorationStyle,
+        fontFamily: fontFamily,
+        fontSizeFactor: fontSizeFactor,
+        fontSizeDelta: fontSizeDelta,
+      ),
+      subhead: subhead.apply(
+        color: displayColor,
+        decoration: decoration,
+        decorationColor: decorationColor,
+        decorationStyle: decorationStyle,
+        fontFamily: fontFamily,
+        fontSizeFactor: fontSizeFactor,
+        fontSizeDelta: fontSizeDelta,
+      ),
+      body2: body2.apply(
+        color: displayColor,
+        decoration: decoration,
+        decorationColor: decorationColor,
+        decorationStyle: decorationStyle,
+        fontFamily: fontFamily,
+        fontSizeFactor: fontSizeFactor,
+        fontSizeDelta: fontSizeDelta,
+      ),
+      body1: body1.apply(
+        color: displayColor,
+        decoration: decoration,
+        decorationColor: decorationColor,
+        decorationStyle: decorationStyle,
+        fontFamily: fontFamily,
+        fontSizeFactor: fontSizeFactor,
+        fontSizeDelta: fontSizeDelta,
+      ),
+      caption: caption.apply(
+        color: displayColor,
+        decoration: decoration,
+        decorationColor: decorationColor,
+        decorationStyle: decorationStyle,
+        fontFamily: fontFamily,
+        fontSizeFactor: fontSizeFactor,
+        fontSizeDelta: fontSizeDelta,
+      ),
+      button: button.apply(
+        color: bodyColor,
+        decoration: decoration,
+        decorationColor: decorationColor,
+        decorationStyle: decorationStyle,
+        fontFamily: fontFamily,
+        fontSizeFactor: fontSizeFactor,
+        fontSizeDelta: fontSizeDelta,
+      ),
+      subtitle: subtitle.apply(
+        color: bodyColor,
+        decoration: decoration,
+        decorationColor: decorationColor,
+        decorationStyle: decorationStyle,
+        fontFamily: fontFamily,
+        fontSizeFactor: fontSizeFactor,
+        fontSizeDelta: fontSizeDelta,
+      ),
+      overline: overline.apply(
+        color: bodyColor,
+        decoration: decoration,
+        decorationColor: decorationColor,
+        decorationStyle: decorationStyle,
+        fontFamily: fontFamily,
+        fontSizeFactor: fontSizeFactor,
+        fontSizeDelta: fontSizeDelta,
+      ),
+    );
+  }
+
+  /// Linearly interpolate between two text themes.
+  ///
+  /// The arguments must not be null.
+  ///
+  /// {@macro flutter.material.themeData.lerp}
+  static TextTheme lerp(TextTheme a, TextTheme b, double t) {
+    assert(a != null);
+    assert(b != null);
+    assert(t != null);
+    return TextTheme(
+      display4: TextStyle.lerp(a.display4, b.display4, t),
+      display3: TextStyle.lerp(a.display3, b.display3, t),
+      display2: TextStyle.lerp(a.display2, b.display2, t),
+      display1: TextStyle.lerp(a.display1, b.display1, t),
+      headline: TextStyle.lerp(a.headline, b.headline, t),
+      title: TextStyle.lerp(a.title, b.title, t),
+      subhead: TextStyle.lerp(a.subhead, b.subhead, t),
+      body2: TextStyle.lerp(a.body2, b.body2, t),
+      body1: TextStyle.lerp(a.body1, b.body1, t),
+      caption: TextStyle.lerp(a.caption, b.caption, t),
+      button: TextStyle.lerp(a.button, b.button, t),
+      subtitle: TextStyle.lerp(a.subtitle, b.subtitle, t),
+      overline: TextStyle.lerp(a.overline, b.overline, t),
+    );
+  }
+
+  @override
+  bool operator ==(dynamic other) {
+    if (identical(this, other))
+      return true;
+    if (other.runtimeType != runtimeType)
+      return false;
+    final TextTheme typedOther = other;
+    return display4 == typedOther.display4
+        && display3 == typedOther.display3
+        && display2 == typedOther.display2
+        && display1 == typedOther.display1
+        && headline == typedOther.headline
+        && title == typedOther.title
+        && subhead == typedOther.subhead
+        && body2 == typedOther.body2
+        && body1 == typedOther.body1
+        && caption == typedOther.caption
+        && button == typedOther.button
+        && subtitle == typedOther.subtitle
+        && overline == typedOther.overline;
+  }
+
+  @override
+  int get hashCode {
+    // The hashValues() function supports up to 20 arguments.
+    return hashValues(
+      display4,
+      display3,
+      display2,
+      display1,
+      headline,
+      title,
+      subhead,
+      body2,
+      body1,
+      caption,
+      button,
+      subtitle,
+      overline,
+    );
+  }
+
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+    super.debugFillProperties(properties);
+    final TextTheme defaultTheme = Typography(platform: defaultTargetPlatform).black;
+    properties.add(DiagnosticsProperty<TextStyle>('display4', display4, defaultValue: defaultTheme.display4));
+    properties.add(DiagnosticsProperty<TextStyle>('display3', display3, defaultValue: defaultTheme.display3));
+    properties.add(DiagnosticsProperty<TextStyle>('display2', display2, defaultValue: defaultTheme.display2));
+    properties.add(DiagnosticsProperty<TextStyle>('display1', display1, defaultValue: defaultTheme.display1));
+    properties.add(DiagnosticsProperty<TextStyle>('headline', headline, defaultValue: defaultTheme.headline));
+    properties.add(DiagnosticsProperty<TextStyle>('title', title, defaultValue: defaultTheme.title));
+    properties.add(DiagnosticsProperty<TextStyle>('subhead', subhead, defaultValue: defaultTheme.subhead));
+    properties.add(DiagnosticsProperty<TextStyle>('body2', body2, defaultValue: defaultTheme.body2));
+    properties.add(DiagnosticsProperty<TextStyle>('body1', body1, defaultValue: defaultTheme.body1));
+    properties.add(DiagnosticsProperty<TextStyle>('caption', caption, defaultValue: defaultTheme.caption));
+    properties.add(DiagnosticsProperty<TextStyle>('button', button, defaultValue: defaultTheme.button));
+    properties.add(DiagnosticsProperty<TextStyle>('subtitle)', subtitle, defaultValue: defaultTheme.subtitle));
+    properties.add(DiagnosticsProperty<TextStyle>('overline', overline, defaultValue: defaultTheme.overline));
+  }
+}
diff --git a/packages/flutter/lib/src/material/theme.dart b/packages/flutter/lib/src/material/theme.dart
index 081e5e9..dc52326 100644
--- a/packages/flutter/lib/src/material/theme.dart
+++ b/packages/flutter/lib/src/material/theme.dart
@@ -124,18 +124,17 @@
   /// }
   /// ```
   static ThemeData of(BuildContext context, { bool shadowThemeOnly = false }) {
-    final _InheritedTheme inheritedTheme =
-        context.inheritFromWidgetOfExactType(_InheritedTheme);
+    final _InheritedTheme inheritedTheme = context.inheritFromWidgetOfExactType(_InheritedTheme);
     if (shadowThemeOnly) {
       if (inheritedTheme == null || inheritedTheme.theme.isMaterialAppTheme)
         return null;
       return inheritedTheme.theme.data;
     }
 
-    final ThemeData colorTheme = (inheritedTheme != null) ? inheritedTheme.theme.data : _kFallbackTheme;
     final MaterialLocalizations localizations = MaterialLocalizations.of(context);
-    final TextTheme geometryTheme = localizations?.localTextGeometry ?? MaterialTextGeometry.englishLike;
-    return ThemeData.localize(colorTheme, geometryTheme);
+    final ScriptCategory category = localizations?.scriptCategory ?? ScriptCategory.englishLike;
+    final ThemeData theme = inheritedTheme?.theme?.data ?? _kFallbackTheme;
+    return ThemeData.localize(theme, theme.typography.geometryThemeFor(category));
   }
 
   @override
diff --git a/packages/flutter/lib/src/material/theme_data.dart b/packages/flutter/lib/src/material/theme_data.dart
index 5e4fb66..e6639e2 100644
--- a/packages/flutter/lib/src/material/theme_data.dart
+++ b/packages/flutter/lib/src/material/theme_data.dart
@@ -18,6 +18,7 @@
 import 'page_transitions_theme.dart';
 import 'slider_theme.dart';
 import 'tab_bar_theme.dart';
+import 'text_theme.dart';
 import 'typography.dart';
 
 export 'package:flutter/services.dart' show Brightness;
@@ -149,6 +150,7 @@
     MaterialTapTargetSize materialTapTargetSize,
     PageTransitionsTheme pageTransitionsTheme,
     ColorScheme colorScheme,
+    Typography typography,
   }) {
     brightness ??= Brightness.light;
     final bool isDark = brightness == Brightness.dark;
@@ -200,7 +202,7 @@
     accentIconTheme ??= accentIsDark ? const IconThemeData(color: Colors.white) : const IconThemeData(color: Colors.black);
     iconTheme ??= isDark ? const IconThemeData(color: Colors.white) : const IconThemeData(color: Colors.black87);
     platform ??= defaultTargetPlatform;
-    final Typography typography = Typography(platform: platform);
+    typography ??= Typography(platform: platform);
     final TextTheme defaultTextTheme = isDark ? typography.white : typography.black;
     textTheme = defaultTextTheme.merge(textTheme);
     final TextTheme defaultPrimaryTextTheme = primaryIsDark ? typography.white : typography.black;
@@ -287,6 +289,7 @@
       materialTapTargetSize: materialTapTargetSize,
       pageTransitionsTheme: pageTransitionsTheme,
       colorScheme: colorScheme,
+      typography: typography,
     );
   }
 
@@ -344,6 +347,7 @@
     @required this.materialTapTargetSize,
     @required this.pageTransitionsTheme,
     @required this.colorScheme,
+    @required this.typography,
   }) : assert(brightness != null),
        assert(primaryColor != null),
        assert(primaryColorBrightness != null),
@@ -386,7 +390,8 @@
        assert(platform != null),
        assert(materialTapTargetSize != null),
        assert(pageTransitionsTheme != null),
-       assert(colorScheme != null);
+       assert(colorScheme != null),
+       assert(typography != null);
 
   // Warning: make sure these properties are in the exact same order as in
   // hashValues() and in the raw constructor and in the order of fields in
@@ -612,6 +617,10 @@
   /// that is possible without significant backwards compatibility breaks.
   final ColorScheme colorScheme;
 
+  /// The color and geometry [TextTheme] values used to configure [textTheme],
+  /// [primaryTextTheme], and [accentTextTheme].
+  final Typography typography;
+
   /// Creates a copy of this theme but with the given fields replaced with the new values.
   ThemeData copyWith({
     Brightness brightness,
@@ -658,6 +667,7 @@
     MaterialTapTargetSize materialTapTargetSize,
     PageTransitionsTheme pageTransitionsTheme,
     ColorScheme colorScheme,
+    Typography typography,
   }) {
     return ThemeData.raw(
       brightness: brightness ?? this.brightness,
@@ -704,6 +714,7 @@
       materialTapTargetSize: materialTapTargetSize ?? this.materialTapTargetSize,
       pageTransitionsTheme: pageTransitionsTheme ?? this.pageTransitionsTheme,
       colorScheme: colorScheme ?? this.colorScheme,
+      typography: typography ?? this.typography,
     );
   }
 
@@ -829,6 +840,7 @@
       materialTapTargetSize: t < 0.5 ? a.materialTapTargetSize : b.materialTapTargetSize,
       pageTransitionsTheme: t < 0.5 ? a.pageTransitionsTheme : b.pageTransitionsTheme,
       colorScheme: ColorScheme.lerp(a.colorScheme, b.colorScheme, t),
+      typography: Typography.lerp(a.typography, b.typography, t),
     );
   }
 
@@ -883,7 +895,8 @@
            (otherData.platform == platform) &&
            (otherData.materialTapTargetSize == materialTapTargetSize) &&
            (otherData.pageTransitionsTheme == pageTransitionsTheme) &&
-           (otherData.colorScheme == colorScheme);
+           (otherData.colorScheme == colorScheme) &&
+           (otherData.typography == typography);
   }
 
   @override
@@ -939,6 +952,7 @@
           materialTapTargetSize,
           pageTransitionsTheme,
           colorScheme,
+          typography,
         ),
       ),
     );
@@ -989,6 +1003,7 @@
     properties.add(DiagnosticsProperty<MaterialTapTargetSize>('materialTapTargetSize', materialTapTargetSize));
     properties.add(DiagnosticsProperty<PageTransitionsTheme>('pageTransitionsTheme', pageTransitionsTheme));
     properties.add(DiagnosticsProperty<ColorScheme>('colorScheme', colorScheme, defaultValue: defaultData.colorScheme));
+    properties.add(DiagnosticsProperty<Typography>('typography', typography, defaultValue: defaultData.typography));
   }
 }
 
diff --git a/packages/flutter/lib/src/material/time_picker.dart b/packages/flutter/lib/src/material/time_picker.dart
index 67334fb..22bd849 100644
--- a/packages/flutter/lib/src/material/time_picker.dart
+++ b/packages/flutter/lib/src/material/time_picker.dart
@@ -16,10 +16,10 @@
 import 'feedback.dart';
 import 'flat_button.dart';
 import 'material_localizations.dart';
+import 'text_theme.dart';
 import 'theme.dart';
 import 'theme_data.dart';
 import 'time.dart';
-import 'typography.dart';
 
 const Duration _kDialAnimateDuration = Duration(milliseconds: 200);
 const double _kTwoPi = 2 * math.pi;
diff --git a/packages/flutter/lib/src/material/typography.dart b/packages/flutter/lib/src/material/typography.dart
index e10a44a..baa49d9 100644
--- a/packages/flutter/lib/src/material/typography.dart
+++ b/packages/flutter/lib/src/material/typography.dart
@@ -6,623 +6,447 @@
 import 'package:flutter/painting.dart';
 
 import 'colors.dart';
+import 'text_theme.dart';
 
+/// A characterization of the of a [TextTheme]'s glyphs that is used to define
+/// its localized [TextStyle] geometry for [ThemeData.textTheme].
+///
+/// The script category defines the overall geometry of a [TextTheme] for
+/// the static [MaterialTextGeometry.localizedFor] method in terms of the
+/// three language categories defined in <https://material.io/go/design-typography>.
+///
+/// Generally speaking, font sizes for [ScriptCategory.tall] and
+/// [ScriptCategory.dense] scripts - for text styles that are smaller than the
+/// title style - are one unit larger than they are for
+/// [ScriptCategory.englishLike] scripts.
+enum ScriptCategory {
+  /// The languages of Western, Central, and Eastern Europe and much of
+  /// Africa are typically written in the Latin alphabet. Vietnamese is a
+  /// notable exception in that, while it uses a localized form of the Latin
+  /// writing system, its accented glyphs can be much taller than those
+  /// found in Western European languages. The Greek and Cyrillic writing
+  /// systems are very similar to Latin.
+  englishLike,
 
+  /// Language scripts that require extra line height to accommodate larger
+  /// glyphs, including Chinese, Japanese, and Korean.
+  dense,
 
-/// Material design text theme.
+  /// Language scripts that require extra line height to accommodate
+  /// larger glyphs, including South and Southeast Asian and
+  /// Middle-Eastern languages, like Arabic, Hindi, Telugu, Thai, and
+  /// Vietnamese.
+  tall,
+}
+
+/// The color and geometry [TextThemes] for Material apps.
 ///
-/// Definitions for the various typographical styles found in material design
-/// (e.g., headline, caption). Rather than creating a [TextTheme] directly,
-/// you can obtain an instance as [Typography.black] or [Typography.white].
+/// The text themes provided by the overall [Theme], like
+/// [ThemeData.textTheme], are based on the current locale's
+/// [MaterialLocalizations.scriptCategory] and are created
+/// by merging a color text theme, [black] or [white]
+/// and a geometry text theme, one of [englishLike], [dense],
+/// or [tall], depending on the locale.
 ///
-/// To obtain the current text theme, call [Theme.of] with the current
-/// [BuildContext] and read the [ThemeData.textTheme] property.
+/// To lookup a localized text theme use
+/// `Theme.of(context).textTheme` or
+/// `Theme.of(context).primaryTextTheme` or
+/// `Theme.of(context).accentTextTheme`.
 ///
-/// The following image [from the material design
-/// specification](https://material.io/go/design-typography#typography-styles)
-/// shows the recommended styles for each of the properties of a [TextTheme].
-/// This image uses the `Roboto` font, which is the font used on Android. On
-/// iOS, the [San Francisco
-/// font](https://developer.apple.com/ios/human-interface-guidelines/visual-design/typography/)
-/// is automatically used instead.
+/// The color text themes are [blackMountainView],
+/// [whiteMountainView], and [blackCupertino] and [whiteCupertino]. The
+/// Mountain View theme [TextStyles] are based on the Roboto fonts and the
+/// Cupertino themes are based on the San Francisco fonts.
 ///
-/// ![To see the image, visit the typography site referenced below.](https://storage.googleapis.com/material-design/publish/material_v_11/assets/0Bzhp5Z4wHba3alhXZ2pPWGk3Zjg/style_typography_styles_scale.png)
+/// Two sets of geometry themes are provided: 2014 and 2018. The 2014 themes
+/// correspond to the original version of the Material Design spec and are
+/// the defaults. The 2018 themes correspond the second iteration of the
+/// specification and feature different font sizes, font weights, and
+/// letter spacing values.
+///
+/// By default, [ThemeData.typography] is
+/// `Typography(platform: platform)` which uses [englishLike2014],
+/// [dense2014] and [tall2014]. To use the 2018 text theme
+/// geometries, specify a typography value:
+/// ```
+/// Typography(
+///   platorm: platform,
+///   englishLike: Typography.englishLike2018,
+///   dense: Typography.dense2018,
+///   tall: Typography.tall2018,
+/// )
+/// ```
 ///
 /// See also:
 ///
-///  * [Typography], the class that generates [TextTheme]s appropriate for a platform.
-///  * [Theme], for other aspects of a material design application that can be
-///    globally adjusted, such as the color scheme.
-///  * <http://material.google.com/style/typography.html>
+///  * [ThemeData.typography], which can be used to configure the
+///    text themes used to create [ThemeData.textTheme],
+///    [ThemeData.primaryTextTheme], [ThemeData.accentTextTheme].
+///  * <https://material.io/design/typography/>
 @immutable
-class TextTheme extends Diagnosticable {
-  /// Creates a text theme that uses the given values.
+class Typography extends Diagnosticable {
+  /// Creates a typography instance.
   ///
-  /// Rather than creating a new text theme, consider using [Typography.black]
-  /// or [Typography.white], which implement the typography styles in the
-  /// material design specification:
+  /// If [platform] is specified, the default values for [black] and [white]
+  /// are [blackCupertino] and [whiteCupertino] respectively. Otherwise
+  /// they are [blackMountainView] and [whiteMoutainView].
   ///
-  /// <https://material.google.com/style/typography.html#typography-styles>
-  ///
-  /// If you do decide to create your own text theme, consider using one of
-  /// those predefined themes as a starting point for [copyWith] or [apply].
-  const TextTheme({
-    this.display4,
-    this.display3,
-    this.display2,
-    this.display1,
-    this.headline,
-    this.title,
-    this.subhead,
-    this.body2,
-    this.body1,
-    this.caption,
-    this.button,
-  });
-
-  /// Extremely large text.
-  ///
-  /// The font size is 112 pixels.
-  final TextStyle display4;
-
-  /// Very, very large text.
-  ///
-  /// Used for the date in the dialog shown by [showDatePicker].
-  final TextStyle display3;
-
-  /// Very large text.
-  final TextStyle display2;
-
-  /// Large text.
-  final TextStyle display1;
-
-  /// Used for large text in dialogs (e.g., the month and year in the dialog
-  /// shown by [showDatePicker]).
-  final TextStyle headline;
-
-  /// Used for the primary text in app bars and dialogs (e.g., [AppBar.title]
-  /// and [AlertDialog.title]).
-  final TextStyle title;
-
-  /// Used for the primary text in lists (e.g., [ListTile.title]).
-  final TextStyle subhead;
-
-  /// Used for emphasizing text that would otherwise be [body1].
-  final TextStyle body2;
-
-  /// Used for the default text style for [Material].
-  final TextStyle body1;
-
-  /// Used for auxiliary text associated with images.
-  final TextStyle caption;
-
-  /// Used for text on [RaisedButton] and [FlatButton].
-  final TextStyle button;
-
-  /// Creates a copy of this text theme but with the given fields replaced with
-  /// the new values.
-  ///
-  /// Consider using [Typography.black] or [Typography.white], which implement
-  /// the typography styles in the material design specification, as a starting
-  /// point.
-  ///
-  /// ## Sample code
-  ///
-  /// ```dart
-  /// /// A Widget that sets the ambient theme's title text color for its
-  /// /// descendants, while leaving other ambient theme attributes alone.
-  /// class TitleColorThemeCopy extends StatelessWidget {
-  ///   TitleColorThemeCopy({Key key, this.child, this.titleColor}) : super(key: key);
-  ///
-  ///   final Color titleColor;
-  ///   final Widget child;
-  ///
-  ///   @override
-  ///   Widget build(BuildContext context) {
-  ///     final ThemeData theme = Theme.of(context);
-  ///     return Theme(
-  ///       data: theme.copyWith(
-  ///         textTheme: theme.textTheme.copyWith(
-  ///           title: theme.textTheme.title.copyWith(
-  ///             color: titleColor,
-  ///           ),
-  ///         ),
-  ///       ),
-  ///       child: child,
-  ///     );
-  ///   }
-  /// }
-  /// ```
-  ///
-  /// See also:
-  ///
-  ///   * [merge] is used instead of [copyWith] when you want to merge all
-  ///     of the fields of a TextTheme instead of individual fields.
-  TextTheme copyWith({
-    TextStyle display4,
-    TextStyle display3,
-    TextStyle display2,
-    TextStyle display1,
-    TextStyle headline,
-    TextStyle title,
-    TextStyle subhead,
-    TextStyle body2,
-    TextStyle body1,
-    TextStyle caption,
-    TextStyle button,
+  /// The default values for [englishLike], [dense], and [tall] are
+  /// [englishLike2014], [dense2014], and [tall2014].
+  factory Typography({
+    TargetPlatform platform,
+    TextTheme black,
+    TextTheme white,
+    TextTheme englishLike,
+    TextTheme dense,
+    TextTheme tall,
   }) {
-    return TextTheme(
-      display4: display4 ?? this.display4,
-      display3: display3 ?? this.display3,
-      display2: display2 ?? this.display2,
-      display1: display1 ?? this.display1,
-      headline: headline ?? this.headline,
-      title: title ?? this.title,
-      subhead: subhead ?? this.subhead,
-      body2: body2 ?? this.body2,
-      body1: body1 ?? this.body1,
-      caption: caption ?? this.caption,
-      button: button ?? this.button,
-    );
+    switch (platform) {
+      case TargetPlatform.iOS:
+        black ??= blackCupertino;
+        white ??= whiteCupertino;
+        break;
+      case TargetPlatform.android:
+      case TargetPlatform.fuchsia:
+        black ??= blackMountainView;
+        white ??= whiteMountainView;
+    }
+    englishLike ??= englishLike2014;
+    dense ??= dense2014;
+    tall ??= tall2014;
+    return Typography._(black, white, englishLike, dense, tall);
   }
 
-  /// Creates a new [TextTheme] where each text style from this object has been
-  /// merged with the matching text style from the `other` object.
+  const Typography._(this.black, this.white, this.englishLike, this.dense, this.tall)
+    : assert(black != null),
+      assert(white != null),
+      assert(englishLike != null),
+      assert(dense != null),
+      assert(tall != null);
+
+  /// A material design text theme with dark glyphs.
   ///
-  /// The merging is done by calling [TextStyle.merge] on each respective pair
-  /// of text styles from this and the [other] text themes and is subject to
-  /// the value of [TextStyle.inherit] flag. For more details, see the
-  /// documentation on [TextStyle.merge] and [TextStyle.inherit].
+  /// This [TextTheme] should provide color but not geometry (font size,
+  /// weight, etc). A text theme's geometry depends on the locale. To look
+  /// up a localized [TextTheme], use the the overall [Theme], for example:
+  /// `Theme.of(context).textTheme`.
   ///
-  /// If this theme, or the `other` theme has members that are null, then the
-  /// non-null one (if any) is used. If the `other` theme is itself null, then
-  /// this [TextTheme] is returned unchanged. If values in both are set, then
-  /// the values are merged using [TextStyle.merge].
+  /// The [englishLike], [dense], and [tall] text theme's provide locale-specific
+  /// geometry.
+  final TextTheme black;
+
+  /// A material design text theme with light glyphs.
   ///
-  /// This is particularly useful if one [TextTheme] defines one set of
-  /// properties and another defines a different set, e.g. having colors
-  /// defined in one text theme and font sizes in another, or when one
-  /// [TextTheme] has only some fields defined, and you want to define the rest
-  /// by merging it with a default theme.
+  /// This [TextTheme] provides color but not geometry (font size, weight, etc).
+  /// A text theme's geometry depends on the locale. To look up a localized
+  /// [TextTheme], use the the overall [Theme], for example:
+  /// `Theme.of(context).textTheme`.
   ///
-  /// ## Sample code
+  /// The [englishLike], [dense], and [tall] text theme's provide locale-specific
+  /// geometry.
+  final TextTheme white;
+
+  /// Defines text geometry for [ScriptCategory.englishLike] scripts, such as
+  /// English, French, Russian, etc.
   ///
-  /// ```dart
-  /// /// A Widget that sets the ambient theme's title text color for its
-  /// /// descendants, while leaving other ambient theme attributes alone.
-  /// class TitleColorTheme extends StatelessWidget {
-  ///   TitleColorTheme({Key key, this.child, this.titleColor}) : super(key: key);
+  /// This text theme is merged with either [black] or [white], depending
+  /// on the overall [ThemeData.brightness], when the current locale's
+  /// [MaterialLocalizations.scriptCategory] is [ScriptCategory.englishLike].
   ///
-  ///   final Color titleColor;
-  ///   final Widget child;
+  /// To look up a localized [TextTheme], use the the overall [Theme], for
+  /// example: `Theme.of(context).textTheme`.
+  final TextTheme englishLike;
+
+  /// Defines text geometry for dense scripts, such as Chinese, Japanese
+  /// and Korean.
   ///
-  ///   @override
-  ///   Widget build(BuildContext context) {
-  ///     ThemeData theme = Theme.of(context);
-  ///     // This partialTheme is incomplete: it only has the title style
-  ///     // defined. Just replacing theme.textTheme with partialTheme would
-  ///     // set the title, but everything else would be null. This isn't very
-  ///     // useful, so merge it with the existing theme to keep all of the
-  ///     // preexisting definitions for the other styles.
-  ///     TextTheme partialTheme = TextTheme(title: TextStyle(color: titleColor));
-  ///     theme = theme.copyWith(textTheme: theme.textTheme.merge(partialTheme));
-  ///     return Theme(data: theme, child: child);
-  ///   }
-  /// }
-  /// ```
+  /// This text theme is merged with either [black] or [white], depending
+  /// on the overall [ThemeData.brightness], when the current locale's
+  /// [MaterialLocalizations.scriptCategory] is [ScriptCategory.dense].
   ///
-  /// See also:
+  /// To look up a localized [TextTheme], use the the overall [Theme], for
+  /// example: `Theme.of(context).textTheme`.
+  final TextTheme dense;
+
+  /// Defines text geometry for tall scripts, such as Farsi, Hindi, and Thai.
   ///
-  ///   * [copyWith] is used instead of [merge] when you wish to override
-  ///     individual fields in the [TextTheme] instead of merging all of the
-  ///     fields of two [TextTheme]s.
-  TextTheme merge(TextTheme other) {
-    if (other == null)
-      return this;
-    return copyWith(
-      display4: display4?.merge(other.display4) ?? other.display4,
-      display3: display3?.merge(other.display3) ?? other.display3,
-      display2: display2?.merge(other.display2) ?? other.display2,
-      display1: display1?.merge(other.display1) ?? other.display1,
-      headline: headline?.merge(other.headline) ?? other.headline,
-      title: title?.merge(other.title) ?? other.title,
-      subhead: subhead?.merge(other.subhead) ?? other.subhead,
-      body2: body2?.merge(other.body2) ?? other.body2,
-      body1: body1?.merge(other.body1) ?? other.body1,
-      caption: caption?.merge(other.caption) ?? other.caption,
-      button: button?.merge(other.button) ?? other.button,
-    );
+  /// This text theme is merged with either [black] or [white], depending
+  /// on the overall [ThemeData.brightness], when the current locale's
+  /// [MaterialLocalizations.scriptCategory] is [ScriptCategory.tall].
+  ///
+  /// To look up a localized [TextTheme], use the the overall [Theme], for
+  /// example: `Theme.of(context).textTheme`.
+  final TextTheme tall;
+
+  /// Returns one of [englishLike], [dense], or [tall].
+  TextTheme geometryThemeFor(ScriptCategory category) {
+    assert(category != null);
+    switch (category) {
+      case ScriptCategory.englishLike:
+        return englishLike;
+      case ScriptCategory.dense:
+        return dense;
+      case ScriptCategory.tall:
+        return tall;
+    }
+    return null;
   }
 
-  /// Creates a copy of this text theme but with the given field replaced in
-  /// each of the individual text styles.
-  ///
-  /// The `displayColor` is applied to [display4], [display3], [display2],
-  /// [display1], and [caption]. The `bodyColor` is applied to the remaining
-  /// text styles.
-  ///
-  /// Consider using [Typography.black] or [Typography.white], which implement
-  /// the typography styles in the material design specification, as a starting
-  /// point.
-  TextTheme apply({
-    String fontFamily,
-    double fontSizeFactor = 1.0,
-    double fontSizeDelta = 0.0,
-    Color displayColor,
-    Color bodyColor,
-    TextDecoration decoration,
-    Color decorationColor,
-    TextDecorationStyle decorationStyle,
+  /// Creates a copy of this [Typography] with the given fields
+  /// replaced by the non-null parameter values.
+  Typography copyWith({
+    TextTheme black,
+    TextTheme white,
+    TextTheme englishLike,
+    TextTheme dense,
+    TextTheme tall,
   }) {
-    return TextTheme(
-      display4: display4.apply(
-        color: displayColor,
-        decoration: decoration,
-        decorationColor: decorationColor,
-        decorationStyle: decorationStyle,
-        fontFamily: fontFamily,
-        fontSizeFactor: fontSizeFactor,
-        fontSizeDelta: fontSizeDelta,
-      ),
-      display3: display3.apply(
-        color: displayColor,
-        decoration: decoration,
-        decorationColor: decorationColor,
-        decorationStyle: decorationStyle,
-        fontFamily: fontFamily,
-        fontSizeFactor: fontSizeFactor,
-        fontSizeDelta: fontSizeDelta,
-      ),
-      display2: display2.apply(
-        color: displayColor,
-        decoration: decoration,
-        decorationColor: decorationColor,
-        decorationStyle: decorationStyle,
-        fontFamily: fontFamily,
-        fontSizeFactor: fontSizeFactor,
-        fontSizeDelta: fontSizeDelta,
-      ),
-      display1: display1.apply(
-        color: displayColor,
-        decoration: decoration,
-        decorationColor: decorationColor,
-        decorationStyle: decorationStyle,
-        fontFamily: fontFamily,
-        fontSizeFactor: fontSizeFactor,
-        fontSizeDelta: fontSizeDelta,
-      ),
-      headline: headline.apply(
-        color: bodyColor,
-        decoration: decoration,
-        decorationColor: decorationColor,
-        decorationStyle: decorationStyle,
-        fontFamily: fontFamily,
-        fontSizeFactor: fontSizeFactor,
-        fontSizeDelta: fontSizeDelta,
-      ),
-      title: title.apply(
-        color: bodyColor,
-        decoration: decoration,
-        decorationColor: decorationColor,
-        decorationStyle: decorationStyle,
-        fontFamily: fontFamily,
-        fontSizeFactor: fontSizeFactor,
-        fontSizeDelta: fontSizeDelta,
-      ),
-      subhead: subhead.apply(
-        color: bodyColor,
-        decoration: decoration,
-        decorationColor: decorationColor,
-        decorationStyle: decorationStyle,
-        fontFamily: fontFamily,
-        fontSizeFactor: fontSizeFactor,
-        fontSizeDelta: fontSizeDelta,
-      ),
-      body2: body2.apply(
-        color: bodyColor,
-        decoration: decoration,
-        decorationColor: decorationColor,
-        decorationStyle: decorationStyle,
-        fontFamily: fontFamily,
-        fontSizeFactor: fontSizeFactor,
-        fontSizeDelta: fontSizeDelta,
-      ),
-      body1: body1.apply(
-        color: bodyColor,
-        decoration: decoration,
-        decorationColor: decorationColor,
-        decorationStyle: decorationStyle,
-        fontFamily: fontFamily,
-        fontSizeFactor: fontSizeFactor,
-        fontSizeDelta: fontSizeDelta,
-      ),
-      caption: caption.apply(
-        color: displayColor,
-        decoration: decoration,
-        decorationColor: decorationColor,
-        decorationStyle: decorationStyle,
-        fontFamily: fontFamily,
-        fontSizeFactor: fontSizeFactor,
-        fontSizeDelta: fontSizeDelta,
-      ),
-      button: button.apply(
-        color: bodyColor,
-        decoration: decoration,
-        decorationColor: decorationColor,
-        decorationStyle: decorationStyle,
-        fontFamily: fontFamily,
-        fontSizeFactor: fontSizeFactor,
-        fontSizeDelta: fontSizeDelta,
-      ),
+    return Typography(
+      black: black ?? this.black,
+      white: white ?? this.white,
+      englishLike: englishLike ?? this.englishLike,
+      dense: dense ?? this.dense,
+      tall: tall ?? this.tall,
     );
   }
 
-  /// Linearly interpolate between two text themes.
-  ///
-  /// The arguments must not be null.
+  /// Linearly interpolate between two [Typography] objects.
   ///
   /// {@macro flutter.painting.gradient.lerp}
-  static TextTheme lerp(TextTheme a, TextTheme b, double t) {
-    assert(a != null);
-    assert(b != null);
-    assert(t != null);
-    return TextTheme(
-      display4: TextStyle.lerp(a.display4, b.display4, t),
-      display3: TextStyle.lerp(a.display3, b.display3, t),
-      display2: TextStyle.lerp(a.display2, b.display2, t),
-      display1: TextStyle.lerp(a.display1, b.display1, t),
-      headline: TextStyle.lerp(a.headline, b.headline, t),
-      title: TextStyle.lerp(a.title, b.title, t),
-      subhead: TextStyle.lerp(a.subhead, b.subhead, t),
-      body2: TextStyle.lerp(a.body2, b.body2, t),
-      body1: TextStyle.lerp(a.body1, b.body1, t),
-      caption: TextStyle.lerp(a.caption, b.caption, t),
-      button: TextStyle.lerp(a.button, b.button, t),
+  static Typography lerp(Typography a, Typography b, double t) {
+    return Typography(
+      black: TextTheme.lerp(a.black, b.black, t),
+      white: TextTheme.lerp(a.white, b.white, t),
+      englishLike: TextTheme.lerp(a.englishLike, b.englishLike, t),
+      dense: TextTheme.lerp(a.dense, b.dense, t),
+      tall: TextTheme.lerp(a.tall, b.tall, t),
     );
   }
 
   @override
-  bool operator ==(dynamic other) {
+  bool operator ==(Object other) {
     if (identical(this, other))
       return true;
     if (other.runtimeType != runtimeType)
       return false;
-    final TextTheme typedOther = other;
-    return display4 == typedOther.display4 &&
-           display3 == typedOther.display3 &&
-           display2 == typedOther.display2 &&
-           display1 == typedOther.display1 &&
-           headline == typedOther.headline &&
-           title == typedOther.title &&
-           subhead == typedOther.subhead &&
-           body2 == typedOther.body2 &&
-           body1 == typedOther.body1 &&
-           caption == typedOther.caption &&
-           button == typedOther.button;
+    final Typography otherTypography = other;
+    return otherTypography.black == black
+        && otherTypography.white == white
+        && otherTypography.englishLike == englishLike
+        && otherTypography.dense == dense
+        && otherTypography.tall == tall;
   }
 
   @override
   int get hashCode {
     return hashValues(
-      display4,
-      display3,
-      display2,
-      display1,
-      headline,
-      title,
-      subhead,
-      body2,
-      body1,
-      caption,
-      button,
+      black,
+      white,
+      englishLike,
+      dense,
+      tall,
     );
   }
 
   @override
   void debugFillProperties(DiagnosticPropertiesBuilder properties) {
     super.debugFillProperties(properties);
-    final TextTheme defaultTheme = Typography(platform: defaultTargetPlatform).black;
-    properties.add(DiagnosticsProperty<TextStyle>('display4', display4, defaultValue: defaultTheme.display4));
-    properties.add(DiagnosticsProperty<TextStyle>('display3', display3, defaultValue: defaultTheme.display3));
-    properties.add(DiagnosticsProperty<TextStyle>('display2', display2, defaultValue: defaultTheme.display2));
-    properties.add(DiagnosticsProperty<TextStyle>('display1', display1, defaultValue: defaultTheme.display1));
-    properties.add(DiagnosticsProperty<TextStyle>('headline', headline, defaultValue: defaultTheme.headline));
-    properties.add(DiagnosticsProperty<TextStyle>('title', title, defaultValue: defaultTheme.title));
-    properties.add(DiagnosticsProperty<TextStyle>('subhead', subhead, defaultValue: defaultTheme.subhead));
-    properties.add(DiagnosticsProperty<TextStyle>('body2', body2, defaultValue: defaultTheme.body2));
-    properties.add(DiagnosticsProperty<TextStyle>('body1', body1, defaultValue: defaultTheme.body1));
-    properties.add(DiagnosticsProperty<TextStyle>('caption', caption, defaultValue: defaultTheme.caption));
-    properties.add(DiagnosticsProperty<TextStyle>('button', button, defaultValue: defaultTheme.button));
-  }
-}
-
-/// The two material design text themes.
-///
-/// Material design defines two text themes: [black] and [white]. The black
-/// text theme, which uses dark glyphs, is used on light backgrounds in light
-/// themes. The white text theme, which uses light glyphs, is used in dark
-/// themes and on dark backgrounds in light themes.
-///
-/// To obtain the current text theme, call [Theme.of] with the current
-/// [BuildContext] and read the [ThemeData.textTheme] property.
-///
-/// See also:
-///
-///  * [TextTheme], which shows what the text styles in a theme look like.
-///  * [Theme], for other aspects of a material design application that can be
-///    globally adjusted, such as the color scheme.
-///  * <http://material.google.com/style/typography.html>
-class Typography {
-  /// Creates the default typography for the specified platform.
-  factory Typography({@required TargetPlatform platform}) {
-    assert(platform != null);
-    switch (platform) {
-      case TargetPlatform.android:
-      case TargetPlatform.fuchsia:
-        return const Typography._(
-          _MaterialTextColorThemes.blackMountainView,
-          _MaterialTextColorThemes.whiteMountainView,
-        );
-      case TargetPlatform.iOS:
-        return const Typography._(
-          _MaterialTextColorThemes.blackCupertino,
-          _MaterialTextColorThemes.whiteCupertino,
-        );
-    }
-    return null;
+    final Typography defaultTypography = Typography();
+    properties.add(DiagnosticsProperty<TextTheme>('black', black, defaultValue: defaultTypography.black));
+    properties.add(DiagnosticsProperty<TextTheme>('white', white, defaultValue: defaultTypography.white));
+    properties.add(DiagnosticsProperty<TextTheme>('englishLike', englishLike, defaultValue: defaultTypography.englishLike));
+    properties.add(DiagnosticsProperty<TextTheme>('dense', dense, defaultValue: defaultTypography.dense));
+    properties.add(DiagnosticsProperty<TextTheme>('tall', tall, defaultValue: defaultTypography.tall));
   }
 
-  const Typography._(this.black, this.white);
-
-  /// A material design text theme with dark glyphs.
-  final TextTheme black;
-
-  /// A material design text theme with light glyphs.
-  final TextTheme white;
-}
-
-/// Provides default text theme colors compliant with the Material Design
-/// specification.
-///
-/// The geometric font properties are missing in these color themes. App are
-/// expected to use [Theme.of] to get [TextTheme] objects fully populated with
-/// font properties.
-///
-/// See also: https://material.io/go/design-typography
-// TODO(yjbanov): implement font fallback (see "Font stack" at https://material.io/go/design-typography)
-class _MaterialTextColorThemes {
+  /// A material design text theme with dark glyphs based on Roboto.
+  ///
+  /// This [TextTheme] provides color but not geometry (font size, weight, etc).
   static const TextTheme blackMountainView = TextTheme(
-    display4: TextStyle(debugLabel: 'blackMountainView display4', fontFamily: 'Roboto',         inherit: true, color: Colors.black54, decoration: TextDecoration.none),
-    display3: TextStyle(debugLabel: 'blackMountainView display3', fontFamily: 'Roboto',         inherit: true, color: Colors.black54, decoration: TextDecoration.none),
-    display2: TextStyle(debugLabel: 'blackMountainView display2', fontFamily: 'Roboto',         inherit: true, color: Colors.black54, decoration: TextDecoration.none),
-    display1: TextStyle(debugLabel: 'blackMountainView display1', fontFamily: 'Roboto',         inherit: true, color: Colors.black54, decoration: TextDecoration.none),
-    headline: TextStyle(debugLabel: 'blackMountainView headline', fontFamily: 'Roboto',         inherit: true, color: Colors.black87, decoration: TextDecoration.none),
-    title   : TextStyle(debugLabel: 'blackMountainView title',    fontFamily: 'Roboto',         inherit: true, color: Colors.black87, decoration: TextDecoration.none),
-    subhead : TextStyle(debugLabel: 'blackMountainView subhead',  fontFamily: 'Roboto',         inherit: true, color: Colors.black87, decoration: TextDecoration.none),
-    body2   : TextStyle(debugLabel: 'blackMountainView body2',    fontFamily: 'Roboto',         inherit: true, color: Colors.black87, decoration: TextDecoration.none),
-    body1   : TextStyle(debugLabel: 'blackMountainView body1',    fontFamily: 'Roboto',         inherit: true, color: Colors.black87, decoration: TextDecoration.none),
-    caption : TextStyle(debugLabel: 'blackMountainView caption',  fontFamily: 'Roboto',         inherit: true, color: Colors.black54, decoration: TextDecoration.none),
-    button  : TextStyle(debugLabel: 'blackMountainView button',   fontFamily: 'Roboto',         inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    display4   : TextStyle(debugLabel: 'blackMountainView display4',   fontFamily: 'Roboto', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
+    display3   : TextStyle(debugLabel: 'blackMountainView display3',   fontFamily: 'Roboto', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
+    display2   : TextStyle(debugLabel: 'blackMountainView display2',   fontFamily: 'Roboto', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
+    display1   : TextStyle(debugLabel: 'blackMountainView display1',   fontFamily: 'Roboto', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
+    headline   : TextStyle(debugLabel: 'blackMountainView headline',   fontFamily: 'Roboto', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    title      : TextStyle(debugLabel: 'blackMountainView title',      fontFamily: 'Roboto', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    subhead    : TextStyle(debugLabel: 'blackMountainView subhead',    fontFamily: 'Roboto', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    body2      : TextStyle(debugLabel: 'blackMountainView body2',      fontFamily: 'Roboto', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    body1      : TextStyle(debugLabel: 'blackMountainView body1',      fontFamily: 'Roboto', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    caption    : TextStyle(debugLabel: 'blackMountainView caption',    fontFamily: 'Roboto', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
+    button     : TextStyle(debugLabel: 'blackMountainView button',     fontFamily: 'Roboto', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    subtitle   : TextStyle(debugLabel: 'blackMountainView subtitle',   fontFamily: 'Roboto', inherit: true, color: Colors.black,   decoration: TextDecoration.none),
+    overline   : TextStyle(debugLabel: 'blackMountainView overline',   fontFamily: 'Roboto', inherit: true, color: Colors.black,   decoration: TextDecoration.none),
   );
 
+  /// A material design text theme with light glyphs based on Roboto.
+  ///
+  /// This [TextTheme] provides color but not geometry (font size, weight, etc).
   static const TextTheme whiteMountainView = TextTheme(
-    display4: TextStyle(debugLabel: 'whiteMountainView display4', fontFamily: 'Roboto',         inherit: true, color: Colors.white70, decoration: TextDecoration.none),
-    display3: TextStyle(debugLabel: 'whiteMountainView display3', fontFamily: 'Roboto',         inherit: true, color: Colors.white70, decoration: TextDecoration.none),
-    display2: TextStyle(debugLabel: 'whiteMountainView display2', fontFamily: 'Roboto',         inherit: true, color: Colors.white70, decoration: TextDecoration.none),
-    display1: TextStyle(debugLabel: 'whiteMountainView display1', fontFamily: 'Roboto',         inherit: true, color: Colors.white70, decoration: TextDecoration.none),
-    headline: TextStyle(debugLabel: 'whiteMountainView headline', fontFamily: 'Roboto',         inherit: true, color: Colors.white,   decoration: TextDecoration.none),
-    title   : TextStyle(debugLabel: 'whiteMountainView title',    fontFamily: 'Roboto',         inherit: true, color: Colors.white,   decoration: TextDecoration.none),
-    subhead : TextStyle(debugLabel: 'whiteMountainView subhead',  fontFamily: 'Roboto',         inherit: true, color: Colors.white,   decoration: TextDecoration.none),
-    body2   : TextStyle(debugLabel: 'whiteMountainView body2',    fontFamily: 'Roboto',         inherit: true, color: Colors.white,   decoration: TextDecoration.none),
-    body1   : TextStyle(debugLabel: 'whiteMountainView body1',    fontFamily: 'Roboto',         inherit: true, color: Colors.white,   decoration: TextDecoration.none),
-    caption : TextStyle(debugLabel: 'whiteMountainView caption',  fontFamily: 'Roboto',         inherit: true, color: Colors.white70, decoration: TextDecoration.none),
-    button  : TextStyle(debugLabel: 'whiteMountainView button',   fontFamily: 'Roboto',         inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    display4   : TextStyle(debugLabel: 'whiteMountainView display4',   fontFamily: 'Roboto', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
+    display3   : TextStyle(debugLabel: 'whiteMountainView display3',   fontFamily: 'Roboto', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
+    display2   : TextStyle(debugLabel: 'whiteMountainView display2',   fontFamily: 'Roboto', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
+    display1   : TextStyle(debugLabel: 'whiteMountainView display1',   fontFamily: 'Roboto', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
+    headline   : TextStyle(debugLabel: 'whiteMountainView headline',   fontFamily: 'Roboto', inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    title      : TextStyle(debugLabel: 'whiteMountainView title',      fontFamily: 'Roboto', inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    subhead    : TextStyle(debugLabel: 'whiteMountainView subhead',    fontFamily: 'Roboto', inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    body2      : TextStyle(debugLabel: 'whiteMountainView body2',      fontFamily: 'Roboto', inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    body1      : TextStyle(debugLabel: 'whiteMountainView body1',      fontFamily: 'Roboto', inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    caption    : TextStyle(debugLabel: 'whiteMountainView caption',    fontFamily: 'Roboto', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
+    button     : TextStyle(debugLabel: 'whiteMountainView button',     fontFamily: 'Roboto', inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    subtitle   : TextStyle(debugLabel: 'whiteMountainView subtitle',   fontFamily: 'Roboto', inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    overline   : TextStyle(debugLabel: 'whiteMountainView overline',   fontFamily: 'Roboto', inherit: true, color: Colors.white,   decoration: TextDecoration.none),
   );
 
+  /// A material design text theme with dark glyphs based on San Francisco.
+  ///
+  /// This [TextTheme] provides color but not geometry (font size, weight, etc).
   static const TextTheme blackCupertino = TextTheme(
-    display4: TextStyle(debugLabel: 'blackCupertino display4', fontFamily: '.SF UI Display', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
-    display3: TextStyle(debugLabel: 'blackCupertino display3', fontFamily: '.SF UI Display', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
-    display2: TextStyle(debugLabel: 'blackCupertino display2', fontFamily: '.SF UI Display', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
-    display1: TextStyle(debugLabel: 'blackCupertino display1', fontFamily: '.SF UI Display', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
-    headline: TextStyle(debugLabel: 'blackCupertino headline', fontFamily: '.SF UI Display', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
-    title   : TextStyle(debugLabel: 'blackCupertino title',    fontFamily: '.SF UI Display', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
-    subhead : TextStyle(debugLabel: 'blackCupertino subhead',  fontFamily: '.SF UI Text',    inherit: true, color: Colors.black87, decoration: TextDecoration.none),
-    body2   : TextStyle(debugLabel: 'blackCupertino body2',    fontFamily: '.SF UI Text',    inherit: true, color: Colors.black87, decoration: TextDecoration.none),
-    body1   : TextStyle(debugLabel: 'blackCupertino body1',    fontFamily: '.SF UI Text',    inherit: true, color: Colors.black87, decoration: TextDecoration.none),
-    caption : TextStyle(debugLabel: 'blackCupertino caption',  fontFamily: '.SF UI Text',    inherit: true, color: Colors.black54, decoration: TextDecoration.none),
-    button  : TextStyle(debugLabel: 'blackCupertino button',   fontFamily: '.SF UI Text',    inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    display4   : TextStyle(debugLabel: 'blackCupertino display4',   fontFamily: '.SF UI Display', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
+    display3   : TextStyle(debugLabel: 'blackCupertino display3',   fontFamily: '.SF UI Display', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
+    display2   : TextStyle(debugLabel: 'blackCupertino display2',   fontFamily: '.SF UI Display', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
+    display1   : TextStyle(debugLabel: 'blackCupertino display1',   fontFamily: '.SF UI Display', inherit: true, color: Colors.black54, decoration: TextDecoration.none),
+    headline   : TextStyle(debugLabel: 'blackCupertino headline',   fontFamily: '.SF UI Display', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    title      : TextStyle(debugLabel: 'blackCupertino title',      fontFamily: '.SF UI Display', inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    subhead    : TextStyle(debugLabel: 'blackCupertino subhead',    fontFamily: '.SF UI Text',    inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    body2      : TextStyle(debugLabel: 'blackCupertino body2',      fontFamily: '.SF UI Text',    inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    body1      : TextStyle(debugLabel: 'blackCupertino body1',      fontFamily: '.SF UI Text',    inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    caption    : TextStyle(debugLabel: 'blackCupertino caption',    fontFamily: '.SF UI Text',    inherit: true, color: Colors.black54, decoration: TextDecoration.none),
+    button     : TextStyle(debugLabel: 'blackCupertino button',     fontFamily: '.SF UI Text',    inherit: true, color: Colors.black87, decoration: TextDecoration.none),
+    subtitle   : TextStyle(debugLabel: 'blackCupertino subtitle',   fontFamily: '.SF UI Text',    inherit: true, color: Colors.black,   decoration: TextDecoration.none),
+    overline   : TextStyle(debugLabel: 'blackCupertino overline',   fontFamily: '.SF UI Text',    inherit: true, color: Colors.black,   decoration: TextDecoration.none),
   );
 
+  /// A material design text theme with light glyphs based on San Francisco.
+  ///
+  /// This [TextTheme] provides color but not geometry (font size, weight, etc).
   static const TextTheme whiteCupertino = TextTheme(
-    display4: TextStyle(debugLabel: 'whiteCupertino display4', fontFamily: '.SF UI Display', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
-    display3: TextStyle(debugLabel: 'whiteCupertino display3', fontFamily: '.SF UI Display', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
-    display2: TextStyle(debugLabel: 'whiteCupertino display2', fontFamily: '.SF UI Display', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
-    display1: TextStyle(debugLabel: 'whiteCupertino display1', fontFamily: '.SF UI Display', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
-    headline: TextStyle(debugLabel: 'whiteCupertino headline', fontFamily: '.SF UI Display', inherit: true, color: Colors.white,   decoration: TextDecoration.none),
-    title   : TextStyle(debugLabel: 'whiteCupertino title',    fontFamily: '.SF UI Display', inherit: true, color: Colors.white,   decoration: TextDecoration.none),
-    subhead : TextStyle(debugLabel: 'whiteCupertino subhead',  fontFamily: '.SF UI Text',    inherit: true, color: Colors.white,   decoration: TextDecoration.none),
-    body2   : TextStyle(debugLabel: 'whiteCupertino body2',    fontFamily: '.SF UI Text',    inherit: true, color: Colors.white,   decoration: TextDecoration.none),
-    body1   : TextStyle(debugLabel: 'whiteCupertino body1',    fontFamily: '.SF UI Text',    inherit: true, color: Colors.white,   decoration: TextDecoration.none),
-    caption : TextStyle(debugLabel: 'whiteCupertino caption',  fontFamily: '.SF UI Text',    inherit: true, color: Colors.white70, decoration: TextDecoration.none),
-    button  : TextStyle(debugLabel: 'whiteCupertino button',   fontFamily: '.SF UI Text',    inherit: true, color: Colors.white,   decoration: TextDecoration.none),
-  );
-}
-
-/// Defines text geometries for the three language categories defined in
-/// https://material.io/go/design-typography.
-class MaterialTextGeometry {
-  /// The name of the English-like script category.
-  static const String englishLikeCategory = 'English-like';
-
-  /// The name of the dense script category.
-  static const String denseCategory = 'dense';
-
-  /// The name of the tall script category.
-  static const String tallCategory = 'tall';
-
-  /// The mapping from script category names to text themes.
-  static const Map<String, TextTheme> _categoryToTextTheme = <String, TextTheme>{
-    englishLikeCategory: englishLike,
-    denseCategory: dense,
-    tallCategory: tall,
-  };
-
-  /// Looks up text geometry corresponding to the given [scriptCategoryName].
-  ///
-  /// Most apps would not call this method directly, but rather call [Theme.of]
-  /// and use the [TextTheme] fields of the returned [ThemeData] object.
-  ///
-  /// [scriptCategoryName] must be one of [englishLikeCategory], [denseCategory]
-  /// and [tallCategory].
-  ///
-  /// See also:
-  ///
-  ///  * [DefaultMaterialLocalizations.localTextGeometry], which uses this
-  ///    method to look-up text geometry for the current locale.
-  static TextTheme forScriptCategory(String scriptCategoryName) => _categoryToTextTheme[scriptCategoryName];
-
-  /// Defines text geometry for English-like scripts, such as English, French, Russian, etc.
-  static const TextTheme englishLike = TextTheme(
-    display4: TextStyle(debugLabel: 'englishLike display4', inherit: false, fontSize: 112.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.alphabetic),
-    display3: TextStyle(debugLabel: 'englishLike display3', inherit: false, fontSize:  56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    display2: TextStyle(debugLabel: 'englishLike display2', inherit: false, fontSize:  45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    display1: TextStyle(debugLabel: 'englishLike display1', inherit: false, fontSize:  34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    headline: TextStyle(debugLabel: 'englishLike headline', inherit: false, fontSize:  24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    title   : TextStyle(debugLabel: 'englishLike title',    inherit: false, fontSize:  20.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
-    subhead : TextStyle(debugLabel: 'englishLike subhead',  inherit: false, fontSize:  16.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    body2   : TextStyle(debugLabel: 'englishLike body2',    inherit: false, fontSize:  14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
-    body1   : TextStyle(debugLabel: 'englishLike body1',    inherit: false, fontSize:  14.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    caption : TextStyle(debugLabel: 'englishLike caption',  inherit: false, fontSize:  12.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    button  : TextStyle(debugLabel: 'englishLike button',   inherit: false, fontSize:  14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
+    display4   : TextStyle(debugLabel: 'whiteCupertino display4',   fontFamily: '.SF UI Display', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
+    display3   : TextStyle(debugLabel: 'whiteCupertino display3',   fontFamily: '.SF UI Display', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
+    display2   : TextStyle(debugLabel: 'whiteCupertino display2',   fontFamily: '.SF UI Display', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
+    display1   : TextStyle(debugLabel: 'whiteCupertino display1',   fontFamily: '.SF UI Display', inherit: true, color: Colors.white70, decoration: TextDecoration.none),
+    headline   : TextStyle(debugLabel: 'whiteCupertino headline',   fontFamily: '.SF UI Display', inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    title      : TextStyle(debugLabel: 'whiteCupertino title',      fontFamily: '.SF UI Display', inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    subhead    : TextStyle(debugLabel: 'whiteCupertino subhead',    fontFamily: '.SF UI Text',    inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    body2      : TextStyle(debugLabel: 'whiteCupertino body2',      fontFamily: '.SF UI Text',    inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    body1      : TextStyle(debugLabel: 'whiteCupertino body1',      fontFamily: '.SF UI Text',    inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    caption    : TextStyle(debugLabel: 'whiteCupertino caption',    fontFamily: '.SF UI Text',    inherit: true, color: Colors.white70, decoration: TextDecoration.none),
+    button     : TextStyle(debugLabel: 'whiteCupertino button',     fontFamily: '.SF UI Text',    inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    subtitle   : TextStyle(debugLabel: 'whiteCupertino subtitle',   fontFamily: '.SF UI Text',    inherit: true, color: Colors.white,   decoration: TextDecoration.none),
+    overline   : TextStyle(debugLabel: 'whiteCupertino overline',   fontFamily: '.SF UI Text',    inherit: true, color: Colors.white,   decoration: TextDecoration.none),
   );
 
-  /// Defines text geometry for dense scripts, such as Chinese, Japanese, Korean, etc.
-  static const TextTheme dense = TextTheme(
-    display4: TextStyle(debugLabel: 'dense display4', inherit: false, fontSize: 112.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.ideographic),
-    display3: TextStyle(debugLabel: 'dense display3', inherit: false, fontSize:  56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
-    display2: TextStyle(debugLabel: 'dense display2', inherit: false, fontSize:  45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
-    display1: TextStyle(debugLabel: 'dense display1', inherit: false, fontSize:  34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
-    headline: TextStyle(debugLabel: 'dense headline', inherit: false, fontSize:  24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
-    title   : TextStyle(debugLabel: 'dense title',    inherit: false, fontSize:  21.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
-    subhead : TextStyle(debugLabel: 'dense subhead',  inherit: false, fontSize:  17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
-    body2   : TextStyle(debugLabel: 'dense body2',    inherit: false, fontSize:  15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
-    body1   : TextStyle(debugLabel: 'dense body1',    inherit: false, fontSize:  15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
-    caption : TextStyle(debugLabel: 'dense caption',  inherit: false, fontSize:  13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
-    button  : TextStyle(debugLabel: 'dense button',   inherit: false, fontSize:  15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
+  /// Defines text geometry for [ScriptCategory.englishLike] scripts, such as
+  /// English, French, Russian, etc.
+  static const TextTheme englishLike2014 = TextTheme(
+    display4 : TextStyle(debugLabel: 'englishLike display4 2014', inherit: false, fontSize: 112.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.alphabetic),
+    display3 : TextStyle(debugLabel: 'englishLike display3 2014', inherit: false, fontSize:  56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    display2 : TextStyle(debugLabel: 'englishLike display2 2014', inherit: false, fontSize:  45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    display1 : TextStyle(debugLabel: 'englishLike display1 2014', inherit: false, fontSize:  34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    headline : TextStyle(debugLabel: 'englishLike headline 2014', inherit: false, fontSize:  24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    title    : TextStyle(debugLabel: 'englishLike title 2014',    inherit: false, fontSize:  20.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
+    subhead  : TextStyle(debugLabel: 'englishLike subhead 2014',  inherit: false, fontSize:  16.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    body2    : TextStyle(debugLabel: 'englishLike body2 2014',    inherit: false, fontSize:  14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
+    body1    : TextStyle(debugLabel: 'englishLike body1 2014',    inherit: false, fontSize:  14.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    caption  : TextStyle(debugLabel: 'englishLike caption 2014',  inherit: false, fontSize:  12.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    button   : TextStyle(debugLabel: 'englishLike button 2014',   inherit: false, fontSize:  14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
+    subtitle : TextStyle(debugLabel: 'englishLike subtitle 2014', inherit: false, fontSize:  14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.1),
+    overline : TextStyle(debugLabel: 'englishLike overline 2014', inherit: false, fontSize:  10.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 1.5),
   );
 
-  /// Defines text geometry for tall scripts, such as Farsi, Hindi, Thai, etc.
-  static const TextTheme tall = TextTheme(
-    display4: TextStyle(debugLabel: 'tall display4', inherit: false, fontSize: 112.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    display3: TextStyle(debugLabel: 'tall display3', inherit: false, fontSize:  56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    display2: TextStyle(debugLabel: 'tall display2', inherit: false, fontSize:  45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    display1: TextStyle(debugLabel: 'tall display1', inherit: false, fontSize:  34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    headline: TextStyle(debugLabel: 'tall headline', inherit: false, fontSize:  24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    title   : TextStyle(debugLabel: 'tall title',    inherit: false, fontSize:  21.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
-    subhead : TextStyle(debugLabel: 'tall subhead',  inherit: false, fontSize:  17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    body2   : TextStyle(debugLabel: 'tall body2',    inherit: false, fontSize:  15.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
-    body1   : TextStyle(debugLabel: 'tall body1',    inherit: false, fontSize:  15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    caption : TextStyle(debugLabel: 'tall caption',  inherit: false, fontSize:  13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
-    button  : TextStyle(debugLabel: 'tall button',   inherit: false, fontSize:  15.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
+  /// Defines text geometry for [ScriptCategory.englishLike] scripts, such as
+  /// English, French, Russian, etc.
+  ///
+  /// The font sizes, weights, and letter spacings in this version match the
+  /// [latest Material Design specification](https://material.io/go/design-typography#typography-styles).
+  static const TextTheme englishLike2018 = TextTheme(
+    display4   : TextStyle(debugLabel: 'englishLike display4 2018', fontSize: 96.0, fontWeight: FontWeight.w300, textBaseline: TextBaseline.alphabetic, letterSpacing: -1.5),
+    display3   : TextStyle(debugLabel: 'englishLike display3 2018', fontSize: 60.0, fontWeight: FontWeight.w300, textBaseline: TextBaseline.alphabetic, letterSpacing: -0.5),
+    display2   : TextStyle(debugLabel: 'englishLike display2 2018', fontSize: 48.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.0),
+    display1   : TextStyle(debugLabel: 'englishLike display1 2018', fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.25),
+    headline   : TextStyle(debugLabel: 'englishLike headline 2018', fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.0),
+    title      : TextStyle(debugLabel: 'englishLike title 2018',    fontSize: 20.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.15),
+    subhead    : TextStyle(debugLabel: 'englishLike subhead 2018',  fontSize: 16.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.15),
+    body2      : TextStyle(debugLabel: 'englishLike body2 2018',    fontSize: 14.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.25),
+    body1      : TextStyle(debugLabel: 'englishLike body1 2018',    fontSize: 16.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.5),
+    button     : TextStyle(debugLabel: 'englishLike button 2018',   fontSize: 14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.75),
+    caption    : TextStyle(debugLabel: 'englishLike caption 2018',  fontSize: 12.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.4),
+    subtitle   : TextStyle(debugLabel: 'englishLike subtitle 2018', fontSize: 14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.1),
+    overline   : TextStyle(debugLabel: 'englishLike overline 2018', fontSize: 10.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 1.5),
+  );
+
+  /// Defines text geometry for dense scripts, such as Chinese, Japanese
+  /// and Korean.
+  static const TextTheme dense2014 = TextTheme(
+    display4 : TextStyle(debugLabel: 'dense display4 2014', inherit: false, fontSize: 112.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.ideographic),
+    display3 : TextStyle(debugLabel: 'dense display3 2014', inherit: false, fontSize:  56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    display2 : TextStyle(debugLabel: 'dense display2 2014', inherit: false, fontSize:  45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    display1 : TextStyle(debugLabel: 'dense display1 2014', inherit: false, fontSize:  34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    headline : TextStyle(debugLabel: 'dense headline 2014', inherit: false, fontSize:  24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    title    : TextStyle(debugLabel: 'dense title 2014',    inherit: false, fontSize:  21.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
+    subhead  : TextStyle(debugLabel: 'dense subhead 2014',  inherit: false, fontSize:  17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    body2    : TextStyle(debugLabel: 'dense body2 2014',    inherit: false, fontSize:  15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
+    body1    : TextStyle(debugLabel: 'dense body1 2014',    inherit: false, fontSize:  15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    caption  : TextStyle(debugLabel: 'dense caption 2014',  inherit: false, fontSize:  13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    button   : TextStyle(debugLabel: 'dense button 2014',   inherit: false, fontSize:  15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
+    subtitle : TextStyle(debugLabel: 'dense subtitle 2014', inherit: false, fontSize:  15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
+    overline : TextStyle(debugLabel: 'dense overline 2014', inherit: false, fontSize:  11.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+  );
+
+  /// Defines text geometry for dense scripts, such as Chinese, Japanese
+  /// and Korean.
+  ///
+  /// The font sizes, weights, and letter spacings in this version match the
+  /// latest [Material Design specification](https://material.io/go/design-typography#typography-styles).
+  static const TextTheme dense2018 = TextTheme(
+    display4  : TextStyle(debugLabel: 'dense display4 2018',  fontSize: 96.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.ideographic),
+    display3  : TextStyle(debugLabel: 'dense display3 2018',  fontSize: 60.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.ideographic),
+    display2  : TextStyle(debugLabel: 'dense display2 2018',  fontSize: 48.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    display1  : TextStyle(debugLabel: 'dense display1 2018',  fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    headline  : TextStyle(debugLabel: 'dense headline 2018',  fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    title     : TextStyle(debugLabel: 'dense title 2018',     fontSize: 21.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
+    subhead   : TextStyle(debugLabel: 'dense subhead 2018',   fontSize: 17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    body2     : TextStyle(debugLabel: 'dense body2 2018',     fontSize: 17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    body1     : TextStyle(debugLabel: 'dense body1 2018',     fontSize: 15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    caption   : TextStyle(debugLabel: 'dense caption 2018',   fontSize: 13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+    button    : TextStyle(debugLabel: 'dense button 2018',    fontSize: 15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
+    subtitle  : TextStyle(debugLabel: 'dense subtitle 2018',  fontSize: 15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
+    overline  : TextStyle(debugLabel: 'dense overline 2018',  fontSize: 11.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
+  );
+
+  /// Defines text geometry for tall scripts, such as Farsi, Hindi, and Thai.
+  static const TextTheme tall2014 = TextTheme(
+    display4 : TextStyle(debugLabel: 'tall display4 2014', inherit: false, fontSize: 112.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    display3 : TextStyle(debugLabel: 'tall display3 2014', inherit: false, fontSize:  56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    display2 : TextStyle(debugLabel: 'tall display2 2014', inherit: false, fontSize:  45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    display1 : TextStyle(debugLabel: 'tall display1 2014', inherit: false, fontSize:  34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    headline : TextStyle(debugLabel: 'tall headline 2014', inherit: false, fontSize:  24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    title    : TextStyle(debugLabel: 'tall title 2014',    inherit: false, fontSize:  21.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
+    subhead  : TextStyle(debugLabel: 'tall subhead 2014',  inherit: false, fontSize:  17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    body2    : TextStyle(debugLabel: 'tall body2 2014',    inherit: false, fontSize:  15.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
+    body1    : TextStyle(debugLabel: 'tall body1 2014',    inherit: false, fontSize:  15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    caption  : TextStyle(debugLabel: 'tall caption 2014',  inherit: false, fontSize:  13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    button   : TextStyle(debugLabel: 'tall button 2014',   inherit: false, fontSize:  15.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
+    subtitle : TextStyle(debugLabel: 'tall subtitle 2014', inherit: false, fontSize:  15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
+    overline : TextStyle(debugLabel: 'tall overline 2014', inherit: false, fontSize:  11.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+  );
+
+  /// Defines text geometry for tall scripts, such as Farsi, Hindi, and Thai.
+  ///
+  /// The font sizes, weights, and letter spacings in this version match the
+  /// latest [Material Design specification](https://material.io/go/design-typography#typography-styles).
+  static const TextTheme tall2018 = TextTheme(
+    display4  : TextStyle(debugLabel: 'tall display4 2018',  fontSize: 96.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    display3  : TextStyle(debugLabel: 'tall display3 2018',  fontSize: 60.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    display2  : TextStyle(debugLabel: 'tall display2 2018',  fontSize: 48.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    display1  : TextStyle(debugLabel: 'tall display1 2018',  fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    headline  : TextStyle(debugLabel: 'tall headline 2018',  fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    title     : TextStyle(debugLabel: 'tall title 2018',     fontSize: 21.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
+    subhead   : TextStyle(debugLabel: 'tall subhead 2018',   fontSize: 17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    body2     : TextStyle(debugLabel: 'tall body2 2018',     fontSize: 17.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
+    body1     : TextStyle(debugLabel: 'tall body1 2018',     fontSize: 15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    button    : TextStyle(debugLabel: 'tall button 2018',    fontSize: 15.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
+    caption   : TextStyle(debugLabel: 'tall caption 2018',   fontSize: 13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
+    subtitle  : TextStyle(debugLabel: 'tall subtitle 2018',  fontSize: 15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
+    overline  : TextStyle(debugLabel: 'tall overline 2018',  fontSize: 11.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
   );
 }
diff --git a/packages/flutter/test/material/text_field_test.dart b/packages/flutter/test/material/text_field_test.dart
index 0124ede..b12527a 100644
--- a/packages/flutter/test/material/text_field_test.dart
+++ b/packages/flutter/test/material/text_field_test.dart
@@ -915,7 +915,7 @@
     );
     final Text helperText = tester.widget(find.text('helper text'));
     expect(helperText.style.color, themeData.hintColor);
-    expect(helperText.style.fontSize, MaterialTextGeometry.englishLike.caption.fontSize);
+    expect(helperText.style.fontSize, Typography.englishLike2014.caption.fontSize);
   });
 
   testWidgets('TextField with specified helperStyle', (WidgetTester tester) async {
diff --git a/packages/flutter/test/material/theme_test.dart b/packages/flutter/test/material/theme_test.dart
index 81f060d..b4a2872 100644
--- a/packages/flutter/test/material/theme_test.dart
+++ b/packages/flutter/test/material/theme_test.dart
@@ -9,6 +9,8 @@
 import 'package:flutter_test/flutter_test.dart';
 
 void main() {
+  const TextTheme defaultGeometryTheme = Typography.englishLike2014;
+
   test('ThemeDataTween control test', () {
     final ThemeData light = ThemeData.light();
     final ThemeData dark = ThemeData.dark();
@@ -55,7 +57,7 @@
       )
     );
 
-    expect(Theme.of(capturedContext), equals(ThemeData.localize(ThemeData.fallback(), MaterialTextGeometry.englishLike)));
+    expect(Theme.of(capturedContext), equals(ThemeData.localize(ThemeData.fallback(), defaultGeometryTheme)));
     expect(Theme.of(capturedContext, shadowThemeOnly: true), isNull);
   });
 
@@ -65,20 +67,20 @@
 
     // Same input, same output.
     expect(
-      ThemeData.localize(light, MaterialTextGeometry.englishLike),
-      same(ThemeData.localize(light, MaterialTextGeometry.englishLike)),
+      ThemeData.localize(light, defaultGeometryTheme),
+      same(ThemeData.localize(light, defaultGeometryTheme)),
     );
 
     // Different text geometry, different output.
     expect(
-      ThemeData.localize(light, MaterialTextGeometry.englishLike),
-      isNot(same(ThemeData.localize(light, MaterialTextGeometry.tall))),
+      ThemeData.localize(light, defaultGeometryTheme),
+      isNot(same(ThemeData.localize(light, Typography.tall2014))),
     );
 
     // Different base theme, different output.
     expect(
-      ThemeData.localize(light, MaterialTextGeometry.englishLike),
-      isNot(same(ThemeData.localize(dark, MaterialTextGeometry.englishLike))),
+      ThemeData.localize(light, defaultGeometryTheme),
+      isNot(same(ThemeData.localize(dark, defaultGeometryTheme))),
     );
   });
 
@@ -408,7 +410,7 @@
       }
     }
 
-    expect(theme.textTheme.display4.debugLabel, '(englishLike display4).merge(blackMountainView display4)');
+    expect(theme.textTheme.display4.debugLabel, '(englishLike display4 2014).merge(blackMountainView display4)');
   });
 }
 
diff --git a/packages/flutter/test/material/typography_test.dart b/packages/flutter/test/material/typography_test.dart
index d933363..4032378 100644
--- a/packages/flutter/test/material/typography_test.dart
+++ b/packages/flutter/test/material/typography_test.dart
@@ -74,6 +74,8 @@
       expect(textTheme.body1, isTextFont);
       expect(textTheme.caption, isTextFont);
       expect(textTheme.button, isTextFont);
+      expect(textTheme.subtitle, isTextFont);
+      expect(textTheme.overline, isTextFont);
     }
   });
 }
diff --git a/packages/flutter_localizations/lib/src/l10n/README.md b/packages/flutter_localizations/lib/src/l10n/README.md
index 12c9bd0..34961c5 100644
--- a/packages/flutter_localizations/lib/src/l10n/README.md
+++ b/packages/flutter_localizations/lib/src/l10n/README.md
@@ -138,11 +138,11 @@
 has this value labeled as `"x-flutter-type": "icuShortTimePattern"`.
 
 The value of `scriptCategory` is based on the
-[Language categories reference](https://material.io/go/design-typography#typography-language-categories-reference)
+[Language categories reference](https://material.io/design/typography/language-support.html#language-categories-reference)
 section in the Material spec. The `scriptCategory` value is used when looking up
 the `TextTheme`, see the
-[MaterialTextGeometry](https://docs.flutter.io/flutter/material/MaterialTextGeometry/forScriptCategory.html)
-class.
+[MaterialTextGeometry](https://docs.flutter.io/flutter/material/MaterialTextGeometry/localizedFor.html)
+method.
 
 
 ### Generated file localizations.dart: all of the localizations as a Map
diff --git a/packages/flutter_localizations/lib/src/l10n/localizations.dart b/packages/flutter_localizations/lib/src/l10n/localizations.dart
index f3a0091..ff3ea4f 100644
--- a/packages/flutter_localizations/lib/src/l10n/localizations.dart
+++ b/packages/flutter_localizations/lib/src/l10n/localizations.dart
@@ -171,7 +171,7 @@
   String get rowsPerPageTitle => r'عدد الصفوف في الصفحة:';
 
   @override
-  String get scriptCategory => r'tall';
+  ScriptCategory get scriptCategory => ScriptCategory.tall;
 
   @override
   String get searchFieldLabel => r'بحث';
@@ -372,7 +372,7 @@
   String get rowsPerPageTitle => r'Редове на страница:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Търсене';
@@ -573,7 +573,7 @@
   String get rowsPerPageTitle => r'Redaka po stranici:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Pretražite';
@@ -774,7 +774,7 @@
   String get rowsPerPageTitle => r'Files per pàgina:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Cerca';
@@ -975,7 +975,7 @@
   String get rowsPerPageTitle => r'Počet řádků na stránku:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Hledat';
@@ -1176,7 +1176,7 @@
   String get rowsPerPageTitle => r'Rækker pr. side:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Søg';
@@ -1377,7 +1377,7 @@
   String get rowsPerPageTitle => r'Zeilen pro Seite:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Suchen';
@@ -1608,7 +1608,7 @@
   String get rowsPerPageTitle => r'Σειρές ανά σελίδα:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Αναζήτηση';
@@ -1809,7 +1809,7 @@
   String get rowsPerPageTitle => r'Rows per page:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Search';
@@ -2313,7 +2313,7 @@
   String get rowsPerPageTitle => r'Filas por página:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Buscar';
@@ -4137,7 +4137,7 @@
   String get rowsPerPageTitle => r'Ridu lehe kohta:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Otsing';
@@ -4338,7 +4338,7 @@
   String get rowsPerPageTitle => r'ردیف در هر صفحه:';
 
   @override
-  String get scriptCategory => r'tall';
+  ScriptCategory get scriptCategory => ScriptCategory.tall;
 
   @override
   String get searchFieldLabel => r'جستجو';
@@ -4539,7 +4539,7 @@
   String get rowsPerPageTitle => r'Riviä/sivu:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Haku';
@@ -4740,7 +4740,7 @@
   String get rowsPerPageTitle => r'Mga row bawat page:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Maghanap';
@@ -4941,7 +4941,7 @@
   String get rowsPerPageTitle => r'Lignes par page :';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Rechercher';
@@ -5169,7 +5169,7 @@
   String get rowsPerPageTitle => r'Zeilen pro Seite:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Suchen';
@@ -5370,7 +5370,7 @@
   String get rowsPerPageTitle => r'שורות בכל דף:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'חיפוש';
@@ -5571,7 +5571,7 @@
   String get rowsPerPageTitle => r'हर पेज में पंक्तियों की संख्या:';
 
   @override
-  String get scriptCategory => r'dense';
+  ScriptCategory get scriptCategory => ScriptCategory.dense;
 
   @override
   String get searchFieldLabel => r'खोजें';
@@ -5772,7 +5772,7 @@
   String get rowsPerPageTitle => r'Redaka po stranici:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Pretražite';
@@ -5973,7 +5973,7 @@
   String get rowsPerPageTitle => r'Oldalankénti sorszám:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Keresés';
@@ -6174,7 +6174,7 @@
   String get rowsPerPageTitle => r'Baris per halaman:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Telusuri';
@@ -6375,7 +6375,7 @@
   String get rowsPerPageTitle => r'Righe per pagina:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Cerca';
@@ -6576,7 +6576,7 @@
   String get rowsPerPageTitle => r'ページあたりの行数:';
 
   @override
-  String get scriptCategory => r'dense';
+  ScriptCategory get scriptCategory => ScriptCategory.dense;
 
   @override
   String get searchFieldLabel => r'検索';
@@ -6777,7 +6777,7 @@
   String get rowsPerPageTitle => r'ជួរមុខ:';
 
   @override
-  String get scriptCategory => r'dense';
+  ScriptCategory get scriptCategory => ScriptCategory.dense;
 
   @override
   String get searchFieldLabel => r'ស្វែងរក';
@@ -6978,7 +6978,7 @@
   String get rowsPerPageTitle => r'페이지당 행 수:';
 
   @override
-  String get scriptCategory => r'dense';
+  ScriptCategory get scriptCategory => ScriptCategory.dense;
 
   @override
   String get searchFieldLabel => r'검색';
@@ -7179,7 +7179,7 @@
   String get rowsPerPageTitle => r'Eilučių puslapyje:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Paieška';
@@ -7380,7 +7380,7 @@
   String get rowsPerPageTitle => r'Rindas lapā:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Meklēt';
@@ -7581,7 +7581,7 @@
   String get rowsPerPageTitle => r'Baris setiap halaman:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Cari';
@@ -7782,7 +7782,7 @@
   String get rowsPerPageTitle => r'Rader per side:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Søk';
@@ -7983,7 +7983,7 @@
   String get rowsPerPageTitle => r'Rijen per pagina:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Zoeken';
@@ -8184,7 +8184,7 @@
   String get rowsPerPageTitle => r'Wiersze na stronie:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Szukaj';
@@ -8385,7 +8385,7 @@
   String get rowsPerPageTitle => r'د هرې پاڼې پاڼې:';
 
   @override
-  String get scriptCategory => r'tall';
+  ScriptCategory get scriptCategory => ScriptCategory.tall;
 
   @override
   String get searchFieldLabel => r'لټون';
@@ -8586,7 +8586,7 @@
   String get rowsPerPageTitle => r'Linhas por página:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Pesquisa';
@@ -8871,7 +8871,7 @@
   String get rowsPerPageTitle => r'Rânduri pe pagină:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Căutați';
@@ -9072,7 +9072,7 @@
   String get rowsPerPageTitle => r'Строк на странице:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Поиск';
@@ -9273,7 +9273,7 @@
   String get rowsPerPageTitle => r'Počet riadkov na stránku:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Hľadať';
@@ -9474,7 +9474,7 @@
   String get rowsPerPageTitle => r'Vrstice na stran:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Iskanje';
@@ -9675,7 +9675,7 @@
   String get rowsPerPageTitle => r'Редова по страници:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Претражите';
@@ -10053,7 +10053,7 @@
   String get rowsPerPageTitle => r'Rader per sida:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Sök';
@@ -10254,7 +10254,7 @@
   String get rowsPerPageTitle => r'แถวต่อหน้า:';
 
   @override
-  String get scriptCategory => r'tall';
+  ScriptCategory get scriptCategory => ScriptCategory.tall;
 
   @override
   String get searchFieldLabel => r'ค้นหา';
@@ -10455,7 +10455,7 @@
   String get rowsPerPageTitle => r'Mga row bawat page:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Maghanap';
@@ -10656,7 +10656,7 @@
   String get rowsPerPageTitle => r'Sayfa başına satır sayısı:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Ara';
@@ -10857,7 +10857,7 @@
   String get rowsPerPageTitle => r'Рядків на сторінці:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Пошук';
@@ -11058,7 +11058,7 @@
   String get rowsPerPageTitle => r'قطاریں فی صفحہ:';
 
   @override
-  String get scriptCategory => r'tall';
+  ScriptCategory get scriptCategory => ScriptCategory.tall;
 
   @override
   String get searchFieldLabel => r'تلاش';
@@ -11259,7 +11259,7 @@
   String get rowsPerPageTitle => r'Số hàng mỗi trang:';
 
   @override
-  String get scriptCategory => r'English-like';
+  ScriptCategory get scriptCategory => ScriptCategory.englishLike;
 
   @override
   String get searchFieldLabel => r'Tìm kiếm';
@@ -11460,7 +11460,7 @@
   String get rowsPerPageTitle => r'每页行数:';
 
   @override
-  String get scriptCategory => r'dense';
+  ScriptCategory get scriptCategory => ScriptCategory.dense;
 
   @override
   String get searchFieldLabel => r'搜索';
diff --git a/packages/flutter_localizations/lib/src/l10n/material_en.arb b/packages/flutter_localizations/lib/src/l10n/material_en.arb
index d72ca74..79e4a56 100644
--- a/packages/flutter_localizations/lib/src/l10n/material_en.arb
+++ b/packages/flutter_localizations/lib/src/l10n/material_en.arb
@@ -1,7 +1,8 @@
 {
   "scriptCategory": "English-like",
   "@scriptCategory": {
-    "description": "The name of the language's script category (see https://material.io/go/design-typography#typography-language-categories-reference)."
+    "description": "The name of the language's script category (see https://material.io/design/typography/language-support.html#language-categories-reference).",
+    "x-flutter-type": "scriptCategory"
   },
 
   "timeOfDayFormat": "h:mm a",
diff --git a/packages/flutter_localizations/lib/src/material_localizations.dart b/packages/flutter_localizations/lib/src/material_localizations.dart
index 61debf8..b33bbd8 100644
--- a/packages/flutter_localizations/lib/src/material_localizations.dart
+++ b/packages/flutter_localizations/lib/src/material_localizations.dart
@@ -502,18 +502,8 @@
     ).replaceFirst(r'$remainingCount', formatDecimal(remainingCount));
   }
 
-  /// The script category used by [localTextGeometry]. Must be one of the strings
-  /// declared in [MaterialTextGeometry].
-  //
-  // TODO(ianh): make this return a TextTheme from MaterialTextGeometry.
-  // TODO(ianh): drop the constructor on MaterialTextGeometry.
-  // TODO(ianh): drop the strings on MaterialTextGeometry.
-  @protected
-  String get scriptCategory;
-
-  /// Looks up text geometry defined in [MaterialTextGeometry].
   @override
-  TextTheme get localTextGeometry => MaterialTextGeometry.forScriptCategory(scriptCategory);
+  ScriptCategory get scriptCategory;
 
   /// A [LocalizationsDelegate] that uses [GlobalMaterialLocalizations.load]
   /// to create an instance of this class.