From f9a73cc208bc56eb900aea57219d350f938695db Mon Sep 17 00:00:00 2001 From: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com> Date: Fri, 26 Feb 2021 11:40:53 -0800 Subject: [PATCH] Revert "TextStyle level leadingDistribution (#24025)" This reverts commit 1bdf5d3287e31952da6b03900d2a0b9159beb06e. --- lib/ui/text.dart | 183 ++---- lib/ui/text/paragraph_builder.cc | 43 +- lib/web_ui/lib/src/engine/text/paragraph.dart | 6 - lib/web_ui/lib/src/ui/text.dart | 27 +- testing/dart/text_test.dart | 57 +- third_party/txt/src/txt/paragraph_style.h | 21 +- third_party/txt/src/txt/paragraph_txt.cc | 212 +++---- third_party/txt/src/txt/paragraph_txt.h | 4 +- third_party/txt/src/txt/text_style.cc | 5 - third_party/txt/src/txt/text_style.h | 4 - third_party/txt/tests/paragraph_unittests.cc | 549 ------------------ 11 files changed, 173 insertions(+), 938 deletions(-) diff --git a/lib/ui/text.dart b/lib/ui/text.dart index 54f794938e5be..f4c78a8abb18f 100644 --- a/lib/ui/text.dart +++ b/lib/ui/text.dart @@ -1565,46 +1565,14 @@ enum TextDecorationStyle { wavy } -/// {@macro dart.ui.textLeadingDistribution} -enum TextLeadingDistribution { - /// Distributes the [leading](https://en.wikipedia.org/wiki/Leading) - /// of the text proportionally above and below the text, to the font's - /// ascent/discent ratio. - /// - /// {@template dart.ui.leading} - /// The leading of a text run is defined as - /// `TextStyle.height * TextStyle.fontSize - TextStyle.fontSize`. When - /// [TextStyle.height] is not set, the text run uses the leading specified by - /// the font instead. - /// {@endtemplate} - proportional, - - /// Distributes the ["leading"](https://en.wikipedia.org/wiki/Leading) - /// of the text evenly above and below the text (i.e. evenly above the - /// font's ascender and below the descender). - /// - /// {@macro dart.ui.leading} - /// - /// The leading can become negative when [TextStyle.height] is smaller than - /// 1.0. - /// - /// This is the default strategy used by CSS, known as - /// ["half-leading"](https://www.w3.org/TR/css-inline-3/#half-leading). - even, -} - /// {@template dart.ui.textHeightBehavior} -/// Defines how to apply [TextStyle.height] over and under text. -/// -/// [applyHeightToFirstAscent] and [applyHeightToLastDescent] represent whether -/// the [TextStyle.height] modifier will be applied to the corresponding metric. -/// By default both properties are true, and [TextStyle.height] is applied as -/// normal. When set to false, the font's default ascent will be used. -/// -/// [leadingDistribution] determines how the [leading] is distributed over and -/// under text. This property applies before [applyHeightToFirstAscent] and -/// [applyHeightToLastDescent]. +/// Defines how the paragraph will apply [TextStyle.height] to the ascent of the +/// first line and descent of the last line. /// +/// Each boolean value represents whether the [TextStyle.height] modifier will +/// be applied to the corresponding metric. By default, all properties are true, +/// and [TextStyle.height] is applied as normal. When set to false, the font's +/// default ascent will be used. /// {@endtemplate} class TextHeightBehavior { @@ -1616,23 +1584,20 @@ class TextHeightBehavior { /// * applyHeightToLastDescent: When true, the [TextStyle.height] modifier /// will be applied to the descent of the last line. When false, the font's /// default descent will be used. - /// * leadingDistribution: How the [leading] is distributed over and under - /// text. /// /// All properties default to true (height modifications applied as normal). const TextHeightBehavior({ this.applyHeightToFirstAscent = true, this.applyHeightToLastDescent = true, - this.leadingDistribution = TextLeadingDistribution.proportional, }); /// Creates a new TextHeightBehavior object from an encoded form. /// /// See [encode] for the creation of the encoded form. - TextHeightBehavior.fromEncoded(int encoded) + const TextHeightBehavior.fromEncoded(int encoded) : 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. @@ -1658,23 +1623,9 @@ class TextHeightBehavior { /// Defaults to true (height modifications applied as normal). final bool applyHeightToLastDescent; - /// {@template dart.ui.textLeadingDistribution} - /// How the ["leading"](https://en.wikipedia.org/wiki/Leading) is distributed - /// over and under the text. - /// - /// Does not affect layout when [TextStyle.height] is not specified. The - /// leading can become negative, for example, when [TextLeadingDistribution.even] - /// is used with a [TextStyle.height] much smaller than 1.0. - /// {@endtemplate} - /// - /// Defaults to [TextLeadingDistribution.proportional], - final TextLeadingDistribution leadingDistribution; - /// Returns an encoded int representation of this object. int encode() { - return (applyHeightToFirstAscent ? 0 : 1 << 0) - | (applyHeightToLastDescent ? 0 : 1 << 1) - | (leadingDistribution.index << 2); + return (applyHeightToFirstAscent ? 0 : 1 << 0) | (applyHeightToLastDescent ? 0 : 1 << 1); } @override @@ -1683,8 +1634,7 @@ class TextHeightBehavior { return false; return other is TextHeightBehavior && other.applyHeightToFirstAscent == applyHeightToFirstAscent - && other.applyHeightToLastDescent == applyHeightToLastDescent - && other.leadingDistribution == leadingDistribution; + && other.applyHeightToLastDescent == applyHeightToLastDescent; } @override @@ -1692,7 +1642,6 @@ class TextHeightBehavior { return hashValues( applyHeightToFirstAscent, applyHeightToLastDescent, - leadingDistribution.index, ); } @@ -1700,8 +1649,7 @@ class TextHeightBehavior { String toString() { return 'TextHeightBehavior(' 'applyHeightToFirstAscent: $applyHeightToFirstAscent, ' - 'applyHeightToLastDescent: $applyHeightToLastDescent, ' - 'leadingDistribution: $leadingDistribution' + 'applyHeightToLastDescent: $applyHeightToLastDescent' ')'; } } @@ -1748,8 +1696,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, @@ -1765,14 +1711,13 @@ Int32List _encodeTextStyle( double? letterSpacing, double? wordSpacing, double? height, - TextLeadingDistribution? leadingDistribution, Locale? locale, Paint? background, Paint? foreground, List? shadows, List? fontFeatures, ) { - final Int32List result = Int32List(9); + final Int32List result = Int32List(8); if (color != null) { result[0] |= 1 << 1; result[1] = color.value; @@ -1801,54 +1746,49 @@ 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. } - return result; } @@ -1883,7 +1823,6 @@ 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. /// * `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. @@ -1903,7 +1842,6 @@ class TextStyle { double? letterSpacing, double? wordSpacing, double? height, - TextLeadingDistribution? leadingDistribution, Locale? locale, Paint? background, Paint? foreground, @@ -1928,7 +1866,6 @@ class TextStyle { letterSpacing, wordSpacing, height, - leadingDistribution, locale, background, foreground, @@ -1988,30 +1925,29 @@ class TextStyle { @override String toString() { return 'TextStyle(' - 'color: ${ _encoded[0] & 0x00002 == 0x00002 ? Color(_encoded[1]) : "unspecified"}, ' - 'decoration: ${ _encoded[0] & 0x00004 == 0x00004 ? TextDecoration._(_encoded[2]) : "unspecified"}, ' - 'decorationColor: ${ _encoded[0] & 0x00008 == 0x00008 ? Color(_encoded[3]) : "unspecified"}, ' - 'decorationStyle: ${ _encoded[0] & 0x00010 == 0x00010 ? TextDecorationStyle.values[_encoded[4]] : "unspecified"}, ' + 'color: ${ _encoded[0] & 0x00002 == 0x00002 ? Color(_encoded[1]) : "unspecified"}, ' + 'decoration: ${ _encoded[0] & 0x00004 == 0x00004 ? TextDecoration._(_encoded[2]) : "unspecified"}, ' + '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"}, ' - '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 != '' ? _fontFamily : "unspecified"}, ' - 'fontFamilyFallback: ${ _encoded[0] & 0x00400 == 0x00400 + '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] & 0x00200 == 0x00200 + && _fontFamily != '' ? _fontFamily : "unspecified"}, ' + '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"}' + && _fontFamilyFallback!.isNotEmpty ? _fontFamilyFallback : "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"}, ' + '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"}' ')'; } } @@ -2141,9 +2077,6 @@ class ParagraphStyle { /// * `textHeightBehavior`: Specifies how the `height` multiplier is /// applied to ascent of the first line and the descent of the last line. /// - /// * `leadingDistribution`: Specifies how the extra vertical space added by - /// the `height` multiplier should be distributed over and under the text. - /// /// * `fontWeight`: The typeface thickness to use when painting the text /// (e.g., bold). /// @@ -2259,7 +2192,6 @@ ByteData _encodeStrut( List? fontFamilyFallback, double? fontSize, double? height, - TextLeadingDistribution? leadingDistribution, double? leading, FontWeight? fontWeight, FontStyle? fontStyle, @@ -2267,14 +2199,13 @@ ByteData _encodeStrut( if (fontFamily == null && fontSize == null && height == null && - leadingDistribution == null && leading == null && fontWeight == null && fontStyle == null && forceStrutHeight == null) return ByteData(0); - final ByteData data = ByteData(16); // Max size is 16 bytes + final ByteData data = ByteData(15); // Max size is 15 bytes int bitmask = 0; // 8 bit mask int byteCount = 1; if (fontWeight != null) { @@ -2300,22 +2231,17 @@ ByteData _encodeStrut( bitmask |= 1 << 4; data.setFloat32(byteCount, height, _kFakeHostEndian); byteCount += 4; - if (leadingDistribution != null) { - bitmask |= 1 << 5; - data.setInt8(byteCount, leadingDistribution.index); - byteCount += 4; - } } if (leading != null) { - bitmask |= 1 << 6; + bitmask |= 1 << 5; data.setFloat32(byteCount, leading, _kFakeHostEndian); byteCount += 4; } if (forceStrutHeight != null) { - bitmask |= 1 << 7; + bitmask |= 1 << 6; // We store this boolean directly in the bitmask since there is // extra space in the 16 bit int. - bitmask |= (forceStrutHeight ? 1 : 0) << 8; + bitmask |= (forceStrutHeight ? 1 : 0) << 7; } data.setInt8(0, bitmask); @@ -2350,14 +2276,7 @@ class StrutStyle { /// be provided for this property to take effect. /// /// * `leading`: The minimum amount of leading between lines as a multiple of - /// the font size. `fontSize` must be provided for this property to take - /// effect. The leading added by this property is distributed evenly over - /// and under the text, regardless of `leadingDistribution`. - /// - /// * `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). + /// the font size. `fontSize` must be provided for this property to take effect. /// /// * `fontWeight`: The typeface thickness to use when painting the text /// (e.g., bold). @@ -2377,7 +2296,6 @@ class StrutStyle { List? fontFamilyFallback, double? fontSize, double? height, - TextLeadingDistribution? leadingDistribution, double? leading, FontWeight? fontWeight, FontStyle? fontStyle, @@ -2387,7 +2305,6 @@ class StrutStyle { fontFamilyFallback, fontSize, height, - leadingDistribution, leading, fontWeight, fontStyle, diff --git a/lib/ui/text/paragraph_builder.cc b/lib/ui/text/paragraph_builder.cc index d53ad7821044f..79dbe23b9957a 100644 --- a/lib/ui/text/paragraph_builder.cc +++ b/lib/ui/text/paragraph_builder.cc @@ -39,18 +39,17 @@ 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 tsColorMask = 1 << tsColorIndex; const int tsTextDecorationMask = 1 << tsTextDecorationIndex; @@ -60,7 +59,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; @@ -120,16 +118,14 @@ const int sFontStyleIndex = 1; const int sFontFamilyIndex = 2; const int sFontSizeIndex = 3; const int sHeightIndex = 4; -const int sLeadingDistributionIndex = 5; -const int sLeadingIndex = 6; -const int sForceStrutHeightIndex = 7; +const int sLeadingIndex = 5; +const int sForceStrutHeightIndex = 6; const int sFontWeightMask = 1 << sFontWeightIndex; const int sFontStyleMask = 1 << sFontStyleIndex; const int sFontFamilyMask = 1 << sFontFamilyIndex; const int sFontSizeMask = 1 << sFontSizeIndex; const int sHeightMask = 1 << sHeightIndex; -const int sLeadingDistributionMask = 1 << sLeadingDistributionIndex; const int sLeadingMask = 1 << sLeadingIndex; const int sForceStrutHeightMask = 1 << sForceStrutHeightIndex; @@ -214,12 +210,6 @@ void decodeStrut(Dart_Handle strut_data, if (mask & sHeightMask) { paragraph_style.strut_height = float_data[float_count++]; paragraph_style.strut_has_height_override = true; - - // LeadingDistribution does not affect layout if height is not set. - if (mask & sLeadingDistributionMask) { - paragraph_style.strut_half_leading = uint8_data[byte_count]; - paragraph_style.strut_has_leading_distribution_override = true; - } } if (mask & sLeadingMask) { paragraph_style.strut_leading = float_data[float_count++]; @@ -383,7 +373,7 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded, Dart_Handle foreground_data, Dart_Handle shadows_data, Dart_Handle font_features_data) { - FML_DCHECK(encoded.num_elements() == 9); + FML_DCHECK(encoded.num_elements() == 8); int32_t mask = encoded[0]; @@ -420,11 +410,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/text/paragraph.dart b/lib/web_ui/lib/src/engine/text/paragraph.dart index 463e763b8eefe..3c4207b3719f9 100644 --- a/lib/web_ui/lib/src/engine/text/paragraph.dart +++ b/lib/web_ui/lib/src/engine/text/paragraph.dart @@ -1211,8 +1211,6 @@ class EngineStrutStyle implements ui.StrutStyle { List? fontFamilyFallback, double? fontSize, double? height, - //TODO(LongCatIsLooong): implement leadingDistribution. - ui.TextLeadingDistribution? leadingDistribution, double? leading, ui.FontWeight? fontWeight, ui.FontStyle? fontStyle, @@ -1221,7 +1219,6 @@ class EngineStrutStyle implements ui.StrutStyle { _fontFamilyFallback = fontFamilyFallback, _fontSize = fontSize, _height = height, - _leadingDistribution = leadingDistribution, _leading = leading, _fontWeight = fontWeight, _fontStyle = fontStyle, @@ -1235,7 +1232,6 @@ class EngineStrutStyle implements ui.StrutStyle { final ui.FontWeight? _fontWeight; final ui.FontStyle? _fontStyle; final bool? _forceStrutHeight; - final ui.TextLeadingDistribution? _leadingDistribution; @override bool operator ==(Object other) { @@ -1250,7 +1246,6 @@ class EngineStrutStyle implements ui.StrutStyle { && other._fontSize == _fontSize && other._height == _height && other._leading == _leading - && other._leadingDistribution == _leadingDistribution && other._fontWeight == _fontWeight && other._fontStyle == _fontStyle && other._forceStrutHeight == _forceStrutHeight @@ -1264,7 +1259,6 @@ class EngineStrutStyle implements ui.StrutStyle { _fontSize, _height, _leading, - _leadingDistribution, _fontWeight, _fontStyle, _forceStrutHeight, diff --git a/lib/web_ui/lib/src/ui/text.dart b/lib/web_ui/lib/src/ui/text.dart index c94308e6369ab..bffb948d5baa3 100644 --- a/lib/web_ui/lib/src/ui/text.dart +++ b/lib/web_ui/lib/src/ui/text.dart @@ -204,29 +204,18 @@ enum TextDecorationStyle { wavy } -enum TextLeadingDistribution { - proportional, - even, -} - class TextHeightBehavior { const TextHeightBehavior({ this.applyHeightToFirstAscent = true, this.applyHeightToLastDescent = true, - this.leadingDistribution = TextLeadingDistribution.proportional, }); - TextHeightBehavior.fromEncoded(int encoded) - : applyHeightToFirstAscent = (encoded & 0x1) == 0, - applyHeightToLastDescent = (encoded & 0x2) == 0, - leadingDistribution = TextLeadingDistribution.values[encoded >> 2]; + const TextHeightBehavior.fromEncoded(int encoded) + : applyHeightToFirstAscent = (encoded & 0x1) == 0, + applyHeightToLastDescent = (encoded & 0x2) == 0; final bool applyHeightToFirstAscent; final bool applyHeightToLastDescent; - final TextLeadingDistribution leadingDistribution; - int encode() { - return (applyHeightToFirstAscent ? 0 : 1 << 0) - | (applyHeightToLastDescent ? 0 : 1 << 1) - | (leadingDistribution.index << 2); + return (applyHeightToFirstAscent ? 0 : 1 << 0) | (applyHeightToLastDescent ? 0 : 1 << 1); } @override @@ -235,8 +224,7 @@ class TextHeightBehavior { return false; return other is TextHeightBehavior && other.applyHeightToFirstAscent == applyHeightToFirstAscent - && other.applyHeightToLastDescent == applyHeightToLastDescent - && other.leadingDistribution == leadingDistribution; + && other.applyHeightToLastDescent == applyHeightToLastDescent; } @override @@ -251,8 +239,7 @@ class TextHeightBehavior { String toString() { return 'TextHeightBehavior(' 'applyHeightToFirstAscent: $applyHeightToFirstAscent, ' - 'applyHeightToLastDescent: $applyHeightToLastDescent, ' - 'leadingDistribution: $leadingDistribution' + 'applyHeightToLastDescent: $applyHeightToLastDescent' ')'; } } @@ -273,7 +260,6 @@ abstract class TextStyle { double? letterSpacing, double? wordSpacing, double? height, - TextLeadingDistribution? leadingDistribution, Locale? locale, Paint? background, Paint? foreground, @@ -384,7 +370,6 @@ abstract class StrutStyle { List? fontFamilyFallback, double? fontSize, double? height, - TextLeadingDistribution? leadingDistribution, double? leading, FontWeight? fontWeight, FontStyle? fontStyle, diff --git a/testing/dart/text_test.dart b/testing/dart/text_test.dart index 9d4218e33db83..55ff04b42ed5c 100644 --- a/testing/dart/text_test.dart +++ b/testing/dart/text_test.dart @@ -42,37 +42,6 @@ void main() { }); }); - group('TextStyle', () { - final TextStyle ts0 = TextStyle(fontWeight: FontWeight.w700, fontSize: 12.0, height: 123.0); - final TextStyle ts1 = TextStyle(color: const Color(0xFF00FF00), fontWeight: FontWeight.w800, fontSize: 10.0, height: 100.0); - final TextStyle ts2 = TextStyle(fontFamily: 'test'); - final TextStyle ts3 = TextStyle(fontFamily: 'foo', fontFamilyFallback: ['Roboto', 'test']); - final TextStyle ts4 = TextStyle(leadingDistribution: TextLeadingDistribution.even); - - test('toString works', () { - expect( - ts0.toString(), - equals('TextStyle(color: unspecified, decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, decorationThickness: unspecified, fontWeight: FontWeight.w700, fontStyle: unspecified, textBaseline: unspecified, fontFamily: unspecified, fontFamilyFallback: unspecified, fontSize: 12.0, letterSpacing: unspecified, wordSpacing: unspecified, height: 123.0x, leadingDistribution: unspecified, locale: unspecified, background: unspecified, foreground: unspecified, shadows: unspecified, fontFeatures: unspecified)'), - ); - expect( - ts1.toString(), - equals('TextStyle(color: Color(0xff00ff00), decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, decorationThickness: unspecified, fontWeight: FontWeight.w800, fontStyle: unspecified, textBaseline: unspecified, fontFamily: unspecified, fontFamilyFallback: unspecified, fontSize: 10.0, letterSpacing: unspecified, wordSpacing: unspecified, height: 100.0x, leadingDistribution: unspecified, locale: unspecified, background: unspecified, foreground: unspecified, shadows: unspecified, fontFeatures: unspecified)'), - ); - expect( - ts2.toString(), - equals('TextStyle(color: unspecified, decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, decorationThickness: unspecified, fontWeight: unspecified, fontStyle: unspecified, textBaseline: unspecified, fontFamily: test, fontFamilyFallback: unspecified, fontSize: unspecified, letterSpacing: unspecified, wordSpacing: unspecified, height: unspecified, leadingDistribution: unspecified, locale: unspecified, background: unspecified, foreground: unspecified, shadows: unspecified, fontFeatures: unspecified)'), - ); - expect( - ts3.toString(), - equals('TextStyle(color: unspecified, decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, decorationThickness: unspecified, fontWeight: unspecified, fontStyle: unspecified, textBaseline: unspecified, fontFamily: foo, fontFamilyFallback: [Roboto, test], fontSize: unspecified, letterSpacing: unspecified, wordSpacing: unspecified, height: unspecified, leadingDistribution: unspecified, locale: unspecified, background: unspecified, foreground: unspecified, shadows: unspecified, fontFeatures: unspecified)'), - ); - expect( - ts4.toString(), - equals('TextStyle(color: unspecified, decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, decorationThickness: unspecified, fontWeight: unspecified, fontStyle: unspecified, textBaseline: unspecified, fontFamily: unspecified, fontFamilyFallback: unspecified, fontSize: unspecified, letterSpacing: unspecified, wordSpacing: unspecified, height: unspecified, leadingDistribution: TextLeadingDistribution.even, locale: unspecified, background: unspecified, foreground: unspecified, shadows: unspecified, fontFeatures: unspecified)'), - ); - }); - }); - group('TextHeightBehavior', () { const TextHeightBehavior behavior0 = TextHeightBehavior(); const TextHeightBehavior behavior1 = TextHeightBehavior( @@ -85,10 +54,6 @@ void main() { const TextHeightBehavior behavior3 = TextHeightBehavior( applyHeightToLastDescent: false ); - const TextHeightBehavior behavior4 = TextHeightBehavior( - applyHeightToLastDescent: false, - leadingDistribution: TextLeadingDistribution.even, - ); test('default constructor works', () { expect(behavior0.applyHeightToFirstAscent, equals(true)); @@ -102,9 +67,6 @@ void main() { expect(behavior3.applyHeightToFirstAscent, equals(true)); expect(behavior3.applyHeightToLastDescent, equals(false)); - - expect(behavior4.applyHeightToLastDescent, equals(false)); - expect(behavior4.leadingDistribution, equals(TextLeadingDistribution.even)); }); test('encode works', () { @@ -112,23 +74,20 @@ void main() { 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)); + expect(const TextHeightBehavior.fromEncoded(0), equals(behavior0)); + expect(const TextHeightBehavior.fromEncoded(3), equals(behavior1)); + expect(const TextHeightBehavior.fromEncoded(1), equals(behavior2)); + expect(const TextHeightBehavior.fromEncoded(2), equals(behavior3)); }); 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)')); - expect(behavior2.toString(), equals('TextHeightBehavior(applyHeightToFirstAscent: false, applyHeightToLastDescent: true, leadingDistribution: TextLeadingDistribution.proportional)')); - expect(behavior3.toString(), equals('TextHeightBehavior(applyHeightToFirstAscent: true, applyHeightToLastDescent: false, leadingDistribution: TextLeadingDistribution.proportional)')); - expect(behavior4.toString(), equals('TextHeightBehavior(applyHeightToFirstAscent: true, applyHeightToLastDescent: false, leadingDistribution: TextLeadingDistribution.even)')); + expect(behavior0.toString(), equals('TextHeightBehavior(applyHeightToFirstAscent: true, applyHeightToLastDescent: true)')); + expect(behavior1.toString(), equals('TextHeightBehavior(applyHeightToFirstAscent: false, applyHeightToLastDescent: false)')); + expect(behavior2.toString(), equals('TextHeightBehavior(applyHeightToFirstAscent: false, applyHeightToLastDescent: true)')); + expect(behavior3.toString(), equals('TextHeightBehavior(applyHeightToFirstAscent: true, applyHeightToLastDescent: false)')); }); }); diff --git a/third_party/txt/src/txt/paragraph_style.h b/third_party/txt/src/txt/paragraph_style.h index 90c54ee4b23d8..46ea7a1e7c1a8 100644 --- a/third_party/txt/src/txt/paragraph_style.h +++ b/third_party/txt/src/txt/paragraph_style.h @@ -41,18 +41,10 @@ enum class TextDirection { ltr, }; -// Adjusts the leading over and under text. -// -// kDisableFirstAscent and kDisableLastDescent allow disabling height -// adjustments to first line's ascent and the last line's descent. If disabled, -// 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. +// Allows disabling height adjustments to first line's ascent and the +// last line's descent. If disabled, the line will use the default font +// metric provided ascent/descent and ParagraphStyle.height will not take +// effect. // // The default behavior is kAll where height adjustments are enabled for all // lines. @@ -66,7 +58,6 @@ enum TextHeightBehavior { kDisableFirstAscent = 0x1, kDisableLastDescent = 0x2, kDisableAll = 0x1 | 0x2, - kEvenLeading = 0x1 << 2, }; class ParagraphStyle { @@ -78,8 +69,8 @@ class ParagraphStyle { std::string font_family = ""; double font_size = 14; double height = 1; - bool has_height_override = false; size_t text_height_behavior = TextHeightBehavior::kAll; + bool has_height_override = false; // Strut properties. strut_enabled must be set to true for the rest of the // properties to take effect. @@ -91,8 +82,6 @@ class ParagraphStyle { double strut_font_size = 14; 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 81f34ec8f42f0..f1febacde5dd7 100644 --- a/third_party/txt/src/txt/paragraph_txt.cc +++ b/third_party/txt/src/txt/paragraph_txt.cc @@ -518,8 +518,8 @@ bool ParagraphTxt::IsStrutValid() const { } void ParagraphTxt::ComputeStrut(StrutMetrics* strut, SkFont& font) { - strut->ascent = std::numeric_limits::lowest(); - strut->descent = std::numeric_limits::lowest(); + strut->ascent = 0; + strut->descent = 0; strut->leading = 0; strut->half_leading = 0; strut->line_height = 0; @@ -553,34 +553,20 @@ void ParagraphTxt::ComputeStrut(StrutMetrics* strut, SkFont& font) { SkFontMetrics strut_metrics; font.getMetrics(&strut_metrics); - const double metrics_height = - -strut_metrics.fAscent + strut_metrics.fDescent; - if (paragraph_style_.strut_has_height_override) { - const double strut_height = - paragraph_style_.strut_height * paragraph_style_.strut_font_size; - const double metrics_leading = - // Zero extra leading if there is no user specified strut leading. + double metrics_height = -strut_metrics.fAscent + strut_metrics.fDescent; + strut->ascent = (-strut_metrics.fAscent / metrics_height) * + paragraph_style_.strut_height * + paragraph_style_.strut_font_size; + strut->descent = (strut_metrics.fDescent / metrics_height) * + paragraph_style_.strut_height * + paragraph_style_.strut_font_size; + strut->leading = + // Zero leading if there is no user specified strut leading. paragraph_style_.strut_leading < 0 ? 0 : (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; - - strut->ascent = - (-strut_metrics.fAscent / metrics_height) * available_height; - strut->descent = - (strut_metrics.fDescent / metrics_height) * available_height; - - strut->leading = metrics_leading + strut_height - available_height; } else { strut->ascent = -strut_metrics.fAscent; strut->descent = strut_metrics.fDescent; @@ -685,8 +671,8 @@ void ParagraphTxt::Layout(double width) { glyph_lines_.clear(); code_unit_runs_.clear(); inline_placeholder_code_unit_runs_.clear(); - max_right_ = std::numeric_limits::lowest(); - min_left_ = std::numeric_limits::max(); + max_right_ = FLT_MIN; + min_left_ = FLT_MAX; final_line_count_ = 0; if (!ComputeLineBreaks()) @@ -1202,101 +1188,79 @@ void ParagraphTxt::UpdateLineMetrics(const SkFontMetrics& metrics, size_t line_number, size_t line_limit) { if (!strut_.force_strut) { - const double metrics_font_height = metrics.fDescent - metrics.fAscent; - // The overall height of the glyph blob. If neither the ascent or the - // descent is disabled, we have block_height = ascent + descent, where - // "ascent" is the extent from the top of the blob to its baseline, and - // "descent" is the extent from the text blob's baseline to its bottom. Not - // to be mistaken with the font's ascent and descent. - 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`. - // - // The raw metrics do not add up to fontSize. The state of font - // metrics is a mess: - // - // Each font has 4 sets of vertical metrics: - // - // * hhea: hheaAscender, hheaDescender, hheaLineGap. - // Used by Apple. - // * OS/2 typo: typoAscender, typoDescender, typoLineGap. - // Used sometimes by Windows for layout. - // * OS/2 win: winAscent, winDescent. - // Also used by Windows, generally will be cut if extends past - // these metrics. - // * EM Square: ascent, descent - // Not actively used, but this defines the 'scale' of the - // units used. - // - // `Use Typo Metrics` is a boolean that, when enabled, prefers - // typo metrics over win metrics. Default is off. Enabled by most - // modern fonts. - // - // In addition to these different sets of metrics, there are also - // multiple strategies for using these metrics: - // - // * Adobe: Set hhea values to typo equivalents. - // * Microsoft: Set hhea values to win equivalents. - // * Web: Use hhea values for text, regardless of `Use Typo Metrics` - // The hheaLineGap is distributed half across the top and half - // across the bottom of the line. - // Exceptions: - // Windows: All browsers respect `Use Typo Metrics` - // Firefox respects `Use Typo Metrics`. - // - // This pertains to this code in that it is ambiguous which set of - // metrics we are actually using via SkFontMetrics. This in turn - // means that if we use the raw metrics, we will see differences - // between platforms as well as unpredictable line heights. - // - // A more thorough explanation is available at - // https://glyphsapp.com/tutorials/vertical-metrics - // - // Doing this ascent/descent normalization to the EM Square allows - // 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; - 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) { - leading = blob_height - font_height; + double ascent; + double descent; + if (style.has_height_override) { + // Scale the ascent and descent such that the sum of ascent and + // descent is `fontsize * style.height * style.font_size`. + // + // The raw metrics do not add up to fontSize. The state of font + // metrics is a mess: + // + // Each font has 4 sets of vertical metrics: + // + // * hhea: hheaAscender, hheaDescender, hheaLineGap. + // Used by Apple. + // * OS/2 typo: typoAscender, typoDescender, typoLineGap. + // Used sometimes by Windows for layout. + // * OS/2 win: winAscent, winDescent. + // Also used by Windows, generally will be cut if extends past + // these metrics. + // * EM Square: ascent, descent + // Not actively used, but this defines the 'scale' of the + // units used. + // + // `Use Typo Metrics` is a boolean that, when enabled, prefers + // typo metrics over win metrics. Default is off. Enabled by most + // modern fonts. + // + // In addition to these different sets of metrics, there are also + // multiple strategies for using these metrics: + // + // * Adobe: Set hhea values to typo equivalents. + // * Microsoft: Set hhea values to win equivalents. + // * Web: Use hhea values for text, regardless of `Use Typo Metrics` + // The hheaLineGap is distributed half across the top and half + // across the bottom of the line. + // Exceptions: + // Windows: All browsers respect `Use Typo Metrics` + // Firefox respects `Use Typo Metrics`. + // + // This pertains to this code in that it is ambiguous which set of + // metrics we are actually using via SkFontMetrics. This in turn + // means that if we use the raw metrics, we will see differences + // between platforms as well as unpredictable line heights. + // + // A more thorough explanation is available at + // https://glyphsapp.com/tutorials/vertical-metrics + // + // Doing this ascent/descent normalization to the EM Square allows + // a sane, consistent, and reasonable line height to be specified, + // though it breaks with what is done by any of the platforms above. + double metrics_height = -metrics.fAscent + metrics.fDescent; + ascent = + (-metrics.fAscent / metrics_height) * style.height * style.font_size; + descent = + (metrics.fDescent / metrics_height) * style.height * style.font_size; } else { - leading = style.has_height_override ? 0.0 : metrics.fLeading; + // Use the font-provided ascent, descent, and leading directly. + ascent = (-metrics.fAscent + metrics.fLeading / 2); + descent = (metrics.fDescent + metrics.fLeading / 2); + } + + // Account for text_height_behavior in paragraph_style_. + // + // Disable first line ascent modifications. + if (line_number == 0 && paragraph_style_.text_height_behavior & + TextHeightBehavior::kDisableFirstAscent) { + ascent = -metrics.fAscent; + } + // Disable last line descent modifications. + if (line_number == line_limit - 1 && + paragraph_style_.text_height_behavior & + TextHeightBehavior::kDisableLastDescent) { + descent = metrics.fDescent; } - const double half_leading = leading / 2; - - // Proportionally distribute the remaining vertical space above and below - // the glyph blob's baseline, per the font's ascent/discent ratio. - const double available_vspace = blob_height - leading; - const double modifiedAscent = - -metrics.fAscent / metrics_font_height * available_vspace + - half_leading; - const double modifiedDescent = - metrics.fDescent / metrics_font_height * available_vspace + - half_leading; - - const bool disableAscent = - line_number == 0 && paragraph_style_.text_height_behavior & - TextHeightBehavior::kDisableFirstAscent; - const bool disableDescent = line_number == line_limit - 1 && - paragraph_style_.text_height_behavior & - TextHeightBehavior::kDisableLastDescent; - - double ascent = disableAscent ? -metrics.fAscent : modifiedAscent; - double descent = disableDescent ? metrics.fDescent : modifiedDescent; ComputePlaceholder(placeholder_run, ascent, descent); @@ -1680,8 +1644,8 @@ std::vector ParagraphTxt::GetRectsForRange( // Per-line metrics for max and min coordinates for left and right boxes. // These metrics cannot be calculated in layout generically because of // selections that do not cover the whole line. - SkScalar max_right = std::numeric_limits::lowest(); - SkScalar min_left = std::numeric_limits::max(); + SkScalar max_right = FLT_MIN; + SkScalar min_left = FLT_MAX; }; std::map line_box_metrics; @@ -1958,8 +1922,8 @@ std::vector ParagraphTxt::GetRectsForPlaceholders() { // Per-line metrics for max and min coordinates for left and right boxes. // These metrics cannot be calculated in layout generically because of // selections that do not cover the whole line. - SkScalar max_right = std::numeric_limits::lowest(); - SkScalar min_left = std::numeric_limits::max(); + SkScalar max_right = FLT_MIN; + SkScalar min_left = FLT_MAX; }; std::vector boxes; diff --git a/third_party/txt/src/txt/paragraph_txt.h b/third_party/txt/src/txt/paragraph_txt.h index e0cf8a6ddd6d0..0919130868211 100644 --- a/third_party/txt/src/txt/paragraph_txt.h +++ b/third_party/txt/src/txt/paragraph_txt.h @@ -315,8 +315,8 @@ class ParagraphTxt : public Paragraph { double longest_line_ = -1.0f; double max_intrinsic_width_ = 0; double min_intrinsic_width_ = 0; - double alphabetic_baseline_ = std::numeric_limits::max(); - double ideographic_baseline_ = std::numeric_limits::max(); + double alphabetic_baseline_ = FLT_MAX; + double ideographic_baseline_ = FLT_MAX; bool needs_layout_ = true; diff --git a/third_party/txt/src/txt/text_style.cc b/third_party/txt/src/txt/text_style.cc index b520c0f0dfa2f..04589659b6539 100644 --- a/third_party/txt/src/txt/text_style.cc +++ b/third_party/txt/src/txt/text_style.cc @@ -48,11 +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) return false; if (foreground != other.foreground) diff --git a/third_party/txt/src/txt/text_style.h b/third_party/txt/src/txt/text_style.h index 6d6bd34766343..0d4a92a099814 100644 --- a/third_party/txt/src/txt/text_style.h +++ b/third_party/txt/src/txt/text_style.h @@ -44,10 +44,6 @@ class TextStyle { FontWeight font_weight = FontWeight::w400; 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 81e2f64113345..445202b60ef7c 100644 --- a/third_party/txt/tests/paragraph_unittests.cc +++ b/third_party/txt/tests/paragraph_unittests.cc @@ -1883,491 +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満毎冠行来昼本可"; - 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::kAll; - 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; - // Override paragraph_style.text_height_behavior: - text_style.has_leading_distribution_override = true; - text_style.half_leading = true; - 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::RectHeightStyle rect_height_style_max = - Paragraph::RectHeightStyle::kMax; - Paragraph::RectWidthStyle rect_width_style = - Paragraph::RectWidthStyle::kTight; - paint.setColor(SK_ColorRED); - - std::vector 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); - } - - std::vector line_boxes = paragraph->GetRectsForRange( - 0, 40, rect_height_style_max, rect_width_style); - EXPECT_EQ(boxes.size(), 3ull); - EXPECT_EQ(line_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_EQ(line_boxes[0].rect.top() - boxes[0].rect.top(), - boxes[0].rect.bottom() - line_boxes[0].rect.bottom()); - EXPECT_EQ(line_boxes[1].rect.top() - boxes[1].rect.top(), - boxes[1].rect.bottom() - line_boxes[1].rect.bottom()); - EXPECT_EQ(line_boxes[2].rect.top() - boxes[2].rect.top(), - boxes[2].rect.bottom() - line_boxes[2].rect.bottom()); - // With half-leadding, the x coordinates should remain the same. - 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(MixedTextHeightBehaviorSameLine)) { - // Both runs will still have the same typeface, but with different text height - // behaviors. - const char* text = "01234満毎冠行来昼本可abcd"; - auto icu_text = icu::UnicodeString::fromUTF8(text); - std::u16string u16_text(icu_text.getBuffer(), - icu_text.getBuffer() + icu_text.length()); - - std::u16string u16_text2(icu_text.getBuffer(), - icu_text.getBuffer() + icu_text.length()); - - txt::ParagraphStyle paragraph_style; - paragraph_style.max_lines = 10; - paragraph_style.text_height_behavior = TextHeightBehavior::kAll; - 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; - // 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); - builder.AddText(u16_text2); - 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::RectHeightStyle rect_height_style_max = - Paragraph::RectHeightStyle::kMax; - Paragraph::RectWidthStyle rect_width_style = - Paragraph::RectWidthStyle::kTight; - paint.setColor(SK_ColorRED); - - std::vector boxes = paragraph->GetRectsForRange( - 0, icu_text.length(), rect_height_style, rect_width_style); - for (size_t i = 0; i < boxes.size(); ++i) { - GetCanvas()->drawRect(boxes[i].rect, paint); - } - - std::vector line_boxes = paragraph->GetRectsForRange( - 0, icu_text.length(), rect_height_style_max, rect_width_style); - // The runs has the same typeface so they should be grouped together. - EXPECT_EQ(boxes.size(), 1ull); - EXPECT_EQ(line_boxes.size(), 1ull); - - const double glyphHeight = boxes[0].rect.height(); - const double metricsAscent = 18.5546875; - const double metricsDescent = 4.8828125; - EXPECT_DOUBLE_EQ(glyphHeight, metricsAscent + metricsDescent); - - const double line_height = 3.6345 * 20; - const double leading = line_height - glyphHeight; - - // Overall descent is from half-leading and overall ascent is from AD-scaling. - EXPECT_NEAR(boxes[0].rect.top() - line_boxes[0].rect.top(), - leading * metricsAscent / (metricsAscent + metricsDescent), - 0.001); - - EXPECT_NEAR(line_boxes[0].rect.bottom() - boxes[0].rect.bottom(), - leading * 0.5, 0.001); -} - -TEST_F(ParagraphTest, - DISABLE_ON_WINDOWS(MixedTextHeightBehaviorSameLineWithZeroHeight)) { - // Both runs will still have the same typeface, but with different text height - // behaviors. - const char* text = "01234満毎冠行来昼本可abcd"; - 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::kAll; - 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; - // Set height to 0 - 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); - 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::RectHeightStyle rect_height_style_max = - Paragraph::RectHeightStyle::kMax; - Paragraph::RectWidthStyle rect_width_style = - Paragraph::RectWidthStyle::kTight; - paint.setColor(SK_ColorRED); - - std::vector boxes = paragraph->GetRectsForRange( - 0, icu_text.length(), rect_height_style, rect_width_style); - for (size_t i = 0; i < boxes.size(); ++i) { - GetCanvas()->drawRect(boxes[i].rect, paint); - } - - std::vector line_boxes = paragraph->GetRectsForRange( - 0, icu_text.length(), rect_height_style_max, rect_width_style); - // The runs has the same typeface so they should be grouped together. - EXPECT_EQ(boxes.size(), 1ull); - EXPECT_EQ(line_boxes.size(), 1ull); - - const double glyphHeight = boxes[0].rect.height(); - const double metricsAscent = 18.5546875; - const double metricsDescent = 4.8828125; - EXPECT_DOUBLE_EQ(glyphHeight, metricsAscent + metricsDescent); - - // line_height for both styled runs is 0, but the overall line height is not - // 0. - EXPECT_DOUBLE_EQ(line_boxes[0].rect.height(), - metricsAscent - (metricsAscent + metricsDescent) / 2); - EXPECT_LT(boxes[0].rect.top(), 0.0); - EXPECT_GT(boxes[0].rect.bottom(), 0.0); -} - -TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(HeightOverrideHalfLeadingStrut)) { - // 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.strut_enabled = true; - paragraph_style.strut_has_height_override = true; - 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()); - - 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; - // Override paragraph_style.text_height_behavior: - text_style.has_leading_distribution_override = true; - text_style.half_leading = true; - 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::RectHeightStyle rect_height_style_max = - Paragraph::RectHeightStyle::kMax; - Paragraph::RectWidthStyle rect_width_style = - Paragraph::RectWidthStyle::kTight; - paint.setColor(SK_ColorRED); - - std::vector 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); - } - - std::vector line_boxes = paragraph->GetRectsForRange( - 0, 40, rect_height_style_max, rect_width_style); - EXPECT_EQ(boxes.size(), 3ull); - EXPECT_EQ(line_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); - - // Strut half leading. - EXPECT_EQ(line_boxes[0].rect.top() - boxes[0].rect.top(), - boxes[0].rect.bottom() - line_boxes[0].rect.bottom()); - EXPECT_EQ(line_boxes[1].rect.top() - boxes[1].rect.top(), - boxes[1].rect.bottom() - line_boxes[1].rect.bottom()); - EXPECT_EQ(line_boxes[2].rect.top() - boxes[2].rect.top(), - boxes[2].rect.bottom() - line_boxes[2].rect.bottom()); - - 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(ZeroHeightHalfLeadingStrutForceHeight)) { - // All 3 lines will have the same typeface. - const char* text = "01234満毎冠行来昼本可abcdn満毎冠行来昼本可"; - 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.strut_enabled = true; - paragraph_style.strut_has_height_override = true; - paragraph_style.strut_height = 0; - // Force strut height. - paragraph_style.force_strut_height = true; - paragraph_style.strut_font_size = 20; - paragraph_style.strut_font_families.push_back("Roboto"); - paragraph_style.strut_half_leading = true; - 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 = 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); - 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::RectHeightStyle rect_height_style_max = - Paragraph::RectHeightStyle::kMax; - Paragraph::RectWidthStyle rect_width_style = - Paragraph::RectWidthStyle::kTight; - paint.setColor(SK_ColorRED); - - std::vector boxes = paragraph->GetRectsForRange( - 0, icu_text.length(), rect_height_style, rect_width_style); - for (size_t i = 0; i < boxes.size(); ++i) { - GetCanvas()->drawRect(boxes[i].rect, paint); - } - - std::vector line_boxes = paragraph->GetRectsForRange( - 0, icu_text.length(), rect_height_style_max, rect_width_style); - // The runs has the same typeface so they should be grouped together. - EXPECT_EQ(boxes.size(), 1ull); - EXPECT_EQ(line_boxes.size(), 1ull); - - const double glyphHeight = boxes[0].rect.height(); - const double metricsAscent = 18.5546875; - const double metricsDescent = 4.8828125; - EXPECT_DOUBLE_EQ(glyphHeight, metricsAscent + metricsDescent); - - EXPECT_DOUBLE_EQ(line_boxes[0].rect.height(), 0.0); - - ASSERT_TRUE(Snapshot()); -} - TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(LeftAlignParagraph)) { const char* text = "This is a very long sentence to test if the text will properly wrap " @@ -7094,68 +6609,4 @@ TEST_F(ParagraphTest, TextHeightBehaviorRectsParagraph) { ASSERT_TRUE(Snapshot()); } -TEST_F(ParagraphTest, MixedTextHeightBehaviorRectsParagraph) { - const char* text = "0123456789"; - auto icu_text = icu::UnicodeString::fromUTF8(text); - std::u16string u16_text(icu_text.getBuffer(), - icu_text.getBuffer() + icu_text.length()); - - txt::ParagraphStyle paragraph_style; - // The paragraph's first line and the last line use the font's ascent/descent. - paragraph_style.text_height_behavior = - txt::TextHeightBehavior::kDisableFirstAscent | - txt::TextHeightBehavior::kDisableLastDescent; - - txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); - - txt::TextStyle text_style; - text_style.color = SK_ColorBLACK; - text_style.font_families = std::vector(1, "Roboto"); - 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); - builder.AddText(u16_text); - - text_style.half_leading = false; - builder.PushStyle(text_style); - builder.AddText(u16_text); - - // 2 identical runs except the first run has half-leading enabled. - builder.Pop(); - - auto paragraph = BuildParagraph(builder); - paragraph->Layout(GetTestCanvasWidth() - 300); - - 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::kMax; - Paragraph::RectWidthStyle rect_width_style = - Paragraph::RectWidthStyle::kTight; - paint.setColor(SK_ColorRED); - std::vector boxes = - paragraph->GetRectsForRange(0, 20, rect_height_style, rect_width_style); - - for (size_t i = 0; i < boxes.size(); ++i) { - GetCanvas()->drawRect(boxes[i].rect, paint); - } - // The kDisableAll flag is applied. - EXPECT_GT(boxes.size(), 1ull); - // The height of the line equals to the metrics height of the font - // (ascent + descent). - EXPECT_FLOAT_EQ(boxes[0].rect.bottom() - boxes[0].rect.top(), - 27.8320312 + 7.32421875); - - ASSERT_TRUE(Snapshot()); -} } // namespace txt