6 Commits
5 changed files with 235 additions and 191 deletions
+1 -1
View File
@@ -81,7 +81,7 @@
}
/* Filter wrapper span */
.libjass-subs div[data-dialogue-id] > span {
.libjass-subs div[data-dialogue-id] {
-webkit-perspective-origin: center;
-webkit-perspective: 200px;
perspective-origin: center;
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "libjass",
"version": "0.8.0",
"version": "0.9.0",
"description": "A library to render ASS subtitles on HTML5 video in the browser.",
"keywords": ["browser", "html5", "subtitles"],
"homepage": "https://github.com/Arnavion/libjass",
+36 -31
View File
@@ -78,13 +78,14 @@ module libjass.parser {
parse_assScript(parent: ParseNode): ParseNode {
var current = new ParseNode(parent);
current.value = Object.create(null);
var sections = new Map<string, any>();
current.value = sections;
while (this._haveMore()) {
var scriptSectionNode = this.parse_assScriptSection(current);
if (scriptSectionNode !== null) {
current.value[scriptSectionNode.value.name] = scriptSectionNode.value.contents;
sections.set(scriptSectionNode.value.name, scriptSectionNode.value.contents);
}
else if (this.read(current, "\n") === null) {
parent.pop();
@@ -112,7 +113,9 @@ module libjass.parser {
current.value.name = sectionHeaderNode.value;
current.value.contents = null;
var formatSpecifier: string[] = null;
var sectionTemplate: Map<string, string> = null;
var sectionTemplateArray: TypedTemplateArray = null;
while (this._haveMore() && this._peek() !== "[") {
if (this.read(current, "\n") !== null) {
@@ -126,30 +129,32 @@ module libjass.parser {
var propertyNode = this.parse_assScriptProperty(current);
if (propertyNode !== null) {
if (formatSpecifier === null) {
if (sectionTemplateArray === null) {
var property: { key: string; value: string } = propertyNode.value;
if (current.value.contents === null && property.key === "Format") {
if (sectionTemplateArray === null && property.key === "Format") {
// The first line of this section is a format specifier. This section will be an array of templates.
formatSpecifier = property.value.split(",").map(formatPart => formatPart.trim());
current.value.contents = <TypedTemplateArray>[];
current.value.contents.formatSpecifier = formatSpecifier;
sectionTemplateArray = <TypedTemplateArray>[];
sectionTemplateArray.formatSpecifier = property.value.split(",").map(formatPart => formatPart.trim());
current.value.contents = sectionTemplateArray;
}
else {
// This section is a single template. Each line is a property of this template.
if (current.value.contents === null) {
current.value.contents = Object.create(null);
if (sectionTemplate === null) {
sectionTemplate = new Map<string, string>();
current.value.contents = sectionTemplate;
}
current.value.contents[property.key] = property.value;
sectionTemplate.set(property.key, property.value);
}
}
else {
// Each line in this section is a template of a particular type, and the section is an array of these templates.
current.value.contents.push(propertyNode.value);
sectionTemplateArray.push(<TypedTemplate>propertyNode.value);
}
}
@@ -250,24 +255,26 @@ module libjass.parser {
current.value = property;
var scriptSectionContents = parent.value.contents;
if (scriptSectionContents !== null) {
var formatSpecifier = (<TypedTemplateArray>scriptSectionContents).formatSpecifier;
if (formatSpecifier !== undefined) {
// This line is a template of a particular type, and its parent section is an array of these templates.
if (parent.value !== null) {
var scriptSectionContents = parent.value.contents;
if (scriptSectionContents !== undefined && scriptSectionContents !== null) {
var formatSpecifier = (<TypedTemplateArray>scriptSectionContents).formatSpecifier;
if (formatSpecifier !== undefined) {
// This line is a template of a particular type, and its parent section is an array of these templates.
var template: Template = Object.create(null);
var value = property.value.split(",");
var template = new Map<string, string>();
var value = property.value.split(",");
if (value.length > formatSpecifier.length) {
value[formatSpecifier.length - 1] = value.slice(formatSpecifier.length - 1).join(",");
if (value.length > formatSpecifier.length) {
value[formatSpecifier.length - 1] = value.slice(formatSpecifier.length - 1).join(",");
}
formatSpecifier.forEach((formatKey, index) => {
template.set(formatKey, value[index]);
});
current.value = <TypedTemplate>{ type: property.key, template: template };
}
formatSpecifier.forEach((formatKey, index) => {
template[formatKey] = value[index];
});
current.value = <TypedTemplate>{ type: property.key, template: template };
}
}
@@ -2431,9 +2438,7 @@ module libjass.parser {
this._start = ((_parent !== null) ? _parent.end : 0);
this._end = this._start;
if (value !== null) {
this.value = value;
}
this.value = value;
}
/**
@@ -2487,7 +2492,7 @@ module libjass.parser {
set value(newValue: any) {
this._value = newValue;
if (this._value.constructor === String && this._children.length === 0) {
if (this._value !== null && this._value.constructor === String && this._children.length === 0) {
this._setEnd(this._start + this._value.length);
}
}
+129 -79
View File
@@ -46,7 +46,7 @@ module libjass.renderers {
private _svgDefsElement: SVGDefsElement = null;
private _currentSubs: Map<Dialogue, HTMLDivElement> = new Map<Dialogue, HTMLDivElement>();
private _preRenderedSubs: Map<number, HTMLDivElement> = new Map<number, HTMLDivElement>();
private _preRenderedSubs: Map<number, { sub: HTMLDivElement; animationDelays: number[] }> = new Map<number, { sub: HTMLDivElement; animationDelays: number[] }>();
private _scaleX: number;
private _scaleY: number;
@@ -199,14 +199,35 @@ module libjass.renderers {
var currentSpan: HTMLSpanElement = null;
var currentSpanStyles = new SpanStyles(this, dialogue, this._scaleX, this._scaleY, this.settings, this._fontSizeElement, this._svgDefsElement);
var nextSpanParent: HTMLElement = sub;
var rotationX = 0;
var rotationY = 0;
var rotationZ = 0;
var startNewSpan = (addNewLine: boolean): void => {
if (currentSpan !== null && currentSpan.textContent !== "") {
sub.appendChild(currentSpanStyles.setStylesOnSpan(currentSpan));
var newSpan = currentSpanStyles.setStylesOnSpan(currentSpan, rotationX, rotationY, rotationZ);
if (currentSpanStyles.rotationX !== rotationX || currentSpanStyles.rotationY !== rotationY || currentSpanStyles.rotationZ !== rotationZ) {
nextSpanParent.appendChild(newSpan);
nextSpanParent = newSpan;
rotationX = currentSpanStyles.rotationX;
rotationY = currentSpanStyles.rotationY;
rotationZ = currentSpanStyles.rotationZ;
}
else {
nextSpanParent.appendChild(newSpan.firstElementChild);
}
}
if (addNewLine) {
sub.appendChild(document.createElement("br"));
nextSpanParent = sub;
nextSpanParent.appendChild(document.createElement("br"));
rotationX = 0;
rotationY = 0;
rotationZ = 0;
}
currentSpan = document.createElement("span");
@@ -367,7 +388,7 @@ module libjass.renderers {
var newStyleName = (<parts.Reset>part).value;
var newStyle: Style = null;
if (newStyleName !== null) {
newStyle = this.ass.styles[newStyleName];
newStyle = this.ass.styles.get(newStyleName);
}
currentSpanStyles.reset(newStyle);
}
@@ -384,51 +405,51 @@ module libjass.renderers {
var movePart = <parts.Move>part;
sub.style.position = "absolute";
animationCollection.add("linear", [new Keyframe(0, {
left: (this._scaleX * movePart.x1).toFixed(3) + "px",
top: (this._scaleY * movePart.y1).toFixed(3) + "px"
}), new Keyframe(movePart.t1, {
left: (this._scaleX * movePart.x1).toFixed(3) + "px",
top: (this._scaleY * movePart.y1).toFixed(3) + "px"
}), new Keyframe(movePart.t2, {
left: (this._scaleX * movePart.x2).toFixed(3) + "px",
top: (this._scaleY * movePart.y2).toFixed(3) + "px"
}), new Keyframe(dialogue.end - dialogue.start, {
left: (this._scaleX * movePart.x2).toFixed(3) + "px",
top: (this._scaleY * movePart.y2).toFixed(3) + "px"
})]);
animationCollection.add("linear", [new Keyframe(0, new Map<string, string>()
.set("left", (this._scaleX * movePart.x1).toFixed(3) + "px")
.set("top", (this._scaleY * movePart.y1).toFixed(3) + "px")
), new Keyframe(movePart.t1, new Map<string, string>()
.set("left", (this._scaleX * movePart.x1).toFixed(3) + "px")
.set("top", (this._scaleY * movePart.y1).toFixed(3) + "px")
), new Keyframe(movePart.t2, new Map<string, string>()
.set("left", (this._scaleX * movePart.x2).toFixed(3) + "px")
.set("top", (this._scaleY * movePart.y2).toFixed(3) + "px")
), new Keyframe(dialogue.end - dialogue.start, new Map<string, string>()
.set("left", (this._scaleX * movePart.x2).toFixed(3) + "px")
.set("top", (this._scaleY * movePart.y2).toFixed(3) + "px")
)]);
}
else if (part instanceof parts.Fade) {
var fadePart = <parts.Fade>part;
animationCollection.add("linear", [new Keyframe(0, {
opacity: "0"
}), new Keyframe(fadePart.start, {
opacity: "1"
}), new Keyframe(dialogue.end - dialogue.start - fadePart.end, {
opacity: String("1")
}), new Keyframe(dialogue.end - dialogue.start, {
opacity: "0"
})]);
animationCollection.add("linear", [new Keyframe(0, new Map<string, string>()
.set("opacity", "0")
), new Keyframe(fadePart.start, new Map<string, string>()
.set("opacity", "1")
), new Keyframe(dialogue.end - dialogue.start - fadePart.end, new Map<string, string>()
.set("opacity", "1")
), new Keyframe(dialogue.end - dialogue.start, new Map<string, string>()
.set("opacity", "0")
)]);
}
else if (part instanceof parts.ComplexFade) {
var complexFadePart = <parts.ComplexFade>part;
animationCollection.add("linear", [new Keyframe(0, {
opacity: String(complexFadePart.a1)
}), new Keyframe(complexFadePart.t1, {
opacity: String(complexFadePart.a1)
}), new Keyframe(complexFadePart.t2, {
opacity: String(complexFadePart.a2)
}), new Keyframe(complexFadePart.t3, {
opacity: String(complexFadePart.a2)
}), new Keyframe(complexFadePart.t4, {
opacity: String(complexFadePart.a3)
}), new Keyframe(dialogue.end - dialogue.start, {
opacity: String(complexFadePart.a3)
})]);
animationCollection.add("linear", [new Keyframe(0, new Map<string, string>()
.set("opacity", complexFadePart.a1.toFixed(3))
), new Keyframe(complexFadePart.t1, new Map<string, string>()
.set("opacity", complexFadePart.a1.toFixed(3))
), new Keyframe(complexFadePart.t2, new Map<string, string>()
.set("opacity", complexFadePart.a2.toFixed(3))
), new Keyframe(complexFadePart.t3, new Map<string, string>()
.set("opacity", complexFadePart.a2.toFixed(3))
), new Keyframe(complexFadePart.t4, new Map<string, string>()
.set("opacity", complexFadePart.a3.toFixed(3))
), new Keyframe(dialogue.end - dialogue.start, new Map<string, string>()
.set("opacity", complexFadePart.a3.toFixed(3))
)]);
}
else if (part instanceof parts.DrawingMode) {
@@ -516,7 +537,7 @@ module libjass.renderers {
sub.setAttribute("data-dialogue-id", this.id + "-" + dialogue.id);
this._preRenderedSubs.set(dialogue.id, sub);
this._preRenderedSubs.set(dialogue.id, { sub: sub, animationDelays: animationCollection.animationDelays });
}
/**
@@ -549,22 +570,11 @@ module libjass.renderers {
}
}
var result = <HTMLDivElement>preRenderedSub.cloneNode(true);
var result = <HTMLDivElement>preRenderedSub.sub.cloneNode(true);
var defaultAnimationDelay = result.style.webkitAnimationDelay;
if (defaultAnimationDelay === undefined) {
defaultAnimationDelay = result.style.animationDelay;
}
if (defaultAnimationDelay !== "") {
var animationDelay =
defaultAnimationDelay
.split(",")
.map(delay => (parseFloat(delay) + dialogue.start - this.clock.currentTime).toFixed(3) + "s")
.join(",");
result.style.webkitAnimationDelay = animationDelay;
result.style.animationDelay = animationDelay;
}
var animationDelay = preRenderedSub.animationDelays.map(delay => (delay + dialogue.start - this.clock.currentTime).toFixed(3) + "s").join(", ");
result.style.webkitAnimationDelay = animationDelay;
result.style.animationDelay = animationDelay;
var layer = dialogue.layer;
var alignment = (result.style.position === "absolute") ? 0 : dialogue.alignment; // Alignment 0 is for absolutely-positioned subs
@@ -675,10 +685,6 @@ module libjass.renderers {
}
mixin(WebRenderer, [EventSource]);
interface KeyframePropertiesMap {
[key: string]: string;
}
/**
* This class represents a single keyframe. It has a list of CSS properties (names and values) associated with a point in time. Multiple keyframes make up an animation.
*
@@ -686,7 +692,7 @@ module libjass.renderers {
* @param {!Object.<string, string>} properties
*/
class Keyframe {
constructor(private _time: number, private _properties: KeyframePropertiesMap) { }
constructor(private _time: number, private _properties: Map<string, string>) { }
/**
* @type {number}
@@ -698,7 +704,7 @@ module libjass.renderers {
/**
* @type {!Object.<string, string>}
*/
get properties(): KeyframePropertiesMap {
get properties(): Map<string, string> {
return this._properties;
}
}
@@ -717,6 +723,7 @@ module libjass.renderers {
private _cssText: string = "";
private _animationStyle: string = "";
private _animationDelays: number[] = [];
private _numAnimations: number = 0;
constructor(renderer: NullRenderer, dialogue: Dialogue) {
@@ -743,6 +750,13 @@ module libjass.renderers {
return this._animationStyle;
}
/**
* This array should be used to set the "animation-delay" CSS property of the target element.
*/
get animationDelays(): number[] {
return this._animationDelays;
}
/**
* Add an animation to this collection. The given keyframes together make one animation.
*
@@ -764,8 +778,8 @@ module libjass.renderers {
ruleCssText += "\t" + (100 * keyframe.time / (this._end - this._start)).toFixed(3) + "% {\n";
Object.keys(keyframe.properties).forEach(propertyName => {
ruleCssText += "\t\t" + propertyName + ": " + keyframe.properties[propertyName] + ";\n";
keyframe.properties.forEach((value, name) => {
ruleCssText += "\t\t" + name + ": " + value + ";\n";
});
ruleCssText += "\t}\n";
@@ -781,7 +795,8 @@ module libjass.renderers {
this._animationStyle += ",";
}
this._animationStyle += animationName + " " + (endTime - startTime).toFixed(3) + "s " + timingFunction + " " + startTime.toFixed(3) + "s";
this._animationStyle += animationName + " " + (endTime - startTime).toFixed(3) + "s " + timingFunction;
this._animationDelays.push(startTime);
}
}
@@ -880,8 +895,8 @@ module libjass.renderers {
this.letterSpacing = newStyle.letterSpacing;
this._rotationX = null;
this._rotationY = null;
this._rotationX = 0;
this._rotationY = 0;
this._rotationZ = newStyle.rotationZ;
this._skewX = null;
@@ -907,7 +922,7 @@ module libjass.renderers {
* @param {!HTMLSpanElement} span
* @return {!HTMLSpanElement} The resulting <span> with the CSS styles applied. This may be a wrapper around the input <span> if the styles were applied using SVG filters.
*/
setStylesOnSpan(span: HTMLSpanElement): HTMLSpanElement {
setStylesOnSpan(span: HTMLSpanElement, previousRotationX: number, previousRotationY: number, previousRotationZ: number): HTMLSpanElement {
var isTextOnlySpan = span.childNodes[0] instanceof Text;
var fontStyleOrWeight = "";
@@ -953,15 +968,6 @@ module libjass.renderers {
transform += "scaleY(" + this._fontScaleY + ") ";
}
}
if (this._rotationY !== null) {
transform += "rotateY(" + this._rotationY + "deg) ";
}
if (this._rotationX !== null) {
transform += "rotateX(" + this._rotationX + "deg) ";
}
if (this._rotationZ !== 0) {
transform += "rotateZ(" + (-1 * this._rotationZ) + "deg) ";
}
if (this._skewX !== null || this._skewY !== null) {
var skewX = SpanStyles._valueOrDefault(this._skewX, 0);
var skewY = SpanStyles._valueOrDefault(this._skewY, 0);
@@ -1086,7 +1092,39 @@ module libjass.renderers {
filterWrapperSpan.style.display = "inline-block";
}
return filterWrapperSpan;
var rotationWrapperSpan = document.createElement("span");
rotationWrapperSpan.appendChild(filterWrapperSpan);
var rotationTransform = "";
if (this._rotationX !== previousRotationX || this._rotationY !== previousRotationY || this._rotationZ !== previousRotationZ) {
if (previousRotationZ !== 0) {
rotationTransform += "rotateZ(" + (previousRotationZ) + "deg) ";
}
if (previousRotationX !== 0) {
rotationTransform += "rotateX(" + (-previousRotationX) + "deg) ";
}
if (previousRotationY !== 0) {
rotationTransform += "rotateY(" + (-previousRotationY) + "deg) ";
}
if (this._rotationY !== 0) {
rotationTransform += "rotateY(" + this._rotationY + "deg) ";
}
if (this._rotationX !== 0) {
rotationTransform += "rotateX(" + this._rotationX + "deg) ";
}
if (this._rotationZ !== 0) {
rotationTransform += "rotateZ(" + (-this._rotationZ) + "deg) ";
}
}
if (rotationTransform !== "") {
rotationWrapperSpan.style.webkitTransform = rotationTransform;
rotationWrapperSpan.style.webkitTransformOrigin = "50% 50%";
rotationWrapperSpan.style.transform = rotationTransform;
rotationWrapperSpan.style.transformOrigin = "50% 50%";
rotationWrapperSpan.style.display = "inline-block";
}
return rotationWrapperSpan;
}
/**
@@ -1224,13 +1262,21 @@ module libjass.renderers {
this._letterSpacing = SpanStyles._valueOrDefault(value, this._defaultStyle.letterSpacing);
}
get rotationX() {
return this._rotationX;
}
/**
* Sets the X-axis rotation property.
*
* @type {?number}
*/
set rotationX(value: number) {
this._rotationX = value;
this._rotationX = SpanStyles._valueOrDefault(value, 0);
}
get rotationY() {
return this._rotationY;
}
/**
@@ -1239,7 +1285,11 @@ module libjass.renderers {
* @type {?number}
*/
set rotationY(value: number) {
this._rotationY = value;
this._rotationY = SpanStyles._valueOrDefault(value, 0);
}
get rotationZ() {
return this._rotationZ;
}
/**
+68 -79
View File
@@ -21,16 +21,12 @@
///<reference path="libjass.ts" />
module libjass {
export interface StyleMap {
[name: string]: Style;
}
/**
* This class represents an ASS script. It contains the script properties, an array of Styles, and an array of Dialogues.
*/
export class ASS {
private _properties: ScriptProperties = new ScriptProperties();
private _styles: StyleMap = Object.create(null);
private _styles: Map<string, Style> = new Map<string, Style>();
private _dialogues: Dialogue[] = [];
private _dialoguesFormatSpecifier: string[];
@@ -46,9 +42,9 @@ module libjass {
/**
* The styles in this script.
*
* @type {!Object.<string, !libjass.Style>}
* @type {!Map.<string, !libjass.Style>}
*/
get styles(): StyleMap {
get styles(): Map<string, Style> {
return this._styles;
}
@@ -115,25 +111,25 @@ module libjass {
}
private static _fromASSString(rawASS: string): ASS {
var script = parser.parse(rawASS, "assScript");
var script = <Map<string, any>>parser.parse(rawASS, "assScript");
var result = new ASS();
// Get the script info template
var infoTemplate: Template = script["Script Info"];
var infoTemplate: Map<string, string> = script.get("Script Info");
if (libjass.verboseMode) {
console.log("Read script info: " + JSON.stringify(infoTemplate), infoTemplate);
}
// Parse the script properties
result.properties.resolutionX = parseInt(infoTemplate["PlayResX"]);
result.properties.resolutionY = parseInt(infoTemplate["PlayResY"]);
result.properties.wrappingStyle = parseInt(infoTemplate["WrapStyle"]);
result.properties.scaleBorderAndShadow = (infoTemplate["ScaledBorderAndShadow"] === "yes");
result.properties.resolutionX = parseInt(infoTemplate.get("PlayResX"));
result.properties.resolutionY = parseInt(infoTemplate.get("PlayResY"));
result.properties.wrappingStyle = parseInt(infoTemplate.get("WrapStyle"));
result.properties.scaleBorderAndShadow = (infoTemplate.get("ScaledBorderAndShadow") === "yes");
// Get styles from the styles section
(<TypedTemplateArray>script["V4+ Styles"]).forEach(line => {
(<TypedTemplateArray>script.get("V4+ Styles")).forEach(line => {
if (line.type === "Style") {
var styleTemplate = line.template;
@@ -143,12 +139,12 @@ module libjass {
// Create the style and add it to the styles map
var newStyle = new Style(styleTemplate);
result.styles[newStyle.name] = newStyle;
result.styles.set(newStyle.name, newStyle);
}
});
// Get dialogues from the events section
var events = <TypedTemplateArray>script["Events"];
var events = <TypedTemplateArray>script.get("Events");
result._dialoguesFormatSpecifier = events.formatSpecifier;
events.forEach(line => result._addEvent(line));
@@ -166,36 +162,36 @@ module libjass {
result.properties.wrappingStyle = 1;
result.properties.scaleBorderAndShadow = true;
var newStyle = new Style({
"Name": "Default",
"Italic": "0", "Bold": "0", "Underline": "0", "StrikeOut": "0",
"Fontname": "", "Fontsize": "50",
"ScaleX": "100", "ScaleY": "100",
"Spacing": "0",
"Angle": "0",
"PrimaryColour": "&H0000FFFF", "SecondaryColour": "&H00000000", "OutlineColour": "&H00000000", "BackColour": "&H00000000",
"Outline": "1", "BorderStyle": "1",
"Shadow": "1",
"Alignment": "2",
"MarginL": "80", "MarginR": "80", "MarginV": "35"
});
result.styles[newStyle.name] = newStyle;
var newStyle = new Style(new Map<string, string>()
.set("Name", "Default")
.set("Italic", "0").set("Bold", "0").set("Underline", "0").set("StrikeOut", "0")
.set("Fontname", "").set("Fontsize", "50")
.set("ScaleX", "100").set("ScaleY", "100")
.set("Spacing", "0")
.set("Angle", "0")
.set("PrimaryColour", "&H0000FFFF").set("SecondaryColour", "&H00000000").set("OutlineColour", "&H00000000").set("BackColour", "&H00000000")
.set("Outline", "1").set("BorderStyle", "1")
.set("Shadow", "1")
.set("Alignment", "2")
.set("MarginL", "80").set("MarginR", "80").set("MarginV", "35")
);
result.styles.set(newStyle.name, newStyle);
script.sort((line1, line2) => line1["number"] - line2["number"]).forEach(line => {
result.dialogues.push(new Dialogue({
"Style": "Default",
"Start": line.start, "End": line.end,
"Layer": "0",
"Text":
result.dialogues.push(new Dialogue(new Map<string, string>()
.set("Style", "Default")
.set("Start", line.start).set("End", line.end)
.set("Layer", "0")
.set("Text",
(<string>line.text)
.replace("<b>", "{\\b1}").replace("</b>", "{\\b0}")
.replace("<i>", "{\\i1}").replace("</i>", "{\\i0}")
.replace("<u>", "{\\u1}").replace("</u>", "{\\u0}")
.replace(/<b>/g, "{\\b1}").replace(/<\/b>/g, "{\\b0}")
.replace(/<i>/g, "{\\i1}").replace(/<\/i>/g, "{\\i0}")
.replace(/<u>/g, "{\\u1}").replace(/<\/u>/g, "{\\u0}")
.replace(
/<font color="#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})">/g,
(/* ujs:unreferenced */ substring: string, red: string, green: string, blue: string) => "{\c&H" + blue + green + red + "&}"
).replace("</font>", "{\\c}")
}, result));
).replace(/<\/font>/g, "{\\c}")
), result));
});
return result;
@@ -304,7 +300,7 @@ module libjass {
/**
* This class represents a single global style declaration in an ASS script. The styles can be obtained via the ASS.styles property.
*
* @param {!Object} template The template object that contains the style's properties. It is a map of the string values read from the ASS file.
* @param {!Map.<string, string>} template The template object that contains the style's properties. It is a map of the string values read from the ASS file.
* @param {string} template["Name"] The name of the style
* @param {string} template["Italic"] -1 if the style is italicized
* @param {string} template["Bold"] -1 if the style is bold
@@ -359,39 +355,39 @@ module libjass {
private _marginRight: number;
private _marginVertical: number;
constructor(template: Template) {
this._name = template["Name"];
constructor(template: Map<string, string>) {
this._name = template.get("Name");
this._italic = template["Italic"] === "-1";
this._bold = template["Bold"] === "-1";
this._underline = template["Underline"] === "-1";
this._strikeThrough = template["StrikeOut"] === "-1";
this._italic = template.get("Italic") === "-1";
this._bold = template.get("Bold") === "-1";
this._underline = template.get("Underline") === "-1";
this._strikeThrough = template.get("StrikeOut") === "-1";
this._fontName = template["Fontname"];
this._fontSize = parseFloat(template["Fontsize"]);
this._fontName = template.get("Fontname");
this._fontSize = parseFloat(template.get("Fontsize"));
this._fontScaleX = parseFloat(template["ScaleX"]) / 100;
this._fontScaleY = parseFloat(template["ScaleY"]) / 100;
this._fontScaleX = parseFloat(template.get("ScaleX")) / 100;
this._fontScaleY = parseFloat(template.get("ScaleY")) / 100;
this._letterSpacing = parseFloat(template["Spacing"]);
this._letterSpacing = parseFloat(template.get("Spacing"));
this._rotationZ = parseFloat(template["Angle"]);
this._rotationZ = parseFloat(template.get("Angle"));
this._primaryColor = <parts.Color>parser.parse(template["PrimaryColour"], "colorWithAlpha");
this._secondaryColor = <parts.Color>parser.parse(template["SecondaryColour"], "colorWithAlpha");
this._outlineColor = <parts.Color>parser.parse(template["OutlineColour"], "colorWithAlpha");
this._shadowColor = <parts.Color>parser.parse(template["BackColour"], "colorWithAlpha");
this._primaryColor = <parts.Color>parser.parse(template.get("PrimaryColour"), "colorWithAlpha");
this._secondaryColor = <parts.Color>parser.parse(template.get("SecondaryColour"), "colorWithAlpha");
this._outlineColor = <parts.Color>parser.parse(template.get("OutlineColour"), "colorWithAlpha");
this._shadowColor = <parts.Color>parser.parse(template.get("BackColour"), "colorWithAlpha");
this._outlineThickness = parseFloat(template["Outline"]);
this._borderStyle = parseInt(template["BorderStyle"]);
this._outlineThickness = parseFloat(template.get("Outline"));
this._borderStyle = parseInt(template.get("BorderStyle"));
this._shadowDepth = parseFloat(template["Shadow"]);
this._shadowDepth = parseFloat(template.get("Shadow"));
this._alignment = parseInt(template["Alignment"]);
this._alignment = parseInt(template.get("Alignment"));
this._marginLeft = parseFloat(template["MarginL"]);
this._marginRight = parseFloat(template["MarginR"]);
this._marginVertical = parseFloat(template["MarginV"]);
this._marginLeft = parseFloat(template.get("MarginL"));
this._marginRight = parseFloat(template.get("MarginR"));
this._marginVertical = parseFloat(template.get("MarginV"));
}
/**
@@ -596,7 +592,7 @@ module libjass {
/**
* This class represents a dialogue in an ASS script.
*
* @param {!Object} template The template object that contains the dialogue's properties. It is a map of the string values read from the ASS file.
* @param {!Map.<string, string>} template The template object that contains the dialogue's properties. It is a map of the string values read from the ASS file.
* @param {string} template["Style"] The name of the default style of this dialogue
* @param {string} template["Start"] The start time
* @param {string} template["End"] The end time
@@ -622,17 +618,17 @@ module libjass {
private _sub: HTMLDivElement = null;
constructor(template: Template, ass: ASS) {
constructor(template: Map<string, string>, ass: ASS) {
this._id = ++Dialogue._lastDialogueId;
this._style = ass.styles[template["Style"]];
this._style = ass.styles.get(template.get("Style"));
this._start = Dialogue._toTime(template["Start"]);
this._end = Dialogue._toTime(template["End"]);
this._start = Dialogue._toTime(template.get("Start"));
this._end = Dialogue._toTime(template.get("End"));
this._layer = Math.max(parseInt(template["Layer"]), 0);
this._layer = Math.max(parseInt(template.get("Layer")), 0);
this._rawPartsString = template["Text"];
this._rawPartsString = template.get("Text");
}
/**
@@ -772,19 +768,12 @@ module libjass {
}
}
/**
* A template object. It is a map of string keys and string values.
*/
export interface Template {
[key: string]: string;
}
/**
* A template object with a particular type.
*/
export interface TypedTemplate {
type: string;
template: Template;
template: Map<string, string>;
}
/**