jassub 1.7.18 → 1.7.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/jassub.es.js CHANGED
@@ -1,11 +1,11 @@
1
1
  typeof HTMLVideoElement < "u" && !("requestVideoFrameCallback" in HTMLVideoElement.prototype) && "getVideoPlaybackQuality" in HTMLVideoElement.prototype && (HTMLVideoElement.prototype._rvfcpolyfillmap = {}, HTMLVideoElement.prototype.requestVideoFrameCallback = function(c) {
2
- const e = performance.now(), t = this.getVideoPlaybackQuality(), s = this.mozPresentedFrames || this.mozPaintedFrames || t.totalVideoFrames - t.droppedVideoFrames, i = (n, r) => {
3
- const a = this.getVideoPlaybackQuality(), h = this.mozPresentedFrames || this.mozPaintedFrames || a.totalVideoFrames - a.droppedVideoFrames;
2
+ const e = performance.now(), t = this.getVideoPlaybackQuality(), s = this.mozPresentedFrames || this.mozPaintedFrames || t.totalVideoFrames - t.droppedVideoFrames, r = (n, a) => {
3
+ const i = this.getVideoPlaybackQuality(), h = this.mozPresentedFrames || this.mozPaintedFrames || i.totalVideoFrames - i.droppedVideoFrames;
4
4
  if (h > s) {
5
- const d = this.mozFrameDelay || a.totalFrameDelay - t.totalFrameDelay || 0, l = r - n;
6
- c(r, {
7
- presentationTime: r + d * 1e3,
8
- expectedDisplayTime: r + l,
5
+ const d = this.mozFrameDelay || i.totalFrameDelay - t.totalFrameDelay || 0, l = a - n;
6
+ c(a, {
7
+ presentationTime: a + d * 1e3,
8
+ expectedDisplayTime: a + l,
9
9
  width: this.videoWidth,
10
10
  height: this.videoHeight,
11
11
  mediaTime: Math.max(0, this.currentTime || 0) + l / 1e3,
@@ -13,9 +13,9 @@ typeof HTMLVideoElement < "u" && !("requestVideoFrameCallback" in HTMLVideoEleme
13
13
  processingDuration: d
14
14
  }), delete this._rvfcpolyfillmap[e];
15
15
  } else
16
- this._rvfcpolyfillmap[e] = requestAnimationFrame((d) => i(r, d));
16
+ this._rvfcpolyfillmap[e] = requestAnimationFrame((d) => r(a, d));
17
17
  };
18
- return this._rvfcpolyfillmap[e] = requestAnimationFrame((n) => i(e, n)), e;
18
+ return this._rvfcpolyfillmap[e] = requestAnimationFrame((n) => r(e, n)), e;
19
19
  }, HTMLVideoElement.prototype.cancelVideoFrameCallback = function(c) {
20
20
  cancelAnimationFrame(this._rvfcpolyfillmap[c]), delete this._rvfcpolyfillmap[c];
21
21
  });
@@ -73,8 +73,10 @@ class o extends EventTarget {
73
73
  * @param {Number} [options.libassGlyphLimit] libass glyph cache memory limit in MiB (approximate).
74
74
  */
75
75
  constructor(e) {
76
- if (super(), !globalThis.Worker) throw this.destroy("Worker not supported");
77
- if (!e) throw this.destroy("No options provided");
76
+ if (super(), !globalThis.Worker)
77
+ throw this.destroy("Worker not supported");
78
+ if (!e)
79
+ throw this.destroy("No options provided");
78
80
  this._loaded = /** @type {Promise<void>} */
79
81
  new Promise((s) => {
80
82
  this._init = s;
@@ -84,7 +86,8 @@ class o extends EventTarget {
84
86
  this._canvasParent = document.createElement("div"), this._canvasParent.className = "JASSUB", this._canvasParent.style.position = "relative", this._canvas = this._createCanvas(), this._video.insertAdjacentElement("afterend", this._canvasParent);
85
87
  else if (!this._canvas)
86
88
  throw this.destroy("Don't know where to render: you should give video or canvas in options.");
87
- if (this._bufferCanvas = document.createElement("canvas"), this._bufferCtx = this._bufferCanvas.getContext("2d"), !this._bufferCtx) throw this.destroy("Canvas rendering not supported");
89
+ if (this._bufferCanvas = document.createElement("canvas"), this._bufferCtx = this._bufferCanvas.getContext("2d"), !this._bufferCtx)
90
+ throw this.destroy("Canvas rendering not supported");
88
91
  this._canvasctrl = this._offscreenRender ? this._canvas.transferControlToOffscreen() : this._canvas, this._ctx = !this._offscreenRender && this._canvasctrl.getContext("2d"), this._lastRenderTime = 0, this.debug = !!e.debug, this.prescaleFactor = e.prescaleFactor || 1, this.prescaleHeightLimit = e.prescaleHeightLimit || 1080, this.maxRenderHeight = e.maxRenderHeight || 0, this._boundResize = this.resize.bind(this), this._boundTimeUpdate = this._timeupdate.bind(this), this._boundSetRate = this.setRate.bind(this), this._boundUpdateColorSpace = this._updateColorSpace.bind(this), this._video && this.setVideo(e.video), this._onDemandRender && (this.busy = !1, this._lastDemandTime = null), this._worker = new Worker(e.workerUrl || "jassub-worker.js"), this._worker.onmessage = (s) => this._onmessage(s), this._worker.onerror = (s) => this._error(s), t.then(() => {
89
92
  this._worker.postMessage({
90
93
  target: "init",
@@ -131,9 +134,11 @@ class o extends EventTarget {
131
134
  }
132
135
  }
133
136
  static async _testImageBugs() {
134
- if (o._hasBitmapBug !== null) return;
137
+ if (o._hasBitmapBug !== null)
138
+ return;
135
139
  const e = document.createElement("canvas"), t = e.getContext("2d", { willReadFrequently: !0 });
136
- if (!t) throw new Error("Canvas rendering not supported");
140
+ if (!t)
141
+ throw new Error("Canvas rendering not supported");
137
142
  if (typeof ImageData.prototype.constructor == "function")
138
143
  try {
139
144
  new ImageData(new Uint8ClampedArray([0, 0, 0, 0]), 1, 1);
@@ -143,19 +148,20 @@ class o extends EventTarget {
143
148
  return h && m.data.set(h), m;
144
149
  };
145
150
  }
146
- const s = document.createElement("canvas"), i = s.getContext("2d", { willReadFrequently: !0 });
147
- if (!i) throw new Error("Canvas rendering not supported");
148
- e.width = s.width = 1, e.height = s.height = 1, t.clearRect(0, 0, 1, 1), i.clearRect(0, 0, 1, 1);
149
- const n = i.getImageData(0, 0, 1, 1).data;
150
- t.putImageData(new ImageData(new Uint8ClampedArray([0, 255, 0, 0]), 1, 1), 0, 0), i.drawImage(e, 0, 0);
151
- const r = i.getImageData(0, 0, 1, 1).data;
152
- if (o._hasAlphaBug = n[1] !== r[1], o._hasAlphaBug && console.log("Detected a browser having issue with transparent pixels, applying workaround"), typeof createImageBitmap < "u") {
153
- const a = new Uint8ClampedArray([255, 0, 255, 0, 255]).subarray(1, 5);
154
- i.drawImage(await createImageBitmap(new ImageData(a, 1)), 0, 0);
155
- const { data: h } = i.getImageData(0, 0, 1, 1);
151
+ const s = document.createElement("canvas"), r = s.getContext("2d", { willReadFrequently: !0 });
152
+ if (!r)
153
+ throw new Error("Canvas rendering not supported");
154
+ e.width = s.width = 1, e.height = s.height = 1, t.clearRect(0, 0, 1, 1), r.clearRect(0, 0, 1, 1);
155
+ const n = r.getImageData(0, 0, 1, 1).data;
156
+ t.putImageData(new ImageData(new Uint8ClampedArray([0, 255, 0, 0]), 1, 1), 0, 0), r.drawImage(e, 0, 0);
157
+ const a = r.getImageData(0, 0, 1, 1).data;
158
+ if (o._hasAlphaBug = n[1] !== a[1], o._hasAlphaBug && console.log("Detected a browser having issue with transparent pixels, applying workaround"), typeof createImageBitmap < "u") {
159
+ const i = new Uint8ClampedArray([255, 0, 255, 0, 255]).subarray(1, 5);
160
+ r.drawImage(await createImageBitmap(new ImageData(i, 1)), 0, 0);
161
+ const { data: h } = r.getImageData(0, 0, 1, 1);
156
162
  o._hasBitmapBug = !1;
157
163
  for (const [d, l] of h.entries())
158
- if (Math.abs(a[d] - l) > 15) {
164
+ if (Math.abs(i[d] - l) > 15) {
159
165
  o._hasBitmapBug = !0, console.log("Detected a browser having issue with partial bitmaps, applying workaround");
160
166
  break;
161
167
  }
@@ -174,33 +180,33 @@ class o extends EventTarget {
174
180
  * @param {Number} [left=0]
175
181
  * @param {Boolean} [force=false]
176
182
  */
177
- resize(e = 0, t = 0, s = 0, i = 0, n = this._video?.paused) {
183
+ resize(e = 0, t = 0, s = 0, r = 0, n = this._video?.paused) {
178
184
  if ((!e || !t) && this._video) {
179
- const r = this._getVideoPosition();
180
- let a = null;
185
+ const a = this._getVideoPosition();
186
+ let i = null;
181
187
  if (this._videoWidth) {
182
188
  const h = this._video.videoWidth / this._videoWidth, d = this._video.videoHeight / this._videoHeight;
183
- a = this._computeCanvasSize((r.width || 0) / h, (r.height || 0) / d);
189
+ i = this._computeCanvasSize((a.width || 0) / h, (a.height || 0) / d);
184
190
  } else
185
- a = this._computeCanvasSize(r.width || 0, r.height || 0);
186
- e = a.width, t = a.height, this._canvasParent && (s = r.y - (this._canvasParent.getBoundingClientRect().top - this._video.getBoundingClientRect().top), i = r.x), this._canvas.style.width = r.width + "px", this._canvas.style.height = r.height + "px";
191
+ i = this._computeCanvasSize(a.width || 0, a.height || 0);
192
+ e = i.width, t = i.height, this._canvasParent && (s = a.y - (this._canvasParent.getBoundingClientRect().top - this._video.getBoundingClientRect().top), r = a.x), this._canvas.style.width = a.width + "px", this._canvas.style.height = a.height + "px";
187
193
  }
188
- this._canvas.style.top = s + "px", this._canvas.style.left = i + "px", n && this.busy === !1 ? this.busy = !0 : n = !1, this.sendMessage("canvas", { width: e, height: t, force: n });
194
+ this._canvas.style.top = s + "px", this._canvas.style.left = r + "px", n && this.busy === !1 ? this.busy = !0 : n = !1, this.sendMessage("canvas", { width: e, height: t, force: n });
189
195
  }
190
196
  _getVideoPosition(e = this._video.videoWidth, t = this._video.videoHeight) {
191
- const s = e / t, { offsetWidth: i, offsetHeight: n } = this._video, r = i / n;
192
- e = i, t = n, r > s ? e = Math.floor(n * s) : t = Math.floor(i / s);
193
- const a = (i - e) / 2, h = (n - t) / 2;
194
- return { width: e, height: t, x: a, y: h };
197
+ const s = e / t, { offsetWidth: r, offsetHeight: n } = this._video, a = r / n;
198
+ e = r, t = n, a > s ? e = Math.floor(n * s) : t = Math.floor(r / s);
199
+ const i = (r - e) / 2, h = (n - t) / 2;
200
+ return { width: e, height: t, x: i, y: h };
195
201
  }
196
202
  _computeCanvasSize(e = 0, t = 0) {
197
- const s = this.prescaleFactor <= 0 ? 1 : this.prescaleFactor, i = self.devicePixelRatio || 1;
198
- if (e = e * i, t = t * i, t <= 0 || e <= 0)
203
+ const s = this.prescaleFactor <= 0 ? 1 : this.prescaleFactor, r = self.devicePixelRatio || 1;
204
+ if (t <= 0 || e <= 0)
199
205
  e = 0, t = 0;
200
206
  else {
201
207
  const n = s < 1 ? -1 : 1;
202
- let r = t * i;
203
- n * r * s <= n * this.prescaleHeightLimit ? r *= s : n * r < n * this.prescaleHeightLimit && (r = this.prescaleHeightLimit), this.maxRenderHeight > 0 && r > this.maxRenderHeight && (r = this.maxRenderHeight), e *= r / t, t = r;
208
+ let a = t * r;
209
+ n * a * s <= n * this.prescaleHeightLimit ? a *= s : n * a < n * this.prescaleHeightLimit && (a = this.prescaleHeightLimit), this.maxRenderHeight > 0 && a > this.maxRenderHeight && (a = this.maxRenderHeight), e *= a / t, t = a;
204
210
  }
205
211
  return { width: e, height: t };
206
212
  }
@@ -385,9 +391,9 @@ class o extends EventTarget {
385
391
  _sendLocalFont(e) {
386
392
  try {
387
393
  queryLocalFonts().then((t) => {
388
- const s = t?.find((i) => i.fullName.toLowerCase() === e);
389
- s && s.blob().then((i) => {
390
- i.arrayBuffer().then((n) => {
394
+ const s = t?.find((r) => r.fullName.toLowerCase() === e);
395
+ s && s.blob().then((r) => {
396
+ r.arrayBuffer().then((n) => {
391
397
  this.addFont(new Uint8Array(n));
392
398
  });
393
399
  });
@@ -408,21 +414,24 @@ class o extends EventTarget {
408
414
  _unbusy() {
409
415
  this._lastDemandTime ? this._demandRender(this._lastDemandTime) : this.busy = !1;
410
416
  }
411
- _handleRVFC(e, { mediaTime: t, width: s, height: i }) {
412
- if (this._destroyed) return null;
413
- this.busy ? this._lastDemandTime = { mediaTime: t, width: s, height: i } : (this.busy = !0, this._demandRender({ mediaTime: t, width: s, height: i })), this._video.requestVideoFrameCallback(this._handleRVFC.bind(this));
417
+ _handleRVFC(e, { mediaTime: t, width: s, height: r }) {
418
+ if (this._destroyed)
419
+ return null;
420
+ this.busy ? this._lastDemandTime = { mediaTime: t, width: s, height: r } : (this.busy = !0, this._demandRender({ mediaTime: t, width: s, height: r })), this._video.requestVideoFrameCallback(this._handleRVFC.bind(this));
414
421
  }
415
422
  _demandRender({ mediaTime: e, width: t, height: s }) {
416
423
  this._lastDemandTime = null, (t !== this._videoWidth || s !== this._videoHeight) && (this._videoWidth = t, this._videoHeight = s, this.resize()), this.sendMessage("demand", { time: e + this.timeOffset });
417
424
  }
418
425
  // if we're using offscreen render, we can't use ctx filters, so we can't use a transfered canvas
419
426
  _detachOffscreen() {
420
- if (!this._offscreenRender || this._ctx) return null;
427
+ if (!this._offscreenRender || this._ctx)
428
+ return null;
421
429
  this._canvas.remove(), this._createCanvas(), this._canvasctrl = this._canvas, this._ctx = this._canvasctrl.getContext("2d"), this.sendMessage("detachOffscreen"), this.busy = !1, this.resize(0, 0, 0, 0, !0);
422
430
  }
423
431
  // if the video or track changed, we need to re-attach the offscreen canvas
424
432
  _reAttachOffscreen() {
425
- if (!this._offscreenRender || !this._ctx) return null;
433
+ if (!this._offscreenRender || !this._ctx)
434
+ return null;
426
435
  this._canvas.remove(), this._createCanvas(), this._canvasctrl = this._canvas.transferControlToOffscreen(), this._ctx = !1, this.sendMessage("offscreenCanvas", null, [this._canvasctrl]), this.resize(0, 0, 0, 0, !0);
427
436
  }
428
437
  _updateColorSpace() {
@@ -444,17 +453,18 @@ class o extends EventTarget {
444
453
  _verifyColorSpace({ subtitleColorSpace: e, videoColorSpace: t = this._videoColorSpace }) {
445
454
  !e || !t || e !== t && (this._detachOffscreen(), this._ctx.filter = `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='f'><feColorMatrix type='matrix' values='${f[e][t]} 0 0 0 0 0 1 0'/></filter></svg>#f")`);
446
455
  }
447
- _render({ images: e, asyncRender: t, times: s, width: i, height: n, colorSpace: r }) {
448
- this._unbusy(), this.debug && (s.IPCTime = Date.now() - s.JSRenderTime), (this._canvasctrl.width !== i || this._canvasctrl.height !== n) && (this._canvasctrl.width = i, this._canvasctrl.height = n, this._verifyColorSpace({ subtitleColorSpace: r })), this._ctx.clearRect(0, 0, this._canvasctrl.width, this._canvasctrl.height);
449
- for (const a of e)
450
- a.image && (t ? (this._ctx.drawImage(a.image, a.x, a.y), a.image.close()) : (this._bufferCanvas.width = a.w, this._bufferCanvas.height = a.h, this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(a.image)), a.w, a.h), 0, 0), this._ctx.drawImage(this._bufferCanvas, a.x, a.y)));
456
+ _render({ images: e, asyncRender: t, times: s, width: r, height: n, colorSpace: a }) {
457
+ this._unbusy(), this.debug && (s.IPCTime = Date.now() - s.JSRenderTime), (this._canvasctrl.width !== r || this._canvasctrl.height !== n) && (this._canvasctrl.width = r, this._canvasctrl.height = n, this._verifyColorSpace({ subtitleColorSpace: a })), this._ctx.clearRect(0, 0, this._canvasctrl.width, this._canvasctrl.height);
458
+ for (const i of e)
459
+ i.image && (t ? (this._ctx.drawImage(i.image, i.x, i.y), i.image.close()) : (this._bufferCanvas.width = i.w, this._bufferCanvas.height = i.h, this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(i.image)), i.w, i.h), 0, 0), this._ctx.drawImage(this._bufferCanvas, i.x, i.y)));
451
460
  if (this.debug) {
452
461
  s.JSRenderTime = Date.now() - s.JSRenderTime - s.IPCTime;
453
- let a = 0;
462
+ let i = 0;
454
463
  const h = s.bitmaps || e.length;
455
464
  delete s.bitmaps;
456
- for (const d in s) a += s[d];
457
- console.log("Bitmaps: " + h + " Total: " + (a | 0) + "ms", s);
465
+ for (const d in s)
466
+ i += s[d];
467
+ console.log("Bitmaps: " + h + " Total: " + (i | 0) + "ms", s);
458
468
  }
459
469
  }
460
470
  _fixAlpha(e) {
@@ -484,14 +494,14 @@ class o extends EventTarget {
484
494
  }
485
495
  _fetchFromWorker(e, t) {
486
496
  try {
487
- const s = e.target, i = setTimeout(() => {
488
- r(new Error("Error: Timeout while try to fetch " + s));
489
- }, 5e3), n = ({ data: a }) => {
490
- a.target === s && (t(null, a), this._worker.removeEventListener("message", n), this._worker.removeEventListener("error", r), clearTimeout(i));
491
- }, r = (a) => {
492
- t(a), this._worker.removeEventListener("message", n), this._worker.removeEventListener("error", r), clearTimeout(i);
497
+ const s = e.target, r = setTimeout(() => {
498
+ a(new Error("Error: Timeout while try to fetch " + s));
499
+ }, 5e3), n = ({ data: i }) => {
500
+ i.target === s && (t(null, i), this._worker.removeEventListener("message", n), this._worker.removeEventListener("error", a), clearTimeout(r));
501
+ }, a = (i) => {
502
+ t(i), this._worker.removeEventListener("message", n), this._worker.removeEventListener("error", a), clearTimeout(r);
493
503
  };
494
- this._worker.addEventListener("message", n), this._worker.addEventListener("error", r), this._worker.postMessage(e);
504
+ this._worker.addEventListener("message", n), this._worker.addEventListener("error", a), this._worker.postMessage(e);
495
505
  } catch (s) {
496
506
  this._error(s);
497
507
  }
@@ -1 +1 @@
1
- (function(c,m){typeof exports=="object"&&typeof module<"u"?module.exports=m():typeof define=="function"&&define.amd?define(m):(c=typeof globalThis<"u"?globalThis:c||self,c.JASSUB=m())})(this,function(){"use strict";typeof HTMLVideoElement<"u"&&!("requestVideoFrameCallback"in HTMLVideoElement.prototype)&&"getVideoPlaybackQuality"in HTMLVideoElement.prototype&&(HTMLVideoElement.prototype._rvfcpolyfillmap={},HTMLVideoElement.prototype.requestVideoFrameCallback=function(_){const e=performance.now(),t=this.getVideoPlaybackQuality(),s=this.mozPresentedFrames||this.mozPaintedFrames||t.totalVideoFrames-t.droppedVideoFrames,i=(n,r)=>{const a=this.getVideoPlaybackQuality(),h=this.mozPresentedFrames||this.mozPaintedFrames||a.totalVideoFrames-a.droppedVideoFrames;if(h>s){const d=this.mozFrameDelay||a.totalFrameDelay-t.totalFrameDelay||0,l=r-n;_(r,{presentationTime:r+d*1e3,expectedDisplayTime:r+l,width:this.videoWidth,height:this.videoHeight,mediaTime:Math.max(0,this.currentTime||0)+l/1e3,presentedFrames:h,processingDuration:d}),delete this._rvfcpolyfillmap[e]}else this._rvfcpolyfillmap[e]=requestAnimationFrame(d=>i(r,d))};return this._rvfcpolyfillmap[e]=requestAnimationFrame(n=>i(e,n)),e},HTMLVideoElement.prototype.cancelVideoFrameCallback=function(_){cancelAnimationFrame(this._rvfcpolyfillmap[_]),delete this._rvfcpolyfillmap[_]});const c={bt709:"BT709",bt470bg:"BT601",smpte170m:"BT601"},m={BT601:{BT709:"1.0863 -0.0723 -0.014 0 0 0.0965 0.8451 0.0584 0 0 -0.0141 -0.0277 1.0418"},BT709:{BT601:"0.9137 0.0784 0.0079 0 0 -0.1049 1.1722 -0.0671 0 0 0.0096 0.0322 0.9582"},FCC:{BT709:"1.0873 -0.0736 -0.0137 0 0 0.0974 0.8494 0.0531 0 0 -0.0127 -0.0251 1.0378",BT601:"1.001 -0.0008 -0.0002 0 0 0.0009 1.005 -0.006 0 0 0.0013 0.0027 0.996"},SMPTE240M:{BT709:"0.9993 0.0006 0.0001 0 0 -0.0004 0.9812 0.0192 0 0 -0.0034 -0.0114 1.0148",BT601:"0.913 0.0774 0.0096 0 0 -0.1051 1.1508 -0.0456 0 0 0.0063 0.0207 0.973"}};class o extends EventTarget{constructor(e){if(super(),!globalThis.Worker)throw this.destroy("Worker not supported");if(!e)throw this.destroy("No options provided");this._loaded=new Promise(s=>{this._init=s});const t=o._test();if(this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(e.onDemandRender??!0),this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!e.canvas&&(e.offscreenRender??!0),this.timeOffset=e.timeOffset||0,this._video=e.video,this._videoHeight=0,this._videoWidth=0,this._videoColorSpace=null,this._canvas=e.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="JASSUB",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy("Don't know where to render: you should give video or canvas in options.");if(this._bufferCanvas=document.createElement("canvas"),this._bufferCtx=this._bufferCanvas.getContext("2d"),!this._bufferCtx)throw this.destroy("Canvas rendering not supported");this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._ctx=!this._offscreenRender&&this._canvasctrl.getContext("2d"),this._lastRenderTime=0,this.debug=!!e.debug,this.prescaleFactor=e.prescaleFactor||1,this.prescaleHeightLimit=e.prescaleHeightLimit||1080,this.maxRenderHeight=e.maxRenderHeight||0,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=this.setRate.bind(this),this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._video&&this.setVideo(e.video),this._onDemandRender&&(this.busy=!1,this._lastDemandTime=null),this._worker=new Worker(e.workerUrl||"jassub-worker.js"),this._worker.onmessage=s=>this._onmessage(s),this._worker.onerror=s=>this._error(s),t.then(()=>{this._worker.postMessage({target:"init",wasmUrl:o._supportsSIMD&&e.modernWasmUrl?e.modernWasmUrl:e.wasmUrl??"jassub-worker.wasm",legacyWasmUrl:e.legacyWasmUrl??"jassub-worker.wasm.js",asyncRender:typeof createImageBitmap<"u"&&(e.asyncRender??!0),onDemandRender:this._onDemandRender,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:e.blendMode||"js",subUrl:e.subUrl,subContent:e.subContent||null,fonts:e.fonts||[],availableFonts:e.availableFonts||{"liberation sans":"./default.woff2"},fallbackFont:e.fallbackFont||"liberation sans",debug:this.debug,targetFps:e.targetFps||24,dropAllAnimations:e.dropAllAnimations,dropAllBlur:e.dropAllBlur,libassMemoryLimit:e.libassMemoryLimit||0,libassGlyphLimit:e.libassGlyphLimit||0,useLocalFonts:typeof queryLocalFonts<"u"&&(e.useLocalFonts??!0),hasBitmapBug:o._hasBitmapBug}),this._offscreenRender===!0&&this.sendMessage("offscreenCanvas",null,[this._canvasctrl])})}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}static _supportsSIMD=null;static _hasAlphaBug=null;static _hasBitmapBug=null;static _testSIMD(){if(o._supportsSIMD===null)try{o._supportsSIMD=WebAssembly.validate(Uint8Array.of(0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11))}catch{o._supportsSIMD=!1}}static async _testImageBugs(){if(o._hasBitmapBug!==null)return;const e=document.createElement("canvas"),t=e.getContext("2d",{willReadFrequently:!0});if(!t)throw new Error("Canvas rendering not supported");if(typeof ImageData.prototype.constructor=="function")try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("Detected that ImageData is not constructable despite browser saying so"),self.ImageData=function(h,d,l){const f=t.createImageData(d,l);return h&&f.data.set(h),f}}const s=document.createElement("canvas"),i=s.getContext("2d",{willReadFrequently:!0});if(!i)throw new Error("Canvas rendering not supported");e.width=s.width=1,e.height=s.height=1,t.clearRect(0,0,1,1),i.clearRect(0,0,1,1);const n=i.getImageData(0,0,1,1).data;t.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),i.drawImage(e,0,0);const r=i.getImageData(0,0,1,1).data;if(o._hasAlphaBug=n[1]!==r[1],o._hasAlphaBug&&console.log("Detected a browser having issue with transparent pixels, applying workaround"),typeof createImageBitmap<"u"){const a=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);i.drawImage(await createImageBitmap(new ImageData(a,1)),0,0);const{data:h}=i.getImageData(0,0,1,1);o._hasBitmapBug=!1;for(const[d,l]of h.entries())if(Math.abs(a[d]-l)>15){o._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else o._hasBitmapBug=!1;e.remove(),s.remove()}static async _test(){o._testSIMD(),await o._testImageBugs()}resize(e=0,t=0,s=0,i=0,n=this._video?.paused){if((!e||!t)&&this._video){const r=this._getVideoPosition();let a=null;if(this._videoWidth){const h=this._video.videoWidth/this._videoWidth,d=this._video.videoHeight/this._videoHeight;a=this._computeCanvasSize((r.width||0)/h,(r.height||0)/d)}else a=this._computeCanvasSize(r.width||0,r.height||0);e=a.width,t=a.height,this._canvasParent&&(s=r.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),i=r.x),this._canvas.style.width=r.width+"px",this._canvas.style.height=r.height+"px"}this._canvas.style.top=s+"px",this._canvas.style.left=i+"px",n&&this.busy===!1?this.busy=!0:n=!1,this.sendMessage("canvas",{width:e,height:t,force:n})}_getVideoPosition(e=this._video.videoWidth,t=this._video.videoHeight){const s=e/t,{offsetWidth:i,offsetHeight:n}=this._video,r=i/n;e=i,t=n,r>s?e=Math.floor(n*s):t=Math.floor(i/s);const a=(i-e)/2,h=(n-t)/2;return{width:e,height:t,x:a,y:h}}_computeCanvasSize(e=0,t=0){const s=this.prescaleFactor<=0?1:this.prescaleFactor,i=self.devicePixelRatio||1;if(e=e*i,t=t*i,t<=0||e<=0)e=0,t=0;else{const n=s<1?-1:1;let r=t*i;n*r*s<=n*this.prescaleHeightLimit?r*=s:n*r<n*this.prescaleHeightLimit&&(r=this.prescaleHeightLimit),this.maxRenderHeight>0&&r>this.maxRenderHeight&&(r=this.maxRenderHeight),e*=r/t,t=r}return{width:e,height:t}}_timeupdate({type:e}){const s={seeking:!0,waiting:!0,playing:!1}[e];s!=null&&(this._playstate=s),this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(e){e instanceof HTMLVideoElement?(this._removeListeners(),this._video=e,this._onDemandRender?this._video.requestVideoFrameCallback(this._handleRVFC.bind(this)):(this._playstate=e.paused,e.addEventListener("timeupdate",this._boundTimeUpdate,!1),e.addEventListener("progress",this._boundTimeUpdate,!1),e.addEventListener("waiting",this._boundTimeUpdate,!1),e.addEventListener("seeking",this._boundTimeUpdate,!1),e.addEventListener("playing",this._boundTimeUpdate,!1),e.addEventListener("ratechange",this._boundSetRate,!1),e.addEventListener("resize",this._boundResize,!1)),"VideoFrame"in window&&(e.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),e.readyState>2&&this._updateColorSpace()),e.videoWidth>0&&this.resize(),typeof ResizeObserver<"u"&&(this._ro||(this._ro=new ResizeObserver(()=>this.resize())),this._ro.observe(e))):this._error("Video element invalid!")}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(e){this.sendMessage("setTrackByUrl",{url:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}setTrack(e){this.sendMessage("setTrack",{content:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(e){this.sendMessage("video",{isPaused:e})}setRate(e){this.sendMessage("video",{rate:e})}setCurrentTime(e,t,s){this.sendMessage("video",{isPaused:e,currentTime:t,rate:s,colorSpace:this._videoColorSpace})}createEvent(e){this.sendMessage("createEvent",{event:e})}setEvent(e,t){this.sendMessage("setEvent",{event:e,index:t})}removeEvent(e){this.sendMessage("removeEvent",{index:e})}getEvents(e){this._fetchFromWorker({target:"getEvents"},(t,{events:s})=>{e(t,s)})}createStyle(e){this.sendMessage("createStyle",{style:e})}setStyle(e,t){this.sendMessage("setStyle",{style:e,index:t})}removeStyle(e){this.sendMessage("removeStyle",{index:e})}getStyles(e){this._fetchFromWorker({target:"getStyles"},(t,{styles:s})=>{e(t,s)})}addFont(e){this.sendMessage("addFont",{font:e})}_sendLocalFont(e){try{queryLocalFonts().then(t=>{const s=t?.find(i=>i.fullName.toLowerCase()===e);s&&s.blob().then(i=>{i.arrayBuffer().then(n=>{this.addFont(new Uint8Array(n))})})})}catch(t){console.warn("Local fonts API:",t)}}_getLocalFont({font:e}){try{navigator?.permissions?.query?navigator.permissions.query({name:"local-fonts"}).then(t=>{t.state==="granted"&&this._sendLocalFont(e)}):this._sendLocalFont(e)}catch(t){console.warn("Local fonts API:",t)}}_unbusy(){this._lastDemandTime?this._demandRender(this._lastDemandTime):this.busy=!1}_handleRVFC(e,{mediaTime:t,width:s,height:i}){if(this._destroyed)return null;this.busy?this._lastDemandTime={mediaTime:t,width:s,height:i}:(this.busy=!0,this._demandRender({mediaTime:t,width:s,height:i})),this._video.requestVideoFrameCallback(this._handleRVFC.bind(this))}_demandRender({mediaTime:e,width:t,height:s}){this._lastDemandTime=null,(t!==this._videoWidth||s!==this._videoHeight)&&(this._videoWidth=t,this._videoHeight=s,this.resize()),this.sendMessage("demand",{time:e+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d"),this.sendMessage("detachOffscreen"),this.busy=!1,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",null,[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){this._video.requestVideoFrameCallback(()=>{try{const e=new VideoFrame(this._video);this._videoColorSpace=c[e.colorSpace.matrix],e.close(),this.sendMessage("getColorSpace")}catch(e){console.warn(e)}})}_verifyColorSpace({subtitleColorSpace:e,videoColorSpace:t=this._videoColorSpace}){!e||!t||e!==t&&(this._detachOffscreen(),this._ctx.filter=`url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='f'><feColorMatrix type='matrix' values='${m[e][t]} 0 0 0 0 0 1 0'/></filter></svg>#f")`)}_render({images:e,asyncRender:t,times:s,width:i,height:n,colorSpace:r}){this._unbusy(),this.debug&&(s.IPCTime=Date.now()-s.JSRenderTime),(this._canvasctrl.width!==i||this._canvasctrl.height!==n)&&(this._canvasctrl.width=i,this._canvasctrl.height=n,this._verifyColorSpace({subtitleColorSpace:r})),this._ctx.clearRect(0,0,this._canvasctrl.width,this._canvasctrl.height);for(const a of e)a.image&&(t?(this._ctx.drawImage(a.image,a.x,a.y),a.image.close()):(this._bufferCanvas.width=a.w,this._bufferCanvas.height=a.h,this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(a.image)),a.w,a.h),0,0),this._ctx.drawImage(this._bufferCanvas,a.x,a.y)));if(this.debug){s.JSRenderTime=Date.now()-s.JSRenderTime-s.IPCTime;let a=0;const h=s.bitmaps||e.length;delete s.bitmaps;for(const d in s)a+=s[d];console.log("Bitmaps: "+h+" Total: "+(a|0)+"ms",s)}}_fixAlpha(e){if(o._hasAlphaBug)for(let t=3;t<e.length;t+=4)e[t]=e[t]>1?e[t]:1;return e}_ready(){this._init(),this.dispatchEvent(new CustomEvent("ready"))}async sendMessage(e,t={},s){await this._loaded,s?this._worker.postMessage({target:e,transferable:s,...t},[...s]):this._worker.postMessage({target:e,...t})}_fetchFromWorker(e,t){try{const s=e.target,i=setTimeout(()=>{r(new Error("Error: Timeout while try to fetch "+s))},5e3),n=({data:a})=>{a.target===s&&(t(null,a),this._worker.removeEventListener("message",n),this._worker.removeEventListener("error",r),clearTimeout(i))},r=a=>{t(a),this._worker.removeEventListener("message",n),this._worker.removeEventListener("error",r),clearTimeout(i)};this._worker.addEventListener("message",n),this._worker.addEventListener("error",r),this._worker.postMessage(e)}catch(s){this._error(s)}}_console({content:e,command:t}){console[t].apply(console,JSON.parse(e))}_onmessage({data:e}){this["_"+e.target]&&this["_"+e.target](e)}_error(e){const t=e instanceof Error?e:e instanceof ErrorEvent?e.error:new Error(e),s=e instanceof Event?new ErrorEvent(e.type,e):new ErrorEvent("error",{error:t});return this.dispatchEvent(s),console.error(t),t}_removeListeners(){this._video&&(this._ro&&this._ro.unobserve(this._video),this._ctx&&(this._ctx.filter="none"),this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace))}destroy(e){return e&&(e=this._error(e)),this._video&&this._canvasParent&&this._video.parentNode?.removeChild(this._canvasParent),this._destroyed=!0,this._removeListeners(),this.sendMessage("destroy"),this._worker?.terminate(),e}}return o});
1
+ (function(c,m){typeof exports=="object"&&typeof module<"u"?module.exports=m():typeof define=="function"&&define.amd?define(m):(c=typeof globalThis<"u"?globalThis:c||self,c.JASSUB=m())})(this,function(){"use strict";typeof HTMLVideoElement<"u"&&!("requestVideoFrameCallback"in HTMLVideoElement.prototype)&&"getVideoPlaybackQuality"in HTMLVideoElement.prototype&&(HTMLVideoElement.prototype._rvfcpolyfillmap={},HTMLVideoElement.prototype.requestVideoFrameCallback=function(_){const e=performance.now(),t=this.getVideoPlaybackQuality(),s=this.mozPresentedFrames||this.mozPaintedFrames||t.totalVideoFrames-t.droppedVideoFrames,r=(n,a)=>{const i=this.getVideoPlaybackQuality(),h=this.mozPresentedFrames||this.mozPaintedFrames||i.totalVideoFrames-i.droppedVideoFrames;if(h>s){const d=this.mozFrameDelay||i.totalFrameDelay-t.totalFrameDelay||0,l=a-n;_(a,{presentationTime:a+d*1e3,expectedDisplayTime:a+l,width:this.videoWidth,height:this.videoHeight,mediaTime:Math.max(0,this.currentTime||0)+l/1e3,presentedFrames:h,processingDuration:d}),delete this._rvfcpolyfillmap[e]}else this._rvfcpolyfillmap[e]=requestAnimationFrame(d=>r(a,d))};return this._rvfcpolyfillmap[e]=requestAnimationFrame(n=>r(e,n)),e},HTMLVideoElement.prototype.cancelVideoFrameCallback=function(_){cancelAnimationFrame(this._rvfcpolyfillmap[_]),delete this._rvfcpolyfillmap[_]});const c={bt709:"BT709",bt470bg:"BT601",smpte170m:"BT601"},m={BT601:{BT709:"1.0863 -0.0723 -0.014 0 0 0.0965 0.8451 0.0584 0 0 -0.0141 -0.0277 1.0418"},BT709:{BT601:"0.9137 0.0784 0.0079 0 0 -0.1049 1.1722 -0.0671 0 0 0.0096 0.0322 0.9582"},FCC:{BT709:"1.0873 -0.0736 -0.0137 0 0 0.0974 0.8494 0.0531 0 0 -0.0127 -0.0251 1.0378",BT601:"1.001 -0.0008 -0.0002 0 0 0.0009 1.005 -0.006 0 0 0.0013 0.0027 0.996"},SMPTE240M:{BT709:"0.9993 0.0006 0.0001 0 0 -0.0004 0.9812 0.0192 0 0 -0.0034 -0.0114 1.0148",BT601:"0.913 0.0774 0.0096 0 0 -0.1051 1.1508 -0.0456 0 0 0.0063 0.0207 0.973"}};class o extends EventTarget{constructor(e){if(super(),!globalThis.Worker)throw this.destroy("Worker not supported");if(!e)throw this.destroy("No options provided");this._loaded=new Promise(s=>{this._init=s});const t=o._test();if(this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(e.onDemandRender??!0),this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!e.canvas&&(e.offscreenRender??!0),this.timeOffset=e.timeOffset||0,this._video=e.video,this._videoHeight=0,this._videoWidth=0,this._videoColorSpace=null,this._canvas=e.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="JASSUB",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy("Don't know where to render: you should give video or canvas in options.");if(this._bufferCanvas=document.createElement("canvas"),this._bufferCtx=this._bufferCanvas.getContext("2d"),!this._bufferCtx)throw this.destroy("Canvas rendering not supported");this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._ctx=!this._offscreenRender&&this._canvasctrl.getContext("2d"),this._lastRenderTime=0,this.debug=!!e.debug,this.prescaleFactor=e.prescaleFactor||1,this.prescaleHeightLimit=e.prescaleHeightLimit||1080,this.maxRenderHeight=e.maxRenderHeight||0,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=this.setRate.bind(this),this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._video&&this.setVideo(e.video),this._onDemandRender&&(this.busy=!1,this._lastDemandTime=null),this._worker=new Worker(e.workerUrl||"jassub-worker.js"),this._worker.onmessage=s=>this._onmessage(s),this._worker.onerror=s=>this._error(s),t.then(()=>{this._worker.postMessage({target:"init",wasmUrl:o._supportsSIMD&&e.modernWasmUrl?e.modernWasmUrl:e.wasmUrl??"jassub-worker.wasm",legacyWasmUrl:e.legacyWasmUrl??"jassub-worker.wasm.js",asyncRender:typeof createImageBitmap<"u"&&(e.asyncRender??!0),onDemandRender:this._onDemandRender,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:e.blendMode||"js",subUrl:e.subUrl,subContent:e.subContent||null,fonts:e.fonts||[],availableFonts:e.availableFonts||{"liberation sans":"./default.woff2"},fallbackFont:e.fallbackFont||"liberation sans",debug:this.debug,targetFps:e.targetFps||24,dropAllAnimations:e.dropAllAnimations,dropAllBlur:e.dropAllBlur,libassMemoryLimit:e.libassMemoryLimit||0,libassGlyphLimit:e.libassGlyphLimit||0,useLocalFonts:typeof queryLocalFonts<"u"&&(e.useLocalFonts??!0),hasBitmapBug:o._hasBitmapBug}),this._offscreenRender===!0&&this.sendMessage("offscreenCanvas",null,[this._canvasctrl])})}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}static _supportsSIMD=null;static _hasAlphaBug=null;static _hasBitmapBug=null;static _testSIMD(){if(o._supportsSIMD===null)try{o._supportsSIMD=WebAssembly.validate(Uint8Array.of(0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11))}catch{o._supportsSIMD=!1}}static async _testImageBugs(){if(o._hasBitmapBug!==null)return;const e=document.createElement("canvas"),t=e.getContext("2d",{willReadFrequently:!0});if(!t)throw new Error("Canvas rendering not supported");if(typeof ImageData.prototype.constructor=="function")try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("Detected that ImageData is not constructable despite browser saying so"),self.ImageData=function(h,d,l){const f=t.createImageData(d,l);return h&&f.data.set(h),f}}const s=document.createElement("canvas"),r=s.getContext("2d",{willReadFrequently:!0});if(!r)throw new Error("Canvas rendering not supported");e.width=s.width=1,e.height=s.height=1,t.clearRect(0,0,1,1),r.clearRect(0,0,1,1);const n=r.getImageData(0,0,1,1).data;t.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),r.drawImage(e,0,0);const a=r.getImageData(0,0,1,1).data;if(o._hasAlphaBug=n[1]!==a[1],o._hasAlphaBug&&console.log("Detected a browser having issue with transparent pixels, applying workaround"),typeof createImageBitmap<"u"){const i=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);r.drawImage(await createImageBitmap(new ImageData(i,1)),0,0);const{data:h}=r.getImageData(0,0,1,1);o._hasBitmapBug=!1;for(const[d,l]of h.entries())if(Math.abs(i[d]-l)>15){o._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else o._hasBitmapBug=!1;e.remove(),s.remove()}static async _test(){o._testSIMD(),await o._testImageBugs()}resize(e=0,t=0,s=0,r=0,n=this._video?.paused){if((!e||!t)&&this._video){const a=this._getVideoPosition();let i=null;if(this._videoWidth){const h=this._video.videoWidth/this._videoWidth,d=this._video.videoHeight/this._videoHeight;i=this._computeCanvasSize((a.width||0)/h,(a.height||0)/d)}else i=this._computeCanvasSize(a.width||0,a.height||0);e=i.width,t=i.height,this._canvasParent&&(s=a.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),r=a.x),this._canvas.style.width=a.width+"px",this._canvas.style.height=a.height+"px"}this._canvas.style.top=s+"px",this._canvas.style.left=r+"px",n&&this.busy===!1?this.busy=!0:n=!1,this.sendMessage("canvas",{width:e,height:t,force:n})}_getVideoPosition(e=this._video.videoWidth,t=this._video.videoHeight){const s=e/t,{offsetWidth:r,offsetHeight:n}=this._video,a=r/n;e=r,t=n,a>s?e=Math.floor(n*s):t=Math.floor(r/s);const i=(r-e)/2,h=(n-t)/2;return{width:e,height:t,x:i,y:h}}_computeCanvasSize(e=0,t=0){const s=this.prescaleFactor<=0?1:this.prescaleFactor,r=self.devicePixelRatio||1;if(t<=0||e<=0)e=0,t=0;else{const n=s<1?-1:1;let a=t*r;n*a*s<=n*this.prescaleHeightLimit?a*=s:n*a<n*this.prescaleHeightLimit&&(a=this.prescaleHeightLimit),this.maxRenderHeight>0&&a>this.maxRenderHeight&&(a=this.maxRenderHeight),e*=a/t,t=a}return{width:e,height:t}}_timeupdate({type:e}){const s={seeking:!0,waiting:!0,playing:!1}[e];s!=null&&(this._playstate=s),this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(e){e instanceof HTMLVideoElement?(this._removeListeners(),this._video=e,this._onDemandRender?this._video.requestVideoFrameCallback(this._handleRVFC.bind(this)):(this._playstate=e.paused,e.addEventListener("timeupdate",this._boundTimeUpdate,!1),e.addEventListener("progress",this._boundTimeUpdate,!1),e.addEventListener("waiting",this._boundTimeUpdate,!1),e.addEventListener("seeking",this._boundTimeUpdate,!1),e.addEventListener("playing",this._boundTimeUpdate,!1),e.addEventListener("ratechange",this._boundSetRate,!1),e.addEventListener("resize",this._boundResize,!1)),"VideoFrame"in window&&(e.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),e.readyState>2&&this._updateColorSpace()),e.videoWidth>0&&this.resize(),typeof ResizeObserver<"u"&&(this._ro||(this._ro=new ResizeObserver(()=>this.resize())),this._ro.observe(e))):this._error("Video element invalid!")}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(e){this.sendMessage("setTrackByUrl",{url:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}setTrack(e){this.sendMessage("setTrack",{content:e}),this._reAttachOffscreen(),this._ctx&&(this._ctx.filter="none")}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(e){this.sendMessage("video",{isPaused:e})}setRate(e){this.sendMessage("video",{rate:e})}setCurrentTime(e,t,s){this.sendMessage("video",{isPaused:e,currentTime:t,rate:s,colorSpace:this._videoColorSpace})}createEvent(e){this.sendMessage("createEvent",{event:e})}setEvent(e,t){this.sendMessage("setEvent",{event:e,index:t})}removeEvent(e){this.sendMessage("removeEvent",{index:e})}getEvents(e){this._fetchFromWorker({target:"getEvents"},(t,{events:s})=>{e(t,s)})}createStyle(e){this.sendMessage("createStyle",{style:e})}setStyle(e,t){this.sendMessage("setStyle",{style:e,index:t})}removeStyle(e){this.sendMessage("removeStyle",{index:e})}getStyles(e){this._fetchFromWorker({target:"getStyles"},(t,{styles:s})=>{e(t,s)})}addFont(e){this.sendMessage("addFont",{font:e})}_sendLocalFont(e){try{queryLocalFonts().then(t=>{const s=t?.find(r=>r.fullName.toLowerCase()===e);s&&s.blob().then(r=>{r.arrayBuffer().then(n=>{this.addFont(new Uint8Array(n))})})})}catch(t){console.warn("Local fonts API:",t)}}_getLocalFont({font:e}){try{navigator?.permissions?.query?navigator.permissions.query({name:"local-fonts"}).then(t=>{t.state==="granted"&&this._sendLocalFont(e)}):this._sendLocalFont(e)}catch(t){console.warn("Local fonts API:",t)}}_unbusy(){this._lastDemandTime?this._demandRender(this._lastDemandTime):this.busy=!1}_handleRVFC(e,{mediaTime:t,width:s,height:r}){if(this._destroyed)return null;this.busy?this._lastDemandTime={mediaTime:t,width:s,height:r}:(this.busy=!0,this._demandRender({mediaTime:t,width:s,height:r})),this._video.requestVideoFrameCallback(this._handleRVFC.bind(this))}_demandRender({mediaTime:e,width:t,height:s}){this._lastDemandTime=null,(t!==this._videoWidth||s!==this._videoHeight)&&(this._videoWidth=t,this._videoHeight=s,this.resize()),this.sendMessage("demand",{time:e+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d"),this.sendMessage("detachOffscreen"),this.busy=!1,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return null;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",null,[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){this._video.requestVideoFrameCallback(()=>{try{const e=new VideoFrame(this._video);this._videoColorSpace=c[e.colorSpace.matrix],e.close(),this.sendMessage("getColorSpace")}catch(e){console.warn(e)}})}_verifyColorSpace({subtitleColorSpace:e,videoColorSpace:t=this._videoColorSpace}){!e||!t||e!==t&&(this._detachOffscreen(),this._ctx.filter=`url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='f'><feColorMatrix type='matrix' values='${m[e][t]} 0 0 0 0 0 1 0'/></filter></svg>#f")`)}_render({images:e,asyncRender:t,times:s,width:r,height:n,colorSpace:a}){this._unbusy(),this.debug&&(s.IPCTime=Date.now()-s.JSRenderTime),(this._canvasctrl.width!==r||this._canvasctrl.height!==n)&&(this._canvasctrl.width=r,this._canvasctrl.height=n,this._verifyColorSpace({subtitleColorSpace:a})),this._ctx.clearRect(0,0,this._canvasctrl.width,this._canvasctrl.height);for(const i of e)i.image&&(t?(this._ctx.drawImage(i.image,i.x,i.y),i.image.close()):(this._bufferCanvas.width=i.w,this._bufferCanvas.height=i.h,this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(i.image)),i.w,i.h),0,0),this._ctx.drawImage(this._bufferCanvas,i.x,i.y)));if(this.debug){s.JSRenderTime=Date.now()-s.JSRenderTime-s.IPCTime;let i=0;const h=s.bitmaps||e.length;delete s.bitmaps;for(const d in s)i+=s[d];console.log("Bitmaps: "+h+" Total: "+(i|0)+"ms",s)}}_fixAlpha(e){if(o._hasAlphaBug)for(let t=3;t<e.length;t+=4)e[t]=e[t]>1?e[t]:1;return e}_ready(){this._init(),this.dispatchEvent(new CustomEvent("ready"))}async sendMessage(e,t={},s){await this._loaded,s?this._worker.postMessage({target:e,transferable:s,...t},[...s]):this._worker.postMessage({target:e,...t})}_fetchFromWorker(e,t){try{const s=e.target,r=setTimeout(()=>{a(new Error("Error: Timeout while try to fetch "+s))},5e3),n=({data:i})=>{i.target===s&&(t(null,i),this._worker.removeEventListener("message",n),this._worker.removeEventListener("error",a),clearTimeout(r))},a=i=>{t(i),this._worker.removeEventListener("message",n),this._worker.removeEventListener("error",a),clearTimeout(r)};this._worker.addEventListener("message",n),this._worker.addEventListener("error",a),this._worker.postMessage(e)}catch(s){this._error(s)}}_console({content:e,command:t}){console[t].apply(console,JSON.parse(e))}_onmessage({data:e}){this["_"+e.target]&&this["_"+e.target](e)}_error(e){const t=e instanceof Error?e:e instanceof ErrorEvent?e.error:new Error(e),s=e instanceof Event?new ErrorEvent(e.type,e):new ErrorEvent("error",{error:t});return this.dispatchEvent(s),console.error(t),t}_removeListeners(){this._video&&(this._ro&&this._ro.unobserve(this._video),this._ctx&&(this._ctx.filter="none"),this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace))}destroy(e){return e&&(e=this._error(e)),this._video&&this._canvasParent&&this._video.parentNode?.removeChild(this._canvasParent),this._destroyed=!0,this._removeListeners(),this.sendMessage("destroy"),this._worker?.terminate(),e}}return o});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jassub",
3
- "version": "1.7.18",
3
+ "version": "1.7.20",
4
4
  "description": "libass Subtitle Renderer and Parser library for browsers",
5
5
  "main": "src/jassub.js",
6
6
  "type": "module",
package/src/jassub.js CHANGED
@@ -307,8 +307,6 @@ export default class JASSUB extends EventTarget {
307
307
  const scalefactor = this.prescaleFactor <= 0 ? 1.0 : this.prescaleFactor
308
308
  const ratio = self.devicePixelRatio || 1
309
309
 
310
- width = width * ratio
311
- height = height * ratio
312
310
  if (height <= 0 || width <= 0) {
313
311
  width = 0
314
312
  height = 0