diff --git a/lib/ui/text.dart b/lib/ui/text.dart index 6d74a9c418c16..ce9358d90683c 100644 --- a/lib/ui/text.dart +++ b/lib/ui/text.dart @@ -1658,11 +1658,10 @@ class TextHeightBehavior { /// Creates a new TextHeightBehavior object from an encoded form. /// - /// See [encode] for the creation of the encoded form. - TextHeightBehavior.fromEncoded(int encoded) + /// See [_encode] for the creation of the encoded form. + const TextHeightBehavior._fromEncoded(int encoded, this.leadingDistribution) : applyHeightToFirstAscent = (encoded & 0x1) == 0, - applyHeightToLastDescent = (encoded & 0x2) == 0, - leadingDistribution = TextLeadingDistribution.values[encoded >> 2]; + applyHeightToLastDescent = (encoded & 0x2) == 0; /// Whether to apply the [TextStyle.height] modifier to the ascent of the first /// line in the paragraph. @@ -1700,11 +1699,11 @@ class TextHeightBehavior { /// Defaults to [TextLeadingDistribution.proportional], final TextLeadingDistribution leadingDistribution; - /// Returns an encoded int representation of this object. - int encode() { + /// Returns an encoded int representation of this object (excluding + /// [leadingDistribution]). + int _encode() { return (applyHeightToFirstAscent ? 0 : 1 << 0) - | (applyHeightToLastDescent ? 0 : 1 << 1) - | (leadingDistribution.index << 2); + | (applyHeightToLastDescent ? 0 : 1 << 1); } @override @@ -1760,7 +1759,8 @@ bool _listEquals(List? a, List? b) { // - Element 0: A bit field where the ith bit indicates whether the ith element // has a non-null value. Bits 8 to 12 indicate whether |fontFamily|, // |fontSize|, |letterSpacing|, |wordSpacing|, and |height| are non-null, -// respectively. Bit 0 is unused. +// respectively. Bit 0 indicates the [TextLeadingDistribution] of the text +// style. // // - Element 1: The |color| in ARGB with 8 bits per channel. // @@ -1778,8 +1778,6 @@ bool _listEquals(List? a, List? b) { // // - Element 7: The enum index of the |textBaseline|. // -// - Element 8: The encoded value of the |leadingDistribution|. -// Int32List _encodeTextStyle( Color? color, TextDecoration? decoration, @@ -1795,7 +1793,6 @@ Int32List _encodeTextStyle( double? letterSpacing, double? wordSpacing, double? height, - TextLeadingDistribution? leadingDistribution, Locale? locale, Paint? background, Paint? foreground, @@ -1803,6 +1800,8 @@ Int32List _encodeTextStyle( List? fontFeatures, ) { final Int32List result = Int32List(9); + // The 0th bit of result[0] is reserved for leadingDistribution. + if (color != null) { result[0] |= 1 << 1; result[1] = color.value; @@ -1831,51 +1830,47 @@ Int32List _encodeTextStyle( result[0] |= 1 << 7; result[7] = textBaseline.index; } - if (leadingDistribution != null) { - result[0] |= 1 << 8; - result[8] = leadingDistribution.index; - } if (decorationThickness != null) { - result[0] |= 1 << 9; + result[0] |= 1 << 8; } if (fontFamily != null || (fontFamilyFallback != null && fontFamilyFallback.isNotEmpty)) { - result[0] |= 1 << 10; + result[0] |= 1 << 9; // Passed separately to native. } if (fontSize != null) { - result[0] |= 1 << 11; + result[0] |= 1 << 10; // Passed separately to native. } if (letterSpacing != null) { - result[0] |= 1 << 12; + result[0] |= 1 << 11; // Passed separately to native. } if (wordSpacing != null) { - result[0] |= 1 << 13; + result[0] |= 1 << 12; // Passed separately to native. } if (height != null) { - result[0] |= 1 << 14; + result[0] |= 1 << 13; // Passed separately to native. } if (locale != null) { - result[0] |= 1 << 15; + result[0] |= 1 << 14; // Passed separately to native. } if (background != null) { - result[0] |= 1 << 16; + result[0] |= 1 << 15; // Passed separately to native. } if (foreground != null) { - result[0] |= 1 << 17; + result[0] |= 1 << 16; // Passed separately to native. } if (shadows != null) { - result[0] |= 1 << 18; + result[0] |= 1 << 17; // Passed separately to native. } if (fontFeatures != null) { - result[0] |= 1 << 19; + result[0] |= 1 << 18; // Passed separately to native. } @@ -1913,7 +1908,8 @@ class TextStyle { /// * `textBaseline`: The common baseline that should be aligned between this text span and its parent text span, or, for the root text spans, with the line box. /// * `height`: The height of this text span, as a multiplier of the font size. Omitting `height` will allow the line height /// to take the height as defined by the font, which may not be exactly the height of the fontSize. - /// * `leadingDistribution`: When `height` is specified, how the extra vertical space should be distributed over and under the text. + /// * `leadingDistribution`: When `height` is specified, how the extra vertical space should be distributed over and under the text. Defaults + /// to the paragraph's [TextHeightBehavior] if left unspecified. /// * `locale`: The locale used to select region-specific glyphs. /// * `background`: The paint drawn as a background for the text. /// * `foreground`: The paint used to draw the text. If this is specified, `color` must be null. @@ -1958,13 +1954,13 @@ class TextStyle { letterSpacing, wordSpacing, height, - leadingDistribution, locale, background, foreground, shadows, fontFeatures, ), + _leadingDistribution = leadingDistribution, _fontFamily = fontFamily ?? '', _fontFamilyFallback = fontFamilyFallback, _fontSize = fontSize, @@ -1991,12 +1987,14 @@ class TextStyle { final Paint? _foreground; final List? _shadows; final List? _fontFeatures; + final TextLeadingDistribution? _leadingDistribution; @override bool operator ==(Object other) { if (identical(this, other)) return true; return other is TextStyle + && other._leadingDistribution == _leadingDistribution && other._fontFamily == _fontFamily && other._fontSize == _fontSize && other._letterSpacing == _letterSpacing @@ -2013,7 +2011,7 @@ class TextStyle { } @override - int get hashCode => hashValues(hashList(_encoded), _fontFamily, _fontFamilyFallback, _fontSize, _letterSpacing, _wordSpacing, _height, _locale, _background, _foreground, hashList(_shadows), _decorationThickness, hashList(_fontFeatures)); + int get hashCode => hashValues(hashList(_encoded), _leadingDistribution, _fontFamily, _fontFamilyFallback, _fontSize, _letterSpacing, _wordSpacing, _height, _locale, _background, _foreground, hashList(_shadows), _decorationThickness, hashList(_fontFeatures)); @override String toString() { @@ -2023,25 +2021,25 @@ class TextStyle { 'decorationColor: ${ _encoded[0] & 0x00008 == 0x00008 ? Color(_encoded[3]) : "unspecified"}, ' 'decorationStyle: ${ _encoded[0] & 0x00010 == 0x00010 ? TextDecorationStyle.values[_encoded[4]] : "unspecified"}, ' // The decorationThickness is not in encoded order in order to keep it near the other decoration properties. - 'decorationThickness: ${_encoded[0] & 0x00200 == 0x00200 ? _decorationThickness : "unspecified"}, ' + 'decorationThickness: ${_encoded[0] & 0x00100 == 0x00100 ? _decorationThickness : "unspecified"}, ' 'fontWeight: ${ _encoded[0] & 0x00020 == 0x00020 ? FontWeight.values[_encoded[5]] : "unspecified"}, ' 'fontStyle: ${ _encoded[0] & 0x00040 == 0x00040 ? FontStyle.values[_encoded[6]] : "unspecified"}, ' 'textBaseline: ${ _encoded[0] & 0x00080 == 0x00080 ? TextBaseline.values[_encoded[7]] : "unspecified"}, ' - 'fontFamily: ${ _encoded[0] & 0x00400 == 0x00400 + 'fontFamily: ${ _encoded[0] & 0x00200 == 0x00200 && _fontFamily != '' ? _fontFamily : "unspecified"}, ' - 'fontFamilyFallback: ${ _encoded[0] & 0x00400 == 0x00400 + 'fontFamilyFallback: ${ _encoded[0] & 0x00200 == 0x00200 && _fontFamilyFallback != null && _fontFamilyFallback!.isNotEmpty ? _fontFamilyFallback : "unspecified"}, ' - 'fontSize: ${ _encoded[0] & 0x00800 == 0x00800 ? _fontSize : "unspecified"}, ' - 'letterSpacing: ${ _encoded[0] & 0x01000 == 0x01000 ? "${_letterSpacing}x" : "unspecified"}, ' - 'wordSpacing: ${ _encoded[0] & 0x02000 == 0x02000 ? "${_wordSpacing}x" : "unspecified"}, ' - 'height: ${ _encoded[0] & 0x04000 == 0x04000 ? "${_height}x" : "unspecified"}, ' - 'leadingDistribution: ${_encoded[0] & 0x0100 == 0x0100 ? "${TextLeadingDistribution.values[_encoded[8]]}" : "unspecified"}, ' - 'locale: ${ _encoded[0] & 0x08000 == 0x08000 ? _locale : "unspecified"}, ' - 'background: ${ _encoded[0] & 0x10000 == 0x10000 ? _background : "unspecified"}, ' - 'foreground: ${ _encoded[0] & 0x20000 == 0x20000 ? _foreground : "unspecified"}, ' - 'shadows: ${ _encoded[0] & 0x40000 == 0x40000 ? _shadows : "unspecified"}, ' - 'fontFeatures: ${ _encoded[0] & 0x80000 == 0x80000 ? _fontFeatures : "unspecified"}' + 'fontSize: ${ _encoded[0] & 0x00400 == 0x00400 ? _fontSize : "unspecified"}, ' + 'letterSpacing: ${ _encoded[0] & 0x00800 == 0x00800 ? "${_letterSpacing}x" : "unspecified"}, ' + 'wordSpacing: ${ _encoded[0] & 0x01000 == 0x01000 ? "${_wordSpacing}x" : "unspecified"}, ' + 'height: ${ _encoded[0] & 0x02000 == 0x02000 ? "${_height}x" : "unspecified"}, ' + 'leadingDistribution: ${_leadingDistribution ?? "unspecified"}, ' + 'locale: ${ _encoded[0] & 0x04000 == 0x04000 ? _locale : "unspecified"}, ' + 'background: ${ _encoded[0] & 0x08000 == 0x08000 ? _background : "unspecified"}, ' + 'foreground: ${ _encoded[0] & 0x10000 == 0x10000 ? _foreground : "unspecified"}, ' + 'shadows: ${ _encoded[0] & 0x20000 == 0x20000 ? _shadows : "unspecified"}, ' + 'fontFeatures: ${ _encoded[0] & 0x40000 == 0x40000 ? _fontFeatures : "unspecified"}' ')'; } } @@ -2065,8 +2063,8 @@ class TextStyle { // // - Element 5: The value of |maxLines|. // -// - Element 6: The encoded value of |textHeightBehavior|. -// +// - Element 6: The encoded value of |textHeightBehavior|, except its leading +// distribution. Int32List _encodeParagraphStyle( TextAlign? textAlign, TextDirection? textDirection, @@ -2104,7 +2102,7 @@ Int32List _encodeParagraphStyle( } if (textHeightBehavior != null) { result[0] |= 1 << 6; - result[6] = textHeightBehavior.encode(); + result[6] = textHeightBehavior._encode(); } if (fontFamily != null) { result[0] |= 1 << 7; @@ -2173,6 +2171,7 @@ class ParagraphStyle { /// /// * `leadingDistribution`: Specifies how the extra vertical space added by /// the `height` multiplier should be distributed over and under the text. + /// Defaults to [TextLeadingDistribution.proportional]. /// /// * `fontWeight`: The typeface thickness to use when painting the text /// (e.g., bold). @@ -2226,7 +2225,8 @@ class ParagraphStyle { _height = height, _strutStyle = strutStyle, _ellipsis = ellipsis, - _locale = locale; + _locale = locale, + _leadingDistribution = textHeightBehavior?.leadingDistribution ?? TextLeadingDistribution.proportional; final Int32List _encoded; final String? _fontFamily; @@ -2235,6 +2235,7 @@ class ParagraphStyle { final StrutStyle? _strutStyle; final String? _ellipsis; final Locale? _locale; + final TextLeadingDistribution _leadingDistribution; @override bool operator ==(Object other) { @@ -2249,11 +2250,12 @@ class ParagraphStyle { && other._strutStyle == _strutStyle && other._ellipsis == _ellipsis && other._locale == _locale + && other._leadingDistribution == _leadingDistribution && _listEquals(other._encoded, _encoded); } @override - int get hashCode => hashValues(hashList(_encoded), _fontFamily, _fontSize, _height, _ellipsis, _locale); + int get hashCode => hashValues(hashList(_encoded), _fontFamily, _fontSize, _height, _ellipsis, _locale, _leadingDistribution); @override String toString() { @@ -2265,7 +2267,7 @@ class ParagraphStyle { 'maxLines: ${ _encoded[0] & 0x020 == 0x020 ? _encoded[5] : "unspecified"}, ' 'textHeightBehavior: ${ _encoded[0] & 0x040 == 0x040 ? - TextHeightBehavior.fromEncoded(_encoded[6]).toString() : "unspecified"}, ' + TextHeightBehavior._fromEncoded(_encoded[6], _leadingDistribution).toString() : "unspecified"}, ' 'fontFamily: ${ _encoded[0] & 0x080 == 0x080 ? _fontFamily : "unspecified"}, ' 'fontSize: ${ _encoded[0] & 0x100 == 0x100 ? _fontSize : "unspecified"}, ' 'height: ${ _encoded[0] & 0x200 == 0x200 ? "${_height}x" : "unspecified"}, ' @@ -2322,11 +2324,9 @@ ByteData _encodeStrut( bitmask |= 1 << 2; // passed separately to native } - if (leadingDistribution != null) { - bitmask |= 1 << 3; - data.setInt8(byteCount, leadingDistribution.index); - byteCount += 1; - } + + // The 3rd bit (0-indexed) is reserved for leadingDistribution. + if (fontSize != null) { bitmask |= 1 << 4; data.setFloat32(byteCount, fontSize, _kFakeHostEndian); @@ -2388,7 +2388,8 @@ class StrutStyle { /// * `leadingDistribution`: how the extra vertical space added by the /// `height` multiplier should be distributed over and under the text, /// independent of `leading` (which is always distributed evenly over and - /// under text). + /// under text). Defaults to the paragraph's [TextHeightBehavior]'s leading + /// distribution. /// /// * `fontWeight`: The typeface thickness to use when painting the text /// (e.g., bold). @@ -2424,13 +2425,16 @@ class StrutStyle { fontStyle, forceStrutHeight, ), + _leadingDistribution = leadingDistribution, _fontFamily = fontFamily, _fontFamilyFallback = fontFamilyFallback; final ByteData _encoded; // Most of the data for strut is encoded. final String? _fontFamily; final List? _fontFamilyFallback; + final TextLeadingDistribution? _leadingDistribution; + bool get _enabled => _encoded.lengthInBytes > 0; @override bool operator ==(Object other) { @@ -2440,12 +2444,13 @@ class StrutStyle { return false; return other is StrutStyle && other._fontFamily == _fontFamily + && other._leadingDistribution == _leadingDistribution && _listEquals(other._fontFamilyFallback, _fontFamilyFallback) && _listEquals(other._encoded.buffer.asInt8List(), _encoded.buffer.asInt8List()); } @override - int get hashCode => hashValues(hashList(_encoded.buffer.asInt8List()), _fontFamily); + int get hashCode => hashValues(hashList(_encoded.buffer.asInt8List()), _fontFamily, _leadingDistribution); } @@ -3306,27 +3311,38 @@ class ParagraphBuilder extends NativeFieldWrapperClass2 { /// Creates a new [ParagraphBuilder] object, which is used to create a /// [Paragraph]. @pragma('vm:entry-point') - ParagraphBuilder(ParagraphStyle style) { - List? strutFontFamilies; - final StrutStyle? strutStyle = style._strutStyle; - if (strutStyle != null) { - strutFontFamilies = []; - final String? fontFamily = strutStyle._fontFamily; - if (fontFamily != null) - strutFontFamilies.add(fontFamily); - if (strutStyle._fontFamilyFallback != null) - strutFontFamilies.addAll(strutStyle._fontFamilyFallback!); - } - _constructor( - style._encoded, - strutStyle?._encoded, - style._fontFamily, - strutFontFamilies, - style._fontSize, - style._height, - style._ellipsis, - _encodeLocale(style._locale) - ); + ParagraphBuilder(ParagraphStyle style) + : _defaultLeadingDistribution = style._leadingDistribution { + List? strutFontFamilies; + final StrutStyle? strutStyle = style._strutStyle; + final ByteData? encodedStrutStyle; + if (strutStyle != null && strutStyle._enabled) { + final String? fontFamily = strutStyle._fontFamily; + strutFontFamilies = [ + if (fontFamily != null) fontFamily, + ...?strutStyle._fontFamilyFallback, + ]; + + assert(TextLeadingDistribution.values.length <= 2); + final TextLeadingDistribution leadingDistribution = strutStyle._leadingDistribution + ?? style._leadingDistribution; + encodedStrutStyle = strutStyle._encoded; + int bitmask = encodedStrutStyle.getInt8(0); + bitmask |= (leadingDistribution.index) << 3; + encodedStrutStyle.setInt8(0, bitmask); + } else { + encodedStrutStyle = null; + } + _constructor( + style._encoded, + encodedStrutStyle, + style._fontFamily, + strutFontFamilies, + style._fontSize, + style._height, + style._ellipsis, + _encodeLocale(style._locale) + ); } void _constructor( @@ -3348,6 +3364,7 @@ class ParagraphBuilder extends NativeFieldWrapperClass2 { List get placeholderScales => _placeholderScales; List _placeholderScales = []; + final TextLeadingDistribution _defaultLeadingDistribution; /// Applies the given style to the added text until [pop] is called. /// /// See [pop] for details. @@ -3355,7 +3372,16 @@ class ParagraphBuilder extends NativeFieldWrapperClass2 { final List fullFontFamilies = []; fullFontFamilies.add(style._fontFamily); if (style._fontFamilyFallback != null) - fullFontFamilies.addAll(style._fontFamilyFallback!); + fullFontFamilies.addAll(style._fontFamilyFallback!); + + final Int32List encoded = style._encoded; + final TextLeadingDistribution finalLeadingDistribution = style._leadingDistribution ?? _defaultLeadingDistribution; + // ensure the enum can be represented using 1 bit. + assert(TextLeadingDistribution.values.length <= 2); + + // Use the leading distribution from the paragraph's style if it's not + // explicitly set in `style`. + encoded[0] |= finalLeadingDistribution.index << 0; ByteData? encodedFontFeatures; final List? fontFeatures = style._fontFeatures; @@ -3369,7 +3395,7 @@ class ParagraphBuilder extends NativeFieldWrapperClass2 { } _pushStyle( - style._encoded, + encoded, fullFontFamilies, style._fontSize, style._letterSpacing, diff --git a/lib/ui/text/paragraph_builder.cc b/lib/ui/text/paragraph_builder.cc index 4589bc0947cd8..2ef379a2fe8c7 100644 --- a/lib/ui/text/paragraph_builder.cc +++ b/lib/ui/text/paragraph_builder.cc @@ -32,6 +32,7 @@ namespace { // TextStyle +const int tsLeadingDistributionIndex = 0; const int tsColorIndex = 1; const int tsTextDecorationIndex = 2; const int tsTextDecorationColorIndex = 3; @@ -39,19 +40,19 @@ const int tsTextDecorationStyleIndex = 4; const int tsFontWeightIndex = 5; const int tsFontStyleIndex = 6; const int tsTextBaselineIndex = 7; -const int tsLeadingDistributionIndex = 8; -const int tsTextDecorationThicknessIndex = 9; -const int tsFontFamilyIndex = 10; -const int tsFontSizeIndex = 11; -const int tsLetterSpacingIndex = 12; -const int tsWordSpacingIndex = 13; -const int tsHeightIndex = 14; -const int tsLocaleIndex = 15; -const int tsBackgroundIndex = 16; -const int tsForegroundIndex = 17; -const int tsTextShadowsIndex = 18; -const int tsFontFeaturesIndex = 19; +const int tsTextDecorationThicknessIndex = 8; +const int tsFontFamilyIndex = 9; +const int tsFontSizeIndex = 10; +const int tsLetterSpacingIndex = 11; +const int tsWordSpacingIndex = 12; +const int tsHeightIndex = 13; +const int tsLocaleIndex = 14; +const int tsBackgroundIndex = 15; +const int tsForegroundIndex = 16; +const int tsTextShadowsIndex = 17; +const int tsFontFeaturesIndex = 18; +const int tsLeadingDistributionMask = 1 << tsLeadingDistributionIndex; const int tsColorMask = 1 << tsColorIndex; const int tsTextDecorationMask = 1 << tsTextDecorationIndex; const int tsTextDecorationColorMask = 1 << tsTextDecorationColorIndex; @@ -60,7 +61,6 @@ const int tsTextDecorationThicknessMask = 1 << tsTextDecorationThicknessIndex; const int tsFontWeightMask = 1 << tsFontWeightIndex; const int tsFontStyleMask = 1 << tsFontStyleIndex; const int tsTextBaselineMask = 1 << tsTextBaselineIndex; -const int tsLeadingDistributionMask = 1 << tsLeadingDistributionIndex; const int tsFontFamilyMask = 1 << tsFontFamilyIndex; const int tsFontSizeMask = 1 << tsFontSizeIndex; const int tsLetterSpacingMask = 1 << tsLetterSpacingIndex; @@ -201,10 +201,8 @@ void decodeStrut(Dart_Handle strut_data, paragraph_style.strut_font_style = static_cast(uint8_data[byte_count++]); } - if (mask & sLeadingDistributionMask) { - paragraph_style.strut_has_leading_distribution_override = true; - paragraph_style.strut_half_leading = uint8_data[byte_count++]; - } + + paragraph_style.strut_half_leading = mask & sLeadingDistributionMask; std::vector float_data; float_data.resize((byte_data.length_in_bytes() - byte_count) / 4); @@ -389,6 +387,7 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded, // explicitly given. txt::TextStyle style = m_paragraphBuilder->PeekStyle(); + style.half_leading = mask & tsLeadingDistributionMask; // Only change the style property from the previous value if a new explicitly // set value is available if (mask & tsColorMask) { @@ -418,11 +417,6 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded, // property wasn't wired up either. } - style.has_leading_distribution_override = mask & tsLeadingDistributionMask; - if (mask & tsLeadingDistributionMask) { - style.half_leading = encoded[tsLeadingDistributionIndex]; - } - if (mask & (tsFontWeightMask | tsFontStyleMask | tsFontSizeMask | tsLetterSpacingMask | tsWordSpacingMask)) { if (mask & tsFontWeightMask) { diff --git a/lib/web_ui/lib/src/engine/canvaskit/text.dart b/lib/web_ui/lib/src/engine/canvaskit/text.dart index 57e171114abca..983155abd394a 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/text.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/text.dart @@ -131,7 +131,8 @@ class CkParagraphStyle implements ui.ParagraphStyle { } if (textHeightBehavior != null) { - properties.textHeightBehavior = textHeightBehavior.encode(); + properties.textHeightBehavior = (textHeightBehavior.applyHeightToFirstAscent ? 0 : 1 << 0) + | (textHeightBehavior.applyHeightToLastDescent ? 0 : 1 << 1); } if (ellipsis != null) { diff --git a/lib/web_ui/lib/src/ui/text.dart b/lib/web_ui/lib/src/ui/text.dart index 906b52c0934a8..779b2903cb617 100644 --- a/lib/web_ui/lib/src/ui/text.dart +++ b/lib/web_ui/lib/src/ui/text.dart @@ -214,20 +214,10 @@ class TextHeightBehavior { this.applyHeightToLastDescent = true, this.leadingDistribution = TextLeadingDistribution.proportional, }); - TextHeightBehavior.fromEncoded(int encoded) - : applyHeightToFirstAscent = (encoded & 0x1) == 0, - applyHeightToLastDescent = (encoded & 0x2) == 0, - leadingDistribution = TextLeadingDistribution.values[encoded >> 2]; final bool applyHeightToFirstAscent; final bool applyHeightToLastDescent; final TextLeadingDistribution leadingDistribution; - int encode() { - return (applyHeightToFirstAscent ? 0 : 1 << 0) - | (applyHeightToLastDescent ? 0 : 1 << 1) - | (leadingDistribution.index << 2); - } - @override bool operator ==(Object other) { if (other.runtimeType != runtimeType) diff --git a/lib/web_ui/test/canvaskit/canvaskit_api_test.dart b/lib/web_ui/test/canvaskit/canvaskit_api_test.dart index fa8b9a077a5dc..bb212fa74cfbf 100644 --- a/lib/web_ui/test/canvaskit/canvaskit_api_test.dart +++ b/lib/web_ui/test/canvaskit/canvaskit_api_test.dart @@ -1273,7 +1273,7 @@ void _paragraphTests() { props.textAlign = canvasKit.TextAlign.Center; props.textDirection = canvasKit.TextDirection.RTL; props.heightMultiplier = 3; - props.textHeightBehavior = ui.TextHeightBehavior().encode(); + props.textHeightBehavior = 0; props.maxLines = 4; props.ellipsis = '___'; props.textStyle = SkTextStyleProperties() diff --git a/testing/dart/text_test.dart b/testing/dart/text_test.dart index 9d4218e33db83..0151b731f1b81 100644 --- a/testing/dart/text_test.dart +++ b/testing/dart/text_test.dart @@ -107,22 +107,6 @@ void main() { expect(behavior4.leadingDistribution, equals(TextLeadingDistribution.even)); }); - test('encode works', () { - expect(behavior0.encode(), equals(0)); - expect(behavior1.encode(), equals(3)); - expect(behavior2.encode(), equals(1)); - expect(behavior3.encode(), equals(2)); - expect(behavior4.encode(), equals(6)); - }); - - test('decode works', () { - expect(TextHeightBehavior.fromEncoded(0), equals(behavior0)); - expect(TextHeightBehavior.fromEncoded(3), equals(behavior1)); - expect(TextHeightBehavior.fromEncoded(1), equals(behavior2)); - expect(TextHeightBehavior.fromEncoded(2), equals(behavior3)); - expect(TextHeightBehavior.fromEncoded(6), equals(behavior4)); - }); - test('toString works', () { expect(behavior0.toString(), equals('TextHeightBehavior(applyHeightToFirstAscent: true, applyHeightToLastDescent: true, leadingDistribution: TextLeadingDistribution.proportional)')); expect(behavior1.toString(), equals('TextHeightBehavior(applyHeightToFirstAscent: false, applyHeightToLastDescent: false, leadingDistribution: TextLeadingDistribution.proportional)')); diff --git a/third_party/txt/src/skia/paragraph_builder_skia.cc b/third_party/txt/src/skia/paragraph_builder_skia.cc index f7169f1b0356a..e17c6391c7953 100644 --- a/third_party/txt/src/skia/paragraph_builder_skia.cc +++ b/third_party/txt/src/skia/paragraph_builder_skia.cc @@ -107,6 +107,7 @@ skt::TextStyle TxtToSkia(const TextStyle& txt) { skia.setWordSpacing(SkDoubleToScalar(txt.word_spacing)); skia.setHeight(SkDoubleToScalar(txt.height)); skia.setHeightOverride(txt.has_height_override); + skia.setHalfLeading(txt.half_leading); skia.setLocale(SkString(txt.locale.c_str())); if (txt.has_background) { diff --git a/third_party/txt/src/txt/paragraph_style.h b/third_party/txt/src/txt/paragraph_style.h index 90c54ee4b23d8..8fa135695a41e 100644 --- a/third_party/txt/src/txt/paragraph_style.h +++ b/third_party/txt/src/txt/paragraph_style.h @@ -48,12 +48,6 @@ enum class TextDirection { // the line will use the default font metric provided ascent/descent and // ParagraphStyle.height or TextStyle.height will not take effect. // -// kEvenLeading determines how the leading is distributed over and under the -// text. When true, half of the leading is added to the top of the text and the -// other half is added to the bottom of the text. Otherwise, instead of -// distributing the space evenly, it's distributed proportionally to the font's -// ascent/descent ratio. -// // The default behavior is kAll where height adjustments are enabled for all // lines. // @@ -66,7 +60,6 @@ enum TextHeightBehavior { kDisableFirstAscent = 0x1, kDisableLastDescent = 0x2, kDisableAll = 0x1 | 0x2, - kEvenLeading = 0x1 << 2, }; class ParagraphStyle { @@ -92,7 +85,6 @@ class ParagraphStyle { double strut_height = 1; bool strut_has_height_override = false; bool strut_half_leading = false; - bool strut_has_leading_distribution_override = false; double strut_leading = -1; // Negative to use font's default leading. [0,inf) // to use custom leading as a ratio of font size. bool force_strut_height = false; diff --git a/third_party/txt/src/txt/paragraph_txt.cc b/third_party/txt/src/txt/paragraph_txt.cc index df2c991ed66c9..46f21abf8f0f2 100644 --- a/third_party/txt/src/txt/paragraph_txt.cc +++ b/third_party/txt/src/txt/paragraph_txt.cc @@ -566,14 +566,8 @@ void ParagraphTxt::ComputeStrut(StrutMetrics* strut, SkFont& font) { : (paragraph_style_.strut_leading * paragraph_style_.strut_font_size); - const bool half_leading_enabled = - paragraph_style_.strut_has_leading_distribution_override - ? paragraph_style_.strut_half_leading - : paragraph_style_.text_height_behavior & - TextHeightBehavior::kEvenLeading; - const double available_height = - half_leading_enabled ? metrics_height : strut_height; + paragraph_style_.strut_half_leading ? metrics_height : strut_height; strut->ascent = (-strut_metrics.fAscent / metrics_height) * available_height; @@ -1213,11 +1207,6 @@ void ParagraphTxt::UpdateLineMetrics(const SkFontMetrics& metrics, const double blob_height = style.has_height_override ? style.height * style.font_size : metrics_font_height + metrics.fLeading; - const bool half_leading_enabled = - style.has_leading_distribution_override - ? style.half_leading - : paragraph_style_.text_height_behavior & - TextHeightBehavior::kEvenLeading; // Scale the ascent and descent such that the sum of ascent and // descent is `style.height * style.font_size`. @@ -1266,14 +1255,14 @@ void ParagraphTxt::UpdateLineMetrics(const SkFontMetrics& metrics, // a sane, consistent, and reasonable "blob_height" to be specified, // though it breaks with what is done by any of the platforms above. const bool shouldNormalizeFont = - style.has_height_override && !half_leading_enabled; + style.has_height_override && !style.half_leading; const double font_height = shouldNormalizeFont ? style.font_size : metrics_font_height; // Reserve the outermost vertical space we want to distribute evenly over // and under the text ("half-leading"). double leading; - if (half_leading_enabled) { + if (style.half_leading) { leading = blob_height - font_height; } else { leading = style.has_height_override ? 0.0 : metrics.fLeading; diff --git a/third_party/txt/src/txt/text_style.cc b/third_party/txt/src/txt/text_style.cc index b520c0f0dfa2f..0d1cacb184f89 100644 --- a/third_party/txt/src/txt/text_style.cc +++ b/third_party/txt/src/txt/text_style.cc @@ -48,9 +48,6 @@ bool TextStyle::equals(const TextStyle& other) const { return false; if (has_height_override != other.has_height_override) return false; - if (has_leading_distribution_override != - other.has_leading_distribution_override) - return false; if (half_leading != other.half_leading) return false; if (locale != other.locale) diff --git a/third_party/txt/src/txt/text_style.h b/third_party/txt/src/txt/text_style.h index 6d6bd34766343..99848a812056a 100644 --- a/third_party/txt/src/txt/text_style.h +++ b/third_party/txt/src/txt/text_style.h @@ -45,9 +45,6 @@ class TextStyle { FontStyle font_style = FontStyle::normal; TextBaseline text_baseline = TextBaseline::kAlphabetic; bool half_leading = false; - // whether TextStyle.half_leading should be applied or we should defer to - // ParagraphStyle.half_leading. - bool has_leading_distribution_override = false; // An ordered list of fonts in order of priority. The first font is more // highly preferred than the last font. std::vector font_families; diff --git a/third_party/txt/tests/paragraph_unittests.cc b/third_party/txt/tests/paragraph_unittests.cc index dcfe0be7b3401..c3cb242a12981 100644 --- a/third_party/txt/tests/paragraph_unittests.cc +++ b/third_party/txt/tests/paragraph_unittests.cc @@ -1883,80 +1883,6 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(HeightOverrideParagraph)) { ASSERT_TRUE(Snapshot()); } -TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(HeightOverrideHalfLeadingParagraph)) { - // All 3 lines will have the same typeface. - const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可"; - auto icu_text = icu::UnicodeString::fromUTF8(text); - std::u16string u16_text(icu_text.getBuffer(), - icu_text.getBuffer() + icu_text.length()); - - txt::ParagraphStyle paragraph_style; - paragraph_style.max_lines = 10; - paragraph_style.text_height_behavior = TextHeightBehavior::kEvenLeading; - txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); - - txt::TextStyle text_style; - text_style.font_families = std::vector(1, "Roboto"); - text_style.font_size = 20; - text_style.letter_spacing = 0; - text_style.word_spacing = 0; - text_style.color = SK_ColorBLACK; - text_style.height = 3.6345; - text_style.has_height_override = true; - // Disables text style leading distribution behavior override so it defaults - // to the paragraph style. - text_style.has_leading_distribution_override = false; - builder.PushStyle(text_style); - - builder.AddText(u16_text); - - builder.Pop(); - - auto paragraph = BuildParagraph(builder); - paragraph->Layout(550); - - paragraph->Paint(GetCanvas(), 0, 0); - - SkPaint paint; - paint.setStyle(SkPaint::kStroke_Style); - paint.setAntiAlias(true); - paint.setStrokeWidth(1); - - // Tests for GetRectsForRange() - Paragraph::RectHeightStyle rect_height_style = - Paragraph::RectHeightStyle::kTight; - Paragraph::RectWidthStyle rect_width_style = - Paragraph::RectWidthStyle::kTight; - paint.setColor(SK_ColorRED); - std::vector boxes = - paragraph->GetRectsForRange(0, 0, rect_height_style, rect_width_style); - for (size_t i = 0; i < boxes.size(); ++i) { - GetCanvas()->drawRect(boxes[i].rect, paint); - } - EXPECT_EQ(boxes.size(), 0ull); - - boxes = - paragraph->GetRectsForRange(0, 40, rect_height_style, rect_width_style); - for (size_t i = 0; i < boxes.size(); ++i) { - GetCanvas()->drawRect(boxes[i].rect, paint); - } - // With half-leadding, the x coordinates should remain the same but the glyphs - // are shifted up (as compared to AD-scaling). - EXPECT_EQ(boxes.size(), 3ull); - - const double line_spacing1 = boxes[1].rect.top() - boxes[0].rect.bottom(); - const double line_spacing2 = boxes[2].rect.top() - boxes[1].rect.bottom(); - - EXPECT_EQ(line_spacing1, line_spacing2); - // half leading. - EXPECT_NEAR(line_spacing1 * 0.5, boxes[0].rect.top(), 0.5); - - EXPECT_FLOAT_EQ(boxes[1].rect.left(), 0); - EXPECT_FLOAT_EQ(boxes[1].rect.right(), 43.851562); - - ASSERT_TRUE(Snapshot()); -} - TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(HeightOverrideHalfLeadingTextStyle)) { // All 3 lines will have the same typeface. const char* text = "01234満毎冠行来昼本可\nabcd\n満毎冠行来昼本可"; @@ -1978,7 +1904,6 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(HeightOverrideHalfLeadingTextStyle)) { text_style.height = 3.6345; text_style.has_height_override = true; // Override paragraph_style.text_height_behavior: - text_style.has_leading_distribution_override = true; text_style.half_leading = true; builder.PushStyle(text_style); @@ -2060,13 +1985,11 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(MixedTextHeightBehaviorSameLine)) { text_style.height = 3.6345; text_style.has_height_override = true; // First run, with half-leading. - text_style.has_leading_distribution_override = true; text_style.half_leading = true; builder.PushStyle(text_style); builder.AddText(u16_text); // Second run with AD-scaling. - text_style.has_leading_distribution_override = true; text_style.half_leading = false; builder.PushStyle(text_style); @@ -2144,13 +2067,11 @@ TEST_F(ParagraphTest, text_style.height = 0; text_style.has_height_override = true; // First run, with half-leading. - text_style.has_leading_distribution_override = true; text_style.half_leading = true; builder.PushStyle(text_style); builder.AddText(u16_text); // Second run with AD-scaling. - text_style.has_leading_distribution_override = true; text_style.half_leading = false; builder.PushStyle(text_style); @@ -2214,7 +2135,6 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(HeightOverrideHalfLeadingStrut)) { paragraph_style.strut_height = 3.6345; paragraph_style.strut_font_size = 20; paragraph_style.strut_font_families.push_back("Roboto"); - paragraph_style.strut_has_leading_distribution_override = true; paragraph_style.strut_half_leading = true; txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); @@ -2226,8 +2146,6 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(HeightOverrideHalfLeadingStrut)) { text_style.color = SK_ColorBLACK; text_style.height = 3.6345; text_style.has_height_override = true; - // Override paragraph_style.text_height_behavior: - text_style.has_leading_distribution_override = true; text_style.half_leading = true; builder.PushStyle(text_style); @@ -2314,13 +2232,11 @@ TEST_F(ParagraphTest, text_style.has_height_override = true; // First run, with half-leading. - text_style.has_leading_distribution_override = true; text_style.half_leading = true; builder.PushStyle(text_style); builder.AddText(u16_text); // Second run with AD-scaling. - text_style.has_leading_distribution_override = true; text_style.half_leading = false; builder.PushStyle(text_style); @@ -7158,7 +7074,6 @@ TEST_F(ParagraphTest, MixedTextHeightBehaviorRectsParagraph) { text_style.font_size = 30; text_style.height = 5; text_style.has_height_override = true; - text_style.has_leading_distribution_override = true; text_style.half_leading = true; builder.PushStyle(text_style);