mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[libTxt] resolve null leading distribution in dart:ui. (flutter/engine#25510)
This commit is contained in:
parent
604aa51067
commit
fe01e1acbb
@ -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,
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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)'));
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user