From 9b0e15cd7875bc49e40da787acc524bd6d11dc70 Mon Sep 17 00:00:00 2001 From: Arnavion Date: Sat, 23 Jan 2016 10:46:47 -0800 Subject: [PATCH] Moved letterboxing code from WebRenderer to DefaultRenderer. The initial implementation of letterboxing incorrectly assumed that subs should always be rendered with the same width:height ratio as the script resolution. In fact desktop renderers stretch the width and height individually, so the presence or absence of letterboxing can only be determined based on the original video dimensions. WebRenderer is abstracted from the original video, so it cannot do this. So now WebRenderer.resize() takes additional left and top parameters and expects the caller to calculate the letterboxing and adjust width, height, left and top accordingly. DefaultRenderer does this. Also removed the redundant width and height parameters from DefaultRenderer.resize() since it was always expected to resize to the video's width and height anyway. Fixes #62 --- src/renderers/default.ts | 33 ++++++++++++++++++++++++++------- src/renderers/web/renderer.ts | 21 +++++++++++---------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/renderers/default.ts b/src/renderers/default.ts index 9ef0efe..a6ff038 100644 --- a/src/renderers/default.ts +++ b/src/renderers/default.ts @@ -40,18 +40,37 @@ export class DefaultRenderer extends WebRenderer { } /** - * @deprecated + * Resize the subtitles to the dimensions of the video element. * - * @param {number} width - * @param {number} height + * This method accounts for letterboxing if the video element's size is not the same ratio as the video resolution. + */ + resize(): void { + // Handle letterboxing around the video. If the width or height are greater than the video can be, then consider that dead space. + + const videoWidth = this._video.videoWidth; + const videoHeight = this._video.videoHeight; + const videoOffsetWidth = this._video.offsetWidth; + const videoOffsetHeight = this._video.offsetHeight; + + const ratio = Math.min(videoOffsetWidth / videoWidth, videoOffsetHeight / videoHeight); + const subsWrapperWidth = videoWidth * ratio; + const subsWrapperHeight = videoHeight * ratio; + const subsWrapperLeft = (videoOffsetWidth - subsWrapperWidth) / 2; + const subsWrapperTop = (videoOffsetHeight - subsWrapperHeight) / 2; + + super.resize(subsWrapperWidth, subsWrapperHeight, subsWrapperLeft, subsWrapperTop); + } + + /** + * @deprecated */ - resizeVideo(width: number, height: number): void { - console.warn("`DefaultRenderer.resizeVideo(width, height)` has been deprecated. Use `DefaultRenderer.resize(width, height)` instead."); - this.resize(width, height); + resizeVideo(): void { + console.warn("`DefaultRenderer.resizeVideo(width, height)` has been deprecated. Use `DefaultRenderer.resize()` instead."); + this.resize(); } protected _ready(): void { - this.resize(this._video.offsetWidth, this._video.offsetHeight); + this.resize(); super._ready(); } diff --git a/src/renderers/web/renderer.ts b/src/renderers/web/renderer.ts index eea9fab..640b524 100644 --- a/src/renderers/web/renderer.ts +++ b/src/renderers/web/renderer.ts @@ -321,20 +321,21 @@ export class WebRenderer extends NullRenderer implements EventSource { * * @param {number} width * @param {number} height + * @param {number=0} left + * @param {number=0} top */ - resize(width: number, height: number): void { + resize(width: number, height: number, left: number = 0, top: number = 0): void { this._removeAllSubs(); - const ratio = Math.min(width / this.ass.properties.resolutionX, height / this.ass.properties.resolutionY); - this._subsWrapperWidth = this.ass.properties.resolutionX * ratio; - const subsWrapperHeight = this.ass.properties.resolutionY * ratio; - this._subsWrapper.style.width = `${ this._subsWrapperWidth.toFixed(3) }px`; - this._subsWrapper.style.height = `${ subsWrapperHeight.toFixed(3) }px`; - this._subsWrapper.style.left = `${ ((width - this._subsWrapperWidth) / 2).toFixed(3) }px`; - this._subsWrapper.style.top = `${ ((height - subsWrapperHeight) / 2).toFixed(3) }px`; + this._subsWrapper.style.width = `${ width.toFixed(3) }px`; + this._subsWrapper.style.height = `${ height.toFixed(3) }px`; + this._subsWrapper.style.left = `${ left.toFixed(3) }px`; + this._subsWrapper.style.top = `${ top.toFixed(3) }px`; - this._scaleX = this._subsWrapperWidth / this.ass.properties.resolutionX; - this._scaleY = subsWrapperHeight / this.ass.properties.resolutionY; + this._subsWrapperWidth = width; + + this._scaleX = width / this.ass.properties.resolutionX; + this._scaleY = height / this.ass.properties.resolutionY; // Any dialogues which have been pre-rendered will need to be pre-rendered again. this._preRenderedSubs.clear();