Skip to content

Commit

Permalink
Add style attributes to shaka.text.Cue and TtmlParser.
Browse files Browse the repository at this point in the history
Closes #927.

Change-Id: Ife2e241f8e91999ac0f4600766b0b0c04738c013
  • Loading branch information
ismena committed Jul 19, 2017
1 parent 6bc354a commit b1f337a
Show file tree
Hide file tree
Showing 4 changed files with 271 additions and 42 deletions.
49 changes: 46 additions & 3 deletions lib/text/cue.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ shaka.text.Cue = function(startTime, endTime, payload) {
*/
this.line = null;

/**
* Separation between line areas inside the cue box in px or em
* (e.g. '100px'/'100em'). If not specified, should be no less than
* the largest font size applied to the text in the cue.
* @type {string}.
*/
this.lineHeight = '';

/**
* Line alignment of the cue box.
* @type {shaka.text.Cue.lineAlign}
Expand Down Expand Up @@ -128,23 +136,36 @@ shaka.text.Cue = function(startTime, endTime, payload) {
this.backgroundColor = '';

/**
* Text font size in pixels.
* @type {?number}
* Text font size in px or em (e.g. '100px'/'100em').
* @type {string}
*/
this.fontSize = null;
this.fontSize = '';

/**
* Text font weight. Either normal or bold.
* @type {shaka.text.Cue.fontWeight}
*/
this.fontWeight = Cue.fontWeight.NORMAL;

/**
* Text font style. Normal, italic or oblique.
* @type {shaka.text.Cue.fontStyle}
*/
this.fontStyle = Cue.fontStyle.NORMAL;

/**
* Text font family.
* @type {!string}
*/
this.fontFamily = '';

/**
* Text decoration. A combination of underline, overline
* and line through. Empty array means no decoration.
* @type {!Array.<!shaka.text.Cue.textDecoration>}
*/
this.textDecoration = [];

/**
* Whether or not line wrapping should be applied
* to the cue.
Expand Down Expand Up @@ -239,3 +260,25 @@ shaka.text.Cue.fontWeight = {
BOLD: 700
};


/**
* @enum {string}
* @export
*/
shaka.text.Cue.fontStyle = {
NORMAL: 'normal',
ITALIC: 'italic',
OBLIQUE: 'oblique'
};


/**
* @enum {string}
* @export
*/
shaka.text.Cue.textDecoration = {
UNDERLINE: 'underline',
LINE_THROUGH: 'lineThrough',
OVERLINE: 'overline'
};

137 changes: 134 additions & 3 deletions lib/text/ttml_text_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ goog.provide('shaka.text.TtmlTextParser');
goog.require('goog.asserts');
goog.require('shaka.text.Cue');
goog.require('shaka.text.TextEngine');
goog.require('shaka.util.ArrayUtils');
goog.require('shaka.util.Error');
goog.require('shaka.util.StringUtils');

Expand Down Expand Up @@ -172,6 +173,14 @@ shaka.text.TtmlTextParser.timeHMSFormat_ =
shaka.text.TtmlTextParser.percentValues_ = /^(\d{1,2}|100)% (\d{1,2}|100)%$/;


/**
* @const
* @private {!RegExp}
* @example 100px
*/
shaka.text.TtmlTextParser.unitValues_ = /^(\d+px|\d+em)$/;


/**
* @const
* @private {!Object}
Expand Down Expand Up @@ -422,6 +431,87 @@ shaka.text.TtmlTextParser.addStyle_ = function(
cueElement, region, styles, 'tts:wrapOption');
if (wrapOption && wrapOption == 'noWrap')
cue.wrapLine = false;

var lineHeight = TtmlTextParser.getStyleAttribute_(
cueElement, region, styles, 'tts:lineHeight');
if (lineHeight && lineHeight.match(TtmlTextParser.unitValues_))
cue.lineHeight = lineHeight;

var fontSize = TtmlTextParser.getStyleAttribute_(
cueElement, region, styles, 'tts:fontSize');
if (fontSize && fontSize.match(TtmlTextParser.unitValues_))
cue.fontSize = fontSize;

var fontStyle = TtmlTextParser.getStyleAttribute_(
cueElement, region, styles, 'tts:fontStyle');
if (fontStyle) {
goog.asserts.assert(fontStyle.toUpperCase() in Cue.fontStyle,
fontStyle.toUpperCase() +
' Should be in Cue.fontStyle values!');
cue.fontStyle = Cue.fontStyle[fontStyle.toUpperCase()];
}

// Text decoration is an array of values which can come both
// from the element's style or be inherited from elements'
// parent nodes. All of those values should be applied as long
// as they don't contradict each other. If they do, elements'
// own style gets preference.
var textDecorationRegion = TtmlTextParser.getStyleAttributeFromRegion_(
region, styles, 'tts:textDecoration');
if (textDecorationRegion)
TtmlTextParser.addTextDecoration_(cue, textDecorationRegion);

var textDecorationElement = TtmlTextParser.getStyleAttributeFromElement_(
cueElement, styles, 'tts:textDecoration');
if (textDecorationElement)
TtmlTextParser.addTextDecoration_(cue, textDecorationElement);
};


/**
* Parses text decoration values and adds/removes them to/from the cue.
*
* @param {!shaka.text.Cue} cue
* @param {string} decoration
* @private
*/
shaka.text.TtmlTextParser.addTextDecoration_ = function(cue, decoration) {
var Cue = shaka.text.Cue;
var values = decoration.split(' ');
for (var i = 0; i < values.length; i++) {
switch (values[i]) {
case 'underline':
if (!cue.textDecoration.includes(Cue.textDecoration.UNDERLINE))
cue.textDecoration.push(Cue.textDecoration.UNDERLINE);
break;
case 'noUnderline':
if (cue.textDecoration.includes(Cue.textDecoration.UNDERLINE)) {
shaka.util.ArrayUtils.remove(cue.textDecoration,
Cue.textDecoration.UNDERLINE);
}
break;
case 'lineThrough':
if (!cue.textDecoration.includes(Cue.textDecoration.LINE_THROUGH))
cue.textDecoration.push(Cue.textDecoration.LINE_THROUGH);
break;
case 'noLineThrough':
if (cue.textDecoration.includes(Cue.textDecoration.LINE_THROUGH)) {
shaka.util.ArrayUtils.remove(cue.textDecoration,
Cue.textDecoration.LINE_THROUGH);
}
break;
case 'overline':
if (!cue.textDecoration.includes(Cue.textDecoration.OVERLINE))
cue.textDecoration.push(Cue.textDecoration.OVERLINE);
break;
case 'noOverline':
if (cue.textDecoration.includes(Cue.textDecoration.OVERLINE)) {
shaka.util.ArrayUtils.remove(cue.textDecoration,
Cue.textDecoration.OVERLINE);
}
break;
}
}
};


Expand All @@ -438,20 +528,61 @@ shaka.text.TtmlTextParser.addStyle_ = function(
*/
shaka.text.TtmlTextParser.getStyleAttribute_ = function(
cueElement, region, styles, attribute) {

// An attribute can be specified on region level or in a styling block
// associated with the region or original element.
var TtmlTextParser = shaka.text.TtmlTextParser;
var attr = TtmlTextParser.getStyleAttributeFromElement_(
cueElement, styles, attribute);
if (attr)
return attr;

return TtmlTextParser.getStyleAttributeFromRegion_(
region, styles, attribute);
};


/**
* Finds a specified attribute on the element's associated region
* and returns the value if the attribute was found.
*
* @param {Element} region
* @param {!Array.<!Element>} styles
* @param {string} attribute
* @return {?string}
* @private
*/
shaka.text.TtmlTextParser.getStyleAttributeFromRegion_ = function(
region, styles, attribute) {
var regionChildren = shaka.text.TtmlTextParser.getLeafNodes_(region);
for (var i = 0; i < regionChildren.length; i++) {
var attr = regionChildren[i].getAttribute(attribute);
if (attr)
return attr;
}

var style = shaka.text.TtmlTextParser.getElementFromCollection_(
region, 'style', styles);
if (style)
return style.getAttribute(attribute);
return null;
};


/**
* Finds a specified attribute on the cue element and returns the value
* if the attribute was found.
*
* @param {!Element} cueElement
* @param {!Array.<!Element>} styles
* @param {string} attribute
* @return {?string}
* @private
*/
shaka.text.TtmlTextParser.getStyleAttributeFromElement_ = function(
cueElement, styles, attribute) {
var getElementFromCollection_ =
shaka.text.TtmlTextParser.getElementFromCollection_;
var style = getElementFromCollection_(region, 'style', styles) ||
getElementFromCollection_(cueElement, 'style', styles);
var style = getElementFromCollection_(cueElement, 'style', styles);
if (style)
return style.getAttribute(attribute);
return null;
Expand Down
12 changes: 12 additions & 0 deletions lib/util/array_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,15 @@ shaka.util.ArrayUtils.indexOf = function(array, value, compareFn) {
return -1;
};


/**
* Remove given element from array (assumes no duplicates).
* @param {!Array.<T>} array
* @param {T} element
* @template T
*/
shaka.util.ArrayUtils.remove = function(array, element) {
var index = array.indexOf(element);
if (index > -1)
array.splice(index, 1);
};
Loading

0 comments on commit b1f337a

Please sign in to comment.