Skip to content

Commit

Permalink
Add position, line and size settings parsing to the TTML parser.
Browse files Browse the repository at this point in the history
Issue #111.

Change-Id: Ieeafda794b54ae2aad6751eadba28e28882d6b49
  • Loading branch information
ismena committed Jul 11, 2016
1 parent 44c0536 commit 7e9bd79
Show file tree
Hide file tree
Showing 2 changed files with 228 additions and 18 deletions.
95 changes: 77 additions & 18 deletions lib/media/ttml_text_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ shaka.media.TtmlTextParser.timeHMSFormat_ =
/^(?:(\d*\.?\d*)h)?(?:(\d*\.?\d*)m)?(?:(\d*\.?\d*)s)?(?:(\d*\.?\d*)ms)?$/;


/**
* @const
* @private {!RegExp}
* @example 50% 10%
*/
shaka.media.TtmlTextParser.percentValues_ = /^(\d{1,2}|100)% (\d{1,2}|100)%$/;


/**
* Gets leaf nodes of the xml node tree. Ignores the text, br elements
* and the spans positioned inside paragraphs
Expand Down Expand Up @@ -226,37 +234,88 @@ shaka.media.TtmlTextParser.parseCue_ = function(


/**
* Adds applicable style properties to a cue (only align at the moment)
* Adds applicable style properties to a cue
*
* @param {!VTTCue} cue
* @param {Element} region
* @param {Array<Element>} styles
* @private
*/
shaka.media.TtmlTextParser.addStyle_ = function(cue, region, styles) {
if (!region) {
return;
var TtmlTextParser = shaka.media.TtmlTextParser;
var results = null;

var align = TtmlTextParser.getStyleAttribute_(
region, styles, 'tts:textAlign');
if (align)
cue.lineAlign = align;

var extent = TtmlTextParser.getStyleAttribute_(region, styles, 'tts:extent');
if (extent) {
results = TtmlTextParser.percentValues_.exec(extent);
if (results != null) {
// use width value of the extent attribute for size.
// Height value is ignored.
cue.size = Number(results[1]);
}
}

var align;
var writingMode = TtmlTextParser.getStyleAttribute_(
region, styles, 'tts:writingMode');
var isVerticalText = true;
if (writingMode == 'tb' || writingMode == 'tblr')
cue.vertical = 'lr';
else if (writingMode == 'tbrl')
cue.vertical = 'rl';
else
isVerticalText = false;

var origin = TtmlTextParser.getStyleAttribute_(region, styles, 'tts:origin');
if (origin) {
results = TtmlTextParser.percentValues_.exec(origin);
if (results != null) {
// for vertical text use first coordinate of tts:origin
// to represent line of the cue and second - for position.
// Otherwise (horizontal), use them the other way around.
if (isVerticalText) {
cue.position = Number(results[2]);
cue.line = Number(results[1]);
} else {
cue.position = Number(results[1]);
cue.line = Number(results[2]);
}
}
}
};


/**
* Finds a specified attribute in ttml and returns its value if the
* attribute was found.
*
* @param {Element} region
* @param {Array<Element>} styles
* @param {string} attribute
* @return {?string}
* @private
*/
shaka.media.TtmlTextParser.getStyleAttribute_ = function(
region, styles, attribute) {

// an attribute can be specified on region level or in a styling block
// associated with the region
var regionChildren = shaka.media.TtmlTextParser.getLeafNodes_(region);
for (var i = 0; i < regionChildren.length; i++) {
var attr = regionChildren[i].getAttribute(attribute);
if (attr)
return attr;
}

// region can have a style attribute or contain <style> nodes
var style = shaka.media.TtmlTextParser.getElementFromCollection_(
region, 'style', styles);
if (style)
align = style.getAttribute('tts:textAlign');

// look for <style> nodes inside the region
else {
var regionChildren = shaka.media.TtmlTextParser.getLeafNodes_(region);
for (var i = 0; i < regionChildren.length; i++) {
align = regionChildren[i].getAttribute('tts:textAlign');
if (align)
break;
}
}
if (align)
cue.lineAlign = align;
return style.getAttribute(attribute);
return null;
};


Expand Down
151 changes: 151 additions & 0 deletions test/media/ttml_text_parser_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,149 @@ describe('TtmlTextParser', function() {
'</tt>');
});

it('supports size setting', function() {
verifyHelper(
[
{start: 62.05, end: 3723.2, text: 'Test', size: 50}
],
'<tt xmlns:tts="ttml#styling">' +
'<layout>' +
'<region xml:id="subtitleArea" tts:extent="50% 16%" />' +
'</layout>' +
'<body region="subtitleArea">' +
'<p begin="01:02.05" end="01:02:03.200">Test</p>' +
'</body>' +
'</tt>');
});

