@@ -62,21 +62,34 @@ class CkParagraphStyle implements ui.ParagraphStyle {
6262 skTextStyle.fontSize = fontSize;
6363 }
6464
65- if (fontFamily == null ||
66- ! skiaFontCollection.registeredFamilies.contains (fontFamily)) {
67- fontFamily = 'Roboto' ;
68- }
69- skTextStyle.fontFamilies = [fontFamily];
65+ skTextStyle.fontFamilies = [fontFamilyOrFallback (fontFamily)];
7066
7167 return skTextStyle;
7268 }
7369
70+ static String fontFamilyOrFallback (String ? requestedFontFamily) {
71+ if (requestedFontFamily == null ||
72+ ! isRegisteredFontFamily (requestedFontFamily)) {
73+ return 'Roboto' ;
74+ } else {
75+ return requestedFontFamily;
76+ }
77+ }
78+
79+ static bool isRegisteredFontFamily (String fontFamily) {
80+ return skiaFontCollection.registeredFamilies.contains (fontFamily);
81+ }
82+
83+ static bool isNotRegisteredFontFamily (String fontFamily) {
84+ return ! isRegisteredFontFamily (fontFamily);
85+ }
86+
7487 static SkStrutStyleProperties toSkStrutStyleProperties (ui.StrutStyle value) {
7588 EngineStrutStyle style = value as EngineStrutStyle ;
7689 final SkStrutStyleProperties skStrutStyle = SkStrutStyleProperties ();
7790 if (style._fontFamily != null ) {
7891 String fontFamily = style._fontFamily! ;
79- if (! skiaFontCollection.registeredFamilies. contains (fontFamily)) {
92+ if (! isRegisteredFontFamily (fontFamily)) {
8093 fontFamily = 'Roboto' ;
8194 }
8295 final List <String > fontFamilies = < String > [fontFamily];
@@ -167,7 +180,7 @@ class CkParagraphStyle implements ui.ParagraphStyle {
167180
168181 CkTextStyle getTextStyle () {
169182 return CkTextStyle (
170- fontFamily: _fontFamily,
183+ fontFamily: fontFamilyOrFallback ( _fontFamily) ,
171184 fontSize: _fontSize,
172185 fontWeight: _fontWeight,
173186 fontStyle: _fontStyle,
@@ -279,19 +292,22 @@ class CkTextStyle implements ui.TextStyle {
279292 properties.locale = locale.toLanguageTag ();
280293 }
281294
282- if (fontFamily == null ||
283- ! skiaFontCollection.registeredFamilies.contains (fontFamily)) {
284- fontFamily = 'Roboto' ;
285- }
286-
287- List <String > fontFamilies = < String > [fontFamily];
288- if (fontFamilyFallback != null &&
289- ! fontFamilyFallback.every ((font) => fontFamily == font)) {
290- fontFamilies.addAll (fontFamilyFallback);
295+ final bool hasFontFamilyFallback = fontFamilyFallback != null && fontFamilyFallback.isNotEmpty;
296+ if (fontFamily != null && hasFontFamilyFallback) {
297+ properties.fontFamilies = < String > [
298+ fontFamily,
299+ ...fontFamilyFallback,
300+ ];
301+ } else if (fontFamily != null ) {
302+ properties.fontFamilies = < String > [fontFamily];
303+ } else if (hasFontFamilyFallback) {
304+ properties.fontFamilies = fontFamilyFallback;
305+ } else {
306+ // All cases where some font family is specified should have been
307+ // exhausted above.
308+ assert (fontFamily == null && ! hasFontFamilyFallback);
291309 }
292310
293- properties.fontFamilies = fontFamilies;
294-
295311 if (fontWeight != null || fontStyle != null ) {
296312 properties.fontStyle = toSkFontStyle (fontWeight, fontStyle);
297313 }
@@ -352,6 +368,24 @@ class CkTextStyle implements ui.TextStyle {
352368 /// The values in this text style are used unless [other] specifically
353369 /// overrides it.
354370 CkTextStyle mergeWith (CkTextStyle other) {
371+ final String ? effectiveFontFamily = other.fontFamily ?? fontFamily;
372+ List <String >? effectiveFontFamilyFallback = other.fontFamilyFallback ?? fontFamilyFallback;
373+
374+ if (effectiveFontFamily == null || CkParagraphStyle .isNotRegisteredFontFamily (effectiveFontFamily)) {
375+ // If the effective family is not registered, we must make sure that we have a good fallback.
376+ if (effectiveFontFamilyFallback == null || effectiveFontFamilyFallback.isEmpty) {
377+ effectiveFontFamilyFallback = < String > ['Roboto' ];
378+ } else {
379+ final bool allFallbacksUnregistered = effectiveFontFamilyFallback.every (CkParagraphStyle .isNotRegisteredFontFamily);
380+ if (allFallbacksUnregistered) {
381+ effectiveFontFamilyFallback = < String > [
382+ ...effectiveFontFamilyFallback,
383+ 'Roboto' ,
384+ ];
385+ }
386+ }
387+ }
388+
355389 return CkTextStyle (
356390 color: other.color ?? color,
357391 decoration: other.decoration ?? decoration,
@@ -361,8 +395,8 @@ class CkTextStyle implements ui.TextStyle {
361395 fontWeight: other.fontWeight ?? fontWeight,
362396 fontStyle: other.fontStyle ?? fontStyle,
363397 textBaseline: other.textBaseline ?? textBaseline,
364- fontFamily: other.fontFamily ?? fontFamily ,
365- fontFamilyFallback: other.fontFamilyFallback ?? fontFamilyFallback ,
398+ fontFamily: effectiveFontFamily ,
399+ fontFamilyFallback: effectiveFontFamilyFallback ,
366400 fontSize: other.fontSize ?? fontSize,
367401 letterSpacing: other.letterSpacing ?? letterSpacing,
368402 wordSpacing: other.wordSpacing ?? wordSpacing,
@@ -609,7 +643,9 @@ class CkParagraphBuilder implements ui.ParagraphBuilder {
609643 _paragraphBuilder = canvasKit.ParagraphBuilder .MakeFromFontProvider (
610644 style.skParagraphStyle,
611645 skiaFontCollection.fontProvider,
612- );
646+ ) {
647+ _styleStack.add (_style.getTextStyle ());
648+ }
613649
614650 @override
615651 void addPlaceholder (
@@ -687,13 +723,19 @@ class CkParagraphBuilder implements ui.ParagraphBuilder {
687723
688724 @override
689725 void pop () {
726+ if (_styleStack.length <= 1 ) {
727+ // The top-level text style is paragraph-level. We don't pop it off.
728+ return ;
729+ }
690730 _commands.add (const _ParagraphCommand .pop ());
691731 _styleStack.removeLast ();
692732 _paragraphBuilder.pop ();
693733 }
694734
695- CkTextStyle _peekStyle () =>
696- _styleStack.isEmpty ? _style.getTextStyle () : _styleStack.last;
735+ CkTextStyle _peekStyle () {
736+ assert (_styleStack.isNotEmpty);
737+ return _styleStack.last;
738+ }
697739
698740 // Used as the paint for background or foreground in the text style when
699741 // the other one is not specified. CanvasKit either both background and
0 commit comments