Unverified Commit c6741614 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Animate TextStyle.fontVariations (#138881)

Fixes https://github.com/flutter/flutter/issues/105120

I also exposed the relevant dart:ui types which had the effect of removing a large number of dart:ui imports from examples.
parent 21766a4f
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
/// Flutter code sample for [FontFeature].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.alternative].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.alternativeFractions].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.caseSensitiveForms].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.characterVariant].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.contextualAlternates].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.denominator].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.fractions].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.historicalForms].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.historicalLigatures].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.liningFigures].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.notationalForms].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.numerators].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.oldstyleFigures].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.ordinalForms].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.proportionalFigures].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.scientificInferiors].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.slashedZero].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.stylisticAlternates].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.stylisticSet].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.stylisticSet].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.subscripts].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.superscripts].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [FontFeature.FontFeature.swash].
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/widgets.dart';
/// Flutter code sample for [dart]:ui FontFeature.FontFeature.tabularFigures.
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_alternative.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_alternative_fractions.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_case_sensitive_forms.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_character_variant.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_contextual_alternates.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_denominator.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_fractions.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_historical_forms.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_historical_ligatures.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_lining_figures.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_notational_forms.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_numerators.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_oldstyle_figures.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_ordinal_forms.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_proportional_figures.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_scientific_inferiors.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_slashed_zero.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_stylistic_alternates.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_stylistic_set.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_stylistic_set.1.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_subscripts.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_superscripts.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_swash.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_api_samples/ui/text/font_feature.font_feature_tabular_figures.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
......
......@@ -12,7 +12,9 @@ export 'dart:ui' show
Color,
ColorFilter,
FilterQuality,
FontFeature,
FontStyle,
FontVariation,
FontWeight,
ImageShader,
Locale,
......@@ -28,6 +30,7 @@ export 'dart:ui' show
Radius,
Rect,
Shader,
Shadow,
Size,
StrokeCap,
StrokeJoin,
......@@ -38,6 +41,8 @@ export 'dart:ui' show
TextDecoration,
TextDecorationStyle,
TextDirection,
TextHeightBehavior,
TextLeadingDistribution,
TextPosition,
TileMode,
VertexMode,
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui' show TextLeadingDistribution;
import 'package:flutter/foundation.dart';
import 'basic_types.dart';
......
......@@ -12,7 +12,6 @@ import 'dart:ui' as ui show
ParagraphConstraints,
ParagraphStyle,
PlaceholderAlignment,
TextHeightBehavior,
TextStyle;
import 'package:flutter/foundation.dart';
......@@ -488,7 +487,7 @@ class TextPainter {
Locale? locale,
StrutStyle? strutStyle,
TextWidthBasis textWidthBasis = TextWidthBasis.parent,
ui.TextHeightBehavior? textHeightBehavior,
TextHeightBehavior? textHeightBehavior,
}) : assert(text == null || text.debugAssertIsValid()),
assert(maxLines == null || maxLines > 0),
assert(textScaleFactor == 1.0 || identical(textScaler, TextScaler.noScaling), 'Use textScaler instead.'),
......@@ -537,7 +536,7 @@ class TextPainter {
Locale? locale,
StrutStyle? strutStyle,
TextWidthBasis textWidthBasis = TextWidthBasis.parent,
ui.TextHeightBehavior? textHeightBehavior,
TextHeightBehavior? textHeightBehavior,
double minWidth = 0.0,
double maxWidth = double.infinity,
}) {
......@@ -589,7 +588,7 @@ class TextPainter {
Locale? locale,
StrutStyle? strutStyle,
TextWidthBasis textWidthBasis = TextWidthBasis.parent,
ui.TextHeightBehavior? textHeightBehavior,
TextHeightBehavior? textHeightBehavior,
double minWidth = 0.0,
double maxWidth = double.infinity,
}) {
......@@ -894,9 +893,9 @@ class TextPainter {
}
/// {@macro dart.ui.textHeightBehavior}
ui.TextHeightBehavior? get textHeightBehavior => _textHeightBehavior;
ui.TextHeightBehavior? _textHeightBehavior;
set textHeightBehavior(ui.TextHeightBehavior? value) {
TextHeightBehavior? get textHeightBehavior => _textHeightBehavior;
TextHeightBehavior? _textHeightBehavior;
set textHeightBehavior(TextHeightBehavior? value) {
if (_textHeightBehavior == value) {
return;
}
......
......@@ -2,14 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:collection';
import 'dart:ui' as ui show
FontFeature,
FontVariation,
ParagraphStyle,
Shadow,
StrutStyle,
TextHeightBehavior,
TextLeadingDistribution,
TextStyle,
lerpDouble;
......@@ -680,7 +676,7 @@ class TextStyle with Diagnosticable {
///
/// Defaults to null, which defers to the paragraph's
/// `ParagraphStyle.textHeightBehavior`'s [leadingDistribution].
final ui.TextLeadingDistribution? leadingDistribution;
final TextLeadingDistribution? leadingDistribution;
/// The locale used to select region-specific glyphs.
///
......@@ -800,7 +796,7 @@ class TextStyle with Diagnosticable {
///
/// Shadows must be in the same order for [TextStyle] to be considered as
/// equivalent as order produces differing transparency.
final List<ui.Shadow>? shadows;
final List<Shadow>? shadows;
/// A list of [FontFeature]s that affect how the font selects glyphs.
///
......@@ -809,7 +805,13 @@ class TextStyle with Diagnosticable {
/// tabular numbers, or it might offer versions of the zero digit with
/// and without slashes. [FontFeature]s can be used to select which of
/// these variants will be used for rendering.
final List<ui.FontFeature>? fontFeatures;
///
/// Font features are not interpolated by [lerp].
///
/// See also:
///
/// * [fontVariations], for font features that have continuous parameters.
final List<FontFeature>? fontFeatures;
/// A list of [FontVariation]s that affect how a variable font is rendered.
///
......@@ -823,10 +825,18 @@ class TextStyle with Diagnosticable {
/// ```dart
/// const TextStyle(
/// fontFamily: 'RobotoSlab',
/// fontVariations: <ui.FontVariation>[ui.FontVariation('wght', 900.0)]
/// fontVariations: <FontVariation>[FontVariation('wght', 900.0)]
/// )
/// ```
final List<ui.FontVariation>? fontVariations;
///
/// Font variations can be interpolated via [lerp]. This is fastest when the
/// same font variation axes are specified, in the same order, in both
/// [TextStyle] objects. See [lerpFontVariations].
///
/// See also:
///
/// * [fontFeatures], for font variations that have discrete values.
final List<FontVariation>? fontVariations;
/// How visual text overflow should be handled.
final TextOverflow? overflow;
......@@ -862,13 +872,13 @@ class TextStyle with Diagnosticable {
double? wordSpacing,
TextBaseline? textBaseline,
double? height,
ui.TextLeadingDistribution? leadingDistribution,
TextLeadingDistribution? leadingDistribution,
Locale? locale,
Paint? foreground,
Paint? background,
List<ui.Shadow>? shadows,
List<ui.FontFeature>? fontFeatures,
List<ui.FontVariation>? fontVariations,
List<Shadow>? shadows,
List<FontFeature>? fontFeatures,
List<FontVariation>? fontVariations,
TextDecoration? decoration,
Color? decorationColor,
TextDecorationStyle? decorationStyle,
......@@ -967,11 +977,11 @@ class TextStyle with Diagnosticable {
double heightFactor = 1.0,
double heightDelta = 0.0,
TextBaseline? textBaseline,
ui.TextLeadingDistribution? leadingDistribution,
TextLeadingDistribution? leadingDistribution,
Locale? locale,
List<ui.Shadow>? shadows,
List<ui.FontFeature>? fontFeatures,
List<ui.FontVariation>? fontVariations,
List<Shadow>? shadows,
List<FontFeature>? fontFeatures,
List<FontVariation>? fontVariations,
String? package,
TextOverflow? overflow,
}) {
......@@ -1136,7 +1146,7 @@ class TextStyle with Diagnosticable {
background: t < 0.5 ? null : b.background,
shadows: t < 0.5 ? null : b.shadows,
fontFeatures: t < 0.5 ? null : b.fontFeatures,
fontVariations: t < 0.5 ? null : b.fontVariations,
fontVariations: lerpFontVariations(null, b.fontVariations, t),
decoration: t < 0.5 ? null : b.decoration,
decorationColor: Color.lerp(null, b.decorationColor, t),
decorationStyle: t < 0.5 ? null : b.decorationStyle,
......@@ -1167,7 +1177,7 @@ class TextStyle with Diagnosticable {
background: t < 0.5 ? a.background : null,
shadows: t < 0.5 ? a.shadows : null,
fontFeatures: t < 0.5 ? a.fontFeatures : null,
fontVariations: t < 0.5 ? a.fontVariations : null,
fontVariations: lerpFontVariations(a.fontVariations, null, t),
decoration: t < 0.5 ? a.decoration : null,
decorationColor: Color.lerp(a.decorationColor, null, t),
decorationStyle: t < 0.5 ? a.decorationStyle : null,
......@@ -1267,7 +1277,7 @@ class TextStyle with Diagnosticable {
: null,
shadows: t < 0.5 ? a.shadows : b.shadows,
fontFeatures: t < 0.5 ? a.fontFeatures : b.fontFeatures,
fontVariations: t < 0.5 ? a.fontVariations : b.fontVariations,
fontVariations: lerpFontVariations(a.fontVariations, b.fontVariations, t),
decoration: t < 0.5 ? a.decoration : b.decoration,
decorationColor: Color.lerp(a.decorationColor, b.decorationColor, t),
decorationStyle: t < 0.5 ? a.decorationStyle : b.decorationStyle,
......@@ -1342,7 +1352,7 @@ class TextStyle with Diagnosticable {
TextScaler textScaler = TextScaler.noScaling,
String? ellipsis,
int? maxLines,
ui.TextHeightBehavior? textHeightBehavior,
TextHeightBehavior? textHeightBehavior,
Locale? locale,
String? fontFamily,
double? fontSize,
......@@ -1352,9 +1362,9 @@ class TextStyle with Diagnosticable {
StrutStyle? strutStyle,
}) {
assert(maxLines == null || maxLines > 0);
final ui.TextLeadingDistribution? leadingDistribution = this.leadingDistribution;
final ui.TextHeightBehavior? effectiveTextHeightBehavior = textHeightBehavior
?? (leadingDistribution == null ? null : ui.TextHeightBehavior(leadingDistribution: leadingDistribution));
final TextLeadingDistribution? leadingDistribution = this.leadingDistribution;
final TextHeightBehavior? effectiveTextHeightBehavior = textHeightBehavior
?? (leadingDistribution == null ? null : TextHeightBehavior(leadingDistribution: leadingDistribution));
return ui.ParagraphStyle(
textAlign: textAlign,
......@@ -1475,9 +1485,9 @@ class TextStyle with Diagnosticable {
overflow,
);
final List<ui.Shadow>? shadows = this.shadows;
final List<ui.FontFeature>? fontFeatures = this.fontFeatures;
final List<ui.FontVariation>? fontVariations = this.fontVariations;
final List<Shadow>? shadows = this.shadows;
final List<FontFeature>? fontFeatures = this.fontFeatures;
final List<FontVariation>? fontVariations = this.fontVariations;
return Object.hash(
inherit,
color,
......@@ -1537,7 +1547,7 @@ class TextStyle with Diagnosticable {
styles.add(DoubleProperty('${prefix}wordSpacing', wordSpacing, defaultValue: null));
styles.add(EnumProperty<TextBaseline>('${prefix}baseline', textBaseline, defaultValue: null));
styles.add(DoubleProperty('${prefix}height', height, unit: 'x', defaultValue: null));
styles.add(EnumProperty<ui.TextLeadingDistribution>('${prefix}leadingDistribution', leadingDistribution, defaultValue: null));
styles.add(EnumProperty<TextLeadingDistribution>('${prefix}leadingDistribution', leadingDistribution, defaultValue: null));
styles.add(DiagnosticsProperty<Locale>('${prefix}locale', locale, defaultValue: null));
styles.add(DiagnosticsProperty<Paint>('${prefix}foreground', foreground, defaultValue: null));
styles.add(DiagnosticsProperty<Paint>('${prefix}background', background, defaultValue: null));
......@@ -1578,3 +1588,95 @@ class TextStyle with Diagnosticable {
styles.add(EnumProperty<TextOverflow>('${prefix}overflow', overflow, defaultValue: null));
}
}
/// Interpolate between two lists of [FontVariation] objects.
///
/// Variations are paired by axis, and interpolated using [FontVariation.lerp].
///
/// Entries that are only present in one list are animated using a step-function
/// at t=0.5 that enables or disables the variation. This can be jarring and
/// largely defeats the point of animating font variations. For best results,
/// specify the same axes in both lists, and for best performance, specify them
/// in the same order.
///
/// ## Performance details
///
/// This algorithm is O(N), but the constant factor varies based on the input,
/// and that is probably more important (because typically N is going to be
/// tiny, like 1 or 2; at the time of writing, there are only about five defined
/// axes that fonts typically use!).
///
/// It is fastest when the lists contain the same axes ([FontVariation.axis]) in
/// the same order. The result is again in the same order, and no attempt is
/// made to detect or remove duplicates in this process. This is, by far, the
/// recommended way to use this algorithm.
///
/// When the order of items in the two input lists vary, the constant factor
/// increases substantially, as it involves creating two maps and a set,
/// inserting every variation in both lists into the maps and the set, and then
/// iterating over them to recreate the list.
///
/// In this case, the resulting order is arbitrary. Duplicates are dropped; in
/// each list, the last [FontVariation] for any particular axis is the one used
/// to compute the value for that axis. Values that only appear on one side are
/// interpolated using [FontVariation.lerp] against a null value, and resulting
/// null values are omitted from the resulting list.
///
/// When the lists begin with matching pairs of axes, the fast algorithm is used
/// up to the point where the lists diverge, and the more expensive algorithm
/// is used on the remaining entries.
///
/// See also:
///
/// * [TextStyle.lerp], which uses this function to handle
/// [TextStyle.fontVariations].
List<FontVariation>? lerpFontVariations(List<FontVariation>? a, List<FontVariation>? b, double t) {
if (t == 0.0) {
return a;
}
if (t == 1.0) {
return b;
}
if (a == null || a.isEmpty || b == null || b.isEmpty) {
// If one side is empty, that means anything on the other
// side will use the null-to-something lerp, which is to
// say, a step function at t=0.5.
return t < 0.5 ? a : b;
}
assert(a.isNotEmpty && b.isNotEmpty);
final List<FontVariation> result = <FontVariation>[];
// First, try the efficient O(N) solution in the event that
// the lists are compatible.
int index = 0;
final int minLength = a.length < b.length ? a.length : b.length;
for (; index < minLength; index += 1) {
if (a[index].axis != b[index].axis) {
// The lists aren't compatible.
break;
}
result.add(FontVariation.lerp(a[index], b[index], t)!);
}
final int maxLength = a.length > b.length ? a.length : b.length;
if (index < maxLength) {
// If we get here, we have found some case where we cannot
// use the efficient approach.
final Set<String> axes = HashSet<String>();
final Map<String, FontVariation> aVariations = HashMap<String, FontVariation>();
for (int indexA = index; indexA < a.length; indexA += 1) {
aVariations[a[indexA].axis] = a[indexA];
axes.add(a[indexA].axis);
}
final Map<String, FontVariation> bVariations = HashMap<String, FontVariation>();
for (int indexB = index; indexB < b.length; indexB += 1) {
bVariations[b[indexB].axis] = b[indexB];
axes.add(b[indexB].axis);
}
for (final String axis in axes) {
final FontVariation? variation = FontVariation.lerp(aVariations[axis], bVariations[axis], t);
if (variation != null) {
result.add(variation);
}
}
}
return result;
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
......
......@@ -595,4 +595,63 @@ void main() {
expect(TextStyle.lerp(fromStyle, toStyle, 1), toStyle);
});
test('lerpFontVariations', () {
// nil cases
expect(lerpFontVariations(const <FontVariation>[], const <FontVariation>[], 0.0), const <FontVariation>[]);
expect(lerpFontVariations(const <FontVariation>[], const <FontVariation>[], 0.5), const <FontVariation>[]);
expect(lerpFontVariations(const <FontVariation>[], const <FontVariation>[], 1.0), const <FontVariation>[]);
expect(lerpFontVariations(null, const <FontVariation>[], 0.0), null);
expect(lerpFontVariations(const <FontVariation>[], null, 0.0), const <FontVariation>[]);
expect(lerpFontVariations(null, null, 0.0), null);
expect(lerpFontVariations(null, const <FontVariation>[], 0.5), const <FontVariation>[]);
expect(lerpFontVariations(const <FontVariation>[], null, 0.5), null);
expect(lerpFontVariations(null, null, 0.5), null);
expect(lerpFontVariations(null, const <FontVariation>[], 1.0), const <FontVariation>[]);
expect(lerpFontVariations(const <FontVariation>[], null, 1.0), null);
expect(lerpFontVariations(null, null, 1.0), null);
const FontVariation w100 = FontVariation.weight(100.0);
const FontVariation w120 = FontVariation.weight(120.0);
const FontVariation w150 = FontVariation.weight(150.0);
const FontVariation w200 = FontVariation.weight(200.0);
const FontVariation w300 = FontVariation.weight(300.0);
const FontVariation w1000 = FontVariation.weight(1000.0);
// one axis
expect(lerpFontVariations(const <FontVariation>[w100], const <FontVariation>[w200], 0.0), const <FontVariation>[w100]);
expect(lerpFontVariations(const <FontVariation>[w100], const <FontVariation>[w200], 0.2), const <FontVariation>[w120]);
expect(lerpFontVariations(const <FontVariation>[w100], const <FontVariation>[w200], 0.5), const <FontVariation>[w150]);
expect(lerpFontVariations(const <FontVariation>[w100], const <FontVariation>[w200], 2.0), const <FontVariation>[w300]);
// weird one axis cases
expect(lerpFontVariations(const <FontVariation>[w100, w1000], const <FontVariation>[w300], 0.0), const <FontVariation>[w100, w1000]);
expect(lerpFontVariations(const <FontVariation>[w100, w1000], const <FontVariation>[w300], 0.5), const <FontVariation>[w200]);
expect(lerpFontVariations(const <FontVariation>[w100, w1000], const <FontVariation>[w300], 1.0), const <FontVariation>[w300]);
expect(lerpFontVariations(const <FontVariation>[w100, w1000], const <FontVariation>[], 0.5), const <FontVariation>[]);
const FontVariation sn80 = FontVariation.slant(-80.0);
const FontVariation sn40 = FontVariation.slant(-40.0);
const FontVariation s0 = FontVariation.slant(0.0);
const FontVariation sp40 = FontVariation.slant(40.0);
const FontVariation sp80 = FontVariation.slant(80.0);
// two axis matched order
expect(lerpFontVariations(const <FontVariation>[w100, sn80], const <FontVariation>[w300, sp80], 0.5), const <FontVariation>[w200, s0]);
// two axis unmatched order
expect(lerpFontVariations(const <FontVariation>[sn80, w100], const <FontVariation>[w300, sp80], 0.0), const <FontVariation>[sn80, w100]);
expect(lerpFontVariations(const <FontVariation>[sn80, w100], const <FontVariation>[w300, sp80], 0.5), unorderedMatches(const <FontVariation>[s0, w200]));
expect(lerpFontVariations(const <FontVariation>[sn80, w100], const <FontVariation>[w300, sp80], 1.0), const <FontVariation>[w300, sp80]);
// two axis with duplicates
expect(lerpFontVariations(const <FontVariation>[sn80, w100, sp80], const <FontVariation>[w300, sp80], 0.5), unorderedMatches(const <FontVariation>[sp80, w200]));
// mixed axis counts
expect(lerpFontVariations(const <FontVariation>[sn80, w100], const <FontVariation>[w300], 0.5), const <FontVariation>[w200]);
expect(lerpFontVariations(const <FontVariation>[sn80], const <FontVariation>[w300], 0.0), const <FontVariation>[sn80]);
expect(lerpFontVariations(const <FontVariation>[sn80], const <FontVariation>[w300], 0.1), const <FontVariation>[sn80]);
expect(lerpFontVariations(const <FontVariation>[sn80], const <FontVariation>[w300], 0.9), const <FontVariation>[w300]);
expect(lerpFontVariations(const <FontVariation>[sn80], const <FontVariation>[w300], 1.0), const <FontVariation>[w300]);
expect(lerpFontVariations(const <FontVariation>[sn40, s0, w100], const <FontVariation>[sp40, w300, sp80], 0.5), anyOf(equals(const <FontVariation>[s0, w200, sp40]), equals(const <FontVariation>[s0, sp40, w200])));
});
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment