diff --git a/externs/shaka/text.js b/externs/shaka/text.js index 953663f134..1fff8609e1 100644 --- a/externs/shaka/text.js +++ b/externs/shaka/text.js @@ -297,6 +297,20 @@ shaka.extern.Cue = class { */ this.fontFamily; + /** + * Text stroke color as a CSS color, e.g. "#FFFFFF" or "white". + * @type {string} + * @exportDoc + */ + this.textStrokeColor; + + /** + * Text stroke width as a CSS stroke-width value. + * @type {string} + * @exportDoc + */ + this.textStrokeWidth; + /** * Text letter spacing as a CSS letter-spacing value. * @type {string} diff --git a/lib/text/cue.js b/lib/text/cue.js index 2c747dcbba..40d24cb515 100644 --- a/lib/text/cue.js +++ b/lib/text/cue.js @@ -144,6 +144,18 @@ shaka.text.Cue = class { */ this.border = ''; + /** + * @override + * @exportInterface + */ + this.textStrokeColor = ''; + + /** + * @override + * @exportInterface + */ + this.textStrokeWidth = ''; + /** * @override * @exportInterface diff --git a/lib/text/ttml_text_parser.js b/lib/text/ttml_text_parser.js index 9964b6bf2f..dc4a715bf0 100644 --- a/lib/text/ttml_text_parser.js +++ b/lib/text/ttml_text_parser.js @@ -509,7 +509,6 @@ shaka.text.TtmlTextParser = class { const color = TtmlTextParser.getStyleAttribute_( cueElement, region, styles, 'color', shouldInheritRegionStyles); - if (color) { cue.color = color; } @@ -562,7 +561,6 @@ shaka.text.TtmlTextParser = class { const fontSize = TtmlTextParser.getStyleAttribute_( cueElement, region, styles, 'fontSize', shouldInheritRegionStyles); - if (fontSize) { const isValidFontSizeUnit = fontSize.match(TtmlTextParser.unitValues_) || @@ -600,6 +598,31 @@ shaka.text.TtmlTextParser = class { } } + const textOutline = TtmlTextParser.getStyleAttribute_( + cueElement, region, styles, 'textOutline', shouldInheritRegionStyles); + if (textOutline) { + // tts:textOutline isn't natively supported by browsers, but it can be + // mostly replicated using the non-standard -webkit-text-stroke-width and + // -webkit-text-stroke-color properties. + const split = textOutline.split(' '); + if (split[0].match(TtmlTextParser.unitValues_)) { + // There is no defined color, so default to the text color. + cue.textStrokeColor = cue.color; + } else { + cue.textStrokeColor = split[0]; + split.shift(); + } + if (split[0] && split[0].match(TtmlTextParser.unitValues_)) { + cue.textStrokeWidth = split[0]; + } else { + // If there is no width, or the width is not a number, don't draw a + // border. + cue.textStrokeColor = ''; + } + // There is an optional blur radius also, but we have no way of + // replicating that, so ignore it. + } + const letterSpacing = TtmlTextParser.getStyleAttribute_( cueElement, region, styles, 'letterSpacing', shouldInheritRegionStyles); if (letterSpacing && letterSpacing.match(TtmlTextParser.unitValues_)) { diff --git a/lib/text/ui_text_displayer.js b/lib/text/ui_text_displayer.js index 12380e2d00..97841c9c0b 100644 --- a/lib/text/ui_text_displayer.js +++ b/lib/text/ui_text_displayer.js @@ -320,6 +320,8 @@ shaka.text.UITextDisplayer = class { style = span.style; } + style.webkitTextStrokeColor = cue.textStrokeColor; + style.webkitTextStrokeWidth = cue.textStrokeWidth; style.backgroundColor = cue.backgroundColor; style.border = cue.border; style.color = cue.color; diff --git a/test/text/ttml_text_parser_unit.js b/test/text/ttml_text_parser_unit.js index d7f69818e9..a1c12b5824 100644 --- a/test/text/ttml_text_parser_unit.js +++ b/test/text/ttml_text_parser_unit.js @@ -1211,6 +1211,8 @@ describe('TtmlTextParser', () => { fontStyle: Cue.fontStyle.ITALIC, lineHeight: '20px', fontSize: '10em', + textStrokeColor: 'blue', + textStrokeWidth: '3px', }, { startTime: 2, @@ -1222,6 +1224,7 @@ describe('TtmlTextParser', () => { '' + '' + '