jellyfin-web/dashboard-ui/bower_components/libjass/libjass.js
2016-04-04 21:23:42 -04:00

9650 lines
398 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* libjass
*
* https://github.com/Arnavion/libjass
*
* Copyright 2013 Arnav Singh
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function (root, factory) {
var global = this;
if (typeof define === "function" && define.amd) {
define([], function () {
return factory(global);
});
} else if (typeof exports === "object" && typeof module === "object") {
module.exports = factory(global);
} else if (typeof exports === "object") {
exports.libjass = factory(global);
} else {
root.libjass = factory(global);
}
})(this, function (global) {
"use strict";
return function (modules) {
var installedModules = Object.create(null);
function require(moduleId) {
if (installedModules[moduleId]) {
return installedModules[moduleId];
}
var exports = installedModules[moduleId] = Object.create(null);
modules[moduleId](exports, require);
return exports;
}
return require(0);
}([ /* 0 ./index */ function (exports, require) {
var settings = require(23);
var settings_1 = require(23);
exports.debugMode = settings_1.debugMode;
exports.verboseMode = settings_1.verboseMode;
var set = require(33);
var set_1 = require(33);
exports.Set = set_1.Set;
var map = require(30);
var map_1 = require(30);
exports.Map = map_1.Map;
var promise = require(32);
var promise_1 = require(32);
exports.Promise = promise_1.Promise;
exports.DeferredPromise = promise_1.DeferredPromise;
var webworker = require(37);
exports.webworker = webworker;
var parts = require(8);
exports.parts = parts;
var parser = require(1);
exports.parser = parser;
var renderers = require(14);
exports.renderers = renderers;
var ass_1 = require(24);
exports.ASS = ass_1.ASS;
var attachment_1 = require(25);
exports.Attachment = attachment_1.Attachment;
exports.AttachmentType = attachment_1.AttachmentType;
var dialogue_1 = require(26);
exports.Dialogue = dialogue_1.Dialogue;
var script_properties_1 = require(28);
exports.ScriptProperties = script_properties_1.ScriptProperties;
var style_1 = require(29);
exports.Style = style_1.Style;
var misc_1 = require(27);
exports.BorderStyle = misc_1.BorderStyle;
exports.Format = misc_1.Format;
exports.WrappingStyle = misc_1.WrappingStyle;
Object.defineProperties(exports, {
debugMode: {
get: function () {
return settings.debugMode;
},
set: settings.setDebugMode
},
verboseMode: {
get: function () {
return settings.verboseMode;
},
set: settings.setVerboseMode
},
Set: {
get: function () {
return set.Set;
},
set: set.setImplementation
},
Map: {
get: function () {
return map.Map;
},
set: map.setImplementation
},
Promise: {
get: function () {
return promise.Promise;
},
set: promise.setImplementation
}
});
}, /* 1 ./parser/index */ function (exports, require) {
var parse_1 = require(3);
exports.parse = parse_1.parse;
var streams_1 = require(5);
exports.BrowserReadableStream = streams_1.BrowserReadableStream;
exports.StringStream = streams_1.StringStream;
exports.XhrStream = streams_1.XhrStream;
var stream_parsers_1 = require(4);
exports.StreamParser = stream_parsers_1.StreamParser;
exports.SrtStreamParser = stream_parsers_1.SrtStreamParser;
}, /* 2 ./parser/misc */ function (exports, require) {
var map_1 = require(30);
/**
* Parses a line into a {@link ./types/misc.Property}.
*
* @param {string} line
* @return {!Property}
*/
function parseLineIntoProperty(line) {
var colonPos = line.indexOf(":");
if (colonPos === -1) {
return null;
}
var name = line.substr(0, colonPos);
var value = line.substr(colonPos + 1).replace(/^\s+/, "");
return {
name: name,
value: value
};
}
exports.parseLineIntoProperty = parseLineIntoProperty;
/**
* Parses a line into a {@link ./types/misc.TypedTemplate} according to the given format specifier.
*
* @param {string} line
* @param {!Array.<string>} formatSpecifier
* @return {!TypedTemplate}
*/
function parseLineIntoTypedTemplate(line, formatSpecifier) {
var property = parseLineIntoProperty(line);
if (property === null) {
return null;
}
var value = property.value.split(",");
if (value.length > formatSpecifier.length) {
value[formatSpecifier.length - 1] = value.slice(formatSpecifier.length - 1).join(",");
}
var template = new map_1.Map();
formatSpecifier.forEach(function (formatKey, index) {
template.set(formatKey, value[index]);
});
return {
type: property.name,
template: template
};
}
exports.parseLineIntoTypedTemplate = parseLineIntoTypedTemplate;
}, /* 3 ./parser/parse */ function (exports, require) {
var parts = require(8);
var settings_1 = require(23);
var map_1 = require(30);
var rules = new map_1.Map();
/**
* Parses a given string with the specified rule.
*
* @param {string} input The string to be parsed.
* @param {string} rule The rule to parse the string with
* @return {*} The value returned depends on the rule used.
*
* @memberOf libjass.parser
*/
function parse(input, rule) {
var run = new ParserRun(input, rule);
if (run.result === null || run.result.end !== input.length) {
if (settings_1.debugMode) {
console.error("Parse failed. %s %s %o", rule, input, run.result);
}
throw new Error("Parse failed.");
}
return run.result.value;
}
exports.parse = parse;
/**
* This class represents a single run of the parser.
*
* @param {string} input
* @param {string} rule
*
* @constructor
* @private
*/
var ParserRun = function () {
function ParserRun(input, rule) {
this._input = input;
this._parseTree = new ParseNode(null);
this._result = rules.get(rule).call(this, this._parseTree);
}
Object.defineProperty(ParserRun.prototype, "result", {
/**
* @type {ParseNode}
*/
get: function () {
return this._result;
},
enumerable: true,
configurable: true
});
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_dialogueParts = function (parent) {
var _a;
var current = new ParseNode(parent);
current.value = [];
while (this._haveMore()) {
var enclosedTagsNode = this.parse_enclosedTags(current);
if (enclosedTagsNode !== null) {
(_a = current.value).push.apply(_a, enclosedTagsNode.value);
} else {
var whiteSpaceOrTextNode = this.parse_newline(current) || this.parse_hardspace(current) || this.parse_text(current);
if (whiteSpaceOrTextNode === null) {
parent.pop();
return null;
}
if (whiteSpaceOrTextNode.value instanceof parts.Text && current.value[current.value.length - 1] instanceof parts.Text) {
// Merge consecutive text parts into one part
var previousTextPart = current.value[current.value.length - 1];
current.value[current.value.length - 1] = new parts.Text(previousTextPart.value + whiteSpaceOrTextNode.value.value);
} else {
current.value.push(whiteSpaceOrTextNode.value);
}
}
}
var inDrawingMode = false;
current.value.forEach(function (part, i) {
if (part instanceof parts.DrawingMode) {
inDrawingMode = part.scale !== 0;
} else if (part instanceof parts.Text && inDrawingMode) {
current.value[i] = new parts.DrawingInstructions(parse(part.value, "drawingInstructions"));
}
});
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_enclosedTags = function (parent) {
var current = new ParseNode(parent);
current.value = [];
if (this.read(current, "{") === null) {
parent.pop();
return null;
}
for (var next = this._peek(); this._haveMore() && next !== "}"; next = this._peek()) {
var childNode = null;
if (this.read(current, "\\") !== null) {
childNode = this.parse_tag_alpha(current) || this.parse_tag_iclip(current) || this.parse_tag_xbord(current) || this.parse_tag_ybord(current) || this.parse_tag_xshad(current) || this.parse_tag_yshad(current) || this.parse_tag_blur(current) || this.parse_tag_bord(current) || this.parse_tag_clip(current) || this.parse_tag_fade(current) || this.parse_tag_fscx(current) || this.parse_tag_fscy(current) || this.parse_tag_move(current) || this.parse_tag_shad(current) || this.parse_tag_fad(current) || this.parse_tag_fax(current) || this.parse_tag_fay(current) || this.parse_tag_frx(current) || this.parse_tag_fry(current) || this.parse_tag_frz(current) || this.parse_tag_fsp(current) || this.parse_tag_fsplus(current) || this.parse_tag_fsminus(current) || this.parse_tag_org(current) || this.parse_tag_pbo(current) || this.parse_tag_pos(current) || this.parse_tag_an(current) || this.parse_tag_be(current) || this.parse_tag_fn(current) || this.parse_tag_fr(current) || this.parse_tag_fs(current) || this.parse_tag_kf(current) || this.parse_tag_ko(current) || this.parse_tag_1a(current) || this.parse_tag_1c(current) || this.parse_tag_2a(current) || this.parse_tag_2c(current) || this.parse_tag_3a(current) || this.parse_tag_3c(current) || this.parse_tag_4a(current) || this.parse_tag_4c(current) || this.parse_tag_a(current) || this.parse_tag_b(current) || this.parse_tag_c(current) || this.parse_tag_i(current) || this.parse_tag_k(current) || this.parse_tag_K(current) || this.parse_tag_p(current) || this.parse_tag_q(current) || this.parse_tag_r(current) || this.parse_tag_s(current) || this.parse_tag_t(current) || this.parse_tag_u(current);
if (childNode === null) {
current.pop();
}
}
if (childNode === null) {
childNode = this.parse_comment(current);
}
if (childNode !== null) {
if (childNode.value instanceof parts.Comment && current.value[current.value.length - 1] instanceof parts.Comment) {
// Merge consecutive comment parts into one part
current.value[current.value.length - 1] = new parts.Comment(current.value[current.value.length - 1].value + childNode.value.value);
} else {
current.value.push(childNode.value);
}
} else {
parent.pop();
return null;
}
}
if (this.read(current, "}") === null) {
parent.pop();
return null;
}
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_newline = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "\\N") === null) {
parent.pop();
return null;
}
current.value = new parts.NewLine();
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_hardspace = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "\\h") === null) {
parent.pop();
return null;
}
current.value = new parts.Text(" ");
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_text = function (parent) {
var value = this._peek();
var current = new ParseNode(parent);
var valueNode = new ParseNode(current, value);
current.value = new parts.Text(valueNode.value);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_comment = function (parent) {
var value = this._peek();
var current = new ParseNode(parent);
var valueNode = new ParseNode(current, value);
current.value = new parts.Comment(valueNode.value);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_a = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "a") === null) {
parent.pop();
return null;
}
var next = this._peek();
switch (next) {
case "1":
var next2 = this._peek(2);
switch (next2) {
case "10":
case "11":
next = next2;
break;
}
break;
case "2":
case "3":
case "5":
case "6":
case "7":
case "9":
break;
default:
parent.pop();
return null;
}
var valueNode = new ParseNode(current, next);
var value = null;
switch (valueNode.value) {
case "1":
value = 1;
break;
case "2":
value = 2;
break;
case "3":
value = 3;
break;
case "5":
value = 7;
break;
case "6":
value = 8;
break;
case "7":
value = 9;
break;
case "9":
value = 4;
break;
case "10":
value = 5;
break;
case "11":
value = 6;
break;
}
current.value = new parts.Alignment(value);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_alpha = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_an = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "an") === null) {
parent.pop();
return null;
}
var next = this._peek();
if (next < "1" || next > "9") {
parent.pop();
return null;
}
var valueNode = new ParseNode(current, next);
current.value = new parts.Alignment(parseInt(valueNode.value));
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_b = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "b") === null) {
parent.pop();
return null;
}
var valueNode = null;
var next = this._peek();
if (next >= "1" && next <= "9") {
next = this._peek(3);
if (next.substr(1) === "00") {
valueNode = new ParseNode(current, next);
valueNode.value = parseInt(valueNode.value);
}
}
if (valueNode === null) {
valueNode = this.parse_enableDisable(current);
}
if (valueNode !== null) {
current.value = new parts.Bold(valueNode.value);
} else {
current.value = new parts.Bold(null);
}
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_be = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_blur = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_bord = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_c = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_clip = function (parent) {
return this._parse_tag_clip_or_iclip("clip", parent);
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_fad = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "fad") === null) {
parent.pop();
return null;
}
if (this.read(current, "(") === null) {
parent.pop();
return null;
}
var startNode = this.parse_decimal(current);
if (startNode === null) {
parent.pop();
return null;
}
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var endNode = this.parse_decimal(current);
if (endNode === null) {
parent.pop();
return null;
}
if (this.read(current, ")") === null) {
parent.pop();
return null;
}
current.value = new parts.Fade(startNode.value / 1e3, endNode.value / 1e3);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_fade = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "fade") === null) {
parent.pop();
return null;
}
if (this.read(current, "(") === null) {
parent.pop();
return null;
}
var a1Node = this.parse_decimal(current);
if (a1Node === null) {
parent.pop();
return null;
}
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var a2Node = this.parse_decimal(current);
if (a2Node === null) {
parent.pop();
return null;
}
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var a3Node = this.parse_decimal(current);
if (a3Node === null) {
parent.pop();
return null;
}
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var t1Node = this.parse_decimal(current);
if (t1Node === null) {
parent.pop();
return null;
}
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var t2Node = this.parse_decimal(current);
if (t2Node === null) {
parent.pop();
return null;
}
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var t3Node = this.parse_decimal(current);
if (t3Node === null) {
parent.pop();
return null;
}
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var t4Node = this.parse_decimal(current);
if (t4Node === null) {
parent.pop();
return null;
}
if (this.read(current, ")") === null) {
parent.pop();
return null;
}
current.value = new parts.ComplexFade(1 - a1Node.value / 255, 1 - a2Node.value / 255, 1 - a3Node.value / 255, t1Node.value / 1e3, t2Node.value / 1e3, t3Node.value / 1e3, t4Node.value / 1e3);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_fax = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_fay = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_fn = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "fn") === null) {
parent.pop();
return null;
}
var valueNode = new ParseNode(current, "");
for (var next = this._peek(); this._haveMore() && next !== "\\" && next !== "}"; next = this._peek()) {
valueNode.value += next;
}
if (valueNode.value.length > 0) {
current.value = new parts.FontName(valueNode.value);
} else {
current.value = new parts.FontName(null);
}
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_fr = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_frx = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_fry = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_frz = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_fs = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_fsplus = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "fs+") === null) {
parent.pop();
return null;
}
var valueNode = this.parse_decimal(current);
if (valueNode === null) {
parent.pop();
return null;
}
current.value = new parts.FontSizePlus(valueNode.value);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_fsminus = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "fs-") === null) {
parent.pop();
return null;
}
var valueNode = this.parse_decimal(current);
if (valueNode === null) {
parent.pop();
return null;
}
current.value = new parts.FontSizeMinus(valueNode.value);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_fscx = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "fscx") === null) {
parent.pop();
return null;
}
var valueNode = this.parse_decimal(current);
if (valueNode !== null) {
current.value = new parts.FontScaleX(valueNode.value / 100);
} else {
current.value = new parts.FontScaleX(null);
}
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_fscy = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "fscy") === null) {
parent.pop();
return null;
}
var valueNode = this.parse_decimal(current);
if (valueNode !== null) {
current.value = new parts.FontScaleY(valueNode.value / 100);
} else {
current.value = new parts.FontScaleY(null);
}
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_fsp = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_i = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_iclip = function (parent) {
return this._parse_tag_clip_or_iclip("iclip", parent);
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_k = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "k") === null) {
parent.pop();
return null;
}
var valueNode = this.parse_decimal(current);
if (valueNode === null) {
parent.pop();
return null;
}
current.value = new parts.ColorKaraoke(valueNode.value / 100);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_K = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "K") === null) {
parent.pop();
return null;
}
var valueNode = this.parse_decimal(current);
if (valueNode === null) {
parent.pop();
return null;
}
current.value = new parts.SweepingColorKaraoke(valueNode.value / 100);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_kf = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "kf") === null) {
parent.pop();
return null;
}
var valueNode = this.parse_decimal(current);
if (valueNode === null) {
parent.pop();
return null;
}
current.value = new parts.SweepingColorKaraoke(valueNode.value / 100);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_ko = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "ko") === null) {
parent.pop();
return null;
}
var valueNode = this.parse_decimal(current);
if (valueNode === null) {
parent.pop();
return null;
}
current.value = new parts.OutlineKaraoke(valueNode.value / 100);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_move = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "move") === null) {
parent.pop();
return null;
}
if (this.read(current, "(") === null) {
parent.pop();
return null;
}
var x1Node = this.parse_decimal(current);
if (x1Node === null) {
parent.pop();
return null;
}
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var y1Node = this.parse_decimal(current);
if (y1Node === null) {
parent.pop();
return null;
}
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var x2Node = this.parse_decimal(current);
if (x2Node === null) {
parent.pop();
return null;
}
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var y2Node = this.parse_decimal(current);
if (y2Node === null) {
parent.pop();
return null;
}
var t1Node = null;
var t2Node = null;
if (this.read(current, ",") !== null) {
t1Node = this.parse_decimal(current);
if (t1Node === null) {
parent.pop();
return null;
}
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
t2Node = this.parse_decimal(current);
if (t2Node === null) {
parent.pop();
return null;
}
}
if (this.read(current, ")") === null) {
parent.pop();
return null;
}
current.value = new parts.Move(x1Node.value, y1Node.value, x2Node.value, y2Node.value, t1Node !== null ? t1Node.value / 1e3 : null, t2Node !== null ? t2Node.value / 1e3 : null);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_org = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "org") === null) {
parent.pop();
return null;
}
if (this.read(current, "(") === null) {
parent.pop();
return null;
}
var xNode = this.parse_decimal(current);
if (xNode === null) {
parent.pop();
return null;
}
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var yNode = this.parse_decimal(current);
if (yNode === null) {
parent.pop();
return null;
}
if (this.read(current, ")") === null) {
parent.pop();
return null;
}
current.value = new parts.RotationOrigin(xNode.value, yNode.value);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_p = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_pbo = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_pos = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "pos") === null) {
parent.pop();
return null;
}
if (this.read(current, "(") === null) {
parent.pop();
return null;
}
var xNode = this.parse_decimal(current);
if (xNode === null) {
parent.pop();
return null;
}
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var yNode = this.parse_decimal(current);
if (yNode === null) {
parent.pop();
return null;
}
if (this.read(current, ")") === null) {
parent.pop();
return null;
}
current.value = new parts.Position(xNode.value, yNode.value);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_q = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "q") === null) {
parent.pop();
return null;
}
var next = this._peek();
if (next < "0" || next > "3") {
parent.pop();
return null;
}
var valueNode = new ParseNode(current, next);
current.value = new parts.WrappingStyle(parseInt(valueNode.value));
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_r = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "r") === null) {
parent.pop();
return null;
}
var valueNode = new ParseNode(current, "");
for (var next = this._peek(); this._haveMore() && next !== "\\" && next !== "}"; next = this._peek()) {
valueNode.value += next;
}
if (valueNode.value.length > 0) {
current.value = new parts.Reset(valueNode.value);
} else {
current.value = new parts.Reset(null);
}
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_s = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_shad = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_t = function (parent) {
var current = new ParseNode(parent);
if (this.read(current, "t") === null) {
parent.pop();
return null;
}
if (this.read(current, "(") === null) {
parent.pop();
return null;
}
var startNode = null;
var endNode = null;
var accelNode = null;
var firstNode = this.parse_decimal(current);
if (firstNode !== null) {
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var secondNode = this.parse_decimal(current);
if (secondNode !== null) {
startNode = firstNode;
endNode = secondNode;
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var thirdNode = this.parse_decimal(current);
if (thirdNode !== null) {
accelNode = thirdNode;
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
}
} else {
accelNode = firstNode;
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
}
}
var transformTags = [];
for (var next = this._peek(); this._haveMore() && next !== ")" && next !== "}"; next = this._peek()) {
var childNode = null;
if (this.read(current, "\\") !== null) {
childNode = this.parse_tag_alpha(current) || this.parse_tag_iclip(current) || this.parse_tag_xbord(current) || this.parse_tag_ybord(current) || this.parse_tag_xshad(current) || this.parse_tag_yshad(current) || this.parse_tag_blur(current) || this.parse_tag_bord(current) || this.parse_tag_clip(current) || this.parse_tag_fscx(current) || this.parse_tag_fscy(current) || this.parse_tag_shad(current) || this.parse_tag_fax(current) || this.parse_tag_fay(current) || this.parse_tag_frx(current) || this.parse_tag_fry(current) || this.parse_tag_frz(current) || this.parse_tag_fsp(current) || this.parse_tag_fsplus(current) || this.parse_tag_fsminus(current) || this.parse_tag_be(current) || this.parse_tag_fr(current) || this.parse_tag_fs(current) || this.parse_tag_1a(current) || this.parse_tag_1c(current) || this.parse_tag_2a(current) || this.parse_tag_2c(current) || this.parse_tag_3a(current) || this.parse_tag_3c(current) || this.parse_tag_4a(current) || this.parse_tag_4c(current) || this.parse_tag_c(current);
if (childNode === null) {
current.pop();
}
}
if (childNode === null) {
childNode = this.parse_comment(current);
}
if (childNode !== null) {
if (childNode.value instanceof parts.Comment && transformTags[transformTags.length - 1] instanceof parts.Comment) {
// Merge consecutive comment parts into one part
transformTags[transformTags.length - 1] = new parts.Comment(transformTags[transformTags.length - 1].value + childNode.value.value);
} else {
transformTags.push(childNode.value);
}
} else {
parent.pop();
return null;
}
}
this.read(current, ")");
current.value = new parts.Transform(startNode !== null ? startNode.value / 1e3 : null, endNode !== null ? endNode.value / 1e3 : null, accelNode !== null ? accelNode.value / 1e3 : null, transformTags);
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_u = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_xbord = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_xshad = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_ybord = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_yshad = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_1a = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_1c = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_2a = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_2c = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_3a = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_3c = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_4a = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_tag_4c = function () {
throw new Error("Method not implemented.");
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_drawingInstructions = function (parent) {
var current = new ParseNode(parent);
var currentType = null;
var numberParts = [];
current.value = [];
while (this._haveMore()) {
while (this.read(current, " ") !== null) {}
if (!this._haveMore()) {
break;
}
if (currentType !== null) {
var numberPart = this.parse_decimal(current);
if (numberPart !== null) {
numberParts.push(numberPart);
if (currentType === "m" && numberParts.length === 2) {
current.value.push(new parts.drawing.MoveInstruction(numberParts[0].value, numberParts[1].value));
numberParts.splice(0, numberParts.length);
} else if (currentType === "l" && numberParts.length === 2) {
current.value.push(new parts.drawing.LineInstruction(numberParts[0].value, numberParts[1].value));
numberParts.splice(0, numberParts.length);
} else if (currentType === "b" && numberParts.length === 6) {
current.value.push(new parts.drawing.CubicBezierCurveInstruction(numberParts[0].value, numberParts[1].value, numberParts[2].value, numberParts[3].value, numberParts[4].value, numberParts[5].value));
numberParts.splice(0, numberParts.length);
}
continue;
}
}
var typePart = this.parse_text(current);
if (typePart === null) {
break;
}
var newType = typePart.value.value;
switch (newType) {
case "m":
case "l":
case "b":
currentType = newType;
numberParts.splice(0, numberParts.length);
break;
}
}
while (this.read(current, " ") !== null) {}
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_decimalInt32 = function (parent) {
var current = new ParseNode(parent);
var isNegative = this.read(current, "-") !== null;
var numberNode = new ParseNode(current, "");
for (var next = this._peek(); this._haveMore() && next >= "0" && next <= "9"; next = this._peek()) {
numberNode.value += next;
}
if (numberNode.value.length === 0) {
parent.pop();
return null;
}
var value = parseInt(numberNode.value);
if (value >= 4294967295) {
value = 4294967295;
} else if (isNegative) {
value = -value;
}
current.value = value;
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_hexInt32 = function (parent) {
var current = new ParseNode(parent);
var isNegative = this.read(current, "-") !== null;
var numberNode = new ParseNode(current, "");
for (var next = this._peek(); this._haveMore() && (next >= "0" && next <= "9" || next >= "a" && next <= "f" || next >= "A" && next <= "F"); next = this._peek()) {
numberNode.value += next;
}
if (numberNode.value.length === 0) {
parent.pop();
return null;
}
var value = parseInt(numberNode.value, 16);
if (value >= 4294967295) {
value = 4294967295;
} else if (isNegative) {
value = -value;
}
current.value = value;
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_decimalOrHexInt32 = function (parent) {
var current = new ParseNode(parent);
var valueNode = this.read(current, "&H") !== null || this.read(current, "&h") !== null ? this.parse_hexInt32(current) : this.parse_decimalInt32(current);
if (valueNode === null) {
parent.pop();
return null;
}
current.value = valueNode.value;
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_decimal = function (parent) {
var current = new ParseNode(parent);
var negative = this.read(current, "-") !== null;
var numericalPart = this.parse_unsignedDecimal(current);
if (numericalPart === null) {
parent.pop();
return null;
}
current.value = numericalPart.value;
if (negative) {
current.value = -current.value;
}
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_unsignedDecimal = function (parent) {
var current = new ParseNode(parent);
var characteristicNode = new ParseNode(current, "");
var mantissaNode = null;
for (var next = this._peek(); this._haveMore() && next >= "0" && next <= "9"; next = this._peek()) {
characteristicNode.value += next;
}
if (characteristicNode.value.length === 0) {
parent.pop();
return null;
}
if (this.read(current, ".") !== null) {
mantissaNode = new ParseNode(current, "");
for (var next = this._peek(); this._haveMore() && next >= "0" && next <= "9"; next = this._peek()) {
mantissaNode.value += next;
}
if (mantissaNode.value.length === 0) {
parent.pop();
return null;
}
}
current.value = parseFloat(characteristicNode.value + (mantissaNode !== null ? "." + mantissaNode.value : ""));
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_enableDisable = function (parent) {
var next = this._peek();
if (next === "0" || next === "1") {
var result = new ParseNode(parent, next);
result.value = result.value === "1";
return result;
}
return null;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_color = function (parent) {
var current = new ParseNode(parent);
while (this.read(current, "&") !== null || this.read(current, "H") !== null) {}
var valueNode = this.parse_hexInt32(current);
if (valueNode === null) {
parent.pop();
return null;
}
var value = valueNode.value;
current.value = new parts.Color(value & 255, value >> 8 & 255, value >> 16 & 255);
while (this.read(current, "&") !== null || this.read(current, "H") !== null) {}
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_alpha = function (parent) {
var current = new ParseNode(parent);
while (this.read(current, "&") !== null || this.read(current, "H") !== null) {}
var valueNode = this.parse_hexInt32(current);
if (valueNode === null) {
parent.pop();
return null;
}
var value = valueNode.value;
current.value = 1 - (value & 255) / 255;
while (this.read(current, "&") !== null || this.read(current, "H") !== null) {}
return current;
};
/**
* @param {!ParseNode} parent
* @return {ParseNode}
*/
ParserRun.prototype.parse_colorWithAlpha = function (parent) {
var current = new ParseNode(parent);
var valueNode = this.parse_decimalOrHexInt32(current);
if (valueNode === null) {
parent.pop();
return null;
}
var value = valueNode.value;
current.value = new parts.Color(value & 255, value >> 8 & 255, value >> 16 & 255, 1 - (value >> 24 & 255) / 255);
return current;
};
/**
* @param {!ParseNode} parent
* @param {string} next
* @return {ParseNode}
*/
ParserRun.prototype.read = function (parent, next) {
if (this._peek(next.length) !== next) {
return null;
}
return new ParseNode(parent, next);
};
/**
* @param {number=1} count
* @return {string}
*
* @private
*/
ParserRun.prototype._peek = function (count) {
if (count === void 0) {
count = 1;
}
// Fastpath for count === 1. http://jsperf.com/substr-vs-indexer
if (count === 1) {
return this._input[this._parseTree.end];
}
return this._input.substr(this._parseTree.end, count);
};
/**
* @return {boolean}
*
* @private
*/
ParserRun.prototype._haveMore = function () {
return this._parseTree.end < this._input.length;
};
/**
* @param {string} tagName One of "clip" and "iclip"
* @param {!ParseNode} parent
* @return {ParseNode}
*
* @private
*/
ParserRun.prototype._parse_tag_clip_or_iclip = function (tagName, parent) {
var current = new ParseNode(parent);
if (this.read(current, tagName) === null) {
parent.pop();
return null;
}
if (this.read(current, "(") === null) {
parent.pop();
return null;
}
var x1Node = null;
var x2Node = null;
var y1Node = null;
var y2Node = null;
var scaleNode = null;
var commandsNode = null;
var firstNode = this.parse_decimal(current);
if (firstNode !== null) {
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
var secondNode = this.parse_decimal(current);
if (secondNode !== null) {
x1Node = firstNode;
y1Node = secondNode;
} else {
scaleNode = firstNode;
}
}
if (x1Node !== null && y1Node !== null) {
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
x2Node = this.parse_decimal(current);
if (this.read(current, ",") === null) {
parent.pop();
return null;
}
y2Node = this.parse_decimal(current);
current.value = new parts.RectangularClip(x1Node.value, y1Node.value, x2Node.value, y2Node.value, tagName === "clip");
} else {
commandsNode = new ParseNode(current, "");
for (var next = this._peek(); this._haveMore() && next !== ")" && next !== "}"; next = this._peek()) {
commandsNode.value += next;
}
current.value = new parts.VectorClip(scaleNode !== null ? scaleNode.value : 1, parse(commandsNode.value, "drawingInstructions"), tagName === "clip");
}
if (this.read(current, ")") === null) {
parent.pop();
return null;
}
return current;
};
return ParserRun;
}();
/**
* Constructs a simple tag parser function and sets it on the prototype of the {@link ./parser/parse.ParserRun} class.
*
* @param {string} tagName The name of the tag to generate the parser function for
* @param {function(new: !libjass.parts.Part, *)} tagConstructor The type of tag to be returned by the generated parser function
* @param {function(!ParseNode): ParseNode} valueParser The parser for the tag's value
* @param {boolean} required Whether the tag's value is required or optional
*
* @private
*/
function makeTagParserFunction(tagName, tagConstructor, valueParser, required) {
ParserRun.prototype["parse_tag_" + tagName] = function (parent) {
var self = this;
var current = new ParseNode(parent);
if (self.read(current, tagName) === null) {
parent.pop();
return null;
}
var valueNode = valueParser.call(self, current);
if (valueNode !== null) {
current.value = new tagConstructor(valueNode.value);
} else if (!required) {
current.value = new tagConstructor(null);
} else {
parent.pop();
return null;
}
return current;
};
}
makeTagParserFunction("alpha", parts.Alpha, ParserRun.prototype.parse_alpha, false);
makeTagParserFunction("be", parts.Blur, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("blur", parts.GaussianBlur, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("bord", parts.Border, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("c", parts.PrimaryColor, ParserRun.prototype.parse_color, false);
makeTagParserFunction("fax", parts.SkewX, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("fay", parts.SkewY, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("fr", parts.RotateZ, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("frx", parts.RotateX, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("fry", parts.RotateY, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("frz", parts.RotateZ, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("fs", parts.FontSize, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("fsp", parts.LetterSpacing, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("i", parts.Italic, ParserRun.prototype.parse_enableDisable, false);
makeTagParserFunction("p", parts.DrawingMode, ParserRun.prototype.parse_decimal, true);
makeTagParserFunction("pbo", parts.DrawingBaselineOffset, ParserRun.prototype.parse_decimal, true);
makeTagParserFunction("s", parts.StrikeThrough, ParserRun.prototype.parse_enableDisable, false);
makeTagParserFunction("shad", parts.Shadow, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("u", parts.Underline, ParserRun.prototype.parse_enableDisable, false);
makeTagParserFunction("xbord", parts.BorderX, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("xshad", parts.ShadowX, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("ybord", parts.BorderY, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("yshad", parts.ShadowY, ParserRun.prototype.parse_decimal, false);
makeTagParserFunction("1a", parts.PrimaryAlpha, ParserRun.prototype.parse_alpha, false);
makeTagParserFunction("1c", parts.PrimaryColor, ParserRun.prototype.parse_color, false);
makeTagParserFunction("2a", parts.SecondaryAlpha, ParserRun.prototype.parse_alpha, false);
makeTagParserFunction("2c", parts.SecondaryColor, ParserRun.prototype.parse_color, false);
makeTagParserFunction("3a", parts.OutlineAlpha, ParserRun.prototype.parse_alpha, false);
makeTagParserFunction("3c", parts.OutlineColor, ParserRun.prototype.parse_color, false);
makeTagParserFunction("4a", parts.ShadowAlpha, ParserRun.prototype.parse_alpha, false);
makeTagParserFunction("4c", parts.ShadowColor, ParserRun.prototype.parse_color, false);
for (var _i = 0, _a = Object.keys(ParserRun.prototype); _i < _a.length; _i++) {
var key = _a[_i];
if (key.indexOf("parse_") === 0 && typeof ParserRun.prototype[key] === "function") {
rules.set(key.substr("parse_".length), ParserRun.prototype[key]);
}
}
/**
* This class represents a single parse node. It has a start and end position, and an optional value object.
*
* @param {ParseNode} parent The parent of this parse node.
* @param {*=null} value If provided, it is assigned as the value of the node.
*
* @constructor
* @private
*/
var ParseNode = function () {
function ParseNode(parent, value) {
if (value === void 0) {
value = null;
}
this._parent = parent;
this._children = [];
if (parent !== null) {
parent.children.push(this);
}
this._start = parent !== null ? parent.end : 0;
this._end = this._start;
this.value = value;
}
Object.defineProperty(ParseNode.prototype, "start", {
/**
* The start position of this parse node.
*
* @type {number}
*/
get: function () {
return this._start;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ParseNode.prototype, "end", {
/**
* The end position of this parse node.
*
* @type {number}
*/
get: function () {
return this._end;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ParseNode.prototype, "parent", {
/**
* @type {ParseNode}
*/
get: function () {
return this._parent;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ParseNode.prototype, "children", {
/**
* @type {!Array.<!ParseNode>}
*/
get: function () {
return this._children;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ParseNode.prototype, "value", {
/**
* An optional object associated with this parse node.
*
* @type {*}
*/
get: function () {
return this._value;
},
/**
* An optional object associated with this parse node.
*
* If the value is a string, then the end property is updated to be the length of the string.
*
* @type {*}
*/
set: function (newValue) {
this._value = newValue;
if (this._value !== null && this._value.constructor === String && this._children.length === 0) {
this._setEnd(this._start + this._value.length);
}
},
enumerable: true,
configurable: true
});
/**
* Removes the last child of this node and updates the end position to be end position of the new last child.
*/
ParseNode.prototype.pop = function () {
this._children.splice(this._children.length - 1, 1);
if (this._children.length > 0) {
this._setEnd(this._children[this._children.length - 1].end);
} else {
this._setEnd(this.start);
}
};
/**
* Updates the end property of this node and its parent recursively to the root node.
*
* @param {number} newEnd
*
* @private
*/
ParseNode.prototype._setEnd = function (newEnd) {
this._end = newEnd;
if (this._parent !== null && this._parent.end !== this._end) {
this._parent._setEnd(this._end);
}
};
return ParseNode;
}();
var promise_1 = require(32);
var commands_1 = require(36);
var misc_1 = require(38);
misc_1.registerWorkerCommand(commands_1.WorkerCommands.Parse, function (parameters) {
return new promise_1.Promise(function (resolve) {
resolve(parse(parameters.input, parameters.rule));
});
});
}, /* 4 ./parser/stream-parsers */ function (exports, require) {
var settings_1 = require(23);
var ass_1 = require(24);
var style_1 = require(29);
var dialogue_1 = require(26);
var attachment_1 = require(25);
var map_1 = require(30);
var promise_1 = require(32);
var misc_1 = require(2);
var Section;
(function (Section) {
Section[Section["ScriptInfo"] = 0] = "ScriptInfo";
Section[Section["Styles"] = 1] = "Styles";
Section[Section["Events"] = 2] = "Events";
Section[Section["Fonts"] = 3] = "Fonts";
Section[Section["Graphics"] = 4] = "Graphics";
Section[Section["Other"] = 5] = "Other";
Section[Section["EOF"] = 6] = "EOF";
})(Section || (Section = {}));
/**
* A parser that parses an {@link libjass.ASS} object from a {@link libjass.parser.Stream}.
*
* @param {!libjass.parser.Stream} stream The {@link libjass.parser.Stream} to parse
*
* @constructor
* @memberOf libjass.parser
*/
var StreamParser = function () {
function StreamParser(stream) {
var _this = this;
this._stream = stream;
this._ass = new ass_1.ASS();
this._minimalDeferred = new promise_1.DeferredPromise();
this._deferred = new promise_1.DeferredPromise();
this._shouldSwallowBom = true;
this._currentSection = Section.ScriptInfo;
this._currentAttachment = null;
this._stream.nextLine().then(function (line) {
return _this._onNextLine(line);
}, function (reason) {
_this._minimalDeferred.reject(reason);
_this._deferred.reject(reason);
});
}
Object.defineProperty(StreamParser.prototype, "minimalASS", {
/**
* @type {!Promise.<!libjass.ASS>} A promise that will be resolved when the script properties of the ASS script have been parsed from the stream. Styles and events have not necessarily been
* parsed at the point this promise becomes resolved.
*/
get: function () {
return this._minimalDeferred.promise;
},
enumerable: true,
configurable: true
});
Object.defineProperty(StreamParser.prototype, "ass", {
/**
* @type {!Promise.<!libjass.ASS>} A promise that will be resolved when the entire stream has been parsed.
*/
get: function () {
return this._deferred.promise;
},
enumerable: true,
configurable: true
});
Object.defineProperty(StreamParser.prototype, "currentSection", {
/**
* @type {number}
*/
get: function () {
return this._currentSection;
},
/**
* @type {number}
*/
set: function (value) {
if (this._currentAttachment !== null) {
this._ass.addAttachment(this._currentAttachment);
this._currentAttachment = null;
}
if (this._currentSection === Section.ScriptInfo && value !== Section.ScriptInfo) {
// Exiting script info section
this._minimalDeferred.resolve(this._ass);
}
if (value === Section.EOF) {
var scriptProperties = this._ass.properties;
if (scriptProperties.resolutionX === undefined || scriptProperties.resolutionY === undefined) {
// Malformed script.
this._minimalDeferred.reject("Malformed ASS script.");
this._deferred.reject("Malformed ASS script.");
} else {
this._minimalDeferred.resolve(this._ass);
this._deferred.resolve(this._ass);
}
}
this._currentSection = value;
},
enumerable: true,
configurable: true
});
/**
* @param {string} line
*
* @private
*/
StreamParser.prototype._onNextLine = function (line) {
var _this = this;
if (line === null) {
this.currentSection = Section.EOF;
return;
}
if (line[line.length - 1] === "\r") {
line = line.substr(0, line.length - 1);
}
if (line.charCodeAt(0) === 65279 && this._shouldSwallowBom) {
line = line.substr(1);
}
this._shouldSwallowBom = false;
if (line === "") {} else if (line[0] === ";" && this._currentAttachment === null) {} else if (line === "[Script Info]") {
this.currentSection = Section.ScriptInfo;
} else if (line === "[V4+ Styles]" || line === "[V4 Styles]") {
this.currentSection = Section.Styles;
} else if (line === "[Events]") {
this.currentSection = Section.Events;
} else if (line === "[Fonts]") {
this.currentSection = Section.Fonts;
} else if (line === "[Graphics]") {
this.currentSection = Section.Graphics;
} else {
if (this._currentAttachment === null && line[0] === "[" && line[line.length - 1] === "]") {
/* This looks like the start of a new section. The section name is unrecognized if it is.
* Since there's no current attachment being parsed it's definitely the start of a new section.
* If an attachment is being parsed, this might be part of the attachment.
*/
this.currentSection = Section.Other;
}
switch (this.currentSection) {
case Section.ScriptInfo:
var property = misc_1.parseLineIntoProperty(line);
if (property !== null) {
switch (property.name) {
case "PlayResX":
this._ass.properties.resolutionX = parseInt(property.value);
break;
case "PlayResY":
this._ass.properties.resolutionY = parseInt(property.value);
break;
case "WrapStyle":
this._ass.properties.wrappingStyle = parseInt(property.value);
break;
case "ScaledBorderAndShadow":
this._ass.properties.scaleBorderAndShadow = property.value === "yes";
break;
}
}
break;
case Section.Styles:
if (this._ass.stylesFormatSpecifier === null) {
var property_1 = misc_1.parseLineIntoProperty(line);
if (property_1 !== null && property_1.name === "Format") {
this._ass.stylesFormatSpecifier = property_1.value.split(",").map(function (str) {
return str.trim();
});
} else {}
} else {
try {
this._ass.addStyle(line);
} catch (ex) {
if (settings_1.debugMode) {
console.error("Could not parse style from line " + line + " - " + (ex.stack || ex));
}
}
}
break;
case Section.Events:
if (this._ass.dialoguesFormatSpecifier === null) {
var property_2 = misc_1.parseLineIntoProperty(line);
if (property_2 !== null && property_2.name === "Format") {
this._ass.dialoguesFormatSpecifier = property_2.value.split(",").map(function (str) {
return str.trim();
});
} else {}
} else {
try {
this._ass.addEvent(line);
} catch (ex) {
if (settings_1.debugMode) {
console.error("Could not parse event from line " + line + " - " + (ex.stack || ex));
}
}
}
break;
case Section.Fonts:
case Section.Graphics:
var startOfNewAttachmentRegex = this.currentSection === Section.Fonts ? /^fontname:(.+)/ : /^filename:(.+)/;
var startOfNewAttachment = startOfNewAttachmentRegex.exec(line);
if (startOfNewAttachment !== null) {
// Start of new attachment
if (this._currentAttachment !== null) {
this._ass.addAttachment(this._currentAttachment);
this._currentAttachment = null;
}
this._currentAttachment = new attachment_1.Attachment(startOfNewAttachment[1].trim(), this.currentSection === Section.Fonts ? attachment_1.AttachmentType.Font : attachment_1.AttachmentType.Graphic);
} else if (this._currentAttachment !== null) {
try {
this._currentAttachment.contents += uuencodedToBase64(line);
} catch (ex) {
if (settings_1.debugMode) {
console.error("Encountered error while reading font " + this._currentAttachment.filename + ": %o", ex);
}
this._currentAttachment = null;
}
} else {}
break;
case Section.Other:
// Ignore other sections.
break;
default:
throw new Error("Unhandled state " + this.currentSection);
}
}
this._stream.nextLine().then(function (line) {
return _this._onNextLine(line);
}, function (reason) {
_this._minimalDeferred.reject(reason);
_this._deferred.reject(reason);
});
};
return StreamParser;
}();
exports.StreamParser = StreamParser;
/**
* A parser that parses an {@link libjass.ASS} object from a {@link libjass.parser.Stream} of an SRT script.
*
* @param {!libjass.parser.Stream} stream The {@link libjass.parser.Stream} to parse
*
* @constructor
* @memberOf libjass.parser
*/
var SrtStreamParser = function () {
function SrtStreamParser(stream) {
var _this = this;
this._stream = stream;
this._ass = new ass_1.ASS();
this._deferred = new promise_1.DeferredPromise();
this._shouldSwallowBom = true;
this._currentDialogueNumber = null;
this._currentDialogueStart = null;
this._currentDialogueEnd = null;
this._currentDialogueText = null;
this._stream.nextLine().then(function (line) {
return _this._onNextLine(line);
}, function (reason) {
_this._deferred.reject(reason);
});
this._ass.properties.resolutionX = 1280;
this._ass.properties.resolutionY = 720;
this._ass.properties.wrappingStyle = 1;
this._ass.properties.scaleBorderAndShadow = true;
var newStyle = new style_1.Style(new map_1.Map([ [ "Name", "Default" ], [ "FontSize", "36" ] ]));
this._ass.styles.set(newStyle.name, newStyle);
}
Object.defineProperty(SrtStreamParser.prototype, "ass", {
/**
* @type {!Promise.<!libjass.ASS>} A promise that will be resolved when the entire stream has been parsed.
*/
get: function () {
return this._deferred.promise;
},
enumerable: true,
configurable: true
});
/**
* @param {string} line
*
* @private
*/
SrtStreamParser.prototype._onNextLine = function (line) {
var _this = this;
if (line === null) {
if (this._currentDialogueNumber !== null && this._currentDialogueStart !== null && this._currentDialogueEnd !== null && this._currentDialogueText !== null) {
this._ass.dialogues.push(new dialogue_1.Dialogue(new map_1.Map([ [ "Style", "Default" ], [ "Start", this._currentDialogueStart ], [ "End", this._currentDialogueEnd ], [ "Text", this._currentDialogueText ] ]), this._ass));
}
this._deferred.resolve(this._ass);
return;
}
if (line[line.length - 1] === "\r") {
line = line.substr(0, line.length - 1);
}
if (line.charCodeAt(0) === 65279 && this._shouldSwallowBom) {
line = line.substr(1);
}
this._shouldSwallowBom = false;
if (line === "") {
if (this._currentDialogueNumber !== null && this._currentDialogueStart !== null && this._currentDialogueEnd !== null && this._currentDialogueText !== null) {
this._ass.dialogues.push(new dialogue_1.Dialogue(new map_1.Map([ [ "Style", "Default" ], [ "Start", this._currentDialogueStart ], [ "End", this._currentDialogueEnd ], [ "Text", this._currentDialogueText ] ]), this._ass));
}
this._currentDialogueNumber = this._currentDialogueStart = this._currentDialogueEnd = this._currentDialogueText = null;
} else {
if (this._currentDialogueNumber === null) {
if (/^\d+$/.test(line)) {
this._currentDialogueNumber = line;
}
} else if (this._currentDialogueStart === null && this._currentDialogueEnd === null) {
var match = /^(\d\d:\d\d:\d\d,\d\d\d) --> (\d\d:\d\d:\d\d,\d\d\d)/.exec(line);
if (match !== null) {
this._currentDialogueStart = match[1].replace(",", ".");
this._currentDialogueEnd = match[2].replace(",", ".");
}
} else {
line = line.replace(/<b>/g, "{\\b1}").replace(/\{b\}/g, "{\\b1}").replace(/<\/b>/g, "{\\b0}").replace(/\{\/b\}/g, "{\\b0}").replace(/<i>/g, "{\\i1}").replace(/\{i\}/g, "{\\i1}").replace(/<\/i>/g, "{\\i0}").replace(/\{\/i\}/g, "{\\i0}").replace(/<u>/g, "{\\u1}").replace(/\{u\}/g, "{\\u1}").replace(/<\/u>/g, "{\\u0}").replace(/\{\/u\}/g, "{\\u0}").replace(/<font color="#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})">/g, function (/* ujs:unreferenced */ substring, red, green, blue) {
return "{c&H" + blue + green + red + "&}";
}).replace(/<\/font>/g, "{\\c}");
if (this._currentDialogueText !== null) {
this._currentDialogueText += "\\N" + line;
} else {
this._currentDialogueText = line;
}
}
}
this._stream.nextLine().then(function (line) {
return _this._onNextLine(line);
}, function (reason) {
_this._deferred.reject(reason);
});
};
return SrtStreamParser;
}();
exports.SrtStreamParser = SrtStreamParser;
/**
* Converts a uuencoded string to a base64 string.
*
* @param {string} str
* @return {string}
*
* @private
*/
function uuencodedToBase64(str) {
var result = "";
for (var i = 0; i < str.length; i++) {
var charCode = str.charCodeAt(i) - 33;
if (charCode < 0 || charCode > 63) {
throw new Error("Out-of-range character code " + charCode + " at index " + i + " in string " + str);
}
if (charCode < 26) {
result += String.fromCharCode("A".charCodeAt(0) + charCode);
} else if (charCode < 52) {
result += String.fromCharCode("a".charCodeAt(0) + charCode - 26);
} else if (charCode < 62) {
result += String.fromCharCode("0".charCodeAt(0) + charCode - 52);
} else if (charCode === 62) {
result += "+";
} else {
result += "/";
}
}
return result;
}
}, /* 5 ./parser/streams */ function (exports, require) {
var promise_1 = require(32);
/**
* A {@link libjass.parser.Stream} that reads from a string in memory.
*
* @param {string} str The string
*
* @constructor
* @implements {libjass.parser.Stream}
* @memberOf libjass.parser
*/
var StringStream = function () {
function StringStream(str) {
this._str = str;
this._readTill = 0;
}
/**
* @return {!Promise.<?string>} A promise that will be resolved with the next line, or null if the string has been completely read.
*/
StringStream.prototype.nextLine = function () {
var result = null;
if (this._readTill < this._str.length) {
var nextNewLinePos = this._str.indexOf("\n", this._readTill);
if (nextNewLinePos !== -1) {
result = promise_1.Promise.resolve(this._str.substring(this._readTill, nextNewLinePos));
this._readTill = nextNewLinePos + 1;
} else {
result = promise_1.Promise.resolve(this._str.substr(this._readTill));
this._readTill = this._str.length;
}
} else {
result = promise_1.Promise.resolve(null);
}
return result;
};
return StringStream;
}();
exports.StringStream = StringStream;
/**
* A {@link libjass.parser.Stream} that reads from an XMLHttpRequest object.
*
* @param {!XMLHttpRequest} xhr The XMLHttpRequest object. Make sure to not call .open() on this object before passing it in here,
* since event handlers cannot be registered after open() has been called.
*
* @constructor
* @implements {libjass.parser.Stream}
* @memberOf libjass.parser
*/
var XhrStream = function () {
function XhrStream(xhr) {
var _this = this;
this._xhr = xhr;
this._readTill = 0;
this._pendingDeferred = null;
this._failedError = null;
xhr.addEventListener("progress", function () {
return _this._onXhrProgress();
}, false);
xhr.addEventListener("load", function () {
return _this._onXhrLoad();
}, false);
xhr.addEventListener("error", function (event) {
return _this._onXhrError(event);
}, false);
}
/**
* @return {!Promise.<?string>} A promise that will be resolved with the next line, or null if the stream is exhausted.
*/
XhrStream.prototype.nextLine = function () {
if (this._pendingDeferred !== null) {
throw new Error("XhrStream only supports one pending unfulfilled read at a time.");
}
var deferred = this._pendingDeferred = new promise_1.DeferredPromise();
this._tryResolveNextLine();
return deferred.promise;
};
/**
* @private
*/
XhrStream.prototype._onXhrProgress = function () {
if (this._pendingDeferred === null) {
return;
}
if (this._xhr.readyState === XMLHttpRequest.DONE) {
/* Suppress resolving next line here. Let the "load" or "error" event handlers do it.
*
* This is required because a failed XHR fires the progress event with readyState === DONE before it fires the error event.
* This would confuse _tryResolveNextLine() into thinking the request succeeded with no data if it was called here.
*/
return;
}
this._tryResolveNextLine();
};
/**
* @private
*/
XhrStream.prototype._onXhrLoad = function () {
if (this._pendingDeferred === null) {
return;
}
this._tryResolveNextLine();
};
/**
* @param {!ErrorEvent} event
*
* @private
*/
XhrStream.prototype._onXhrError = function (event) {
this._failedError = event;
if (this._pendingDeferred === null) {
return;
}
this._tryResolveNextLine();
};
/**
* @private
*/
XhrStream.prototype._tryResolveNextLine = function () {
if (this._failedError !== null) {
this._pendingDeferred.reject(this._failedError);
return;
}
var response = this._xhr.responseText;
var nextNewLinePos = response.indexOf("\n", this._readTill);
if (nextNewLinePos !== -1) {
this._pendingDeferred.resolve(response.substring(this._readTill, nextNewLinePos));
this._readTill = nextNewLinePos + 1;
this._pendingDeferred = null;
} else if (this._xhr.readyState === XMLHttpRequest.DONE) {
if (this._failedError !== null) {
this._pendingDeferred.reject(this._failedError);
} else if (this._readTill < response.length) {
this._pendingDeferred.resolve(response.substr(this._readTill));
this._readTill = response.length;
} else {
this._pendingDeferred.resolve(null);
}
this._pendingDeferred = null;
}
};
return XhrStream;
}();
exports.XhrStream = XhrStream;
/**
* A {@link libjass.parser.Stream} that reads from a ReadableStream object.
*
* @param {!ReadableStream} stream
* @param {string} encoding
*
* @constructor
* @implements {libjass.parser.Stream}
* @memberOf libjass.parser
*/
var BrowserReadableStream = function () {
function BrowserReadableStream(stream, encoding) {
this._buffer = "";
this._pendingDeferred = null;
this._reader = stream.getReader();
this._decoder = new global.TextDecoder(encoding, {
ignoreBOM: true
});
}
/**
* @return {!Promise.<?string>} A promise that will be resolved with the next line, or null if the stream is exhausted.
*/
BrowserReadableStream.prototype.nextLine = function () {
if (this._pendingDeferred !== null) {
throw new Error("BrowserReadableStream only supports one pending unfulfilled read at a time.");
}
var deferred = this._pendingDeferred = new promise_1.DeferredPromise();
this._tryResolveNextLine();
return deferred.promise;
};
/**
* @private
*/
BrowserReadableStream.prototype._tryResolveNextLine = function () {
var _this = this;
var nextNewLinePos = this._buffer.indexOf("\n");
if (nextNewLinePos !== -1) {
this._pendingDeferred.resolve(this._buffer.substr(0, nextNewLinePos));
this._buffer = this._buffer.substr(nextNewLinePos + 1);
this._pendingDeferred = null;
} else {
this._reader.read().then(function (next) {
var value = next.value;
var done = next.done;
if (!done) {
_this._buffer += _this._decoder.decode(value, {
stream: true
});
_this._tryResolveNextLine();
} else {
// No more data.
if (_this._buffer.length === 0) {
_this._pendingDeferred.resolve(null);
} else {
_this._pendingDeferred.resolve(_this._buffer);
_this._buffer = "";
}
_this._pendingDeferred = null;
}
});
}
};
return BrowserReadableStream;
}();
exports.BrowserReadableStream = BrowserReadableStream;
}, /* 6 ./parser/ttf */ function (exports, require) {
var __decorate = require(34).__decorate;
var map_1 = require(30);
var set_1 = require(33);
var DataType;
(function (DataType) {
DataType[DataType["Char"] = 0] = "Char";
DataType[DataType["Uint16"] = 1] = "Uint16";
DataType[DataType["Uint32"] = 2] = "Uint32";
})(DataType || (DataType = {}));
var fieldDecorators = new map_1.Map();
var OffsetTable = function () {
function OffsetTable() {}
__decorate([ field(DataType.Uint16) ], OffsetTable.prototype, "majorVersion", void 0);
__decorate([ field(DataType.Uint16) ], OffsetTable.prototype, "minorVersion", void 0);
__decorate([ field(DataType.Uint16) ], OffsetTable.prototype, "numTables", void 0);
__decorate([ field(DataType.Uint16) ], OffsetTable.prototype, "searchRange", void 0);
__decorate([ field(DataType.Uint16) ], OffsetTable.prototype, "entrySelector", void 0);
__decorate([ field(DataType.Uint16) ], OffsetTable.prototype, "rangeShift", void 0);
OffsetTable = __decorate([ struct ], OffsetTable);
return OffsetTable;
}();
var TableRecord = function () {
function TableRecord() {}
__decorate([ field(DataType.Char) ], TableRecord.prototype, "c1", void 0);
__decorate([ field(DataType.Char) ], TableRecord.prototype, "c2", void 0);
__decorate([ field(DataType.Char) ], TableRecord.prototype, "c3", void 0);
__decorate([ field(DataType.Char) ], TableRecord.prototype, "c4", void 0);
__decorate([ field(DataType.Uint32) ], TableRecord.prototype, "checksum", void 0);
__decorate([ field(DataType.Uint32) ], TableRecord.prototype, "offset", void 0);
__decorate([ field(DataType.Uint32) ], TableRecord.prototype, "length", void 0);
TableRecord = __decorate([ struct ], TableRecord);
return TableRecord;
}();
var NameTableHeader = function () {
function NameTableHeader() {}
__decorate([ field(DataType.Uint16) ], NameTableHeader.prototype, "formatSelector", void 0);
__decorate([ field(DataType.Uint16) ], NameTableHeader.prototype, "count", void 0);
__decorate([ field(DataType.Uint16) ], NameTableHeader.prototype, "stringOffset", void 0);
NameTableHeader = __decorate([ struct ], NameTableHeader);
return NameTableHeader;
}();
var NameRecord = function () {
function NameRecord() {}
__decorate([ field(DataType.Uint16) ], NameRecord.prototype, "platformId", void 0);
__decorate([ field(DataType.Uint16) ], NameRecord.prototype, "encodingId", void 0);
__decorate([ field(DataType.Uint16) ], NameRecord.prototype, "languageId", void 0);
__decorate([ field(DataType.Uint16) ], NameRecord.prototype, "nameId", void 0);
__decorate([ field(DataType.Uint16) ], NameRecord.prototype, "length", void 0);
__decorate([ field(DataType.Uint16) ], NameRecord.prototype, "offset", void 0);
NameRecord = __decorate([ struct ], NameRecord);
return NameRecord;
}();
/**
* Gets all the font names from the given font attachment.
*
* @param {!libjass.Attachment} attachment
* @return {!libjass.Set.<string>}
*/
function getTtfNames(attachment) {
var decoded = atob(attachment.contents);
var bytes = new Uint8Array(new ArrayBuffer(decoded.length));
for (var i = 0; i < decoded.length; i++) {
bytes[i] = decoded.charCodeAt(i);
}
var reader = {
dataView: new DataView(bytes.buffer),
position: 0
};
var offsetTable = OffsetTable.read(reader);
var nameTableRecord = null;
for (var i = 0; i < offsetTable.numTables; i++) {
var tableRecord = TableRecord.read(reader);
if (tableRecord.c1 + tableRecord.c2 + tableRecord.c3 + tableRecord.c4 === "name") {
nameTableRecord = tableRecord;
break;
}
}
reader.position = nameTableRecord.offset;
var nameTableHeader = NameTableHeader.read(reader);
var result = new set_1.Set();
for (var i = 0; i < nameTableHeader.count; i++) {
var nameRecord = NameRecord.read(reader);
switch (nameRecord.nameId) {
case 1:
case 4:
case 6:
var recordOffset = nameTableRecord.offset + nameTableHeader.stringOffset + nameRecord.offset;
var nameBytes = bytes.subarray(recordOffset, recordOffset + nameRecord.length);
switch (nameRecord.platformId) {
case 1:
{
var name_1 = "";
for (var j = 0; j < nameBytes.length; j++) {
name_1 += String.fromCharCode(nameBytes[j]);
}
result.add(name_1);
}
break;
case 3:
{
var name_2 = "";
for (var j = 0; j < nameBytes.length; j += 2) {
name_2 += String.fromCharCode((nameBytes[j] << 8) + nameBytes[j + 1]);
}
result.add(name_2);
}
break;
}
break;
default:
break;
}
}
return result;
}
exports.getTtfNames = getTtfNames;
/**
* @param {!function(new(): T)} clazz
* @return {!function(new(): T)}
*
* @template T
* @private
*/
function struct(clazz) {
var fields = clazz.__fields;
clazz.read = function (reader) {
var result = new clazz();
for (var _i = 0; _i < fields.length; _i++) {
var field_1 = fields[_i];
var value = void 0;
switch (field_1.type) {
case DataType.Char:
value = String.fromCharCode(reader.dataView.getInt8(reader.position));
reader.position += 1;
break;
case DataType.Uint16:
value = reader.dataView.getUint16(reader.position);
reader.position += 2;
break;
case DataType.Uint32:
value = reader.dataView.getUint32(reader.position);
reader.position += 4;
break;
}
result[field_1.field] = value;
}
return result;
};
return clazz;
}
/**
* @param {number} type
* @return {function(T, string)}
*
* @template T
* @private
*/
function field(type) {
var existingDecorator = fieldDecorators.get(type);
if (existingDecorator === undefined) {
existingDecorator = function (proto, field) {
var ctor = proto.constructor;
if (ctor.__fields === undefined) {
ctor.__fields = [];
}
ctor.__fields.push({
type: type,
field: field
});
};
fieldDecorators.set(type, existingDecorator);
}
return existingDecorator;
}
}, /* 7 ./parts/drawing */ function (exports) {
/**
* An instruction to move to a particular position.
*
* @param {number} x
* @param {number} y
*
* @constructor
* @implements {libjass.parts.drawing.Instruction}
* @memberOf libjass.parts.drawing
*/
var MoveInstruction = function () {
function MoveInstruction(x, y) {
this._x = x;
this._y = y;
}
Object.defineProperty(MoveInstruction.prototype, "x", {
/**
* The X position of this move instruction.
*
* @type {number}
*/
get: function () {
return this._x;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MoveInstruction.prototype, "y", {
/**
* The Y position of this move instruction.
*
* @type {number}
*/
get: function () {
return this._y;
},
enumerable: true,
configurable: true
});
return MoveInstruction;
}();
exports.MoveInstruction = MoveInstruction;
/**
* An instruction to draw a line to a particular position.
*
* @param {number} x
* @param {number} y
*
* @constructor
* @implements {libjass.parts.drawing.Instruction}
* @memberOf libjass.parts.drawing
*/
var LineInstruction = function () {
function LineInstruction(x, y) {
this._x = x;
this._y = y;
}
Object.defineProperty(LineInstruction.prototype, "x", {
/**
* The X position of this line instruction.
*
* @type {number}
*/
get: function () {
return this._x;
},
enumerable: true,
configurable: true
});
Object.defineProperty(LineInstruction.prototype, "y", {
/**
* The Y position of this line instruction.
*
* @type {number}
*/
get: function () {
return this._y;
},
enumerable: true,
configurable: true
});
return LineInstruction;
}();
exports.LineInstruction = LineInstruction;
/**
* An instruction to draw a cubic bezier curve to a particular position, with two given control points.
*
* @param {number} x1
* @param {number} y1
* @param {number} x2
* @param {number} y2
* @param {number} x3
* @param {number} y3
*
* @constructor
* @implements {libjass.parts.drawing.Instruction}
* @memberOf libjass.parts.drawing
*/
var CubicBezierCurveInstruction = function () {
function CubicBezierCurveInstruction(x1, y1, x2, y2, x3, y3) {
this._x1 = x1;
this._y1 = y1;
this._x2 = x2;
this._y2 = y2;
this._x3 = x3;
this._y3 = y3;
}
Object.defineProperty(CubicBezierCurveInstruction.prototype, "x1", {
/**
* The X position of the first control point of this cubic bezier curve instruction.
*
* @type {number}
*/
get: function () {
return this._x1;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CubicBezierCurveInstruction.prototype, "y1", {
/**
* The Y position of the first control point of this cubic bezier curve instruction.
*
* @type {number}
*/
get: function () {
return this._y1;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CubicBezierCurveInstruction.prototype, "x2", {
/**
* The X position of the second control point of this cubic bezier curve instruction.
*
* @type {number}
*/
get: function () {
return this._x2;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CubicBezierCurveInstruction.prototype, "y2", {
/**
* The Y position of the second control point of this cubic bezier curve instruction.
*
* @type {number}
*/
get: function () {
return this._y2;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CubicBezierCurveInstruction.prototype, "x3", {
/**
* The ending X position of this cubic bezier curve instruction.
*
* @type {number}
*/
get: function () {
return this._x3;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CubicBezierCurveInstruction.prototype, "y3", {
/**
* The ending Y position of this cubic bezier curve instruction.
*
* @type {number}
*/
get: function () {
return this._y3;
},
enumerable: true,
configurable: true
});
return CubicBezierCurveInstruction;
}();
exports.CubicBezierCurveInstruction = CubicBezierCurveInstruction;
}, /* 8 ./parts/index */ function (exports, require) {
var drawing = require(7);
exports.drawing = drawing;
/**
* Represents a CSS color with red, green, blue and alpha components.
*
* Instances of this class are immutable.
*
* @param {number} red
* @param {number} green
* @param {number} blue
* @param {number=1} alpha
*
* @constructor
* @memberOf libjass.parts
*/
var Color = function () {
function Color(red, green, blue, alpha) {
if (alpha === void 0) {
alpha = 1;
}
this._red = red;
this._green = green;
this._blue = blue;
this._alpha = alpha;
}
Object.defineProperty(Color.prototype, "red", {
/**
* The red component of this color as a number between 0 and 255.
*
* @type {number}
*/
get: function () {
return this._red;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Color.prototype, "green", {
/**
* The green component of this color as a number between 0 and 255.
*
* @type {number}
*/
get: function () {
return this._green;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Color.prototype, "blue", {
/**
* The blue component of this color as a number between 0 and 255.
*
* @type {number}
*/
get: function () {
return this._blue;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Color.prototype, "alpha", {
/**
* The alpha component of this color as a number between 0 and 1, where 0 means transparent and 1 means opaque.
*
* @type {number}
*/
get: function () {
return this._alpha;
},
enumerable: true,
configurable: true
});
/**
* @param {?number} value The new alpha. If null, the existing alpha is used.
* @return {!libjass.parts.Color} Returns a new Color instance with the same color but the provided alpha.
*/
Color.prototype.withAlpha = function (value) {
if (value !== null) {
return new Color(this._red, this._green, this._blue, value);
}
return this;
};
/**
* @return {string} The CSS representation "rgba(...)" of this color.
*/
Color.prototype.toString = function () {
return "rgba(" + this._red + ", " + this._green + ", " + this._blue + ", " + this._alpha.toFixed(3) + ")";
};
/**
* Returns a new Color by interpolating the current color to the final color by the given progression.
*
* @param {!libjass.parts.Color} final
* @param {number} progression
* @return {!libjass.parts.Color}
*/
Color.prototype.interpolate = function (final, progression) {
return new Color(this._red + progression * (final.red - this._red), this._green + progression * (final.green - this._green), this._blue + progression * (final.blue - this._blue), this._alpha + progression * (final.alpha - this._alpha));
};
return Color;
}();
exports.Color = Color;
/**
* A comment, i.e., any text enclosed in {} that is not understood as an ASS tag.
*
* @param {string} value The text of this comment
*
* @constructor
* @memberOf libjass.parts
*/
var Comment = function () {
function Comment(value) {
this._value = value;
}
Object.defineProperty(Comment.prototype, "value", {
/**
* The value of this comment.
*
* @type {string}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return Comment;
}();
exports.Comment = Comment;
/**
* A block of text, i.e., any text not enclosed in {}. Also includes \h.
*
* @param {string} value The content of this block of text
*
* @constructor
* @memberOf libjass.parts
*/
var Text = function () {
function Text(value) {
this._value = value;
}
Object.defineProperty(Text.prototype, "value", {
/**
* The value of this text part.
*
* @type {string}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
/**
* @return {string}
*/
Text.prototype.toString = function () {
return "Text { value: " + this._value.replace(/\u00A0/g, "\\h") + " }";
};
return Text;
}();
exports.Text = Text;
/**
* A newline character \N.
*
* @constructor
* @memberOf libjass.parts
*/
var NewLine = function () {
function NewLine() {}
return NewLine;
}();
exports.NewLine = NewLine;
/**
* An italic tag {\i}
*
* @param {?boolean} value {\i1} -> true, {\i0} -> false, {\i} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var Italic = function () {
function Italic(value) {
this._value = value;
}
Object.defineProperty(Italic.prototype, "value", {
/**
* The value of this italic tag.
*
* @type {?boolean}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return Italic;
}();
exports.Italic = Italic;
/**
* A bold tag {\b}
*
* @param {*} value {\b1} -> true, {\b0} -> false, {\b###} -> weight of the bold (number), {\b} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var Bold = function () {
function Bold(value) {
this._value = value;
}
Object.defineProperty(Bold.prototype, "value", {
/**
* The value of this bold tag.
*
* @type {?boolean|?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return Bold;
}();
exports.Bold = Bold;
/**
* An underline tag {\u}
*
* @param {?boolean} value {\u1} -> true, {\u0} -> false, {\u} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var Underline = function () {
function Underline(value) {
this._value = value;
}
Object.defineProperty(Underline.prototype, "value", {
/**
* The value of this underline tag.
*
* @type {?boolean}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return Underline;
}();
exports.Underline = Underline;
/**
* A strike-through tag {\s}
*
* @param {?boolean} value {\s1} -> true, {\s0} -> false, {\s} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var StrikeThrough = function () {
function StrikeThrough(value) {
this._value = value;
}
Object.defineProperty(StrikeThrough.prototype, "value", {
/**
* The value of this strike-through tag.
*
* @type {?boolean}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return StrikeThrough;
}();
exports.StrikeThrough = StrikeThrough;
/**
* A border tag {\bord}
*
* @param {?number} value {\bord###} -> width (number), {\bord} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var Border = function () {
function Border(value) {
this._value = value;
}
Object.defineProperty(Border.prototype, "value", {
/**
* The value of this border tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return Border;
}();
exports.Border = Border;
/**
* A horizontal border tag {\xbord}
*
* @param {?number} value {\xbord###} -> width (number), {\xbord} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var BorderX = function () {
function BorderX(value) {
this._value = value;
}
Object.defineProperty(BorderX.prototype, "value", {
/**
* The value of this horizontal border tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return BorderX;
}();
exports.BorderX = BorderX;
/**
* A vertical border tag {\ybord}
*
* @param {?number} value {\ybord###} -> height (number), {\ybord} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var BorderY = function () {
function BorderY(value) {
this._value = value;
}
Object.defineProperty(BorderY.prototype, "value", {
/**
* The value of this vertical border tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return BorderY;
}();
exports.BorderY = BorderY;
/**
* A shadow tag {\shad}
*
* @param {?number} value {\shad###} -> depth (number), {\shad} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var Shadow = function () {
function Shadow(value) {
this._value = value;
}
Object.defineProperty(Shadow.prototype, "value", {
/**
* The value of this shadow tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return Shadow;
}();
exports.Shadow = Shadow;
/**
* A horizontal shadow tag {\xshad}
*
* @param {?number} value {\xshad###} -> depth (number), {\xshad} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var ShadowX = function () {
function ShadowX(value) {
this._value = value;
}
Object.defineProperty(ShadowX.prototype, "value", {
/**
* The value of this horizontal shadow tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return ShadowX;
}();
exports.ShadowX = ShadowX;
/**
* A vertical shadow tag {\yshad}
*
* @param {?number} value {\yshad###} -> depth (number), {\yshad} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var ShadowY = function () {
function ShadowY(value) {
this._value = value;
}
Object.defineProperty(ShadowY.prototype, "value", {
/**
* The value of this vertical shadow tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return ShadowY;
}();
exports.ShadowY = ShadowY;
/**
* A blur tag {\be}
*
* @param {?number} value {\be###} -> strength (number), {\be} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var Blur = function () {
function Blur(value) {
this._value = value;
}
Object.defineProperty(Blur.prototype, "value", {
/**
* The value of this blur tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return Blur;
}();
exports.Blur = Blur;
/**
* A Gaussian blur tag {\blur}
*
* @param {?number} value {\blur###} -> strength (number), {\blur} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var GaussianBlur = function () {
function GaussianBlur(value) {
this._value = value;
}
Object.defineProperty(GaussianBlur.prototype, "value", {
/**
* The value of this Gaussian blur tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return GaussianBlur;
}();
exports.GaussianBlur = GaussianBlur;
/**
* A font name tag {\fn}
*
* @param {?string} value {\fn###} -> name (string), {\fn} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var FontName = function () {
function FontName(value) {
this._value = value;
}
Object.defineProperty(FontName.prototype, "value", {
/**
* The value of this font name tag.
*
* @type {?string}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return FontName;
}();
exports.FontName = FontName;
/**
* A font size tag {\fs}
*
* @param {?number} value {\fs###} -> size (number), {\fs} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var FontSize = function () {
function FontSize(value) {
this._value = value;
}
Object.defineProperty(FontSize.prototype, "value", {
/**
* The value of this font size tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return FontSize;
}();
exports.FontSize = FontSize;
/**
* A font size increase tag {\fs+}
*
* @param {number} value {\fs+###} -> difference (number)
*
* @constructor
* @memberOf libjass.parts
*/
var FontSizePlus = function () {
function FontSizePlus(value) {
this._value = value;
}
Object.defineProperty(FontSizePlus.prototype, "value", {
/**
* The value of this font size increase tag.
*
* @type {number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return FontSizePlus;
}();
exports.FontSizePlus = FontSizePlus;
/**
* A font size decrease tag {\fs-}
*
* @param {number} value {\fs-###} -> difference (number)
*
* @constructor
* @memberOf libjass.parts
*/
var FontSizeMinus = function () {
function FontSizeMinus(value) {
this._value = value;
}
Object.defineProperty(FontSizeMinus.prototype, "value", {
/**
* The value of this font size decrease tag.
*
* @type {number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return FontSizeMinus;
}();
exports.FontSizeMinus = FontSizeMinus;
/**
* A horizontal font scaling tag {\fscx}
*
* @param {?number} value {\fscx###} -> scale (number), {\fscx} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var FontScaleX = function () {
function FontScaleX(value) {
this._value = value;
}
Object.defineProperty(FontScaleX.prototype, "value", {
/**
* The value of this horizontal font scaling tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return FontScaleX;
}();
exports.FontScaleX = FontScaleX;
/**
* A vertical font scaling tag {\fscy}
*
* @param {?number} value {\fscy###} -> scale (number), {\fscy} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var FontScaleY = function () {
function FontScaleY(value) {
this._value = value;
}
Object.defineProperty(FontScaleY.prototype, "value", {
/**
* The value of this vertical font scaling tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return FontScaleY;
}();
exports.FontScaleY = FontScaleY;
/**
* A letter-spacing tag {\fsp}
*
* @param {?number} value {\fsp###} -> spacing (number), {\fsp} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var LetterSpacing = function () {
function LetterSpacing(value) {
this._value = value;
}
Object.defineProperty(LetterSpacing.prototype, "value", {
/**
* The value of this letter-spacing tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return LetterSpacing;
}();
exports.LetterSpacing = LetterSpacing;
/**
* An X-axis rotation tag {\frx}
*
* @param {?number} value {\frx###} -> angle (number), {\frx} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var RotateX = function () {
function RotateX(value) {
this._value = value;
}
Object.defineProperty(RotateX.prototype, "value", {
/**
* The value of this X-axis rotation tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return RotateX;
}();
exports.RotateX = RotateX;
/**
* A Y-axis rotation tag {\fry}
*
* @param {?number} value {\fry###} -> angle (number), {\fry} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var RotateY = function () {
function RotateY(value) {
this._value = value;
}
Object.defineProperty(RotateY.prototype, "value", {
/**
* The value of this Y-axis rotation tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return RotateY;
}();
exports.RotateY = RotateY;
/**
* A Z-axis rotation tag {\fr} or {\frz}
*
* @param {?number} value {\frz###} -> angle (number), {\frz} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var RotateZ = function () {
function RotateZ(value) {
this._value = value;
}
Object.defineProperty(RotateZ.prototype, "value", {
/**
* The value of this Z-axis rotation tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return RotateZ;
}();
exports.RotateZ = RotateZ;
/**
* An X-axis shearing tag {\fax}
*
* @param {?number} value {\fax###} -> angle (number), {\fax} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var SkewX = function () {
function SkewX(value) {
this._value = value;
}
Object.defineProperty(SkewX.prototype, "value", {
/**
* The value of this X-axis shearing tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return SkewX;
}();
exports.SkewX = SkewX;
/**
* A Y-axis shearing tag {\fay}
*
* @param {?number} value {\fay###} -> angle (number), {\fay} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var SkewY = function () {
function SkewY(value) {
this._value = value;
}
Object.defineProperty(SkewY.prototype, "value", {
/**
* The value of this Y-axis shearing tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return SkewY;
}();
exports.SkewY = SkewY;
/**
* A primary color tag {\c} or {\1c}
*
* @param {libjass.parts.Color} value {\1c###} -> color (Color), {\1c} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var PrimaryColor = function () {
function PrimaryColor(value) {
this._value = value;
}
Object.defineProperty(PrimaryColor.prototype, "value", {
/**
* The value of this primary color tag.
*
* @type {libjass.parts.Color}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return PrimaryColor;
}();
exports.PrimaryColor = PrimaryColor;
/**
* A secondary color tag {\2c}
*
* @param {libjass.parts.Color} value {\2c###} -> color (Color), {\2c} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var SecondaryColor = function () {
function SecondaryColor(value) {
this._value = value;
}
Object.defineProperty(SecondaryColor.prototype, "value", {
/**
* The value of this secondary color tag.
*
* @type {libjass.parts.Color}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return SecondaryColor;
}();
exports.SecondaryColor = SecondaryColor;
/**
* An outline color tag {\3c}
*
* @param {libjass.parts.Color} value {\3c###} -> color (Color), {\3c} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var OutlineColor = function () {
function OutlineColor(value) {
this._value = value;
}
Object.defineProperty(OutlineColor.prototype, "value", {
/**
* The value of this outline color tag.
*
* @type {libjass.parts.Color}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return OutlineColor;
}();
exports.OutlineColor = OutlineColor;
/**
* A shadow color tag {\4c}
*
* @param {libjass.parts.Color} value {\4c###} -> color (Color), {\4c} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var ShadowColor = function () {
function ShadowColor(value) {
this._value = value;
}
Object.defineProperty(ShadowColor.prototype, "value", {
/**
* The value of this shadow color tag.
*
* @type {libjass.parts.Color}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return ShadowColor;
}();
exports.ShadowColor = ShadowColor;
/**
* An alpha tag {\alpha}
*
* @param {?number} value {\alpha###} -> alpha (number), {\alpha} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var Alpha = function () {
function Alpha(value) {
this._value = value;
}
Object.defineProperty(Alpha.prototype, "value", {
/**
* The value of this alpha tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return Alpha;
}();
exports.Alpha = Alpha;
/**
* A primary alpha tag {\1a}
*
* @param {?number} value {\1a###} -> alpha (number), {\1a} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var PrimaryAlpha = function () {
function PrimaryAlpha(value) {
this._value = value;
}
Object.defineProperty(PrimaryAlpha.prototype, "value", {
/**
* The value of this primary alpha tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return PrimaryAlpha;
}();
exports.PrimaryAlpha = PrimaryAlpha;
/**
* A secondary alpha tag {\2a}
*
* @param {?number} value {\2a###} -> alpha (number), {\2a} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var SecondaryAlpha = function () {
function SecondaryAlpha(value) {
this._value = value;
}
Object.defineProperty(SecondaryAlpha.prototype, "value", {
/**
* The value of this secondary alpha tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return SecondaryAlpha;
}();
exports.SecondaryAlpha = SecondaryAlpha;
/**
* An outline alpha tag {\3a}
*
* @param {?number} value {\3a###} -> alpha (number), {\3a} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var OutlineAlpha = function () {
function OutlineAlpha(value) {
this._value = value;
}
Object.defineProperty(OutlineAlpha.prototype, "value", {
/**
* The value of this outline alpha tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return OutlineAlpha;
}();
exports.OutlineAlpha = OutlineAlpha;
/**
* A shadow alpha tag {\4a}
*
* @param {?number} value {\4a###} -> alpha (number), {\4a} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var ShadowAlpha = function () {
function ShadowAlpha(value) {
this._value = value;
}
Object.defineProperty(ShadowAlpha.prototype, "value", {
/**
* The value of this shadow alpha tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return ShadowAlpha;
}();
exports.ShadowAlpha = ShadowAlpha;
/**
* An alignment tag {\an} or {\a}
*
* @param {number} value {\an###} -> alignment (number)
*
* @constructor
* @memberOf libjass.parts
*/
var Alignment = function () {
function Alignment(value) {
this._value = value;
}
Object.defineProperty(Alignment.prototype, "value", {
/**
* The value of this alignment tag.
*
* @type {?number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return Alignment;
}();
exports.Alignment = Alignment;
/**
* A color karaoke tag {\k}
*
* @param {number} duration {\k###} -> duration (number)
*
* @constructor
* @memberOf libjass.parts
*/
var ColorKaraoke = function () {
function ColorKaraoke(duration) {
this._duration = duration;
}
Object.defineProperty(ColorKaraoke.prototype, "duration", {
/**
* The duration of this color karaoke tag.
*
* @type {number}
*/
get: function () {
return this._duration;
},
enumerable: true,
configurable: true
});
return ColorKaraoke;
}();
exports.ColorKaraoke = ColorKaraoke;
/**
* A sweeping color karaoke tag {\K} or {\kf}
*
* @param {number} duration {\kf###} -> duration (number)
*
* @constructor
* @memberOf libjass.parts
*/
var SweepingColorKaraoke = function () {
function SweepingColorKaraoke(duration) {
this._duration = duration;
}
Object.defineProperty(SweepingColorKaraoke.prototype, "duration", {
/**
* The duration of this sweeping color karaoke tag.
*
* @type {number}
*/
get: function () {
return this._duration;
},
enumerable: true,
configurable: true
});
return SweepingColorKaraoke;
}();
exports.SweepingColorKaraoke = SweepingColorKaraoke;
/**
* An outline karaoke tag {\ko}
*
* @param {number} duration {\ko###} -> duration (number)
*
* @constructor
* @memberOf libjass.parts
*/
var OutlineKaraoke = function () {
function OutlineKaraoke(duration) {
this._duration = duration;
}
Object.defineProperty(OutlineKaraoke.prototype, "duration", {
/**
* The duration of this outline karaoke tag.
*
* @type {number}
*/
get: function () {
return this._duration;
},
enumerable: true,
configurable: true
});
return OutlineKaraoke;
}();
exports.OutlineKaraoke = OutlineKaraoke;
/**
* A wrapping style tag {\q}
*
* @param {number} value {\q###} -> style (number)
*
* @constructor
* @memberOf libjass.parts
*/
var WrappingStyle = function () {
function WrappingStyle(value) {
this._value = value;
}
Object.defineProperty(WrappingStyle.prototype, "value", {
/**
* The value of this wrapping style tag.
*
* @type {number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return WrappingStyle;
}();
exports.WrappingStyle = WrappingStyle;
/**
* A style reset tag {\r}
*
* @param {?string} value {\r###} -> style name (string), {\r} -> null
*
* @constructor
* @memberOf libjass.parts
*/
var Reset = function () {
function Reset(value) {
this._value = value;
}
Object.defineProperty(Reset.prototype, "value", {
/**
* The value of this style reset tag.
*
* @type {?string}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return Reset;
}();
exports.Reset = Reset;
/**
* A position tag {\pos}
*
* @param {number} x
* @param {number} y
*
* @constructor
* @memberOf libjass.parts
*/
var Position = function () {
function Position(x, y) {
this._x = x;
this._y = y;
}
Object.defineProperty(Position.prototype, "x", {
/**
* The x value of this position tag.
*
* @type {number}
*/
get: function () {
return this._x;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Position.prototype, "y", {
/**
* The y value of this position tag.
*
* @type {number}
*/
get: function () {
return this._y;
},
enumerable: true,
configurable: true
});
return Position;
}();
exports.Position = Position;
/**
* A movement tag {\move}
*
* @param {number} x1
* @param {number} y1
* @param {number} x2
* @param {number} y2
* @param {number} t1
* @param {number} t2
*
* @constructor
* @memberOf libjass.parts
*/
var Move = function () {
function Move(x1, y1, x2, y2, t1, t2) {
this._x1 = x1;
this._y1 = y1;
this._x2 = x2;
this._y2 = y2;
this._t1 = t1;
this._t2 = t2;
}
Object.defineProperty(Move.prototype, "x1", {
/**
* The starting x value of this move tag.
*
* @type {number}
*/
get: function () {
return this._x1;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Move.prototype, "y1", {
/**
* The starting y value of this move tag.
*
* @type {number}
*/
get: function () {
return this._y1;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Move.prototype, "x2", {
/**
* The ending x value of this move tag.
*
* @type {number}
*/
get: function () {
return this._x2;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Move.prototype, "y2", {
/**
* The ending y value of this move tag.
*
* @type {number}
*/
get: function () {
return this._y2;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Move.prototype, "t1", {
/**
* The start time of this move tag.
*
* @type {number}
*/
get: function () {
return this._t1;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Move.prototype, "t2", {
/**
* The end time value of this move tag.
*
* @type {number}
*/
get: function () {
return this._t2;
},
enumerable: true,
configurable: true
});
return Move;
}();
exports.Move = Move;
/**
* A rotation origin tag {\org}
*
* @param {number} x
* @param {number} y
*
* @constructor
* @memberOf libjass.parts
*/
var RotationOrigin = function () {
function RotationOrigin(x, y) {
this._x = x;
this._y = y;
}
Object.defineProperty(RotationOrigin.prototype, "x", {
/**
* The x value of this rotation origin tag.
*
* @type {number}
*/
get: function () {
return this._x;
},
enumerable: true,
configurable: true
});
Object.defineProperty(RotationOrigin.prototype, "y", {
/**
* The y value of this rotation origin tag.
*
* @type {number}
*/
get: function () {
return this._y;
},
enumerable: true,
configurable: true
});
return RotationOrigin;
}();
exports.RotationOrigin = RotationOrigin;
/**
* A simple fade tag {\fad}
*
* @param {number} start
* @param {number} end
*
* @constructor
* @memberOf libjass.parts
*/
var Fade = function () {
function Fade(start, end) {
this._start = start;
this._end = end;
}
Object.defineProperty(Fade.prototype, "start", {
/**
* The start time of this fade tag.
*
* @type {number}
*/
get: function () {
return this._start;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Fade.prototype, "end", {
/**
* The end time of this fade tag.
*
* @type {number}
*/
get: function () {
return this._end;
},
enumerable: true,
configurable: true
});
return Fade;
}();
exports.Fade = Fade;
/**
* A complex fade tag {\fade}
*
* @param {number} a1
* @param {number} a2
* @param {number} a3
* @param {number} t1
* @param {number} t2
* @param {number} t3
* @param {number} t4
*
* @constructor
* @memberOf libjass.parts
*/
var ComplexFade = function () {
function ComplexFade(a1, a2, a3, t1, t2, t3, t4) {
this._a1 = a1;
this._a2 = a2;
this._a3 = a3;
this._t1 = t1;
this._t2 = t2;
this._t3 = t3;
this._t4 = t4;
}
Object.defineProperty(ComplexFade.prototype, "a1", {
/**
* The alpha value of this complex fade tag at time t2.
*
* @type {number}
*/
get: function () {
return this._a1;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComplexFade.prototype, "a2", {
/**
* The alpha value of this complex fade tag at time t3.
*
* @type {number}
*/
get: function () {
return this._a2;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComplexFade.prototype, "a3", {
/**
* The alpha value of this complex fade tag at time t4.
*
* @type {number}
*/
get: function () {
return this._a3;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComplexFade.prototype, "t1", {
/**
* The starting time of this complex fade tag.
*
* @type {number}
*/
get: function () {
return this._t1;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComplexFade.prototype, "t2", {
/**
* The first intermediate time of this complex fade tag.
*
* @type {number}
*/
get: function () {
return this._t2;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComplexFade.prototype, "t3", {
/**
* The second intermediate time of this complex fade tag.
*
* @type {number}
*/
get: function () {
return this._t3;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ComplexFade.prototype, "t4", {
/**
* The ending time of this complex fade tag.
*
* @type {number}
*/
get: function () {
return this._t4;
},
enumerable: true,
configurable: true
});
return ComplexFade;
}();
exports.ComplexFade = ComplexFade;
/**
* A transform tag {\t}
*
* @param {number} start
* @param {number} end
* @param {number} accel
* @param {!Array.<!libjass.parts.Tag>} tags
*
* @constructor
* @memberOf libjass.parts
*/
var Transform = function () {
function Transform(start, end, accel, tags) {
this._start = start;
this._end = end;
this._accel = accel;
this._tags = tags;
}
Object.defineProperty(Transform.prototype, "start", {
/**
* The starting time of this transform tag.
*
* @type {?number}
*/
get: function () {
return this._start;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Transform.prototype, "end", {
/**
* The ending time of this transform tag.
*
* @type {?number}
*/
get: function () {
return this._end;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Transform.prototype, "accel", {
/**
* The acceleration of this transform tag.
*
* @type {?number}
*/
get: function () {
return this._accel;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Transform.prototype, "tags", {
/**
* The tags animated by this transform tag.
*
* @type {!Array.<!libjass.parts.Tag>}
*/
get: function () {
return this._tags;
},
enumerable: true,
configurable: true
});
return Transform;
}();
exports.Transform = Transform;
/**
* A rectangular clip tag {\clip} or {\iclip}
*
* @param {number} x1
* @param {number} y1
* @param {number} x2
* @param {number} y2
* @param {boolean} inside
*
* @constructor
* @memberOf libjass.parts
*/
var RectangularClip = function () {
function RectangularClip(x1, y1, x2, y2, inside) {
this._x1 = x1;
this._y1 = y1;
this._x2 = x2;
this._y2 = y2;
this._inside = inside;
}
Object.defineProperty(RectangularClip.prototype, "x1", {
/**
* The X coordinate of the starting position of this rectangular clip tag.
*
* @type {number}
*/
get: function () {
return this._x1;
},
enumerable: true,
configurable: true
});
Object.defineProperty(RectangularClip.prototype, "y1", {
/**
* The Y coordinate of the starting position of this rectangular clip tag.
*
* @type {number}
*/
get: function () {
return this._y1;
},
enumerable: true,
configurable: true
});
Object.defineProperty(RectangularClip.prototype, "x2", {
/**
* The X coordinate of the ending position of this rectangular clip tag.
*
* @type {number}
*/
get: function () {
return this._x2;
},
enumerable: true,
configurable: true
});
Object.defineProperty(RectangularClip.prototype, "y2", {
/**
* The Y coordinate of the ending position of this rectangular clip tag.
*
* @type {number}
*/
get: function () {
return this._y2;
},
enumerable: true,
configurable: true
});
Object.defineProperty(RectangularClip.prototype, "inside", {
/**
* Whether this rectangular clip tag clips the region it encloses or the region it excludes.
*
* @type {boolean}
*/
get: function () {
return this._inside;
},
enumerable: true,
configurable: true
});
return RectangularClip;
}();
exports.RectangularClip = RectangularClip;
/**
* A vector clip tag {\clip} or {\iclip}
*
* @param {number} scale
* @param {!Array.<!libjass.parts.drawing.Instruction>} instructions
* @param {boolean} inside
*
* @constructor
* @memberOf libjass.parts
*/
var VectorClip = function () {
function VectorClip(scale, instructions, inside) {
this._scale = scale;
this._instructions = instructions;
this._inside = inside;
}
Object.defineProperty(VectorClip.prototype, "scale", {
/**
* The scale of this vector clip tag.
*
* @type {number}
*/
get: function () {
return this._scale;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VectorClip.prototype, "instructions", {
/**
* The clip commands of this vector clip tag.
*
* @type {string}
*/
get: function () {
return this._instructions;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VectorClip.prototype, "inside", {
/**
* Whether this vector clip tag clips the region it encloses or the region it excludes.
*
* @type {boolean}
*/
get: function () {
return this._inside;
},
enumerable: true,
configurable: true
});
return VectorClip;
}();
exports.VectorClip = VectorClip;
/**
* A drawing mode tag {\p}
*
* @param {number} scale
*
* @constructor
* @memberOf libjass.parts
*/
var DrawingMode = function () {
function DrawingMode(scale) {
this._scale = scale;
}
Object.defineProperty(DrawingMode.prototype, "scale", {
/**
* The scale of this drawing mode tag.
*
* @type {number}
*/
get: function () {
return this._scale;
},
enumerable: true,
configurable: true
});
return DrawingMode;
}();
exports.DrawingMode = DrawingMode;
/**
* A drawing mode baseline offset tag {\pbo}
*
* @param {number} value
*
* @constructor
* @memberOf libjass.parts
*/
var DrawingBaselineOffset = function () {
function DrawingBaselineOffset(value) {
this._value = value;
}
Object.defineProperty(DrawingBaselineOffset.prototype, "value", {
/**
* The value of this drawing mode baseline offset tag.
*
* @type {number}
*/
get: function () {
return this._value;
},
enumerable: true,
configurable: true
});
return DrawingBaselineOffset;
}();
exports.DrawingBaselineOffset = DrawingBaselineOffset;
/**
* A pseudo-part representing text interpreted as drawing instructions
*
* @param {!Array.<!libjass.parts.drawing.Instruction>} instructions
*
* @constructor
* @memberOf libjass.parts
*/
var DrawingInstructions = function () {
function DrawingInstructions(instructions) {
this._instructions = instructions;
}
Object.defineProperty(DrawingInstructions.prototype, "instructions", {
/**
* The instructions contained in this drawing instructions part.
*
* @type {!Array.<!libjass.parts.drawing.Instruction>}
*/
get: function () {
return this._instructions;
},
enumerable: true,
configurable: true
});
return DrawingInstructions;
}();
exports.DrawingInstructions = DrawingInstructions;
var addToString = function (ctor, ctorName) {
if (!ctor.prototype.hasOwnProperty("toString")) {
var propertyNames = Object.getOwnPropertyNames(ctor.prototype).filter(function (property) {
return property !== "constructor";
});
ctor.prototype.toString = function () {
var _this = this;
return ctorName + " { " + propertyNames.map(function (name) {
return name + ": " + _this[name];
}).join(", ") + (propertyNames.length > 0 ? " " : "") + "}";
};
}
};
var misc_1 = require(38);
for (var _i = 0, _a = Object.keys(exports); _i < _a.length; _i++) {
var key = _a[_i];
var value = exports[key];
if (value instanceof Function) {
addToString(value, key);
misc_1.registerClassPrototype(value.prototype);
}
}
for (var _b = 0, _c = Object.keys(drawing); _b < _c.length; _b++) {
var key = _c[_b];
var value = drawing[key];
if (value instanceof Function) {
addToString(value, "Drawing" + key);
misc_1.registerClassPrototype(value.prototype);
}
}
}, /* 9 ./renderers/clocks/auto */ function (exports, require) {
var settings_1 = require(23);
var manual_1 = require(11);
/**
* An implementation of {@link libjass.renderers.Clock} that automatically ticks and generates {@link libjass.renderers.ClockEvent}s according to the state of an external driver.
*
* For example, if you're using libjass to render subtitles on a canvas with your own video controls, these video controls will function as the driver to this AutoClock.
* It would call {@link libjass.renderers.AutoClock.play}, {@link libjass.renderers.AutoClock.pause}, etc. when the user pressed the corresponding video controls.
*
* The difference from ManualClock is that AutoClock does not require the driver to call something like {@link libjass.renderers.ManualClock.tick}. Instead it keeps its
* own time with a high-resolution requestAnimationFrame-based timer.
*
* If using libjass with a <video> element, consider using {@link libjass.renderers.VideoClock} that uses the video element as a driver.
*
* @param {function():number} getCurrentTime A callback that will be invoked to get the current time of the external driver.
* @param {number} autoPauseAfter If two calls to getCurrentTime are more than autoPauseAfter milliseconds apart but return the same time, then the external driver will be
* considered to have paused.
*
* @constructor
* @implements {libjass.renderers.Clock}
* @memberOf libjass.renderers
*/
var AutoClock = function () {
function AutoClock(getCurrentTime, autoPauseAfter) {
this._getCurrentTime = getCurrentTime;
this._autoPauseAfter = autoPauseAfter;
this._manualClock = new manual_1.ManualClock();
this._nextAnimationFrameRequestId = null;
this._lastKnownExternalTime = null;
this._lastKnownExternalTimeObtainedAt = null;
}
/**
* Tells the clock to start generating ticks.
*/
AutoClock.prototype.play = function () {
if (!this._manualClock.enabled) {
return;
}
this._startTicking();
this._manualClock.play();
};
/**
* Tells the clock to pause.
*/
AutoClock.prototype.pause = function () {
if (!this._manualClock.enabled) {
return;
}
if (this._nextAnimationFrameRequestId === null) {
if (settings_1.debugMode) {
console.warn("AutoClock.pause: Abnormal state detected. AutoClock._nextAnimationFrameRequestId should not have been null.");
}
return;
}
this._stopTicking();
this._manualClock.pause();
};
/**
* Tells the clock that the external driver is seeking.
*/
AutoClock.prototype.seeking = function () {
this._manualClock.seek(this._getCurrentTime());
};
Object.defineProperty(AutoClock.prototype, "currentTime", {
// Clock members
/**
* @type {number}
*/
get: function () {
return this._manualClock.currentTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AutoClock.prototype, "enabled", {
/**
* @type {boolean}
*/
get: function () {
return this._manualClock.enabled;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AutoClock.prototype, "paused", {
/**
* @type {boolean}
*/
get: function () {
return this._manualClock.paused;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AutoClock.prototype, "rate", {
/**
* Gets the rate of the clock - how fast the clock ticks compared to real time.
*
* @type {number}
*/
get: function () {
return this._manualClock.rate;
},
enumerable: true,
configurable: true
});
/**
* Sets the rate of the clock - how fast the clock ticks compared to real time.
*
* @param {number} rate The new rate of the clock.
*/
AutoClock.prototype.setRate = function (rate) {
this._manualClock.setRate(rate);
};
/**
* Enable the clock.
*
* @return {boolean} True if the clock is now enabled, false if it was already enabled.
*/
AutoClock.prototype.enable = function () {
if (!this._manualClock.enable()) {
return false;
}
this._startTicking();
return true;
};
/**
* Disable the clock.
*
* @return {boolean} True if the clock is now disabled, false if it was already disabled.
*/
AutoClock.prototype.disable = function () {
if (!this._manualClock.disable()) {
return false;
}
this._stopTicking();
return true;
};
/**
* Toggle the clock.
*/
AutoClock.prototype.toggle = function () {
if (this._manualClock.enabled) {
this.disable();
} else {
this.enable();
}
};
/**
* Enable or disable the clock.
*
* @param {boolean} enabled If true, the clock is enabled, otherwise it's disabled.
* @return {boolean} True if the clock is now in the given state, false if it was already in that state.
*/
AutoClock.prototype.setEnabled = function (enabled) {
if (enabled) {
return this.enable();
} else {
return this.disable();
}
};
/**
* @param {number} type
* @param {!Function} listener
*/
AutoClock.prototype.addEventListener = function (type, listener) {
this._manualClock.addEventListener(type, listener);
};
/**
* @param {number} timeStamp
*
* @private
*/
AutoClock.prototype._onTimerTick = function (timeStamp) {
var _this = this;
if (!this._manualClock.enabled) {
if (settings_1.debugMode) {
console.warn("AutoClock._onTimerTick: Called when disabled.");
}
return;
}
var currentTime = this._manualClock.currentTime;
var currentExternalTime = this._getCurrentTime();
if (!this._manualClock.paused) {
if (this._lastKnownExternalTime !== null && currentExternalTime === this._lastKnownExternalTime) {
if (timeStamp - this._lastKnownExternalTimeObtainedAt > this._autoPauseAfter) {
this._lastKnownExternalTimeObtainedAt = null;
this._manualClock.pause();
} else {
this._manualClock.tick((timeStamp - this._lastKnownExternalTimeObtainedAt) / 1e3 * this._manualClock.rate + this._lastKnownExternalTime);
}
} else {
this._lastKnownExternalTime = currentExternalTime;
this._lastKnownExternalTimeObtainedAt = timeStamp;
this._manualClock.tick(currentExternalTime);
}
} else {
if (currentTime !== currentExternalTime) {
this._lastKnownExternalTime = currentExternalTime;
this._lastKnownExternalTimeObtainedAt = timeStamp;
this._manualClock.tick(currentExternalTime);
}
}
this._nextAnimationFrameRequestId = requestAnimationFrame(function (timeStamp) {
return _this._onTimerTick(timeStamp);
});
};
AutoClock.prototype._startTicking = function () {
var _this = this;
if (this._nextAnimationFrameRequestId === null) {
this._nextAnimationFrameRequestId = requestAnimationFrame(function (timeStamp) {
return _this._onTimerTick(timeStamp);
});
}
};
AutoClock.prototype._stopTicking = function () {
if (this._nextAnimationFrameRequestId !== null) {
cancelAnimationFrame(this._nextAnimationFrameRequestId);
this._nextAnimationFrameRequestId = null;
}
};
return AutoClock;
}();
exports.AutoClock = AutoClock;
}, /* 10 ./renderers/clocks/base */ function (exports) {
/**
* A mixin class that represents an event source.
*
* @constructor
* @memberOf libjass.renderers
* @template T
*/
var EventSource = function () {
function EventSource() {}
/**
* Add a listener for the given event.
*
* @param {!T} type The type of event to attach the listener for
* @param {!Function} listener The listener
*/
EventSource.prototype.addEventListener = function (type, listener) {
var listeners = this._eventListeners.get(type);
if (listeners === undefined) {
this._eventListeners.set(type, listeners = []);
}
listeners.push(listener);
};
/**
* Calls all listeners registered for the given event type.
*
* @param {!T} type The type of event to dispatch
* @param {!Array.<*>} args Arguments for the listeners of the event
*/
EventSource.prototype._dispatchEvent = function (type, args) {
var listeners = this._eventListeners.get(type);
if (listeners !== undefined) {
for (var _i = 0; _i < listeners.length; _i++) {
var listener = listeners[_i];
listener.apply(this, args);
}
}
};
return EventSource;
}();
exports.EventSource = EventSource;
/**
* The type of clock event.
*
* @enum
* @memberOf libjass.renderers
*/
(function (ClockEvent) {
ClockEvent[ClockEvent["Play"] = 0] = "Play";
ClockEvent[ClockEvent["Tick"] = 1] = "Tick";
ClockEvent[ClockEvent["Pause"] = 2] = "Pause";
ClockEvent[ClockEvent["Stop"] = 3] = "Stop";
ClockEvent[ClockEvent["RateChange"] = 4] = "RateChange";
})(exports.ClockEvent || (exports.ClockEvent = {}));
}, /* 11 ./renderers/clocks/manual */ function (exports, require) {
var mixin_1 = require(31);
var map_1 = require(30);
var base_1 = require(10);
/**
* An implementation of {@link libjass.renderers.Clock} that allows user script to manually trigger {@link libjass.renderers.ClockEvent}s.
*
* @constructor
* @implements {libjass.renderers.Clock}
* @implements {libjass.renderers.EventSource.<libjass.renderers.ClockEvent>}
* @memberOf libjass.renderers
*/
var ManualClock = function () {
function ManualClock() {
this._currentTime = -1;
this._rate = 1;
this._enabled = true;
this._paused = true;
// EventSource members
/**
* @type {!Map.<T, !Array.<Function>>}
*/
this._eventListeners = new map_1.Map();
}
/**
* Trigger a {@link libjass.renderers.ClockEvent.Play}
*/
ManualClock.prototype.play = function () {
if (!this._enabled) {
return;
}
if (!this._paused) {
return;
}
this._paused = false;
this._dispatchEvent(base_1.ClockEvent.Play, []);
};
/**
* Trigger a {@link libjass.renderers.ClockEvent.Tick} with the given time.
*
* @param {number} currentTime
*/
ManualClock.prototype.tick = function (currentTime) {
if (!this._enabled) {
return;
}
if (this._currentTime === currentTime) {
return;
}
this.play();
this._currentTime = currentTime;
this._dispatchEvent(base_1.ClockEvent.Tick, []);
};
/**
* Seek to the given time. Unlike {@link libjass.renderers.ManualClock.tick} this is used to represent a discontinuous jump, such as the user seeking
* via the video element's position bar.
*
* @param {number} time
*/
ManualClock.prototype.seek = function (time) {
if (!this._enabled) {
return;
}
this.pause();
if (this._currentTime === time) {
return;
}
this.stop();
this.tick(time);
this.pause();
};
/**
* Trigger a {@link libjass.renderers.ClockEvent.Pause}
*/
ManualClock.prototype.pause = function () {
if (!this._enabled) {
return;
}
if (this._paused) {
return;
}
this._paused = true;
this._dispatchEvent(base_1.ClockEvent.Pause, []);
};
/**
* Trigger a {@link libjass.renderers.ClockEvent.Stop}
*/
ManualClock.prototype.stop = function () {
this._dispatchEvent(base_1.ClockEvent.Stop, []);
};
Object.defineProperty(ManualClock.prototype, "currentTime", {
// Clock members
/**
* @type {number}
*/
get: function () {
return this._currentTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ManualClock.prototype, "enabled", {
/**
* @type {boolean}
*/
get: function () {
return this._enabled;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ManualClock.prototype, "paused", {
/**
* @type {boolean}
*/
get: function () {
return this._paused;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ManualClock.prototype, "rate", {
/**
* Gets the rate of the clock - how fast the clock ticks compared to real time.
*
* @type {number}
*/
get: function () {
return this._rate;
},
enumerable: true,
configurable: true
});
/**
* Sets the rate of the clock - how fast the clock ticks compared to real time.
*
* @param {number} rate The new rate of the clock.
*/
ManualClock.prototype.setRate = function (rate) {
if (this._rate === rate) {
return;
}
this._rate = rate;
this._dispatchEvent(base_1.ClockEvent.RateChange, []);
};
/**
* Enable the clock.
*
* @return {boolean} True if the clock is now enabled, false if it was already enabled.
*/
ManualClock.prototype.enable = function () {
if (this._enabled) {
return false;
}
this._enabled = true;
return true;
};
/**
* Disable the clock.
*
* @return {boolean} True if the clock is now disabled, false if it was already disabled.
*/
ManualClock.prototype.disable = function () {
if (!this._enabled) {
return false;
}
this.pause();
this.stop();
this._enabled = false;
return true;
};
/**
* Toggle the clock.
*/
ManualClock.prototype.toggle = function () {
if (this._enabled) {
this.disable();
} else {
this.enable();
}
};
/**
* Enable or disable the clock.
*
* @param {boolean} enabled If true, the clock is enabled, otherwise it's disabled.
* @return {boolean} True if the clock is now in the given state, false if it was already in that state.
*/
ManualClock.prototype.setEnabled = function (enabled) {
if (enabled) {
return this.enable();
} else {
return this.disable();
}
};
return ManualClock;
}();
exports.ManualClock = ManualClock;
mixin_1.mixin(ManualClock, [ base_1.EventSource ]);
}, /* 12 ./renderers/clocks/video */ function (exports, require) {
var auto_1 = require(9);
/**
* An implementation of libjass.renderers.Clock that generates {@link libjass.renderers.ClockEvent}s according to the state of a <video> element.
*
* @param {!HTMLVideoElement} video
*
* @constructor
* @implements {libjass.renderers.Clock}
* @memberOf libjass.renderers
*/
var VideoClock = function () {
function VideoClock(video) {
var _this = this;
this._autoClock = new auto_1.AutoClock(function () {
return video.currentTime;
}, 100);
video.addEventListener("playing", function () {
return _this._autoClock.play();
}, false);
video.addEventListener("pause", function () {
return _this._autoClock.pause();
}, false);
video.addEventListener("seeking", function () {
return _this._autoClock.seeking();
}, false);
video.addEventListener("ratechange", function () {
return _this._autoClock.setRate(video.playbackRate);
}, false);
}
Object.defineProperty(VideoClock.prototype, "currentTime", {
/**
* @type {number}
*/
get: function () {
return this._autoClock.currentTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VideoClock.prototype, "enabled", {
/**
* @type {boolean}
*/
get: function () {
return this._autoClock.enabled;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VideoClock.prototype, "paused", {
/**
* @type {boolean}
*/
get: function () {
return this._autoClock.paused;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VideoClock.prototype, "rate", {
/**
* Gets the rate of the clock - how fast the clock ticks compared to real time.
*
* @type {number}
*/
get: function () {
return this._autoClock.rate;
},
enumerable: true,
configurable: true
});
/**
* Enable the clock.
*
* @return {boolean} True if the clock is now enabled, false if it was already enabled.
*/
VideoClock.prototype.enable = function () {
return this._autoClock.enable();
};
/**
* Disable the clock.
*
* @return {boolean} True if the clock is now disabled, false if it was already disabled.
*/
VideoClock.prototype.disable = function () {
return this._autoClock.disable();
};
/**
* Toggle the clock.
*/
VideoClock.prototype.toggle = function () {
if (this._autoClock.enabled) {
this.disable();
} else {
this.enable();
}
};
/**
* Enable or disable the clock.
*
* @param {boolean} enabled If true, the clock is enabled, otherwise it's disabled.
* @return {boolean} True if the clock is now in the given state, false if it was already in that state.
*/
VideoClock.prototype.setEnabled = function (enabled) {
if (enabled) {
return this.enable();
} else {
return this.disable();
}
};
/**
* @param {number} type
* @param {!Function} listener
*/
VideoClock.prototype.addEventListener = function (type, listener) {
this._autoClock.addEventListener(type, listener);
};
return VideoClock;
}();
exports.VideoClock = VideoClock;
}, /* 13 ./renderers/default */ function (exports, require) {
var __extends = require(34).__extends;
var video_1 = require(12);
var renderer_1 = require(21);
/**
* A default renderer implementation.
*
* @param {!HTMLVideoElement} video
* @param {!libjass.ASS} ass
* @param {libjass.renderers.RendererSettings} settings
*
* @constructor
* @extends {libjass.renderers.WebRenderer}
* @memberOf libjass.renderers
*/
var DefaultRenderer = function (_super) {
__extends(DefaultRenderer, _super);
function DefaultRenderer(video, ass, settings) {
_super.call(this, ass, new video_1.VideoClock(video), document.createElement("div"), settings);
this._video = video;
this._video.parentElement.replaceChild(this.libjassSubsWrapper, this._video);
this.libjassSubsWrapper.insertBefore(this._video, this.libjassSubsWrapper.firstElementChild);
}
/**
* Resize the subtitles to the dimensions of the video element.
*
* This method accounts for letterboxing if the video element's size is not the same ratio as the video resolution.
*/
DefaultRenderer.prototype.resize = function () {
// Handle letterboxing around the video. If the width or height are greater than the video can be, then consider that dead space.
var videoWidth = this._video.videoWidth;
var videoHeight = this._video.videoHeight;
var videoOffsetWidth = this._video.offsetWidth;
var videoOffsetHeight = this._video.offsetHeight;
var ratio = Math.min(videoOffsetWidth / videoWidth, videoOffsetHeight / videoHeight);
var subsWrapperWidth = videoWidth * ratio;
var subsWrapperHeight = videoHeight * ratio;
var subsWrapperLeft = (videoOffsetWidth - subsWrapperWidth) / 2;
var subsWrapperTop = (videoOffsetHeight - subsWrapperHeight) / 2;
_super.prototype.resize.call(this, subsWrapperWidth, subsWrapperHeight, subsWrapperLeft, subsWrapperTop);
};
/**
* @deprecated
*/
DefaultRenderer.prototype.resizeVideo = function () {
console.warn("`DefaultRenderer.resizeVideo(width, height)` has been deprecated. Use `DefaultRenderer.resize()` instead.");
this.resize();
};
DefaultRenderer.prototype._ready = function () {
this.resize();
_super.prototype._ready.call(this);
};
return DefaultRenderer;
}(renderer_1.WebRenderer);
exports.DefaultRenderer = DefaultRenderer;
}, /* 14 ./renderers/index */ function (exports, require) {
var base_1 = require(10);
exports.ClockEvent = base_1.ClockEvent;
exports.EventSource = base_1.EventSource;
var auto_1 = require(9);
exports.AutoClock = auto_1.AutoClock;
var manual_1 = require(11);
exports.ManualClock = manual_1.ManualClock;
var video_1 = require(12);
exports.VideoClock = video_1.VideoClock;
var default_1 = require(13);
exports.DefaultRenderer = default_1.DefaultRenderer;
var null_1 = require(15);
exports.NullRenderer = null_1.NullRenderer;
var renderer_1 = require(21);
exports.WebRenderer = renderer_1.WebRenderer;
var settings_1 = require(16);
exports.RendererSettings = settings_1.RendererSettings;
}, /* 15 ./renderers/null */ function (exports, require) {
var base_1 = require(10);
var settings_1 = require(16);
var settings_2 = require(23);
/**
* A renderer implementation that doesn't output anything.
*
* @param {!libjass.ASS} ass
* @param {!libjass.renderers.Clock} clock
* @param {libjass.renderers.RendererSettings} settings
*
* @constructor
* @memberOf libjass.renderers
*/
var NullRenderer = function () {
function NullRenderer(ass, clock, settings) {
var _this = this;
this._ass = ass;
this._clock = clock;
this._id = ++NullRenderer._lastRendererId;
this._settings = settings_1.RendererSettings.from(settings);
this._clock.addEventListener(base_1.ClockEvent.Play, function () {
return _this._onClockPlay();
});
this._clock.addEventListener(base_1.ClockEvent.Tick, function () {
return _this._onClockTick();
});
this._clock.addEventListener(base_1.ClockEvent.Pause, function () {
return _this._onClockPause();
});
this._clock.addEventListener(base_1.ClockEvent.Stop, function () {
return _this._onClockStop();
});
this._clock.addEventListener(base_1.ClockEvent.RateChange, function () {
return _this._onClockRateChange();
});
}
Object.defineProperty(NullRenderer.prototype, "id", {
/**
* The unique ID of this renderer. Auto-generated.
*
* @type {number}
*/
get: function () {
return this._id;
},
enumerable: true,
configurable: true
});
Object.defineProperty(NullRenderer.prototype, "ass", {
/**
* @type {!libjass.ASS}
*/
get: function () {
return this._ass;
},
enumerable: true,
configurable: true
});
Object.defineProperty(NullRenderer.prototype, "clock", {
/**
* @type {!libjass.renderers.Clock}
*/
get: function () {
return this._clock;
},
enumerable: true,
configurable: true
});
Object.defineProperty(NullRenderer.prototype, "settings", {
/**
* @type {!libjass.renderers.RendererSettings}
*/
get: function () {
return this._settings;
},
enumerable: true,
configurable: true
});
/**
* Pre-render a dialogue. This is a no-op for this type.
*
* @param {!libjass.Dialogue} dialogue
*/
NullRenderer.prototype.preRender = function () {};
/**
* Draw a dialogue. This is a no-op for this type.
*
* @param {!libjass.Dialogue} dialogue
*/
NullRenderer.prototype.draw = function () {};
/**
* Enable the renderer.
*
* @return {boolean} True if the renderer is now enabled, false if it was already enabled.
*/
NullRenderer.prototype.enable = function () {
return this._clock.enable();
};
/**
* Disable the renderer.
*
* @return {boolean} True if the renderer is now disabled, false if it was already disabled.
*/
NullRenderer.prototype.disable = function () {
return this._clock.disable();
};
/**
* Toggle the renderer.
*/
NullRenderer.prototype.toggle = function () {
this._clock.toggle();
};
/**
* Enable or disable the renderer.
*
* @param {boolean} enabled If true, the renderer is enabled, otherwise it's disabled.
* @return {boolean} True if the renderer is now in the given state, false if it was already in that state.
*/
NullRenderer.prototype.setEnabled = function (enabled) {
return this._clock.setEnabled(enabled);
};
Object.defineProperty(NullRenderer.prototype, "enabled", {
/**
* @type {boolean}
*/
get: function () {
return this._clock.enabled;
},
enumerable: true,
configurable: true
});
/**
* Runs when the clock is enabled, or starts playing, or is resumed from pause.
*
* @protected
*/
NullRenderer.prototype._onClockPlay = function () {
if (settings_2.verboseMode) {
console.log("NullRenderer._onClockPlay");
}
};
/**
* Runs when the clock's current time changed. This might be a result of either regular playback or seeking.
*
* @protected
*/
NullRenderer.prototype._onClockTick = function () {
var currentTime = this._clock.currentTime;
if (settings_2.verboseMode) {
console.log("NullRenderer._onClockTick: currentTime = " + currentTime);
}
for (var _i = 0, _a = this._ass.dialogues; _i < _a.length; _i++) {
var dialogue = _a[_i];
if (dialogue.end > currentTime) {
if (dialogue.start <= currentTime) {
// This dialogue is visible right now. Draw it.
this.draw(dialogue);
} else if (dialogue.start <= currentTime + this._settings.preRenderTime) {
// This dialogue will be visible soon. Pre-render it.
this.preRender(dialogue);
}
}
}
};
/**
* Runs when the clock is paused.
*
* @protected
*/
NullRenderer.prototype._onClockPause = function () {
if (settings_2.verboseMode) {
console.log("NullRenderer._onClockPause");
}
};
/**
* Runs when the clock is disabled.
*
* @protected
*/
NullRenderer.prototype._onClockStop = function () {
if (settings_2.verboseMode) {
console.log("NullRenderer._onClockStop");
}
};
/**
* Runs when the clock changes its rate.
*
* @protected
*/
NullRenderer.prototype._onClockRateChange = function () {
if (settings_2.verboseMode) {
console.log("NullRenderer._onClockRateChange");
}
};
NullRenderer._lastRendererId = -1;
return NullRenderer;
}();
exports.NullRenderer = NullRenderer;
}, /* 16 ./renderers/settings */ function (exports, require) {
var map_1 = require(30);
/**
* Settings for the renderer.
*
* @constructor
* @memberOf libjass.renderers
*/
var RendererSettings = function () {
function RendererSettings() {}
/**
* A convenience method to create a font map from a <style> or <link> element that contains @font-face rules. There should be one @font-face rule for each font name, mapping to a font file URL.
*
* For example:
*
* @font-face {
* font-family: "Helvetica";
* src: url("/fonts/helvetica.ttf"), local("Arial");
* }
*
* @param {!LinkStyle} linkStyle
* @return {!Map.<string, string>}
*
* @static
*/
RendererSettings.makeFontMapFromStyleElement = function (linkStyle) {
var fontMap = new map_1.Map();
var styleSheet = linkStyle.sheet;
for (var i = 0; i < styleSheet.cssRules.length; i++) {
var rule = styleSheet.cssRules[i];
if (isFontFaceRule(rule)) {
var name_1 = rule.style.getPropertyValue("font-family").match(/^["']?(.*?)["']?$/)[1];
var src = rule.style.getPropertyValue("src");
if (!src) {
src = rule.cssText.split("\n").map(function (line) {
return line.match(/src:\s*([^;]+?)\s*;/);
}).filter(function (matches) {
return matches !== null;
}).map(function (matches) {
return matches[1];
})[0];
}
fontMap.set(name_1, src);
}
}
return fontMap;
};
/**
* Converts an arbitrary object into a {@link libjass.renderers.RendererSettings} object.
*
* @param {*} object
* @return {!libjass.renderers.RendererSettings}
*
* @static
*/
RendererSettings.from = function (object) {
if (object === undefined || object === null) {
object = {};
}
var _a = object;
var _b = _a.fontMap;
var fontMap = _b === void 0 ? null : _b;
var _c = _a.preRenderTime;
var preRenderTime = _c === void 0 ? 5 : _c;
var _d = _a.preciseOutlines;
var preciseOutlines = _d === void 0 ? false : _d;
var _e = _a.enableSvg;
var enableSvg = _e === void 0 ? true : _e;
var _f = _a.fallbackFonts;
var fallbackFonts = _f === void 0 ? 'Arial, Helvetica, sans-serif, "Segoe UI Symbol"' : _f;
var _g = _a.useAttachedFonts;
var useAttachedFonts = _g === void 0 ? false : _g;
var result = new RendererSettings();
result.fontMap = fontMap;
result.preRenderTime = preRenderTime;
result.preciseOutlines = preciseOutlines;
result.enableSvg = enableSvg;
result.fallbackFonts = fallbackFonts;
result.useAttachedFonts = useAttachedFonts;
return result;
};
return RendererSettings;
}();
exports.RendererSettings = RendererSettings;
/**
* @param {!CSSRule} rule
* @return {boolean}
*
* @private
*/
function isFontFaceRule(rule) {
return rule.type === CSSRule.FONT_FACE_RULE;
}
}, /* 17 ./renderers/web/animation-collection */ function (exports, require) {
var map_1 = require(30);
/**
* This class represents a collection of animations. Each animation contains one or more keyframes.
* The collection can then be converted to a CSS3 representation.
*
* @param {!libjass.renderers.NullRenderer} renderer The renderer that this collection is associated with
* @param {!HTMLStyleElement} style A <style> element to insert the animation rules into
*
* @constructor
*/
var AnimationCollection = function () {
function AnimationCollection(renderer, style) {
this._style = style;
this._animationStyle = "";
this._animationDelays = new map_1.Map();
this._numAnimations = 0;
this._id = renderer.id + "-" + AnimationCollection._nextId++;
this._rate = renderer.clock.rate;
}
Object.defineProperty(AnimationCollection.prototype, "animationStyle", {
/**
* This string should be set as the "animation" CSS property of the target element.
*
* @type {string}
*/
get: function () {
return this._animationStyle;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AnimationCollection.prototype, "animationDelays", {
/**
* This array should be used to set the "animation-delay" CSS property of the target element.
*
* @type {!Array.<number>}
*/
get: function () {
return this._animationDelays;
},
enumerable: true,
configurable: true
});
/**
* Add an animation to this collection. The given keyframes together make one animation.
*
* @param {string} timingFunction One of the acceptable values for the "animation-timing-function" CSS property
* @param {!Array.<!libjass.renderers.Keyframe>} keyframes
*/
AnimationCollection.prototype.add = function (timingFunction, keyframes) {
var start = null;
var end = null;
for (var _i = 0; _i < keyframes.length; _i++) {
var keyframe = keyframes[_i];
if (start === null) {
start = keyframe.time;
}
end = keyframe.time;
}
var ruleCssText = "";
for (var _a = 0; _a < keyframes.length; _a++) {
var keyframe = keyframes[_a];
ruleCssText += " " + (100 * (end - start === 0 ? 1 : (keyframe.time - start) / (end - start))).toFixed(3) + "% {\n";
keyframe.properties.forEach(function (value, name) {
ruleCssText += " " + name + ": " + value + ";\n";
});
ruleCssText += " }\n";
}
var animationName = "animation-" + this._id + "-" + this._numAnimations++;
this._style.appendChild(document.createTextNode("@-webkit-keyframes " + animationName + " {\n" + ruleCssText + "\n}"));
this._style.appendChild(document.createTextNode("@keyframes " + animationName + " {\n" + ruleCssText + "\n}"));
if (this._animationStyle !== "") {
this._animationStyle += ",";
}
this._animationStyle += animationName + " " + ((end - start) / this._rate).toFixed(3) + "s " + timingFunction;
this._animationDelays.set(animationName, start);
};
AnimationCollection._nextId = 0;
return AnimationCollection;
}();
exports.AnimationCollection = AnimationCollection;
}, /* 18 ./renderers/web/drawing-styles */ function (exports, require) {
var parts = require(8);
/**
* This class represents an ASS drawing - a set of drawing instructions between {\p} tags.
*
* @param {number} outputScaleX
* @param {number} outputScaleY
*
* @constructor
*/
var DrawingStyles = function () {
function DrawingStyles(outputScaleX, outputScaleY) {
this._outputScaleX = outputScaleX;
this._outputScaleY = outputScaleY;
this._scale = 1;
this._baselineOffset = 0;
}
Object.defineProperty(DrawingStyles.prototype, "scale", {
/**
* @type {number}
*/
set: function (value) {
this._scale = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(DrawingStyles.prototype, "baselineOffset", {
/**
* @type {number}
*/
set: function (value) {
this._baselineOffset = value;
},
enumerable: true,
configurable: true
});
/**
* Converts this drawing to an <svg> element.
*
* @param {!libjass.parts.DrawingInstructions} drawingInstructions
* @param {!libjass.parts.Color} fillColor
* @return {!SVGSVGElement}
*/
DrawingStyles.prototype.toSVG = function (drawingInstructions, fillColor) {
var scaleFactor = Math.pow(2, this._scale - 1);
var scaleX = this._outputScaleX / scaleFactor;
var scaleY = this._outputScaleY / scaleFactor;
var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
var bboxWidth = 0;
var bboxHeight = 0;
for (var _i = 0, _a = drawingInstructions.instructions; _i < _a.length; _i++) {
var instruction = _a[_i];
if (instruction instanceof parts.drawing.MoveInstruction) {
path.pathSegList.appendItem(path.createSVGPathSegMovetoAbs(instruction.x, instruction.y + this._baselineOffset));
bboxWidth = Math.max(bboxWidth, instruction.x);
bboxHeight = Math.max(bboxHeight, instruction.y + this._baselineOffset);
} else if (instruction instanceof parts.drawing.LineInstruction) {
path.pathSegList.appendItem(path.createSVGPathSegLinetoAbs(instruction.x, instruction.y + this._baselineOffset));
bboxWidth = Math.max(bboxWidth, instruction.x);
bboxHeight = Math.max(bboxHeight, instruction.y + this._baselineOffset);
} else if (instruction instanceof parts.drawing.CubicBezierCurveInstruction) {
path.pathSegList.appendItem(path.createSVGPathSegCurvetoCubicAbs(instruction.x3, instruction.y3 + this._baselineOffset, instruction.x1, instruction.y1 + this._baselineOffset, instruction.x2, instruction.y2 + this._baselineOffset));
bboxWidth = Math.max(bboxWidth, instruction.x1, instruction.x2, instruction.x3);
bboxHeight = Math.max(bboxHeight, instruction.y1 + this._baselineOffset, instruction.y2 + this._baselineOffset, instruction.y3 + this._baselineOffset);
}
}
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("version", "1.1");
svg.width.baseVal.valueAsString = (bboxWidth * scaleX).toFixed(3) + "px";
svg.height.baseVal.valueAsString = (bboxHeight * scaleY).toFixed(3) + "px";
var g = document.createElementNS("http://www.w3.org/2000/svg", "g");
svg.appendChild(g);
g.setAttribute("transform", "scale(" + scaleX.toFixed(3) + " " + scaleY.toFixed(3) + ")");
g.appendChild(path);
path.setAttribute("fill", fillColor.toString());
return svg;
};
return DrawingStyles;
}();
exports.DrawingStyles = DrawingStyles;
}, /* 19 ./renderers/web/font-size */ function (exports, require) {
var promise_1 = require(32);
/**
* @param {string} fontFamily
* @param {number} fontSize
* @param {string} fallbackFonts
* @param {!HTMLDivElement} fontSizeElement
*
* @private
*/
function prepareFontSizeElement(fontFamily, fontSize, fallbackFonts, fontSizeElement) {
var fonts = '"' + fontFamily + '"';
if (fallbackFonts !== "") {
fonts += ", " + fallbackFonts;
}
fontSizeElement.style.fontFamily = fonts;
fontSizeElement.style.fontSize = fontSize + "px";
}
/**
* @param {string} fontFamily
* @param {number} fontSize
* @param {string} fallbackFonts
* @param {!HTMLDivElement} fontSizeElement
* @return {!Promise.<number>}
*
* @private
*/
function lineHeightForFontSize(fontFamily, fontSize, fallbackFonts, fontSizeElement) {
prepareFontSizeElement(fontFamily, fontSize, fallbackFonts, fontSizeElement);
return new promise_1.Promise(function (resolve) {
return setTimeout(function () {
return resolve(fontSizeElement.offsetHeight);
}, 1e3);
});
}
/**
* @param {string} fontFamily
* @param {number} fontSize
* @param {string} fallbackFonts
* @param {!HTMLDivElement} fontSizeElement
* @return {number}
*
* @private
*/
function lineHeightForFontSizeSync(fontFamily, fontSize, fallbackFonts, fontSizeElement) {
prepareFontSizeElement(fontFamily, fontSize, fallbackFonts, fontSizeElement);
return fontSizeElement.offsetHeight;
}
/**
* @param {number} lowerLineHeight
* @param {number} upperLineHeight
* @return {[number, number]}
*
* @private
*/
function fontMetricsFromLineHeights(lowerLineHeight, upperLineHeight) {
return [ lowerLineHeight, (360 - 180) / (upperLineHeight - lowerLineHeight) ];
}
/**
* Calculates font metrics for the given font family.
*
* @param {string} fontFamily
* @param {string} fallbackFonts
* @param {!HTMLDivElement} fontSizeElement
* @return {!Promise.<number>}
*/
function calculateFontMetrics(fontFamily, fallbackFonts, fontSizeElement) {
return lineHeightForFontSize(fontFamily, 180, fallbackFonts, fontSizeElement).then(function (lowerLineHeight) {
return lineHeightForFontSize(fontFamily, 360, fallbackFonts, fontSizeElement).then(function (upperLineHeight) {
return fontMetricsFromLineHeights(lowerLineHeight, upperLineHeight);
});
});
}
exports.calculateFontMetrics = calculateFontMetrics;
/**
* @param {number} lineHeight
* @param {number} lowerLineHeight
* @param {number} factor
* @return {number}
*
* @private
*/
function fontSizeFromMetrics(lineHeight, lowerLineHeight, factor) {
return 180 + (lineHeight - lowerLineHeight) * factor;
}
/**
* Uses linear interpolation to calculate the CSS font size that would give the specified line height for the specified font family.
*
* WARNING: If fontMetricsCache doesn't already contain a cached value for this font family, and it is not a font already installed on the user's device, then this function
* may return wrong values. To avoid this, make sure to preload the font using the {@link libjass.renderers.RendererSettings.fontMap} property when constructing the renderer.
*
* @param {string} fontFamily
* @param {number} lineHeight
* @param {string} fallbackFonts
* @param {!HTMLDivElement} fontSizeElement
* @param {!Map.<string, [number, number]>} fontMetricsCache
* @return {number}
*/
function fontSizeForLineHeight(fontFamily, lineHeight, fallbackFonts, fontSizeElement, fontMetricsCache) {
var existingMetrics = fontMetricsCache.get(fontFamily);
if (existingMetrics === undefined) {
var lowerLineHeight_1 = lineHeightForFontSizeSync(fontFamily, 180, fallbackFonts, fontSizeElement);
var upperLineHeight = lineHeightForFontSizeSync(fontFamily, 360, fallbackFonts, fontSizeElement);
fontMetricsCache.set(fontFamily, existingMetrics = fontMetricsFromLineHeights(lowerLineHeight_1, upperLineHeight));
}
var lowerLineHeight = existingMetrics[0];
var factor = existingMetrics[1];
return fontSizeFromMetrics(lineHeight, lowerLineHeight, factor);
}
exports.fontSizeForLineHeight = fontSizeForLineHeight;
}, /* 20 ./renderers/web/keyframe */ function (exports) {
/**
* This class represents a single keyframe. It has a list of CSS properties (names and values) associated with a point in time. Multiple keyframes make up an animation.
*
* @param {number} time
* @param {!Map.<string, string>} properties
*
* @constructor
*/
var Keyframe = function () {
function Keyframe(time, properties) {
this._time = time;
this._properties = properties;
}
Object.defineProperty(Keyframe.prototype, "time", {
/**
* @type {number}
*/
get: function () {
return this._time;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Keyframe.prototype, "properties", {
/**
* @type {!Map.<string, string>}
*/
get: function () {
return this._properties;
},
enumerable: true,
configurable: true
});
return Keyframe;
}();
exports.Keyframe = Keyframe;
}, /* 21 ./renderers/web/renderer */ function (exports, require) {
var __extends = require(34).__extends;
var animation_collection_1 = require(17);
var drawing_styles_1 = require(18);
var font_size_1 = require(19);
var keyframe_1 = require(20);
var span_styles_1 = require(22);
var base_1 = require(10);
var null_1 = require(15);
var ttf_1 = require(6);
var parts = require(8);
var settings_1 = require(23);
var attachment_1 = require(25);
var misc_1 = require(27);
var mixin_1 = require(31);
var map_1 = require(30);
var promise_1 = require(32);
var fontSrcUrlRegex = /^(url|local)\(["']?(.+?)["']?\)$/;
/**
* A renderer implementation that draws subtitles to the given <div>
*
* After the renderer fires its ready event, {@link libjass.renderers.WebRenderer.resize} must be called to initialize its size before starting the clock.
*
* @param {!libjass.ASS} ass
* @param {!libjass.renderers.Clock} clock
* @param {!HTMLDivElement} libjassSubsWrapper Subtitles will be rendered to this <div>
* @param {!libjass.renderers.RendererSettings} settings
*
* @constructor
* @extends {libjass.renderers.NullRenderer}
* @implements {libjass.renderers.EventSource.<string>}
* @memberOf libjass.renderers
*/
var WebRenderer = function (_super) {
__extends(WebRenderer, _super);
function WebRenderer(ass, clock, libjassSubsWrapper, settings) {
var _this = this;
_super.call(this, ass, clock, function () {
if (!(libjassSubsWrapper instanceof HTMLDivElement)) {
var temp = settings;
settings = libjassSubsWrapper;
libjassSubsWrapper = temp;
console.warn("WebRenderer's constructor now takes libjassSubsWrapper as the third parameter and settings as the fourth parameter. Please update the caller.");
}
return settings;
}());
this._libjassSubsWrapper = libjassSubsWrapper;
this._layerWrappers = [];
this._layerAlignmentWrappers = [];
this._fontMetricsCache = new map_1.Map();
this._currentSubs = new map_1.Map();
this._preRenderedSubs = new map_1.Map();
// EventSource members
/**
* @type {!Map.<T, !Array.<Function>>}
*/
this._eventListeners = new map_1.Map();
this._libjassSubsWrapper.classList.add("libjass-wrapper");
this._subsWrapper = document.createElement("div");
this._libjassSubsWrapper.appendChild(this._subsWrapper);
this._subsWrapper.className = "libjass-subs";
this._fontSizeElement = document.createElement("div");
this._libjassSubsWrapper.appendChild(this._fontSizeElement);
this._fontSizeElement.className = "libjass-font-measure";
this._fontSizeElement.appendChild(document.createTextNode("M"));
// Preload fonts
if (settings_1.debugMode) {
console.log("Preloading fonts...");
}
var preloadFontPromises = [];
var fontFetchPromisesCache = new map_1.Map();
var fontMap = this.settings.fontMap === null ? new map_1.Map() : this.settings.fontMap;
var attachedFontsMap = new map_1.Map();
if (this.settings.useAttachedFonts) {
ass.attachments.forEach(function (attachment) {
if (attachment.type !== attachment_1.AttachmentType.Font) {
return;
}
var ttfNames = null;
try {
ttfNames = ttf_1.getTtfNames(attachment);
} catch (ex) {
console.error(ex);
return;
}
var attachmentUrl = "data:application/x-font-ttf;base64," + attachment.contents;
ttfNames.forEach(function (name) {
var correspondingFontMapEntry = fontMap.get(name);
if (correspondingFontMapEntry !== undefined) {
// Also defined in fontMap.
if (typeof correspondingFontMapEntry !== "string") {
// Entry in fontMap is an array. Append this URL to it.
correspondingFontMapEntry.push(attachmentUrl);
} else {
/* The entry in fontMap is a string. Don't append this URL to it. Instead, put it in attachedFontsMap now
* and it'll be merged with the entry from fontMap later. If it was added here, and later the string needed
* to be split on commas, then the commas in the data URI would break the result.
*/
var existingList = attachedFontsMap.get(name);
if (existingList === undefined) {
attachedFontsMap.set(name, existingList = []);
}
existingList.push(attachmentUrl);
}
} else {
// Not defined in fontMap. Add it there.
fontMap.set(name, [ attachmentUrl ]);
}
});
});
}
fontMap.forEach(function (srcs, fontFamily) {
var fontFamilyMetricsPromise;
if (global.document.fonts && global.document.fonts.add) {
// value should be string. If it's string[], combine it into string
var source = typeof srcs === "string" ? srcs : srcs.map(function (src) {
return src.match(fontSrcUrlRegex) !== null ? src : 'url("' + src + '")';
}).join(", ");
var attachedFontUrls = attachedFontsMap.get(fontFamily);
if (attachedFontUrls !== undefined) {
for (var _i = 0; _i < attachedFontUrls.length; _i++) {
var url = attachedFontUrls[_i];
source += ', url("' + url + '")';
}
}
var existingFontFaces = [];
global.document.fonts.forEach(function (fontFace) {
if (fontFace.family === fontFamily || fontFace.family === '"' + fontFamily + '"') {
existingFontFaces.push(fontFace);
}
});
var fontFetchPromise;
if (existingFontFaces.length === 0) {
var fontFace = new FontFace(fontFamily, source);
var quotedFontFace = new FontFace('"' + fontFamily + '"', source);
global.document.fonts.add(fontFace);
global.document.fonts.add(quotedFontFace);
fontFetchPromise = promise_1.any([ fontFace.load(), quotedFontFace.load() ]);
} else {
fontFetchPromise = promise_1.any(existingFontFaces.map(function (fontFace) {
return fontFace.load();
}));
}
fontFamilyMetricsPromise = _this._calculateFontMetricsAfterFetch(fontFamily, fontFetchPromise.catch(function (reason) {
console.warn("Fetching fonts for " + fontFamily + " at " + source + " failed: %o", reason);
return null;
}));
} else {
// value should be string[]. If it's string, split it into string[]
var urls = (typeof srcs === "string" ? srcs.split(/,/) : srcs).map(function (url) {
return url.trim();
}).map(function (url) {
var match = url.match(fontSrcUrlRegex);
if (match === null) {
// A URL
return url;
}
if (match[1] === "local") {
// A local() URL. Don't fetch it.
return null;
}
// A url() URL. Extract the raw URL.
return match[2];
}).filter(function (url) {
return url !== null;
});
var attachedFontUrls = attachedFontsMap.get(fontFamily);
if (attachedFontUrls !== undefined) {
urls = urls.concat(attachedFontUrls);
}
var thisFontFamilysFetchPromises = urls.map(function (url) {
var fontFetchPromise = fontFetchPromisesCache.get(url);
if (fontFetchPromise === undefined) {
fontFetchPromise = new promise_1.Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", function () {
if (settings_1.debugMode) {
console.log("Preloaded " + url + ".");
}
resolve(null);
});
xhr.addEventListener("error", function (err) {
reject(err);
});
xhr.open("GET", url, true);
xhr.send();
});
fontFetchPromisesCache.set(url, fontFetchPromise);
}
return fontFetchPromise;
});
var allFontsFetchedPromise = thisFontFamilysFetchPromises.length === 0 ? promise_1.Promise.resolve(null) : promise_1.first(thisFontFamilysFetchPromises).catch(function (reason) {
console.warn("Fetching fonts for " + fontFamily + " at " + urls.join(", ") + " failed: %o", reason);
return null;
});
fontFamilyMetricsPromise = _this._calculateFontMetricsAfterFetch(fontFamily, allFontsFetchedPromise);
}
preloadFontPromises.push(fontFamilyMetricsPromise.then(function (metrics) {
return _this._fontMetricsCache.set(fontFamily, metrics);
}));
});
promise_1.Promise.all(preloadFontPromises).then(function () {
if (settings_1.debugMode) {
console.log("All fonts have been preloaded.");
}
_this._ready();
});
}
Object.defineProperty(WebRenderer.prototype, "libjassSubsWrapper", {
/**
* @type {!HTMLDivElement}
*/
get: function () {
return this._libjassSubsWrapper;
},
enumerable: true,
configurable: true
});
/**
* Resize the subtitles to the given new dimensions.
*
* @param {number} width
* @param {number} height
* @param {number=0} left
* @param {number=0} top
*/
WebRenderer.prototype.resize = function (width, height, left, top) {
if (left === void 0) {
left = 0;
}
if (top === void 0) {
top = 0;
}
this._removeAllSubs();
this._subsWrapper.style.width = width.toFixed(3) + "px";
this._subsWrapper.style.height = height.toFixed(3) + "px";
this._subsWrapper.style.left = left.toFixed(3) + "px";
this._subsWrapper.style.top = top.toFixed(3) + "px";
this._subsWrapperWidth = width;
this._scaleX = width / this.ass.properties.resolutionX;
this._scaleY = height / this.ass.properties.resolutionY;
// Any dialogues which have been pre-rendered will need to be pre-rendered again.
this._preRenderedSubs.clear();
// this.currentTime will be -1 if resize() is called before the clock begins playing for the first time. In this situation, there is no need to force a redraw.
if (this.clock.currentTime !== -1) {
this._onClockTick();
}
};
/**
* The magic happens here. The subtitle div is rendered and stored. Call {@link libjass.renderers.WebRenderer.draw} to get a clone of the div to display.
*
* @param {!libjass.Dialogue} dialogue
* @return {PreRenderedSub}
*/
WebRenderer.prototype.preRender = function (dialogue) {
var _this = this;
var alreadyPreRenderedSub = this._preRenderedSubs.get(dialogue.id);
if (alreadyPreRenderedSub) {
return alreadyPreRenderedSub;
}
var currentTimeRelativeToDialogueStart = this.clock.currentTime - dialogue.start;
if (dialogue.containsTransformTag && currentTimeRelativeToDialogueStart < 0) {
// draw() expects this function to always return non-null, but it only calls this function when currentTimeRelativeToDialogueStart would be >= 0
return null;
}
var sub = document.createElement("div");
sub.style.marginLeft = (this._scaleX * dialogue.style.marginLeft).toFixed(3) + "px";
sub.style.marginRight = (this._scaleX * dialogue.style.marginRight).toFixed(3) + "px";
sub.style.marginTop = sub.style.marginBottom = (this._scaleY * dialogue.style.marginVertical).toFixed(3) + "px";
sub.style.minWidth = (this._subsWrapperWidth - this._scaleX * (dialogue.style.marginLeft + dialogue.style.marginRight)).toFixed(3) + "px";
var dialogueAnimationStylesElement = document.createElement("style");
dialogueAnimationStylesElement.id = "libjass-animation-styles-" + this.id + "-" + dialogue.id;
dialogueAnimationStylesElement.type = "text/css";
var dialogueAnimationCollection = new animation_collection_1.AnimationCollection(this, dialogueAnimationStylesElement);
var svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svgElement.setAttribute("version", "1.1");
svgElement.setAttribute("class", "libjass-filters");
svgElement.width.baseVal.valueAsString = "0";
svgElement.height.baseVal.valueAsString = "0";
var svgDefsElement = document.createElementNS("http://www.w3.org/2000/svg", "defs");
svgElement.appendChild(svgDefsElement);
var currentSpan = null;
var currentSpanStyles = new span_styles_1.SpanStyles(this, dialogue, this._scaleX, this._scaleY, this.settings, this._fontSizeElement, svgDefsElement, this._fontMetricsCache);
var currentAnimationCollection = null;
var previousAddNewLine = false;
// If two or more \N's are encountered in sequence, then all but the first will be created using currentSpanStyles.makeNewLine() instead
var startNewSpan = function (addNewLine) {
if (currentSpan !== null && currentSpan.hasChildNodes()) {
sub.appendChild(currentSpanStyles.setStylesOnSpan(currentSpan, currentAnimationCollection));
}
if (currentAnimationCollection !== null) {
currentAnimationCollection.animationDelays.forEach(function (delay, name) {
return dialogueAnimationCollection.animationDelays.set(name, delay);
});
}
if (addNewLine) {
if (previousAddNewLine) {
sub.appendChild(currentSpanStyles.makeNewLine());
} else {
sub.appendChild(document.createElement("br"));
}
}
currentSpan = document.createElement("span");
currentAnimationCollection = new animation_collection_1.AnimationCollection(_this, dialogueAnimationStylesElement);
previousAddNewLine = addNewLine;
};
startNewSpan(false);
var currentDrawingStyles = new drawing_styles_1.DrawingStyles(this._scaleX, this._scaleY);
var wrappingStyle = this.ass.properties.wrappingStyle;
var karaokeTimesAccumulator = 0;
for (var _i = 0, _a = dialogue.parts; _i < _a.length; _i++) {
var part = _a[_i];
if (part instanceof parts.Italic) {
currentSpanStyles.italic = part.value;
} else if (part instanceof parts.Bold) {
currentSpanStyles.bold = part.value;
} else if (part instanceof parts.Underline) {
currentSpanStyles.underline = part.value;
} else if (part instanceof parts.StrikeThrough) {
currentSpanStyles.strikeThrough = part.value;
} else if (part instanceof parts.Border) {
currentSpanStyles.outlineWidth = part.value;
currentSpanStyles.outlineHeight = part.value;
} else if (part instanceof parts.BorderX) {
currentSpanStyles.outlineWidth = part.value;
} else if (part instanceof parts.BorderY) {
currentSpanStyles.outlineHeight = part.value;
} else if (part instanceof parts.Shadow) {
currentSpanStyles.shadowDepthX = part.value;
currentSpanStyles.shadowDepthY = part.value;
} else if (part instanceof parts.ShadowX) {
currentSpanStyles.shadowDepthX = part.value;
} else if (part instanceof parts.ShadowY) {
currentSpanStyles.shadowDepthY = part.value;
} else if (part instanceof parts.Blur) {
currentSpanStyles.blur = part.value;
} else if (part instanceof parts.GaussianBlur) {
currentSpanStyles.gaussianBlur = part.value;
} else if (part instanceof parts.FontName) {
currentSpanStyles.fontName = part.value;
} else if (part instanceof parts.FontSize) {
currentSpanStyles.fontSize = part.value;
} else if (part instanceof parts.FontSizePlus) {
currentSpanStyles.fontSize += part.value;
} else if (part instanceof parts.FontSizeMinus) {
currentSpanStyles.fontSize -= part.value;
} else if (part instanceof parts.FontScaleX) {
currentSpanStyles.fontScaleX = part.value;
} else if (part instanceof parts.FontScaleY) {
currentSpanStyles.fontScaleY = part.value;
} else if (part instanceof parts.LetterSpacing) {
currentSpanStyles.letterSpacing = part.value;
} else if (part instanceof parts.RotateX) {
currentSpanStyles.rotationX = part.value;
} else if (part instanceof parts.RotateY) {
currentSpanStyles.rotationY = part.value;
} else if (part instanceof parts.RotateZ) {
currentSpanStyles.rotationZ = part.value;
} else if (part instanceof parts.SkewX) {
currentSpanStyles.skewX = part.value;
} else if (part instanceof parts.SkewY) {
currentSpanStyles.skewY = part.value;
} else if (part instanceof parts.PrimaryColor) {
currentSpanStyles.primaryColor = part.value;
} else if (part instanceof parts.SecondaryColor) {
currentSpanStyles.secondaryColor = part.value;
} else if (part instanceof parts.OutlineColor) {
currentSpanStyles.outlineColor = part.value;
} else if (part instanceof parts.ShadowColor) {
currentSpanStyles.shadowColor = part.value;
} else if (part instanceof parts.Alpha) {
currentSpanStyles.primaryAlpha = part.value;
currentSpanStyles.secondaryAlpha = part.value;
currentSpanStyles.outlineAlpha = part.value;
currentSpanStyles.shadowAlpha = part.value;
} else if (part instanceof parts.PrimaryAlpha) {
currentSpanStyles.primaryAlpha = part.value;
} else if (part instanceof parts.SecondaryAlpha) {
currentSpanStyles.secondaryAlpha = part.value;
} else if (part instanceof parts.OutlineAlpha) {
currentSpanStyles.outlineAlpha = part.value;
} else if (part instanceof parts.ShadowAlpha) {
currentSpanStyles.shadowAlpha = part.value;
} else if (part instanceof parts.Alignment) {} else if (part instanceof parts.ColorKaraoke) {
startNewSpan(false);
currentAnimationCollection.add("step-end", [ new keyframe_1.Keyframe(0, new map_1.Map([ [ "color", currentSpanStyles.secondaryColor.withAlpha(currentSpanStyles.secondaryAlpha).toString() ] ])), new keyframe_1.Keyframe(karaokeTimesAccumulator, new map_1.Map([ [ "color", currentSpanStyles.primaryColor.withAlpha(currentSpanStyles.primaryAlpha).toString() ] ])) ]);
karaokeTimesAccumulator += part.duration;
} else if (part instanceof parts.WrappingStyle) {
wrappingStyle = part.value;
} else if (part instanceof parts.Reset) {
currentSpanStyles.reset(this.ass.styles.get(part.value));
} else if (part instanceof parts.Position) {
sub.style.position = "absolute";
sub.style.left = (this._scaleX * part.x).toFixed(3) + "px";
sub.style.top = (this._scaleY * part.y).toFixed(3) + "px";
} else if (part instanceof parts.Move) {
sub.style.position = "absolute";
dialogueAnimationCollection.add("linear", [ new keyframe_1.Keyframe(0, new map_1.Map([ [ "left", (this._scaleX * part.x1).toFixed(3) + "px" ], [ "top", (this._scaleY * part.y1).toFixed(3) + "px" ] ])), new keyframe_1.Keyframe(part.t1, new map_1.Map([ [ "left", (this._scaleX * part.x1).toFixed(3) + "px" ], [ "top", (this._scaleY * part.y1).toFixed(3) + "px" ] ])), new keyframe_1.Keyframe(part.t2, new map_1.Map([ [ "left", (this._scaleX * part.x2).toFixed(3) + "px" ], [ "top", (this._scaleY * part.y2).toFixed(3) + "px" ] ])), new keyframe_1.Keyframe(dialogue.end - dialogue.start, new map_1.Map([ [ "left", (this._scaleX * part.x2).toFixed(3) + "px" ], [ "top", (this._scaleY * part.y2).toFixed(3) + "px" ] ])) ]);
} else if (part instanceof parts.Fade) {
dialogueAnimationCollection.add("linear", [ new keyframe_1.Keyframe(0, new map_1.Map([ [ "opacity", "0" ] ])), new keyframe_1.Keyframe(part.start, new map_1.Map([ [ "opacity", "1" ] ])), new keyframe_1.Keyframe(dialogue.end - dialogue.start - part.end, new map_1.Map([ [ "opacity", "1" ] ])), new keyframe_1.Keyframe(dialogue.end - dialogue.start, new map_1.Map([ [ "opacity", "0" ] ])) ]);
} else if (part instanceof parts.ComplexFade) {
dialogueAnimationCollection.add("linear", [ new keyframe_1.Keyframe(0, new map_1.Map([ [ "opacity", part.a1.toFixed(3) ] ])), new keyframe_1.Keyframe(part.t1, new map_1.Map([ [ "opacity", part.a1.toFixed(3) ] ])), new keyframe_1.Keyframe(part.t2, new map_1.Map([ [ "opacity", part.a2.toFixed(3) ] ])), new keyframe_1.Keyframe(part.t3, new map_1.Map([ [ "opacity", part.a2.toFixed(3) ] ])), new keyframe_1.Keyframe(part.t4, new map_1.Map([ [ "opacity", part.a3.toFixed(3) ] ])), new keyframe_1.Keyframe(dialogue.end - dialogue.start, new map_1.Map([ [ "opacity", part.a3.toFixed(3) ] ])) ]);
} else if (part instanceof parts.Transform) {
var progression = currentTimeRelativeToDialogueStart <= part.start ? 0 : currentTimeRelativeToDialogueStart >= part.end ? 1 : Math.pow((currentTimeRelativeToDialogueStart - part.start) / (part.end - part.start), part.accel);
for (var _b = 0, _c = part.tags; _b < _c.length; _b++) {
var tag = _c[_b];
if (tag instanceof parts.Border) {
currentSpanStyles.outlineWidth += progression * (tag.value - currentSpanStyles.outlineWidth);
currentSpanStyles.outlineHeight += progression * (tag.value - currentSpanStyles.outlineHeight);
} else if (tag instanceof parts.BorderX) {
currentSpanStyles.outlineWidth += progression * (tag.value - currentSpanStyles.outlineWidth);
} else if (tag instanceof parts.BorderY) {
currentSpanStyles.outlineHeight += progression * (tag.value - currentSpanStyles.outlineHeight);
} else if (tag instanceof parts.Shadow) {
currentSpanStyles.shadowDepthX += progression * (tag.value - currentSpanStyles.shadowDepthX);
currentSpanStyles.shadowDepthY += progression * (tag.value - currentSpanStyles.shadowDepthY);
} else if (tag instanceof parts.ShadowX) {
currentSpanStyles.shadowDepthX += progression * (tag.value - currentSpanStyles.shadowDepthX);
} else if (tag instanceof parts.ShadowY) {
currentSpanStyles.shadowDepthY += progression * (tag.value - currentSpanStyles.shadowDepthY);
} else if (tag instanceof parts.Blur) {
currentSpanStyles.blur += progression * (tag.value - currentSpanStyles.blur);
} else if (tag instanceof parts.GaussianBlur) {
currentSpanStyles.gaussianBlur += progression * (tag.value - currentSpanStyles.gaussianBlur);
} else if (tag instanceof parts.FontSize) {
currentSpanStyles.fontSize += progression * (tag.value - currentSpanStyles.fontSize);
} else if (tag instanceof parts.FontSizePlus) {
currentSpanStyles.fontSize += progression * tag.value;
} else if (tag instanceof parts.FontSizeMinus) {
currentSpanStyles.fontSize -= progression * tag.value;
} else if (tag instanceof parts.FontScaleX) {
currentSpanStyles.fontScaleX += progression * (tag.value - currentSpanStyles.fontScaleX);
} else if (tag instanceof parts.FontScaleY) {
currentSpanStyles.fontScaleY += progression * (tag.value - currentSpanStyles.fontScaleY);
} else if (tag instanceof parts.LetterSpacing) {
currentSpanStyles.letterSpacing += progression * (tag.value - currentSpanStyles.letterSpacing);
} else if (tag instanceof parts.RotateX) {
currentSpanStyles.rotationX += progression * (tag.value - currentSpanStyles.rotationX);
} else if (tag instanceof parts.RotateY) {
currentSpanStyles.rotationY += progression * (tag.value - currentSpanStyles.rotationY);
} else if (tag instanceof parts.RotateZ) {
currentSpanStyles.rotationZ += progression * (tag.value - currentSpanStyles.rotationZ);
} else if (tag instanceof parts.SkewX) {
currentSpanStyles.skewX += progression * (tag.value - currentSpanStyles.skewX);
} else if (tag instanceof parts.SkewY) {
currentSpanStyles.skewY += progression * (tag.value - currentSpanStyles.skewY);
} else if (tag instanceof parts.PrimaryColor) {
currentSpanStyles.primaryColor = currentSpanStyles.primaryColor.interpolate(tag.value, progression);
} else if (tag instanceof parts.SecondaryColor) {
currentSpanStyles.secondaryColor = currentSpanStyles.secondaryColor.interpolate(tag.value, progression);
} else if (tag instanceof parts.OutlineColor) {
currentSpanStyles.outlineColor = currentSpanStyles.outlineColor.interpolate(tag.value, progression);
} else if (tag instanceof parts.ShadowColor) {
currentSpanStyles.shadowColor = currentSpanStyles.shadowColor.interpolate(tag.value, progression);
} else if (tag instanceof parts.Alpha) {
currentSpanStyles.primaryAlpha += progression * (tag.value - currentSpanStyles.primaryAlpha);
currentSpanStyles.secondaryAlpha += progression * (tag.value - currentSpanStyles.secondaryAlpha);
currentSpanStyles.outlineAlpha += progression * (tag.value - currentSpanStyles.outlineAlpha);
currentSpanStyles.shadowAlpha += progression * (tag.value - currentSpanStyles.shadowAlpha);
} else if (tag instanceof parts.PrimaryAlpha) {
currentSpanStyles.primaryAlpha += progression * (tag.value - currentSpanStyles.primaryAlpha);
} else if (tag instanceof parts.SecondaryAlpha) {
currentSpanStyles.secondaryAlpha += progression * (tag.value - currentSpanStyles.secondaryAlpha);
} else if (tag instanceof parts.OutlineAlpha) {
currentSpanStyles.outlineAlpha += progression * (tag.value - currentSpanStyles.outlineAlpha);
} else if (tag instanceof parts.ShadowAlpha) {
currentSpanStyles.shadowAlpha += progression * (tag.value - currentSpanStyles.shadowAlpha);
}
}
} else if (part instanceof parts.DrawingMode) {
if (part.scale !== 0) {
currentDrawingStyles.scale = part.scale;
}
} else if (part instanceof parts.DrawingBaselineOffset) {
currentDrawingStyles.baselineOffset = part.value;
} else if (part instanceof parts.DrawingInstructions) {
currentSpan.appendChild(currentDrawingStyles.toSVG(part, currentSpanStyles.primaryColor.withAlpha(currentSpanStyles.primaryAlpha)));
startNewSpan(false);
} else if (part instanceof parts.Text) {
currentSpan.appendChild(document.createTextNode(part.value + ""));
startNewSpan(false);
} else if (settings_1.debugMode && part instanceof parts.Comment) {
currentSpan.appendChild(document.createTextNode(part.value));
startNewSpan(false);
} else if (part instanceof parts.NewLine) {
startNewSpan(true);
}
}
for (var _d = 0, _e = dialogue.parts; _d < _e.length; _d++) {
var part = _e[_d];
if (part instanceof parts.Position || part instanceof parts.Move) {
var transformOrigin = WebRenderer._transformOrigins[dialogue.alignment];
var divTransformStyle = "translate(" + -transformOrigin[0] + "%, " + -transformOrigin[1] + "%) translate(-" + sub.style.marginLeft + ", -" + sub.style.marginTop + ")";
var transformOriginString = transformOrigin[0] + "% " + transformOrigin[1] + "%";
sub.style.webkitTransform = divTransformStyle;
sub.style.webkitTransformOrigin = transformOriginString;
sub.style.transform = divTransformStyle;
sub.style.transformOrigin = transformOriginString;
break;
}
}
switch (wrappingStyle) {
case misc_1.WrappingStyle.EndOfLineWrapping:
sub.style.whiteSpace = "pre-wrap";
break;
case misc_1.WrappingStyle.NoLineWrapping:
sub.style.whiteSpace = "pre";
break;
case misc_1.WrappingStyle.SmartWrappingWithWiderTopLine:
case misc_1.WrappingStyle.SmartWrappingWithWiderBottomLine:
/* Not supported. Treat the same as EndOfLineWrapping */
sub.style.whiteSpace = "pre-wrap";
break;
}
if (sub.style.position !== "") {
// Explicitly set text alignment on absolutely-positioned subs because they'll go in a .an0 <div> and so won't get alignment CSS text-align.
switch (dialogue.alignment) {
case 1:
case 4:
case 7:
sub.style.textAlign = "left";
break;
case 2:
case 5:
case 8:
sub.style.textAlign = "center";
break;
case 3:
case 6:
case 9:
sub.style.textAlign = "right";
break;
}
}
sub.style.webkitAnimation = dialogueAnimationCollection.animationStyle;
sub.style.animation = dialogueAnimationCollection.animationStyle;
sub.setAttribute("data-dialogue-id", this.id + "-" + dialogue.id);
if (dialogueAnimationStylesElement.textContent !== "") {
sub.appendChild(dialogueAnimationStylesElement);
}
if (svgDefsElement.hasChildNodes()) {
sub.appendChild(svgElement);
}
var result = {
sub: sub,
animationDelays: dialogueAnimationCollection.animationDelays
};
if (!dialogue.containsTransformTag) {
this._preRenderedSubs.set(dialogue.id, result);
}
return result;
};
/**
* Returns the subtitle div for display. The {@link libjass.renderers.Clock.currentTime} of the {@link libjass.renderers.NullRenderer.clock} is used to shift the
* animations appropriately, so that at the time the div is inserted into the DOM and the animations begin, they are in sync with the clock time.
*
* @param {!libjass.Dialogue} dialogue
*/
WebRenderer.prototype.draw = function (dialogue) {
var _this = this;
if (this._currentSubs.has(dialogue) && !dialogue.containsTransformTag) {
return;
}
if (settings_1.debugMode) {
console.log(dialogue.toString());
}
var preRenderedSub = this._preRenderedSubs.get(dialogue.id);
if (preRenderedSub === undefined) {
preRenderedSub = this.preRender(dialogue);
if (settings_1.debugMode) {
console.log(dialogue.toString());
}
}
var result = preRenderedSub.sub.cloneNode(true);
var applyAnimationDelays = function (node) {
var animationNames = node.style.animationName || node.style.webkitAnimationName;
if (animationNames !== undefined && animationNames !== "") {
var animationDelays = animationNames.split(",").map(function (name) {
name = name.trim();
var delay = preRenderedSub.animationDelays.get(name);
return ((delay + dialogue.start - _this.clock.currentTime) / _this.clock.rate).toFixed(3) + "s";
}).join(", ");
node.style.webkitAnimationDelay = animationDelays;
node.style.animationDelay = animationDelays;
}
};
applyAnimationDelays(result);
var animatedDescendants = result.querySelectorAll('[style*="animation:"]');
for (var i = 0; i < animatedDescendants.length; i++) {
applyAnimationDelays(animatedDescendants[i]);
}
var layer = dialogue.layer;
var alignment = result.style.position === "absolute" ? 0 : dialogue.alignment;
// Alignment 0 is for absolutely-positioned subs
// Create the layer wrapper div and the alignment div inside it if not already created
if (this._layerWrappers[layer] === undefined) {
var layerWrapper = document.createElement("div");
layerWrapper.className = "layer layer" + layer;
// Find the next greater layer div and insert this div before that one
var insertBeforeElement = null;
for (var insertBeforeLayer = layer + 1; insertBeforeLayer < this._layerWrappers.length && insertBeforeElement === null; insertBeforeLayer++) {
if (this._layerWrappers[insertBeforeLayer] !== undefined) {
insertBeforeElement = this._layerWrappers[insertBeforeLayer];
}
}
this._subsWrapper.insertBefore(layerWrapper, insertBeforeElement);
this._layerWrappers[layer] = layerWrapper;
this._layerAlignmentWrappers[layer] = [];
}
if (this._layerAlignmentWrappers[layer][alignment] === undefined) {
var layerAlignmentWrapper = document.createElement("div");
layerAlignmentWrapper.className = "an an" + alignment;
// Find the next greater layer,alignment div and insert this div before that one
var layerWrapper = this._layerWrappers[layer];
var insertBeforeElement = null;
for (var insertBeforeAlignment = alignment + 1; insertBeforeAlignment < this._layerAlignmentWrappers[layer].length && insertBeforeElement === null; insertBeforeAlignment++) {
if (this._layerAlignmentWrappers[layer][insertBeforeAlignment] !== undefined) {
insertBeforeElement = this._layerAlignmentWrappers[layer][insertBeforeAlignment];
}
}
layerWrapper.insertBefore(layerAlignmentWrapper, insertBeforeElement);
this._layerAlignmentWrappers[layer][alignment] = layerAlignmentWrapper;
}
this._layerAlignmentWrappers[layer][alignment].appendChild(result);
// Workaround for IE
var dialogueAnimationStylesElement = result.getElementsByTagName("style")[0];
if (dialogueAnimationStylesElement !== undefined) {
var sheet = dialogueAnimationStylesElement.sheet;
if (sheet.cssRules.length === 0) {
sheet.cssText = dialogueAnimationStylesElement.textContent;
}
}
this._currentSubs.set(dialogue, result);
};
WebRenderer.prototype._onClockPlay = function () {
_super.prototype._onClockPlay.call(this);
this._removeAllSubs();
this._subsWrapper.style.display = "";
this._subsWrapper.classList.remove("paused");
};
WebRenderer.prototype._onClockTick = function () {
// Remove dialogues that should be removed before adding new ones via super._onClockTick()
var _this = this;
var currentTime = this.clock.currentTime;
this._currentSubs.forEach(function (sub, dialogue) {
if (dialogue.start > currentTime || dialogue.end < currentTime || dialogue.containsTransformTag) {
_this._currentSubs.delete(dialogue);
_this._removeSub(sub);
}
});
_super.prototype._onClockTick.call(this);
};
WebRenderer.prototype._onClockPause = function () {
_super.prototype._onClockPause.call(this);
this._subsWrapper.classList.add("paused");
};
WebRenderer.prototype._onClockStop = function () {
_super.prototype._onClockStop.call(this);
this._subsWrapper.style.display = "none";
};
WebRenderer.prototype._onClockRateChange = function () {
_super.prototype._onClockRateChange.call(this);
// Any dialogues which have been pre-rendered will need to be pre-rendered again.
this._preRenderedSubs.clear();
};
WebRenderer.prototype._ready = function () {
this._dispatchEvent("ready", []);
};
/**
* @param {string} fontFamily
* @param {!Promise.<*>} fontFetchPromise
* @return {!Promise.<[number, number]>}
*
* @private
*/
WebRenderer.prototype._calculateFontMetricsAfterFetch = function (fontFamily, fontFetchPromise) {
var _this = this;
return fontFetchPromise.then(function () {
var fontSizeElement = _this._fontSizeElement.cloneNode(true);
_this._libjassSubsWrapper.appendChild(fontSizeElement);
return promise_1.lastly(font_size_1.calculateFontMetrics(fontFamily, _this.settings.fallbackFonts, fontSizeElement), function () {
_this._libjassSubsWrapper.removeChild(fontSizeElement);
});
});
};
/**
* @param {!HTMLDivElement} sub
*
* @private
*/
WebRenderer.prototype._removeSub = function (sub) {
sub.parentNode.removeChild(sub);
};
WebRenderer.prototype._removeAllSubs = function () {
var _this = this;
this._currentSubs.forEach(function (sub) {
return _this._removeSub(sub);
});
this._currentSubs.clear();
};
WebRenderer._transformOrigins = [ null, [ 0, 100 ], [ 50, 100 ], [ 100, 100 ], [ 0, 50 ], [ 50, 50 ], [ 100, 50 ], [ 0, 0 ], [ 50, 0 ], [ 100, 0 ] ];
return WebRenderer;
}(null_1.NullRenderer);
exports.WebRenderer = WebRenderer;
mixin_1.mixin(WebRenderer, [ base_1.EventSource ]);
}, /* 22 ./renderers/web/span-styles */ function (exports, require) {
var font_size_1 = require(19);
/**
* This class represents the style attribute of a span.
* As a Dialogue's div is rendered, individual parts are added to span's, and this class is used to maintain the style attribute of those.
*
* @param {!libjass.renderers.NullRenderer} renderer The renderer that this set of styles is associated with
* @param {!libjass.Dialogue} dialogue The Dialogue that this set of styles is associated with
* @param {number} scaleX The horizontal scaling of the subtitles
* @param {number} scaleY The vertical scaling of the subtitles
* @param {!libjass.renderers.RendererSettings} settings The renderer settings
* @param {!HTMLDivElement} fontSizeElement A <div> element to measure font sizes with
* @param {!SVGDefsElement} svgDefsElement An SVG <defs> element to append filter definitions to
* @param {!Map<string, [number, number]>} fontMetricsCache Font metrics cache
*
* @constructor
*/
var SpanStyles = function () {
function SpanStyles(renderer, dialogue, scaleX, scaleY, settings, fontSizeElement, svgDefsElement, fontMetricsCache) {
this._scaleX = scaleX;
this._scaleY = scaleY;
this._settings = settings;
this._fontSizeElement = fontSizeElement;
this._svgDefsElement = svgDefsElement;
this._fontMetricsCache = fontMetricsCache;
this._nextFilterId = 0;
this._id = renderer.id + "-" + dialogue.id;
this._defaultStyle = dialogue.style;
this.reset(null);
}
/**
* Resets the styles to the defaults provided by the argument.
*
* @param {libjass.Style} newStyle The new defaults to reset the style to. If null, the styles are reset to the default style of the Dialogue.
*/
SpanStyles.prototype.reset = function (newStyle) {
if (newStyle === undefined || newStyle === null) {
newStyle = this._defaultStyle;
}
this.italic = newStyle.italic;
this.bold = newStyle.bold;
this.underline = newStyle.underline;
this.strikeThrough = newStyle.strikeThrough;
this.outlineWidth = newStyle.outlineThickness;
this.outlineHeight = newStyle.outlineThickness;
this.shadowDepthX = newStyle.shadowDepth;
this.shadowDepthY = newStyle.shadowDepth;
this.fontName = newStyle.fontName;
this.fontSize = newStyle.fontSize;
this.fontScaleX = newStyle.fontScaleX;
this.fontScaleY = newStyle.fontScaleY;
this.letterSpacing = newStyle.letterSpacing;
this._rotationX = null;
this._rotationY = null;
this._rotationZ = newStyle.rotationZ;
this._skewX = null;
this._skewY = null;
this.primaryColor = newStyle.primaryColor;
this.secondaryColor = newStyle.secondaryColor;
this.outlineColor = newStyle.outlineColor;
this.shadowColor = newStyle.shadowColor;
this.primaryAlpha = newStyle.primaryColor.alpha;
this.secondaryAlpha = newStyle.secondaryColor.alpha;
this.outlineAlpha = newStyle.outlineColor.alpha;
this.shadowAlpha = newStyle.shadowColor.alpha;
this.blur = null;
this.gaussianBlur = null;
};
/**
* Sets the style attribute on the given span element.
*
* @param {!HTMLSpanElement} span
* @param {!AnimationCollection} animationCollection
* @return {!HTMLSpanElement} The resulting <span> with the CSS styles applied. This may be a wrapper around the input <span> if the styles were applied using SVG filters.
*/
SpanStyles.prototype.setStylesOnSpan = function (span, animationCollection) {
var isTextOnlySpan = span.childNodes[0] instanceof Text;
var fontStyleOrWeight = "";
if (this._italic) {
fontStyleOrWeight += "italic ";
}
if (this._bold === true) {
fontStyleOrWeight += "bold ";
} else if (this._bold !== false) {
fontStyleOrWeight += this._bold + " ";
}
var fontSize = (this._scaleY * font_size_1.fontSizeForLineHeight(this._fontName, this._fontSize * (isTextOnlySpan ? this._fontScaleX : 1), this._settings.fallbackFonts, this._fontSizeElement, this._fontMetricsCache)).toFixed(3);
var lineHeight = (this._scaleY * this._fontSize).toFixed(3);
var fonts = this._fontName;
// Quote the font family unless it's a generic family, as those must never be quoted
switch (fonts) {
case "cursive":
case "fantasy":
case "monospace":
case "sans-serif":
case "serif":
break;
default:
fonts = '"' + fonts + '"';
break;
}
if (this._settings.fallbackFonts !== "") {
fonts += ", " + this._settings.fallbackFonts;
}
span.style.font = "" + fontStyleOrWeight + fontSize + "px/" + lineHeight + "px " + fonts;
var textDecoration = "";
if (this._underline) {
textDecoration = "underline";
}
if (this._strikeThrough) {
textDecoration += " line-through";
}
span.style.textDecoration = textDecoration.trim();
var transform = "";
if (isTextOnlySpan) {
if (this._fontScaleY !== this._fontScaleX) {
transform += "scaleY(" + (this._fontScaleY / this._fontScaleX).toFixed(3) + ") ";
}
} else {
if (this._fontScaleX !== 1) {
transform += "scaleX(" + this._fontScaleX + ") ";
}
if (this._fontScaleY !== 1) {
transform += "scaleY(" + this._fontScaleY + ") ";
}
}
if (this._rotationY !== null) {
transform += "rotateY(" + this._rotationY + "deg) ";
}
if (this._rotationX !== null) {
transform += "rotateX(" + this._rotationX + "deg) ";
}
if (this._rotationZ !== 0) {
transform += "rotateZ(" + -1 * this._rotationZ + "deg) ";
}
if (this._skewX !== null || this._skewY !== null) {
var skewX = SpanStyles._valueOrDefault(this._skewX, 0);
var skewY = SpanStyles._valueOrDefault(this._skewY, 0);
transform += "matrix(1, " + skewY + ", " + skewX + ", 1, 0, 0) ";
}
if (transform !== "") {
span.style.webkitTransform = transform;
span.style.webkitTransformOrigin = "50% 50%";
span.style.transform = transform;
span.style.transformOrigin = "50% 50%";
span.style.display = "inline-block";
}
span.style.letterSpacing = (this._scaleX * this._letterSpacing).toFixed(3) + "px";
var outlineWidth = this._scaleX * this._outlineWidth;
var outlineHeight = this._scaleY * this._outlineHeight;
var filterWrapperSpan = document.createElement("span");
filterWrapperSpan.appendChild(span);
var primaryColor = this._primaryColor.withAlpha(this._primaryAlpha);
var outlineColor = this._outlineColor.withAlpha(this._outlineAlpha);
var shadowColor = this._shadowColor.withAlpha(this._shadowAlpha);
// If we're in non-SVG mode and all colors have the same alpha, then set all colors to alpha === 1 and set the common alpha as the span's opacity property instead
if (!this._settings.enableSvg && (outlineWidth === 0 && outlineHeight === 0 || outlineColor.alpha === primaryColor.alpha) && (this._shadowDepthX === 0 && this._shadowDepthY === 0 || shadowColor.alpha === primaryColor.alpha)) {
primaryColor = this._primaryColor.withAlpha(1);
outlineColor = this._outlineColor.withAlpha(1);
shadowColor = this._shadowColor.withAlpha(1);
span.style.opacity = this._primaryAlpha.toFixed(3);
}
span.style.color = primaryColor.toString();
if (this._settings.enableSvg) {
this._setSvgOutlineOnSpan(filterWrapperSpan, outlineWidth, outlineHeight, outlineColor, this._primaryAlpha);
} else {
this._setTextShadowOutlineOnSpan(span, outlineWidth, outlineHeight, outlineColor);
}
if (this._shadowDepthX !== 0 || this._shadowDepthY !== 0) {
var shadowCssString = shadowColor.toString() + " " + (this._shadowDepthX * this._scaleX).toFixed(3) + "px " + (this._shadowDepthY * this._scaleY).toFixed(3) + "px 0px";
if (span.style.textShadow === "") {
span.style.textShadow = shadowCssString;
} else {
span.style.textShadow += ", " + shadowCssString;
}
}
if (this._rotationX !== 0 || this._rotationY !== 0) {
// Perspective needs to be set on a "transformable element"
filterWrapperSpan.style.display = "inline-block";
}
span.style.webkitAnimation = animationCollection.animationStyle;
span.style.animation = animationCollection.animationStyle;
return filterWrapperSpan;
};
/**
* @param {!HTMLSpanElement} filterWrapperSpan
* @param {number} outlineWidth
* @param {number} outlineHeight
* @param {!libjass.parts.Color} outlineColor
* @param {number} primaryAlpha
*
* @private
*/
SpanStyles.prototype._setSvgOutlineOnSpan = function (filterWrapperSpan, outlineWidth, outlineHeight, outlineColor, primaryAlpha) {
var filterId = "svg-filter-" + this._id + "-" + this._nextFilterId++;
var filterElement = document.createElementNS("http://www.w3.org/2000/svg", "filter");
filterElement.id = filterId;
filterElement.x.baseVal.valueAsString = "-50%";
filterElement.width.baseVal.valueAsString = "200%";
filterElement.y.baseVal.valueAsString = "-50%";
filterElement.height.baseVal.valueAsString = "200%";
if (outlineWidth > 0 || outlineHeight > 0) {
/* Construct an elliptical border by merging together many rectangles. The border is creating using dilate morphology filters, but these only support
* generating rectangles. http://lists.w3.org/Archives/Public/public-fx/2012OctDec/0003.html
*/
var outlineNumber = 0;
var increment = !this._settings.preciseOutlines && this._gaussianBlur > 0 ? this._gaussianBlur : 1;
(function (addOutline) {
if (outlineWidth <= outlineHeight) {
if (outlineWidth > 0) {
var x;
for (x = 0; x <= outlineWidth; x += increment) {
addOutline(x, outlineHeight / outlineWidth * Math.sqrt(outlineWidth * outlineWidth - x * x));
}
if (x !== outlineWidth + increment) {
addOutline(outlineWidth, 0);
}
} else {
addOutline(0, outlineHeight);
}
} else {
if (outlineHeight > 0) {
var y;
for (y = 0; y <= outlineHeight; y += increment) {
addOutline(outlineWidth / outlineHeight * Math.sqrt(outlineHeight * outlineHeight - y * y), y);
}
if (y !== outlineHeight + increment) {
addOutline(0, outlineHeight);
}
} else {
addOutline(outlineWidth, 0);
}
}
})(function (x, y) {
var outlineFilter = document.createElementNS("http://www.w3.org/2000/svg", "feMorphology");
filterElement.appendChild(outlineFilter);
outlineFilter.in1.baseVal = "source";
outlineFilter.operator.baseVal = SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_DILATE;
outlineFilter.radiusX.baseVal = x;
outlineFilter.radiusY.baseVal = y;
outlineFilter.result.baseVal = "outline" + outlineNumber;
outlineNumber++;
});
// Start with SourceAlpha. Leave the alpha as 0 if it's 0, and set it to 1 if it's greater than 0
var source = document.createElementNS("http://www.w3.org/2000/svg", "feComponentTransfer");
filterElement.insertBefore(source, filterElement.firstElementChild);
source.in1.baseVal = "SourceAlpha";
source.result.baseVal = "source";
var sourceAlphaTransferNode = document.createElementNS("http://www.w3.org/2000/svg", "feFuncA");
source.appendChild(sourceAlphaTransferNode);
sourceAlphaTransferNode.type.baseVal = SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_LINEAR;
/* The alphas of all colored pixels of the SourceAlpha should be made as close to 1 as possible. This way the summed outlines below will be uniformly dark.
* Multiply the pixels by 1 / primaryAlpha so that the primaryAlpha pixels become 1. A higher value would make the outline larger and too sharp,
* leading to jagged outer edge and transparent space around the inner edge between itself and the SourceGraphic.
*/
sourceAlphaTransferNode.slope.baseVal = primaryAlpha === 0 ? 1 : 1 / primaryAlpha;
sourceAlphaTransferNode.intercept.baseVal = 0;
// Merge the individual outlines
var mergedOutlines = document.createElementNS("http://www.w3.org/2000/svg", "feMerge");
filterElement.appendChild(mergedOutlines);
for (var i = 0; i < outlineNumber; i++) {
var outlineReferenceNode_1 = document.createElementNS("http://www.w3.org/2000/svg", "feMergeNode");
mergedOutlines.appendChild(outlineReferenceNode_1);
outlineReferenceNode_1.in1.baseVal = "outline" + i;
}
// Color it with the outline color
var coloredSource = document.createElementNS("http://www.w3.org/2000/svg", "feComponentTransfer");
filterElement.appendChild(coloredSource);
coloredSource.setAttribute("color-interpolation-filters", "sRGB");
var outlineRedTransferNode = document.createElementNS("http://www.w3.org/2000/svg", "feFuncR");
coloredSource.appendChild(outlineRedTransferNode);
outlineRedTransferNode.type.baseVal = SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_LINEAR;
outlineRedTransferNode.slope.baseVal = 0;
outlineRedTransferNode.intercept.baseVal = outlineColor.red / 255 * outlineColor.alpha;
var outlineGreenTransferNode = document.createElementNS("http://www.w3.org/2000/svg", "feFuncG");
coloredSource.appendChild(outlineGreenTransferNode);
outlineGreenTransferNode.type.baseVal = SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_LINEAR;
outlineGreenTransferNode.slope.baseVal = 0;
outlineGreenTransferNode.intercept.baseVal = outlineColor.green / 255 * outlineColor.alpha;
var outlineBlueTransferNode = document.createElementNS("http://www.w3.org/2000/svg", "feFuncB");
coloredSource.appendChild(outlineBlueTransferNode);
outlineBlueTransferNode.type.baseVal = SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_LINEAR;
outlineBlueTransferNode.slope.baseVal = 0;
outlineBlueTransferNode.intercept.baseVal = outlineColor.blue / 255 * outlineColor.alpha;
var outlineAlphaTransferNode = document.createElementNS("http://www.w3.org/2000/svg", "feFuncA");
coloredSource.appendChild(outlineAlphaTransferNode);
outlineAlphaTransferNode.type.baseVal = SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_LINEAR;
outlineAlphaTransferNode.slope.baseVal = outlineColor.alpha;
outlineAlphaTransferNode.intercept.baseVal = 0;
// Blur the merged outline
if (this._gaussianBlur > 0) {
var gaussianBlurFilter = document.createElementNS("http://www.w3.org/2000/svg", "feGaussianBlur");
filterElement.appendChild(gaussianBlurFilter);
gaussianBlurFilter.stdDeviationX.baseVal = this._gaussianBlur;
gaussianBlurFilter.stdDeviationY.baseVal = this._gaussianBlur;
}
for (var i = 0; i < this._blur; i++) {
var blurFilter = document.createElementNS("http://www.w3.org/2000/svg", "feConvolveMatrix");
filterElement.appendChild(blurFilter);
blurFilter.setAttribute("kernelMatrix", "1 2 1 2 4 2 1 2 1");
blurFilter.edgeMode.baseVal = SVGFEConvolveMatrixElement.SVG_EDGEMODE_NONE;
}
// Cut out the source, so only the outline remains
var outlineCutoutNode = document.createElementNS("http://www.w3.org/2000/svg", "feComposite");
filterElement.appendChild(outlineCutoutNode);
outlineCutoutNode.in2.baseVal = "source";
outlineCutoutNode.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OUT;
// Merge the outline with the SourceGraphic
var mergedOutlineAndSourceGraphic = document.createElementNS("http://www.w3.org/2000/svg", "feMerge");
filterElement.appendChild(mergedOutlineAndSourceGraphic);
var outlineReferenceNode = document.createElementNS("http://www.w3.org/2000/svg", "feMergeNode");
mergedOutlineAndSourceGraphic.appendChild(outlineReferenceNode);
var sourceGraphicReferenceNode = document.createElementNS("http://www.w3.org/2000/svg", "feMergeNode");
mergedOutlineAndSourceGraphic.appendChild(sourceGraphicReferenceNode);
sourceGraphicReferenceNode.in1.baseVal = "SourceGraphic";
} else {
// Blur the source graphic directly
if (this._gaussianBlur > 0) {
var gaussianBlurFilter = document.createElementNS("http://www.w3.org/2000/svg", "feGaussianBlur");
filterElement.appendChild(gaussianBlurFilter);
gaussianBlurFilter.stdDeviationX.baseVal = this._gaussianBlur;
gaussianBlurFilter.stdDeviationY.baseVal = this._gaussianBlur;
}
for (var i = 0; i < this._blur; i++) {
var blurFilter = document.createElementNS("http://www.w3.org/2000/svg", "feConvolveMatrix");
filterElement.appendChild(blurFilter);
blurFilter.setAttribute("kernelMatrix", "1 2 1 2 4 2 1 2 1");
blurFilter.edgeMode.baseVal = SVGFEConvolveMatrixElement.SVG_EDGEMODE_NONE;
}
}
if (filterElement.childElementCount > 0) {
this._svgDefsElement.appendChild(filterElement);
filterWrapperSpan.style.webkitFilter = 'url("#' + filterId + '")';
filterWrapperSpan.style.filter = 'url("#' + filterId + '")';
}
};
/**
* @param {!HTMLSpanElement} span
* @param {number} outlineWidth
* @param {number} outlineHeight
* @param {!libjass.parts.Color} outlineColor
*
* @private
*/
SpanStyles.prototype._setTextShadowOutlineOnSpan = function (span, outlineWidth, outlineHeight, outlineColor) {
var _this = this;
if (outlineWidth > 0 || outlineHeight > 0) {
var outlineCssString = "";
(function (addOutline) {
for (var x = 0; x <= outlineWidth; x++) {
var maxY = outlineWidth === 0 ? outlineHeight : outlineHeight * Math.sqrt(1 - x * x / (outlineWidth * outlineWidth));
for (var y = 0; y <= maxY; y++) {
addOutline(x, y);
if (x !== 0) {
addOutline(-x, y);
}
if (y !== 0) {
addOutline(x, -y);
}
if (x !== 0 && y !== 0) {
addOutline(-x, -y);
}
}
}
})(function (x, y) {
outlineCssString += ", " + outlineColor.toString() + " " + x + "px " + y + "px " + _this._gaussianBlur.toFixed(3) + "px";
});
span.style.textShadow = outlineCssString.substr(", ".length);
}
};
/**
* @return {!HTMLBRElement}
*/
SpanStyles.prototype.makeNewLine = function () {
var result = document.createElement("br");
result.style.lineHeight = (this._scaleY * this._fontSize).toFixed(3) + "px";
return result;
};
Object.defineProperty(SpanStyles.prototype, "italic", {
/**
* Sets the italic property. null defaults it to the default style's value.
*
* @type {?boolean}
*/
set: function (value) {
this._italic = SpanStyles._valueOrDefault(value, this._defaultStyle.italic);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "bold", {
/**
* Sets the bold property. null defaults it to the default style's value.
*
* @type {(?number|?boolean)}
*/
set: function (value) {
this._bold = SpanStyles._valueOrDefault(value, this._defaultStyle.bold);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "underline", {
/**
* Sets the underline property. null defaults it to the default style's value.
*
* @type {?boolean}
*/
set: function (value) {
this._underline = SpanStyles._valueOrDefault(value, this._defaultStyle.underline);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "strikeThrough", {
/**
* Sets the strike-through property. null defaults it to the default style's value.
*
* @type {?boolean}
*/
set: function (value) {
this._strikeThrough = SpanStyles._valueOrDefault(value, this._defaultStyle.strikeThrough);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "outlineWidth", {
/**
* Gets the outline width property.
*
* @type {number}
*/
get: function () {
return this._outlineWidth;
},
/**
* Sets the outline width property. null defaults it to the style's original outline width value.
*
* @type {?number}
*/
set: function (value) {
this._outlineWidth = SpanStyles._valueOrDefault(value, this._defaultStyle.outlineThickness);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "outlineHeight", {
/**
* Gets the outline width property.
*
* @type {number}
*/
get: function () {
return this._outlineWidth;
},
/**
* Sets the outline height property. null defaults it to the style's original outline height value.
*
* @type {?number}
*/
set: function (value) {
this._outlineHeight = SpanStyles._valueOrDefault(value, this._defaultStyle.outlineThickness);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "shadowDepthX", {
/**
* Gets the shadow width property.
*
* @type {number}
*/
get: function () {
return this._shadowDepthX;
},
/**
* Sets the shadow width property. null defaults it to the style's original shadow depth value.
*
* @type {?number}
*/
set: function (value) {
this._shadowDepthX = SpanStyles._valueOrDefault(value, this._defaultStyle.shadowDepth);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "shadowDepthY", {
/**
* Gets the shadow height property.
*
* @type {number}
*/
get: function () {
return this._shadowDepthY;
},
/**
* Sets the shadow height property. null defaults it to the style's original shadow depth value.
*
* @type {?number}
*/
set: function (value) {
this._shadowDepthY = SpanStyles._valueOrDefault(value, this._defaultStyle.shadowDepth);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "blur", {
/**
* Gets the blur property.
*
* @type {number}
*/
get: function () {
return this._blur;
},
/**
* Sets the blur property. null defaults it to 0.
*
* @type {?number}
*/
set: function (value) {
this._blur = SpanStyles._valueOrDefault(value, 0);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "gaussianBlur", {
/**
* Gets the Gaussian blur property.
*
* @type {number}
*/
get: function () {
return this._gaussianBlur;
},
/**
* Sets the Gaussian blur property. null defaults it to 0.
*
* @type {?number}
*/
set: function (value) {
this._gaussianBlur = SpanStyles._valueOrDefault(value, 0);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "fontName", {
/**
* Sets the font name property. null defaults it to the default style's value.
*
* @type {?string}
*/
set: function (value) {
this._fontName = SpanStyles._valueOrDefault(value, this._defaultStyle.fontName);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "fontSize", {
/**
* Gets the font size property.
*
* @type {number}
*/
get: function () {
return this._fontSize;
},
/**
* Sets the font size property. null defaults it to the default style's value.
*
* @type {?number}
*/
set: function (value) {
this._fontSize = SpanStyles._valueOrDefault(value, this._defaultStyle.fontSize);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "fontScaleX", {
/**
* Gets the horizontal font scaling property.
*
* @type {number}
*/
get: function () {
return this._fontScaleX;
},
/**
* Sets the horizontal font scaling property. null defaults it to the default style's value.
*
* @type {?number}
*/
set: function (value) {
this._fontScaleX = SpanStyles._valueOrDefault(value, this._defaultStyle.fontScaleX);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "fontScaleY", {
/**
* Gets the vertical font scaling property.
*
* @type {number}
*/
get: function () {
return this._fontScaleY;
},
/**
* Sets the vertical font scaling property. null defaults it to the default style's value.
*
* @type {?number}
*/
set: function (value) {
this._fontScaleY = SpanStyles._valueOrDefault(value, this._defaultStyle.fontScaleY);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "letterSpacing", {
/**
* Gets the letter spacing property.
*
* @type {number}
*/
get: function () {
return this._letterSpacing;
},
/**
* Sets the letter spacing property. null defaults it to the default style's value.
*
* @type {?number}
*/
set: function (value) {
this._letterSpacing = SpanStyles._valueOrDefault(value, this._defaultStyle.letterSpacing);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "rotationX", {
/**
* Gets the X-axis rotation property.
*
* @type {?number}
*/
get: function () {
return this._rotationX;
},
/**
* Sets the X-axis rotation property.
*
* @type {?number}
*/
set: function (value) {
this._rotationX = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "rotationY", {
/**
* Gets the Y-axis rotation property.
*
* @type {?number}
*/
get: function () {
return this._rotationY;
},
/**
* Sets the Y-axis rotation property.
*
* @type {?number}
*/
set: function (value) {
this._rotationY = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "rotationZ", {
/**
* Gets the Z-axis rotation property.
*
* @type {?number}
*/
get: function () {
return this._rotationZ;
},
/**
* Sets the Z-axis rotation property.
*
* @type {?number}
*/
set: function (value) {
this._rotationZ = SpanStyles._valueOrDefault(value, this._defaultStyle.rotationZ);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "skewX", {
/**
* Gets the X-axis skew property.
*
* @type {?number}
*/
get: function () {
return this._skewX;
},
/**
* Sets the X-axis skew property.
*
* @type {?number}
*/
set: function (value) {
this._skewX = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "skewY", {
/**
* Gets the Y-axis skew property.
*
* @type {?number}
*/
get: function () {
return this._skewY;
},
/**
* Sets the Y-axis skew property.
*
* @type {?number}
*/
set: function (value) {
this._skewY = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "primaryColor", {
/**
* Gets the primary color property.
*
* @type {!libjass.Color}
*/
get: function () {
return this._primaryColor;
},
/**
* Sets the primary color property. null defaults it to the default style's value.
*
* @type {libjass.Color}
*/
set: function (value) {
this._primaryColor = SpanStyles._valueOrDefault(value, this._defaultStyle.primaryColor);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "secondaryColor", {
/**
* Gets the secondary color property.
*
* @type {!libjass.Color}
*/
get: function () {
return this._secondaryColor;
},
/**
* Sets the secondary color property. null defaults it to the default style's value.
*
* @type {libjass.Color}
*/
set: function (value) {
this._secondaryColor = SpanStyles._valueOrDefault(value, this._defaultStyle.secondaryColor);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "outlineColor", {
/**
* Gets the outline color property.
*
* @type {!libjass.Color}
*/
get: function () {
return this._outlineColor;
},
/**
* Sets the outline color property. null defaults it to the default style's value.
*
* @type {libjass.Color}
*/
set: function (value) {
this._outlineColor = SpanStyles._valueOrDefault(value, this._defaultStyle.outlineColor);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "shadowColor", {
/**
* Gets the shadow color property.
*
* @type {!libjass.Color}
*/
get: function () {
return this._shadowColor;
},
/**
* Sets the shadow color property. null defaults it to the default style's value.
*
* @type {libjass.Color}
*/
set: function (value) {
this._shadowColor = SpanStyles._valueOrDefault(value, this._defaultStyle.shadowColor);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "primaryAlpha", {
/**
* Gets the primary alpha property.
*
* @type {number}
*/
get: function () {
return this._primaryAlpha;
},
/**
* Sets the primary alpha property.
*
* @type {?number}
*/
set: function (value) {
this._primaryAlpha = SpanStyles._valueOrDefault(value, this._defaultStyle.primaryColor.alpha);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "secondaryAlpha", {
/**
* Gets the secondary alpha property.
*
* @type {number}
*/
get: function () {
return this._secondaryAlpha;
},
/**
* Sets the secondary alpha property.
*
* @type {?number}
*/
set: function (value) {
this._secondaryAlpha = SpanStyles._valueOrDefault(value, this._defaultStyle.secondaryColor.alpha);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "outlineAlpha", {
/**
* Gets the outline alpha property.
*
* @type {number}
*/
get: function () {
return this._outlineAlpha;
},
/**
* Sets the outline alpha property.
*
* @type {?number}
*/
set: function (value) {
this._outlineAlpha = SpanStyles._valueOrDefault(value, this._defaultStyle.outlineColor.alpha);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SpanStyles.prototype, "shadowAlpha", {
/**
* Gets the shadow alpha property.
*
* @type {number}
*/
get: function () {
return this._shadowAlpha;
},
/**
* Sets the shadow alpha property.
*
* @type {?number}
*/
set: function (value) {
this._shadowAlpha = SpanStyles._valueOrDefault(value, this._defaultStyle.shadowColor.alpha);
},
enumerable: true,
configurable: true
});
SpanStyles._valueOrDefault = function (newValue, defaultValue) {
return newValue !== null ? newValue : defaultValue;
};
return SpanStyles;
}();
exports.SpanStyles = SpanStyles;
}, /* 23 ./settings */ function (exports) {
/**
* Debug mode. When true, libjass logs some debug messages.
*
* @type {boolean}
*/
exports.debugMode = false;
/**
* Verbose debug mode. When true, libjass logs some more debug messages. This setting is independent of {@link libjass.debugMode}
*
* @type {boolean}
*
* @memberOf libjass
*/
exports.verboseMode = false;
/**
* Sets the debug mode.
*
* @param {boolean} value
*/
function setDebugMode(value) {
exports.debugMode = value;
}
exports.setDebugMode = setDebugMode;
/**
* Sets the verbose debug mode.
*
* @param {boolean} value
*/
function setVerboseMode(value) {
exports.verboseMode = value;
}
exports.setVerboseMode = setVerboseMode;
}, /* 24 ./types/ass */ function (exports, require) {
var dialogue_1 = require(26);
var style_1 = require(29);
var script_properties_1 = require(28);
var misc_1 = require(27);
var settings_1 = require(23);
var parser = require(1);
var misc_2 = require(2);
var map_1 = require(30);
var promise_1 = require(32);
/**
* This class represents an ASS script. It contains the {@link libjass.ScriptProperties}, an array of {@link libjass.Style}s, and an array of {@link libjass.Dialogue}s.
*
* @constructor
* @memberOf libjass
*/
var ASS = function () {
function ASS() {
this._properties = new script_properties_1.ScriptProperties();
this._styles = new map_1.Map();
this._dialogues = [];
this._attachments = [];
this._stylesFormatSpecifier = null;
this._dialoguesFormatSpecifier = null;
// Deprecated constructor argument
if (arguments.length === 1) {
throw new Error("Constructor `new ASS(rawASS)` has been deprecated. Use `ASS.fromString(rawASS)` instead.");
}
this._styles.set("Default", new style_1.Style(new map_1.Map([ [ "Name", "Default" ] ])));
}
Object.defineProperty(ASS.prototype, "properties", {
/**
* The properties of this script.
*
* @type {!libjass.ScriptProperties}
*/
get: function () {
return this._properties;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ASS.prototype, "styles", {
/**
* The styles in this script.
*
* @type {!Map.<string, !libjass.Style>}
*/
get: function () {
return this._styles;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ASS.prototype, "dialogues", {
/**
* The dialogues in this script.
*
* @type {!Array.<!libjass.Dialogue>}
*/
get: function () {
return this._dialogues;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ASS.prototype, "attachments", {
/**
* The attachments of this script.
*
* @type {!Array.<!libjass.Attachment>}
*/
get: function () {
return this._attachments;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ASS.prototype, "stylesFormatSpecifier", {
/**
* The format specifier for the styles section.
*
* @type {!Array.<string>}
*/
get: function () {
return this._stylesFormatSpecifier;
},
/**
* The format specifier for the events section.
*
* @type {!Array.<string>}
*/
set: function (value) {
this._stylesFormatSpecifier = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ASS.prototype, "dialoguesFormatSpecifier", {
/**
* The format specifier for the styles section.
*
* @type {!Array.<string>}
*/
get: function () {
return this._dialoguesFormatSpecifier;
},
/**
* The format specifier for the events section.
*
* @type {!Array.<string>}
*/
set: function (value) {
this._dialoguesFormatSpecifier = value;
},
enumerable: true,
configurable: true
});
/**
* Add a style to this ASS script.
*
* @param {string} line The line from the script that contains the new style.
*/
ASS.prototype.addStyle = function (line) {
var styleLine = misc_2.parseLineIntoTypedTemplate(line, this._stylesFormatSpecifier);
if (styleLine === null || styleLine.type !== "Style") {
return;
}
var styleTemplate = styleLine.template;
if (settings_1.verboseMode) {
var repr = "";
styleTemplate.forEach(function (value, key) {
return repr += key + " = " + value + ", ";
});
console.log("Read style: " + repr);
}
// Create the dialogue and add it to the dialogues array
var style = new style_1.Style(styleTemplate);
this._styles.set(style.name, style);
};
/**
* Add an event to this ASS script.
*
* @param {string} line The line from the script that contains the new event.
*/
ASS.prototype.addEvent = function (line) {
var dialogueLine = misc_2.parseLineIntoTypedTemplate(line, this._dialoguesFormatSpecifier);
if (dialogueLine === null || dialogueLine.type !== "Dialogue") {
return;
}
var dialogueTemplate = dialogueLine.template;
if (settings_1.verboseMode) {
var repr = "";
dialogueTemplate.forEach(function (value, key) {
return repr += key + " = " + value + ", ";
});
console.log("Read dialogue: " + repr);
}
// Create the dialogue and add it to the dialogues array
this.dialogues.push(new dialogue_1.Dialogue(dialogueTemplate, this));
};
/**
* Add an attachment to this ASS script.
*
* @param {!libjass.Attachment} attachment
*/
ASS.prototype.addAttachment = function (attachment) {
this._attachments.push(attachment);
};
/**
* Creates an ASS object from the raw text of an ASS script.
*
* @param {string} raw The raw text of the script.
* @param {number=0} type The type of the script. One of the {@link libjass.Format} constants.
* @return {!Promise.<!libjass.ASS>}
*
* @static
*/
ASS.fromString = function (raw, type) {
if (type === void 0) {
type = misc_1.Format.ASS;
}
return ASS.fromStream(new parser.StringStream(raw), type);
};
/**
* Creates an ASS object from the given {@link libjass.parser.Stream}.
*
* @param {!libjass.parser.Stream} stream The stream to parse the script from
* @param {number=0} type The type of the script. One of the {@link libjass.Format} constants.
* @return {!Promise.<!libjass.ASS>} A promise that will be resolved with the ASS object when it has been fully parsed
*
* @static
*/
ASS.fromStream = function (stream, type) {
if (type === void 0) {
type = misc_1.Format.ASS;
}
switch (type) {
case misc_1.Format.ASS:
return new parser.StreamParser(stream).ass;
case misc_1.Format.SRT:
return new parser.SrtStreamParser(stream).ass;
default:
throw new Error("Illegal value of type: " + type);
}
};
/**
* Creates an ASS object from the given URL.
*
* @param {string} url The URL of the script.
* @param {number=0} type The type of the script. One of the {@link libjass.Format} constants.
* @return {!Promise.<!libjass.ASS>} A promise that will be resolved with the ASS object when it has been fully parsed
*
* @static
*/
ASS.fromUrl = function (url, type) {
if (type === void 0) {
type = misc_1.Format.ASS;
}
var fetchPromise;
if (typeof global.fetch === "function" && typeof global.ReadableStream === "function" && typeof global.ReadableStream.prototype.getReader === "function" && typeof global.TextDecoder === "function") {
fetchPromise = global.fetch(url).then(function (response) {
if (response.ok === false || response.ok === undefined && (response.status < 200 || response.status > 299)) {
throw new Error("HTTP request for " + url + " failed with status code " + response.status);
}
return ASS.fromReadableStream(response.body, "utf-8", type);
});
} else {
fetchPromise = promise_1.Promise.reject(new Error("Not supported."));
}
return fetchPromise.catch(function (reason) {
console.warn("fetch() failed, falling back to XHR: %o", reason);
var xhr = new XMLHttpRequest();
var result = ASS.fromStream(new parser.XhrStream(xhr), type);
xhr.open("GET", url, true);
xhr.send();
return result;
});
};
/**
* Creates an ASS object from the given ReadableStream.
*
* @param {!ReadableStream} stream
* @param {string="utf-8"} encoding
* @param {number=0} type The type of the script. One of the {@link libjass.Format} constants.
* @return {!Promise.<!libjass.ASS>} A promise that will be resolved with the ASS object when it has been fully parsed
*
* @static
*/
ASS.fromReadableStream = function (stream, encoding, type) {
if (encoding === void 0) {
encoding = "utf-8";
}
if (type === void 0) {
type = misc_1.Format.ASS;
}
return ASS.fromStream(new parser.BrowserReadableStream(stream, encoding), type);
};
return ASS;
}();
exports.ASS = ASS;
}, /* 25 ./types/attachment */ function (exports) {
/**
* The type of an attachment.
*/
(function (AttachmentType) {
AttachmentType[AttachmentType["Font"] = 0] = "Font";
AttachmentType[AttachmentType["Graphic"] = 1] = "Graphic";
})(exports.AttachmentType || (exports.AttachmentType = {}));
/**
* This class represents an attachment in a {@link libjass.ASS} script.
*
* @param {string} filename The filename of this attachment.
* @param {number} type The type of this attachment.
*
* @constructor
* @memberOf libjass
*/
var Attachment = function () {
function Attachment(filename, type) {
this._filename = filename;
this._type = type;
this._contents = "";
}
Object.defineProperty(Attachment.prototype, "filename", {
/**
* The filename of this attachment.
*
* @type {number}
*/
get: function () {
return this._filename;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Attachment.prototype, "type", {
/**
* The type of this attachment.
*
* @type {number}
*/
get: function () {
return this._type;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Attachment.prototype, "contents", {
/**
* The contents of this attachment in base64 encoding.
*
* @type {number}
*/
get: function () {
return this._contents;
},
/**
* The contents of this attachment in base64 encoding.
*
* @type {number}
*/
set: function (value) {
this._contents = value;
},
enumerable: true,
configurable: true
});
return Attachment;
}();
exports.Attachment = Attachment;
}, /* 26 ./types/dialogue */ function (exports, require) {
var misc_1 = require(27);
var parse_1 = require(3);
var parts = require(8);
var settings_1 = require(23);
var map_1 = require(30);
/**
* This class represents a dialogue in a {@link libjass.ASS} script.
*
* @param {!Map.<string, string>} template The template object that contains the dialogue's properties. It is a map of the string values read from the ASS file.
* @param {string} template["Style"] The name of the default style of this dialogue
* @param {string} template["Start"] The start time
* @param {string} template["End"] The end time
* @param {string} template["Layer"] The layer number
* @param {string} template["Text"] The text of this dialogue
* @param {!libjass.ASS} ass The ASS object to which this dialogue belongs
*
* @constructor
* @memberOf libjass
*/
var Dialogue = function () {
function Dialogue(template, ass) {
this._parts = null;
this._containsTransformTag = false;
{
var normalizedTemplate = new map_1.Map();
template.forEach(function (value, key) {
normalizedTemplate.set(key.toLowerCase(), value);
});
template = normalizedTemplate;
}
this._id = ++Dialogue._lastDialogueId;
var styleName = template.get("style");
if (styleName !== undefined && styleName !== null && styleName.constructor === String) {
styleName = styleName.replace(/^\*+/, "");
if (styleName.match(/^Default$/i) !== null) {
styleName = "Default";
}
}
this._style = ass.styles.get(styleName);
if (this._style === undefined) {
if (settings_1.debugMode) {
console.warn("Unrecognized style " + styleName + '. Falling back to "Default"');
}
this._style = ass.styles.get("Default");
}
if (this._style === undefined) {
throw new Error("Unrecognized style " + styleName);
}
this._start = Dialogue._toTime(template.get("start"));
this._end = Dialogue._toTime(template.get("end"));
this._layer = Math.max(misc_1.valueOrDefault(template, "layer", parseInt, function (value) {
return !isNaN(value);
}, "0"), 0);
this._rawPartsString = template.get("text");
if (this._rawPartsString === undefined || this._rawPartsString === null || this._rawPartsString.constructor !== String) {
throw new Error("Dialogue doesn't have any text.");
}
}
Object.defineProperty(Dialogue.prototype, "id", {
/**
* The unique ID of this dialogue. Auto-generated.
*
* @type {number}
*/
get: function () {
return this._id;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Dialogue.prototype, "start", {
/**
* The start time of this dialogue.
*
* @type {number}
*/
get: function () {
return this._start;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Dialogue.prototype, "end", {
/**
* The end time of this dialogue.
*
* @type {number}
*/
get: function () {
return this._end;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Dialogue.prototype, "style", {
/**
* The default style of this dialogue.
*
* @type {!libjass.Style}
*/
get: function () {
return this._style;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Dialogue.prototype, "alignment", {
/**
* The alignment number of this dialogue.
*
* @type {number}
*/
get: function () {
if (this._parts === null) {
this._parsePartsString();
}
return this._alignment;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Dialogue.prototype, "layer", {
/**
* The layer number of this dialogue.
*
* @type {number}
*/
get: function () {
return this._layer;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Dialogue.prototype, "parts", {
/**
* The {@link libjass.parts} of this dialogue.
*
* @type {!Array.<!libjass.parts.Part>}
*/
get: function () {
if (this._parts === null) {
this._parsePartsString();
}
return this._parts;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Dialogue.prototype, "containsTransformTag", {
/**
* Convenience getter for whether this dialogue contains a {\t} tag.
*
* @type {boolean}
*/
get: function () {
if (this._parts === null) {
this._parsePartsString();
}
return this._containsTransformTag;
},
enumerable: true,
configurable: true
});
/**
* @return {string} A simple representation of this dialogue's properties and parts.
*/
Dialogue.prototype.toString = function () {
return "#" + this._id + " [" + this._start.toFixed(3) + "-" + this._end.toFixed(3) + "] " + (this._parts !== null ? this._parts.join(", ") : this._rawPartsString);
};
/**
* Parses this dialogue's parts from the raw parts string.
*
* @private
*/
Dialogue.prototype._parsePartsString = function () {
var _this = this;
this._parts = parse_1.parse(this._rawPartsString, "dialogueParts");
this._alignment = this._style.alignment;
this._parts.forEach(function (part, index) {
if (part instanceof parts.Alignment) {
_this._alignment = part.value;
} else if (part instanceof parts.Move) {
if (part.t1 === null || part.t2 === null) {
_this._parts[index] = new parts.Move(part.x1, part.y1, part.x2, part.y2, 0, _this._end - _this._start);
}
} else if (part instanceof parts.Transform) {
if (part.start === null || part.end === null || part.accel === null) {
_this._parts[index] = new parts.Transform(part.start === null ? 0 : part.start, part.end === null ? _this._end - _this._start : part.end, part.accel === null ? 1 : part.accel, part.tags);
}
_this._containsTransformTag = true;
}
});
if (settings_1.debugMode) {
var possiblyIncorrectParses = this._parts.filter(function (part) {
return part instanceof parts.Comment && part.value.indexOf("\\") !== -1;
});
if (possiblyIncorrectParses.length > 0) {
console.warn("Possible incorrect parse:\n" + this._rawPartsString + "\nwas parsed as\n" + this.toString() + "\nThe possibly incorrect parses are:\n" + possiblyIncorrectParses.join("\n"));
}
}
};
/**
* Converts this string into the number of seconds it represents. This string must be in the form of hh:mm:ss.MMM
*
* @param {string} str
* @return {number}
*
* @private
* @static
*/
Dialogue._toTime = function (str) {
return str.split(":").reduce(function (previousValue, currentValue) {
return previousValue * 60 + parseFloat(currentValue);
}, 0);
};
Dialogue._lastDialogueId = -1;
return Dialogue;
}();
exports.Dialogue = Dialogue;
}, /* 27 ./types/misc */ function (exports) {
/**
* The format of the string passed to {@link libjass.ASS.fromString}
*
* @enum
* @memberOf libjass
*/
(function (Format) {
Format[Format["ASS"] = 0] = "ASS";
Format[Format["SRT"] = 1] = "SRT";
})(exports.Format || (exports.Format = {}));
/**
* The wrapping style defined in the {@link libjass.ScriptProperties}
*
* @enum
* @memberOf libjass
*/
(function (WrappingStyle) {
WrappingStyle[WrappingStyle["SmartWrappingWithWiderTopLine"] = 0] = "SmartWrappingWithWiderTopLine";
WrappingStyle[WrappingStyle["SmartWrappingWithWiderBottomLine"] = 3] = "SmartWrappingWithWiderBottomLine";
WrappingStyle[WrappingStyle["EndOfLineWrapping"] = 1] = "EndOfLineWrapping";
WrappingStyle[WrappingStyle["NoLineWrapping"] = 2] = "NoLineWrapping";
})(exports.WrappingStyle || (exports.WrappingStyle = {}));
/**
* The border style defined in the {@link libjass.Style} properties.
*
* @enum
* @memberOf libjass
*/
(function (BorderStyle) {
BorderStyle[BorderStyle["Outline"] = 1] = "Outline";
BorderStyle[BorderStyle["OpaqueBox"] = 3] = "OpaqueBox";
})(exports.BorderStyle || (exports.BorderStyle = {}));
/**
* @param {!Map.<string, string>} template
* @param {string} key
* @param {function(string):T} converter
* @param {?function(T):boolean} validator
* @param {T} defaultValue
* @return {T}
*
* @template T
*/
function valueOrDefault(template, key, converter, validator, defaultValue) {
var value = template.get(key);
if (value === undefined) {
return converter(defaultValue);
}
try {
var result = converter(value);
if (validator !== null && !validator(result)) {
throw new Error("Validation failed.");
}
return result;
} catch (ex) {
throw new Error("Property " + key + " has invalid value " + value + " - " + ex.stack);
}
}
exports.valueOrDefault = valueOrDefault;
}, /* 28 ./types/script-properties */ function (exports) {
/**
* This class represents the properties of a {@link libjass.ASS} script.
*
* @constructor
* @memberOf libjass
*/
var ScriptProperties = function () {
function ScriptProperties() {}
Object.defineProperty(ScriptProperties.prototype, "resolutionX", {
/**
* The horizontal script resolution.
*
* @type {number}
*/
get: function () {
return this._resolutionX;
},
/**
* The horizontal script resolution.
*
* @type {number}
*/
set: function (value) {
this._resolutionX = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ScriptProperties.prototype, "resolutionY", {
/**
* The vertical script resolution.
*
* @type {number}
*/
get: function () {
return this._resolutionY;
},
/**
* The vertical script resolution.
*
* @type {number}
*/
set: function (value) {
this._resolutionY = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ScriptProperties.prototype, "wrappingStyle", {
/**
* The wrap style. One of the {@link libjass.WrappingStyle} constants.
*
* @type {number}
*/
get: function () {
return this._wrappingStyle;
},
/**
* The wrap style. One of the {@link libjass.WrappingStyle} constants.
*
* @type {number}
*/
set: function (value) {
this._wrappingStyle = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ScriptProperties.prototype, "scaleBorderAndShadow", {
/**
* Whether to scale outline widths and shadow depths from script resolution to video resolution or not. If true, widths and depths are scaled.
*
* @type {boolean}
*/
get: function () {
return this._scaleBorderAndShadow;
},
/**
* Whether to scale outline widths and shadow depths from script resolution to video resolution or not. If true, widths and depths are scaled.
*
* @type {boolean}
*/
set: function (value) {
this._scaleBorderAndShadow = value;
},
enumerable: true,
configurable: true
});
return ScriptProperties;
}();
exports.ScriptProperties = ScriptProperties;
}, /* 29 ./types/style */ function (exports, require) {
var misc_1 = require(27);
var parse_1 = require(3);
var map_1 = require(30);
/**
* This class represents a single global style declaration in a {@link libjass.ASS} script. The styles can be obtained via the {@link libjass.ASS.styles} property.
*
* @param {!Map.<string, string>} template The template object that contains the style's properties. It is a map of the string values read from the ASS file.
* @param {string} template["Name"] The name of the style
* @param {string} template["Italic"] -1 if the style is italicized
* @param {string} template["Bold"] -1 if the style is bold
* @param {string} template["Underline"] -1 if the style is underlined
* @param {string} template["StrikeOut"] -1 if the style is struck-through
* @param {string} template["Fontname"] The name of the font
* @param {string} template["Fontsize"] The size of the font
* @param {string} template["ScaleX"] The horizontal scaling of the font
* @param {string} template["ScaleY"] The vertical scaling of the font
* @param {string} template["Spacing"] The letter spacing of the font
* @param {string} template["PrimaryColour"] The primary color
* @param {string} template["OutlineColour"] The outline color
* @param {string} template["BackColour"] The shadow color
* @param {string} template["Outline"] The outline thickness
* @param {string} template["Shadow"] The shadow depth
* @param {string} template["Alignment"] The alignment number
* @param {string} template["MarginL"] The left margin
* @param {string} template["MarginR"] The right margin
* @param {string} template["MarginV"] The vertical margin
*
* @constructor
* @memberOf libjass
*/
var Style = function () {
function Style(template) {
{
var normalizedTemplate = new map_1.Map();
template.forEach(function (value, key) {
normalizedTemplate.set(key.toLowerCase(), value);
});
template = normalizedTemplate;
}
this._name = template.get("name");
if (this._name === undefined || this._name === null || this._name.constructor !== String) {
throw new Error("Style doesn't have a name.");
}
this._name = this._name.replace(/^\*+/, "");
this._italic = !!misc_1.valueOrDefault(template, "italic", parseFloat, function (value) {
return !isNaN(value);
}, "0");
this._bold = !!misc_1.valueOrDefault(template, "bold", parseFloat, function (value) {
return !isNaN(value);
}, "0");
this._underline = !!misc_1.valueOrDefault(template, "underline", parseFloat, function (value) {
return !isNaN(value);
}, "0");
this._strikeThrough = !!misc_1.valueOrDefault(template, "strikeout", parseFloat, function (value) {
return !isNaN(value);
}, "0");
this._fontName = misc_1.valueOrDefault(template, "fontname", function (str) {
return str;
}, function (value) {
return value.constructor === String;
}, "sans-serif");
this._fontSize = misc_1.valueOrDefault(template, "fontsize", parseFloat, function (value) {
return !isNaN(value);
}, "18");
this._fontScaleX = misc_1.valueOrDefault(template, "scalex", parseFloat, function (value) {
return value >= 0;
}, "100") / 100;
this._fontScaleY = misc_1.valueOrDefault(template, "scaley", parseFloat, function (value) {
return value >= 0;
}, "100") / 100;
this._letterSpacing = misc_1.valueOrDefault(template, "spacing", parseFloat, function (value) {
return value >= 0;
}, "0");
this._rotationZ = misc_1.valueOrDefault(template, "angle", parseFloat, function (value) {
return !isNaN(value);
}, "0");
this._primaryColor = misc_1.valueOrDefault(template, "primarycolour", function (str) {
return parse_1.parse(str, "colorWithAlpha");
}, null, "&H00FFFFFF");
this._secondaryColor = misc_1.valueOrDefault(template, "secondarycolour", function (str) {
return parse_1.parse(str, "colorWithAlpha");
}, null, "&H00FFFF00");
this._outlineColor = misc_1.valueOrDefault(template, "outlinecolour", function (str) {
return parse_1.parse(str, "colorWithAlpha");
}, null, "&H00000000");
this._shadowColor = misc_1.valueOrDefault(template, "backcolour", function (str) {
return parse_1.parse(str, "colorWithAlpha");
}, null, "&H80000000");
this._outlineThickness = misc_1.valueOrDefault(template, "outline", parseFloat, function (value) {
return value >= 0;
}, "2");
this._borderStyle = misc_1.valueOrDefault(template, "borderstyle", parseInt, function (value) {
return misc_1.BorderStyle[misc_1.BorderStyle[value]] === value;
}, "1");
this._shadowDepth = misc_1.valueOrDefault(template, "shadow", parseFloat, function (value) {
return value >= 0;
}, "3");
this._alignment = misc_1.valueOrDefault(template, "alignment", parseInt, function (value) {
return value >= 1 && value <= 9;
}, "2");
this._marginLeft = misc_1.valueOrDefault(template, "marginl", parseFloat, function (value) {
return !isNaN(value);
}, "20");
this._marginRight = misc_1.valueOrDefault(template, "marginr", parseFloat, function (value) {
return !isNaN(value);
}, "20");
this._marginVertical = misc_1.valueOrDefault(template, "marginv", parseFloat, function (value) {
return !isNaN(value);
}, "20");
}
Object.defineProperty(Style.prototype, "name", {
/**
* The name of this style.
*
* @type {string}
*/
get: function () {
return this._name;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "italic", {
/**
* Whether this style is italicized or not.
*
* @type {string}
*/
get: function () {
return this._italic;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "bold", {
/**
* Whether this style is bold or not.
*
* @type {boolean}
*/
get: function () {
return this._bold;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "underline", {
/**
* Whether this style is underlined or not.
*
* @type {boolean}
*/
get: function () {
return this._underline;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "strikeThrough", {
/**
* Whether this style is struck-through or not.
*
* @type {boolean}
*/
get: function () {
return this._strikeThrough;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "fontName", {
/**
* The name of this style's font.
*
* @type {string}
*/
get: function () {
return this._fontName;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "fontSize", {
/**
* The size of this style's font.
*
* @type {number}
*/
get: function () {
return this._fontSize;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "fontScaleX", {
/**
* The horizontal scaling of this style's font.
*
* @type {number}
*/
get: function () {
return this._fontScaleX;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "fontScaleY", {
/**
* The vertical scaling of this style's font.
*
* @type {number}
*/
get: function () {
return this._fontScaleY;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "letterSpacing", {
/**
* The letter spacing scaling of this style's font.
*
* @type {number}
*/
get: function () {
return this._letterSpacing;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "rotationZ", {
/**
* The default Z-rotation of this style.
*
* @type {number}
*/
get: function () {
return this._rotationZ;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "primaryColor", {
/**
* The color of this style's font.
*
* @type {!libjass.parts.Color}
*/
get: function () {
return this._primaryColor;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "secondaryColor", {
/**
* The alternate color of this style's font, used in karaoke.
*
* @type {!libjass.parts.Color}
*/
get: function () {
return this._secondaryColor;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "outlineColor", {
/**
* The color of this style's outline.
*
* @type {!libjass.parts.Color}
*/
get: function () {
return this._outlineColor;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "shadowColor", {
/**
* The color of this style's shadow.
*
* @type {!libjass.parts.Color}
*/
get: function () {
return this._shadowColor;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "outlineThickness", {
/**
* The thickness of this style's outline.
*
* @type {number}
*/
get: function () {
return this._outlineThickness;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "borderStyle", {
/**
* The border style of this style.
*
* @type {number}
*/
get: function () {
return this._borderStyle;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "shadowDepth", {
/**
* The depth of this style's shadow.
*
* @type {number}
*/
get: function () {
return this._shadowDepth;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "alignment", {
/**
* The alignment of dialogues of this style.
*
* @type {number}
*/
get: function () {
return this._alignment;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "marginLeft", {
/**
* The left margin of dialogues of this style.
*
* @type {number}
*/
get: function () {
return this._marginLeft;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "marginRight", {
/**
* The right margin of dialogues of this style.
*
* @type {number}
*/
get: function () {
return this._marginRight;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Style.prototype, "marginVertical", {
/**
* The vertical margin of dialogues of this style.
*
* @type {number}
*/
get: function () {
return this._marginVertical;
},
enumerable: true,
configurable: true
});
return Style;
}();
exports.Style = Style;
}, /* 30 ./utility/map */ function (exports) {
/**
* Set to the global implementation of Map if the environment has one, else set to {@link ./utility/map.SimpleMap}
*
* Set it to null to force {@link ./utility/map.SimpleMap} to be used even if a global Map is present.
*
* @type {function(new:Map, !Array.<!Array.<*>>=)}
*
* @memberOf libjass
*/
exports.Map = global.Map;
/**
* Map implementation for browsers that don't support it. Only supports keys which are of Number or String type, or which have a property called "id".
*
* Keys and values are stored as properties of an object, with property names derived from the key type.
*
* @param {!Array.<!Array.<*>>=} iterable Only an array of elements (where each element is a 2-tuple of key and value) is supported.
*
* @constructor
* @template K, V
* @private
*/
var SimpleMap = function () {
function SimpleMap(iterable) {
this.clear();
if (iterable === undefined) {
return;
}
if (!Array.isArray(iterable)) {
throw new Error("Non-array iterables are not supported by the SimpleMap constructor.");
}
for (var _i = 0; _i < iterable.length; _i++) {
var element = iterable[_i];
this.set(element[0], element[1]);
}
}
/**
* @param {K} key
* @return {V}
*/
SimpleMap.prototype.get = function (key) {
var property = this._keyToProperty(key);
if (property === null) {
return undefined;
}
return this._values[property];
};
/**
* @param {K} key
* @return {boolean}
*/
SimpleMap.prototype.has = function (key) {
var property = this._keyToProperty(key);
if (property === null) {
return false;
}
return property in this._keys;
};
/**
* @param {K} key
* @param {V} value
* @return {libjass.Map.<K, V>} This map
*/
SimpleMap.prototype.set = function (key, value) {
var property = this._keyToProperty(key);
if (property === null) {
throw new Error("This Map implementation only supports Number and String keys, or keys with an id property.");
}
if (!(property in this._keys)) {
this._size++;
}
this._keys[property] = key;
this._values[property] = value;
return this;
};
/**
* @param {K} key
* @return {boolean} true if the key was present before being deleted, false otherwise
*/
SimpleMap.prototype.delete = function (key) {
var property = this._keyToProperty(key);
if (property === null) {
return false;
}
var result = property in this._keys;
if (result) {
delete this._keys[property];
delete this._values[property];
this._size--;
}
return result;
};
/**
*/
SimpleMap.prototype.clear = function () {
this._keys = Object.create(null);
this._values = Object.create(null);
this._size = 0;
};
/**
* @param {function(V, K, libjass.Map.<K, V>)} callbackfn A function that is called with each key and value in the map.
* @param {*} thisArg
*/
SimpleMap.prototype.forEach = function (callbackfn, thisArg) {
for (var _i = 0, _a = Object.keys(this._keys); _i < _a.length; _i++) {
var property = _a[_i];
callbackfn.call(thisArg, this._values[property], this._keys[property], this);
}
};
Object.defineProperty(SimpleMap.prototype, "size", {
/**
* @type {number}
*/
get: function () {
return this._size;
},
enumerable: true,
configurable: true
});
/**
* Converts the given key into a property name for the internal map.
*
* @param {K} key
* @return {string}
*
* @private
*/
SimpleMap.prototype._keyToProperty = function (key) {
if (typeof key === "number") {
return "#" + key;
}
if (typeof key === "string") {
return "'" + key;
}
if (key.id !== undefined) {
return "!" + key.id;
}
return null;
};
return SimpleMap;
}();
if (exports.Map === undefined || typeof exports.Map.prototype.forEach !== "function" || function () {
try {
return new exports.Map([ [ 1, "foo" ], [ 2, "bar" ] ]).size !== 2;
} catch (ex) {
return true;
}
}()) {
exports.Map = SimpleMap;
}
/**
* Sets the Map implementation used by libjass to the provided one. If null, {@link ./utility/map.SimpleMap} is used.
*
* @param {?function(new:Map, !Array.<!Array.<*>>=)} value
*/
function setImplementation(value) {
if (value !== null) {
exports.Map = value;
} else {
exports.Map = SimpleMap;
}
}
exports.setImplementation = setImplementation;
}, /* 31 ./utility/mixin */ function (exports) {
/**
* Adds properties of the given mixins' prototypes to the given class's prototype.
*
* @param {!*} clazz
* @param {!Array.<*>} mixins
*/
function mixin(clazz, mixins) {
for (var _i = 0; _i < mixins.length; _i++) {
var mixin_1 = mixins[_i];
for (var _a = 0, _b = Object.getOwnPropertyNames(mixin_1.prototype); _a < _b.length; _a++) {
var name_1 = _b[_a];
clazz.prototype[name_1] = mixin_1.prototype[name_1];
}
}
}
exports.mixin = mixin;
}, /* 32 ./utility/promise */ function (exports) {
/**
* Set to the global implementation of Promise if the environment has one, else set to {@link ./utility/promise.SimplePromise}
*
* Set it to null to force {@link ./utility/promise.SimplePromise} to be used even if a global Promise is present.
*
* @type {function(new:Promise)}
*
* @memberOf libjass
*/
exports.Promise = global.Promise;
// Based on https://github.com/petkaantonov/bluebird/blob/1b1467b95442c12378d0ea280ede61d640ab5510/src/schedule.js
var enqueueJob = function () {
var MutationObserver = global.MutationObserver || global.WebkitMutationObserver;
if (global.process !== undefined && typeof global.process.nextTick === "function") {
return function (callback) {
global.process.nextTick(callback);
};
} else if (MutationObserver !== undefined) {
var pending = [];
var currentlyPending = false;
var div = document.createElement("div");
var observer = new MutationObserver(function () {
var processing = pending.splice(0, pending.length);
for (var _i = 0; _i < processing.length; _i++) {
var callback = processing[_i];
callback();
}
currentlyPending = false;
if (pending.length > 0) {
div.classList.toggle("foo");
currentlyPending = true;
}
});
observer.observe(div, {
attributes: true
});
return function (callback) {
pending.push(callback);
if (!currentlyPending) {
div.classList.toggle("foo");
currentlyPending = true;
}
};
} else {
return function (callback) {
return setTimeout(callback, 0);
};
}
}();
/**
* Promise implementation for browsers that don't support it.
*
* @param {function(function(T|!Thenable.<T>), function(*))} executor
*
* @constructor
* @template T
* @private
*/
var SimplePromise = function () {
function SimplePromise(executor) {
this._state = SimplePromiseState.PENDING;
this._fulfillReactions = [];
this._rejectReactions = [];
this._fulfilledValue = null;
this._rejectedReason = null;
if (typeof executor !== "function") {
throw new TypeError('typeof executor !== "function"');
}
var _a = this._createResolvingFunctions();
var resolve = _a.resolve;
var reject = _a.reject;
try {
executor(resolve, reject);
} catch (ex) {
reject(ex);
}
}
/**
* @param {?function(T):(U|!Thenable.<U>)} onFulfilled
* @param {?function(*):(U|!Thenable.<U>)} onRejected
* @return {!Promise.<U>}
*
* @template U
*/
SimplePromise.prototype.then = function (onFulfilled, onRejected) {
var resultCapability = new DeferredPromise();
if (typeof onFulfilled !== "function") {
onFulfilled = function (value) {
return value;
};
}
if (typeof onRejected !== "function") {
onRejected = function (reason) {
throw reason;
};
}
var fulfillReaction = {
capabilities: resultCapability,
handler: onFulfilled
};
var rejectReaction = {
capabilities: resultCapability,
handler: onRejected
};
switch (this._state) {
case SimplePromiseState.PENDING:
this._fulfillReactions.push(fulfillReaction);
this._rejectReactions.push(rejectReaction);
break;
case SimplePromiseState.FULFILLED:
this._enqueueFulfilledReactionJob(fulfillReaction, this._fulfilledValue);
break;
case SimplePromiseState.REJECTED:
this._enqueueRejectedReactionJob(rejectReaction, this._rejectedReason);
break;
}
return resultCapability.promise;
};
/**
* @param {function(*):(T|!Thenable.<T>)} onRejected
* @return {!Promise.<T>}
*/
SimplePromise.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
};
/**
* @param {T|!Thenable.<T>} value
* @return {!Promise.<T>}
*
* @template T
* @static
*/
SimplePromise.resolve = function (value) {
if (value instanceof SimplePromise) {
return value;
}
return new exports.Promise(function (resolve) {
return resolve(value);
});
};
/**
* @param {*} reason
* @return {!Promise.<T>}
*
* @template T
* @static
*/
SimplePromise.reject = function (reason) {
return new exports.Promise(function (/* ujs:unreferenced */ resolve, reject) {
return reject(reason);
});
};
/**
* @param {!Array.<T|!Thenable.<T>>} values
* @return {!Promise.<!Array.<T>>}
*
* @template T
* @static
*/
SimplePromise.all = function (values) {
return new exports.Promise(function (resolve, reject) {
var result = [];
var numUnresolved = values.length;
if (numUnresolved === 0) {
resolve(result);
return;
}
values.forEach(function (value, index) {
return exports.Promise.resolve(value).then(function (value) {
result[index] = value;
numUnresolved--;
if (numUnresolved === 0) {
resolve(result);
}
}, reject);
});
});
};
/**
* @param {!Array.<T|!Thenable.<T>>} values
* @return {!Promise.<T>}
*
* @template T
* @static
*/
SimplePromise.race = function (values) {
return new exports.Promise(function (resolve, reject) {
for (var _i = 0; _i < values.length; _i++) {
var value = values[_i];
exports.Promise.resolve(value).then(resolve, reject);
}
});
};
/**
* @return {{ resolve(T|!Thenable.<T>), reject(*) }}
*
* @private
*/
SimplePromise.prototype._createResolvingFunctions = function () {
var _this = this;
var alreadyResolved = false;
var resolve = function (resolution) {
if (alreadyResolved) {
return;
}
alreadyResolved = true;
if (resolution === _this) {
_this._reject(new TypeError("resolution === this"));
return;
}
if (resolution === null || typeof resolution !== "object" && typeof resolution !== "function") {
_this._fulfill(resolution);
return;
}
try {
var then = resolution.then;
} catch (ex) {
_this._reject(ex);
return;
}
if (typeof then !== "function") {
_this._fulfill(resolution);
return;
}
enqueueJob(function () {
return _this._resolveWithThenable(resolution, then);
});
};
var reject = function (reason) {
if (alreadyResolved) {
return;
}
alreadyResolved = true;
_this._reject(reason);
};
return {
resolve: resolve,
reject: reject
};
};
/**
* @param {!Thenable.<T>} thenable
* @param {{function(this:!Thenable.<T>, function(T|!Thenable.<T>), function(*))}} then
*
* @private
*/
SimplePromise.prototype._resolveWithThenable = function (thenable, then) {
var _a = this._createResolvingFunctions();
var resolve = _a.resolve;
var reject = _a.reject;
try {
then.call(thenable, resolve, reject);
} catch (ex) {
reject(ex);
}
};
/**
* @param {T} value
*
* @private
*/
SimplePromise.prototype._fulfill = function (value) {
var reactions = this._fulfillReactions;
this._fulfilledValue = value;
this._fulfillReactions = undefined;
this._rejectReactions = undefined;
this._state = SimplePromiseState.FULFILLED;
for (var _i = 0; _i < reactions.length; _i++) {
var reaction = reactions[_i];
this._enqueueFulfilledReactionJob(reaction, value);
}
};
/**
* @param {*} reason
*
* @private
*/
SimplePromise.prototype._reject = function (reason) {
var reactions = this._rejectReactions;
this._rejectedReason = reason;
this._fulfillReactions = undefined;
this._rejectReactions = undefined;
this._state = SimplePromiseState.REJECTED;
for (var _i = 0; _i < reactions.length; _i++) {
var reaction = reactions[_i];
this._enqueueRejectedReactionJob(reaction, reason);
}
};
/**
* @param {!FulfilledPromiseReaction.<T, *>} reaction
* @param {T} value
*
* @private
*/
SimplePromise.prototype._enqueueFulfilledReactionJob = function (reaction, value) {
enqueueJob(function () {
var _a = reaction.capabilities;
var resolve = _a.resolve;
var reject = _a.reject;
var handler = reaction.handler;
var handlerResult;
try {
handlerResult = handler(value);
} catch (ex) {
reject(ex);
return;
}
resolve(handlerResult);
});
};
/**
* @param {!RejectedPromiseReaction.<*>} reaction
* @param {*} reason
*
* @private
*/
SimplePromise.prototype._enqueueRejectedReactionJob = function (reaction, reason) {
enqueueJob(function () {
var _a = reaction.capabilities;
var resolve = _a.resolve;
var reject = _a.reject;
var handler = reaction.handler;
var handlerResult;
try {
handlerResult = handler(reason);
} catch (ex) {
reject(ex);
return;
}
resolve(handlerResult);
});
};
return SimplePromise;
}();
if (exports.Promise === undefined) {
exports.Promise = SimplePromise;
}
/**
* The state of the {@link ./utility/promise.SimplePromise}
*
* @enum
* @private
*/
var SimplePromiseState;
(function (SimplePromiseState) {
SimplePromiseState[SimplePromiseState["PENDING"] = 0] = "PENDING";
SimplePromiseState[SimplePromiseState["FULFILLED"] = 1] = "FULFILLED";
SimplePromiseState[SimplePromiseState["REJECTED"] = 2] = "REJECTED";
})(SimplePromiseState || (SimplePromiseState = {}));
/**
* Sets the Promise implementation used by libjass to the provided one. If null, {@link ./utility/promise.SimplePromise} is used.
*
* @param {?function(new:Promise)} value
*/
function setImplementation(value) {
if (value !== null) {
exports.Promise = value;
} else {
exports.Promise = SimplePromise;
}
}
exports.setImplementation = setImplementation;
/**
* A deferred promise.
*
* @constructor
* @memberOf libjass
* @template T
*/
var DeferredPromise = function () {
function DeferredPromise() {
var _this = this;
this._promise = new exports.Promise(function (resolve, reject) {
Object.defineProperties(_this, {
resolve: {
value: resolve,
enumerable: true
},
reject: {
value: reject,
enumerable: true
}
});
});
}
Object.defineProperty(DeferredPromise.prototype, "promise", {
/**
* @type {!Promise.<T>}
*/
get: function () {
return this._promise;
},
enumerable: true,
configurable: true
});
return DeferredPromise;
}();
exports.DeferredPromise = DeferredPromise;
/**
* Returns a promise that resolves to the first (in iteration order) promise that fulfills, and rejects if all the promises reject.
*
* @param {!Array.<!Promise.<T>>} promises
* @return {!Promise.<T>}
*
* @template T
*/
function first(promises) {
return first_rec(promises, []);
}
exports.first = first;
/**
* @param {!Array.<!Promise.<T>>} promises
* @param {!Array.<*>} previousRejections
* @return {!Promise.<T>}
*
* @template T
* @private
*/
function first_rec(promises, previousRejections) {
if (promises.length === 0) {
return exports.Promise.reject(previousRejections);
}
var head = promises[0];
var tail = promises.slice(1);
return head.catch(function (reason) {
return first_rec(tail, previousRejections.concat(reason));
});
}
/**
* Returns a promise that resolves to the first (in time order) promise that fulfills, and rejects if all the promises reject.
*
* @param {!Array.<!Promise.<T>>} promises
* @return {!Promise.<T>}
*
* @template T
*/
function any(promises) {
return new exports.Promise(function (resolve, reject) {
return exports.Promise.all(promises.map(function (promise) {
return promise.then(resolve, function (reason) {
return reason;
});
})).then(reject);
});
}
exports.any = any;
/**
* Returns a promise that runs the given callback when the promise has resolved regardless of whether it fulfilled or rejected.
*
* @param {!Promise.<T>} promise
* @param {function()} body
* @return {!Promise.<T>}
*
* @template T
*/
function lastly(promise, body) {
return promise.then(function (value) {
body();
return value;
}, function (reason) {
body();
throw reason;
});
}
exports.lastly = lastly;
}, /* 33 ./utility/set */ function (exports) {
/**
* Set to the global implementation of Set if the environment has one, else set to {@link ./utility/set.SimpleSet}
*
* Set it to null to force {@link ./utility/set.SimpleSet} to be used even if a global Set is present.
*
* @type {function(new:Set, !Array.<T>=)}
*
* @memberOf libjass
*/
exports.Set = global.Set;
/**
* Set implementation for browsers that don't support it. Only supports Number and String elements.
*
* Elements are stored as properties of an object, with names derived from their type.
*
* @param {!Array.<T>=} iterable Only an array of values is supported.
*
* @constructor
* @template T
* @private
*/
var SimpleSet = function () {
function SimpleSet(iterable) {
this.clear();
if (iterable === undefined) {
return;
}
if (!Array.isArray(iterable)) {
throw new Error("Non-array iterables are not supported by the SimpleSet constructor.");
}
for (var _i = 0; _i < iterable.length; _i++) {
var value = iterable[_i];
this.add(value);
}
}
/**
* @param {T} value
* @return {libjass.Set.<T>} This set
*/
SimpleSet.prototype.add = function (value) {
var property = this._toProperty(value);
if (property === null) {
throw new Error("This Set implementation only supports Number and String values.");
}
if (!(property in this._elements)) {
this._size++;
}
this._elements[property] = value;
return this;
};
/**
*/
SimpleSet.prototype.clear = function () {
this._elements = Object.create(null);
this._size = 0;
};
/**
* @param {T} value
* @return {boolean}
*/
SimpleSet.prototype.has = function (value) {
var property = this._toProperty(value);
if (property === null) {
return false;
}
return property in this._elements;
};
/**
* @param {function(T, T, libjass.Set.<T>)} callbackfn A function that is called with each value in the set.
* @param {*} thisArg
*/
SimpleSet.prototype.forEach = function (callbackfn, thisArg) {
for (var _i = 0, _a = Object.keys(this._elements); _i < _a.length; _i++) {
var property = _a[_i];
var element = this._elements[property];
callbackfn.call(thisArg, element, element, this);
}
};
Object.defineProperty(SimpleSet.prototype, "size", {
/**
* @type {number}
*/
get: function () {
return this._size;
},
enumerable: true,
configurable: true
});
/**
* Converts the given value into a property name for the internal map.
*
* @param {T} value
* @return {string}
*
* @private
*/
SimpleSet.prototype._toProperty = function (value) {
if (typeof value === "number") {
return "#" + value;
}
if (typeof value === "string") {
return "'" + value;
}
return null;
};
return SimpleSet;
}();
if (exports.Set === undefined || typeof exports.Set.prototype.forEach !== "function" || function () {
try {
return new exports.Set([ 1, 2 ]).size !== 2;
} catch (ex) {
return true;
}
}()) {
exports.Set = SimpleSet;
}
/**
* Sets the Set implementation used by libjass to the provided one. If null, {@link ./utility/set.SimpleSet} is used.
*
* @param {?function(new:Set, !Array.<T>=)} value
*/
function setImplementation(value) {
if (value !== null) {
exports.Set = value;
} else {
exports.Set = SimpleSet;
}
}
exports.setImplementation = setImplementation;
}, /* 34 ./utility/ts-helpers */ function (exports) {
/**
* Class inheritance shim.
*
* @param {!Function} derived
* @param {!Function} base
*/
function __extends(derived, base) {
for (var property in base) {
if (base.hasOwnProperty(property)) {
derived[property] = base[property];
}
}
function __() {
this.constructor = derived;
}
__.prototype = base.prototype;
derived.prototype = new __();
}
exports.__extends = __extends;
/**
* Decorator shim.
*
* @param {!Array.<!Function>} decorators
* @param {!*} target
* @param {string=} key
* @return {*}
*/
function __decorate(decorators, target, key) {
if (arguments.length < 3) {
return decorateClass(decorators.reverse(), target);
} else {
decorateField(decorators.reverse(), target, key);
}
}
exports.__decorate = __decorate;
/**
* Class decorator shim.
*
* @param {!Array.<function(function(new(): T)): function(new(): T)>} decorators
* @param {function(new(): T)} clazz
* @return {function(new(): T)}
*
* @template T
* @private
*/
function decorateClass(decorators, clazz) {
for (var _i = 0; _i < decorators.length; _i++) {
var decorator = decorators[_i];
clazz = decorator(clazz) || clazz;
}
return clazz;
}
/**
* Class member decorator shim.
*
* @param {!Array.<function(T, string)>} decorators
* @param {!T} proto
* @param {string} name
*
* @template T
* @private
*/
function decorateField(decorators, proto, name) {
for (var _i = 0; _i < decorators.length; _i++) {
var decorator = decorators[_i];
decorator(proto, name);
}
}
}, /* 35 ./webworker/channel */ function (exports, require) {
var map_1 = require(30);
var promise_1 = require(32);
var commands_1 = require(36);
var misc_1 = require(38);
/**
* Internal implementation of libjass.webworker.WorkerChannel
*
* @param {!*} comm The object used to talk to the other side of the channel. When created by the main thread, this is the Worker object.
* When created by the web worker, this is its global object.
*
* @constructor
* @implements {libjass.webworker.WorkerChannel}
*/
var WorkerChannelImpl = function () {
function WorkerChannelImpl(comm) {
var _this = this;
this._comm = comm;
this._pendingRequests = new map_1.Map();
this._comm.addEventListener("message", function (ev) {
return _this._onMessage(ev.data);
}, false);
}
/**
* @param {number} command
* @param {*} parameters
* @return {!Promise.<*>}
*/
WorkerChannelImpl.prototype.request = function (command, parameters) {
var deferred = new promise_1.DeferredPromise();
var requestId = ++WorkerChannelImpl._lastRequestId;
this._pendingRequests.set(requestId, deferred);
var requestMessage = {
requestId: requestId,
command: command,
parameters: parameters
};
this._comm.postMessage(misc_1.serialize(requestMessage));
return deferred.promise;
};
/**
* @param {number} requestId
*/
WorkerChannelImpl.prototype.cancelRequest = function (requestId) {
var deferred = this._pendingRequests.get(requestId);
if (deferred === undefined) {
return;
}
this._pendingRequests.delete(requestId);
deferred.reject(new Error("Cancelled."));
};
/**
* @param {!WorkerResponseMessage} message
*
* @private
*/
WorkerChannelImpl.prototype._respond = function (message) {
var requestId = message.requestId;
var error = message.error;
var result = message.result;
if (error instanceof Error) {
error = {
message: error.message,
stack: error.stack
};
}
this._comm.postMessage(misc_1.serialize({
command: commands_1.WorkerCommands.Response,
requestId: requestId,
error: error,
result: result
}));
};
/**
* @param {string} rawMessage
*
* @private
*/
WorkerChannelImpl.prototype._onMessage = function (rawMessage) {
var _this = this;
var message = misc_1.deserialize(rawMessage);
if (message.command === commands_1.WorkerCommands.Response) {
var responseMessage = message;
var deferred = this._pendingRequests.get(responseMessage.requestId);
if (deferred !== undefined) {
this._pendingRequests.delete(responseMessage.requestId);
if (responseMessage.error === null) {
deferred.resolve(responseMessage.result);
} else {
deferred.reject(responseMessage.error);
}
}
} else {
var requestMessage = message;
var requestId = requestMessage.requestId;
var commandCallback = misc_1.getWorkerCommandHandler(requestMessage.command);
if (commandCallback === undefined) {
this._respond({
requestId: requestId,
error: new Error("No handler registered for command " + requestMessage.command),
result: null
});
return;
}
commandCallback(requestMessage.parameters).then(function (result) {
return {
requestId: requestId,
error: null,
result: result
};
}, function (error) {
return {
requestId: requestId,
error: error,
result: null
};
}).then(function (responseMessage) {
return _this._respond(responseMessage);
});
}
};
WorkerChannelImpl._lastRequestId = -1;
return WorkerChannelImpl;
}();
exports.WorkerChannelImpl = WorkerChannelImpl;
misc_1.registerWorkerCommand(commands_1.WorkerCommands.Ping, function () {
return new promise_1.Promise(function (resolve) {
return resolve(null);
});
});
}, /* 36 ./webworker/commands */ function (exports) {
/**
* The commands that can be sent to or from a web worker.
*/
(function (WorkerCommands) {
WorkerCommands[WorkerCommands["Response"] = 0] = "Response";
WorkerCommands[WorkerCommands["Parse"] = 1] = "Parse";
WorkerCommands[WorkerCommands["Ping"] = 2] = "Ping";
})(exports.WorkerCommands || (exports.WorkerCommands = {}));
}, /* 37 ./webworker/index */ function (exports, require) {
var channel_1 = require(35);
var commands_1 = require(36);
exports.WorkerCommands = commands_1.WorkerCommands;
/**
* Indicates whether web workers are supposed in this environment or not.
*
* @type {boolean}
*
* @memberOf libjass.webworker
*/
exports.supported = typeof Worker !== "undefined";
var _scriptNode = typeof document !== "undefined" && document.currentScript !== undefined ? document.currentScript : null;
/**
* Create a new web worker and returns a {@link libjass.webworker.WorkerChannel} to it.
*
* @param {string=} scriptPath The path to libjass.js to be loaded in the web worker. If the browser supports document.currentScript, the parameter is optional and, if not provided,
* the path will be determined from the src attribute of the <script> element that contains the currently running copy of libjass.js
* @return {!libjass.webworker.WorkerChannel} A communication channel to the new web worker.
*
* @memberOf libjass.webworker
*/
function createWorker(scriptPath) {
if (scriptPath === void 0) {
scriptPath = _scriptNode.src;
}
return new channel_1.WorkerChannelImpl(new Worker(scriptPath));
}
exports.createWorker = createWorker;
if (typeof WorkerGlobalScope !== "undefined" && global instanceof WorkerGlobalScope) {
// This is a web worker. Set up a channel to talk back to the main thread.
new channel_1.WorkerChannelImpl(global);
}
}, /* 38 ./webworker/misc */ function (exports, require) {
var map_1 = require(30);
var workerCommands = new map_1.Map();
var classPrototypes = new map_1.Map();
/**
* Registers a handler for the given worker command.
*
* @param {number} command The command that this handler will handle. One of the {@link libjass.webworker.WorkerCommands} constants.
* @param {function(*, function(*, *))} handler The handler. A function of the form (parameters: *, response: function(error: *, result: *): void): void
*/
function registerWorkerCommand(command, handler) {
workerCommands.set(command, handler);
}
exports.registerWorkerCommand = registerWorkerCommand;
/**
* Gets the handler for the given worker command.
*
* @param {number} command
* @return {?function(*, function(*, *))}
*/
function getWorkerCommandHandler(command) {
return workerCommands.get(command);
}
exports.getWorkerCommandHandler = getWorkerCommandHandler;
/**
* Registers a prototype as a deserializable type.
*
* @param {!*} prototype
*/
function registerClassPrototype(prototype) {
prototype._classTag = classPrototypes.size;
classPrototypes.set(prototype._classTag, prototype);
}
exports.registerClassPrototype = registerClassPrototype;
/**
* @param {*} obj
* @return {string}
*/
function serialize(obj) {
return JSON.stringify(obj, function (/* ujs:unreferenced */ key, value) {
if (value && value._classTag !== undefined) {
value._classTag = value._classTag;
}
return value;
});
}
exports.serialize = serialize;
/**
* @param {string} str
* @return {*}
*/
function deserialize(str) {
return JSON.parse(str, function (/* ujs:unreferenced */ key, value) {
if (value && value._classTag !== undefined) {
var hydratedValue = Object.create(classPrototypes.get(value._classTag));
for (var _i = 0, _a = Object.keys(value); _i < _a.length; _i++) {
var key_1 = _a[_i];
if (key_1 !== "_classTag") {
hydratedValue[key_1] = value[key_1];
}
}
value = hydratedValue;
}
return value;
});
}
exports.deserialize = deserialize;
} ]);
});
//# sourceMappingURL=libjass.js.map