it('supports line and position settings for horizontal text',
function() {
verifyHelper(
[
{start: 62.05, end: 3723.2, text: 'Test', position: 50, line: 16}
],
'<tt xmlns:tts="ttml#styling">' +
'<layout>' +
'<region xml:id="subtitleArea" tts:origin="50% 16%"/>' +
'</layout>' +
'<body region="subtitleArea">' +
'<p begin="01:02.05" end="01:02:03.200">Test</p>' +
'</body>' +
'</tt>');
verifyHelper(
[
{start: 62.05, end: 3723.2, text: 'Test', position: 50, line: 16}
],
'<tt xmlns:tts="ttml#styling">' +
'<layout>' +
'<region xml:id="subtitleArea" tts:origin="50% 16%" ' +
'tts:writingMode="lrtb" />' +
'</layout>' +
'<body region="subtitleArea">' +
'<p begin="01:02.05" end="01:02:03.200">Test</p>' +
'</body>' +
'</tt>');
verifyHelper(
[
{start: 62.05, end: 3723.2, text: 'Test', position: 50, line: 16}
],
'<tt xmlns:tts="ttml#styling">' +
'<layout>' +
'<region xml:id="subtitleArea" tts:origin="50% 16%" ' +
'tts:writingMode="lr" />' +
'</layout>' +
'<body region="subtitleArea">' +
'<p begin="01:02.05" end="01:02:03.200">Test</p>' +
'</body>' +
'</tt>');
});

it('supports line and position settings for vertical text',
function() {
verifyHelper(
[
{start: 62.05, end: 3723.2, text: 'Test', position: 16, line: 50}
],
'<tt xmlns:tts="ttml#styling">' +
'<layout>' +
'<region xml:id="subtitleArea" tts:origin="50% 16%" ' +
'tts:writingMode="tb" />' +
'</layout>' +
'<body region="subtitleArea">' +
'<p begin="01:02.05" end="01:02:03.200">Test</p>' +
'</body>' +
'</tt>');
verifyHelper(
[
{start: 62.05, end: 3723.2, text: 'Test', position: 16, line: 50}
],
'<tt xmlns:tts="ttml#styling">' +
'<layout>' +
'<region xml:id="subtitleArea" tts:origin="50% 16%" ' +
'tts:writingMode="tblr" />' +
'</layout>' +
'<body region="subtitleArea">' +
'<p begin="01:02.05" end="01:02:03.200">Test</p>' +
'</body>' +
'</tt>');
verifyHelper(
[
{start: 62.05, end: 3723.2, text: 'Test', position: 16, line: 50}
],
'<tt xmlns:tts="ttml#styling">' +
'<layout>' +
'<region xml:id="subtitleArea" tts:origin="50% 16%" ' +
'tts:writingMode="tbrl" />' +
'</layout>' +
'<body region="subtitleArea">' +
'<p begin="01:02.05" end="01:02:03.200">Test</p>' +
'</body>' +
'</tt>');
});

it('supports vertical setting',
function() {
verifyHelper(
[
{start: 62.05, end: 3723.2, text: 'Test', vertical: 'lr'}
],
'<tt xmlns:tts="ttml#styling">' +
'<layout>' +
'<region xml:id="subtitleArea" ' +
'tts:writingMode="tb" />' +
'</layout>' +
'<body region="subtitleArea">' +
'<p begin="01:02.05" end="01:02:03.200">Test</p>' +
'</body>' +
'</tt>');
verifyHelper(
[
{start: 62.05, end: 3723.2, text: 'Test', vertical: 'rl'}
],
'<tt xmlns:tts="ttml#styling">' +
'<layout>' +
'<region xml:id="subtitleArea" ' +
'tts:writingMode="tbrl" />' +
'</layout>' +
'<body region="subtitleArea">' +
'<p begin="01:02.05" end="01:02:03.200">Test</p>' +
'</body>' +
'</tt>');
verifyHelper(
[
{start: 62.05, end: 3723.2, text: 'Test', vertical: 'lr'}
],
'<tt xmlns:tts="ttml#styling">' +
'<layout>' +
'<region xml:id="subtitleArea" ' +
'tts:writingMode="tblr" />' +
'</layout>' +
'<body region="subtitleArea">' +
'<p begin="01:02.05" end="01:02:03.200">Test</p>' +
'</body>' +
'</tt>');
});


function verifyHelper(cues, string) {
var data = shaka.util.StringUtils.toUTF8(string);
Expand All @@ -196,6 +339,14 @@ describe('TtmlTextParser', function() {

if (cues[i].lineAlign)
expect(result[i].lineAlign).toBe(cues[i].lineAlign);
if (cues[i].size)
expect(result[i].size).toBe(cues[i].size);
if (cues[i].line)
expect(result[i].line).toBe(cues[i].line);
if (cues[i].position)
expect(result[i].position).toBe(cues[i].position);
if (cues[i].vertical)
expect(result[i].vertical).toBe(cues[i].vertical);
}
}

Expand Down

0 comments on commit 7e9bd79

Please sign in to comment.