@@ -18,6 +18,7 @@ class EngineParagraph implements ui.Paragraph {
1818 @required ui.TextAlign textAlign,
1919 @required ui.TextDirection textDirection,
2020 @required ui.Paint background,
21+ @required List <ui.Shadow > shadows,
2122 }) : assert ((plainText == null && paint == null ) ||
2223 (plainText != null && paint != null )),
2324 _paragraphElement = paragraphElement,
@@ -26,7 +27,8 @@ class EngineParagraph implements ui.Paragraph {
2627 _textAlign = textAlign,
2728 _textDirection = textDirection,
2829 _paint = paint,
29- _background = background;
30+ _background = background,
31+ _shadows = shadows;
3032
3133 final html.HtmlElement _paragraphElement;
3234 final ParagraphGeometricStyle _geometricStyle;
@@ -35,6 +37,7 @@ class EngineParagraph implements ui.Paragraph {
3537 final ui.TextAlign _textAlign;
3638 final ui.TextDirection _textDirection;
3739 final ui.Paint _background;
40+ final List <ui.Shadow > _shadows;
3841
3942 @visibleForTesting
4043 String get plainText => _plainText;
@@ -287,7 +290,8 @@ class EngineParagraph implements ui.Paragraph {
287290 return ui.TextRange (start: textPosition.offset, end: textPosition.offset);
288291 }
289292
290- final int start = WordBreaker .prevBreakIndex (_plainText, textPosition.offset);
293+ final int start =
294+ WordBreaker .prevBreakIndex (_plainText, textPosition.offset);
291295 final int end = WordBreaker .nextBreakIndex (_plainText, textPosition.offset);
292296 return ui.TextRange (start: start, end: end);
293297 }
@@ -321,6 +325,7 @@ class EngineParagraphStyle implements ui.ParagraphStyle {
321325 ui.StrutStyle strutStyle,
322326 String ellipsis,
323327 ui.Locale locale,
328+ List <ui.Shadow > shadows,
324329 }) : _textAlign = textAlign,
325330 _textDirection = textDirection,
326331 _fontWeight = fontWeight,
@@ -332,7 +337,8 @@ class EngineParagraphStyle implements ui.ParagraphStyle {
332337 // TODO(b/128317744): add support for strut style.
333338 _strutStyle = strutStyle,
334339 _ellipsis = ellipsis,
335- _locale = locale;
340+ _locale = locale,
341+ _shadows = shadows;
336342
337343 final ui.TextAlign _textAlign;
338344 final ui.TextDirection _textDirection;
@@ -345,6 +351,7 @@ class EngineParagraphStyle implements ui.ParagraphStyle {
345351 final EngineStrutStyle _strutStyle;
346352 final String _ellipsis;
347353 final ui.Locale _locale;
354+ final List <ui.Shadow > _shadows;
348355
349356 String get _effectiveFontFamily {
350357 if (assertionsEnabled) {
@@ -413,6 +420,7 @@ class EngineParagraphStyle implements ui.ParagraphStyle {
413420 'height: ${_height != null ? "${_height .toStringAsFixed (1 )}x" : "unspecified" }, '
414421 'ellipsis: ${_ellipsis != null ? "\" $_ellipsis \" " : "unspecified" }, '
415422 'locale: ${_locale ?? "unspecified" }'
423+ 'shadows: ${_shadows ?? "unspecified" }'
416424 ')' ;
417425 } else {
418426 return super .toString ();
@@ -798,6 +806,7 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder {
798806 ui.Locale locale = _paragraphStyle._locale;
799807 ui.Paint background;
800808 ui.Paint foreground;
809+ List <ui.Shadow > shadows;
801810
802811 int i = 0 ;
803812
@@ -852,6 +861,9 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder {
852861 if (style._foreground != null ) {
853862 foreground = style._foreground;
854863 }
864+ if (style._shadows != null ) {
865+ shadows = style._shadows;
866+ }
855867 i++ ;
856868 }
857869
@@ -871,6 +883,7 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder {
871883 locale: locale,
872884 background: background,
873885 foreground: foreground,
886+ shadows: shadows,
874887 );
875888
876889 ui.Paint paint;
@@ -900,6 +913,7 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder {
900913 wordSpacing: wordSpacing,
901914 decoration: _textDecorationToCssString (decoration, decorationStyle),
902915 ellipsis: _paragraphStyle._ellipsis,
916+ shadows: shadows,
903917 ),
904918 plainText: '' ,
905919 paint: paint,
@@ -953,6 +967,7 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder {
953967 wordSpacing: wordSpacing,
954968 decoration: _textDecorationToCssString (decoration, decorationStyle),
955969 ellipsis: _paragraphStyle._ellipsis,
970+ shadows: shadows,
956971 ),
957972 plainText: plainText,
958973 paint: paint,
@@ -996,6 +1011,7 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder {
9961011 lineHeight: _paragraphStyle._height,
9971012 maxLines: _paragraphStyle._maxLines,
9981013 ellipsis: _paragraphStyle._ellipsis,
1014+ shadows: _paragraphStyle._shadows,
9991015 ),
10001016 plainText: null ,
10011017 paint: null ,
@@ -1082,6 +1098,9 @@ void _applyParagraphStyleToElement({
10821098 if (style._effectiveFontFamily != null ) {
10831099 cssStyle.fontFamily = canonicalizeFontFamily (style._effectiveFontFamily);
10841100 }
1101+ if (style._shadows != null ) {
1102+ cssStyle.textShadow = _shadowListToCss (style._shadows);
1103+ }
10851104 } else {
10861105 if (style._textAlign != previousStyle._textAlign) {
10871106 cssStyle.textAlign = textAlignToCssValue (
@@ -1108,6 +1127,9 @@ void _applyParagraphStyleToElement({
11081127 if (style._fontFamily != previousStyle._fontFamily) {
11091128 cssStyle.fontFamily = canonicalizeFontFamily (style._fontFamily);
11101129 }
1130+ if (style._shadows != previousStyle._shadows) {
1131+ cssStyle.textShadow = _shadowListToCss (style._shadows);
1132+ }
11111133 }
11121134}
11131135
@@ -1150,7 +1172,8 @@ void _applyTextStyleToElement({
11501172 }
11511173 } else {
11521174 if (style._effectiveFontFamily != null ) {
1153- cssStyle.fontFamily = canonicalizeFontFamily (style._effectiveFontFamily);
1175+ cssStyle.fontFamily =
1176+ canonicalizeFontFamily (style._effectiveFontFamily);
11541177 }
11551178 }
11561179 if (style._letterSpacing != null ) {
@@ -1162,6 +1185,9 @@ void _applyTextStyleToElement({
11621185 if (style._decoration != null ) {
11631186 updateDecoration = true ;
11641187 }
1188+ if (style._shadows != null ) {
1189+ cssStyle.textShadow = _shadowListToCss (style._shadows);
1190+ }
11651191 } else {
11661192 if (style._color != previousStyle._color ||
11671193 style._foreground != previousStyle._foreground) {
@@ -1197,6 +1223,9 @@ void _applyTextStyleToElement({
11971223 style._decorationColor != previousStyle._decorationColor) {
11981224 updateDecoration = true ;
11991225 }
1226+ if (style._shadows != previousStyle._shadows) {
1227+ cssStyle.textShadow = _shadowListToCss (style._shadows);
1228+ }
12001229 }
12011230
12021231 if (updateDecoration) {
@@ -1214,6 +1243,27 @@ void _applyTextStyleToElement({
12141243 }
12151244}
12161245
1246+ String _shadowListToCss (List <ui.Shadow > shadows) {
1247+ if (shadows.isEmpty) {
1248+ return '' ;
1249+ }
1250+ // CSS text-shadow is a comma separated list of shadows.
1251+ // <offsetx> <offsety> <blur-radius> <color>.
1252+ // Shadows are applied front-to-back with first shadow on top.
1253+ // Color is optional. offsetx,y are required. blur-radius is optional as well
1254+ // and defaults to 0.
1255+ StringBuffer sb = new StringBuffer ();
1256+ for (int i = 0 , len = shadows.length; i < len; i++ ) {
1257+ if (i != 0 ) {
1258+ sb.write (',' );
1259+ }
1260+ ui.Shadow shadow = shadows[i];
1261+ sb.write ('${shadow .offset .dx }px ${shadow .offset .dy }px '
1262+ '${shadow .blurRadius }px ${shadow .color .toCssString ()}' );
1263+ }
1264+ return sb.toString ();
1265+ }
1266+
12171267/// Applies background color properties in text style to paragraph or span
12181268/// elements.
12191269void _applyTextBackgroundToElement ({
0 commit comments