[libTxt] resolve null leading distribution in dart:ui. (flutter/engine#25510)

This commit is contained in:
LongCatIsLooong 2021-04-19 13:49:01 -07:00 committed by GitHub
parent 604aa51067
commit fe01e1acbb
12 changed files with 128 additions and 242 deletions

View File

@ -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<T>(List<T>? a, List<T>? 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<T>(List<T>? a, List<T>? 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<FontFeature>? 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<Shadow>? _shadows;
final List<FontFeature>? _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<int>(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<String>? _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<String>(other._fontFamilyFallback, _fontFamilyFallback)
&& _listEquals<int>(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<String>? strutFontFamilies;
final StrutStyle? strutStyle = style._strutStyle;
if (strutStyle != null) {
strutFontFamilies = <String>[];
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<String>? strutFontFamilies;
final StrutStyle? strutStyle = style._strutStyle;
final ByteData? encodedStrutStyle;
if (strutStyle != null && strutStyle._enabled) {
final String? fontFamily = strutStyle._fontFamily;
strutFontFamilies = <String>[
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<double> get placeholderScales => _placeholderScales;
List<double> _placeholderScales = <double>[];
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<String> fullFontFamilies = <String>[];
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<FontFeature>? fontFeatures = style._fontFeatures;
@ -3369,7 +3395,7 @@ class ParagraphBuilder extends NativeFieldWrapperClass2 {
}
_pushStyle(
style._encoded,
encoded,
fullFontFamilies,
style._fontSize,
style._letterSpacing,

View File

@ -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<txt::FontStyle>(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> 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) {

View File

@ -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) {

View File

@ -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)

View File

@ -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()

View File

@ -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)'));

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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<std::string> font_families;

View File

@ -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<std::string>(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<txt::Paragraph::TextBox> 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);