Skip to content

Commit ee297aa

Browse files
authored
Reland "Engine/LibTxt/dart:ui impl of TextHeightBehavior flutter#15087" (flutter#16155)
1 parent 4a55b4f commit ee297aa

File tree

10 files changed

+452
-24
lines changed

10 files changed

+452
-24
lines changed

lib/ui/text.dart

Lines changed: 115 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,94 @@ enum TextDecorationStyle {
429429
wavy
430430
}
431431

432+
/// {@template flutter.dart:ui.textHeightBehavior}
433+
/// Defines how the paragraph will apply [TextStyle.height] to the ascent of the
434+
/// first line and descent of the last line.
435+
///
436+
/// Each boolean value represents whether the [TextStyle.height] modifier will
437+
/// be applied to the corresponding metric. By default, all properties are true,
438+
/// and [TextStyle.height] is applied as normal. When set to false, the font's
439+
/// default ascent will be used.
440+
/// {@endtemplate}
441+
class TextHeightBehavior {
442+
443+
/// Creates a new TextHeightBehavior object.
444+
///
445+
/// * applyHeightToFirstAscent: When true, the [TextStyle.height] modifier
446+
/// will be applied to the ascent of the first line. When false, the font's
447+
/// default ascent will be used.
448+
/// * applyHeightToLastDescent: When true, the [TextStyle.height] modifier
449+
/// will be applied to the descent of the last line. When false, the font's
450+
/// default descent will be used.
451+
///
452+
/// All properties default to true (height modifications applied as normal).
453+
const TextHeightBehavior({
454+
this.applyHeightToFirstAscent = true,
455+
this.applyHeightToLastDescent = true,
456+
});
457+
458+
/// Creates a new TextHeightBehavior object from an encoded form.
459+
///
460+
/// See [encode] for the creation of the encoded form.
461+
const TextHeightBehavior.fromEncoded(int encoded) : applyHeightToFirstAscent = (encoded & 0x1) == 0,
462+
applyHeightToLastDescent = (encoded & 0x2) == 0;
463+
464+
465+
/// Whether to apply the [TextStyle.height] modifier to the ascent of the first
466+
/// line in the paragraph.
467+
///
468+
/// When true, the [TextStyle.height] modifier will be applied to to the ascent
469+
/// of the first line. When false, the font's default ascent will be used and
470+
/// the [TextStyle.height] will have no effect on the ascent of the first line.
471+
///
472+
/// This property only has effect if a non-null [TextStyle.height] is specified.
473+
///
474+
/// Defaults to true (height modifications applied as normal).
475+
final bool applyHeightToFirstAscent;
476+
477+
/// Whether to apply the [TextStyle.height] modifier to the descent of the last
478+
/// line in the paragraph.
479+
///
480+
/// When true, the [TextStyle.height] modifier will be applied to to the descent
481+
/// of the last line. When false, the font's default descent will be used and
482+
/// the [TextStyle.height] will have no effect on the descent of the last line.
483+
///
484+
/// This property only has effect if a non-null [TextStyle.height] is specified.
485+
///
486+
/// Defaults to true (height modifications applied as normal).
487+
final bool applyHeightToLastDescent;
488+
489+
/// Returns an encoded int representation of this object.
490+
int encode() {
491+
return (applyHeightToFirstAscent ? 0 : 1 << 0) | (applyHeightToLastDescent ? 0 : 1 << 1);
492+
}
493+
494+
@override
495+
bool operator ==(dynamic other) {
496+
if (other.runtimeType != runtimeType)
497+
return false;
498+
return other is TextHeightBehavior
499+
&& other.applyHeightToFirstAscent == applyHeightToFirstAscent
500+
&& other.applyHeightToLastDescent == applyHeightToLastDescent;
501+
}
502+
503+
@override
504+
int get hashCode {
505+
return hashValues(
506+
applyHeightToFirstAscent,
507+
applyHeightToLastDescent,
508+
);
509+
}
510+
511+
@override
512+
String toString() {
513+
return 'TextHeightBehavior('
514+
'applyHeightToFirstAscent: $applyHeightToFirstAscent, '
515+
'applyHeightToLastDescent: $applyHeightToLastDescent'
516+
')';
517+
}
518+
}
519+
432520
/// Determines if lists [a] and [b] are deep equivalent.
433521
///
434522
/// Returns true if the lists are both null, or if they are both non-null, have
@@ -746,20 +834,23 @@ class TextStyle {
746834
//
747835
// - Element 5: The value of |maxLines|.
748836
//
837+
// - Element 6: The encoded value of |textHeightBehavior|.
838+
//
749839
Int32List _encodeParagraphStyle(
750840
TextAlign textAlign,
751841
TextDirection textDirection,
752842
int maxLines,
753843
String fontFamily,
754844
double fontSize,
755845
double height,
846+
TextHeightBehavior textHeightBehavior,
756847
FontWeight fontWeight,
757848
FontStyle fontStyle,
758849
StrutStyle strutStyle,
759850
String ellipsis,
760851
Locale locale,
761852
) {
762-
final Int32List result = Int32List(6); // also update paragraph_builder.cc
853+
final Int32List result = Int32List(7); // also update paragraph_builder.cc
763854
if (textAlign != null) {
764855
result[0] |= 1 << 1;
765856
result[1] = textAlign.index;
@@ -780,28 +871,32 @@ Int32List _encodeParagraphStyle(
780871
result[0] |= 1 << 5;
781872
result[5] = maxLines;
782873
}
783-
if (fontFamily != null) {
874+
if (textHeightBehavior != null) {
784875
result[0] |= 1 << 6;
876+
result[6] = textHeightBehavior.encode();
877+
}
878+
if (fontFamily != null) {
879+
result[0] |= 1 << 7;
785880
// Passed separately to native.
786881
}
787882
if (fontSize != null) {
788-
result[0] |= 1 << 7;
883+
result[0] |= 1 << 8;
789884
// Passed separately to native.
790885
}
791886
if (height != null) {
792-
result[0] |= 1 << 8;
887+
result[0] |= 1 << 9;
793888
// Passed separately to native.
794889
}
795890
if (strutStyle != null) {
796-
result[0] |= 1 << 9;
891+
result[0] |= 1 << 10;
797892
// Passed separately to native.
798893
}
799894
if (ellipsis != null) {
800-
result[0] |= 1 << 10;
895+
result[0] |= 1 << 11;
801896
// Passed separately to native.
802897
}
803898
if (locale != null) {
804-
result[0] |= 1 << 11;
899+
result[0] |= 1 << 12;
805900
// Passed separately to native.
806901
}
807902
return result;
@@ -842,6 +937,9 @@ class ParagraphStyle {
842937
/// the line height to take the height as defined by the font, which may not
843938
/// be exactly the height of the `fontSize`.
844939
///
940+
/// * `textHeightBehavior`: Specifies how the `height` multiplier is
941+
/// applied to ascent of the first line and the descent of the last line.
942+
///
845943
/// * `fontWeight`: The typeface thickness to use when painting the text
846944
/// (e.g., bold).
847945
///
@@ -869,6 +967,7 @@ class ParagraphStyle {
869967
String fontFamily,
870968
double fontSize,
871969
double height,
970+
TextHeightBehavior textHeightBehavior,
872971
FontWeight fontWeight,
873972
FontStyle fontStyle,
874973
StrutStyle strutStyle,
@@ -881,6 +980,7 @@ class ParagraphStyle {
881980
fontFamily,
882981
fontSize,
883982
height,
983+
textHeightBehavior,
884984
fontWeight,
885985
fontStyle,
886986
strutStyle,
@@ -929,11 +1029,14 @@ class ParagraphStyle {
9291029
'fontWeight: ${ _encoded[0] & 0x008 == 0x008 ? FontWeight.values[_encoded[3]] : "unspecified"}, '
9301030
'fontStyle: ${ _encoded[0] & 0x010 == 0x010 ? FontStyle.values[_encoded[4]] : "unspecified"}, '
9311031
'maxLines: ${ _encoded[0] & 0x020 == 0x020 ? _encoded[5] : "unspecified"}, '
932-
'fontFamily: ${ _encoded[0] & 0x040 == 0x040 ? _fontFamily : "unspecified"}, '
933-
'fontSize: ${ _encoded[0] & 0x080 == 0x080 ? _fontSize : "unspecified"}, '
934-
'height: ${ _encoded[0] & 0x100 == 0x100 ? "${_height}x" : "unspecified"}, '
935-
'ellipsis: ${ _encoded[0] & 0x200 == 0x200 ? "\"$_ellipsis\"" : "unspecified"}, '
936-
'locale: ${ _encoded[0] & 0x400 == 0x400 ? _locale : "unspecified"}'
1032+
'textHeightBehavior: ${
1033+
_encoded[0] & 0x040 == 0x040 ?
1034+
TextHeightBehavior.fromEncoded(_encoded[6]).toString() : "unspecified"}, '
1035+
'fontFamily: ${ _encoded[0] & 0x080 == 0x080 ? _fontFamily : "unspecified"}, '
1036+
'fontSize: ${ _encoded[0] & 0x100 == 0x100 ? _fontSize : "unspecified"}, '
1037+
'height: ${ _encoded[0] & 0x200 == 0x200 ? "${_height}x" : "unspecified"}, '
1038+
'ellipsis: ${ _encoded[0] & 0x400 == 0x400 ? "\"$_ellipsis\"" : "unspecified"}, '
1039+
'locale: ${ _encoded[0] & 0x800 == 0x800 ? _locale : "unspecified"}'
9371040
')';
9381041
}
9391042
}

lib/ui/text/paragraph_builder.cc

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,13 @@ const int psTextDirectionIndex = 2;
7575
const int psFontWeightIndex = 3;
7676
const int psFontStyleIndex = 4;
7777
const int psMaxLinesIndex = 5;
78-
const int psFontFamilyIndex = 6;
79-
const int psFontSizeIndex = 7;
80-
const int psHeightIndex = 8;
81-
const int psStrutStyleIndex = 9;
82-
const int psEllipsisIndex = 10;
83-
const int psLocaleIndex = 11;
78+
const int psTextHeightBehaviorIndex = 6;
79+
const int psFontFamilyIndex = 7;
80+
const int psFontSizeIndex = 8;
81+
const int psHeightIndex = 9;
82+
const int psStrutStyleIndex = 10;
83+
const int psEllipsisIndex = 11;
84+
const int psLocaleIndex = 12;
8485

8586
const int psTextAlignMask = 1 << psTextAlignIndex;
8687
const int psTextDirectionMask = 1 << psTextDirectionIndex;
@@ -90,6 +91,7 @@ const int psMaxLinesMask = 1 << psMaxLinesIndex;
9091
const int psFontFamilyMask = 1 << psFontFamilyIndex;
9192
const int psFontSizeMask = 1 << psFontSizeIndex;
9293
const int psHeightMask = 1 << psHeightIndex;
94+
const int psTextHeightBehaviorMask = 1 << psTextHeightBehaviorIndex;
9395
const int psStrutStyleMask = 1 << psStrutStyleIndex;
9496
const int psEllipsisMask = 1 << psEllipsisIndex;
9597
const int psLocaleMask = 1 << psLocaleIndex;
@@ -265,6 +267,10 @@ ParagraphBuilder::ParagraphBuilder(
265267
style.has_height_override = true;
266268
}
267269

270+
if (mask & psTextHeightBehaviorMask) {
271+
style.text_height_behavior = encoded[psTextHeightBehaviorIndex];
272+
}
273+
268274
if (mask & psStrutStyleMask) {
269275
decodeStrut(strutData, strutFontFamilies, style);
270276
}

lib/web_ui/lib/src/engine/compositor/text.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class SkParagraphStyle implements ui.ParagraphStyle {
2525
String fontFamily,
2626
double fontSize,
2727
double height,
28+
ui.TextHeightBehavior textHeightBehavior,
2829
ui.FontWeight fontWeight,
2930
ui.FontStyle fontStyle,
3031
ui.StrutStyle strutStyle,
@@ -38,6 +39,7 @@ class SkParagraphStyle implements ui.ParagraphStyle {
3839
fontFamily,
3940
fontSize,
4041
height,
42+
textHeightBehavior,
4143
fontWeight,
4244
fontStyle,
4345
ellipsis,
@@ -85,6 +87,7 @@ class SkParagraphStyle implements ui.ParagraphStyle {
8587
String fontFamily,
8688
double fontSize,
8789
double height,
90+
ui.TextHeightBehavior textHeightBehavior,
8891
ui.FontWeight fontWeight,
8992
ui.FontStyle fontStyle,
9093
String ellipsis,
@@ -129,6 +132,10 @@ class SkParagraphStyle implements ui.ParagraphStyle {
129132
skParagraphStyle['heightMultiplier'] = height;
130133
}
131134

135+
if (textHeightBehavior != null) {
136+
skParagraphStyle['textHeightBehavior'] = textHeightBehavior.encode();
137+
}
138+
132139
if (maxLines != null) {
133140
skParagraphStyle['maxLines'] = maxLines;
134141
}

lib/web_ui/lib/src/engine/text/paragraph.dart

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ class EngineParagraphStyle implements ui.ParagraphStyle {
468468
String fontFamily,
469469
double fontSize,
470470
double height,
471+
ui.TextHeightBehavior textHeightBehavior,
471472
ui.FontWeight fontWeight,
472473
ui.FontStyle fontStyle,
473474
ui.StrutStyle strutStyle,
@@ -481,6 +482,7 @@ class EngineParagraphStyle implements ui.ParagraphStyle {
481482
_fontFamily = fontFamily,
482483
_fontSize = fontSize,
483484
_height = height,
485+
_textHeightBehavior = textHeightBehavior,
484486
// TODO(b/128317744): add support for strut style.
485487
_strutStyle = strutStyle,
486488
_ellipsis = ellipsis,
@@ -494,6 +496,7 @@ class EngineParagraphStyle implements ui.ParagraphStyle {
494496
final String _fontFamily;
495497
final double _fontSize;
496498
final double _height;
499+
final ui.TextHeightBehavior _textHeightBehavior;
497500
final EngineStrutStyle _strutStyle;
498501
final String _ellipsis;
499502
final ui.Locale _locale;
@@ -547,13 +550,27 @@ class EngineParagraphStyle implements ui.ParagraphStyle {
547550
_fontFamily == typedOther._fontFamily ||
548551
_fontSize == typedOther._fontSize ||
549552
_height == typedOther._height ||
553+
_textHeightBehavior == typedOther._textHeightBehavior ||
550554
_ellipsis == typedOther._ellipsis ||
551555
_locale == typedOther._locale;
552556
}
553557

554558
@override
555-
int get hashCode =>
556-
ui.hashValues(_fontFamily, _fontSize, _height, _ellipsis, _locale);
559+
int get hashCode {
560+
return ui.hashValues(
561+
_textAlign,
562+
_textDirection,
563+
_fontWeight,
564+
_fontStyle,
565+
_maxLines,
566+
_fontFamily,
567+
_fontSize,
568+
_height,
569+
_textHeightBehavior,
570+
_ellipsis,
571+
_locale
572+
);
573+
}
557574

558575
@override
559576
String toString() {
@@ -564,6 +581,7 @@ class EngineParagraphStyle implements ui.ParagraphStyle {
564581
'fontWeight: ${_fontWeight ?? "unspecified"}, '
565582
'fontStyle: ${_fontStyle ?? "unspecified"}, '
566583
'maxLines: ${_maxLines ?? "unspecified"}, '
584+
'textHeightBehavior: ${_textHeightBehavior ?? "unspecified"}, '
567585
'fontFamily: ${_fontFamily ?? "unspecified"}, '
568586
'fontSize: ${_fontSize != null ? _fontSize.toStringAsFixed(1) : "unspecified"}, '
569587
'height: ${_height != null ? "${_height.toStringAsFixed(1)}x" : "unspecified"}, '

0 commit comments

Comments
 (0)