Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit d42b5b7

Browse files
libtxt: support for locale-specific text styles (#4943)
Fixes flutter/flutter#12630
1 parent d2b69fe commit d42b5b7

File tree

9 files changed

+80
-21
lines changed

9 files changed

+80
-21
lines changed

lib/snapshot/fuchsia_compilation_trace.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,13 +1845,15 @@ dart:ui,TextStyle,get:_fontSize
18451845
dart:ui,TextStyle,get:_letterSpacing
18461846
dart:ui,TextStyle,get:_wordSpacing
18471847
dart:ui,TextStyle,get:_height
1848+
dart:ui,TextStyle,get:_locale
18481849
dart:ui,FilterQuality,get:index
18491850
dart:ui,ParagraphStyle,ParagraphStyle.
18501851
dart:ui,ParagraphStyle,get:_encoded
18511852
dart:ui,ParagraphStyle,get:_fontFamily
18521853
dart:ui,ParagraphStyle,get:_fontSize
18531854
dart:ui,ParagraphStyle,get:_lineHeight
18541855
dart:ui,ParagraphStyle,get:_ellipsis
1856+
dart:ui,ParagraphStyle,get:_locale
18551857
dart:ui,_Jenkins,combine
18561858
dart:ui,_Jenkins,finish
18571859
dart:ui,_HashEnd,_HashEnd.

lib/ui/text.dart

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ Int32List _encodeTextStyle(
256256
double letterSpacing,
257257
double wordSpacing,
258258
double height,
259+
Locale locale,
259260
) {
260261
final Int32List result = new Int32List(8);
261262
if (color != null) {
@@ -306,6 +307,10 @@ Int32List _encodeTextStyle(
306307
result[0] |= 1 << 12;
307308
// Passed separately to native.
308309
}
310+
if (locale != null) {
311+
result[0] |= 1 << 13;
312+
// Passed separately to native.
313+
}
309314
return result;
310315
}
311316

@@ -325,6 +330,7 @@ class TextStyle {
325330
/// * `wordSpacing`: The amount of space (in logical pixels) to add at each sequence of white-space (i.e. between each word).
326331
/// * `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.
327332
/// * `height`: The height of this text span, as a multiple of the font size.
333+
/// * `locale`: The locale used to select region-specific glyphs.
328334
TextStyle({
329335
Color color,
330336
TextDecoration decoration,
@@ -338,6 +344,7 @@ class TextStyle {
338344
double letterSpacing,
339345
double wordSpacing,
340346
double height,
347+
Locale locale,
341348
}) : _encoded = _encodeTextStyle(
342349
color,
343350
decoration,
@@ -351,19 +358,22 @@ class TextStyle {
351358
letterSpacing,
352359
wordSpacing,
353360
height,
361+
locale,
354362
),
355363
_fontFamily = fontFamily ?? '',
356364
_fontSize = fontSize,
357365
_letterSpacing = letterSpacing,
358366
_wordSpacing = wordSpacing,
359-
_height = height;
367+
_height = height,
368+
_locale = locale;
360369

361370
final Int32List _encoded;
362371
final String _fontFamily;
363372
final double _fontSize;
364373
final double _letterSpacing;
365374
final double _wordSpacing;
366375
final double _height;
376+
final Locale _locale;
367377

368378
@override
369379
bool operator ==(dynamic other) {
@@ -376,7 +386,8 @@ class TextStyle {
376386
_fontSize != typedOther._fontSize ||
377387
_letterSpacing != typedOther._letterSpacing ||
378388
_wordSpacing != typedOther._wordSpacing ||
379-
_height != typedOther._height)
389+
_height != typedOther._height ||
390+
_locale != typedOther._locale)
380391
return false;
381392
for (int index = 0; index < _encoded.length; index += 1) {
382393
if (_encoded[index] != typedOther._encoded[index])
@@ -386,7 +397,7 @@ class TextStyle {
386397
}
387398

388399
@override
389-
int get hashCode => hashValues(hashList(_encoded), _fontFamily, _fontSize, _letterSpacing, _wordSpacing, _height);
400+
int get hashCode => hashValues(hashList(_encoded), _fontFamily, _fontSize, _letterSpacing, _wordSpacing, _height, _locale);
390401

391402
@override
392403
String toString() {
@@ -402,7 +413,8 @@ class TextStyle {
402413
'fontSize: ${ _encoded[0] & 0x0200 == 0x0200 ? _fontSize : "unspecified"}, '
403414
'letterSpacing: ${ _encoded[0] & 0x0400 == 0x0400 ? "${_letterSpacing}x" : "unspecified"}, '
404415
'wordSpacing: ${ _encoded[0] & 0x0800 == 0x0800 ? "${_wordSpacing}x" : "unspecified"}, '
405-
'height: ${ _encoded[0] & 0x1000 == 0x1000 ? "${_height}x" : "unspecified"}'
416+
'height: ${ _encoded[0] & 0x1000 == 0x1000 ? "${_height}x" : "unspecified"}, '
417+
'locale: ${ _encoded[0] & 0x2000 == 0x2000 ? _locale : "unspecified"}'
406418
')';
407419
}
408420
}
@@ -434,6 +446,7 @@ Int32List _encodeParagraphStyle(
434446
double fontSize,
435447
double lineHeight,
436448
String ellipsis,
449+
Locale locale,
437450
) {
438451
final Int32List result = new Int32List(6); // also update paragraph_builder.cc
439452
if (textAlign != null) {
@@ -472,6 +485,10 @@ Int32List _encodeParagraphStyle(
472485
result[0] |= 1 << 9;
473486
// Passed separately to native.
474487
}
488+
if (locale != null) {
489+
result[0] |= 1 << 10;
490+
// Passed separately to native.
491+
}
475492
return result;
476493
}
477494

@@ -521,6 +538,8 @@ class ParagraphStyle {
521538
/// constraints are those set in the [ParagraphConstraints] object passed to
522539
/// the [Paragraph.layout] method. The empty string and the null value are
523540
/// considered equivalent and turn off this behavior.
541+
///
542+
/// * `locale`: The locale used to select region-specific glyphs.
524543
ParagraphStyle({
525544
TextAlign textAlign,
526545
TextDirection textDirection,
@@ -531,6 +550,7 @@ class ParagraphStyle {
531550
double fontSize,
532551
double lineHeight,
533552
String ellipsis,
553+
Locale locale,
534554
}) : _encoded = _encodeParagraphStyle(
535555
textAlign,
536556
textDirection,
@@ -541,17 +561,20 @@ class ParagraphStyle {
541561
fontSize,
542562
lineHeight,
543563
ellipsis,
564+
locale,
544565
),
545566
_fontFamily = fontFamily,
546567
_fontSize = fontSize,
547568
_lineHeight = lineHeight,
548-
_ellipsis = ellipsis;
569+
_ellipsis = ellipsis,
570+
_locale = locale;
549571

550572
final Int32List _encoded;
551573
final String _fontFamily;
552574
final double _fontSize;
553575
final double _lineHeight;
554576
final String _ellipsis;
577+
final Locale _locale;
555578

556579
@override
557580
bool operator ==(dynamic other) {
@@ -563,7 +586,8 @@ class ParagraphStyle {
563586
if (_fontFamily != typedOther._fontFamily ||
564587
_fontSize != typedOther._fontSize ||
565588
_lineHeight != typedOther._lineHeight ||
566-
_ellipsis != typedOther._ellipsis)
589+
_ellipsis != typedOther._ellipsis ||
590+
_locale != typedOther._locale)
567591
return false;
568592
for (int index = 0; index < _encoded.length; index += 1) {
569593
if (_encoded[index] != typedOther._encoded[index])
@@ -573,7 +597,7 @@ class ParagraphStyle {
573597
}
574598

575599
@override
576-
int get hashCode => hashValues(hashList(_encoded), _fontFamily, _fontSize, _lineHeight, _ellipsis);
600+
int get hashCode => hashValues(hashList(_encoded), _fontFamily, _fontSize, _lineHeight, _ellipsis, _locale);
577601

578602
@override
579603
String toString() {
@@ -586,7 +610,8 @@ class ParagraphStyle {
586610
'fontFamily: ${ _encoded[0] & 0x040 == 0x040 ? _fontFamily : "unspecified"}, '
587611
'fontSize: ${ _encoded[0] & 0x080 == 0x080 ? _fontSize : "unspecified"}, '
588612
'lineHeight: ${ _encoded[0] & 0x100 == 0x100 ? "${_lineHeight}x" : "unspecified"}, '
589-
'ellipsis: ${ _encoded[0] & 0x200 == 0x200 ? "\"$_ellipsis\"" : "unspecified"}'
613+
'ellipsis: ${ _encoded[0] & 0x200 == 0x200 ? "\"$_ellipsis\"" : "unspecified"}, '
614+
'locale: ${ _encoded[0] & 0x400 == 0x400 ? _locale : "unspecified"}'
590615
')';
591616
}
592617
}
@@ -982,14 +1007,16 @@ class Paragraph extends NativeFieldWrapperClass2 {
9821007
class ParagraphBuilder extends NativeFieldWrapperClass2 {
9831008
/// Creates a [ParagraphBuilder] object, which is used to create a
9841009
/// [Paragraph].
985-
ParagraphBuilder(ParagraphStyle style) { _constructor(style._encoded, style._fontFamily, style._fontSize, style._lineHeight, style._ellipsis); }
986-
void _constructor(Int32List encoded, String fontFamily, double fontSize, double lineHeight, String ellipsis) native 'ParagraphBuilder_constructor';
1010+
ParagraphBuilder(ParagraphStyle style) { _constructor(style._encoded, style._fontFamily, style._fontSize, style._lineHeight, style._ellipsis, _encodeLocale(style._locale)); }
1011+
void _constructor(Int32List encoded, String fontFamily, double fontSize, double lineHeight, String ellipsis, String locale) native 'ParagraphBuilder_constructor';
9871012

9881013
/// Applies the given style to the added text until [pop] is called.
9891014
///
9901015
/// See [pop] for details.
991-
void pushStyle(TextStyle style) => _pushStyle(style._encoded, style._fontFamily, style._fontSize, style._letterSpacing, style._wordSpacing, style._height);
992-
void _pushStyle(Int32List encoded, String fontFamily, double fontSize, double letterSpacing, double wordSpacing, double height) native 'ParagraphBuilder_pushStyle';
1016+
void pushStyle(TextStyle style) => _pushStyle(style._encoded, style._fontFamily, style._fontSize, style._letterSpacing, style._wordSpacing, style._height, _encodeLocale(style._locale));
1017+
void _pushStyle(Int32List encoded, String fontFamily, double fontSize, double letterSpacing, double wordSpacing, double height, String locale) native 'ParagraphBuilder_pushStyle';
1018+
1019+
static String _encodeLocale(Locale locale) => locale?.toString() ?? '';
9931020

9941021
/// Ends the effect of the most recent call to [pushStyle].
9951022
///

lib/ui/text/paragraph_builder.cc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const int tsFontSizeIndex = 9;
4141
const int tsLetterSpacingIndex = 10;
4242
const int tsWordSpacingIndex = 11;
4343
const int tsHeightIndex = 12;
44+
const int tsLocaleIndex = 13;
4445

4546
const int tsColorMask = 1 << tsColorIndex;
4647
const int tsTextDecorationMask = 1 << tsTextDecorationIndex;
@@ -54,6 +55,7 @@ const int tsFontSizeMask = 1 << tsFontSizeIndex;
5455
const int tsLetterSpacingMask = 1 << tsLetterSpacingIndex;
5556
const int tsWordSpacingMask = 1 << tsWordSpacingIndex;
5657
const int tsHeightMask = 1 << tsHeightIndex;
58+
const int tsLocaleMask = 1 << tsLocaleIndex;
5759

5860
// ParagraphStyle
5961

@@ -66,6 +68,7 @@ const int psFontFamilyIndex = 6;
6668
const int psFontSizeIndex = 7;
6769
const int psLineHeightIndex = 8;
6870
const int psEllipsisIndex = 9;
71+
const int psLocaleIndex = 10;
6972

7073
const int psTextAlignMask = 1 << psTextAlignIndex;
7174
const int psTextDirectionMask = 1 << psTextDirectionIndex;
@@ -76,6 +79,7 @@ const int psFontFamilyMask = 1 << psFontFamilyIndex;
7679
const int psFontSizeMask = 1 << psFontSizeIndex;
7780
const int psLineHeightMask = 1 << psLineHeightIndex;
7881
const int psEllipsisMask = 1 << psEllipsisIndex;
82+
const int psLocaleMask = 1 << psLocaleIndex;
7983

8084
float getComputedSizeFromSpecifiedSize(float specifiedSize) {
8185
if (specifiedSize < std::numeric_limits<float>::epsilon())
@@ -191,7 +195,7 @@ FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
191195

192196
void ParagraphBuilder::RegisterNatives(tonic::DartLibraryNatives* natives) {
193197
natives->Register(
194-
{{"ParagraphBuilder_constructor", ParagraphBuilder_constructor, 6, true},
198+
{{"ParagraphBuilder_constructor", ParagraphBuilder_constructor, 7, true},
195199
FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
196200
}
197201

@@ -200,16 +204,18 @@ fxl::RefPtr<ParagraphBuilder> ParagraphBuilder::create(
200204
const std::string& fontFamily,
201205
double fontSize,
202206
double lineHeight,
203-
const std::u16string& ellipsis) {
207+
const std::u16string& ellipsis,
208+
const std::string& locale) {
204209
return fxl::MakeRefCounted<ParagraphBuilder>(encoded, fontFamily, fontSize,
205-
lineHeight, ellipsis);
210+
lineHeight, ellipsis, locale);
206211
}
207212

208213
ParagraphBuilder::ParagraphBuilder(tonic::Int32List& encoded,
209214
const std::string& fontFamily,
210215
double fontSize,
211216
double lineHeight,
212-
const std::u16string& ellipsis) {
217+
const std::u16string& ellipsis,
218+
const std::string& locale) {
213219
if (!Settings::Get().using_blink) {
214220
int32_t mask = encoded[0];
215221
txt::ParagraphStyle style;
@@ -242,6 +248,10 @@ ParagraphBuilder::ParagraphBuilder(tonic::Int32List& encoded,
242248
style.ellipsis = ellipsis;
243249
}
244250

251+
if (mask & psLocaleMask) {
252+
style.locale = locale;
253+
}
254+
245255
m_paragraphBuilder = std::make_unique<txt::ParagraphBuilder>(
246256
style, blink::FontCollection::ForProcess().GetFontCollection());
247257
} else {
@@ -274,7 +284,8 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded,
274284
double fontSize,
275285
double letterSpacing,
276286
double wordSpacing,
277-
double height) {
287+
double height,
288+
const std::string& locale) {
278289
FXL_DCHECK(encoded.num_elements() == 8);
279290

280291
int32_t mask = encoded[0];
@@ -331,6 +342,10 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded,
331342
style.height = height;
332343
}
333344

345+
if (mask & tsLocaleMask) {
346+
style.locale = locale;
347+
}
348+
334349
m_paragraphBuilder->PushStyle(style);
335350
} else {
336351
// Blink Version.

lib/ui/text/paragraph_builder.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ class ParagraphBuilder : public fxl::RefCountedThreadSafe<ParagraphBuilder>,
3131
const std::string& fontFamily,
3232
double fontSize,
3333
double lineHeight,
34-
const std::u16string& ellipsis);
34+
const std::u16string& ellipsis,
35+
const std::string& locale);
3536

3637
~ParagraphBuilder() override;
3738

@@ -40,7 +41,8 @@ class ParagraphBuilder : public fxl::RefCountedThreadSafe<ParagraphBuilder>,
4041
double fontSize,
4142
double letterSpacing,
4243
double wordSpacing,
43-
double height);
44+
double height,
45+
const std::string& locale);
4446

4547
void pop();
4648

@@ -55,7 +57,8 @@ class ParagraphBuilder : public fxl::RefCountedThreadSafe<ParagraphBuilder>,
5557
const std::string& fontFamily,
5658
double fontSize,
5759
double lineHeight,
58-
const std::u16string& ellipsis);
60+
const std::u16string& ellipsis,
61+
const std::string& locale);
5962

6063
void createRenderView();
6164

third_party/txt/src/txt/paragraph.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "font_collection.h"
2929
#include "font_skia.h"
3030
#include "lib/fxl/logging.h"
31+
#include "minikin/FontLanguageListCache.h"
3132
#include "minikin/HbFontCache.h"
3233
#include "minikin/LayoutUtils.h"
3334
#include "minikin/LineBreaker.h"
@@ -130,7 +131,12 @@ bool GetItalic(const TextStyle& style) {
130131
}
131132

132133
minikin::FontStyle GetMinikinFontStyle(const TextStyle& style) {
133-
return minikin::FontStyle(GetWeight(style), GetItalic(style));
134+
uint32_t language_list_id =
135+
style.locale.empty()
136+
? minikin::FontLanguageListCache::kEmptyListId
137+
: minikin::FontStyle::registerLanguageList(style.locale);
138+
return minikin::FontStyle(language_list_id, 0, GetWeight(style),
139+
GetItalic(style));
134140
}
135141

136142
void GetFontAndMinikinPaint(const TextStyle& style,

third_party/txt/src/txt/paragraph_style.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ TextStyle ParagraphStyle::GetTextStyle() const {
2424
result.font_style = font_style;
2525
result.font_family = font_family;
2626
result.font_size = font_size;
27+
result.locale = locale;
2728
return result;
2829
}
2930

third_party/txt/src/txt/paragraph_style.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class ParagraphStyle {
5353
size_t max_lines = std::numeric_limits<size_t>::max();
5454
double line_height = 1.0;
5555
std::u16string ellipsis;
56+
std::string locale;
57+
5658
// Default strategy is kBreakStrategy_Greedy. Sometimes,
5759
// kBreakStrategy_HighQuality will produce more desireable layouts (eg, very
5860
// long words are more likely to be reasonably placed).

third_party/txt/src/txt/text_style.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ bool TextStyle::equals(const TextStyle& other) const {
4747
return false;
4848
if (height != other.height)
4949
return false;
50+
if (locale != other.locale)
51+
return false;
5052

5153
return true;
5254
}

third_party/txt/src/txt/text_style.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class TextStyle {
4545
double letter_spacing = 0.0;
4646
double word_spacing = 0.0;
4747
double height = 1.0;
48+
std::string locale;
4849

4950
TextStyle();
5051

0 commit comments

Comments
 (0)