From fd7346123e1b7fef9ed183b314ee277b048ec0e9 Mon Sep 17 00:00:00 2001 From: weizhenye Date: Sat, 7 Apr 2018 02:37:01 +0800 Subject: [PATCH] 0.0.6 --- dist/ass.esm.js | 28 +- dist/ass.js | 3702 ++++++++++++++++++++++++----------------------- dist/ass.min.js | 2 +- package.json | 2 +- 4 files changed, 1871 insertions(+), 1863 deletions(-) diff --git a/dist/ass.esm.js b/dist/ass.esm.js index cc07dbf..2acced3 100644 --- a/dist/ass.esm.js +++ b/dist/ass.esm.js @@ -26,11 +26,17 @@ function parseEffect(text) { function parseDrawing(text) { return text .toLowerCase() + // numbers + .replace(/([+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?)/g, ' $1 ') + // commands .replace(/([mnlbspc])/g, ' $1 ') .trim() .replace(/\s+/g, ' ') .split(/\s(?=[mnlbspc])/) - .map(function (cmd) { return cmd.split(' '); }); + .map(function (cmd) { return ( + cmd.split(' ') + .filter(function (x, i) { return !(i && Number.isNaN(x * 1)); }) + ); }); } var numTags = [ @@ -418,23 +424,21 @@ function compileDrawing(rawCommands) { while (i < rawCommands.length) { var arr = rawCommands[i]; var cmd = createCommand(arr); - if (cmd.type) { + if (isValid(cmd)) { if (cmd.type === 'S') { - var ref = commands[i - 1].points.slice(-1)[0]; + var ref = (commands[i - 1] || { points: [{ x: 0, y: 0 }] }).points.slice(-1)[0]; var x = ref.x; var y = ref.y; cmd.points.unshift({ x: x, y: y }); } - if (isValid(cmd)) { - if (i) { - cmd.prev = commands[i - 1].type; - commands[i - 1].next = cmd.type; - } - commands.push(cmd); + if (i) { + cmd.prev = commands[i - 1].type; + commands[i - 1].next = cmd.type; } + commands.push(cmd); i++; } else { - if (commands[i - 1].type === 'S') { + if (i && commands[i - 1].type === 'S') { var additionPoints = { p: cmd.points, c: commands[i - 1].points.slice(0, 3), @@ -1817,8 +1821,8 @@ function unbindEvents() { function resize() { var cw = this.video.clientWidth; var ch = this.video.clientHeight; - var vw = this.video.videoWidth; - var vh = this.video.videoHeight; + var vw = this.video.videoWidth || cw; + var vh = this.video.videoHeight || ch; var sw = this._.scriptRes.width; var sh = this._.scriptRes.height; var rw = sw; diff --git a/dist/ass.js b/dist/ass.js index 12709e7..f48a12d 100644 --- a/dist/ass.js +++ b/dist/ass.js @@ -1,2023 +1,2027 @@ (function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.ASS = factory()); + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.ASS = factory()); }(this, (function () { 'use strict'; -function parseEffect(text) { - var param = text - .toLowerCase() - .trim() - .split(/\s*;\s*/); - if (param[0] === 'banner') { - return { - name: param[0], - delay: param[1] * 1 || 0, - leftToRight: param[2] * 1 || 0, - fadeAwayWidth: param[3] * 1 || 0, - }; - } - if (/^scroll\s/.test(param[0])) { - return { - name: param[0], - y1: Math.min(param[1] * 1, param[2] * 1), - y2: Math.max(param[1] * 1, param[2] * 1), - delay: param[3] * 1 || 0, - fadeAwayHeight: param[4] * 1 || 0, - }; - } - return null; -} - -function parseDrawing(text) { - return text - .toLowerCase() - .replace(/([mnlbspc])/g, ' $1 ') - .trim() - .replace(/\s+/g, ' ') - .split(/\s(?=[mnlbspc])/) - .map(function (cmd) { return cmd.split(' '); }); -} - -var numTags = [ - 'b', 'i', 'u', 's', 'fsp', - 'k', 'K', 'kf', 'ko', 'kt', - 'fe', 'q', 'p', 'pbo', 'a', 'an', - 'fscx', 'fscy', 'fax', 'fay', 'frx', 'fry', 'frz', 'fr', - 'be', 'blur', 'bord', 'xbord', 'ybord', 'shad', 'xshad', 'yshad' ]; - -var numRegexs = numTags.map(function (nt) { return ({ name: nt, regex: new RegExp(("^" + nt + "-?\\d")) }); }); - -function parseTag(text) { - var assign; - - var tag = {}; - for (var i = 0; i < numRegexs.length; i++) { - var ref = numRegexs[i]; - var name = ref.name; - var regex = ref.regex; - if (regex.test(text)) { - tag[name] = text.slice(name.length) * 1; - return tag; - } - } - if (/^fn/.test(text)) { - tag.fn = text.slice(2); - } else if (/^r/.test(text)) { - tag.r = text.slice(1); - } else if (/^fs[\d+-]/.test(text)) { - tag.fs = text.slice(2); - } else if (/^\d?c&?H?[0-9a-f]+|^\d?c$/i.test(text)) { - var ref$1 = text.match(/^(\d?)c&?H?(\w*)/); - var num = ref$1[1]; - var color = ref$1[2]; - tag[("c" + (num || 1))] = color && ("000000" + color).slice(-6); - } else if (/^\da&?H?[0-9a-f]+/i.test(text)) { - var ref$2 = text.match(/^(\d)a&?H?(\w\w)/); - var num$1 = ref$2[1]; - var alpha = ref$2[2]; - tag[("a" + num$1)] = alpha; - } else if (/^alpha&?H?[0-9a-f]+/i.test(text)) { - (assign = text.match(/^alpha&?H?([0-9a-f]+)/i), tag.alpha = assign[1]); - tag.alpha = ("00" + (tag.alpha)).slice(-2); - } else if (/^(?:pos|org|move|fad|fade)\(/.test(text)) { - var ref$3 = text.match(/^(\w+)\((.*?)\)?$/); - var key = ref$3[1]; - var value = ref$3[2]; - tag[key] = value - .trim() - .split(/\s*,\s*/) - .map(Number); - } else if (/^i?clip/.test(text)) { - var p = text - .match(/^i?clip\((.*?)\)?$/)[1] + function parseEffect(text) { + var param = text + .toLowerCase() .trim() - .split(/\s*,\s*/); - tag.clip = { - inverse: /iclip/.test(text), - scale: 1, - drawing: null, - dots: null, - }; - if (p.length === 1) { - tag.clip.drawing = parseDrawing(p[0]); - } - if (p.length === 2) { - tag.clip.scale = p[0] * 1; - tag.clip.drawing = parseDrawing(p[1]); + .split(/\s*;\s*/); + if (param[0] === 'banner') { + return { + name: param[0], + delay: param[1] * 1 || 0, + leftToRight: param[2] * 1 || 0, + fadeAwayWidth: param[3] * 1 || 0, + }; } - if (p.length === 4) { - tag.clip.dots = p.map(Number); + if (/^scroll\s/.test(param[0])) { + return { + name: param[0], + y1: Math.min(param[1] * 1, param[2] * 1), + y2: Math.max(param[1] * 1, param[2] * 1), + delay: param[3] * 1 || 0, + fadeAwayHeight: param[4] * 1 || 0, + }; } - } else if (/^t\(/.test(text)) { - var p$1 = text - .match(/^t\((.*?)\)?$/)[1] + return null; + } + + function parseDrawing(text) { + return text + .toLowerCase() + // numbers + .replace(/([+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?)/g, ' $1 ') + // commands + .replace(/([mnlbspc])/g, ' $1 ') .trim() - .replace(/\\.*/, function (x) { return x.replace(/,/g, '\n'); }) - .split(/\s*,\s*/); - if (!p$1[0]) { return tag; } - tag.t = { - t1: 0, - t2: 0, - accel: 1, - tags: p$1[p$1.length - 1] - .replace(/\n/g, ',') - .split('\\') - .slice(1) - .map(parseTag), - }; - if (p$1.length === 2) { - tag.t.accel = p$1[0] * 1; - } - if (p$1.length === 3) { - tag.t.t1 = p$1[0] * 1; - tag.t.t2 = p$1[1] * 1; + .replace(/\s+/g, ' ') + .split(/\s(?=[mnlbspc])/) + .map(function (cmd) { return ( + cmd.split(' ') + .filter(function (x, i) { return !(i && Number.isNaN(x * 1)); }) + ); }); + } + + var numTags = [ + 'b', 'i', 'u', 's', 'fsp', + 'k', 'K', 'kf', 'ko', 'kt', + 'fe', 'q', 'p', 'pbo', 'a', 'an', + 'fscx', 'fscy', 'fax', 'fay', 'frx', 'fry', 'frz', 'fr', + 'be', 'blur', 'bord', 'xbord', 'ybord', 'shad', 'xshad', 'yshad' ]; + + var numRegexs = numTags.map(function (nt) { return ({ name: nt, regex: new RegExp(("^" + nt + "-?\\d")) }); }); + + function parseTag(text) { + var assign; + + var tag = {}; + for (var i = 0; i < numRegexs.length; i++) { + var ref = numRegexs[i]; + var name = ref.name; + var regex = ref.regex; + if (regex.test(text)) { + tag[name] = text.slice(name.length) * 1; + return tag; + } } - if (p$1.length === 4) { - tag.t.t1 = p$1[0] * 1; - tag.t.t2 = p$1[1] * 1; - tag.t.accel = p$1[2] * 1; + if (/^fn/.test(text)) { + tag.fn = text.slice(2); + } else if (/^r/.test(text)) { + tag.r = text.slice(1); + } else if (/^fs[\d+-]/.test(text)) { + tag.fs = text.slice(2); + } else if (/^\d?c&?H?[0-9a-f]+|^\d?c$/i.test(text)) { + var ref$1 = text.match(/^(\d?)c&?H?(\w*)/); + var num = ref$1[1]; + var color = ref$1[2]; + tag[("c" + (num || 1))] = color && ("000000" + color).slice(-6); + } else if (/^\da&?H?[0-9a-f]+/i.test(text)) { + var ref$2 = text.match(/^(\d)a&?H?(\w\w)/); + var num$1 = ref$2[1]; + var alpha = ref$2[2]; + tag[("a" + num$1)] = alpha; + } else if (/^alpha&?H?[0-9a-f]+/i.test(text)) { + (assign = text.match(/^alpha&?H?([0-9a-f]+)/i), tag.alpha = assign[1]); + tag.alpha = ("00" + (tag.alpha)).slice(-2); + } else if (/^(?:pos|org|move|fad|fade)\(/.test(text)) { + var ref$3 = text.match(/^(\w+)\((.*?)\)?$/); + var key = ref$3[1]; + var value = ref$3[2]; + tag[key] = value + .trim() + .split(/\s*,\s*/) + .map(Number); + } else if (/^i?clip/.test(text)) { + var p = text + .match(/^i?clip\((.*?)\)?$/)[1] + .trim() + .split(/\s*,\s*/); + tag.clip = { + inverse: /iclip/.test(text), + scale: 1, + drawing: null, + dots: null, + }; + if (p.length === 1) { + tag.clip.drawing = parseDrawing(p[0]); + } + if (p.length === 2) { + tag.clip.scale = p[0] * 1; + tag.clip.drawing = parseDrawing(p[1]); + } + if (p.length === 4) { + tag.clip.dots = p.map(Number); + } + } else if (/^t\(/.test(text)) { + var p$1 = text + .match(/^t\((.*?)\)?$/)[1] + .trim() + .replace(/\\.*/, function (x) { return x.replace(/,/g, '\n'); }) + .split(/\s*,\s*/); + if (!p$1[0]) { return tag; } + tag.t = { + t1: 0, + t2: 0, + accel: 1, + tags: p$1[p$1.length - 1] + .replace(/\n/g, ',') + .split('\\') + .slice(1) + .map(parseTag), + }; + if (p$1.length === 2) { + tag.t.accel = p$1[0] * 1; + } + if (p$1.length === 3) { + tag.t.t1 = p$1[0] * 1; + tag.t.t2 = p$1[1] * 1; + } + if (p$1.length === 4) { + tag.t.t1 = p$1[0] * 1; + tag.t.t2 = p$1[1] * 1; + tag.t.accel = p$1[2] * 1; + } } - } - return tag; -} - -function parseTags(text) { - var tags = []; - var depth = 0; - var str = ''; - for (var i = 0; i < text.length; i++) { - var x = text[i]; - if (x === '(') { depth++; } - if (x === ')') { depth--; } - if (depth < 0) { depth = 0; } - if (!depth && x === '\\') { - if (str) { - tags.push(str); + return tag; + } + + function parseTags(text) { + var tags = []; + var depth = 0; + var str = ''; + for (var i = 0; i < text.length; i++) { + var x = text[i]; + if (x === '(') { depth++; } + if (x === ')') { depth--; } + if (depth < 0) { depth = 0; } + if (!depth && x === '\\') { + if (str) { + tags.push(str); + } + str = ''; + } else { + str += x; } - str = ''; - } else { - str += x; } - } - tags.push(str); - return tags.map(parseTag); -} - -function parseText(text) { - var pairs = text.split(/{([^{}]*?)}/); - var parsed = []; - if (pairs[0].length) { - parsed.push({ tags: [], text: pairs[0], drawing: [] }); - } - for (var i = 1; i < pairs.length; i += 2) { - var tags = parseTags(pairs[i]); - var isDrawing = tags.reduce(function (v, tag) { return (tag.p === undefined ? v : !!tag.p); }, false); - parsed.push({ - tags: tags, - text: isDrawing ? '' : pairs[i + 1], - drawing: isDrawing ? parseDrawing(pairs[i + 1]) : [], - }); - } - return { - raw: text, - combined: parsed.map(function (frag) { return frag.text; }).join(''), - parsed: parsed, - }; -} - -function parseTime(time) { - var t = time.split(':'); - return t[0] * 3600 + t[1] * 60 + t[2] * 1; -} - -function parseDialogue(text, format) { - var fields = text.split(','); - if (fields.length > format.length) { - var textField = fields.slice(format.length - 1).join(); - fields = fields.slice(0, format.length - 1); - fields.push(textField); + tags.push(str); + return tags.map(parseTag); } - var dia = {}; - for (var i = 0; i < fields.length; i++) { - var fmt = format[i]; - var fld = fields[i].trim(); - switch (fmt) { - case 'Layer': - case 'MarginL': - case 'MarginR': - case 'MarginV': - dia[fmt] = fld * 1; - break; - case 'Start': - case 'End': - dia[fmt] = parseTime(fld); - break; - case 'Effect': - dia[fmt] = parseEffect(fld); - break; - case 'Text': - dia[fmt] = parseText(fld); - break; - default: - dia[fmt] = fld; + function parseText(text) { + var pairs = text.split(/{([^{}]*?)}/); + var parsed = []; + if (pairs[0].length) { + parsed.push({ tags: [], text: pairs[0], drawing: [] }); } + for (var i = 1; i < pairs.length; i += 2) { + var tags = parseTags(pairs[i]); + var isDrawing = tags.reduce(function (v, tag) { return (tag.p === undefined ? v : !!tag.p); }, false); + parsed.push({ + tags: tags, + text: isDrawing ? '' : pairs[i + 1], + drawing: isDrawing ? parseDrawing(pairs[i + 1]) : [], + }); + } + return { + raw: text, + combined: parsed.map(function (frag) { return frag.text; }).join(''), + parsed: parsed, + }; } - return dia; -} - -function parseFormat(text) { - return text.match(/Format\s*:\s*(.*)/i)[1].split(/\s*,\s*/); -} + function parseTime(time) { + var t = time.split(':'); + return t[0] * 3600 + t[1] * 60 + t[2] * 1; + } -function parseStyle(text) { - return text.match(/Style\s*:\s*(.*)/i)[1].split(/\s*,\s*/); -} + function parseDialogue(text, format) { + var fields = text.split(','); + if (fields.length > format.length) { + var textField = fields.slice(format.length - 1).join(); + fields = fields.slice(0, format.length - 1); + fields.push(textField); + } -function parse(text) { - var tree = { - info: {}, - styles: { format: [], style: [] }, - events: { format: [], comment: [], dialogue: [] }, - }; - var lines = text.split(/\r?\n/); - var state = 0; - for (var i = 0; i < lines.length; i++) { - var line = lines[i].trim(); - if (/^;/.test(line)) { continue; } - - if (/^\[Script Info\]/i.test(line)) { state = 1; } - else if (/^\[V4\+? Styles\]/i.test(line)) { state = 2; } - else if (/^\[Events\]/i.test(line)) { state = 3; } - else if (/^\[.*\]/.test(line)) { state = 0; } - - if (state === 0) { continue; } - if (state === 1) { - if (/:/.test(line)) { - var ref = line.match(/(.*?)\s*:\s*(.*)/); - var key = ref[1]; - var value = ref[2]; - tree.info[key] = value; + var dia = {}; + for (var i = 0; i < fields.length; i++) { + var fmt = format[i]; + var fld = fields[i].trim(); + switch (fmt) { + case 'Layer': + case 'MarginL': + case 'MarginR': + case 'MarginV': + dia[fmt] = fld * 1; + break; + case 'Start': + case 'End': + dia[fmt] = parseTime(fld); + break; + case 'Effect': + dia[fmt] = parseEffect(fld); + break; + case 'Text': + dia[fmt] = parseText(fld); + break; + default: + dia[fmt] = fld; } } - if (state === 2) { - if (/^Format\s*:/i.test(line)) { - tree.styles.format = parseFormat(line); - } - if (/^Style\s*:/i.test(line)) { - tree.styles.style.push(parseStyle(line)); + + return dia; + } + + function parseFormat(text) { + return text.match(/Format\s*:\s*(.*)/i)[1].split(/\s*,\s*/); + } + + function parseStyle(text) { + return text.match(/Style\s*:\s*(.*)/i)[1].split(/\s*,\s*/); + } + + function parse(text) { + var tree = { + info: {}, + styles: { format: [], style: [] }, + events: { format: [], comment: [], dialogue: [] }, + }; + var lines = text.split(/\r?\n/); + var state = 0; + for (var i = 0; i < lines.length; i++) { + var line = lines[i].trim(); + if (/^;/.test(line)) { continue; } + + if (/^\[Script Info\]/i.test(line)) { state = 1; } + else if (/^\[V4\+? Styles\]/i.test(line)) { state = 2; } + else if (/^\[Events\]/i.test(line)) { state = 3; } + else if (/^\[.*\]/.test(line)) { state = 0; } + + if (state === 0) { continue; } + if (state === 1) { + if (/:/.test(line)) { + var ref = line.match(/(.*?)\s*:\s*(.*)/); + var key = ref[1]; + var value = ref[2]; + tree.info[key] = value; + } } - } - if (state === 3) { - if (/^Format\s*:/i.test(line)) { - tree.events.format = parseFormat(line); + if (state === 2) { + if (/^Format\s*:/i.test(line)) { + tree.styles.format = parseFormat(line); + } + if (/^Style\s*:/i.test(line)) { + tree.styles.style.push(parseStyle(line)); + } } - if (/^(?:Comment|Dialogue)\s*:/i.test(line)) { - var ref$1 = line.match(/^(\w+?)\s*:\s*(.*)/i); - var key$1 = ref$1[1]; - var value$1 = ref$1[2]; - tree.events[key$1.toLowerCase()].push(parseDialogue(value$1, tree.events.format)); + if (state === 3) { + if (/^Format\s*:/i.test(line)) { + tree.events.format = parseFormat(line); + } + if (/^(?:Comment|Dialogue)\s*:/i.test(line)) { + var ref$1 = line.match(/^(\w+?)\s*:\s*(.*)/i); + var key$1 = ref$1[1]; + var value$1 = ref$1[2]; + tree.events[key$1.toLowerCase()].push(parseDialogue(value$1, tree.events.format)); + } } } + + return tree; } - return tree; -} - -var assign = Object.assign || ( - /* istanbul ignore next */ - function assign(target) { - var sources = [], len = arguments.length - 1; - while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ]; - - for (var i = 0; i < sources.length; i++) { - if (!sources[i]) { continue; } - var keys = Object.keys(sources[i]); - for (var j = 0; j < keys.length; j++) { - // eslint-disable-next-line no-param-reassign - target[keys[j]] = sources[i][keys[j]]; + var assign = Object.assign || ( + /* istanbul ignore next */ + function assign(target) { + var sources = [], len = arguments.length - 1; + while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ]; + + for (var i = 0; i < sources.length; i++) { + if (!sources[i]) { continue; } + var keys = Object.keys(sources[i]); + for (var j = 0; j < keys.length; j++) { + // eslint-disable-next-line no-param-reassign + target[keys[j]] = sources[i][keys[j]]; + } } + return target; } - return target; - } -); - -function createCommand(arr) { - var cmd = { - type: null, - prev: null, - next: null, - points: [], - }; - if (/[mnlbs]/.test(arr[0])) { - cmd.type = arr[0] - .toUpperCase() - .replace('N', 'L') - .replace('B', 'C'); - } - for (var len = arr.length - !(arr.length & 1), i = 1; i < len; i += 2) { - cmd.points.push({ x: arr[i] * 1, y: arr[i + 1] * 1 }); + ); + + function createCommand(arr) { + var cmd = { + type: null, + prev: null, + next: null, + points: [], + }; + if (/[mnlbs]/.test(arr[0])) { + cmd.type = arr[0] + .toUpperCase() + .replace('N', 'L') + .replace('B', 'C'); + } + for (var len = arr.length - !(arr.length & 1), i = 1; i < len; i += 2) { + cmd.points.push({ x: arr[i] * 1, y: arr[i + 1] * 1 }); + } + return cmd; } - return cmd; -} -function isValid(cmd) { - if (!cmd.points.length || !cmd.type) { - return false; + function isValid(cmd) { + if (!cmd.points.length || !cmd.type) { + return false; + } + if (/C|S/.test(cmd.type) && cmd.points.length < 3) { + return false; + } + return true; } - if (/C|S/.test(cmd.type) && cmd.points.length < 3) { - return false; + + function getViewBox(commands) { + var ref; + + var minX = Infinity; + var minY = Infinity; + var maxX = -Infinity; + var maxY = -Infinity; + (ref = []).concat.apply(ref, commands.map(function (ref) { + var points = ref.points; + + return points; + })).forEach(function (ref) { + var x = ref.x; + var y = ref.y; + + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x); + maxY = Math.max(maxY, y); + }); + return { + minX: minX, + minY: minY, + width: maxX - minX, + height: maxY - minY, + }; } - return true; -} - -function getViewBox(commands) { - var ref; - - var minX = Infinity; - var minY = Infinity; - var maxX = -Infinity; - var maxY = -Infinity; - (ref = []).concat.apply(ref, commands.map(function (ref) { - var points = ref.points; - - return points; - })).forEach(function (ref) { - var x = ref.x; - var y = ref.y; - - minX = Math.min(minX, x); - minY = Math.min(minY, y); - maxX = Math.max(maxX, x); - maxY = Math.max(maxY, y); - }); - return { - minX: minX, - minY: minY, - width: maxX - minX, - height: maxY - minY, - }; -} - -/** - * Convert S command to B command - * Reference from https://github.com/d3/d3/blob/v3.5.17/src/svg/line.js#L259 - * @param {Array} points points - * @param {String} prev type of previous command - * @param {String} next type of next command - * @return {Array} converted commands - */ -function s2b(points, prev, next) { - var results = []; - var bb1 = [0, 2 / 3, 1 / 3, 0]; - var bb2 = [0, 1 / 3, 2 / 3, 0]; - var bb3 = [0, 1 / 6, 2 / 3, 1 / 6]; - var dot4 = function (a, b) { return (a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]); }; - var px = [points[points.length - 1].x, points[0].x, points[1].x, points[2].x]; - var py = [points[points.length - 1].y, points[0].y, points[1].y, points[2].y]; - results.push({ - type: prev === 'M' ? 'M' : 'L', - points: [{ x: dot4(bb3, px), y: dot4(bb3, py) }], - }); - for (var i = 3; i < points.length; i++) { - px = [points[i - 3].x, points[i - 2].x, points[i - 1].x, points[i].x]; - py = [points[i - 3].y, points[i - 2].y, points[i - 1].y, points[i].y]; + + /** + * Convert S command to B command + * Reference from https://github.com/d3/d3/blob/v3.5.17/src/svg/line.js#L259 + * @param {Array} points points + * @param {String} prev type of previous command + * @param {String} next type of next command + * @return {Array} converted commands + */ + function s2b(points, prev, next) { + var results = []; + var bb1 = [0, 2 / 3, 1 / 3, 0]; + var bb2 = [0, 1 / 3, 2 / 3, 0]; + var bb3 = [0, 1 / 6, 2 / 3, 1 / 6]; + var dot4 = function (a, b) { return (a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]); }; + var px = [points[points.length - 1].x, points[0].x, points[1].x, points[2].x]; + var py = [points[points.length - 1].y, points[0].y, points[1].y, points[2].y]; results.push({ - type: 'C', - points: [ - { x: dot4(bb1, px), y: dot4(bb1, py) }, - { x: dot4(bb2, px), y: dot4(bb2, py) }, - { x: dot4(bb3, px), y: dot4(bb3, py) } ], + type: prev === 'M' ? 'M' : 'L', + points: [{ x: dot4(bb3, px), y: dot4(bb3, py) }], }); + for (var i = 3; i < points.length; i++) { + px = [points[i - 3].x, points[i - 2].x, points[i - 1].x, points[i].x]; + py = [points[i - 3].y, points[i - 2].y, points[i - 1].y, points[i].y]; + results.push({ + type: 'C', + points: [ + { x: dot4(bb1, px), y: dot4(bb1, py) }, + { x: dot4(bb2, px), y: dot4(bb2, py) }, + { x: dot4(bb3, px), y: dot4(bb3, py) } ], + }); + } + if (next === 'L' || next === 'C') { + var last = points[points.length - 1]; + results.push({ type: 'L', points: [{ x: last.x, y: last.y }] }); + } + return results; } - if (next === 'L' || next === 'C') { - var last = points[points.length - 1]; - results.push({ type: 'L', points: [{ x: last.x, y: last.y }] }); - } - return results; -} - -function toSVGPath(instructions) { - return instructions.map(function (ref) { - var type = ref.type; - var points = ref.points; - return ( - type + points.map(function (ref) { - var x = ref.x; - var y = ref.y; + function toSVGPath(instructions) { + return instructions.map(function (ref) { + var type = ref.type; + var points = ref.points; - return (x + "," + y); - }).join(',') - ); - }).join(''); -} - -function compileDrawing(rawCommands) { - var ref$1; - - var commands = []; - var i = 0; - while (i < rawCommands.length) { - var arr = rawCommands[i]; - var cmd = createCommand(arr); - if (cmd.type) { - if (cmd.type === 'S') { - var ref = commands[i - 1].points.slice(-1)[0]; + return ( + type + points.map(function (ref) { var x = ref.x; var y = ref.y; - cmd.points.unshift({ x: x, y: y }); - } + + return (x + "," + y); + }).join(',') + ); + }).join(''); + } + + function compileDrawing(rawCommands) { + var ref$1; + + var commands = []; + var i = 0; + while (i < rawCommands.length) { + var arr = rawCommands[i]; + var cmd = createCommand(arr); if (isValid(cmd)) { + if (cmd.type === 'S') { + var ref = (commands[i - 1] || { points: [{ x: 0, y: 0 }] }).points.slice(-1)[0]; + var x = ref.x; + var y = ref.y; + cmd.points.unshift({ x: x, y: y }); + } if (i) { cmd.prev = commands[i - 1].type; commands[i - 1].next = cmd.type; } commands.push(cmd); + i++; + } else { + if (i && commands[i - 1].type === 'S') { + var additionPoints = { + p: cmd.points, + c: commands[i - 1].points.slice(0, 3), + }; + commands[i - 1].points = commands[i - 1].points.concat( + (additionPoints[arr[0]] || []).map(function (ref) { + var x = ref.x; + var y = ref.y; + + return ({ x: x, y: y }); + }) + ); + } + rawCommands.splice(i, 1); } - i++; - } else { - if (commands[i - 1].type === 'S') { - var additionPoints = { - p: cmd.points, - c: commands[i - 1].points.slice(0, 3), - }; - commands[i - 1].points = commands[i - 1].points.concat( - (additionPoints[arr[0]] || []).map(function (ref) { - var x = ref.x; - var y = ref.y; - - return ({ x: x, y: y }); - }) - ); - } - rawCommands.splice(i, 1); } - } - var instructions = (ref$1 = []).concat.apply( - ref$1, commands.map(function (ref) { - var type = ref.type; - var points = ref.points; - var prev = ref.prev; - var next = ref.next; + var instructions = (ref$1 = []).concat.apply( + ref$1, commands.map(function (ref) { + var type = ref.type; + var points = ref.points; + var prev = ref.prev; + var next = ref.next; - return ( - type === 'S' - ? s2b(points, prev, next) - : { type: type, points: points } + return ( + type === 'S' + ? s2b(points, prev, next) + : { type: type, points: points } + ); + }) ); - }) - ); - return assign({ instructions: instructions, d: toSVGPath(instructions) }, getViewBox(commands)); -} + return assign({ instructions: instructions, d: toSVGPath(instructions) }, getViewBox(commands)); + } -var tTags = [ - 'fs', 'clip', - 'c1', 'c2', 'c3', 'c4', 'a1', 'a2', 'a3', 'a4', 'alpha', - 'fscx', 'fscy', 'fax', 'fay', 'frx', 'fry', 'frz', 'fr', - 'be', 'blur', 'bord', 'xbord', 'ybord', 'shad', 'xshad', 'yshad' ]; + var tTags = [ + 'fs', 'clip', + 'c1', 'c2', 'c3', 'c4', 'a1', 'a2', 'a3', 'a4', 'alpha', + 'fscx', 'fscy', 'fax', 'fay', 'frx', 'fry', 'frz', 'fr', + 'be', 'blur', 'bord', 'xbord', 'ybord', 'shad', 'xshad', 'yshad' ]; -function compileTag(tag, key, presets) { - var obj, obj$1, obj$2; + function compileTag(tag, key, presets) { + var obj, obj$1, obj$2; - if ( presets === void 0 ) presets = {}; - var value = tag[key]; - if (value === undefined) { - return null; - } - if (key === 'pos' || key === 'org') { - return value.length === 2 ? ( obj = {}, obj[key] = { x: value[0], y: value[1] }, obj) : null; - } - if (key === 'move') { - var x1 = value[0]; - var y1 = value[1]; - var x2 = value[2]; - var y2 = value[3]; - var t1 = value[4]; if ( t1 === void 0 ) t1 = 0; - var t2 = value[5]; if ( t2 === void 0 ) t2 = 0; - return value.length === 4 || value.length === 6 - ? { move: { x1: x1, y1: y1, x2: x2, y2: y2, t1: t1, t2: t2 } } - : null; - } - if (key === 'fad' || key === 'fade') { - if (value.length === 2) { - var t1$1 = value[0]; - var t2$1 = value[1]; - return { fade: { type: 'fad', t1: t1$1, t2: t2$1 } }; - } - if (value.length === 7) { - var a1 = value[0]; - var a2 = value[1]; - var a3 = value[2]; - var t1$2 = value[3]; - var t2$2 = value[4]; - var t3 = value[5]; - var t4 = value[6]; - return { fade: { type: 'fade', a1: a1, a2: a2, a3: a3, t1: t1$2, t2: t2$2, t3: t3, t4: t4 } }; + if ( presets === void 0 ) presets = {}; + var value = tag[key]; + if (value === undefined) { + return null; } - return null; - } - if (key === 'clip') { - var inverse = value.inverse; - var scale = value.scale; - var drawing = value.drawing; - var dots = value.dots; - if (drawing) { - return { clip: { inverse: inverse, scale: scale, drawing: compileDrawing(drawing), dots: dots } }; - } - if (dots) { - var x1$1 = dots[0]; - var y1$1 = dots[1]; - var x2$1 = dots[2]; - var y2$1 = dots[3]; - return { clip: { inverse: inverse, scale: scale, drawing: drawing, dots: { x1: x1$1, y1: y1$1, x2: x2$1, y2: y2$1 } } }; + if (key === 'pos' || key === 'org') { + return value.length === 2 ? ( obj = {}, obj[key] = { x: value[0], y: value[1] }, obj) : null; } - return null; - } - if (/^[xy]?(bord|shad)$/.test(key)) { - value = Math.max(value, 0); - } - if (key === 'bord') { - return { xbord: value, ybord: value }; - } - if (key === 'shad') { - return { xshad: value, yshad: value }; - } - if (/^c\d$/.test(key)) { - return ( obj$1 = {}, obj$1[key] = value || presets[key], obj$1); - } - if (key === 'alpha') { - return { a1: value, a2: value, a3: value, a4: value }; - } - if (key === 'fr') { - return { frz: value }; + if (key === 'move') { + var x1 = value[0]; + var y1 = value[1]; + var x2 = value[2]; + var y2 = value[3]; + var t1 = value[4]; if ( t1 === void 0 ) t1 = 0; + var t2 = value[5]; if ( t2 === void 0 ) t2 = 0; + return value.length === 4 || value.length === 6 + ? { move: { x1: x1, y1: y1, x2: x2, y2: y2, t1: t1, t2: t2 } } + : null; + } + if (key === 'fad' || key === 'fade') { + if (value.length === 2) { + var t1$1 = value[0]; + var t2$1 = value[1]; + return { fade: { type: 'fad', t1: t1$1, t2: t2$1 } }; + } + if (value.length === 7) { + var a1 = value[0]; + var a2 = value[1]; + var a3 = value[2]; + var t1$2 = value[3]; + var t2$2 = value[4]; + var t3 = value[5]; + var t4 = value[6]; + return { fade: { type: 'fade', a1: a1, a2: a2, a3: a3, t1: t1$2, t2: t2$2, t3: t3, t4: t4 } }; + } + return null; + } + if (key === 'clip') { + var inverse = value.inverse; + var scale = value.scale; + var drawing = value.drawing; + var dots = value.dots; + if (drawing) { + return { clip: { inverse: inverse, scale: scale, drawing: compileDrawing(drawing), dots: dots } }; + } + if (dots) { + var x1$1 = dots[0]; + var y1$1 = dots[1]; + var x2$1 = dots[2]; + var y2$1 = dots[3]; + return { clip: { inverse: inverse, scale: scale, drawing: drawing, dots: { x1: x1$1, y1: y1$1, x2: x2$1, y2: y2$1 } } }; + } + return null; + } + if (/^[xy]?(bord|shad)$/.test(key)) { + value = Math.max(value, 0); + } + if (key === 'bord') { + return { xbord: value, ybord: value }; + } + if (key === 'shad') { + return { xshad: value, yshad: value }; + } + if (/^c\d$/.test(key)) { + return ( obj$1 = {}, obj$1[key] = value || presets[key], obj$1); + } + if (key === 'alpha') { + return { a1: value, a2: value, a3: value, a4: value }; + } + if (key === 'fr') { + return { frz: value }; + } + if (key === 'fs') { + return { + fs: /^\+|-/.test(value) + ? (value * 1 > -10 ? (1 + value / 10) : 1) * presets.fs + : value * 1, + }; + } + if (key === 't') { + var t1$3 = value.t1; + var accel = value.accel; + var tags = value.tags; + var t2$3 = value.t2 || (presets.end - presets.start) * 1e3; + var compiledTag = {}; + tags.forEach(function (t) { + var k = Object.keys(t)[0]; + if (~tTags.indexOf(k) && !(k === 'clip' && !t[k].dots)) { + assign(compiledTag, compileTag(t, k, presets)); + } + }); + return { t: { t1: t1$3, t2: t2$3, accel: accel, tag: compiledTag } }; + } + return ( obj$2 = {}, obj$2[key] = value, obj$2); } - if (key === 'fs') { + + var a2an = [ + null, 1, 2, 3, + null, 7, 8, 9, + null, 4, 5, 6 ]; + + var globalTags = ['r', 'a', 'an', 'pos', 'org', 'move', 'fade', 'fad', 'clip']; + + function createSlice(name, styles) { return { - fs: /^\+|-/.test(value) - ? (value * 1 > -10 ? (1 + value / 10) : 1) * presets.fs - : value * 1, + name: name, + borderStyle: styles[name].style.BorderStyle, + tag: styles[name].tag, + fragments: [], }; } - if (key === 't') { - var t1$3 = value.t1; - var accel = value.accel; - var tags = value.tags; - var t2$3 = value.t2 || (presets.end - presets.start) * 1e3; - var compiledTag = {}; - tags.forEach(function (t) { - var k = Object.keys(t)[0]; - if (~tTags.indexOf(k) && !(k === 'clip' && !t[k].dots)) { - assign(compiledTag, compileTag(t, k, presets)); + + function compileText(ref) { + var styles = ref.styles; + var name = ref.name; + var parsed = ref.parsed; + var start = ref.start; + var end = ref.end; + + var alignment; + var pos; + var org; + var move; + var fade; + var clip; + var slices = []; + var slice = createSlice(name, styles); + var prevTag = {}; + for (var i = 0; i < parsed.length; i++) { + var ref$1 = parsed[i]; + var tags = ref$1.tags; + var text = ref$1.text; + var drawing = ref$1.drawing; + var reset = (void 0); + for (var j = 0; j < tags.length; j++) { + var tag = tags[j]; + reset = tag.r === undefined ? reset : tag.r; } - }); - return { t: { t1: t1$3, t2: t2$3, accel: accel, tag: compiledTag } }; - } - return ( obj$2 = {}, obj$2[key] = value, obj$2); -} - -var a2an = [ - null, 1, 2, 3, - null, 7, 8, 9, - null, 4, 5, 6 ]; - -var globalTags = ['r', 'a', 'an', 'pos', 'org', 'move', 'fade', 'fad', 'clip']; - -function createSlice(name, styles) { - return { - name: name, - borderStyle: styles[name].style.BorderStyle, - tag: styles[name].tag, - fragments: [], - }; -} - -function compileText(ref) { - var styles = ref.styles; - var name = ref.name; - var parsed = ref.parsed; - var start = ref.start; - var end = ref.end; - - var alignment; - var pos; - var org; - var move; - var fade; - var clip; - var slices = []; - var slice = createSlice(name, styles); - var prevTag = {}; - for (var i = 0; i < parsed.length; i++) { - var ref$1 = parsed[i]; - var tags = ref$1.tags; - var text = ref$1.text; - var drawing = ref$1.drawing; - var reset = (void 0); - for (var j = 0; j < tags.length; j++) { - var tag = tags[j]; - reset = tag.r === undefined ? reset : tag.r; - } - var fragment = { - tag: reset === undefined ? JSON.parse(JSON.stringify(prevTag)) : {}, - text: text, - drawing: drawing.length ? compileDrawing(drawing) : null, - }; - for (var j$1 = 0; j$1 < tags.length; j$1++) { - var tag$1 = tags[j$1]; - alignment = alignment || a2an[tag$1.a || 0] || tag$1.an; - pos = pos || compileTag(tag$1, 'pos'); - org = org || compileTag(tag$1, 'org'); - move = move || compileTag(tag$1, 'move'); - fade = fade || compileTag(tag$1, 'fade') || compileTag(tag$1, 'fad'); - clip = compileTag(tag$1, 'clip') || clip; - var key = Object.keys(tag$1)[0]; - if (key && !~globalTags.indexOf(key)) { - var ref$2 = slice.tag; - var c1 = ref$2.c1; - var c2 = ref$2.c2; - var c3 = ref$2.c3; - var c4 = ref$2.c4; - var fs = prevTag.fs || slice.tag.fs; - var compiledTag = compileTag(tag$1, key, { start: start, end: end, c1: c1, c2: c2, c3: c3, c4: c4, fs: fs }); - if (key === 't') { - fragment.tag.t = fragment.tag.t || []; - fragment.tag.t.push(compiledTag.t); - } else { - assign(fragment.tag, compiledTag); + var fragment = { + tag: reset === undefined ? JSON.parse(JSON.stringify(prevTag)) : {}, + text: text, + drawing: drawing.length ? compileDrawing(drawing) : null, + }; + for (var j$1 = 0; j$1 < tags.length; j$1++) { + var tag$1 = tags[j$1]; + alignment = alignment || a2an[tag$1.a || 0] || tag$1.an; + pos = pos || compileTag(tag$1, 'pos'); + org = org || compileTag(tag$1, 'org'); + move = move || compileTag(tag$1, 'move'); + fade = fade || compileTag(tag$1, 'fade') || compileTag(tag$1, 'fad'); + clip = compileTag(tag$1, 'clip') || clip; + var key = Object.keys(tag$1)[0]; + if (key && !~globalTags.indexOf(key)) { + var ref$2 = slice.tag; + var c1 = ref$2.c1; + var c2 = ref$2.c2; + var c3 = ref$2.c3; + var c4 = ref$2.c4; + var fs = prevTag.fs || slice.tag.fs; + var compiledTag = compileTag(tag$1, key, { start: start, end: end, c1: c1, c2: c2, c3: c3, c4: c4, fs: fs }); + if (key === 't') { + fragment.tag.t = fragment.tag.t || []; + fragment.tag.t.push(compiledTag.t); + } else { + assign(fragment.tag, compiledTag); + } } } - } - prevTag = fragment.tag; - if (reset !== undefined) { - slices.push(slice); - slice = createSlice(styles[reset] ? reset : name, styles); - } - if (fragment.text || fragment.drawing) { - var prev = slice.fragments[slice.fragments.length - 1] || {}; - if (prev.text && fragment.text && !Object.keys(fragment.tag).length) { - // merge fragment to previous if its tag is empty - prev.text += fragment.text; - } else { - slice.fragments.push(fragment); + prevTag = fragment.tag; + if (reset !== undefined) { + slices.push(slice); + slice = createSlice(styles[reset] ? reset : name, styles); + } + if (fragment.text || fragment.drawing) { + var prev = slice.fragments[slice.fragments.length - 1] || {}; + if (prev.text && fragment.text && !Object.keys(fragment.tag).length) { + // merge fragment to previous if its tag is empty + prev.text += fragment.text; + } else { + slice.fragments.push(fragment); + } } } - } - slices.push(slice); + slices.push(slice); - return assign({ alignment: alignment, slices: slices }, pos, org, move, fade, clip); -} + return assign({ alignment: alignment, slices: slices }, pos, org, move, fade, clip); + } -function compileDialogues(ref) { - var styles = ref.styles; - var dialogues = ref.dialogues; + function compileDialogues(ref) { + var styles = ref.styles; + var dialogues = ref.dialogues; - var minLayer = Infinity; - var results = []; - for (var i = 0; i < dialogues.length; i++) { - var dia = dialogues[i]; - if (dia.Start >= dia.End) { - continue; + var minLayer = Infinity; + var results = []; + for (var i = 0; i < dialogues.length; i++) { + var dia = dialogues[i]; + if (dia.Start >= dia.End) { + continue; + } + if (!styles[dia.Style]) { + dia.Style = 'Default'; + } + var stl = styles[dia.Style].style; + var compiledText = compileText({ + styles: styles, + name: dia.Style, + parsed: dia.Text.parsed, + start: dia.Start, + end: dia.End, + }); + var alignment = compiledText.alignment || stl.Alignment; + minLayer = Math.min(minLayer, dia.Layer); + results.push(assign({ + layer: dia.Layer, + start: dia.Start, + end: dia.End, + // reset style by `\r` will not effect margin and alignment + margin: { + left: dia.MarginL || stl.MarginL, + right: dia.MarginR || stl.MarginR, + vertical: dia.MarginV || stl.MarginV, + }, + effect: dia.Effect, + }, compiledText, { alignment: alignment })); } - if (!styles[dia.Style]) { - dia.Style = 'Default'; + for (var i$1 = 0; i$1 < results.length; i$1++) { + results[i$1].layer -= minLayer; } - var stl = styles[dia.Style].style; - var compiledText = compileText({ - styles: styles, - name: dia.Style, - parsed: dia.Text.parsed, - start: dia.Start, - end: dia.End, - }); - var alignment = compiledText.alignment || stl.Alignment; - minLayer = Math.min(minLayer, dia.Layer); - results.push(assign({ - layer: dia.Layer, - start: dia.Start, - end: dia.End, - // reset style by `\r` will not effect margin and alignment - margin: { - left: dia.MarginL || stl.MarginL, - right: dia.MarginR || stl.MarginR, - vertical: dia.MarginV || stl.MarginV, - }, - effect: dia.Effect, - }, compiledText, { alignment: alignment })); - } - for (var i$1 = 0; i$1 < results.length; i$1++) { - results[i$1].layer -= minLayer; - } - return results.sort(function (a, b) { return a.start - b.start || a.end - b.end; }); -} - -// same as Aegisub -// https://github.com/Aegisub/Aegisub/blob/master/src/ass_style.h -var DEFAULT_STYLE = { - Name: 'Default', - Fontname: 'Arial', - Fontsize: '20', - PrimaryColour: '&H00FFFFFF&', - SecondaryColour: '&H000000FF&', - OutlineColour: '&H00000000&', - BackColour: '&H00000000&', - Bold: '0', - Italic: '0', - Underline: '0', - StrikeOut: '0', - ScaleX: '100', - ScaleY: '100', - Spacing: '0', - Angle: '0', - BorderStyle: '1', - Outline: '2', - Shadow: '2', - Alignment: '2', - MarginL: '10', - MarginR: '10', - MarginV: '10', - Encoding: '1', -}; - -function parseStyleColor(color) { - var ref = color.match(/&H(\w\w)?(\w{6})&?/); - var a = ref[1]; - var c = ref[2]; - return [a || '00', c]; -} - -function compileStyles(ref) { - var info = ref.info; - var style = ref.style; - var format = ref.format; - var defaultStyle = ref.defaultStyle; - - var result = {}; - var styles = [ - assign({}, DEFAULT_STYLE, defaultStyle, { Name: 'Default' }) ].concat( style.map(function (stl) { - var s = {}; - for (var i = 0; i < format.length; i++) { - s[format[i]] = stl[i]; - } - return s; - }) ); - var loop = function ( i ) { - var s = styles[i]; - // this behavior is same as Aegisub by black-box testing - if (/^(\*+)Default$/.test(s.Name)) { - s.Name = 'Default'; - } - Object.keys(s).forEach(function (key) { - if (key !== 'Name' && key !== 'Fontname' && !/Colour/.test(key)) { - s[key] *= 1; + return results.sort(function (a, b) { return a.start - b.start || a.end - b.end; }); + } + + // same as Aegisub + // https://github.com/Aegisub/Aegisub/blob/master/src/ass_style.h + var DEFAULT_STYLE = { + Name: 'Default', + Fontname: 'Arial', + Fontsize: '20', + PrimaryColour: '&H00FFFFFF&', + SecondaryColour: '&H000000FF&', + OutlineColour: '&H00000000&', + BackColour: '&H00000000&', + Bold: '0', + Italic: '0', + Underline: '0', + StrikeOut: '0', + ScaleX: '100', + ScaleY: '100', + Spacing: '0', + Angle: '0', + BorderStyle: '1', + Outline: '2', + Shadow: '2', + Alignment: '2', + MarginL: '10', + MarginR: '10', + MarginV: '10', + Encoding: '1', + }; + + function parseStyleColor(color) { + var ref = color.match(/&H(\w\w)?(\w{6})&?/); + var a = ref[1]; + var c = ref[2]; + return [a || '00', c]; + } + + function compileStyles(ref) { + var info = ref.info; + var style = ref.style; + var format = ref.format; + var defaultStyle = ref.defaultStyle; + + var result = {}; + var styles = [ + assign({}, DEFAULT_STYLE, defaultStyle, { Name: 'Default' }) ].concat( style.map(function (stl) { + var s = {}; + for (var i = 0; i < format.length; i++) { + s[format[i]] = stl[i]; + } + return s; + }) ); + var loop = function ( i ) { + var s = styles[i]; + // this behavior is same as Aegisub by black-box testing + if (/^(\*+)Default$/.test(s.Name)) { + s.Name = 'Default'; } - }); - var ref$1 = parseStyleColor(s.PrimaryColour); - var a1 = ref$1[0]; - var c1 = ref$1[1]; - var ref$2 = parseStyleColor(s.SecondaryColour); - var a2 = ref$2[0]; - var c2 = ref$2[1]; - var ref$3 = parseStyleColor(s.OutlineColour); - var a3 = ref$3[0]; - var c3 = ref$3[1]; - var ref$4 = parseStyleColor(s.BackColour); - var a4 = ref$4[0]; - var c4 = ref$4[1]; - var tag = { - fn: s.Fontname, - fs: s.Fontsize, - c1: c1, - a1: a1, - c2: c2, - a2: a2, - c3: c3, - a3: a3, - c4: c4, - a4: a4, - b: Math.abs(s.Bold), - i: Math.abs(s.Italic), - u: Math.abs(s.Underline), - s: Math.abs(s.StrikeOut), - fscx: s.ScaleX, - fscy: s.ScaleY, - fsp: s.Spacing, - frz: s.Angle, - xbord: s.Outline, - ybord: s.Outline, - xshad: s.Shadow, - yshad: s.Shadow, - q: /^[0-3]$/.test(info.WrapStyle) ? info.WrapStyle * 1 : 2, + Object.keys(s).forEach(function (key) { + if (key !== 'Name' && key !== 'Fontname' && !/Colour/.test(key)) { + s[key] *= 1; + } + }); + var ref$1 = parseStyleColor(s.PrimaryColour); + var a1 = ref$1[0]; + var c1 = ref$1[1]; + var ref$2 = parseStyleColor(s.SecondaryColour); + var a2 = ref$2[0]; + var c2 = ref$2[1]; + var ref$3 = parseStyleColor(s.OutlineColour); + var a3 = ref$3[0]; + var c3 = ref$3[1]; + var ref$4 = parseStyleColor(s.BackColour); + var a4 = ref$4[0]; + var c4 = ref$4[1]; + var tag = { + fn: s.Fontname, + fs: s.Fontsize, + c1: c1, + a1: a1, + c2: c2, + a2: a2, + c3: c3, + a3: a3, + c4: c4, + a4: a4, + b: Math.abs(s.Bold), + i: Math.abs(s.Italic), + u: Math.abs(s.Underline), + s: Math.abs(s.StrikeOut), + fscx: s.ScaleX, + fscy: s.ScaleY, + fsp: s.Spacing, + frz: s.Angle, + xbord: s.Outline, + ybord: s.Outline, + xshad: s.Shadow, + yshad: s.Shadow, + q: /^[0-3]$/.test(info.WrapStyle) ? info.WrapStyle * 1 : 2, + }; + result[s.Name] = { style: s, tag: tag }; }; - result[s.Name] = { style: s, tag: tag }; - }; - for (var i = 0; i < styles.length; i++) loop( i ); - return result; -} - -function compile(text, options) { - if ( options === void 0 ) options = {}; - - var tree = parse(text); - var styles = compileStyles({ - info: tree.info, - style: tree.styles.style, - format: tree.styles.format, - defaultStyle: options.defaultStyle || {}, - }); - return { - info: tree.info, - width: tree.info.PlayResX * 1 || null, - height: tree.info.PlayResY * 1 || null, - collisions: tree.info.Collisions || 'Normal', - styles: styles, - dialogues: compileDialogues({ + for (var i = 0; i < styles.length; i++) loop( i ); + return result; + } + + function compile(text, options) { + if ( options === void 0 ) options = {}; + + var tree = parse(text); + var styles = compileStyles({ + info: tree.info, + style: tree.styles.style, + format: tree.styles.format, + defaultStyle: options.defaultStyle || {}, + }); + return { + info: tree.info, + width: tree.info.PlayResX * 1 || null, + height: tree.info.PlayResY * 1 || null, + collisions: tree.info.Collisions || 'Normal', styles: styles, - dialogues: tree.events.dialogue, - }), - }; -} - -var raf = - window.requestAnimationFrame || - window.mozRequestAnimationFrame || - window.webkitRequestAnimationFrame || - (function (cb) { return setTimeout(cb, 50 / 3); }); - -var caf = - window.cancelAnimationFrame || - window.mozCancelAnimationFrame || - window.webkitCancelAnimationFrame || - clearTimeout; - -function color2rgba(c) { - var t = c.match(/(\w\w)(\w\w)(\w\w)(\w\w)/); - var a = 1 - ("0x" + (t[1])) / 255; - var b = +("0x" + (t[2])); - var g = +("0x" + (t[3])); - var r = +("0x" + (t[4])); - return ("rgba(" + r + "," + g + "," + b + "," + a + ")"); -} - -function uuid() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - var r = Math.random() * 16 | 0; - var v = c === 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); -} - -function createSVGEl(name, attrs) { - if ( attrs === void 0 ) attrs = []; - - var $el = document.createElementNS('http://www.w3.org/2000/svg', name); - for (var i = 0; i < attrs.length; i++) { - var attr = attrs[i]; - $el.setAttributeNS( - attr[0] === 'xlink:href' ? 'http://www.w3.org/1999/xlink' : null, - attr[0], - attr[1] - ); + dialogues: compileDialogues({ + styles: styles, + dialogues: tree.events.dialogue, + }), + }; } - return $el; -} - -function getVendor(prop) { - var ref = document.body; - var style = ref.style; - var Prop = prop.replace(/^\w/, function (x) { return x.toUpperCase(); }); - if (prop in style) { return ''; } - if (("webkit" + Prop) in style) { return '-webkit-'; } - if (("moz" + Prop) in style) { return '-moz-'; } - return ''; -} - -var vendor = { - transform: getVendor('transform'), - animation: getVendor('animation'), - clipPath: getVendor('clipPath'), -}; - -var strokeTags = ['c3', 'a3', 'c4', 'a4', 'xbord', 'ybord', 'xshad', 'yshad', 'blur', 'be']; -var transformTags = ['fscx', 'fscy', 'frx', 'fry', 'frz', 'fax', 'fay']; - -function createClipPath(clip) { - var sw = this._.scriptRes.width; - var sh = this._.scriptRes.height; - var d = ''; - if (clip.dots !== null) { - var ref = clip.dots; - var x1 = ref.x1; - var y1 = ref.y1; - var x2 = ref.x2; - var y2 = ref.y2; - x1 /= sw; - y1 /= sh; - x2 /= sw; - y2 /= sh; - d = "M" + x1 + "," + y1 + "L" + x1 + "," + y2 + "," + x2 + "," + y2 + "," + x2 + "," + y1 + "Z"; + + var raf = + window.requestAnimationFrame || + window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || + (function (cb) { return setTimeout(cb, 50 / 3); }); + + var caf = + window.cancelAnimationFrame || + window.mozCancelAnimationFrame || + window.webkitCancelAnimationFrame || + clearTimeout; + + function color2rgba(c) { + var t = c.match(/(\w\w)(\w\w)(\w\w)(\w\w)/); + var a = 1 - ("0x" + (t[1])) / 255; + var b = +("0x" + (t[2])); + var g = +("0x" + (t[3])); + var r = +("0x" + (t[4])); + return ("rgba(" + r + "," + g + "," + b + "," + a + ")"); + } + + function uuid() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0; + var v = c === 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); } - if (clip.drawing !== null) { - d = clip.drawing.instructions.map(function (ref) { - var type = ref.type; - var points = ref.points; - return ( - type + points.map(function (ref) { - var x = ref.x; - var y = ref.y; + function createSVGEl(name, attrs) { + if ( attrs === void 0 ) attrs = []; - return ((x / sw) + "," + (y / sh)); - }).join(',') - ); - }).join(''); + var $el = document.createElementNS('http://www.w3.org/2000/svg', name); + for (var i = 0; i < attrs.length; i++) { + var attr = attrs[i]; + $el.setAttributeNS( + attr[0] === 'xlink:href' ? 'http://www.w3.org/1999/xlink' : null, + attr[0], + attr[1] + ); + } + return $el; } - var scale = 1 / (1 << (clip.scale - 1)); - if (clip.inverse) { - d += "M0,0L0," + scale + "," + scale + "," + scale + "," + scale + ",0,0,0Z"; + + function getVendor(prop) { + var ref = document.body; + var style = ref.style; + var Prop = prop.replace(/^\w/, function (x) { return x.toUpperCase(); }); + if (prop in style) { return ''; } + if (("webkit" + Prop) in style) { return '-webkit-'; } + if (("moz" + Prop) in style) { return '-moz-'; } + return ''; } - var id = "ASS-" + (uuid()); - var $clipPath = createSVGEl('clipPath', [ - ['id', id], - ['clipPathUnits', 'objectBoundingBox'] ]); - $clipPath.appendChild(createSVGEl('path', [ - ['d', d], - ['transform', ("scale(" + scale + ")")], - ['clip-rule', 'evenodd'] ])); - this._.$defs.appendChild($clipPath); - return { - $clipPath: $clipPath, - cssText: ((vendor.clipPath) + "clip-path:url(#" + id + ");"), + + var vendor = { + transform: getVendor('transform'), + animation: getVendor('animation'), + clipPath: getVendor('clipPath'), }; -} -function setClipPath(dialogue) { - if (!dialogue.clip) { - return; + var strokeTags = ['c3', 'a3', 'c4', 'a4', 'xbord', 'ybord', 'xshad', 'yshad', 'blur', 'be']; + var transformTags = ['fscx', 'fscy', 'frx', 'fry', 'frz', 'fax', 'fay']; + + function createClipPath(clip) { + var sw = this._.scriptRes.width; + var sh = this._.scriptRes.height; + var d = ''; + if (clip.dots !== null) { + var ref = clip.dots; + var x1 = ref.x1; + var y1 = ref.y1; + var x2 = ref.x2; + var y2 = ref.y2; + x1 /= sw; + y1 /= sh; + x2 /= sw; + y2 /= sh; + d = "M" + x1 + "," + y1 + "L" + x1 + "," + y2 + "," + x2 + "," + y2 + "," + x2 + "," + y1 + "Z"; + } + if (clip.drawing !== null) { + d = clip.drawing.instructions.map(function (ref) { + var type = ref.type; + var points = ref.points; + + return ( + type + points.map(function (ref) { + var x = ref.x; + var y = ref.y; + + return ((x / sw) + "," + (y / sh)); + }).join(',') + ); + }).join(''); + } + var scale = 1 / (1 << (clip.scale - 1)); + if (clip.inverse) { + d += "M0,0L0," + scale + "," + scale + "," + scale + "," + scale + ",0,0,0Z"; + } + var id = "ASS-" + (uuid()); + var $clipPath = createSVGEl('clipPath', [ + ['id', id], + ['clipPathUnits', 'objectBoundingBox'] ]); + $clipPath.appendChild(createSVGEl('path', [ + ['d', d], + ['transform', ("scale(" + scale + ")")], + ['clip-rule', 'evenodd'] ])); + this._.$defs.appendChild($clipPath); + return { + $clipPath: $clipPath, + cssText: ((vendor.clipPath) + "clip-path:url(#" + id + ");"), + }; } - var $fobb = document.createElement('div'); - this._.$stage.insertBefore($fobb, dialogue.$div); - $fobb.appendChild(dialogue.$div); - $fobb.className = 'ASS-fix-objectBoundingBox'; - var ref = createClipPath.call(this, dialogue.clip); - var cssText = ref.cssText; - var $clipPath = ref.$clipPath; - this._.$defs.appendChild($clipPath); - $fobb.style.cssText = cssText; - assign(dialogue, { $div: $fobb, $clipPath: $clipPath }); -} - -var $fixFontSize = document.createElement('div'); -$fixFontSize.className = 'ASS-fix-font-size'; -$fixFontSize.textContent = 'M'; - -var cache = Object.create(null); - -function getRealFontSize(fn, fs) { - var key = fn + "-" + fs; - if (!cache[key]) { - $fixFontSize.style.cssText = "font-size:" + fs + "px;font-family:\"" + fn + "\",Arial;"; - cache[key] = fs * fs / $fixFontSize.clientHeight; + + function setClipPath(dialogue) { + if (!dialogue.clip) { + return; + } + var $fobb = document.createElement('div'); + this._.$stage.insertBefore($fobb, dialogue.$div); + $fobb.appendChild(dialogue.$div); + $fobb.className = 'ASS-fix-objectBoundingBox'; + var ref = createClipPath.call(this, dialogue.clip); + var cssText = ref.cssText; + var $clipPath = ref.$clipPath; + this._.$defs.appendChild($clipPath); + $fobb.style.cssText = cssText; + assign(dialogue, { $div: $fobb, $clipPath: $clipPath }); + } + + var $fixFontSize = document.createElement('div'); + $fixFontSize.className = 'ASS-fix-font-size'; + $fixFontSize.textContent = 'M'; + + var cache = Object.create(null); + + function getRealFontSize(fn, fs) { + var key = fn + "-" + fs; + if (!cache[key]) { + $fixFontSize.style.cssText = "font-size:" + fs + "px;font-family:\"" + fn + "\",Arial;"; + cache[key] = fs * fs / $fixFontSize.clientHeight; + } + return cache[key]; } - return cache[key]; -} - -function createSVGStroke(tag, id, scale) { - var hasBorder = tag.xbord || tag.ybord; - var hasShadow = tag.xshad || tag.yshad; - var isOpaque = tag.a1 !== 'FF'; - var blur = tag.blur || tag.be || 0; - var $filter = createSVGEl('filter', [['id', id]]); - $filter.appendChild(createSVGEl('feGaussianBlur', [ - ['stdDeviation', hasBorder ? 0 : blur], - ['in', 'SourceGraphic'], - ['result', 'sg_b'] ])); - $filter.appendChild(createSVGEl('feFlood', [ - ['flood-color', color2rgba(tag.a1 + tag.c1)], - ['result', 'c1'] ])); - $filter.appendChild(createSVGEl('feComposite', [ - ['operator', 'in'], - ['in', 'c1'], - ['in2', 'sg_b'], - ['result', 'main'] ])); - if (hasBorder) { - $filter.appendChild(createSVGEl('feMorphology', [ - ['radius', ((tag.xbord * scale) + " " + (tag.ybord * scale))], - ['operator', 'dilate'], - ['in', 'SourceGraphic'], - ['result', 'dil'] ])); + + function createSVGStroke(tag, id, scale) { + var hasBorder = tag.xbord || tag.ybord; + var hasShadow = tag.xshad || tag.yshad; + var isOpaque = tag.a1 !== 'FF'; + var blur = tag.blur || tag.be || 0; + var $filter = createSVGEl('filter', [['id', id]]); $filter.appendChild(createSVGEl('feGaussianBlur', [ - ['stdDeviation', blur], - ['in', 'dil'], - ['result', 'dil_b'] ])); - $filter.appendChild(createSVGEl('feComposite', [ - ['operator', 'out'], - ['in', 'dil_b'], - ['in2', 'SourceGraphic'], - ['result', 'dil_b_o'] ])); + ['stdDeviation', hasBorder ? 0 : blur], + ['in', 'SourceGraphic'], + ['result', 'sg_b'] ])); $filter.appendChild(createSVGEl('feFlood', [ - ['flood-color', color2rgba(tag.a3 + tag.c3)], - ['result', 'c3'] ])); + ['flood-color', color2rgba(tag.a1 + tag.c1)], + ['result', 'c1'] ])); $filter.appendChild(createSVGEl('feComposite', [ ['operator', 'in'], - ['in', 'c3'], - ['in2', 'dil_b_o'], - ['result', 'border'] ])); - } - if (hasShadow && (hasBorder || isOpaque)) { - $filter.appendChild(createSVGEl('feOffset', [ - ['dx', tag.xshad * scale], - ['dy', tag.yshad * scale], - ['in', hasBorder ? 'dil' : 'SourceGraphic'], - ['result', 'off'] ])); - $filter.appendChild(createSVGEl('feGaussianBlur', [ - ['stdDeviation', blur], - ['in', 'off'], - ['result', 'off_b'] ])); - if (!isOpaque) { + ['in', 'c1'], + ['in2', 'sg_b'], + ['result', 'main'] ])); + if (hasBorder) { + $filter.appendChild(createSVGEl('feMorphology', [ + ['radius', ((tag.xbord * scale) + " " + (tag.ybord * scale))], + ['operator', 'dilate'], + ['in', 'SourceGraphic'], + ['result', 'dil'] ])); + $filter.appendChild(createSVGEl('feGaussianBlur', [ + ['stdDeviation', blur], + ['in', 'dil'], + ['result', 'dil_b'] ])); + $filter.appendChild(createSVGEl('feComposite', [ + ['operator', 'out'], + ['in', 'dil_b'], + ['in2', 'SourceGraphic'], + ['result', 'dil_b_o'] ])); + $filter.appendChild(createSVGEl('feFlood', [ + ['flood-color', color2rgba(tag.a3 + tag.c3)], + ['result', 'c3'] ])); + $filter.appendChild(createSVGEl('feComposite', [ + ['operator', 'in'], + ['in', 'c3'], + ['in2', 'dil_b_o'], + ['result', 'border'] ])); + } + if (hasShadow && (hasBorder || isOpaque)) { $filter.appendChild(createSVGEl('feOffset', [ ['dx', tag.xshad * scale], ['dy', tag.yshad * scale], - ['in', 'SourceGraphic'], - ['result', 'sg_off'] ])); + ['in', hasBorder ? 'dil' : 'SourceGraphic'], + ['result', 'off'] ])); + $filter.appendChild(createSVGEl('feGaussianBlur', [ + ['stdDeviation', blur], + ['in', 'off'], + ['result', 'off_b'] ])); + if (!isOpaque) { + $filter.appendChild(createSVGEl('feOffset', [ + ['dx', tag.xshad * scale], + ['dy', tag.yshad * scale], + ['in', 'SourceGraphic'], + ['result', 'sg_off'] ])); + $filter.appendChild(createSVGEl('feComposite', [ + ['operator', 'out'], + ['in', 'off_b'], + ['in2', 'sg_off'], + ['result', 'off_b_o'] ])); + } + $filter.appendChild(createSVGEl('feFlood', [ + ['flood-color', color2rgba(tag.a4 + tag.c4)], + ['result', 'c4'] ])); $filter.appendChild(createSVGEl('feComposite', [ - ['operator', 'out'], - ['in', 'off_b'], - ['in2', 'sg_off'], - ['result', 'off_b_o'] ])); + ['operator', 'in'], + ['in', 'c4'], + ['in2', isOpaque ? 'off_b' : 'off_b_o'], + ['result', 'shadow'] ])); } - $filter.appendChild(createSVGEl('feFlood', [ - ['flood-color', color2rgba(tag.a4 + tag.c4)], - ['result', 'c4'] ])); - $filter.appendChild(createSVGEl('feComposite', [ - ['operator', 'in'], - ['in', 'c4'], - ['in2', isOpaque ? 'off_b' : 'off_b_o'], - ['result', 'shadow'] ])); - } - var $merge = createSVGEl('feMerge', []); - if (hasShadow && (hasBorder || isOpaque)) { - $merge.appendChild(createSVGEl('feMergeNode', [['in', 'shadow']])); - } - if (hasBorder) { - $merge.appendChild(createSVGEl('feMergeNode', [['in', 'border']])); - } - $merge.appendChild(createSVGEl('feMergeNode', [['in', 'main']])); - $filter.appendChild($merge); - return $filter; -} - -function createCSSStroke(tag, scale) { - var arr = []; - var oc = color2rgba(tag.a3 + tag.c3); - var ox = tag.xbord * scale; - var oy = tag.ybord * scale; - var sc = color2rgba(tag.a4 + tag.c4); - var sx = tag.xshad * scale; - var sy = tag.yshad * scale; - var blur = tag.blur || tag.be || 0; - if (!(ox + oy + sx + sy)) { return 'none'; } - if (ox || oy) { - for (var i = -1; i <= 1; i++) { - for (var j = -1; j <= 1; j++) { - for (var x = 1; x < ox; x++) { - for (var y = 1; y < oy; y++) { - if (i || j) { - arr.push((oc + " " + (i * x) + "px " + (j * y) + "px " + blur + "px")); + var $merge = createSVGEl('feMerge', []); + if (hasShadow && (hasBorder || isOpaque)) { + $merge.appendChild(createSVGEl('feMergeNode', [['in', 'shadow']])); + } + if (hasBorder) { + $merge.appendChild(createSVGEl('feMergeNode', [['in', 'border']])); + } + $merge.appendChild(createSVGEl('feMergeNode', [['in', 'main']])); + $filter.appendChild($merge); + return $filter; + } + + function createCSSStroke(tag, scale) { + var arr = []; + var oc = color2rgba(tag.a3 + tag.c3); + var ox = tag.xbord * scale; + var oy = tag.ybord * scale; + var sc = color2rgba(tag.a4 + tag.c4); + var sx = tag.xshad * scale; + var sy = tag.yshad * scale; + var blur = tag.blur || tag.be || 0; + if (!(ox + oy + sx + sy)) { return 'none'; } + if (ox || oy) { + for (var i = -1; i <= 1; i++) { + for (var j = -1; j <= 1; j++) { + for (var x = 1; x < ox; x++) { + for (var y = 1; y < oy; y++) { + if (i || j) { + arr.push((oc + " " + (i * x) + "px " + (j * y) + "px " + blur + "px")); + } } } + arr.push((oc + " " + (i * ox) + "px " + (j * oy) + "px " + blur + "px")); } - arr.push((oc + " " + (i * ox) + "px " + (j * oy) + "px " + blur + "px")); } } - } - if (sx || sy) { - var pnx = sx > 0 ? 1 : -1; - var pny = sy > 0 ? 1 : -1; - sx = Math.abs(sx); - sy = Math.abs(sy); - for (var x$1 = Math.max(ox, sx - ox); x$1 < sx + ox; x$1++) { - for (var y$1 = Math.max(oy, sy - oy); y$1 < sy + oy; y$1++) { - arr.push((sc + " " + (x$1 * pnx) + "px " + (y$1 * pny) + "px " + blur + "px")); + if (sx || sy) { + var pnx = sx > 0 ? 1 : -1; + var pny = sy > 0 ? 1 : -1; + sx = Math.abs(sx); + sy = Math.abs(sy); + for (var x$1 = Math.max(ox, sx - ox); x$1 < sx + ox; x$1++) { + for (var y$1 = Math.max(oy, sy - oy); y$1 < sy + oy; y$1++) { + arr.push((sc + " " + (x$1 * pnx) + "px " + (y$1 * pny) + "px " + blur + "px")); + } } + arr.push((sc + " " + ((sx + ox) * pnx) + "px " + ((sy + oy) * pny) + "px " + blur + "px")); } - arr.push((sc + " " + ((sx + ox) * pnx) + "px " + ((sy + oy) * pny) + "px " + blur + "px")); - } - return arr.join(); -} - -function createTransform(tag) { - return [ - // TODO: I don't know why perspective is 314, it just performances well. - 'perspective(314px)', - ("rotateY(" + (tag.fry || 0) + "deg)"), - ("rotateX(" + (tag.frx || 0) + "deg)"), - ("rotateZ(" + (-tag.frz || 0) + "deg)"), - ("scale(" + (tag.p ? 1 : (tag.fscx || 100) / 100) + "," + (tag.p ? 1 : (tag.fscy || 100) / 100) + ")"), - ("skew(" + (tag.fax || 0) + "rad," + (tag.fay || 0) + "rad)") ].join(' '); -} - -function setTransformOrigin(dialogue) { - var alignment = dialogue.alignment; - var width = dialogue.width; - var height = dialogue.height; - var x = dialogue.x; - var y = dialogue.y; - var $div = dialogue.$div; - var org = dialogue.org; - if (!org) { - org = { x: 0, y: 0 }; - if (alignment % 3 === 1) { org.x = x; } - if (alignment % 3 === 2) { org.x = x + width / 2; } - if (alignment % 3 === 0) { org.x = x + width; } - if (alignment <= 3) { org.y = y + height; } - if (alignment >= 4 && alignment <= 6) { org.y = y + height / 2; } - if (alignment >= 7) { org.y = y; } - } - for (var i = $div.childNodes.length - 1; i >= 0; i--) { - var node = $div.childNodes[i]; - if (node.dataset.hasRotate === 'true') { - // It's not extremely precise for offsets are round the value to an integer. - var tox = org.x - x - node.offsetLeft; - var toy = org.y - y - node.offsetTop; - node.style.cssText += (vendor.transform) + "transform-origin:" + tox + "px " + toy + "px;"; + return arr.join(); + } + + function createTransform(tag) { + return [ + // TODO: I don't know why perspective is 314, it just performances well. + 'perspective(314px)', + ("rotateY(" + (tag.fry || 0) + "deg)"), + ("rotateX(" + (tag.frx || 0) + "deg)"), + ("rotateZ(" + (-tag.frz || 0) + "deg)"), + ("scale(" + (tag.p ? 1 : (tag.fscx || 100) / 100) + "," + (tag.p ? 1 : (tag.fscy || 100) / 100) + ")"), + ("skew(" + (tag.fax || 0) + "rad," + (tag.fay || 0) + "rad)") ].join(' '); + } + + function setTransformOrigin(dialogue) { + var alignment = dialogue.alignment; + var width = dialogue.width; + var height = dialogue.height; + var x = dialogue.x; + var y = dialogue.y; + var $div = dialogue.$div; + var org = dialogue.org; + if (!org) { + org = { x: 0, y: 0 }; + if (alignment % 3 === 1) { org.x = x; } + if (alignment % 3 === 2) { org.x = x + width / 2; } + if (alignment % 3 === 0) { org.x = x + width; } + if (alignment <= 3) { org.y = y + height; } + if (alignment >= 4 && alignment <= 6) { org.y = y + height / 2; } + if (alignment >= 7) { org.y = y; } + } + for (var i = $div.childNodes.length - 1; i >= 0; i--) { + var node = $div.childNodes[i]; + if (node.dataset.hasRotate === 'true') { + // It's not extremely precise for offsets are round the value to an integer. + var tox = org.x - x - node.offsetLeft; + var toy = org.y - y - node.offsetTop; + node.style.cssText += (vendor.transform) + "transform-origin:" + tox + "px " + toy + "px;"; + } } } -} - -function getKeyframeString(name, list) { - return ("@" + (vendor.animation) + "keyframes " + name + " {" + list + "}\n"); -} - -var KeyframeBlockList = function KeyframeBlockList() { - this.obj = {}; -}; -KeyframeBlockList.prototype.set = function set (keyText, prop, value) { - if (!this.obj[keyText]) { this.obj[keyText] = {}; } - this.obj[keyText][prop] = value; -}; -KeyframeBlockList.prototype.setT = function setT (ref) { - var t1 = ref.t1; - var t2 = ref.t2; - var duration = ref.duration; - var prop = ref.prop; - var from = ref.from; - var to = ref.to; - - this.set('0.000%', prop, from); - if (t1 < duration) { - this.set((((t1 / duration * 100).toFixed(3)) + "%"), prop, from); + + function getKeyframeString(name, list) { + return ("@" + (vendor.animation) + "keyframes " + name + " {" + list + "}\n"); } - if (t2 < duration) { - this.set((((t2 / duration * 100).toFixed(3)) + "%"), prop, to); + + var KeyframeBlockList = function KeyframeBlockList() { + this.obj = {}; + }; + KeyframeBlockList.prototype.set = function set (keyText, prop, value) { + if (!this.obj[keyText]) { this.obj[keyText] = {}; } + this.obj[keyText][prop] = value; + }; + KeyframeBlockList.prototype.setT = function setT (ref) { + var t1 = ref.t1; + var t2 = ref.t2; + var duration = ref.duration; + var prop = ref.prop; + var from = ref.from; + var to = ref.to; + + this.set('0.000%', prop, from); + if (t1 < duration) { + this.set((((t1 / duration * 100).toFixed(3)) + "%"), prop, from); + } + if (t2 < duration) { + this.set((((t2 / duration * 100).toFixed(3)) + "%"), prop, to); + } + this.set('100.000%', prop, to); + }; + KeyframeBlockList.prototype.toString = function toString () { + var this$1 = this; + + return Object.keys(this.obj) + .map(function (keyText) { return ( + (keyText + "{" + (Object.keys(this$1.obj[keyText]) + .map(function (prop) { return ("" + (vendor[prop] || '') + prop + ":" + (this$1.obj[keyText][prop]) + ";"); }) + .join('')) + "}") + ); }) + .join(''); + }; + + // TODO: multi \t can't be merged directly + function mergeT(ts) { + return ts.reduceRight(function (results, t) { + var merged = false; + return results + .map(function (r) { + merged = t.t1 === r.t1 && t.t2 === r.t2 && t.accel === r.accel; + return assign({}, r, merged ? { tag: assign({}, r.tag, t.tag) } : {}); + }) + .concat(merged ? [] : t); + }, []); } - this.set('100.000%', prop, to); -}; -KeyframeBlockList.prototype.toString = function toString () { + + function getKeyframes() { var this$1 = this; - return Object.keys(this.obj) - .map(function (keyText) { return ( - (keyText + "{" + (Object.keys(this$1.obj[keyText]) - .map(function (prop) { return ("" + (vendor[prop] || '') + prop + ":" + (this$1.obj[keyText][prop]) + ";"); }) - .join('')) + "}") - ); }) - .join(''); -}; - -// TODO: multi \t can't be merged directly -function mergeT(ts) { - return ts.reduceRight(function (results, t) { - var merged = false; - return results - .map(function (r) { - merged = t.t1 === r.t1 && t.t2 === r.t2 && t.accel === r.accel; - return assign({}, r, merged ? { tag: assign({}, r.tag, t.tag) } : {}); - }) - .concat(merged ? [] : t); - }, []); -} - -function getKeyframes() { - var this$1 = this; - - var keyframes = ''; - this.dialogues.forEach(function (dialogue) { - var start = dialogue.start; - var end = dialogue.end; - var effect = dialogue.effect; - var move = dialogue.move; - var fade = dialogue.fade; - var slices = dialogue.slices; - var duration = (end - start) * 1000; - var diaKbl = new KeyframeBlockList(); - // TODO: when effect and move both exist, its behavior is weird, for now only move works. - if (effect && !move) { - var name = effect.name; - var delay = effect.delay; - var lefttoright = effect.lefttoright; - var y1 = effect.y1; - var y2 = effect.y2 || this$1._.resampledRes.height; - if (name === 'banner') { - var tx = this$1.scale * (duration / delay) * (lefttoright ? 1 : -1); - diaKbl.set('0.000%', 'transform', 'translateX(0)'); - diaKbl.set('100.000%', 'transform', ("translateX(" + tx + "px)")); - } - if (/^scroll/.test(name)) { - var updown = /up/.test(name) ? -1 : 1; - var tFrom = "translateY(" + (this$1.scale * y1 * updown) + "px)"; - var tTo = "translateY(" + (this$1.scale * y2 * updown) + "px)"; - var dp = (y2 - y1) / (duration / delay) * 100; - diaKbl.set('0.000%', 'transform', tFrom); - if (dp < 100) { - diaKbl.set(((dp.toFixed(3)) + "%"), 'transform', tTo); + var keyframes = ''; + this.dialogues.forEach(function (dialogue) { + var start = dialogue.start; + var end = dialogue.end; + var effect = dialogue.effect; + var move = dialogue.move; + var fade = dialogue.fade; + var slices = dialogue.slices; + var duration = (end - start) * 1000; + var diaKbl = new KeyframeBlockList(); + // TODO: when effect and move both exist, its behavior is weird, for now only move works. + if (effect && !move) { + var name = effect.name; + var delay = effect.delay; + var lefttoright = effect.lefttoright; + var y1 = effect.y1; + var y2 = effect.y2 || this$1._.resampledRes.height; + if (name === 'banner') { + var tx = this$1.scale * (duration / delay) * (lefttoright ? 1 : -1); + diaKbl.set('0.000%', 'transform', 'translateX(0)'); + diaKbl.set('100.000%', 'transform', ("translateX(" + tx + "px)")); + } + if (/^scroll/.test(name)) { + var updown = /up/.test(name) ? -1 : 1; + var tFrom = "translateY(" + (this$1.scale * y1 * updown) + "px)"; + var tTo = "translateY(" + (this$1.scale * y2 * updown) + "px)"; + var dp = (y2 - y1) / (duration / delay) * 100; + diaKbl.set('0.000%', 'transform', tFrom); + if (dp < 100) { + diaKbl.set(((dp.toFixed(3)) + "%"), 'transform', tTo); + } + diaKbl.set('100.000%', 'transform', tTo); } - diaKbl.set('100.000%', 'transform', tTo); } - } - if (move) { - var x1 = move.x1; - var y1$1 = move.y1; - var x2 = move.x2; - var y2$1 = move.y2; - var t1 = move.t1; - var t2 = move.t2 || duration; - var pos = dialogue.pos || { x: 0, y: 0 }; - var values = [{ x: x1, y: y1$1 }, { x: x2, y: y2$1 }].map(function (ref) { - var x = ref.x; - var y = ref.y; - - return ( - ("translate(" + (this$1.scale * (x - pos.x)) + "px, " + (this$1.scale * (y - pos.y)) + "px)") - ); - }); - diaKbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'transform', from: values[0], to: values[1] }); - } - if (fade) { - if (fade.type === 'fad') { - var t1$1 = fade.t1; - var t2$1 = fade.t2; - diaKbl.set('0.000%', 'opacity', 0); - if (t1$1 < duration) { - diaKbl.set((((t1$1 / duration * 100).toFixed(3)) + "%"), 'opacity', 1); - if (t1$1 + t2$1 < duration) { - diaKbl.set(((((duration - t2$1) / duration * 100).toFixed(3)) + "%"), 'opacity', 1); + if (move) { + var x1 = move.x1; + var y1$1 = move.y1; + var x2 = move.x2; + var y2$1 = move.y2; + var t1 = move.t1; + var t2 = move.t2 || duration; + var pos = dialogue.pos || { x: 0, y: 0 }; + var values = [{ x: x1, y: y1$1 }, { x: x2, y: y2$1 }].map(function (ref) { + var x = ref.x; + var y = ref.y; + + return ( + ("translate(" + (this$1.scale * (x - pos.x)) + "px, " + (this$1.scale * (y - pos.y)) + "px)") + ); + }); + diaKbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'transform', from: values[0], to: values[1] }); + } + if (fade) { + if (fade.type === 'fad') { + var t1$1 = fade.t1; + var t2$1 = fade.t2; + diaKbl.set('0.000%', 'opacity', 0); + if (t1$1 < duration) { + diaKbl.set((((t1$1 / duration * 100).toFixed(3)) + "%"), 'opacity', 1); + if (t1$1 + t2$1 < duration) { + diaKbl.set(((((duration - t2$1) / duration * 100).toFixed(3)) + "%"), 'opacity', 1); + } + diaKbl.set('100.000%', 'opacity', 0); + } else { + diaKbl.set('100.000%', 'opacity', duration / t1$1); } - diaKbl.set('100.000%', 'opacity', 0); } else { - diaKbl.set('100.000%', 'opacity', duration / t1$1); + var a1 = fade.a1; + var a2 = fade.a2; + var a3 = fade.a3; + var t1$2 = fade.t1; + var t2$2 = fade.t2; + var t3 = fade.t3; + var t4 = fade.t4; + var keyTexts = [t1$2, t2$2, t3, t4].map(function (t) { return (((t / duration * 100).toFixed(3)) + "%"); }); + var values$1 = [a1, a2, a3].map(function (a) { return 1 - a / 255; }); + diaKbl.set('0.000%', 'opacity', values$1[0]); + if (t1$2 < duration) { diaKbl.set(keyTexts[0], 'opacity', values$1[0]); } + if (t2$2 < duration) { diaKbl.set(keyTexts[1], 'opacity', values$1[1]); } + if (t3 < duration) { diaKbl.set(keyTexts[2], 'opacity', values$1[1]); } + if (t4 < duration) { diaKbl.set(keyTexts[3], 'opacity', values$1[2]); } + diaKbl.set('100.000%', 'opacity', values$1[2]); } - } else { - var a1 = fade.a1; - var a2 = fade.a2; - var a3 = fade.a3; - var t1$2 = fade.t1; - var t2$2 = fade.t2; - var t3 = fade.t3; - var t4 = fade.t4; - var keyTexts = [t1$2, t2$2, t3, t4].map(function (t) { return (((t / duration * 100).toFixed(3)) + "%"); }); - var values$1 = [a1, a2, a3].map(function (a) { return 1 - a / 255; }); - diaKbl.set('0.000%', 'opacity', values$1[0]); - if (t1$2 < duration) { diaKbl.set(keyTexts[0], 'opacity', values$1[0]); } - if (t2$2 < duration) { diaKbl.set(keyTexts[1], 'opacity', values$1[1]); } - if (t3 < duration) { diaKbl.set(keyTexts[2], 'opacity', values$1[1]); } - if (t4 < duration) { diaKbl.set(keyTexts[3], 'opacity', values$1[2]); } - diaKbl.set('100.000%', 'opacity', values$1[2]); } - } - var diaList = diaKbl.toString(); - if (diaList) { - assign(dialogue, { animationName: ("ASS-" + (uuid())) }); - keyframes += getKeyframeString(dialogue.animationName, diaList); - } + var diaList = diaKbl.toString(); + if (diaList) { + assign(dialogue, { animationName: ("ASS-" + (uuid())) }); + keyframes += getKeyframeString(dialogue.animationName, diaList); + } + slices.forEach(function (slice) { + slice.fragments.forEach(function (fragment) { + if (!fragment.tag.t || !fragment.tag.t.length) { + return; + } + var kbl = new KeyframeBlockList(); + var fromTag = assign({}, slice.tag, fragment.tag); + // TODO: accel is not implemented yet + mergeT(fragment.tag.t).forEach(function (ref) { + var t1 = ref.t1; + var t2 = ref.t2; + var tag = ref.tag; + + if (tag.fs) { + var from = (this$1.scale * getRealFontSize(fromTag.fn, fromTag.fs)) + "px"; + var to = (this$1.scale * getRealFontSize(tag.fn, fromTag.fs)) + "px"; + kbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'font-size', from: from, to: to }); + } + if (tag.fsp) { + var from$1 = (this$1.scale * fromTag.fsp) + "px"; + var to$1 = (this$1.scale * tag.fsp) + "px"; + kbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'letter-spacing', from: from$1, to: to$1 }); + } + var hasAlpha = ( + tag.a1 !== undefined && + tag.a1 === tag.a2 && + tag.a2 === tag.a3 && + tag.a3 === tag.a4 + ); + if (tag.c1 || (tag.a1 && !hasAlpha)) { + var from$2 = color2rgba(fromTag.a1 + fromTag.c1); + var to$2 = color2rgba((tag.a1 || fromTag.a1) + (tag.c1 || fromTag.c1)); + kbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'color', from: from$2, to: to$2 }); + } + if (hasAlpha) { + var from$3 = 1 - parseInt(fromTag.a1, 16) / 255; + var to$3 = 1 - parseInt(tag.a1, 16) / 255; + kbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'opacity', from: from$3, to: to$3 }); + } + var hasStroke = strokeTags.some(function (x) { return ( + tag[x] !== undefined && + tag[x] !== (fragment.tag[x] || slice.tag[x]) + ); }); + if (hasStroke) { + var scale = /Yes/i.test(this$1.info.ScaledBorderAndShadow) ? this$1.scale : 1; + var from$4 = createCSSStroke(fromTag, scale); + var to$4 = createCSSStroke(assign({}, fromTag, tag), scale); + kbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'text-shadow', from: from$4, to: to$4 }); + } + var hasTransfrom = transformTags.some(function (x) { return ( + tag[x] !== undefined && + tag[x] !== (fragment.tag[x] || slice.tag[x]) + ); }); + if (hasTransfrom) { + var toTag = assign({}, fromTag, tag); + if (fragment.drawing) { + // scales will be handled inside svg + assign(toTag, { + p: 0, + fscx: ((tag.fscx || fromTag.fscx) / fromTag.fscx) * 100, + fscy: ((tag.fscy || fromTag.fscy) / fromTag.fscy) * 100, + }); + assign(fromTag, { fscx: 100, fscy: 100 }); + } + var from$5 = createTransform(fromTag); + var to$5 = createTransform(toTag); + kbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'transform', from: from$5, to: to$5 }); + } + }); + var list = kbl.toString(); + assign(fragment, { animationName: ("ASS-" + (uuid())) }); + keyframes += getKeyframeString(fragment.animationName, list); + }); + }); + }); + return keyframes; + } + + function createAnimation(name, duration, delay) { + var va = vendor.animation; + return ( + va + "animation-name:" + name + ";" + + va + "animation-duration:" + duration + "s;" + + va + "animation-delay:" + delay + "s;" + + va + "animation-timing-function:linear;" + + va + "animation-iteration-count:1;" + + va + "animation-fill-mode:forwards;" + ); + } + + function createDrawing(fragment, styleTag) { + var tag = assign({}, styleTag, fragment.tag); + var ref = fragment.drawing; + var minX = ref.minX; + var minY = ref.minY; + var width = ref.width; + var height = ref.height; + var baseScale = this.scale / (1 << (tag.p - 1)); + var scaleX = (tag.fscx ? tag.fscx / 100 : 1) * baseScale; + var scaleY = (tag.fscy ? tag.fscy / 100 : 1) * baseScale; + var blur = tag.blur || tag.be || 0; + var vbx = tag.xbord + (tag.xshad < 0 ? -tag.xshad : 0) + blur; + var vby = tag.ybord + (tag.yshad < 0 ? -tag.yshad : 0) + blur; + var vbw = width * scaleX + 2 * tag.xbord + Math.abs(tag.xshad) + 2 * blur; + var vbh = height * scaleY + 2 * tag.ybord + Math.abs(tag.yshad) + 2 * blur; + var $svg = createSVGEl('svg', [ + ['width', vbw], + ['height', vbh], + ['viewBox', ((-vbx) + " " + (-vby) + " " + vbw + " " + vbh)] ]); + var strokeScale = /Yes/i.test(this.info.ScaledBorderAndShadow) ? this.scale : 1; + var filterId = "ASS-" + (uuid()); + var $defs = createSVGEl('defs'); + $defs.appendChild(createSVGStroke(tag, filterId, strokeScale)); + $svg.appendChild($defs); + var symbolId = "ASS-" + (uuid()); + var $symbol = createSVGEl('symbol', [ + ['id', symbolId], + ['viewBox', (minX + " " + minY + " " + width + " " + height)] ]); + $symbol.appendChild(createSVGEl('path', [['d', fragment.drawing.d]])); + $svg.appendChild($symbol); + $svg.appendChild(createSVGEl('use', [ + ['width', width * scaleX], + ['height', height * scaleY], + ['xlink:href', ("#" + symbolId)], + ['filter', ("url(#" + filterId + ")")] ])); + $svg.style.cssText = ( + 'position:absolute;' + + "left:" + (minX * scaleX - vbx) + "px;" + + "top:" + (minY * scaleY - vby) + "px;" + ); + return { + $svg: $svg, + cssText: ("position:relative;width:" + (width * scaleX) + "px;height:" + (height * scaleY) + "px;"), + }; + } + + function encodeText(text, q) { + return text + .replace(//g, '>') + .replace(/\s/g, ' ') + .replace(/\\h/g, ' ') + .replace(/\\N/g, '
') + .replace(/\\n/g, q === 2 ? '
' : ' '); + } + + function createDialogue(dialogue) { + var this$1 = this; + + var $div = document.createElement('div'); + $div.className = 'ASS-dialogue'; + var df = document.createDocumentFragment(); + var slices = dialogue.slices; + var start = dialogue.start; + var end = dialogue.end; slices.forEach(function (slice) { + var borderStyle = slice.borderStyle; slice.fragments.forEach(function (fragment) { - if (!fragment.tag.t || !fragment.tag.t.length) { - return; - } - var kbl = new KeyframeBlockList(); - var fromTag = assign({}, slice.tag, fragment.tag); - // TODO: accel is not implemented yet - mergeT(fragment.tag.t).forEach(function (ref) { - var t1 = ref.t1; - var t2 = ref.t2; - var tag = ref.tag; - - if (tag.fs) { - var from = (this$1.scale * getRealFontSize(fromTag.fn, fromTag.fs)) + "px"; - var to = (this$1.scale * getRealFontSize(tag.fn, fromTag.fs)) + "px"; - kbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'font-size', from: from, to: to }); + var text = fragment.text; + var drawing = fragment.drawing; + var animationName = fragment.animationName; + var tag = assign({}, slice.tag, fragment.tag); + var cssText = 'display:inline-block;'; + var vct = this$1.video.currentTime; + if (!drawing) { + cssText += "font-family:\"" + (tag.fn) + "\",Arial;"; + cssText += "font-size:" + (this$1.scale * getRealFontSize(tag.fn, tag.fs)) + "px;"; + cssText += "color:" + (color2rgba(tag.a1 + tag.c1)) + ";"; + var scale = /Yes/i.test(this$1.info.ScaledBorderAndShadow) ? this$1.scale : 1; + if (borderStyle === 1) { + cssText += "text-shadow:" + (createCSSStroke(tag, scale)) + ";"; } - if (tag.fsp) { - var from$1 = (this$1.scale * fromTag.fsp) + "px"; - var to$1 = (this$1.scale * tag.fsp) + "px"; - kbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'letter-spacing', from: from$1, to: to$1 }); + if (borderStyle === 3) { + cssText += ( + "background-color:" + (color2rgba(tag.a3 + tag.c3)) + ";" + + "box-shadow:" + (createCSSStroke(tag, scale)) + ";" + ); } - var hasAlpha = ( - tag.a1 !== undefined && - tag.a1 === tag.a2 && - tag.a2 === tag.a3 && - tag.a3 === tag.a4 - ); - if (tag.c1 || (tag.a1 && !hasAlpha)) { - var from$2 = color2rgba(fromTag.a1 + fromTag.c1); - var to$2 = color2rgba((tag.a1 || fromTag.a1) + (tag.c1 || fromTag.c1)); - kbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'color', from: from$2, to: to$2 }); + cssText += tag.b ? ("font-weight:" + (tag.b === 1 ? 'bold' : tag.b) + ";") : ''; + cssText += tag.i ? 'font-style:italic;' : ''; + cssText += (tag.u || tag.s) ? ("text-decoration:" + (tag.u ? 'underline' : '') + " " + (tag.s ? 'line-through' : '') + ";") : ''; + cssText += tag.fsp ? ("letter-spacing:" + (tag.fsp) + "px;") : ''; + // TODO: (tag.q === 0) and (tag.q === 3) are not implemented yet, + // for now just handle it as (tag.q === 1) + if (tag.q === 1 || tag.q === 0 || tag.q === 3) { + cssText += 'word-break:break-all;white-space:normal;'; } - if (hasAlpha) { - var from$3 = 1 - parseInt(fromTag.a1, 16) / 255; - var to$3 = 1 - parseInt(tag.a1, 16) / 255; - kbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'opacity', from: from$3, to: to$3 }); + if (tag.q === 2) { + cssText += 'word-break:normal;white-space:nowrap;'; } - var hasStroke = strokeTags.some(function (x) { return ( - tag[x] !== undefined && - tag[x] !== (fragment.tag[x] || slice.tag[x]) - ); }); - if (hasStroke) { - var scale = /Yes/i.test(this$1.info.ScaledBorderAndShadow) ? this$1.scale : 1; - var from$4 = createCSSStroke(fromTag, scale); - var to$4 = createCSSStroke(assign({}, fromTag, tag), scale); - kbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'text-shadow', from: from$4, to: to$4 }); + } + var hasTransfrom = transformTags.some(function (x) { return ( + /^fsc[xy]$/.test(x) ? tag[x] !== 100 : !!tag[x] + ); }); + if (hasTransfrom) { + cssText += (vendor.transform) + "transform:" + (createTransform(tag)) + ";"; + if (!drawing) { + cssText += 'transform-style:preserve-3d;word-break:normal;white-space:nowrap;'; } - var hasTransfrom = transformTags.some(function (x) { return ( - tag[x] !== undefined && - tag[x] !== (fragment.tag[x] || slice.tag[x]) - ); }); - if (hasTransfrom) { - var toTag = assign({}, fromTag, tag); - if (fragment.drawing) { - // scales will be handled inside svg - assign(toTag, { - p: 0, - fscx: ((tag.fscx || fromTag.fscx) / fromTag.fscx) * 100, - fscy: ((tag.fscy || fromTag.fscy) / fromTag.fscy) * 100, - }); - assign(fromTag, { fscx: 100, fscy: 100 }); + } + if (animationName) { + cssText += createAnimation(animationName, end - start, Math.min(0, start - vct)); + } + if (drawing && tag.pbo) { + var pbo = this$1.scale * -tag.pbo * (tag.fscy || 100) / 100; + cssText += "vertical-align:" + pbo + "px;"; + } + + var hasRotate = /"fr[xyz]":[^0]/.test(JSON.stringify(tag)); + encodeText(text, tag.q).split('
').forEach(function (html, idx) { + var $span = document.createElement('span'); + $span.dataset.hasRotate = hasRotate; + if (drawing) { + var obj = createDrawing.call(this$1, fragment, slice.tag); + $span.style.cssText = obj.cssText; + $span.appendChild(obj.$svg); + } else { + if (idx) { + df.appendChild(document.createElement('br')); + } + if (!html) { + return; } - var from$5 = createTransform(fromTag); - var to$5 = createTransform(toTag); - kbl.setT({ t1: t1, t2: t2, duration: duration, prop: 'transform', from: from$5, to: to$5 }); + $span.innerHTML = html; } + // TODO: maybe it can be optimized + $span.style.cssText += cssText; + df.appendChild($span); }); - var list = kbl.toString(); - assign(fragment, { animationName: ("ASS-" + (uuid())) }); - keyframes += getKeyframeString(fragment.animationName, list); }); }); - }); - return keyframes; -} - -function createAnimation(name, duration, delay) { - var va = vendor.animation; - return ( - va + "animation-name:" + name + ";" + - va + "animation-duration:" + duration + "s;" + - va + "animation-delay:" + delay + "s;" + - va + "animation-timing-function:linear;" + - va + "animation-iteration-count:1;" + - va + "animation-fill-mode:forwards;" - ); -} - -function createDrawing(fragment, styleTag) { - var tag = assign({}, styleTag, fragment.tag); - var ref = fragment.drawing; - var minX = ref.minX; - var minY = ref.minY; - var width = ref.width; - var height = ref.height; - var baseScale = this.scale / (1 << (tag.p - 1)); - var scaleX = (tag.fscx ? tag.fscx / 100 : 1) * baseScale; - var scaleY = (tag.fscy ? tag.fscy / 100 : 1) * baseScale; - var blur = tag.blur || tag.be || 0; - var vbx = tag.xbord + (tag.xshad < 0 ? -tag.xshad : 0) + blur; - var vby = tag.ybord + (tag.yshad < 0 ? -tag.yshad : 0) + blur; - var vbw = width * scaleX + 2 * tag.xbord + Math.abs(tag.xshad) + 2 * blur; - var vbh = height * scaleY + 2 * tag.ybord + Math.abs(tag.yshad) + 2 * blur; - var $svg = createSVGEl('svg', [ - ['width', vbw], - ['height', vbh], - ['viewBox', ((-vbx) + " " + (-vby) + " " + vbw + " " + vbh)] ]); - var strokeScale = /Yes/i.test(this.info.ScaledBorderAndShadow) ? this.scale : 1; - var filterId = "ASS-" + (uuid()); - var $defs = createSVGEl('defs'); - $defs.appendChild(createSVGStroke(tag, filterId, strokeScale)); - $svg.appendChild($defs); - var symbolId = "ASS-" + (uuid()); - var $symbol = createSVGEl('symbol', [ - ['id', symbolId], - ['viewBox', (minX + " " + minY + " " + width + " " + height)] ]); - $symbol.appendChild(createSVGEl('path', [['d', fragment.drawing.d]])); - $svg.appendChild($symbol); - $svg.appendChild(createSVGEl('use', [ - ['width', width * scaleX], - ['height', height * scaleY], - ['xlink:href', ("#" + symbolId)], - ['filter', ("url(#" + filterId + ")")] ])); - $svg.style.cssText = ( - 'position:absolute;' + - "left:" + (minX * scaleX - vbx) + "px;" + - "top:" + (minY * scaleY - vby) + "px;" - ); - return { - $svg: $svg, - cssText: ("position:relative;width:" + (width * scaleX) + "px;height:" + (height * scaleY) + "px;"), - }; -} - -function encodeText(text, q) { - return text - .replace(//g, '>') - .replace(/\s/g, ' ') - .replace(/\\h/g, ' ') - .replace(/\\N/g, '
') - .replace(/\\n/g, q === 2 ? '
' : ' '); -} - -function createDialogue(dialogue) { - var this$1 = this; - - var $div = document.createElement('div'); - $div.className = 'ASS-dialogue'; - var df = document.createDocumentFragment(); - var slices = dialogue.slices; - var start = dialogue.start; - var end = dialogue.end; - slices.forEach(function (slice) { - var borderStyle = slice.borderStyle; - slice.fragments.forEach(function (fragment) { - var text = fragment.text; - var drawing = fragment.drawing; - var animationName = fragment.animationName; - var tag = assign({}, slice.tag, fragment.tag); - var cssText = 'display:inline-block;'; - var vct = this$1.video.currentTime; - if (!drawing) { - cssText += "font-family:\"" + (tag.fn) + "\",Arial;"; - cssText += "font-size:" + (this$1.scale * getRealFontSize(tag.fn, tag.fs)) + "px;"; - cssText += "color:" + (color2rgba(tag.a1 + tag.c1)) + ";"; - var scale = /Yes/i.test(this$1.info.ScaledBorderAndShadow) ? this$1.scale : 1; - if (borderStyle === 1) { - cssText += "text-shadow:" + (createCSSStroke(tag, scale)) + ";"; - } - if (borderStyle === 3) { - cssText += ( - "background-color:" + (color2rgba(tag.a3 + tag.c3)) + ";" + - "box-shadow:" + (createCSSStroke(tag, scale)) + ";" - ); - } - cssText += tag.b ? ("font-weight:" + (tag.b === 1 ? 'bold' : tag.b) + ";") : ''; - cssText += tag.i ? 'font-style:italic;' : ''; - cssText += (tag.u || tag.s) ? ("text-decoration:" + (tag.u ? 'underline' : '') + " " + (tag.s ? 'line-through' : '') + ";") : ''; - cssText += tag.fsp ? ("letter-spacing:" + (tag.fsp) + "px;") : ''; - // TODO: (tag.q === 0) and (tag.q === 3) are not implemented yet, - // for now just handle it as (tag.q === 1) - if (tag.q === 1 || tag.q === 0 || tag.q === 3) { - cssText += 'word-break:break-all;white-space:normal;'; - } - if (tag.q === 2) { - cssText += 'word-break:normal;white-space:nowrap;'; - } + $div.appendChild(df); + return $div; + } + + function allocate(dialogue) { + var layer = dialogue.layer; + var margin = dialogue.margin; + var width = dialogue.width; + var height = dialogue.height; + var alignment = dialogue.alignment; + var end = dialogue.end; + var stageWidth = this.width - (this.scale * (margin.left + margin.right) | 0); + var stageHeight = this.height; + var vertical = this.scale * margin.vertical | 0; + var vct = this.video.currentTime * 100; + this._.space[layer] = this._.space[layer] || { + left: { width: new Uint16Array(stageHeight + 1), end: new Uint16Array(stageHeight + 1) }, + center: { width: new Uint16Array(stageHeight + 1), end: new Uint16Array(stageHeight + 1) }, + right: { width: new Uint16Array(stageHeight + 1), end: new Uint16Array(stageHeight + 1) }, + }; + var channel = this._.space[layer]; + var align = ['right', 'left', 'center'][alignment % 3]; + var willCollide = function (y) { + var lw = channel.left.width[y]; + var cw = channel.center.width[y]; + var rw = channel.right.width[y]; + var le = channel.left.end[y]; + var ce = channel.center.end[y]; + var re = channel.right.end[y]; + return ( + (align === 'left' && ( + (le > vct && lw) || + (ce > vct && cw && 2 * width + cw > stageWidth) || + (re > vct && rw && width + rw > stageWidth) + )) || + (align === 'center' && ( + (le > vct && lw && 2 * lw + width > stageWidth) || + (ce > vct && cw) || + (re > vct && rw && 2 * rw + width > stageWidth) + )) || + (align === 'right' && ( + (le > vct && lw && lw + width > stageWidth) || + (ce > vct && cw && 2 * width + cw > stageWidth) || + (re > vct && rw) + )) + ); + }; + var count = 0; + var result = 0; + var find = function (y) { + count = willCollide(y) ? 0 : count + 1; + if (count >= height) { + result = y; + return true; } - var hasTransfrom = transformTags.some(function (x) { return ( - /^fsc[xy]$/.test(x) ? tag[x] !== 100 : !!tag[x] - ); }); - if (hasTransfrom) { - cssText += (vendor.transform) + "transform:" + (createTransform(tag)) + ";"; - if (!drawing) { - cssText += 'transform-style:preserve-3d;word-break:normal;white-space:nowrap;'; - } + return false; + }; + if (alignment <= 3) { + for (var i = stageHeight - vertical - 1; i > vertical; i--) { + if (find(i)) { break; } } - if (animationName) { - cssText += createAnimation(animationName, end - start, Math.min(0, start - vct)); + } else if (alignment >= 7) { + for (var i$1 = vertical + 1; i$1 < stageHeight - vertical; i$1++) { + if (find(i$1)) { break; } } - if (drawing && tag.pbo) { - var pbo = this$1.scale * -tag.pbo * (tag.fscy || 100) / 100; - cssText += "vertical-align:" + pbo + "px;"; + } else { + for (var i$2 = (stageHeight - height) >> 1; i$2 < stageHeight - vertical; i$2++) { + if (find(i$2)) { break; } } - - var hasRotate = /"fr[xyz]":[^0]/.test(JSON.stringify(tag)); - encodeText(text, tag.q).split('
').forEach(function (html, idx) { - var $span = document.createElement('span'); - $span.dataset.hasRotate = hasRotate; - if (drawing) { - var obj = createDrawing.call(this$1, fragment, slice.tag); - $span.style.cssText = obj.cssText; - $span.appendChild(obj.$svg); - } else { - if (idx) { - df.appendChild(document.createElement('br')); - } - if (!html) { - return; - } - $span.innerHTML = html; - } - // TODO: maybe it can be optimized - $span.style.cssText += cssText; - df.appendChild($span); - }); - }); - }); - $div.appendChild(df); - return $div; -} - -function allocate(dialogue) { - var layer = dialogue.layer; - var margin = dialogue.margin; - var width = dialogue.width; - var height = dialogue.height; - var alignment = dialogue.alignment; - var end = dialogue.end; - var stageWidth = this.width - (this.scale * (margin.left + margin.right) | 0); - var stageHeight = this.height; - var vertical = this.scale * margin.vertical | 0; - var vct = this.video.currentTime * 100; - this._.space[layer] = this._.space[layer] || { - left: { width: new Uint16Array(stageHeight + 1), end: new Uint16Array(stageHeight + 1) }, - center: { width: new Uint16Array(stageHeight + 1), end: new Uint16Array(stageHeight + 1) }, - right: { width: new Uint16Array(stageHeight + 1), end: new Uint16Array(stageHeight + 1) }, - }; - var channel = this._.space[layer]; - var align = ['right', 'left', 'center'][alignment % 3]; - var willCollide = function (y) { - var lw = channel.left.width[y]; - var cw = channel.center.width[y]; - var rw = channel.right.width[y]; - var le = channel.left.end[y]; - var ce = channel.center.end[y]; - var re = channel.right.end[y]; - return ( - (align === 'left' && ( - (le > vct && lw) || - (ce > vct && cw && 2 * width + cw > stageWidth) || - (re > vct && rw && width + rw > stageWidth) - )) || - (align === 'center' && ( - (le > vct && lw && 2 * lw + width > stageWidth) || - (ce > vct && cw) || - (re > vct && rw && 2 * rw + width > stageWidth) - )) || - (align === 'right' && ( - (le > vct && lw && lw + width > stageWidth) || - (ce > vct && cw && 2 * width + cw > stageWidth) || - (re > vct && rw) - )) - ); - }; - var count = 0; - var result = 0; - var find = function (y) { - count = willCollide(y) ? 0 : count + 1; - if (count >= height) { - result = y; - return true; - } - return false; - }; - if (alignment <= 3) { - for (var i = stageHeight - vertical - 1; i > vertical; i--) { - if (find(i)) { break; } } - } else if (alignment >= 7) { - for (var i$1 = vertical + 1; i$1 < stageHeight - vertical; i$1++) { - if (find(i$1)) { break; } + if (alignment > 3) { + result -= height - 1; } - } else { - for (var i$2 = (stageHeight - height) >> 1; i$2 < stageHeight - vertical; i$2++) { - if (find(i$2)) { break; } + for (var i$3 = result; i$3 < result + height; i$3++) { + channel[align].width[i$3] = width; + channel[align].end[i$3] = end * 100; } + return result; } - if (alignment > 3) { - result -= height - 1; - } - for (var i$3 = result; i$3 < result + height; i$3++) { - channel[align].width[i$3] = width; - channel[align].end[i$3] = end * 100; - } - return result; -} - -function getPosition(dialogue) { - var effect = dialogue.effect; - var move = dialogue.move; - var alignment = dialogue.alignment; - var width = dialogue.width; - var height = dialogue.height; - var margin = dialogue.margin; - var slices = dialogue.slices; - var x = 0; - var y = 0; - if (effect) { - if (effect.name === 'banner') { - if (alignment <= 3) { y = this.height - height - margin.vertical; } - if (alignment >= 4 && alignment <= 6) { y = (this.height - height) / 2; } - if (alignment >= 7) { y = margin.vertical; } - x = effect.lefttoright ? -width : this.width; - } - } else if (dialogue.pos || move) { - var pos = dialogue.pos || { x: 0, y: 0 }; - if (alignment % 3 === 1) { x = this.scale * pos.x; } - if (alignment % 3 === 2) { x = this.scale * pos.x - width / 2; } - if (alignment % 3 === 0) { x = this.scale * pos.x - width; } - if (alignment <= 3) { y = this.scale * pos.y - height; } - if (alignment >= 4 && alignment <= 6) { y = this.scale * pos.y - height / 2; } - if (alignment >= 7) { y = this.scale * pos.y; } - } else { - if (alignment % 3 === 1) { x = 0; } - if (alignment % 3 === 2) { x = (this.width - width) / 2; } - if (alignment % 3 === 0) { x = this.width - width - this.scale * margin.right; } - var hasT = slices.some(function (slice) { return ( - slice.fragments.some(function (ref) { - var animationName = ref.animationName; - - return animationName; - }) - ); }); - if (hasT) { - if (alignment <= 3) { y = this.height - height - margin.vertical; } - if (alignment >= 4 && alignment <= 6) { y = (this.height - height) / 2; } - if (alignment >= 7) { y = margin.vertical; } + + function getPosition(dialogue) { + var effect = dialogue.effect; + var move = dialogue.move; + var alignment = dialogue.alignment; + var width = dialogue.width; + var height = dialogue.height; + var margin = dialogue.margin; + var slices = dialogue.slices; + var x = 0; + var y = 0; + if (effect) { + if (effect.name === 'banner') { + if (alignment <= 3) { y = this.height - height - margin.vertical; } + if (alignment >= 4 && alignment <= 6) { y = (this.height - height) / 2; } + if (alignment >= 7) { y = margin.vertical; } + x = effect.lefttoright ? -width : this.width; + } + } else if (dialogue.pos || move) { + var pos = dialogue.pos || { x: 0, y: 0 }; + if (alignment % 3 === 1) { x = this.scale * pos.x; } + if (alignment % 3 === 2) { x = this.scale * pos.x - width / 2; } + if (alignment % 3 === 0) { x = this.scale * pos.x - width; } + if (alignment <= 3) { y = this.scale * pos.y - height; } + if (alignment >= 4 && alignment <= 6) { y = this.scale * pos.y - height / 2; } + if (alignment >= 7) { y = this.scale * pos.y; } } else { - y = allocate.call(this, dialogue); + if (alignment % 3 === 1) { x = 0; } + if (alignment % 3 === 2) { x = (this.width - width) / 2; } + if (alignment % 3 === 0) { x = this.width - width - this.scale * margin.right; } + var hasT = slices.some(function (slice) { return ( + slice.fragments.some(function (ref) { + var animationName = ref.animationName; + + return animationName; + }) + ); }); + if (hasT) { + if (alignment <= 3) { y = this.height - height - margin.vertical; } + if (alignment >= 4 && alignment <= 6) { y = (this.height - height) / 2; } + if (alignment >= 7) { y = margin.vertical; } + } else { + y = allocate.call(this, dialogue); + } } + return { x: x, y: y }; } - return { x: x, y: y }; -} - -function createStyle(dialogue) { - var layer = dialogue.layer; - var start = dialogue.start; - var end = dialogue.end; - var alignment = dialogue.alignment; - var effect = dialogue.effect; - var pos = dialogue.pos; - var margin = dialogue.margin; - var animationName = dialogue.animationName; - var width = dialogue.width; - var height = dialogue.height; - var x = dialogue.x; - var y = dialogue.y; - var vct = this.video.currentTime; - var cssText = ''; - if (layer) { cssText += "z-index:" + layer + ";"; } - if (animationName) { - cssText += createAnimation(animationName, end - start, Math.min(0, start - vct)); - } - cssText += "text-align:" + (['right', 'left', 'center'][alignment % 3]) + ";"; - if (!effect) { - var mw = this.width - this.scale * (margin.left + margin.right); - cssText += "max-width:" + mw + "px;"; - if (!pos) { - if (alignment % 3 === 1) { - cssText += "margin-left:" + (this.scale * margin.left) + "px;"; + + function createStyle(dialogue) { + var layer = dialogue.layer; + var start = dialogue.start; + var end = dialogue.end; + var alignment = dialogue.alignment; + var effect = dialogue.effect; + var pos = dialogue.pos; + var margin = dialogue.margin; + var animationName = dialogue.animationName; + var width = dialogue.width; + var height = dialogue.height; + var x = dialogue.x; + var y = dialogue.y; + var vct = this.video.currentTime; + var cssText = ''; + if (layer) { cssText += "z-index:" + layer + ";"; } + if (animationName) { + cssText += createAnimation(animationName, end - start, Math.min(0, start - vct)); + } + cssText += "text-align:" + (['right', 'left', 'center'][alignment % 3]) + ";"; + if (!effect) { + var mw = this.width - this.scale * (margin.left + margin.right); + cssText += "max-width:" + mw + "px;"; + if (!pos) { + if (alignment % 3 === 1) { + cssText += "margin-left:" + (this.scale * margin.left) + "px;"; + } + if (alignment % 3 === 0) { + cssText += "margin-right:" + (this.scale * margin.right) + "px;"; + } + if (width > this.width - this.scale * (margin.left + margin.right)) { + cssText += "margin-left:" + (this.scale * margin.left) + "px;"; + cssText += "margin-right:" + (this.scale * margin.right) + "px;"; + } } - if (alignment % 3 === 0) { - cssText += "margin-right:" + (this.scale * margin.right) + "px;"; + } + cssText += "width:" + width + "px;height:" + height + "px;left:" + x + "px;top:" + y + "px;"; + return cssText; + } + + function renderer(dialogue) { + var $div = createDialogue.call(this, dialogue); + assign(dialogue, { $div: $div }); + this._.$stage.appendChild($div); + var ref = $div.getBoundingClientRect(); + var width = ref.width; + var height = ref.height; + assign(dialogue, { width: width, height: height }); + assign(dialogue, getPosition.call(this, dialogue)); + $div.style.cssText = createStyle.call(this, dialogue); + setTransformOrigin(dialogue); + setClipPath.call(this, dialogue); + return dialogue; + } + + function framing() { + var this$1 = this; + + var vct = this.video.currentTime; + for (var i = this._.stagings.length - 1; i >= 0; i--) { + var dia = this$1._.stagings[i]; + var end = dia.end; + if (dia.effect && /scroll/.test(dia.effect.name)) { + var ref = dia.effect; + var y1 = ref.y1; + var y2 = ref.y2; + var delay = ref.delay; + var duration = ((y2 || this$1._.resampledRes.height) - y1) / (1000 / delay); + end = Math.min(end, dia.start + duration); } - if (width > this.width - this.scale * (margin.left + margin.right)) { - cssText += "margin-left:" + (this.scale * margin.left) + "px;"; - cssText += "margin-right:" + (this.scale * margin.right) + "px;"; + if (end < vct) { + this$1._.$stage.removeChild(dia.$div); + if (dia.$clipPath) { + this$1._.$defs.removeChild(dia.$clipPath); + } + this$1._.stagings.splice(i, 1); } } - } - cssText += "width:" + width + "px;height:" + height + "px;left:" + x + "px;top:" + y + "px;"; - return cssText; -} - -function renderer(dialogue) { - var $div = createDialogue.call(this, dialogue); - assign(dialogue, { $div: $div }); - this._.$stage.appendChild($div); - var ref = $div.getBoundingClientRect(); - var width = ref.width; - var height = ref.height; - assign(dialogue, { width: width, height: height }); - assign(dialogue, getPosition.call(this, dialogue)); - $div.style.cssText = createStyle.call(this, dialogue); - setTransformOrigin(dialogue); - setClipPath.call(this, dialogue); - return dialogue; -} - -function framing() { - var this$1 = this; - - var vct = this.video.currentTime; - for (var i = this._.stagings.length - 1; i >= 0; i--) { - var dia = this$1._.stagings[i]; - var end = dia.end; - if (dia.effect && /scroll/.test(dia.effect.name)) { - var ref = dia.effect; - var y1 = ref.y1; - var y2 = ref.y2; - var delay = ref.delay; - var duration = ((y2 || this$1._.resampledRes.height) - y1) / (1000 / delay); - end = Math.min(end, dia.start + duration); - } - if (end < vct) { - this$1._.$stage.removeChild(dia.$div); - if (dia.$clipPath) { - this$1._.$defs.removeChild(dia.$clipPath); + var dias = this.dialogues; + while ( + this._.index < dias.length && + vct >= dias[this._.index].start + ) { + if (vct < dias[this$1._.index].end) { + var dia$1 = renderer.call(this$1, dias[this$1._.index]); + this$1._.stagings.push(dia$1); } - this$1._.stagings.splice(i, 1); + ++this$1._.index; } } - var dias = this.dialogues; - while ( - this._.index < dias.length && - vct >= dias[this._.index].start - ) { - if (vct < dias[this$1._.index].end) { - var dia$1 = renderer.call(this$1, dias[this$1._.index]); - this$1._.stagings.push(dia$1); - } - ++this$1._.index; - } -} -function play() { - var this$1 = this; + function play() { + var this$1 = this; - var frame = function () { - framing.call(this$1); - this$1._.requestId = raf(frame); - }; - this._.requestId = raf(frame); - this._.$stage.classList.remove('ASS-animation-paused'); - return this; -} - -function pause() { - caf(this._.requestId); - this._.requestId = 0; - this._.$stage.classList.add('ASS-animation-paused'); - return this; -} - -function clear() { - var this$1 = this; - - while (this._.$stage.lastChild) { - this$1._.$stage.removeChild(this$1._.$stage.lastChild); + var frame = function () { + framing.call(this$1); + this$1._.requestId = raf(frame); + }; + this._.requestId = raf(frame); + this._.$stage.classList.remove('ASS-animation-paused'); + return this; } - while (this._.$defs.lastChild) { - this$1._.$defs.removeChild(this$1._.$defs.lastChild); + + function pause() { + caf(this._.requestId); + this._.requestId = 0; + this._.$stage.classList.add('ASS-animation-paused'); + return this; } - this._.stagings = []; - this._.space = []; -} - -function seek() { - var vct = this.video.currentTime; - var dias = this.dialogues; - clear.call(this); - this._.index = (function () { - var from = 0; - var to = dias.length - 1; - while (from + 1 < to && vct > dias[(to + from) >> 1].end) { - from = (to + from) >> 1; - } - if (!from) { return 0; } - for (var i = from; i < to; i++) { - if ( - dias[i].end > vct && vct >= dias[i].start || - i && dias[i - 1].end < vct && vct < dias[i].start - ) { - return i; + + function clear() { + var this$1 = this; + + while (this._.$stage.lastChild) { + this$1._.$stage.removeChild(this$1._.$stage.lastChild); + } + while (this._.$defs.lastChild) { + this$1._.$defs.removeChild(this$1._.$defs.lastChild); + } + this._.stagings = []; + this._.space = []; + } + + function seek() { + var vct = this.video.currentTime; + var dias = this.dialogues; + clear.call(this); + this._.index = (function () { + var from = 0; + var to = dias.length - 1; + while (from + 1 < to && vct > dias[(to + from) >> 1].end) { + from = (to + from) >> 1; } + if (!from) { return 0; } + for (var i = from; i < to; i++) { + if ( + dias[i].end > vct && vct >= dias[i].start || + i && dias[i - 1].end < vct && vct < dias[i].start + ) { + return i; + } + } + return to; + })(); + framing.call(this); + } + + function bindEvents() { + var l = this._.listener; + l.play = play.bind(this); + l.pause = pause.bind(this); + l.seeking = seek.bind(this); + this.video.addEventListener('play', l.play); + this.video.addEventListener('pause', l.pause); + this.video.addEventListener('seeking', l.seeking); + } + + function unbindEvents() { + var l = this._.listener; + this.video.removeEventListener('play', l.play); + this.video.removeEventListener('pause', l.pause); + this.video.removeEventListener('seeking', l.seeking); + l.play = null; + l.pause = null; + l.seeking = null; + } + + function resize() { + var cw = this.video.clientWidth; + var ch = this.video.clientHeight; + var vw = this.video.videoWidth || cw; + var vh = this.video.videoHeight || ch; + var sw = this._.scriptRes.width; + var sh = this._.scriptRes.height; + var rw = sw; + var rh = sh; + var videoScale = Math.min(cw / vw, ch / vh); + if (this.resampling === 'video_width') { + rh = sw / vw * vh; } - return to; - })(); - framing.call(this); -} - -function bindEvents() { - var l = this._.listener; - l.play = play.bind(this); - l.pause = pause.bind(this); - l.seeking = seek.bind(this); - this.video.addEventListener('play', l.play); - this.video.addEventListener('pause', l.pause); - this.video.addEventListener('seeking', l.seeking); -} - -function unbindEvents() { - var l = this._.listener; - this.video.removeEventListener('play', l.play); - this.video.removeEventListener('pause', l.pause); - this.video.removeEventListener('seeking', l.seeking); - l.play = null; - l.pause = null; - l.seeking = null; -} - -function resize() { - var cw = this.video.clientWidth; - var ch = this.video.clientHeight; - var vw = this.video.videoWidth; - var vh = this.video.videoHeight; - var sw = this._.scriptRes.width; - var sh = this._.scriptRes.height; - var rw = sw; - var rh = sh; - var videoScale = Math.min(cw / vw, ch / vh); - if (this.resampling === 'video_width') { - rh = sw / vw * vh; - } - if (this.resampling === 'video_height') { - rw = sh / vh * vw; - } - this.scale = Math.min(cw / rw, ch / rh); - if (this.resampling === 'script_width') { - this.scale = videoScale * (vw / rw); - } - if (this.resampling === 'script_height') { - this.scale = videoScale * (vh / rh); + if (this.resampling === 'video_height') { + rw = sh / vh * vw; + } + this.scale = Math.min(cw / rw, ch / rh); + if (this.resampling === 'script_width') { + this.scale = videoScale * (vw / rw); + } + if (this.resampling === 'script_height') { + this.scale = videoScale * (vh / rh); + } + this.width = this.scale * rw; + this.height = this.scale * rh; + this._.resampledRes = { width: rw, height: rh }; + + this.container.style.cssText = "width:" + cw + "px;height:" + ch + "px;"; + var cssText = ( + "width:" + (this.width) + "px;" + + "height:" + (this.height) + "px;" + + "top:" + ((ch - this.height) / 2) + "px;" + + "left:" + ((cw - this.width) / 2) + "px;" + ); + this._.$stage.style.cssText = cssText; + this._.$svg.style.cssText = cssText; + this._.$svg.setAttributeNS(null, 'viewBox', ("0 0 " + sw + " " + sh)); + + this._.$animation.innerHTML = getKeyframes.call(this); + seek.call(this); + + return this; } - this.width = this.scale * rw; - this.height = this.scale * rh; - this._.resampledRes = { width: rw, height: rh }; - - this.container.style.cssText = "width:" + cw + "px;height:" + ch + "px;"; - var cssText = ( - "width:" + (this.width) + "px;" + - "height:" + (this.height) + "px;" + - "top:" + ((ch - this.height) / 2) + "px;" + - "left:" + ((cw - this.width) / 2) + "px;" - ); - this._.$stage.style.cssText = cssText; - this._.$svg.style.cssText = cssText; - this._.$svg.setAttributeNS(null, 'viewBox', ("0 0 " + sw + " " + sh)); - this._.$animation.innerHTML = getKeyframes.call(this); - seek.call(this); + var GLOBAL_CSS = '.ASS-container,.ASS-stage{position:relative;overflow:hidden}.ASS-container video{position:absolute;top:0;left:0}.ASS-stage{pointer-events:none;position:absolute}.ASS-dialogue{font-size:0;position:absolute}.ASS-fix-font-size{position:absolute;visibility:hidden}.ASS-fix-objectBoundingBox{width:100%;height:100%;position:absolute;top:0;left:0}.ASS-animation-paused *{-webkit-animation-play-state:paused!important;animation-play-state:paused!important}'; - return this; -} + function init(source, video, options) { + if ( options === void 0 ) options = {}; -var GLOBAL_CSS = '.ASS-container,.ASS-stage{position:relative;overflow:hidden}.ASS-container video{position:absolute;top:0;left:0}.ASS-stage{pointer-events:none;position:absolute}.ASS-dialogue{font-size:0;position:absolute}.ASS-fix-font-size{position:absolute;visibility:hidden}.ASS-fix-objectBoundingBox{width:100%;height:100%;position:absolute;top:0;left:0}.ASS-animation-paused *{-webkit-animation-play-state:paused!important;animation-play-state:paused!important}'; + this.scale = 1; -function init(source, video, options) { - if ( options === void 0 ) options = {}; + // private variables + this._ = { + index: 0, + stagings: [], + space: [], + listener: {}, + $svg: createSVGEl('svg'), + $defs: createSVGEl('defs'), + $stage: document.createElement('div'), + $animation: document.createElement('style'), + }; + this._.$svg.appendChild(this._.$defs); + this._.$stage.className = 'ASS-stage ASS-animation-paused'; + this._.$animation.type = 'text/css'; + this._.$animation.className = 'ASS-animation'; + document.head.appendChild(this._.$animation); + + this._.resampling = options.resampling || 'video_height'; + + this.container = options.container || document.createElement('div'); + this.container.classList.add('ASS-container'); + this.container.appendChild($fixFontSize); + this.container.appendChild(this._.$svg); + this._.hasInitContainer = !!options.container; + + this.video = video; + bindEvents.call(this); + if (!this._.hasInitContainer) { + var isPlaying = !video.paused; + video.parentNode.insertBefore(this.container, video); + this.container.appendChild(video); + if (isPlaying && video.paused) { + video.play(); + } + } + this.container.appendChild(this._.$stage); + + var ref = compile(source); + var info = ref.info; + var width = ref.width; + var height = ref.height; + var dialogues = ref.dialogues; + this.info = info; + this._.scriptRes = { + width: width || video.videoWidth, + height: height || video.videoHeight, + }; + this.dialogues = dialogues; + + var $style = document.getElementById('ASS-global-style'); + if (!$style) { + $style = document.createElement('style'); + $style.type = 'text/css'; + $style.id = 'ASS-global-style'; + $style.appendChild(document.createTextNode(GLOBAL_CSS)); + document.head.appendChild($style); + } - this.scale = 1; + resize.call(this); - // private variables - this._ = { - index: 0, - stagings: [], - space: [], - listener: {}, - $svg: createSVGEl('svg'), - $defs: createSVGEl('defs'), - $stage: document.createElement('div'), - $animation: document.createElement('style'), - }; - this._.$svg.appendChild(this._.$defs); - this._.$stage.className = 'ASS-stage ASS-animation-paused'; - this._.$animation.type = 'text/css'; - this._.$animation.className = 'ASS-animation'; - document.head.appendChild(this._.$animation); - - this._.resampling = options.resampling || 'video_height'; - - this.container = options.container || document.createElement('div'); - this.container.classList.add('ASS-container'); - this.container.appendChild($fixFontSize); - this.container.appendChild(this._.$svg); - this._.hasInitContainer = !!options.container; - - this.video = video; - bindEvents.call(this); - if (!this._.hasInitContainer) { - var isPlaying = !video.paused; - video.parentNode.insertBefore(this.container, video); - this.container.appendChild(video); - if (isPlaying && video.paused) { - video.play(); + if (!this.video.paused) { + seek.call(this); + play.call(this); } - } - this.container.appendChild(this._.$stage); - - var ref = compile(source); - var info = ref.info; - var width = ref.width; - var height = ref.height; - var dialogues = ref.dialogues; - this.info = info; - this._.scriptRes = { - width: width || video.videoWidth, - height: height || video.videoHeight, - }; - this.dialogues = dialogues; - - var $style = document.getElementById('ASS-global-style'); - if (!$style) { - $style = document.createElement('style'); - $style.type = 'text/css'; - $style.id = 'ASS-global-style'; - $style.appendChild(document.createTextNode(GLOBAL_CSS)); - document.head.appendChild($style); + + return this; } - resize.call(this); + function show() { + this._.$stage.style.visibility = 'visible'; + return this; + } - if (!this.video.paused) { - seek.call(this); - play.call(this); + function hide() { + this._.$stage.style.visibility = 'hidden'; + return this; } - return this; -} + function destroy() { + var this$1 = this; -function show() { - this._.$stage.style.visibility = 'visible'; - return this; -} + pause.call(this); + clear.call(this); + unbindEvents.call(this, this._.listener); + if (!this._.hasInitContainer) { + var isPlay = !this.video.paused; + this.container.parentNode.insertBefore(this.video, this.container); + this.container.parentNode.removeChild(this.container); + if (isPlay && this.video.paused) { + this.video.play(); + } + } + document.head.removeChild(this._.$animation); + // eslint-disable-next-line no-restricted-syntax + for (var key in this$1) { + if (Object.prototype.hasOwnProperty.call(this$1, key)) { + this$1[key] = null; + } + } -function hide() { - this._.$stage.style.visibility = 'hidden'; - return this; -} + return this; + } -function destroy() { - var this$1 = this; + var regex = /^(video|script)_(width|height)$/; - pause.call(this); - clear.call(this); - unbindEvents.call(this, this._.listener); - if (!this._.hasInitContainer) { - var isPlay = !this.video.paused; - this.container.parentNode.insertBefore(this.video, this.container); - this.container.parentNode.removeChild(this.container); - if (isPlay && this.video.paused) { - this.video.play(); - } + function getter() { + return regex.test(this._.resampling) ? this._.resampling : 'video_height'; } - document.head.removeChild(this._.$animation); - // eslint-disable-next-line no-restricted-syntax - for (var key in this$1) { - if (Object.prototype.hasOwnProperty.call(this$1, key)) { - this$1[key] = null; + + function setter(r) { + if (r === this._.resampling) { return r; } + if (regex.test(r)) { + this._.resampling = r; + this.resize(); } + return this._.resampling; } - return this; -} - -var regex = /^(video|script)_(width|height)$/; + var ASS = function ASS(source, video, options) { + if (typeof source !== 'string' || !(video instanceof HTMLVideoElement)) { + return this; + } + return init.call(this, source, video, options); + }; -function getter() { - return regex.test(this._.resampling) ? this._.resampling : 'video_height'; -} + var prototypeAccessors = { resampling: { configurable: true } }; + ASS.prototype.resize = function resize$1 () { + return resize.call(this); + }; + ASS.prototype.show = function show$1 () { + return show.call(this); + }; + ASS.prototype.hide = function hide$1 () { + return hide.call(this); + }; + ASS.prototype.destroy = function destroy$1 () { + return destroy.call(this); + }; + prototypeAccessors.resampling.get = function () { + return getter.call(this); + }; + prototypeAccessors.resampling.set = function (r) { + return setter.call(this, r); + }; -function setter(r) { - if (r === this._.resampling) { return r; } - if (regex.test(r)) { - this._.resampling = r; - this.resize(); - } - return this._.resampling; -} + Object.defineProperties( ASS.prototype, prototypeAccessors ); -var ASS = function ASS(source, video, options) { - if (typeof source !== 'string' || !(video instanceof HTMLVideoElement)) { - return this; - } - return init.call(this, source, video, options); -}; - -var prototypeAccessors = { resampling: { configurable: true } }; -ASS.prototype.resize = function resize$1 () { - return resize.call(this); -}; -ASS.prototype.show = function show$1 () { - return show.call(this); -}; -ASS.prototype.hide = function hide$1 () { - return hide.call(this); -}; -ASS.prototype.destroy = function destroy$1 () { - return destroy.call(this); -}; -prototypeAccessors.resampling.get = function () { - return getter.call(this); -}; -prototypeAccessors.resampling.set = function (r) { - return setter.call(this, r); -}; - -Object.defineProperties( ASS.prototype, prototypeAccessors ); - -return ASS; + return ASS; }))); diff --git a/dist/ass.min.js b/dist/ass.min.js index 86d8268..6d65cd7 100644 --- a/dist/ass.min.js +++ b/dist/ass.min.js @@ -1 +1 @@ -(function(t,e){typeof exports==="object"&&typeof module!=="undefined"?module.exports=e():typeof define==="function"&&define.amd?define(e):t.ASS=e()})(this,function(){"use strict";function t(t){var e=t.toLowerCase().trim().split(/\s*;\s*/);if(e[0]==="banner"){return{name:e[0],delay:e[1]*1||0,leftToRight:e[2]*1||0,fadeAwayWidth:e[3]*1||0}}if(/^scroll\s/.test(e[0])){return{name:e[0],y1:Math.min(e[1]*1,e[2]*1),y2:Math.max(e[1]*1,e[2]*1),delay:e[3]*1||0,fadeAwayHeight:e[4]*1||0}}return null}function e(t){return t.toLowerCase().replace(/([mnlbspc])/g," $1 ").trim().replace(/\s+/g," ").split(/\s(?=[mnlbspc])/).map(function(t){return t.split(" ")})}var a=["b","i","u","s","fsp","k","K","kf","ko","kt","fe","q","p","pbo","a","an","fscx","fscy","fax","fay","frx","fry","frz","fr","be","blur","bord","xbord","ybord","shad","xshad","yshad"];var r=a.map(function(t){return{name:t,regex:new RegExp("^"+t+"-?\\d")}});function i(t){var a;var n={};for(var s=0;sa.length){var i=r.slice(a.length-1).join();r=r.slice(0,a.length-1);r.push(i)}var n={};for(var l=0;l0)a[r]=arguments[r+1];for(var i=0;i-10?1+s/10:1)*a.fs:s*1}}if(e==="t"){var L=s.t1;var B=s.accel;var O=s.tags;var z=s.t2||(a.end-a.start)*1e3;var R={};O.forEach(function(t){var e=Object.keys(t)[0];if(~x.indexOf(e)&&!(e==="clip"&&!t[e].dots)){c(R,w(t,e,a))}});return{t:{t1:L,t2:z,accel:B,tag:R}}}return n={},n[e]=s,n}var b=[null,1,2,3,null,7,8,9,null,4,5,6];var S=["r","a","an","pos","org","move","fade","fad","clip"];function _(t,e){return{name:t,borderStyle:e[t].style.BorderStyle,tag:e[t].tag,fragments:[]}}function C(t){var e=t.styles;var a=t.name;var r=t.parsed;var i=t.start;var n=t.end;var s;var o;var l;var f;var v;var h;var d=[];var p=_(a,e);var u={};for(var g=0;g=s.End){continue}if(!e[s.Style]){s.Style="Default"}var o=e[s.Style].style;var l=C({styles:e,name:s.Style,parsed:s.Text.parsed,start:s.Start,end:s.End});var f=l.alignment||o.Alignment;r=Math.min(r,s.Layer);i.push(c({layer:s.Layer,start:s.Start,end:s.End,margin:{left:s.MarginL||o.MarginL,right:s.MarginR||o.MarginR,vertical:s.MarginV||o.MarginV},effect:s.Effect},l,{alignment:f}))}for(var v=0;v0?1:-1;var u=l>0?1:-1;o=Math.abs(o);l=Math.abs(l);for(var g=Math.max(i,o-i);g=4&&e<=6){o.y=n+r/2}if(e>=7){o.y=n}}for(var l=s.childNodes.length-1;l>=0;l--){var f=s.childNodes[l];if(f.dataset.hasRotate==="true"){var v=o.x-i-f.offsetLeft;var h=o.y-n-f.offsetTop;f.style.cssText+=O.transform+"transform-origin:"+v+"px "+h+"px;"}}}function V(t,e){return"@"+O.animation+"keyframes "+t+" {"+e+"}\n"}var W=function t(){this.obj={}};W.prototype.set=function t(e,a,r){if(!this.obj[e]){this.obj[e]={}}this.obj[e][a]=r};W.prototype.setT=function t(e){var a=e.t1;var r=e.t2;var i=e.duration;var n=e.prop;var s=e.from;var o=e.to;this.set("0.000%",n,s);if(a/g,">").replace(/\s/g," ").replace(/\\h/g," ").replace(/\\N/g,"
").replace(/\\n/g,e===2?"
":" ")}function et(t){var e=this;var a=document.createElement("div");a.className="ASS-dialogue";var r=document.createDocumentFragment();var i=t.slices;var n=t.start;var s=t.end;i.forEach(function(t){var a=t.borderStyle;t.fragments.forEach(function(i){var o=i.text;var l=i.drawing;var f=i.animationName;var v=c({},t.tag,i.tag);var h="display:inline-block;";var d=e.video.currentTime;if(!l){h+='font-family:"'+v.fn+'",Arial;';h+="font-size:"+e.scale*U(v.fn,v.fs)+"px;";h+="color:"+F(v.a1+v.c1)+";";var p=/Yes/i.test(e.info.ScaledBorderAndShadow)?e.scale:1;if(a===1){h+="text-shadow:"+D(v,p)+";"}if(a===3){h+="background-color:"+F(v.a3+v.c3)+";"+"box-shadow:"+D(v,p)+";"}h+=v.b?"font-weight:"+(v.b===1?"bold":v.b)+";":"";h+=v.i?"font-style:italic;":"";h+=v.u||v.s?"text-decoration:"+(v.u?"underline":"")+" "+(v.s?"line-through":"")+";":"";h+=v.fsp?"letter-spacing:"+v.fsp+"px;":"";if(v.q===1||v.q===0||v.q===3){h+="word-break:break-all;white-space:normal;"}if(v.q===2){h+="word-break:normal;white-space:nowrap;"}}var u=R.some(function(t){return/^fsc[xy]$/.test(t)?v[t]!==100:!!v[t]});if(u){h+=O.transform+"transform:"+G(v)+";";if(!l){h+="transform-style:preserve-3d;word-break:normal;white-space:nowrap;"}}if(f){h+=K(f,s-n,Math.min(0,n-d))}if(l&&v.pbo){var g=e.scale*-v.pbo*(v.fscy||100)/100;h+="vertical-align:"+g+"px;"}var m=/"fr[xyz]":[^0]/.test(JSON.stringify(v));tt(o,v.q).split("
").forEach(function(a,n){var s=document.createElement("span");s.dataset.hasRotate=m;if(l){var o=Q.call(e,i,t.tag);s.style.cssText=o.cssText;s.appendChild(o.$svg)}else{if(n){r.appendChild(document.createElement("br"))}if(!a){return}s.innerHTML=a}s.style.cssText+=h;r.appendChild(s)})})});a.appendChild(r);return a}function at(t){var e=t.layer;var a=t.margin;var r=t.width;var i=t.height;var n=t.alignment;var s=t.end;var o=this.width-(this.scale*(a.left+a.right)|0);var l=this.height;var f=this.scale*a.vertical|0;var v=this.video.currentTime*100;this._.space[e]=this._.space[e]||{left:{width:new Uint16Array(l+1),end:new Uint16Array(l+1)},center:{width:new Uint16Array(l+1),end:new Uint16Array(l+1)},right:{width:new Uint16Array(l+1),end:new Uint16Array(l+1)}};var h=this._.space[e];var c=["right","left","center"][n%3];var d=function(t){var e=h.left.width[t];var a=h.center.width[t];var i=h.right.width[t];var n=h.left.end[t];var s=h.center.end[t];var l=h.right.end[t];return c==="left"&&(n>v&&e||s>v&&a&&2*r+a>o||l>v&&i&&r+i>o)||c==="center"&&(n>v&&e&&2*e+r>o||s>v&&a||l>v&&i&&2*i+r>o)||c==="right"&&(n>v&&e&&e+r>o||s>v&&a&&2*r+a>o||l>v&&i)};var p=0;var u=0;var g=function(t){p=d(t)?0:p+1;if(p>=i){u=t;return true}return false};if(n<=3){for(var m=l-f-1;m>f;m--){if(g(m)){break}}}else if(n>=7){for(var y=f+1;y>1;x3){u-=i-1}for(var w=u;w=4&&r<=6){f=(this.height-n)/2}if(r>=7){f=s.vertical}l=e.lefttoright?-i:this.width}}else if(t.pos||a){var v=t.pos||{x:0,y:0};if(r%3===1){l=this.scale*v.x}if(r%3===2){l=this.scale*v.x-i/2}if(r%3===0){l=this.scale*v.x-i}if(r<=3){f=this.scale*v.y-n}if(r>=4&&r<=6){f=this.scale*v.y-n/2}if(r>=7){f=this.scale*v.y}}else{if(r%3===1){l=0}if(r%3===2){l=(this.width-i)/2}if(r%3===0){l=this.width-i-this.scale*s.right}var h=o.some(function(t){return t.fragments.some(function(t){var e=t.animationName;return e})});if(h){if(r<=3){f=this.height-n-s.vertical}if(r>=4&&r<=6){f=(this.height-n)/2}if(r>=7){f=s.vertical}}else{f=at.call(this,t)}}return{x:l,y:f}}function it(t){var e=t.layer;var a=t.start;var r=t.end;var i=t.alignment;var n=t.effect;var s=t.pos;var o=t.margin;var l=t.animationName;var f=t.width;var v=t.height;var h=t.x;var c=t.y;var d=this.video.currentTime;var p="";if(e){p+="z-index:"+e+";"}if(l){p+=K(l,r-a,Math.min(0,a-d))}p+="text-align:"+["right","left","center"][i%3]+";";if(!n){var u=this.width-this.scale*(o.left+o.right);p+="max-width:"+u+"px;";if(!s){if(i%3===1){p+="margin-left:"+this.scale*o.left+"px;"}if(i%3===0){p+="margin-right:"+this.scale*o.right+"px;"}if(f>this.width-this.scale*(o.left+o.right)){p+="margin-left:"+this.scale*o.left+"px;";p+="margin-right:"+this.scale*o.right+"px;"}}}p+="width:"+f+"px;height:"+v+"px;left:"+h+"px;top:"+c+"px;";return p}function nt(t){var e=et.call(this,t);c(t,{$div:e});this._.$stage.appendChild(e);var a=e.getBoundingClientRect();var r=a.width;var i=a.height;c(t,{width:r,height:i});c(t,rt.call(this,t));e.style.cssText=it.call(this,t);X(t);I.call(this,t);return t}function st(){var t=this;var e=this.video.currentTime;for(var a=this._.stagings.length-1;a>=0;a--){var r=t._.stagings[a];var i=r.end;if(r.effect&&/scroll/.test(r.effect.name)){var n=r.effect;var s=n.y1;var o=n.y2;var l=n.delay;var f=((o||t._.resampledRes.height)-s)/(1e3/l);i=Math.min(i,r.start+f)}if(i=v[this._.index].start){if(ee[r+a>>1].end){a=r+a>>1}if(!a){return 0}for(var i=a;it&&t>=e[i].start||i&&e[i-1].ende.length){var r=a.slice(e.length-1).join();a=a.slice(0,e.length-1);a.push(r)}var i={};for(var n=0;n0)a[r]=arguments[r+1];for(var i=0;i-10?1+s/10:1)*a.fs:s*1}}if(e==="t"){var E=s.t1;var T=s.accel;var F=s.tags;var j=s.t2||(a.end-a.start)*1e3;var L={};F.forEach(function(t){var e=Object.keys(t)[0];if(~O.indexOf(e)&&!(e==="clip"&&!t[e].dots)){P(L,z(t,e,a))}});return{t:{t1:E,t2:j,accel:T,tag:L}}}return n={},n[e]=s,n}var R=[null,1,2,3,null,7,8,9,null,4,5,6];var H=["r","a","an","pos","org","move","fade","fad","clip"];function I(t,e){return{name:t,borderStyle:e[t].style.BorderStyle,tag:e[t].tag,fragments:[]}}function S(t){var e=t.styles;var a=t.name;var r=t.parsed;var i=t.start;var n=t.end;var s;var o;var l;var f;var v;var h;var c=[];var d=I(a,e);var p={};for(var u=0;u=s.End){continue}if(!e[s.Style]){s.Style="Default"}var o=e[s.Style].style;var l=S({styles:e,name:s.Style,parsed:s.Text.parsed,start:s.Start,end:s.End});var f=l.alignment||o.Alignment;r=Math.min(r,s.Layer);i.push(P({layer:s.Layer,start:s.Start,end:s.End,margin:{left:s.MarginL||o.MarginL,right:s.MarginR||o.MarginR,vertical:s.MarginV||o.MarginV},effect:s.Effect},l,{alignment:f}))}for(var v=0;v0?1:-1;var u=l>0?1:-1;o=Math.abs(o);l=Math.abs(l);for(var g=Math.max(i,o-i);g=4&&e<=6){o.y=n+r/2}if(e>=7){o.y=n}}for(var l=s.childNodes.length-1;l>=0;l--){var f=s.childNodes[l];if(f.dataset.hasRotate==="true"){var v=o.x-i-f.offsetLeft;var h=o.y-n-f.offsetTop;f.style.cssText+=M.transform+"transform-origin:"+v+"px "+h+"px;"}}}function W(t,e){return"@"+M.animation+"keyframes "+t+" {"+e+"}\n"}var J=function t(){this.obj={}};J.prototype.set=function t(e,a,r){if(!this.obj[e]){this.obj[e]={}}this.obj[e][a]=r};J.prototype.setT=function t(e){var a=e.t1;var r=e.t2;var i=e.duration;var n=e.prop;var s=e.from;var o=e.to;this.set("0.000%",n,s);if(a/g,">").replace(/\s/g," ").replace(/\\h/g," ").replace(/\\N/g,"
").replace(/\\n/g,e===2?"
":" ")}function et(t){var d=this;var e=document.createElement("div");e.className="ASS-dialogue";var p=document.createDocumentFragment();var a=t.slices;var u=t.start;var g=t.end;a.forEach(function(h){var c=h.borderStyle;h.fragments.forEach(function(i){var t=i.text;var n=i.drawing;var e=i.animationName;var a=P({},h.tag,i.tag);var s="display:inline-block;";var r=d.video.currentTime;if(!n){s+='font-family:"'+a.fn+'",Arial;';s+="font-size:"+d.scale*G(a.fn,a.fs)+"px;";s+="color:"+q(a.a1+a.c1)+";";var o=/Yes/i.test(d.info.ScaledBorderAndShadow)?d.scale:1;if(c===1){s+="text-shadow:"+X(a,o)+";"}if(c===3){s+="background-color:"+q(a.a3+a.c3)+";"+"box-shadow:"+X(a,o)+";"}s+=a.b?"font-weight:"+(a.b===1?"bold":a.b)+";":"";s+=a.i?"font-style:italic;":"";s+=a.u||a.s?"text-decoration:"+(a.u?"underline":"")+" "+(a.s?"line-through":"")+";":"";s+=a.fsp?"letter-spacing:"+a.fsp+"px;":"";if(a.q===1||a.q===0||a.q===3){s+="word-break:break-all;white-space:normal;"}if(a.q===2){s+="word-break:normal;white-space:nowrap;"}}var l=D.some(function(t){return/^fsc[xy]$/.test(t)?a[t]!==100:!!a[t]});if(l){s+=M.transform+"transform:"+V(a)+";";if(!n){s+="transform-style:preserve-3d;word-break:normal;white-space:nowrap;"}}if(e){s+=K(e,g-u,Math.min(0,u-r))}if(n&&a.pbo){var f=d.scale*-a.pbo*(a.fscy||100)/100;s+="vertical-align:"+f+"px;"}var v=/"fr[xyz]":[^0]/.test(JSON.stringify(a));tt(t,a.q).split("
").forEach(function(t,e){var a=document.createElement("span");a.dataset.hasRotate=v;if(n){var r=Q.call(d,i,h.tag);a.style.cssText=r.cssText;a.appendChild(r.$svg)}else{if(e){p.appendChild(document.createElement("br"))}if(!t){return}a.innerHTML=t}a.style.cssText+=s;p.appendChild(a)})})});e.appendChild(p);return e}function at(t){var e=t.layer;var a=t.margin;var o=t.width;var r=t.height;var i=t.alignment;var n=t.end;var l=this.width-(this.scale*(a.left+a.right)|0);var s=this.height;var f=this.scale*a.vertical|0;var v=this.video.currentTime*100;this._.space[e]=this._.space[e]||{left:{width:new Uint16Array(s+1),end:new Uint16Array(s+1)},center:{width:new Uint16Array(s+1),end:new Uint16Array(s+1)},right:{width:new Uint16Array(s+1),end:new Uint16Array(s+1)}};var h=this._.space[e];var c=["right","left","center"][i%3];var d=function(t){var e=h.left.width[t];var a=h.center.width[t];var r=h.right.width[t];var i=h.left.end[t];var n=h.center.end[t];var s=h.right.end[t];return c==="left"&&(i>v&&e||n>v&&a&&2*o+a>l||s>v&&r&&o+r>l)||c==="center"&&(i>v&&e&&2*e+o>l||n>v&&a||s>v&&r&&2*r+o>l)||c==="right"&&(i>v&&e&&e+o>l||n>v&&a&&2*o+a>l||s>v&&r)};var p=0;var u=0;var g=function(t){p=d(t)?0:p+1;if(p>=r){u=t;return true}return false};if(i<=3){for(var m=s-f-1;m>f;m--){if(g(m)){break}}}else if(i>=7){for(var y=f+1;y>1;x3){u-=r-1}for(var w=u;w=4&&r<=6){f=(this.height-n)/2}if(r>=7){f=s.vertical}l=e.lefttoright?-i:this.width}}else if(t.pos||a){var v=t.pos||{x:0,y:0};if(r%3===1){l=this.scale*v.x}if(r%3===2){l=this.scale*v.x-i/2}if(r%3===0){l=this.scale*v.x-i}if(r<=3){f=this.scale*v.y-n}if(r>=4&&r<=6){f=this.scale*v.y-n/2}if(r>=7){f=this.scale*v.y}}else{if(r%3===1){l=0}if(r%3===2){l=(this.width-i)/2}if(r%3===0){l=this.width-i-this.scale*s.right}var h=o.some(function(t){return t.fragments.some(function(t){var e=t.animationName;return e})});if(h){if(r<=3){f=this.height-n-s.vertical}if(r>=4&&r<=6){f=(this.height-n)/2}if(r>=7){f=s.vertical}}else{f=at.call(this,t)}}return{x:l,y:f}}function it(t){var e=t.layer;var a=t.start;var r=t.end;var i=t.alignment;var n=t.effect;var s=t.pos;var o=t.margin;var l=t.animationName;var f=t.width;var v=t.height;var h=t.x;var c=t.y;var d=this.video.currentTime;var p="";if(e){p+="z-index:"+e+";"}if(l){p+=K(l,r-a,Math.min(0,a-d))}p+="text-align:"+["right","left","center"][i%3]+";";if(!n){var u=this.width-this.scale*(o.left+o.right);p+="max-width:"+u+"px;";if(!s){if(i%3===1){p+="margin-left:"+this.scale*o.left+"px;"}if(i%3===0){p+="margin-right:"+this.scale*o.right+"px;"}if(f>this.width-this.scale*(o.left+o.right)){p+="margin-left:"+this.scale*o.left+"px;";p+="margin-right:"+this.scale*o.right+"px;"}}}p+="width:"+f+"px;height:"+v+"px;left:"+h+"px;top:"+c+"px;";return p}function nt(t){var e=et.call(this,t);P(t,{$div:e});this._.$stage.appendChild(e);var a=e.getBoundingClientRect();var r=a.width;var i=a.height;P(t,{width:r,height:i});P(t,rt.call(this,t));e.style.cssText=it.call(this,t);j(t);N.call(this,t);return t}function st(){var t=this;var e=this.video.currentTime;for(var a=this._.stagings.length-1;a>=0;a--){var r=t._.stagings[a];var i=r.end;if(r.effect&&/scroll/.test(r.effect.name)){var n=r.effect;var s=n.y1;var o=n.y2;var l=n.delay;var f=((o||t._.resampledRes.height)-s)/(1e3/l);i=Math.min(i,r.start+f)}if(i=v[this._.index].start){if(ei[e+t>>1].end){t=e+t>>1}if(!t){return 0}for(var a=t;ar&&r>=i[a].start||a&&i[a-1].end