| // Copyright 2014 The Flutter 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 'dart:ui' |
| as ui |
| show FontFeature, FontVariation, ParagraphStyle, Shadow, TextStyle, lerpDouble; |
| |
| import 'package:flutter/painting.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| // This matcher verifies ui.TextStyle.toString (from dart:ui) reports a superset |
| // of the given TextStyle's (from painting.dart) properties. |
| class _DartUiTextStyleToStringMatcher extends Matcher { |
| _DartUiTextStyleToStringMatcher(this.textStyle); |
| |
| final TextStyle textStyle; |
| |
| late final List<String> propertiesInOrder = <String>[ |
| _propertyToString('color', textStyle.color), |
| _propertyToString('decoration', textStyle.decoration), |
| _propertyToString('decorationColor', textStyle.decorationColor), |
| _propertyToString('decorationStyle', textStyle.decorationStyle), |
| _propertyToString('decorationThickness', textStyle.decorationThickness), |
| _propertyToString('fontWeight', textStyle.fontWeight), |
| _propertyToString('fontStyle', textStyle.fontStyle), |
| _propertyToString('textBaseline', textStyle.textBaseline), |
| _propertyToString('fontFamily', textStyle.fontFamily), |
| _propertyToString('fontFamilyFallback', textStyle.fontFamilyFallback), |
| _propertyToString('fontSize', textStyle.fontSize), |
| _propertyToString('letterSpacing', textStyle.letterSpacing), |
| _propertyToString('wordSpacing', textStyle.wordSpacing), |
| _propertyToString('height', textStyle.height), |
| _propertyToString('leadingDistribution', textStyle.leadingDistribution), |
| _propertyToString('locale', textStyle.locale), |
| _propertyToString('background', textStyle.background), |
| _propertyToString('foreground', textStyle.foreground), |
| _propertyToString('shadows', textStyle.shadows), |
| _propertyToString('fontFeatures', textStyle.fontFeatures), |
| _propertyToString('fontVariations', textStyle.fontVariations), |
| ]; |
| |
| static String _propertyToString(String name, Object? property) => |
| '$name: ${property ?? 'unspecified'}'; |
| |
| @override |
| Description describe(Description description) => description.add('is a superset of $textStyle.'); |
| |
| @override |
| bool matches(dynamic item, Map<dynamic, dynamic> matchState) { |
| final description = item.toString(); |
| const prefix = 'TextStyle('; |
| const suffix = ')'; |
| if (!description.startsWith(prefix) || !description.endsWith(suffix)) { |
| return false; |
| } |
| |
| final String propertyDescription = description.substring( |
| prefix.length, |
| description.length - suffix.length, |
| ); |
| var startIndex = 0; |
| for (final String property in propertiesInOrder) { |
| startIndex = propertyDescription.indexOf(property, startIndex); |
| if (startIndex < 0) { |
| matchState['missingProperty'] = property; |
| return false; |
| } |
| startIndex += property.length; |
| } |
| return true; |
| } |
| |
| @override |
| Description describeMismatch( |
| dynamic item, |
| Description mismatchDescription, |
| Map<dynamic, dynamic> matchState, |
| bool verbose, |
| ) { |
| final Description description = super.describeMismatch( |
| item, |
| mismatchDescription, |
| matchState, |
| verbose, |
| ); |
| final itemAsString = item.toString(); |
| final property = matchState['missingProperty'] as String?; |
| if (property != null) { |
| description.add("expect property: '$property'"); |
| final int propertyIndex = propertiesInOrder.indexOf(property); |
| if (propertyIndex > 0) { |
| final String lastProperty = propertiesInOrder[propertyIndex - 1]; |
| description.add(" after: '$lastProperty'\n"); |
| description.add('but found: ${itemAsString.substring(itemAsString.indexOf(lastProperty))}'); |
| } |
| description.add('\n'); |
| } |
| return description; |
| } |
| } |
| |
| Matcher matchesToStringOf(TextStyle textStyle) => _DartUiTextStyleToStringMatcher(textStyle); |
| |
| void main() { |
| test('TextStyle control test', () { |
| expect( |
| const TextStyle(inherit: false).toString(), |
| equals('TextStyle(inherit: false, <no style specified>)'), |
| ); |
| expect(const TextStyle().toString(), equals('TextStyle(<all styles inherited>)')); |
| |
| const s1 = TextStyle(fontSize: 10.0, fontWeight: FontWeight.w800, height: 123.0); |
| expect(s1.fontFamily, isNull); |
| expect(s1.fontSize, 10.0); |
| expect(s1.fontWeight, FontWeight.w800); |
| expect(s1.height, 123.0); |
| expect(s1, equals(s1)); |
| expect( |
| s1.toString(), |
| equals('TextStyle(inherit: true, size: 10.0, weight: 800, height: 123.0x)'), |
| ); |
| |
| // Check that the inherit flag can be set with copyWith(). |
| expect( |
| s1.copyWith(inherit: false).toString(), |
| equals('TextStyle(inherit: false, size: 10.0, weight: 800, height: 123.0x)'), |
| ); |
| |
| final TextStyle s2 = s1.copyWith( |
| color: const Color(0xFF00FF00), |
| height: 100.0, |
| leadingDistribution: TextLeadingDistribution.even, |
| ); |
| expect(s1.fontFamily, isNull); |
| expect(s1.fontSize, 10.0); |
| expect(s1.fontWeight, FontWeight.w800); |
| expect(s1.height, 123.0); |
| expect(s1.color, isNull); |
| expect(s2.fontFamily, isNull); |
| expect(s2.fontSize, 10.0); |
| expect(s2.fontWeight, FontWeight.w800); |
| expect(s2.height, 100.0); |
| expect(s2.color, const Color(0xFF00FF00)); |
| expect(s2.leadingDistribution, TextLeadingDistribution.even); |
| expect(s2, isNot(equals(s1))); |
| expect( |
| s2.toString(), |
| equals( |
| 'TextStyle(inherit: true, color: ${const Color(0xff00ff00)}, size: 10.0, weight: 800, height: 100.0x, leadingDistribution: even)', |
| ), |
| ); |
| |
| final TextStyle s3 = s1.apply(fontSizeFactor: 2.0, fontSizeDelta: -2.0, fontWeightDelta: -4); |
| expect(s1.fontFamily, isNull); |
| expect(s1.fontSize, 10.0); |
| expect(s1.fontWeight, FontWeight.w800); |
| expect(s1.height, 123.0); |
| expect(s1.color, isNull); |
| expect(s3.fontFamily, isNull); |
| expect(s3.fontSize, 18.0); |
| expect(s3.fontWeight, FontWeight.w400); |
| expect(s3.height, 123.0); |
| expect(s3.color, isNull); |
| expect(s3, isNot(equals(s1))); |
| |
| expect(s1.apply(fontWeightDelta: -10).fontWeight, FontWeight.w100); |
| expect(s1.apply(fontWeightDelta: 2).fontWeight, FontWeight.w900); |
| expect(s1.merge(null), equals(s1)); |
| |
| final TextStyle s4 = s2.merge(s1); |
| expect(s1.fontFamily, isNull); |
| expect(s1.fontSize, 10.0); |
| expect(s1.fontWeight, FontWeight.w800); |
| expect(s1.height, 123.0); |
| expect(s1.color, isNull); |
| expect(s2.fontFamily, isNull); |
| expect(s2.fontSize, 10.0); |
| expect(s2.fontWeight, FontWeight.w800); |
| expect(s2.height, 100.0); |
| expect(s2.color, const Color(0xFF00FF00)); |
| expect(s2.leadingDistribution, TextLeadingDistribution.even); |
| expect(s2, isNot(equals(s1))); |
| expect(s2, isNot(equals(s4))); |
| expect(s4.fontFamily, isNull); |
| expect(s4.fontSize, 10.0); |
| expect(s4.fontWeight, FontWeight.w800); |
| expect(s4.height, 123.0); |
| expect(s4.color, const Color(0xFF00FF00)); |
| expect(s4.leadingDistribution, TextLeadingDistribution.even); |
| |
| final TextStyle s5 = TextStyle.lerp(s1, s3, 0.25)!; |
| expect(s1.fontFamily, isNull); |
| expect(s1.fontSize, 10.0); |
| expect(s1.fontWeight, FontWeight.w800); |
| expect(s1.height, 123.0); |
| expect(s1.color, isNull); |
| expect(s3.fontFamily, isNull); |
| expect(s3.fontSize, 18.0); |
| expect(s3.fontWeight, FontWeight.w400); |
| expect(s3.height, 123.0); |
| expect(s3.color, isNull); |
| expect(s3, isNot(equals(s1))); |
| expect(s3, isNot(equals(s5))); |
| expect(s5.fontFamily, isNull); |
| expect(s5.fontSize, 12.0); |
| expect(s5.fontWeight, FontWeight.w700); |
| expect(s5.height, 123.0); |
| expect(s5.color, isNull); |
| |
| expect(TextStyle.lerp(null, null, 0.5), isNull); |
| |
| final TextStyle s6 = TextStyle.lerp(null, s3, 0.25)!; |
| expect(s3.fontFamily, isNull); |
| expect(s3.fontSize, 18.0); |
| expect(s3.fontWeight, FontWeight.w400); |
| expect(s3.height, 123.0); |
| expect(s3.color, isNull); |
| expect(s3, isNot(equals(s6))); |
| expect(s6.fontFamily, isNull); |
| expect(s6.fontSize, isNull); |
| expect(s6.fontWeight, FontWeight.w400); |
| expect(s6.height, isNull); |
| expect(s6.color, isNull); |
| |
| final TextStyle s7 = TextStyle.lerp(null, s3, 0.75)!; |
| expect(s3.fontFamily, isNull); |
| expect(s3.fontSize, 18.0); |
| expect(s3.fontWeight, FontWeight.w400); |
| expect(s3.height, 123.0); |
| expect(s3.color, isNull); |
| expect(s3, equals(s7)); |
| expect(s7.fontFamily, isNull); |
| expect(s7.fontSize, 18.0); |
| expect(s7.fontWeight, FontWeight.w400); |
| expect(s7.height, 123.0); |
| expect(s7.color, isNull); |
| |
| final TextStyle s8 = TextStyle.lerp(s3, null, 0.25)!; |
| expect(s3.fontFamily, isNull); |
| expect(s3.fontSize, 18.0); |
| expect(s3.fontWeight, FontWeight.w400); |
| expect(s3.height, 123.0); |
| expect(s3.color, isNull); |
| expect(s3, equals(s8)); |
| expect(s8.fontFamily, isNull); |
| expect(s8.fontSize, 18.0); |
| expect(s8.fontWeight, FontWeight.w400); |
| expect(s8.height, 123.0); |
| expect(s8.color, isNull); |
| |
| final TextStyle s9 = TextStyle.lerp(s3, null, 0.75)!; |
| expect(s3.fontFamily, isNull); |
| expect(s3.fontSize, 18.0); |
| expect(s3.fontWeight, FontWeight.w400); |
| expect(s3.height, 123.0); |
| expect(s3.color, isNull); |
| expect(s3, isNot(equals(s9))); |
| expect(s9.fontFamily, isNull); |
| expect(s9.fontSize, isNull); |
| expect(s9.fontWeight, FontWeight.w400); |
| expect(s9.height, isNull); |
| expect(s9.color, isNull); |
| |
| final ui.TextStyle ts5 = s5.getTextStyle(); |
| expect(ts5, equals(ui.TextStyle(fontWeight: FontWeight.w700, fontSize: 12.0, height: 123.0))); |
| expect(ts5, matchesToStringOf(s5)); |
| final ui.TextStyle ts2 = s2.getTextStyle(); |
| expect( |
| ts2, |
| equals( |
| ui.TextStyle( |
| color: const Color(0xFF00FF00), |
| fontWeight: FontWeight.w800, |
| fontSize: 10.0, |
| height: 100.0, |
| leadingDistribution: TextLeadingDistribution.even, |
| ), |
| ), |
| ); |
| expect(ts2, matchesToStringOf(s2)); |
| |
| final ui.ParagraphStyle ps2 = s2.getParagraphStyle(textAlign: TextAlign.center); |
| expect( |
| ps2, |
| equals( |
| ui.ParagraphStyle( |
| textAlign: TextAlign.center, |
| fontWeight: FontWeight.w800, |
| fontSize: 10.0, |
| height: 100.0, |
| textHeightBehavior: const TextHeightBehavior( |
| leadingDistribution: TextLeadingDistribution.even, |
| ), |
| ), |
| ), |
| ); |
| final ui.ParagraphStyle ps5 = s5.getParagraphStyle(); |
| expect( |
| ps5, |
| equals(ui.ParagraphStyle(fontWeight: FontWeight.w700, fontSize: 12.0, height: 123.0)), |
| ); |
| }); |
| |
| test('TextStyle with text direction', () { |
| final ui.ParagraphStyle ps6 = const TextStyle().getParagraphStyle( |
| textDirection: TextDirection.ltr, |
| ); |
| expect(ps6, equals(ui.ParagraphStyle(textDirection: TextDirection.ltr, fontSize: 14.0))); |
| |
| final ui.ParagraphStyle ps7 = const TextStyle().getParagraphStyle( |
| textDirection: TextDirection.rtl, |
| ); |
| expect(ps7, equals(ui.ParagraphStyle(textDirection: TextDirection.rtl, fontSize: 14.0))); |
| }); |
| |
| test('TextStyle using package font', () { |
| const s6 = TextStyle(fontFamily: 'test'); |
| expect(s6.fontFamily, 'test'); |
| expect(s6.getTextStyle(), matchesToStringOf(s6)); |
| |
| const s7 = TextStyle(fontFamily: 'test', package: 'p'); |
| expect(s7.fontFamily, 'packages/p/test'); |
| expect(s7.getTextStyle(), matchesToStringOf(s7)); |
| |
| const s8 = TextStyle(fontFamilyFallback: <String>['test', 'test2'], package: 'p'); |
| expect(s8.fontFamilyFallback![0], 'packages/p/test'); |
| expect(s8.fontFamilyFallback![1], 'packages/p/test2'); |
| expect(s8.fontFamilyFallback!.length, 2); |
| |
| const s9 = TextStyle(package: 'p'); |
| expect(s9.fontFamilyFallback, null); |
| |
| const s10 = TextStyle(fontFamilyFallback: <String>[], package: 'p'); |
| expect(s10.fontFamilyFallback, <String>[]); |
| |
| // Ensure that package prefix is not duplicated after copying. |
| final TextStyle s11 = s8.copyWith(); |
| expect(s11.fontFamilyFallback![0], 'packages/p/test'); |
| expect(s11.fontFamilyFallback![1], 'packages/p/test2'); |
| expect(s11.fontFamilyFallback!.length, 2); |
| expect(s8, s11); |
| |
| // Ensure that package prefix is not duplicated after applying. |
| final TextStyle s12 = s8.apply(); |
| expect(s12.fontFamilyFallback![0], 'packages/p/test'); |
| expect(s12.fontFamilyFallback![1], 'packages/p/test2'); |
| expect(s12.fontFamilyFallback!.length, 2); |
| expect(s8, s12); |
| }); |
| |
| test('TextStyle package font merge', () { |
| const s1 = TextStyle( |
| package: 'p', |
| fontFamily: 'font1', |
| fontFamilyFallback: <String>['fallback1'], |
| ); |
| const s2 = TextStyle( |
| package: 'p', |
| fontFamily: 'font2', |
| fontFamilyFallback: <String>['fallback2'], |
| ); |
| |
| final TextStyle emptyMerge = const TextStyle().merge(s1); |
| expect(emptyMerge.fontFamily, 'packages/p/font1'); |
| expect(emptyMerge.fontFamilyFallback, <String>['packages/p/fallback1']); |
| |
| final TextStyle lerp1 = TextStyle.lerp(s1, s2, 0)!; |
| expect(lerp1.fontFamily, 'packages/p/font1'); |
| expect(lerp1.fontFamilyFallback, <String>['packages/p/fallback1']); |
| |
| final TextStyle lerp2 = TextStyle.lerp(s1, s2, 1.0)!; |
| expect(lerp2.fontFamily, 'packages/p/font2'); |
| expect(lerp2.fontFamilyFallback, <String>['packages/p/fallback2']); |
| }); |
| |
| test('TextStyle font family fallback', () { |
| const s1 = TextStyle(fontFamilyFallback: <String>['Roboto', 'test']); |
| expect(s1.fontFamilyFallback![0], 'Roboto'); |
| expect(s1.fontFamilyFallback![1], 'test'); |
| expect(s1.fontFamilyFallback!.length, 2); |
| |
| const s2 = TextStyle(fontFamily: 'foo', fontFamilyFallback: <String>['Roboto', 'test']); |
| expect(s2.fontFamilyFallback![0], 'Roboto'); |
| expect(s2.fontFamilyFallback![1], 'test'); |
| expect(s2.fontFamily, 'foo'); |
| expect(s2.fontFamilyFallback!.length, 2); |
| |
| const s3 = TextStyle(fontFamily: 'foo'); |
| expect(s3.fontFamily, 'foo'); |
| expect(s3.fontFamilyFallback, null); |
| |
| const s4 = TextStyle(fontFamily: 'foo', fontFamilyFallback: <String>[]); |
| expect(s4.fontFamily, 'foo'); |
| expect(s4.fontFamilyFallback, <String>[]); |
| expect(s4.fontFamilyFallback!.isEmpty, true); |
| |
| final ui.TextStyle uis1 = s2.getTextStyle(); |
| expect(uis1, matchesToStringOf(s2)); |
| |
| expect(s2.apply().fontFamily, 'foo'); |
| expect(s2.apply().fontFamilyFallback, const <String>['Roboto', 'test']); |
| expect(s2.apply(fontFamily: 'bar').fontFamily, 'bar'); |
| expect( |
| s2.apply(fontFamilyFallback: const <String>['Banana']).fontFamilyFallback, |
| const <String>['Banana'], |
| ); |
| }); |
| |
| test('TextStyle.debugLabel', () { |
| const unknown = TextStyle(); |
| const foo = TextStyle(debugLabel: 'foo', fontSize: 1.0); |
| const bar = TextStyle(debugLabel: 'bar', fontSize: 2.0); |
| const baz = TextStyle(debugLabel: 'baz', fontSize: 3.0); |
| |
| expect(unknown.debugLabel, null); |
| expect(unknown.toString(), 'TextStyle(<all styles inherited>)'); |
| expect(unknown.copyWith().debugLabel, null); |
| expect(unknown.copyWith(debugLabel: '123').debugLabel, '123'); |
| expect(unknown.apply().debugLabel, null); |
| |
| expect(foo.debugLabel, 'foo'); |
| expect(foo.toString(), 'TextStyle(debugLabel: foo, inherit: true, size: 1.0)'); |
| expect(foo.merge(bar).debugLabel, '(foo).merge(bar)'); |
| expect(foo.merge(bar).merge(baz).debugLabel, '((foo).merge(bar)).merge(baz)'); |
| expect(foo.copyWith().debugLabel, '(foo).copyWith'); |
| expect(foo.apply().debugLabel, '(foo).apply'); |
| expect(TextStyle.lerp(foo, bar, 0.5)!.debugLabel, 'lerp(foo ⎯0.5→ bar)'); |
| expect( |
| TextStyle.lerp(foo.merge(bar), baz, 0.51)!.copyWith().debugLabel, |
| '(lerp((foo).merge(bar) ⎯0.5→ baz)).copyWith', |
| ); |
| }); |
| |
| test('TextStyle.hashCode', () { |
| const a = TextStyle( |
| fontFamilyFallback: <String>['Roboto'], |
| shadows: <ui.Shadow>[ui.Shadow()], |
| fontFeatures: <ui.FontFeature>[ui.FontFeature('abcd')], |
| fontVariations: <ui.FontVariation>[ui.FontVariation('wght', 123.0)], |
| ); |
| const b = TextStyle( |
| fontFamilyFallback: <String>['Noto'], |
| shadows: <ui.Shadow>[ui.Shadow()], |
| fontFeatures: <ui.FontFeature>[ui.FontFeature('abcd')], |
| fontVariations: <ui.FontVariation>[ui.FontVariation('wght', 123.0)], |
| ); |
| expect(a.hashCode, a.hashCode); |
| expect(a.hashCode, isNot(equals(b.hashCode))); |
| |
| const c = TextStyle(leadingDistribution: TextLeadingDistribution.even); |
| const d = TextStyle(leadingDistribution: TextLeadingDistribution.proportional); |
| expect(c.hashCode, c.hashCode); |
| expect(c.hashCode, isNot(d.hashCode)); |
| }); |
| |
| test('TextStyle shadows', () { |
| const shadow1 = ui.Shadow(blurRadius: 1.0, offset: Offset(1.0, 1.0)); |
| const shadow2 = ui.Shadow(blurRadius: 2.0, color: Color(0xFF111111), offset: Offset(2.0, 2.0)); |
| const shadow3 = ui.Shadow(blurRadius: 3.0, color: Color(0xFF222222), offset: Offset(3.0, 3.0)); |
| const shadow4 = ui.Shadow(blurRadius: 4.0, color: Color(0xFF333333), offset: Offset(4.0, 4.0)); |
| |
| const s1 = TextStyle(shadows: <ui.Shadow>[shadow1, shadow2]); |
| const s2 = TextStyle(shadows: <ui.Shadow>[shadow3, shadow4]); |
| |
| final TextStyle lerp12 = TextStyle.lerp(s1, s2, 0.5)!; |
| |
| expect(lerp12.shadows, hasLength(2)); |
| expect( |
| lerp12.shadows?[0].blurRadius, |
| ui.lerpDouble(shadow1.blurRadius, shadow3.blurRadius, 0.5), |
| ); |
| expect(lerp12.shadows?[0].color, Color.lerp(shadow1.color, shadow3.color, 0.5)); |
| expect(lerp12.shadows?[0].offset, Offset.lerp(shadow1.offset, shadow3.offset, 0.5)); |
| expect( |
| lerp12.shadows?[1].blurRadius, |
| ui.lerpDouble(shadow2.blurRadius, shadow4.blurRadius, 0.5), |
| ); |
| expect(lerp12.shadows?[1].color, Color.lerp(shadow2.color, shadow4.color, 0.5)); |
| expect(lerp12.shadows?[1].offset, Offset.lerp(shadow2.offset, shadow4.offset, 0.5)); |
| }); |
| |
| test('TextStyle foreground and color combos', () { |
| const red = Color.fromARGB(255, 255, 0, 0); |
| const blue = Color.fromARGB(255, 0, 0, 255); |
| const redTextStyle = TextStyle(color: red); |
| const blueTextStyle = TextStyle(color: blue); |
| final redPaintTextStyle = TextStyle(foreground: Paint()..color = red); |
| final bluePaintTextStyle = TextStyle(foreground: Paint()..color = blue); |
| |
| // merge/copyWith |
| final TextStyle redBlueBothForegroundMerged = redTextStyle.merge(blueTextStyle); |
| expect(redBlueBothForegroundMerged.color, blue); |
| expect(redBlueBothForegroundMerged.foreground, isNull); |
| |
| final TextStyle redBlueBothPaintMerged = redPaintTextStyle.merge(bluePaintTextStyle); |
| expect(redBlueBothPaintMerged.color, null); |
| expect(redBlueBothPaintMerged.foreground, bluePaintTextStyle.foreground); |
| |
| final TextStyle redPaintBlueColorMerged = redPaintTextStyle.merge(blueTextStyle); |
| expect(redPaintBlueColorMerged.color, null); |
| expect(redPaintBlueColorMerged.foreground, redPaintTextStyle.foreground); |
| |
| final TextStyle blueColorRedPaintMerged = blueTextStyle.merge(redPaintTextStyle); |
| expect(blueColorRedPaintMerged.color, null); |
| expect(blueColorRedPaintMerged.foreground, redPaintTextStyle.foreground); |
| |
| // apply |
| expect(redPaintTextStyle.apply(color: blue).color, isNull); |
| expect(redPaintTextStyle.apply(color: blue).foreground!.color, red); |
| expect(redTextStyle.apply(color: blue).color, blue); |
| |
| // lerp |
| expect(TextStyle.lerp(redTextStyle, blueTextStyle, .25)!.color, Color.lerp(red, blue, .25)); |
| expect(TextStyle.lerp(redTextStyle, bluePaintTextStyle, .25)!.color, isNull); |
| expect(TextStyle.lerp(redTextStyle, bluePaintTextStyle, .25)!.foreground!.color, red); |
| expect(TextStyle.lerp(redTextStyle, bluePaintTextStyle, .75)!.foreground!.color, blue); |
| |
| expect(TextStyle.lerp(redPaintTextStyle, bluePaintTextStyle, .25)!.color, isNull); |
| expect(TextStyle.lerp(redPaintTextStyle, bluePaintTextStyle, .25)!.foreground!.color, red); |
| expect(TextStyle.lerp(redPaintTextStyle, bluePaintTextStyle, .75)!.foreground!.color, blue); |
| }); |
| |
| test('backgroundColor', () { |
| const s1 = TextStyle(); |
| expect(s1.backgroundColor, isNull); |
| expect(s1.toString(), 'TextStyle(<all styles inherited>)'); |
| |
| const s2 = TextStyle(backgroundColor: Color(0xFF00FF00)); |
| expect(s2.backgroundColor, const Color(0xFF00FF00)); |
| expect(s2.toString(), 'TextStyle(inherit: true, backgroundColor: ${const Color(0xff00ff00)})'); |
| |
| final ui.TextStyle ts2 = s2.getTextStyle(); |
| |
| // TODO(matanlurey): Remove when https://github.com/flutter/flutter/issues/112498 is resolved. |
| // The web implementation never includes "dither: ..." as a property, and after #112498 neither |
| // does non-web (as there will no longer be a user-visible "dither" property). So, relax the |
| // test to just check for the color by using a regular expression. |
| expect(ts2.toString(), matches(RegExp(r'background: Paint\(Color\(.*\).*\)'))); |
| }); |
| |
| test('TextStyle background and backgroundColor combos', () { |
| const red = Color.fromARGB(255, 255, 0, 0); |
| const blue = Color.fromARGB(255, 0, 0, 255); |
| const redTextStyle = TextStyle(backgroundColor: red); |
| const blueTextStyle = TextStyle(backgroundColor: blue); |
| final redPaintTextStyle = TextStyle(background: Paint()..color = red); |
| final bluePaintTextStyle = TextStyle(background: Paint()..color = blue); |
| |
| // merge/copyWith |
| final TextStyle redBlueBothForegroundMerged = redTextStyle.merge(blueTextStyle); |
| expect(redBlueBothForegroundMerged.backgroundColor, blue); |
| expect(redBlueBothForegroundMerged.foreground, isNull); |
| |
| final TextStyle redBlueBothPaintMerged = redPaintTextStyle.merge(bluePaintTextStyle); |
| expect(redBlueBothPaintMerged.backgroundColor, null); |
| expect(redBlueBothPaintMerged.background, bluePaintTextStyle.background); |
| |
| final TextStyle redPaintBlueColorMerged = redPaintTextStyle.merge(blueTextStyle); |
| expect(redPaintBlueColorMerged.backgroundColor, null); |
| expect(redPaintBlueColorMerged.background, redPaintTextStyle.background); |
| |
| final TextStyle blueColorRedPaintMerged = blueTextStyle.merge(redPaintTextStyle); |
| expect(blueColorRedPaintMerged.backgroundColor, null); |
| expect(blueColorRedPaintMerged.background, redPaintTextStyle.background); |
| |
| // apply |
| expect(redPaintTextStyle.apply(backgroundColor: blue).backgroundColor, isNull); |
| expect(redPaintTextStyle.apply(backgroundColor: blue).background!.color, red); |
| expect(redTextStyle.apply(backgroundColor: blue).backgroundColor, blue); |
| |
| // lerp |
| expect( |
| TextStyle.lerp(redTextStyle, blueTextStyle, .25)!.backgroundColor, |
| Color.lerp(red, blue, .25), |
| ); |
| expect(TextStyle.lerp(redTextStyle, bluePaintTextStyle, .25)!.backgroundColor, isNull); |
| expect(TextStyle.lerp(redTextStyle, bluePaintTextStyle, .25)!.background!.color, red); |
| expect(TextStyle.lerp(redTextStyle, bluePaintTextStyle, .75)!.background!.color, blue); |
| |
| expect(TextStyle.lerp(redPaintTextStyle, bluePaintTextStyle, .25)!.backgroundColor, isNull); |
| expect(TextStyle.lerp(redPaintTextStyle, bluePaintTextStyle, .25)!.background!.color, red); |
| expect(TextStyle.lerp(redPaintTextStyle, bluePaintTextStyle, .75)!.background!.color, blue); |
| }); |
| |
| test('TextStyle strut textScaler', () { |
| const style0 = TextStyle(fontSize: 10); |
| final ui.ParagraphStyle paragraphStyle0 = style0.getParagraphStyle( |
| textScaler: const TextScaler.linear(2.5), |
| ); |
| |
| const style1 = TextStyle(fontSize: 25); |
| final ui.ParagraphStyle paragraphStyle1 = style1.getParagraphStyle(); |
| |
| expect(paragraphStyle0 == paragraphStyle1, true); |
| }); |
| |
| test('TextStyle apply', () { |
| const style = TextStyle( |
| fontSize: 10, |
| shadows: <ui.Shadow>[], |
| fontStyle: FontStyle.normal, |
| fontFeatures: <ui.FontFeature>[], |
| fontVariations: <ui.FontVariation>[], |
| textBaseline: TextBaseline.alphabetic, |
| leadingDistribution: TextLeadingDistribution.even, |
| ); |
| expect(style.apply().shadows, const <ui.Shadow>[]); |
| expect( |
| style.apply(shadows: const <ui.Shadow>[ui.Shadow(blurRadius: 2.0)]).shadows, |
| const <ui.Shadow>[ui.Shadow(blurRadius: 2.0)], |
| ); |
| expect(style.apply().fontStyle, FontStyle.normal); |
| expect(style.apply(fontStyle: FontStyle.italic).fontStyle, FontStyle.italic); |
| expect(style.apply().locale, isNull); |
| expect( |
| style.apply(locale: const Locale.fromSubtags(languageCode: 'es')).locale, |
| const Locale.fromSubtags(languageCode: 'es'), |
| ); |
| expect(style.apply().fontFeatures, const <ui.FontFeature>[]); |
| expect( |
| style.apply(fontFeatures: const <ui.FontFeature>[ui.FontFeature.enable('test')]).fontFeatures, |
| const <ui.FontFeature>[ui.FontFeature.enable('test')], |
| ); |
| expect(style.apply().fontVariations, const <ui.FontVariation>[]); |
| expect( |
| style |
| .apply(fontVariations: const <ui.FontVariation>[ui.FontVariation('test', 100.0)]) |
| .fontVariations, |
| const <ui.FontVariation>[ui.FontVariation('test', 100.0)], |
| ); |
| expect(style.apply().textBaseline, TextBaseline.alphabetic); |
| expect( |
| style.apply(textBaseline: TextBaseline.ideographic).textBaseline, |
| TextBaseline.ideographic, |
| ); |
| expect(style.apply().leadingDistribution, TextLeadingDistribution.even); |
| expect( |
| style.apply(leadingDistribution: TextLeadingDistribution.proportional).leadingDistribution, |
| TextLeadingDistribution.proportional, |
| ); |
| |
| expect( |
| const TextStyle(height: kTextHeightNone).apply(heightFactor: 1000, heightDelta: 1000).height, |
| kTextHeightNone, |
| ); |
| }); |
| |
| test('TextStyle fontFamily and package', () { |
| expect( |
| const TextStyle(fontFamily: 'fontFamily', package: 'foo') != |
| const TextStyle(fontFamily: 'fontFamily', package: 'bar'), |
| true, |
| ); |
| expect( |
| const TextStyle(fontFamily: 'fontFamily', package: 'foo').hashCode != |
| const TextStyle(package: 'bar', fontFamily: 'fontFamily').hashCode, |
| true, |
| ); |
| expect(const TextStyle(fontFamily: 'fontFamily').fontFamily, 'fontFamily'); |
| expect(const TextStyle(fontFamily: 'fontFamily').fontFamily, 'fontFamily'); |
| expect( |
| const TextStyle(fontFamily: 'fontFamily').copyWith(package: 'bar').fontFamily, |
| 'packages/bar/fontFamily', |
| ); |
| expect( |
| const TextStyle(fontFamily: 'fontFamily', package: 'foo').fontFamily, |
| 'packages/foo/fontFamily', |
| ); |
| expect( |
| const TextStyle(fontFamily: 'fontFamily', package: 'foo').copyWith(package: 'bar').fontFamily, |
| 'packages/bar/fontFamily', |
| ); |
| expect( |
| const TextStyle().merge(const TextStyle(fontFamily: 'fontFamily', package: 'bar')).fontFamily, |
| 'packages/bar/fontFamily', |
| ); |
| expect( |
| const TextStyle().apply(fontFamily: 'fontFamily', package: 'foo').fontFamily, |
| 'packages/foo/fontFamily', |
| ); |
| expect( |
| const TextStyle( |
| fontFamily: 'fontFamily', |
| package: 'foo', |
| ).apply(fontFamily: 'fontFamily', package: 'bar').fontFamily, |
| 'packages/bar/fontFamily', |
| ); |
| }); |
| |
| test('TextStyle.lerp identical a,b', () { |
| expect(TextStyle.lerp(null, null, 0), null); |
| const style = TextStyle(); |
| expect(identical(TextStyle.lerp(style, style, 0.5), style), true); |
| }); |
| |
| test('Throws when lerping between inherit:true and inherit:false with unspecified fields', () { |
| const fromStyle = TextStyle(); |
| const toStyle = TextStyle(inherit: false); |
| expect(() => TextStyle.lerp(fromStyle, toStyle, 0.5), throwsFlutterError); |
| expect(TextStyle.lerp(fromStyle, fromStyle, 0.5), fromStyle); |
| }); |
| |
| test( |
| 'Does not throw when lerping between inherit:true and inherit:false but fully specified styles', |
| () { |
| const fromStyle = TextStyle(); |
| const toStyle = TextStyle( |
| inherit: false, |
| color: Color(0x87654321), |
| backgroundColor: Color(0x12345678), |
| fontSize: 20, |
| letterSpacing: 1, |
| wordSpacing: 1, |
| height: 20, |
| decorationColor: Color(0x11111111), |
| decorationThickness: 5, |
| ); |
| 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 w100 = FontVariation.weight(100.0); |
| const w120 = FontVariation.weight(120.0); |
| const w150 = FontVariation.weight(150.0); |
| const w200 = FontVariation.weight(200.0); |
| const w300 = FontVariation.weight(300.0); |
| const 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 sn80 = FontVariation.slant(-80.0); |
| const sn40 = FontVariation.slant(-40.0); |
| const s0 = FontVariation.slant(0.0); |
| const sp40 = FontVariation.slant(40.0); |
| const 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]), |
| ), |
| ); |
| }); |
| } |