ovenplayer 0.10.49 → 0.10.51

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.
Files changed (34) hide show
  1. package/dist/ovenplayer.js +1 -1
  2. package/dist/ovenplayer.js.map +1 -1
  3. package/package.json +49 -49
  4. package/src/js/api/Configurator.js +1 -1
  5. package/src/js/api/ads/vast/Ad.js +237 -237
  6. package/src/js/api/caption/Loader.js +1 -1
  7. package/src/js/api/caption/Manager.js +1 -1
  8. package/src/js/api/caption/parser/VttParser.js +1541 -1542
  9. package/src/js/api/playlist/Manager.js +229 -229
  10. package/src/js/api/provider/html5/providers/Dash.js +286 -286
  11. package/src/js/api/provider/html5/providers/Hls.js +110 -2
  12. package/src/js/api/provider/html5/providers/WebRTC.js +2 -1
  13. package/src/js/api/provider/html5/providers/WebRTCLoader.js +35 -2
  14. package/src/js/api/provider/utils.js +69 -69
  15. package/src/js/ovenplayer.sdk.js +143 -143
  16. package/src/js/utils/likeA$.js +241 -242
  17. package/src/js/utils/resize-sensor.js +145 -168
  18. package/src/js/utils/strings.js +104 -104
  19. package/src/js/view/components/controls/settingPanel/audioTrackPanel.js +57 -57
  20. package/src/js/view/components/controls/settingPanel/main.js +1 -1
  21. package/src/js/view/components/controls/settingPanel/mainTemplate.js +29 -29
  22. package/src/js/view/components/controls/settingPanel/qualityPanel.js +68 -68
  23. package/src/js/view/components/controls/settingPanel/subtitleTrackPanel.js +56 -56
  24. package/src/js/view/components/helpers/captionViewer.js +97 -15
  25. package/src/js/view/components/helpers/captionViewerTemplate.js +1 -2
  26. package/src/js/view/components/helpers/waterMark.js +69 -69
  27. package/src/js/view/engine/OvenTemplate.js +158 -158
  28. package/src/js/view/global/PanelManager.js +47 -47
  29. package/src/stylesheet/ovenplayer.less +52 -21
  30. package/src/js/utils/adapter.js +0 -4944
  31. package/src/js/utils/captions/vttCue.js +0 -308
  32. package/src/js/utils/captions/vttRegion.js +0 -136
  33. package/src/js/utils/polyfills/dom.js +0 -634
  34. package/src/js/utils/underscore.js +0 -6
@@ -1,1542 +1,1541 @@
1
- /* vtt.js - v0.12.1 (https://github.com/mozilla/vtt.js) built on 03-12-2015 */
2
- import VTTCue from 'utils/captions/vttCue';
3
- import VTTRegion from 'utils/captions/vttRegion';
4
-
5
- /**
6
- * Copyright 2013 vtt.js Contributors
7
- *
8
- * Licensed under the Apache License, Version 2.0 (the "License");
9
- * you may not use this file except in compliance with the License.
10
- * You may obtain a copy of the License at
11
- *
12
- * http://www.apache.org/licenses/LICENSE-2.0
13
- *
14
- * Unless required by applicable law or agreed to in writing, software
15
- * distributed under the License is distributed on an "AS IS" BASIS,
16
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
- * See the License for the specific language governing permissions and
18
- * limitations under the License.
19
- */
20
-
21
- /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
22
- /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
23
-
24
- let WebVTT = function(){};
25
- function makeColorSet(color, opacity) {
26
- if(opacity === undefined) {
27
- opacity = 1;
28
- }
29
- return "rgba(" + [parseInt(color.substring(0, 2), 16),
30
- parseInt(color.substring(2, 4), 16),
31
- parseInt(color.substring(4, 6), 16),
32
- opacity].join(",") + ")";
33
- }
34
-
35
- var WebVTTPrefs = ['webvtt.font.color', 'webvtt.font.opacity', 'webvtt.font.scale',
36
- 'webvtt.bg.color', 'webvtt.bg.opacity',
37
- 'webvtt.edge.color', 'webvtt.edge.type'];
38
-
39
- var fontScale = 1;
40
-
41
- function observe(subject, topic, data) {
42
- switch (data) {
43
- case "webvtt.font.color":
44
- case "webvtt.font.opacity":
45
- var fontColor = Services.prefs.getCharPref("webvtt.font.color");
46
- var fontOpacity = Services.prefs.getIntPref("webvtt.font.opacity") / 100;
47
- WebVTTSet.fontSet = makeColorSet(fontColor, fontOpacity);
48
- break;
49
- case "webvtt.font.scale":
50
- fontScale = Services.prefs.getIntPref("webvtt.font.scale") / 100;
51
- break;
52
- case "webvtt.bg.color":
53
- case "webvtt.bg.opacity":
54
- var backgroundColor = Services.prefs.getCharPref("webvtt.bg.color");
55
- var backgroundOpacity = Services.prefs.getIntPref("webvtt.bg.opacity") / 100;
56
- WebVTTSet.backgroundSet = makeColorSet(backgroundColor, backgroundOpacity);
57
- break;
58
- case "webvtt.edge.color":
59
- case "webvtt.edge.type":
60
- var edgeTypeList = ["", "0px 0px ", "4px 4px 4px ", "-2px -2px ", "2px 2px "];
61
- var edgeType = Services.prefs.getIntPref("webvtt.edge.type");
62
- var edgeColor = Services.prefs.getCharPref("webvtt.edge.color");
63
- WebVTTSet.edgeSet = edgeTypeList[edgeType] + makeColorSet(edgeColor);
64
- break;
65
- }
66
- }
67
-
68
- if(typeof Services !== "undefined") {
69
- var WebVTTSet = {};
70
- WebVTTPrefs.forEach(function (pref) {
71
- observe(undefined, undefined, pref);
72
- Services.prefs.addObserver(pref, observe, false);
73
- });
74
- }
75
-
76
- var _objCreate = Object.create || (function() {
77
- function F() {}
78
- return function(o) {
79
- if (arguments.length !== 1) {
80
- throw new Error('Object.create shim only accepts one parameter.');
81
- }
82
- F.prototype = o;
83
- return new F();
84
- };
85
- })();
86
-
87
- // Creates a new ParserError object from an errorData object. The errorData
88
- // object should have default code and message properties. The default message
89
- // property can be overriden by passing in a message parameter.
90
- // See ParsingError.Errors below for acceptable errors.
91
- function ParsingError(errorData, message) {
92
- this.name = "ParsingError";
93
- this.code = errorData.code;
94
- this.message = message || errorData.message;
95
- }
96
- ParsingError.prototype = _objCreate(Error.prototype);
97
- ParsingError.prototype.constructor = ParsingError;
98
-
99
- // ParsingError metadata for acceptable ParsingErrors.
100
- ParsingError.Errors = {
101
- BadSignature: {
102
- code: 0,
103
- message: "Malformed WebVTT signature."
104
- },
105
- BadTimeStamp: {
106
- code: 1,
107
- message: "Malformed time stamp."
108
- }
109
- };
110
-
111
- // Try to parse input as a time stamp.
112
- function parseTimeStamp(input) {
113
-
114
- function computeSeconds(h, m, s, f) {
115
- return (h | 0) * 3600 + (m | 0) * 60 + (s | 0) + (f | 0) / 1000;
116
- }
117
-
118
- var m = input.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/);
119
- if (!m) {
120
- return null;
121
- }
122
-
123
- if (m[3]) {
124
- // Timestamp takes the form of [hours]:[minutes]:[seconds].[milliseconds]
125
- return computeSeconds(m[1], m[2], m[3].replace(":", ""), m[4]);
126
- } else if (m[1] > 59) {
127
- // Timestamp takes the form of [hours]:[minutes].[milliseconds]
128
- // First position is hours as it's over 59.
129
- return computeSeconds(m[1], m[2], 0, m[4]);
130
- } else {
131
- // Timestamp takes the form of [minutes]:[seconds].[milliseconds]
132
- return computeSeconds(0, m[1], m[2], m[4]);
133
- }
134
- }
135
-
136
- // A settings object holds key/value pairs and will ignore anything but the first
137
- // assignment to a specific key.
138
- function Settings() {
139
- this.values = _objCreate(null);
140
- }
141
-
142
- Settings.prototype = {
143
- // Only accept the first assignment to any key.
144
- set: function(k, v) {
145
- if (!this.get(k) && v !== "") {
146
- this.values[k] = v;
147
- }
148
- },
149
- // Return the value for a key, or a default value.
150
- // If 'defaultKey' is passed then 'dflt' is assumed to be an object with
151
- // a number of possible default values as properties where 'defaultKey' is
152
- // the key of the property that will be chosen; otherwise it's assumed to be
153
- // a single value.
154
- get: function(k, dflt, defaultKey) {
155
- if (defaultKey) {
156
- return this.has(k) ? this.values[k] : dflt[defaultKey];
157
- }
158
- return this.has(k) ? this.values[k] : dflt;
159
- },
160
- // Check whether we have a value for a key.
161
- has: function(k) {
162
- return k in this.values;
163
- },
164
- // Accept a setting if its one of the given alternatives.
165
- alt: function(k, v, a) {
166
- for (var n = 0; n < a.length; ++n) {
167
- if (v === a[n]) {
168
- this.set(k, v);
169
- break;
170
- }
171
- }
172
- },
173
- // Accept a setting if its a valid (signed) integer.
174
- integer: function(k, v) {
175
- if (/^-?\d+$/.test(v)) { // integer
176
- this.set(k, parseInt(v, 10));
177
- }
178
- },
179
- // Accept a setting if its a valid percentage.
180
- percent: function(k, v) {
181
- var m;
182
- if ((m = v.match(/^([\d]{1,3})(\.[\d]*)?%$/))) {
183
- v = parseFloat(v);
184
- if (v >= 0 && v <= 100) {
185
- this.set(k, v);
186
- return true;
187
- }
188
- }
189
- return false;
190
- }
191
- };
192
-
193
- // Helper function to parse input into groups separated by 'groupDelim', and
194
- // interprete each group as a key/value pair separated by 'keyValueDelim'.
195
- function parseOptions(input, callback, keyValueDelim, groupDelim) {
196
- var groups = groupDelim ? input.split(groupDelim) : [input];
197
- for (var i in groups) {
198
- if (typeof groups[i] !== "string") {
199
- continue;
200
- }
201
- var kv = groups[i].split(keyValueDelim);
202
- if (kv.length !== 2) {
203
- continue;
204
- }
205
- var k = kv[0];
206
- var v = kv[1];
207
- callback(k, v);
208
- }
209
- }
210
-
211
- function parseCue(input, cue, regionList) {
212
- // Remember the original input if we need to throw an error.
213
- var oInput = input;
214
- // 4.1 WebVTT timestamp
215
- function consumeTimeStamp() {
216
- var ts = parseTimeStamp(input);
217
- if (ts === null) {
218
- throw new ParsingError(ParsingError.Errors.BadTimeStamp,
219
- "Malformed timestamp: " + oInput);
220
- }
221
- // Remove time stamp from input.
222
- input = input.replace(/^[^\sa-zA-Z-]+/, "");
223
- return ts;
224
- }
225
-
226
- // 4.4.2 WebVTT cue settings
227
- function consumeCueSettings(input, cue) {
228
- var settings = new Settings();
229
-
230
- parseOptions(input, function (k, v) {
231
- switch (k) {
232
- case "region":
233
- // Find the last region we parsed with the same region id.
234
- for (var i = regionList.length - 1; i >= 0; i--) {
235
- if (regionList[i].id === v) {
236
- settings.set(k, regionList[i].region);
237
- break;
238
- }
239
- }
240
- break;
241
- case "vertical":
242
- settings.alt(k, v, ["rl", "lr"]);
243
- break;
244
- case "line":
245
- var vals = v.split(","),
246
- vals0 = vals[0];
247
- settings.integer(k, vals0);
248
- settings.percent(k, vals0) ? settings.set("snapToLines", false) : null;
249
- settings.alt(k, vals0, ["auto"]);
250
- if (vals.length === 2) {
251
- settings.alt("lineAlign", vals[1], ["start", "middle", "end"]);
252
- }
253
- break;
254
- case "position":
255
- vals = v.split(",");
256
- settings.percent(k, vals[0]);
257
- if (vals.length === 2) {
258
- settings.alt("positionAlign", vals[1], ["start", "middle", "end"]);
259
- }
260
- break;
261
- case "size":
262
- settings.percent(k, v);
263
- break;
264
- case "align":
265
- settings.alt(k, v, ["start", "middle", "end", "left", "right"]);
266
- break;
267
- }
268
- }, /:/, /\s/);
269
-
270
- //hslee remove these fields.
271
- //Because safari dies here always. And Player doen't use style fields.
272
- // Apply default values for any missing fields.
273
- /*cue.region = settings.get("region", null);
274
- cue.vertical = settings.get("vertical", "");
275
- cue.line = settings.get("line", "auto");
276
- cue.lineAlign = settings.get("lineAlign", "start");
277
- cue.snapToLines = settings.get("snapToLines", true);
278
- cue.size = settings.get("size", 100);
279
- //cue.align = settings.get("align", "middle");
280
- cue.position = settings.get("position", "auto");
281
- cue.positionAlign = settings.get("positionAlign", {
282
- start: "start",
283
- left: "start",
284
- middle: "middle",
285
- end: "end",
286
- right: "end"
287
- }, cue.align
288
- );*/
289
- }
290
-
291
- function skipWhitespace() {
292
- input = input.replace(/^\s+/, "");
293
- }
294
-
295
- // 4.1 WebVTT cue timings.
296
- skipWhitespace();
297
- cue.startTime = consumeTimeStamp(); // (1) collect cue start time
298
- skipWhitespace();
299
- if (input.substr(0, 3) !== "-->") { // (3) next characters must match "-->"
300
- throw new ParsingError(ParsingError.Errors.BadTimeStamp,
301
- "Malformed time stamp (time stamps must be separated by '-->'): " +
302
- oInput);
303
- }
304
- input = input.substr(3);
305
- skipWhitespace();
306
- cue.endTime = consumeTimeStamp(); // (5) collect cue end time
307
-
308
- // 4.1 WebVTT cue settings list.
309
- skipWhitespace();
310
- consumeCueSettings(input, cue);
311
- }
312
-
313
- var ESCAPE = {
314
- "&amp;": "&",
315
- "&lt;": "<",
316
- "&gt;": ">",
317
- "&lrm;": "\u200e",
318
- "&rlm;": "\u200f",
319
- "&nbsp;": "\u00a0"
320
- };
321
-
322
- var TAG_NAME = {
323
- c: "span",
324
- i: "i",
325
- b: "b",
326
- u: "u",
327
- ruby: "ruby",
328
- rt: "rt",
329
- v: "span",
330
- lang: "span"
331
- };
332
-
333
- var TAG_ANNOTATION = {
334
- v: "title",
335
- lang: "lang"
336
- };
337
-
338
- var NEEDS_PARENT = {
339
- rt: "ruby"
340
- };
341
-
342
- // Parse content into a document fragment.
343
- function parseContent(window, input) {
344
- function nextToken() {
345
- // Check for end-of-string.
346
- if (!input) {
347
- return null;
348
- }
349
-
350
- // Consume 'n' characters from the input.
351
- function consume(result) {
352
- input = input.substr(result.length);
353
- return result;
354
- }
355
-
356
- var m = input.match(/^([^<]*)(<[^>]+>?)?/);
357
- // If there is some text before the next tag, return it, otherwise return
358
- // the tag.
359
- return consume(m[1] ? m[1] : m[2]);
360
- }
361
-
362
- // Unescape a string 's'.
363
- function unescape1(e) {
364
- return ESCAPE[e];
365
- }
366
- function unescape(s) {
367
- while ((m = s.match(/&(amp|lt|gt|lrm|rlm|nbsp);/))) {
368
- s = s.replace(m[0], unescape1);
369
- }
370
- return s;
371
- }
372
-
373
- function shouldAdd(current, element) {
374
- return !NEEDS_PARENT[element.localName] ||
375
- NEEDS_PARENT[element.localName] === current.localName;
376
- }
377
-
378
- // Create an element for this tag.
379
- function createElement(type, annotation) {
380
- var tagName = TAG_NAME[type];
381
- if (!tagName) {
382
- return null;
383
- }
384
- var element = window.document.createElement(tagName);
385
- element.localName = tagName;
386
- var name = TAG_ANNOTATION[type];
387
- if (name && annotation) {
388
- element[name] = annotation.trim();
389
- }
390
- return element;
391
- }
392
-
393
- var rootDiv = window.document.createElement("div"),
394
- current = rootDiv,
395
- t,
396
- tagStack = [];
397
-
398
- while ((t = nextToken()) !== null) {
399
- if (t[0] === '<') {
400
- if (t[1] === "/") {
401
- // If the closing tag matches, move back up to the parent node.
402
- if (tagStack.length &&
403
- tagStack[tagStack.length - 1] === t.substr(2).replace(">", "")) {
404
- tagStack.pop();
405
- current = current.parentNode;
406
- }
407
- // Otherwise just ignore the end tag.
408
- continue;
409
- }
410
- var ts = parseTimeStamp(t.substr(1, t.length - 2));
411
- var node;
412
- if (ts) {
413
- // Timestamps are lead nodes as well.
414
- node = window.document.createProcessingInstruction("timestamp", ts);
415
- current.appendChild(node);
416
- continue;
417
- }
418
- var m = t.match(/^<([^.\s/0-9>]+)(\.[^\s\\>]+)?([^>\\]+)?(\\?)>?$/);
419
- // If we can't parse the tag, skip to the next tag.
420
- if (!m) {
421
- continue;
422
- }
423
- // Try to construct an element, and ignore the tag if we couldn't.
424
- node = createElement(m[1], m[3]);
425
- if (!node) {
426
- continue;
427
- }
428
- // Determine if the tag should be added based on the context of where it
429
- // is placed in the cuetext.
430
- if (!shouldAdd(current, node)) {
431
- continue;
432
- }
433
- // Set the class list (as a list of classes, separated by space).
434
- if (m[2]) {
435
- node.className = m[2].substr(1).replace('.', ' ');
436
- }
437
- // Append the node to the current node, and enter the scope of the new
438
- // node.
439
- tagStack.push(m[1]);
440
- current.appendChild(node);
441
- current = node;
442
- continue;
443
- }
444
-
445
- // Text nodes are leaf nodes.
446
- current.appendChild(window.document.createTextNode(unescape(t)));
447
- }
448
-
449
- return rootDiv;
450
- }
451
-
452
- // This is a list of all the Unicode characters that have a strong
453
- // right-to-left category. What this means is that these characters are
454
- // written right-to-left for sure. It was generated by pulling all the strong
455
- // right-to-left characters out of the Unicode data table. That table can
456
- // found at: http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
457
- var strongRTLChars = [0x05BE, 0x05C0, 0x05C3, 0x05C6, 0x05D0, 0x05D1,
458
- 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA,
459
- 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1, 0x05E2, 0x05E3,
460
- 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x05F0, 0x05F1,
461
- 0x05F2, 0x05F3, 0x05F4, 0x0608, 0x060B, 0x060D, 0x061B, 0x061E, 0x061F,
462
- 0x0620, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628,
463
- 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631,
464
- 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063A,
465
- 0x063B, 0x063C, 0x063D, 0x063E, 0x063F, 0x0640, 0x0641, 0x0642, 0x0643,
466
- 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 0x066D, 0x066E,
467
- 0x066F, 0x0671, 0x0672, 0x0673, 0x0674, 0x0675, 0x0676, 0x0677, 0x0678,
468
- 0x0679, 0x067A, 0x067B, 0x067C, 0x067D, 0x067E, 0x067F, 0x0680, 0x0681,
469
- 0x0682, 0x0683, 0x0684, 0x0685, 0x0686, 0x0687, 0x0688, 0x0689, 0x068A,
470
- 0x068B, 0x068C, 0x068D, 0x068E, 0x068F, 0x0690, 0x0691, 0x0692, 0x0693,
471
- 0x0694, 0x0695, 0x0696, 0x0697, 0x0698, 0x0699, 0x069A, 0x069B, 0x069C,
472
- 0x069D, 0x069E, 0x069F, 0x06A0, 0x06A1, 0x06A2, 0x06A3, 0x06A4, 0x06A5,
473
- 0x06A6, 0x06A7, 0x06A8, 0x06A9, 0x06AA, 0x06AB, 0x06AC, 0x06AD, 0x06AE,
474
- 0x06AF, 0x06B0, 0x06B1, 0x06B2, 0x06B3, 0x06B4, 0x06B5, 0x06B6, 0x06B7,
475
- 0x06B8, 0x06B9, 0x06BA, 0x06BB, 0x06BC, 0x06BD, 0x06BE, 0x06BF, 0x06C0,
476
- 0x06C1, 0x06C2, 0x06C3, 0x06C4, 0x06C5, 0x06C6, 0x06C7, 0x06C8, 0x06C9,
477
- 0x06CA, 0x06CB, 0x06CC, 0x06CD, 0x06CE, 0x06CF, 0x06D0, 0x06D1, 0x06D2,
478
- 0x06D3, 0x06D4, 0x06D5, 0x06E5, 0x06E6, 0x06EE, 0x06EF, 0x06FA, 0x06FB,
479
- 0x06FC, 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, 0x0703, 0x0704,
480
- 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, 0x070A, 0x070B, 0x070C, 0x070D,
481
- 0x070F, 0x0710, 0x0712, 0x0713, 0x0714, 0x0715, 0x0716, 0x0717, 0x0718,
482
- 0x0719, 0x071A, 0x071B, 0x071C, 0x071D, 0x071E, 0x071F, 0x0720, 0x0721,
483
- 0x0722, 0x0723, 0x0724, 0x0725, 0x0726, 0x0727, 0x0728, 0x0729, 0x072A,
484
- 0x072B, 0x072C, 0x072D, 0x072E, 0x072F, 0x074D, 0x074E, 0x074F, 0x0750,
485
- 0x0751, 0x0752, 0x0753, 0x0754, 0x0755, 0x0756, 0x0757, 0x0758, 0x0759,
486
- 0x075A, 0x075B, 0x075C, 0x075D, 0x075E, 0x075F, 0x0760, 0x0761, 0x0762,
487
- 0x0763, 0x0764, 0x0765, 0x0766, 0x0767, 0x0768, 0x0769, 0x076A, 0x076B,
488
- 0x076C, 0x076D, 0x076E, 0x076F, 0x0770, 0x0771, 0x0772, 0x0773, 0x0774,
489
- 0x0775, 0x0776, 0x0777, 0x0778, 0x0779, 0x077A, 0x077B, 0x077C, 0x077D,
490
- 0x077E, 0x077F, 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0786,
491
- 0x0787, 0x0788, 0x0789, 0x078A, 0x078B, 0x078C, 0x078D, 0x078E, 0x078F,
492
- 0x0790, 0x0791, 0x0792, 0x0793, 0x0794, 0x0795, 0x0796, 0x0797, 0x0798,
493
- 0x0799, 0x079A, 0x079B, 0x079C, 0x079D, 0x079E, 0x079F, 0x07A0, 0x07A1,
494
- 0x07A2, 0x07A3, 0x07A4, 0x07A5, 0x07B1, 0x07C0, 0x07C1, 0x07C2, 0x07C3,
495
- 0x07C4, 0x07C5, 0x07C6, 0x07C7, 0x07C8, 0x07C9, 0x07CA, 0x07CB, 0x07CC,
496
- 0x07CD, 0x07CE, 0x07CF, 0x07D0, 0x07D1, 0x07D2, 0x07D3, 0x07D4, 0x07D5,
497
- 0x07D6, 0x07D7, 0x07D8, 0x07D9, 0x07DA, 0x07DB, 0x07DC, 0x07DD, 0x07DE,
498
- 0x07DF, 0x07E0, 0x07E1, 0x07E2, 0x07E3, 0x07E4, 0x07E5, 0x07E6, 0x07E7,
499
- 0x07E8, 0x07E9, 0x07EA, 0x07F4, 0x07F5, 0x07FA, 0x0800, 0x0801, 0x0802,
500
- 0x0803, 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809, 0x080A, 0x080B,
501
- 0x080C, 0x080D, 0x080E, 0x080F, 0x0810, 0x0811, 0x0812, 0x0813, 0x0814,
502
- 0x0815, 0x081A, 0x0824, 0x0828, 0x0830, 0x0831, 0x0832, 0x0833, 0x0834,
503
- 0x0835, 0x0836, 0x0837, 0x0838, 0x0839, 0x083A, 0x083B, 0x083C, 0x083D,
504
- 0x083E, 0x0840, 0x0841, 0x0842, 0x0843, 0x0844, 0x0845, 0x0846, 0x0847,
505
- 0x0848, 0x0849, 0x084A, 0x084B, 0x084C, 0x084D, 0x084E, 0x084F, 0x0850,
506
- 0x0851, 0x0852, 0x0853, 0x0854, 0x0855, 0x0856, 0x0857, 0x0858, 0x085E,
507
- 0x08A0, 0x08A2, 0x08A3, 0x08A4, 0x08A5, 0x08A6, 0x08A7, 0x08A8, 0x08A9,
508
- 0x08AA, 0x08AB, 0x08AC, 0x200F, 0xFB1D, 0xFB1F, 0xFB20, 0xFB21, 0xFB22,
509
- 0xFB23, 0xFB24, 0xFB25, 0xFB26, 0xFB27, 0xFB28, 0xFB2A, 0xFB2B, 0xFB2C,
510
- 0xFB2D, 0xFB2E, 0xFB2F, 0xFB30, 0xFB31, 0xFB32, 0xFB33, 0xFB34, 0xFB35,
511
- 0xFB36, 0xFB38, 0xFB39, 0xFB3A, 0xFB3B, 0xFB3C, 0xFB3E, 0xFB40, 0xFB41,
512
- 0xFB43, 0xFB44, 0xFB46, 0xFB47, 0xFB48, 0xFB49, 0xFB4A, 0xFB4B, 0xFB4C,
513
- 0xFB4D, 0xFB4E, 0xFB4F, 0xFB50, 0xFB51, 0xFB52, 0xFB53, 0xFB54, 0xFB55,
514
- 0xFB56, 0xFB57, 0xFB58, 0xFB59, 0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D, 0xFB5E,
515
- 0xFB5F, 0xFB60, 0xFB61, 0xFB62, 0xFB63, 0xFB64, 0xFB65, 0xFB66, 0xFB67,
516
- 0xFB68, 0xFB69, 0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D, 0xFB6E, 0xFB6F, 0xFB70,
517
- 0xFB71, 0xFB72, 0xFB73, 0xFB74, 0xFB75, 0xFB76, 0xFB77, 0xFB78, 0xFB79,
518
- 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D, 0xFB7E, 0xFB7F, 0xFB80, 0xFB81, 0xFB82,
519
- 0xFB83, 0xFB84, 0xFB85, 0xFB86, 0xFB87, 0xFB88, 0xFB89, 0xFB8A, 0xFB8B,
520
- 0xFB8C, 0xFB8D, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, 0xFB92, 0xFB93, 0xFB94,
521
- 0xFB95, 0xFB96, 0xFB97, 0xFB98, 0xFB99, 0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D,
522
- 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3, 0xFBA4, 0xFBA5, 0xFBA6,
523
- 0xFBA7, 0xFBA8, 0xFBA9, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD, 0xFBAE, 0xFBAF,
524
- 0xFBB0, 0xFBB1, 0xFBB2, 0xFBB3, 0xFBB4, 0xFBB5, 0xFBB6, 0xFBB7, 0xFBB8,
525
- 0xFBB9, 0xFBBA, 0xFBBB, 0xFBBC, 0xFBBD, 0xFBBE, 0xFBBF, 0xFBC0, 0xFBC1,
526
- 0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6, 0xFBD7, 0xFBD8, 0xFBD9, 0xFBDA, 0xFBDB,
527
- 0xFBDC, 0xFBDD, 0xFBDE, 0xFBDF, 0xFBE0, 0xFBE1, 0xFBE2, 0xFBE3, 0xFBE4,
528
- 0xFBE5, 0xFBE6, 0xFBE7, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEB, 0xFBEC, 0xFBED,
529
- 0xFBEE, 0xFBEF, 0xFBF0, 0xFBF1, 0xFBF2, 0xFBF3, 0xFBF4, 0xFBF5, 0xFBF6,
530
- 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF,
531
- 0xFC00, 0xFC01, 0xFC02, 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFC08,
532
- 0xFC09, 0xFC0A, 0xFC0B, 0xFC0C, 0xFC0D, 0xFC0E, 0xFC0F, 0xFC10, 0xFC11,
533
- 0xFC12, 0xFC13, 0xFC14, 0xFC15, 0xFC16, 0xFC17, 0xFC18, 0xFC19, 0xFC1A,
534
- 0xFC1B, 0xFC1C, 0xFC1D, 0xFC1E, 0xFC1F, 0xFC20, 0xFC21, 0xFC22, 0xFC23,
535
- 0xFC24, 0xFC25, 0xFC26, 0xFC27, 0xFC28, 0xFC29, 0xFC2A, 0xFC2B, 0xFC2C,
536
- 0xFC2D, 0xFC2E, 0xFC2F, 0xFC30, 0xFC31, 0xFC32, 0xFC33, 0xFC34, 0xFC35,
537
- 0xFC36, 0xFC37, 0xFC38, 0xFC39, 0xFC3A, 0xFC3B, 0xFC3C, 0xFC3D, 0xFC3E,
538
- 0xFC3F, 0xFC40, 0xFC41, 0xFC42, 0xFC43, 0xFC44, 0xFC45, 0xFC46, 0xFC47,
539
- 0xFC48, 0xFC49, 0xFC4A, 0xFC4B, 0xFC4C, 0xFC4D, 0xFC4E, 0xFC4F, 0xFC50,
540
- 0xFC51, 0xFC52, 0xFC53, 0xFC54, 0xFC55, 0xFC56, 0xFC57, 0xFC58, 0xFC59,
541
- 0xFC5A, 0xFC5B, 0xFC5C, 0xFC5D, 0xFC5E, 0xFC5F, 0xFC60, 0xFC61, 0xFC62,
542
- 0xFC63, 0xFC64, 0xFC65, 0xFC66, 0xFC67, 0xFC68, 0xFC69, 0xFC6A, 0xFC6B,
543
- 0xFC6C, 0xFC6D, 0xFC6E, 0xFC6F, 0xFC70, 0xFC71, 0xFC72, 0xFC73, 0xFC74,
544
- 0xFC75, 0xFC76, 0xFC77, 0xFC78, 0xFC79, 0xFC7A, 0xFC7B, 0xFC7C, 0xFC7D,
545
- 0xFC7E, 0xFC7F, 0xFC80, 0xFC81, 0xFC82, 0xFC83, 0xFC84, 0xFC85, 0xFC86,
546
- 0xFC87, 0xFC88, 0xFC89, 0xFC8A, 0xFC8B, 0xFC8C, 0xFC8D, 0xFC8E, 0xFC8F,
547
- 0xFC90, 0xFC91, 0xFC92, 0xFC93, 0xFC94, 0xFC95, 0xFC96, 0xFC97, 0xFC98,
548
- 0xFC99, 0xFC9A, 0xFC9B, 0xFC9C, 0xFC9D, 0xFC9E, 0xFC9F, 0xFCA0, 0xFCA1,
549
- 0xFCA2, 0xFCA3, 0xFCA4, 0xFCA5, 0xFCA6, 0xFCA7, 0xFCA8, 0xFCA9, 0xFCAA,
550
- 0xFCAB, 0xFCAC, 0xFCAD, 0xFCAE, 0xFCAF, 0xFCB0, 0xFCB1, 0xFCB2, 0xFCB3,
551
- 0xFCB4, 0xFCB5, 0xFCB6, 0xFCB7, 0xFCB8, 0xFCB9, 0xFCBA, 0xFCBB, 0xFCBC,
552
- 0xFCBD, 0xFCBE, 0xFCBF, 0xFCC0, 0xFCC1, 0xFCC2, 0xFCC3, 0xFCC4, 0xFCC5,
553
- 0xFCC6, 0xFCC7, 0xFCC8, 0xFCC9, 0xFCCA, 0xFCCB, 0xFCCC, 0xFCCD, 0xFCCE,
554
- 0xFCCF, 0xFCD0, 0xFCD1, 0xFCD2, 0xFCD3, 0xFCD4, 0xFCD5, 0xFCD6, 0xFCD7,
555
- 0xFCD8, 0xFCD9, 0xFCDA, 0xFCDB, 0xFCDC, 0xFCDD, 0xFCDE, 0xFCDF, 0xFCE0,
556
- 0xFCE1, 0xFCE2, 0xFCE3, 0xFCE4, 0xFCE5, 0xFCE6, 0xFCE7, 0xFCE8, 0xFCE9,
557
- 0xFCEA, 0xFCEB, 0xFCEC, 0xFCED, 0xFCEE, 0xFCEF, 0xFCF0, 0xFCF1, 0xFCF2,
558
- 0xFCF3, 0xFCF4, 0xFCF5, 0xFCF6, 0xFCF7, 0xFCF8, 0xFCF9, 0xFCFA, 0xFCFB,
559
- 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, 0xFD00, 0xFD01, 0xFD02, 0xFD03, 0xFD04,
560
- 0xFD05, 0xFD06, 0xFD07, 0xFD08, 0xFD09, 0xFD0A, 0xFD0B, 0xFD0C, 0xFD0D,
561
- 0xFD0E, 0xFD0F, 0xFD10, 0xFD11, 0xFD12, 0xFD13, 0xFD14, 0xFD15, 0xFD16,
562
- 0xFD17, 0xFD18, 0xFD19, 0xFD1A, 0xFD1B, 0xFD1C, 0xFD1D, 0xFD1E, 0xFD1F,
563
- 0xFD20, 0xFD21, 0xFD22, 0xFD23, 0xFD24, 0xFD25, 0xFD26, 0xFD27, 0xFD28,
564
- 0xFD29, 0xFD2A, 0xFD2B, 0xFD2C, 0xFD2D, 0xFD2E, 0xFD2F, 0xFD30, 0xFD31,
565
- 0xFD32, 0xFD33, 0xFD34, 0xFD35, 0xFD36, 0xFD37, 0xFD38, 0xFD39, 0xFD3A,
566
- 0xFD3B, 0xFD3C, 0xFD3D, 0xFD50, 0xFD51, 0xFD52, 0xFD53, 0xFD54, 0xFD55,
567
- 0xFD56, 0xFD57, 0xFD58, 0xFD59, 0xFD5A, 0xFD5B, 0xFD5C, 0xFD5D, 0xFD5E,
568
- 0xFD5F, 0xFD60, 0xFD61, 0xFD62, 0xFD63, 0xFD64, 0xFD65, 0xFD66, 0xFD67,
569
- 0xFD68, 0xFD69, 0xFD6A, 0xFD6B, 0xFD6C, 0xFD6D, 0xFD6E, 0xFD6F, 0xFD70,
570
- 0xFD71, 0xFD72, 0xFD73, 0xFD74, 0xFD75, 0xFD76, 0xFD77, 0xFD78, 0xFD79,
571
- 0xFD7A, 0xFD7B, 0xFD7C, 0xFD7D, 0xFD7E, 0xFD7F, 0xFD80, 0xFD81, 0xFD82,
572
- 0xFD83, 0xFD84, 0xFD85, 0xFD86, 0xFD87, 0xFD88, 0xFD89, 0xFD8A, 0xFD8B,
573
- 0xFD8C, 0xFD8D, 0xFD8E, 0xFD8F, 0xFD92, 0xFD93, 0xFD94, 0xFD95, 0xFD96,
574
- 0xFD97, 0xFD98, 0xFD99, 0xFD9A, 0xFD9B, 0xFD9C, 0xFD9D, 0xFD9E, 0xFD9F,
575
- 0xFDA0, 0xFDA1, 0xFDA2, 0xFDA3, 0xFDA4, 0xFDA5, 0xFDA6, 0xFDA7, 0xFDA8,
576
- 0xFDA9, 0xFDAA, 0xFDAB, 0xFDAC, 0xFDAD, 0xFDAE, 0xFDAF, 0xFDB0, 0xFDB1,
577
- 0xFDB2, 0xFDB3, 0xFDB4, 0xFDB5, 0xFDB6, 0xFDB7, 0xFDB8, 0xFDB9, 0xFDBA,
578
- 0xFDBB, 0xFDBC, 0xFDBD, 0xFDBE, 0xFDBF, 0xFDC0, 0xFDC1, 0xFDC2, 0xFDC3,
579
- 0xFDC4, 0xFDC5, 0xFDC6, 0xFDC7, 0xFDF0, 0xFDF1, 0xFDF2, 0xFDF3, 0xFDF4,
580
- 0xFDF5, 0xFDF6, 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, 0xFDFB, 0xFDFC, 0xFE70,
581
- 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE76, 0xFE77, 0xFE78, 0xFE79, 0xFE7A,
582
- 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F, 0xFE80, 0xFE81, 0xFE82, 0xFE83,
583
- 0xFE84, 0xFE85, 0xFE86, 0xFE87, 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C,
584
- 0xFE8D, 0xFE8E, 0xFE8F, 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95,
585
- 0xFE96, 0xFE97, 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E,
586
- 0xFE9F, 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7,
587
- 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF, 0xFEB0,
588
- 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, 0xFEB9,
589
- 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0, 0xFEC1, 0xFEC2,
590
- 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, 0xFEC9, 0xFECA, 0xFECB,
591
- 0xFECC, 0xFECD, 0xFECE, 0xFECF, 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4,
592
- 0xFED5, 0xFED6, 0xFED7, 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD,
593
- 0xFEDE, 0xFEDF, 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6,
594
- 0xFEE7, 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF,
595
- 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, 0xFEF8,
596
- 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0x10800, 0x10801, 0x10802, 0x10803,
597
- 0x10804, 0x10805, 0x10808, 0x1080A, 0x1080B, 0x1080C, 0x1080D, 0x1080E,
598
- 0x1080F, 0x10810, 0x10811, 0x10812, 0x10813, 0x10814, 0x10815, 0x10816,
599
- 0x10817, 0x10818, 0x10819, 0x1081A, 0x1081B, 0x1081C, 0x1081D, 0x1081E,
600
- 0x1081F, 0x10820, 0x10821, 0x10822, 0x10823, 0x10824, 0x10825, 0x10826,
601
- 0x10827, 0x10828, 0x10829, 0x1082A, 0x1082B, 0x1082C, 0x1082D, 0x1082E,
602
- 0x1082F, 0x10830, 0x10831, 0x10832, 0x10833, 0x10834, 0x10835, 0x10837,
603
- 0x10838, 0x1083C, 0x1083F, 0x10840, 0x10841, 0x10842, 0x10843, 0x10844,
604
- 0x10845, 0x10846, 0x10847, 0x10848, 0x10849, 0x1084A, 0x1084B, 0x1084C,
605
- 0x1084D, 0x1084E, 0x1084F, 0x10850, 0x10851, 0x10852, 0x10853, 0x10854,
606
- 0x10855, 0x10857, 0x10858, 0x10859, 0x1085A, 0x1085B, 0x1085C, 0x1085D,
607
- 0x1085E, 0x1085F, 0x10900, 0x10901, 0x10902, 0x10903, 0x10904, 0x10905,
608
- 0x10906, 0x10907, 0x10908, 0x10909, 0x1090A, 0x1090B, 0x1090C, 0x1090D,
609
- 0x1090E, 0x1090F, 0x10910, 0x10911, 0x10912, 0x10913, 0x10914, 0x10915,
610
- 0x10916, 0x10917, 0x10918, 0x10919, 0x1091A, 0x1091B, 0x10920, 0x10921,
611
- 0x10922, 0x10923, 0x10924, 0x10925, 0x10926, 0x10927, 0x10928, 0x10929,
612
- 0x1092A, 0x1092B, 0x1092C, 0x1092D, 0x1092E, 0x1092F, 0x10930, 0x10931,
613
- 0x10932, 0x10933, 0x10934, 0x10935, 0x10936, 0x10937, 0x10938, 0x10939,
614
- 0x1093F, 0x10980, 0x10981, 0x10982, 0x10983, 0x10984, 0x10985, 0x10986,
615
- 0x10987, 0x10988, 0x10989, 0x1098A, 0x1098B, 0x1098C, 0x1098D, 0x1098E,
616
- 0x1098F, 0x10990, 0x10991, 0x10992, 0x10993, 0x10994, 0x10995, 0x10996,
617
- 0x10997, 0x10998, 0x10999, 0x1099A, 0x1099B, 0x1099C, 0x1099D, 0x1099E,
618
- 0x1099F, 0x109A0, 0x109A1, 0x109A2, 0x109A3, 0x109A4, 0x109A5, 0x109A6,
619
- 0x109A7, 0x109A8, 0x109A9, 0x109AA, 0x109AB, 0x109AC, 0x109AD, 0x109AE,
620
- 0x109AF, 0x109B0, 0x109B1, 0x109B2, 0x109B3, 0x109B4, 0x109B5, 0x109B6,
621
- 0x109B7, 0x109BE, 0x109BF, 0x10A00, 0x10A10, 0x10A11, 0x10A12, 0x10A13,
622
- 0x10A15, 0x10A16, 0x10A17, 0x10A19, 0x10A1A, 0x10A1B, 0x10A1C, 0x10A1D,
623
- 0x10A1E, 0x10A1F, 0x10A20, 0x10A21, 0x10A22, 0x10A23, 0x10A24, 0x10A25,
624
- 0x10A26, 0x10A27, 0x10A28, 0x10A29, 0x10A2A, 0x10A2B, 0x10A2C, 0x10A2D,
625
- 0x10A2E, 0x10A2F, 0x10A30, 0x10A31, 0x10A32, 0x10A33, 0x10A40, 0x10A41,
626
- 0x10A42, 0x10A43, 0x10A44, 0x10A45, 0x10A46, 0x10A47, 0x10A50, 0x10A51,
627
- 0x10A52, 0x10A53, 0x10A54, 0x10A55, 0x10A56, 0x10A57, 0x10A58, 0x10A60,
628
- 0x10A61, 0x10A62, 0x10A63, 0x10A64, 0x10A65, 0x10A66, 0x10A67, 0x10A68,
629
- 0x10A69, 0x10A6A, 0x10A6B, 0x10A6C, 0x10A6D, 0x10A6E, 0x10A6F, 0x10A70,
630
- 0x10A71, 0x10A72, 0x10A73, 0x10A74, 0x10A75, 0x10A76, 0x10A77, 0x10A78,
631
- 0x10A79, 0x10A7A, 0x10A7B, 0x10A7C, 0x10A7D, 0x10A7E, 0x10A7F, 0x10B00,
632
- 0x10B01, 0x10B02, 0x10B03, 0x10B04, 0x10B05, 0x10B06, 0x10B07, 0x10B08,
633
- 0x10B09, 0x10B0A, 0x10B0B, 0x10B0C, 0x10B0D, 0x10B0E, 0x10B0F, 0x10B10,
634
- 0x10B11, 0x10B12, 0x10B13, 0x10B14, 0x10B15, 0x10B16, 0x10B17, 0x10B18,
635
- 0x10B19, 0x10B1A, 0x10B1B, 0x10B1C, 0x10B1D, 0x10B1E, 0x10B1F, 0x10B20,
636
- 0x10B21, 0x10B22, 0x10B23, 0x10B24, 0x10B25, 0x10B26, 0x10B27, 0x10B28,
637
- 0x10B29, 0x10B2A, 0x10B2B, 0x10B2C, 0x10B2D, 0x10B2E, 0x10B2F, 0x10B30,
638
- 0x10B31, 0x10B32, 0x10B33, 0x10B34, 0x10B35, 0x10B40, 0x10B41, 0x10B42,
639
- 0x10B43, 0x10B44, 0x10B45, 0x10B46, 0x10B47, 0x10B48, 0x10B49, 0x10B4A,
640
- 0x10B4B, 0x10B4C, 0x10B4D, 0x10B4E, 0x10B4F, 0x10B50, 0x10B51, 0x10B52,
641
- 0x10B53, 0x10B54, 0x10B55, 0x10B58, 0x10B59, 0x10B5A, 0x10B5B, 0x10B5C,
642
- 0x10B5D, 0x10B5E, 0x10B5F, 0x10B60, 0x10B61, 0x10B62, 0x10B63, 0x10B64,
643
- 0x10B65, 0x10B66, 0x10B67, 0x10B68, 0x10B69, 0x10B6A, 0x10B6B, 0x10B6C,
644
- 0x10B6D, 0x10B6E, 0x10B6F, 0x10B70, 0x10B71, 0x10B72, 0x10B78, 0x10B79,
645
- 0x10B7A, 0x10B7B, 0x10B7C, 0x10B7D, 0x10B7E, 0x10B7F, 0x10C00, 0x10C01,
646
- 0x10C02, 0x10C03, 0x10C04, 0x10C05, 0x10C06, 0x10C07, 0x10C08, 0x10C09,
647
- 0x10C0A, 0x10C0B, 0x10C0C, 0x10C0D, 0x10C0E, 0x10C0F, 0x10C10, 0x10C11,
648
- 0x10C12, 0x10C13, 0x10C14, 0x10C15, 0x10C16, 0x10C17, 0x10C18, 0x10C19,
649
- 0x10C1A, 0x10C1B, 0x10C1C, 0x10C1D, 0x10C1E, 0x10C1F, 0x10C20, 0x10C21,
650
- 0x10C22, 0x10C23, 0x10C24, 0x10C25, 0x10C26, 0x10C27, 0x10C28, 0x10C29,
651
- 0x10C2A, 0x10C2B, 0x10C2C, 0x10C2D, 0x10C2E, 0x10C2F, 0x10C30, 0x10C31,
652
- 0x10C32, 0x10C33, 0x10C34, 0x10C35, 0x10C36, 0x10C37, 0x10C38, 0x10C39,
653
- 0x10C3A, 0x10C3B, 0x10C3C, 0x10C3D, 0x10C3E, 0x10C3F, 0x10C40, 0x10C41,
654
- 0x10C42, 0x10C43, 0x10C44, 0x10C45, 0x10C46, 0x10C47, 0x10C48, 0x1EE00,
655
- 0x1EE01, 0x1EE02, 0x1EE03, 0x1EE05, 0x1EE06, 0x1EE07, 0x1EE08, 0x1EE09,
656
- 0x1EE0A, 0x1EE0B, 0x1EE0C, 0x1EE0D, 0x1EE0E, 0x1EE0F, 0x1EE10, 0x1EE11,
657
- 0x1EE12, 0x1EE13, 0x1EE14, 0x1EE15, 0x1EE16, 0x1EE17, 0x1EE18, 0x1EE19,
658
- 0x1EE1A, 0x1EE1B, 0x1EE1C, 0x1EE1D, 0x1EE1E, 0x1EE1F, 0x1EE21, 0x1EE22,
659
- 0x1EE24, 0x1EE27, 0x1EE29, 0x1EE2A, 0x1EE2B, 0x1EE2C, 0x1EE2D, 0x1EE2E,
660
- 0x1EE2F, 0x1EE30, 0x1EE31, 0x1EE32, 0x1EE34, 0x1EE35, 0x1EE36, 0x1EE37,
661
- 0x1EE39, 0x1EE3B, 0x1EE42, 0x1EE47, 0x1EE49, 0x1EE4B, 0x1EE4D, 0x1EE4E,
662
- 0x1EE4F, 0x1EE51, 0x1EE52, 0x1EE54, 0x1EE57, 0x1EE59, 0x1EE5B, 0x1EE5D,
663
- 0x1EE5F, 0x1EE61, 0x1EE62, 0x1EE64, 0x1EE67, 0x1EE68, 0x1EE69, 0x1EE6A,
664
- 0x1EE6C, 0x1EE6D, 0x1EE6E, 0x1EE6F, 0x1EE70, 0x1EE71, 0x1EE72, 0x1EE74,
665
- 0x1EE75, 0x1EE76, 0x1EE77, 0x1EE79, 0x1EE7A, 0x1EE7B, 0x1EE7C, 0x1EE7E,
666
- 0x1EE80, 0x1EE81, 0x1EE82, 0x1EE83, 0x1EE84, 0x1EE85, 0x1EE86, 0x1EE87,
667
- 0x1EE88, 0x1EE89, 0x1EE8B, 0x1EE8C, 0x1EE8D, 0x1EE8E, 0x1EE8F, 0x1EE90,
668
- 0x1EE91, 0x1EE92, 0x1EE93, 0x1EE94, 0x1EE95, 0x1EE96, 0x1EE97, 0x1EE98,
669
- 0x1EE99, 0x1EE9A, 0x1EE9B, 0x1EEA1, 0x1EEA2, 0x1EEA3, 0x1EEA5, 0x1EEA6,
670
- 0x1EEA7, 0x1EEA8, 0x1EEA9, 0x1EEAB, 0x1EEAC, 0x1EEAD, 0x1EEAE, 0x1EEAF,
671
- 0x1EEB0, 0x1EEB1, 0x1EEB2, 0x1EEB3, 0x1EEB4, 0x1EEB5, 0x1EEB6, 0x1EEB7,
672
- 0x1EEB8, 0x1EEB9, 0x1EEBA, 0x1EEBB, 0x10FFFD];
673
-
674
- function determineBidi(cueDiv) {
675
- var nodeStack = [],
676
- text = "",
677
- charCode;
678
-
679
- if (!cueDiv || !cueDiv.childNodes) {
680
- return "ltr";
681
- }
682
-
683
- function pushNodes(nodeStack, node) {
684
- for (var i = node.childNodes.length - 1; i >= 0; i--) {
685
- nodeStack.push(node.childNodes[i]);
686
- }
687
- }
688
-
689
- function nextTextNode(nodeStack) {
690
- if (!nodeStack || !nodeStack.length) {
691
- return null;
692
- }
693
-
694
- var node = nodeStack.pop(),
695
- text = node.textContent || node.innerText;
696
- if (text) {
697
- // TODO: This should match all unicode type B characters (paragraph
698
- // separator characters). See issue #115.
699
- var m = text.match(/^.*(\n|\r)/);
700
- if (m) {
701
- nodeStack.length = 0;
702
- return m[0];
703
- }
704
- return text;
705
- }
706
- if (node.tagName === "ruby") {
707
- return nextTextNode(nodeStack);
708
- }
709
- if (node.childNodes) {
710
- pushNodes(nodeStack, node);
711
- return nextTextNode(nodeStack);
712
- }
713
- }
714
-
715
- pushNodes(nodeStack, cueDiv);
716
- while ((text = nextTextNode(nodeStack))) {
717
- for (var i = 0; i < text.length; i++) {
718
- charCode = text.charCodeAt(i);
719
- for (var j = 0; j < strongRTLChars.length; j++) {
720
- if (strongRTLChars[j] === charCode) {
721
- return "rtl";
722
- }
723
- }
724
- }
725
- }
726
- return "ltr";
727
- }
728
-
729
- function computeLinePos(cue) {
730
- if (typeof cue.line === "number" &&
731
- (cue.snapToLines || (cue.line >= 0 && cue.line <= 100))) {
732
- return cue.line;
733
- }
734
- if (!cue.track || !cue.track.textTrackList ||
735
- !cue.track.textTrackList.mediaElement) {
736
- return -1;
737
- }
738
- var track = cue.track,
739
- trackList = track.textTrackList,
740
- count = 0;
741
- for (var i = 0; i < trackList.length && trackList[i] !== track; i++) {
742
- if (trackList[i].mode === "showing") {
743
- count++;
744
- }
745
- }
746
- return ++count * -1;
747
- }
748
-
749
- function StyleBox() {
750
- }
751
-
752
- // Apply styles to a div. If there is no div passed then it defaults to the
753
- // div on 'this'.
754
- StyleBox.prototype.applyStyles = function(styles, div) {
755
- div = div || this.div;
756
- for (var prop in styles) {
757
- if (styles.hasOwnProperty(prop)) {
758
- div.style[prop] = styles[prop];
759
- }
760
- }
761
- };
762
-
763
- StyleBox.prototype.formatStyle = function(val, unit) {
764
- return val === 0 ? 0 : val + unit;
765
- };
766
-
767
- // Constructs the computed display state of the cue (a div). Places the div
768
- // into the overlay which should be a block level element (usually a div).
769
- function CueStyleBox(window, cue, styleOptions) {
770
- var isIE8 = (typeof navigator !== "undefined") &&
771
- (/MSIE\s8\.0/).test(navigator.userAgent);
772
- var color = "rgba(255, 255, 255, 1)";
773
- var backgroundColor = "rgba(0, 0, 0, 0.8)";
774
- var textShadow = "";
775
-
776
- if(typeof WebVTTSet !== "undefined") {
777
- color = WebVTTSet.fontSet;
778
- backgroundColor = WebVTTSet.backgroundSet;
779
- textShadow = WebVTTSet.edgeSet;
780
- }
781
-
782
- if (isIE8) {
783
- color = "rgb(255, 255, 255)";
784
- backgroundColor = "rgb(0, 0, 0)";
785
- }
786
-
787
- StyleBox.call(this);
788
- this.cue = cue;
789
-
790
- // Parse our cue's text into a DOM tree rooted at 'cueDiv'. This div will
791
- // have inline positioning and will function as the cue background box.
792
- this.cueDiv = parseContent(window, cue.text);
793
- var styles = {
794
- color: color,
795
- backgroundColor: backgroundColor,
796
- textShadow: textShadow,
797
- position: "relative",
798
- left: 0,
799
- right: 0,
800
- top: 0,
801
- bottom: 0,
802
- display: "inline"
803
- };
804
-
805
- if (!isIE8) {
806
- styles.writingMode = cue.vertical === "" ? "horizontal-tb"
807
- : cue.vertical === "lr" ? "vertical-lr"
808
- : "vertical-rl";
809
- styles.unicodeBidi = "plaintext";
810
- }
811
- this.applyStyles(styles, this.cueDiv);
812
-
813
- // Create an absolutely positioned div that will be used to position the cue
814
- // div. Note, all WebVTT cue-setting alignments are equivalent to the CSS
815
- // mirrors of them except "middle" which is "center" in CSS.
816
- this.div = window.document.createElement("div");
817
- styles = {
818
- textAlign: cue.align === "middle" ? "center" : cue.align,
819
- font: styleOptions.font,
820
- whiteSpace: "pre-line",
821
- position: "absolute"
822
- };
823
-
824
- if (!isIE8) {
825
- styles.direction = determineBidi(this.cueDiv);
826
- styles.writingMode = cue.vertical === "" ? "horizontal-tb"
827
- : cue.vertical === "lr" ? "vertical-lr"
828
- : "vertical-rl".
829
- stylesunicodeBidi = "plaintext";
830
- }
831
-
832
- this.applyStyles(styles);
833
-
834
- this.div.appendChild(this.cueDiv);
835
-
836
- // Calculate the distance from the reference edge of the viewport to the text
837
- // position of the cue box. The reference edge will be resolved later when
838
- // the box orientation styles are applied.
839
- var textPos = 0;
840
- switch (cue.positionAlign) {
841
- case "start":
842
- textPos = cue.position;
843
- break;
844
- case "middle":
845
- textPos = cue.position - (cue.size / 2);
846
- break;
847
- case "end":
848
- textPos = cue.position - cue.size;
849
- break;
850
- }
851
-
852
- // Horizontal box orientation; textPos is the distance from the left edge of the
853
- // area to the left edge of the box and cue.size is the distance extending to
854
- // the right from there.
855
- if (cue.vertical === "") {
856
- this.applyStyles({
857
- left: this.formatStyle(textPos, "%"),
858
- width: this.formatStyle(cue.size, "%")
859
- });
860
- // Vertical box orientation; textPos is the distance from the top edge of the
861
- // area to the top edge of the box and cue.size is the height extending
862
- // downwards from there.
863
- } else {
864
- this.applyStyles({
865
- top: this.formatStyle(textPos, "%"),
866
- height: this.formatStyle(cue.size, "%")
867
- });
868
- }
869
-
870
- this.move = function(box) {
871
- this.applyStyles({
872
- top: this.formatStyle(box.top, "px"),
873
- bottom: this.formatStyle(box.bottom, "px"),
874
- left: this.formatStyle(box.left, "px"),
875
- right: this.formatStyle(box.right, "px"),
876
- height: this.formatStyle(box.height, "px"),
877
- width: this.formatStyle(box.width, "px")
878
- });
879
- };
880
- }
881
- CueStyleBox.prototype = _objCreate(StyleBox.prototype);
882
- CueStyleBox.prototype.constructor = CueStyleBox;
883
-
884
- // Represents the co-ordinates of an Element in a way that we can easily
885
- // compute things with such as if it overlaps or intersects with another Element.
886
- // Can initialize it with either a StyleBox or another BoxPosition.
887
- function BoxPosition(obj) {
888
- var isIE8 = (typeof navigator !== "undefined") &&
889
- (/MSIE\s8\.0/).test(navigator.userAgent);
890
-
891
- // Either a BoxPosition was passed in and we need to copy it, or a StyleBox
892
- // was passed in and we need to copy the results of 'getBoundingClientRect'
893
- // as the object returned is readonly. All co-ordinate values are in reference
894
- // to the viewport origin (top left).
895
- var lh, height, width, top;
896
- if (obj.div) {
897
- height = obj.div.offsetHeight;
898
- width = obj.div.offsetWidth;
899
- top = obj.div.offsetTop;
900
-
901
- var rects = (rects = obj.div.childNodes) && (rects = rects[0]) &&
902
- rects.getClientRects && rects.getClientRects();
903
- obj = obj.div.getBoundingClientRect();
904
- // In certain cases the outter div will be slightly larger then the sum of
905
- // the inner div's lines. This could be due to bold text, etc, on some platforms.
906
- // In this case we should get the average line height and use that. This will
907
- // result in the desired behaviour.
908
- lh = rects ? Math.max((rects[0] && rects[0].height) || 0, obj.height / rects.length)
909
- : 0;
910
-
911
- }
912
- this.left = obj.left;
913
- this.right = obj.right;
914
- this.top = obj.top || top;
915
- this.height = obj.height || height;
916
- this.bottom = obj.bottom || (top + (obj.height || height));
917
- this.width = obj.width || width;
918
- this.lineHeight = lh !== undefined ? lh : obj.lineHeight;
919
-
920
- if (isIE8 && !this.lineHeight) {
921
- this.lineHeight = 13;
922
- }
923
- }
924
-
925
- // Move the box along a particular axis. Optionally pass in an amount to move
926
- // the box. If no amount is passed then the default is the line height of the
927
- // box.
928
- BoxPosition.prototype.move = function(axis, toMove) {
929
- toMove = toMove !== undefined ? toMove : this.lineHeight;
930
- switch (axis) {
931
- case "+x":
932
- this.left += toMove;
933
- this.right += toMove;
934
- break;
935
- case "-x":
936
- this.left -= toMove;
937
- this.right -= toMove;
938
- break;
939
- case "+y":
940
- this.top += toMove;
941
- this.bottom += toMove;
942
- break;
943
- case "-y":
944
- this.top -= toMove;
945
- this.bottom -= toMove;
946
- break;
947
- }
948
- };
949
-
950
- // Check if this box overlaps another box, b2.
951
- BoxPosition.prototype.overlaps = function(b2) {
952
- return this.left < b2.right &&
953
- this.right > b2.left &&
954
- this.top < b2.bottom &&
955
- this.bottom > b2.top;
956
- };
957
-
958
- // Check if this box overlaps any other boxes in boxes.
959
- BoxPosition.prototype.overlapsAny = function(boxes) {
960
- for (var i = 0; i < boxes.length; i++) {
961
- if (this.overlaps(boxes[i])) {
962
- return true;
963
- }
964
- }
965
- return false;
966
- };
967
-
968
- // Check if this box is within another box.
969
- BoxPosition.prototype.within = function(container) {
970
- return this.top >= container.top &&
971
- this.bottom <= container.bottom &&
972
- this.left >= container.left &&
973
- this.right <= container.right;
974
- };
975
-
976
- // Check if this box is entirely within the container or it is overlapping
977
- // on the edge opposite of the axis direction passed. For example, if "+x" is
978
- // passed and the box is overlapping on the left edge of the container, then
979
- // return true.
980
- BoxPosition.prototype.overlapsOppositeAxis = function(container, axis) {
981
- switch (axis) {
982
- case "+x":
983
- return this.left < container.left;
984
- case "-x":
985
- return this.right > container.right;
986
- case "+y":
987
- return this.top < container.top;
988
- case "-y":
989
- return this.bottom > container.bottom;
990
- }
991
- };
992
-
993
- // Find the percentage of the area that this box is overlapping with another
994
- // box.
995
- BoxPosition.prototype.intersectPercentage = function(b2) {
996
- var x = Math.max(0, Math.min(this.right, b2.right) - Math.max(this.left, b2.left)),
997
- y = Math.max(0, Math.min(this.bottom, b2.bottom) - Math.max(this.top, b2.top)),
998
- intersectArea = x * y;
999
- return intersectArea / (this.height * this.width);
1000
- };
1001
-
1002
- // Convert the positions from this box to CSS compatible positions using
1003
- // the reference container's positions. This has to be done because this
1004
- // box's positions are in reference to the viewport origin, whereas, CSS
1005
- // values are in referecne to their respective edges.
1006
- BoxPosition.prototype.toCSSCompatValues = function(reference) {
1007
- return {
1008
- top: this.top - reference.top,
1009
- bottom: reference.bottom - this.bottom,
1010
- left: this.left - reference.left,
1011
- right: reference.right - this.right,
1012
- height: this.height,
1013
- width: this.width
1014
- };
1015
- };
1016
-
1017
- // Get an object that represents the box's position without anything extra.
1018
- // Can pass a StyleBox, HTMLElement, or another BoxPositon.
1019
- BoxPosition.getSimpleBoxPosition = function(obj) {
1020
- var height = obj.div ? obj.div.offsetHeight : obj.tagName ? obj.offsetHeight : 0;
1021
- var width = obj.div ? obj.div.offsetWidth : obj.tagName ? obj.offsetWidth : 0;
1022
- var top = obj.div ? obj.div.offsetTop : obj.tagName ? obj.offsetTop : 0;
1023
-
1024
- obj = obj.div ? obj.div.getBoundingClientRect() :
1025
- obj.tagName ? obj.getBoundingClientRect() : obj;
1026
- var ret = {
1027
- left: obj.left,
1028
- right: obj.right,
1029
- top: obj.top || top,
1030
- height: obj.height || height,
1031
- bottom: obj.bottom || (top + (obj.height || height)),
1032
- width: obj.width || width
1033
- };
1034
- return ret;
1035
- };
1036
-
1037
- // Move a StyleBox to its specified, or next best, position. The containerBox
1038
- // is the box that contains the StyleBox, such as a div. boxPositions are
1039
- // a list of other boxes that the styleBox can't overlap with.
1040
- function moveBoxToLinePosition(window, styleBox, containerBox, boxPositions) {
1041
-
1042
- // Find the best position for a cue box, b, on the video. The axis parameter
1043
- // is a list of axis, the order of which, it will move the box along. For example:
1044
- // Passing ["+x", "-x"] will move the box first along the x axis in the positive
1045
- // direction. If it doesn't find a good position for it there it will then move
1046
- // it along the x axis in the negative direction.
1047
- function findBestPosition(b, axis) {
1048
- var bestPosition,
1049
- specifiedPosition = new BoxPosition(b),
1050
- percentage = 1; // Highest possible so the first thing we get is better.
1051
-
1052
- for (var i = 0; i < axis.length; i++) {
1053
- while (b.overlapsOppositeAxis(containerBox, axis[i]) ||
1054
- (b.within(containerBox) && b.overlapsAny(boxPositions))) {
1055
- b.move(axis[i]);
1056
- }
1057
- // We found a spot where we aren't overlapping anything. This is our
1058
- // best position.
1059
- if (b.within(containerBox)) {
1060
- return b;
1061
- }
1062
- var p = b.intersectPercentage(containerBox);
1063
- // If we're outside the container box less then we were on our last try
1064
- // then remember this position as the best position.
1065
- if (percentage > p) {
1066
- bestPosition = new BoxPosition(b);
1067
- percentage = p;
1068
- }
1069
- // Reset the box position to the specified position.
1070
- b = new BoxPosition(specifiedPosition);
1071
- }
1072
- return bestPosition || specifiedPosition;
1073
- }
1074
-
1075
- var boxPosition = new BoxPosition(styleBox),
1076
- cue = styleBox.cue,
1077
- linePos = computeLinePos(cue),
1078
- axis = [];
1079
-
1080
- // If we have a line number to align the cue to.
1081
- if (cue.snapToLines) {
1082
- var size;
1083
- switch (cue.vertical) {
1084
- case "":
1085
- axis = [ "+y", "-y" ];
1086
- size = "height";
1087
- break;
1088
- case "rl":
1089
- axis = [ "+x", "-x" ];
1090
- size = "width";
1091
- break;
1092
- case "lr":
1093
- axis = [ "-x", "+x" ];
1094
- size = "width";
1095
- break;
1096
- }
1097
-
1098
- var step = boxPosition.lineHeight,
1099
- position = step * Math.round(linePos),
1100
- maxPosition = containerBox[size] + step,
1101
- initialAxis = axis[0];
1102
-
1103
- // If the specified intial position is greater then the max position then
1104
- // clamp the box to the amount of steps it would take for the box to
1105
- // reach the max position.
1106
- if (Math.abs(position) > maxPosition) {
1107
- position = position < 0 ? -1 : 1;
1108
- position *= Math.ceil(maxPosition / step) * step;
1109
- }
1110
-
1111
- // If computed line position returns negative then line numbers are
1112
- // relative to the bottom of the video instead of the top. Therefore, we
1113
- // need to increase our initial position by the length or width of the
1114
- // video, depending on the writing direction, and reverse our axis directions.
1115
- if (linePos < 0) {
1116
- position += cue.vertical === "" ? containerBox.height : containerBox.width;
1117
- axis = axis.reverse();
1118
- }
1119
-
1120
- // Move the box to the specified position. This may not be its best
1121
- // position.
1122
- boxPosition.move(initialAxis, position);
1123
-
1124
- } else {
1125
- // If we have a percentage line value for the cue.
1126
- var calculatedPercentage = (boxPosition.lineHeight / containerBox.height) * 100;
1127
-
1128
- switch (cue.lineAlign) {
1129
- case "middle":
1130
- linePos -= (calculatedPercentage / 2);
1131
- break;
1132
- case "end":
1133
- linePos -= calculatedPercentage;
1134
- break;
1135
- }
1136
-
1137
- // Apply initial line position to the cue box.
1138
- switch (cue.vertical) {
1139
- case "":
1140
- styleBox.applyStyles({
1141
- top: styleBox.formatStyle(linePos, "%")
1142
- });
1143
- break;
1144
- case "rl":
1145
- styleBox.applyStyles({
1146
- left: styleBox.formatStyle(linePos, "%")
1147
- });
1148
- break;
1149
- case "lr":
1150
- styleBox.applyStyles({
1151
- right: styleBox.formatStyle(linePos, "%")
1152
- });
1153
- break;
1154
- }
1155
-
1156
- axis = [ "+y", "-x", "+x", "-y" ];
1157
-
1158
- // Get the box position again after we've applied the specified positioning
1159
- // to it.
1160
- boxPosition = new BoxPosition(styleBox);
1161
- }
1162
-
1163
- var bestPosition = findBestPosition(boxPosition, axis);
1164
- styleBox.move(bestPosition.toCSSCompatValues(containerBox));
1165
- }
1166
-
1167
- /*function WebVTT() {
1168
- // Nothing
1169
- }*/
1170
-
1171
- // Helper to allow strings to be decoded instead of the default binary utf8 data.
1172
- WebVTT.StringDecoder = function() {
1173
- return {
1174
- decode: function(data) {
1175
- if (!data) {
1176
- return "";
1177
- }
1178
- if (typeof data !== "string") {
1179
- throw new Error("Error - expected string data.");
1180
- }
1181
- return decodeURIComponent(encodeURIComponent(data));
1182
- }
1183
- };
1184
- };
1185
-
1186
- WebVTT.convertCueToDOMTree = function(window, cuetext) {
1187
- if (!window || !cuetext) {
1188
- return null;
1189
- }
1190
- return parseContent(window, cuetext);
1191
- };
1192
-
1193
- var FONT_SIZE_PERCENT = 0.05;
1194
- var FONT_STYLE = "sans-serif";
1195
- var CUE_BACKGROUND_PADDING = "1.5%";
1196
-
1197
- // Runs the processing model over the cues and regions passed to it.
1198
- // @param overlay A block level element (usually a div) that the computed cues
1199
- // and regions will be placed into.
1200
- WebVTT.processCues = function(window, cues, overlay) {
1201
- if (!window || !cues || !overlay) {
1202
- return null;
1203
- }
1204
-
1205
- // Remove all previous children.
1206
- while (overlay.firstChild) {
1207
- overlay.removeChild(overlay.firstChild);
1208
- }
1209
-
1210
- var paddedOverlay = window.document.createElement("div");
1211
- paddedOverlay.style.position = "absolute";
1212
- paddedOverlay.style.left = "0";
1213
- paddedOverlay.style.right = "0";
1214
- paddedOverlay.style.top = "0";
1215
- paddedOverlay.style.bottom = "0";
1216
- paddedOverlay.style.margin = CUE_BACKGROUND_PADDING;
1217
- overlay.appendChild(paddedOverlay);
1218
-
1219
- // Determine if we need to compute the display states of the cues. This could
1220
- // be the case if a cue's state has been changed since the last computation or
1221
- // if it has not been computed yet.
1222
- function shouldCompute(cues) {
1223
- for (var i = 0; i < cues.length; i++) {
1224
- if (cues[i].hasBeenReset || !cues[i].displayState) {
1225
- return true;
1226
- }
1227
- }
1228
- return false;
1229
- }
1230
-
1231
- // We don't need to recompute the cues' display states. Just reuse them.
1232
- if (!shouldCompute(cues)) {
1233
- for (var i = 0; i < cues.length; i++) {
1234
- paddedOverlay.appendChild(cues[i].displayState);
1235
- }
1236
- return;
1237
- }
1238
-
1239
- var boxPositions = [],
1240
- containerBox = BoxPosition.getSimpleBoxPosition(paddedOverlay),
1241
- fontSize = Math.round(containerBox.height * FONT_SIZE_PERCENT * 100) / 100;
1242
- var styleOptions = {
1243
- font: (fontSize * fontScale) + "px " + FONT_STYLE
1244
- };
1245
-
1246
- (function() {
1247
- var styleBox, cue;
1248
-
1249
- for (var i = 0; i < cues.length; i++) {
1250
- cue = cues[i];
1251
-
1252
- // Compute the intial position and styles of the cue div.
1253
- styleBox = new CueStyleBox(window, cue, styleOptions);
1254
- paddedOverlay.appendChild(styleBox.div);
1255
-
1256
- // Move the cue div to it's correct line position.
1257
- moveBoxToLinePosition(window, styleBox, containerBox, boxPositions);
1258
-
1259
- // Remember the computed div so that we don't have to recompute it later
1260
- // if we don't have too.
1261
- cue.displayState = styleBox.div;
1262
-
1263
- boxPositions.push(BoxPosition.getSimpleBoxPosition(styleBox));
1264
- }
1265
- })();
1266
- };
1267
-
1268
- WebVTT.Parser = function(window, decoder) {
1269
- this.window = window;
1270
- this.state = "INITIAL";
1271
- this.buffer = "";
1272
- this.decoder = decoder || new TextDecoder("utf8");
1273
- this.regionList = [];
1274
- };
1275
-
1276
- WebVTT.Parser.prototype = {
1277
- // If the error is a ParsingError then report it to the consumer if
1278
- // possible. If it's not a ParsingError then throw it like normal.
1279
- reportOrThrowError: function(e) {
1280
- if (e instanceof ParsingError) {
1281
- this.onparsingerror && this.onparsingerror(e);
1282
- } else {
1283
- throw e;
1284
- }
1285
- },
1286
- parse: function (data, flushing) {
1287
- var self = this;
1288
- // If there is no data then we won't decode it, but will just try to parse
1289
- // whatever is in buffer already. This may occur in circumstances, for
1290
- // example when flush() is called.
1291
- if (data) {
1292
- // Try to decode the data that we received.
1293
- self.buffer += self.decoder.decode(data, {stream: true});
1294
- }
1295
- function collectNextLine() {
1296
- var buffer = self.buffer;
1297
- var pos = 0;
1298
- while (pos < buffer.length && buffer[pos] !== '\r' && buffer[pos] !== '\n') {
1299
- ++pos;
1300
- }
1301
- var line = buffer.substr(0, pos);
1302
- // Advance the buffer early in case we fail below.
1303
- if (buffer[pos] === '\r') {
1304
- ++pos;
1305
- }
1306
- if (buffer[pos] === '\n') {
1307
- ++pos;
1308
- }
1309
- self.buffer = buffer.substr(pos);
1310
- return line;
1311
- }
1312
-
1313
- // 3.4 WebVTT region and WebVTT region settings syntax
1314
- function parseRegion(input) {
1315
- var settings = new Settings();
1316
-
1317
- parseOptions(input, function (k, v) {
1318
- switch (k) {
1319
- case "id":
1320
- settings.set(k, v);
1321
- break;
1322
- case "width":
1323
- settings.percent(k, v);
1324
- break;
1325
- case "lines":
1326
- settings.integer(k, v);
1327
- break;
1328
- case "regionanchor":
1329
- case "viewportanchor":
1330
- var xy = v.split(',');
1331
- if (xy.length !== 2) {
1332
- break;
1333
- }
1334
- // We have to make sure both x and y parse, so use a temporary
1335
- // settings object here.
1336
- var anchor = new Settings();
1337
- anchor.percent("x", xy[0]);
1338
- anchor.percent("y", xy[1]);
1339
- if (!anchor.has("x") || !anchor.has("y")) {
1340
- break;
1341
- }
1342
- settings.set(k + "X", anchor.get("x"));
1343
- settings.set(k + "Y", anchor.get("y"));
1344
- break;
1345
- case "scroll":
1346
- settings.alt(k, v, ["up"]);
1347
- break;
1348
- }
1349
- }, /=/, /\s/);
1350
-
1351
- // Create the region, using default values for any values that were not
1352
- // specified.
1353
- if (settings.has("id")) {
1354
- var region = new VTTRegion();
1355
- region.width = settings.get("width", 100);
1356
- region.lines = settings.get("lines", 3);
1357
- region.regionAnchorX = settings.get("regionanchorX", 0);
1358
- region.regionAnchorY = settings.get("regionanchorY", 100);
1359
- region.viewportAnchorX = settings.get("viewportanchorX", 0);
1360
- region.viewportAnchorY = settings.get("viewportanchorY", 100);
1361
- region.scroll = settings.get("scroll", "");
1362
- // Register the region.
1363
- self.onregion && self.onregion(region);
1364
- // Remember the VTTRegion for later in case we parse any VTTCues that
1365
- // reference it.
1366
- self.regionList.push({
1367
- id: settings.get("id"),
1368
- region: region
1369
- });
1370
- }
1371
- }
1372
-
1373
- // 3.2 WebVTT metadata header syntax
1374
- function parseHeader(input) {
1375
- parseOptions(input, function (k, v) {
1376
- switch (k) {
1377
- case "Region":
1378
- // 3.3 WebVTT region metadata header syntax
1379
- parseRegion(v);
1380
- break;
1381
- }
1382
- }, /:/);
1383
- }
1384
-
1385
- // 5.1 WebVTT file parsing.
1386
- try {
1387
- var line;
1388
- if (self.state === "INITIAL") {
1389
- // We can't start parsing until we have the first line.
1390
- if (!/\r\n|\n/.test(self.buffer)) {
1391
- return this;
1392
- }
1393
-
1394
- line = collectNextLine();
1395
-
1396
- var m = line.match(/^WEBVTT([ \t].*)?$/);
1397
- if (!m || !m[0]) {
1398
- throw new ParsingError(ParsingError.Errors.BadSignature);
1399
- }
1400
-
1401
- self.state = "HEADER";
1402
- }
1403
-
1404
- var alreadyCollectedLine = false;
1405
- while (self.buffer) {
1406
- // We can't parse a line until we have the full line.
1407
- if (!/\r\n|\n/.test(self.buffer)) {
1408
- return this;
1409
- }
1410
-
1411
- if (!alreadyCollectedLine) {
1412
- line = collectNextLine();
1413
- } else {
1414
- alreadyCollectedLine = false;
1415
- }
1416
- switch (self.state) {
1417
- case "HEADER":
1418
- // 13-18 - Allow a header (metadata) under the WEBVTT line.
1419
- if (/:/.test(line)) {
1420
- parseHeader(line);
1421
- } else if (!line) {
1422
- // An empty line terminates the header and starts the body (cues).
1423
- self.state = "ID";
1424
- }
1425
- continue;
1426
- case "NOTE":
1427
- // Ignore NOTE blocks.
1428
- if (!line) {
1429
- self.state = "ID";
1430
- }
1431
- continue;
1432
- case "ID":
1433
- // Check for the start of NOTE blocks.
1434
- if (/^NOTE($|[ \t])/.test(line)) {
1435
- self.state = "NOTE";
1436
- break;
1437
- }
1438
- // 19-29 - Allow any number of line terminators, then initialize new cue values.
1439
- if (!line) {
1440
- continue;
1441
- }
1442
- self.cue = new VTTCue(0, 0, "");
1443
- self.state = "CUE";
1444
- // 30-39 - Check if self line contains an optional identifier or timing data.
1445
- if (line.indexOf("-->") === -1) {
1446
- self.cue.id = line;
1447
- continue;
1448
- }
1449
- // Process line as start of a cue.
1450
- /*falls through*/
1451
- case "CUE":
1452
- // 40 - Collect cue timings and settings.
1453
- try {
1454
- parseCue(line, self.cue, self.regionList);
1455
- } catch (e) {
1456
- self.reportOrThrowError(e);
1457
- // In case of an error ignore rest of the cue.
1458
- self.cue = null;
1459
- self.state = "BADCUE";
1460
- continue;
1461
- }
1462
- self.state = "CUETEXT";
1463
- continue;
1464
- case "CUETEXT":
1465
- var hasSubstring = line.indexOf("-->") !== -1;
1466
- // 34 - If we have an empty line then report the cue.
1467
- // 35 - If we have the special substring '-->' then report the cue,
1468
- // but do not collect the line as we need to process the current
1469
- // one as a new cue.
1470
- if (!line || hasSubstring && (alreadyCollectedLine = true)) {
1471
- // We are done parsing self cue.
1472
- self.oncue && self.oncue(self.cue);
1473
- self.cue = null;
1474
- self.state = "ID";
1475
- continue;
1476
- }
1477
- if (self.cue.text) {
1478
- self.cue.text += "\n";
1479
- }
1480
- self.cue.text += line;
1481
- continue;
1482
- case "BADCUE": // BADCUE
1483
- // 54-62 - Collect and discard the remaining cue.
1484
- if (!line) {
1485
- self.state = "ID";
1486
- }
1487
- continue;
1488
- }
1489
- }
1490
-
1491
-
1492
- if (!flushing) {
1493
- //때때로 (한긇 vtt로 추정) cue가 남아 있는채로 self.flush()를 호출해서 cue가 있기 때문에 다시 self.parse()를 타는 경우가 생김.
1494
- //왜 이렇게 짜여 있는지 모르겠고 일단 아래와 같은 코드로 위기를 극복한다.
1495
- if (self.state === "CUETEXT" && self.cue && self.oncue) {
1496
- self.oncue(self.cue);
1497
- }
1498
- self.flush();
1499
- return this;
1500
- }
1501
- } catch (e) {
1502
- self.reportOrThrowError(e);
1503
- // If we are currently parsing a cue, report what we have.
1504
- if (self.state === "CUETEXT" && self.cue && self.oncue) {
1505
- self.oncue(self.cue);
1506
- }
1507
- self.cue = null;
1508
- // Enter BADWEBVTT state if header was not parsed correctly otherwise
1509
- // another exception occurred so enter BADCUE state.
1510
- self.state = self.state === "INITIAL" ? "BADWEBVTT" : "BADCUE";
1511
- }
1512
- return this;
1513
- },
1514
- flush: function () {
1515
- var self = this;
1516
-
1517
- try {
1518
- // Finish decoding the stream.
1519
- self.buffer += self.decoder.decode();
1520
- // Synthesize the end of the current cue or region.
1521
- if (self.cue || self.state === "HEADER") {
1522
- self.buffer += "\n\n";
1523
- self.parse(null, true);
1524
- }
1525
- // If we've flushed, parsed, and we're still on the INITIAL state then
1526
- // that means we don't have enough of the stream to parse the first
1527
- // line.
1528
- if (self.state === "INITIAL") {
1529
- throw new ParsingError(ParsingError.Errors.BadSignature);
1530
- }
1531
- } catch(e) {
1532
- self.reportOrThrowError(e);
1533
- }
1534
- self.onflush && self.onflush();
1535
- return this;
1536
- }
1537
- };
1538
-
1539
-
1540
-
1541
-
1542
- export default WebVTT;
1
+ /* vtt.js - v0.12.1 (https://github.com/mozilla/vtt.js) built on 03-12-2015 */
2
+ import {VTTCue, VTTRegion} from 'media-captions';
3
+
4
+ /**
5
+ * Copyright 2013 vtt.js Contributors
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+
20
+ /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
21
+ /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
22
+
23
+ let WebVTT = function(){};
24
+ function makeColorSet(color, opacity) {
25
+ if(opacity === undefined) {
26
+ opacity = 1;
27
+ }
28
+ return "rgba(" + [parseInt(color.substring(0, 2), 16),
29
+ parseInt(color.substring(2, 4), 16),
30
+ parseInt(color.substring(4, 6), 16),
31
+ opacity].join(",") + ")";
32
+ }
33
+
34
+ var WebVTTPrefs = ['webvtt.font.color', 'webvtt.font.opacity', 'webvtt.font.scale',
35
+ 'webvtt.bg.color', 'webvtt.bg.opacity',
36
+ 'webvtt.edge.color', 'webvtt.edge.type'];
37
+
38
+ var fontScale = 1;
39
+
40
+ function observe(subject, topic, data) {
41
+ switch (data) {
42
+ case "webvtt.font.color":
43
+ case "webvtt.font.opacity":
44
+ var fontColor = Services.prefs.getCharPref("webvtt.font.color");
45
+ var fontOpacity = Services.prefs.getIntPref("webvtt.font.opacity") / 100;
46
+ WebVTTSet.fontSet = makeColorSet(fontColor, fontOpacity);
47
+ break;
48
+ case "webvtt.font.scale":
49
+ fontScale = Services.prefs.getIntPref("webvtt.font.scale") / 100;
50
+ break;
51
+ case "webvtt.bg.color":
52
+ case "webvtt.bg.opacity":
53
+ var backgroundColor = Services.prefs.getCharPref("webvtt.bg.color");
54
+ var backgroundOpacity = Services.prefs.getIntPref("webvtt.bg.opacity") / 100;
55
+ WebVTTSet.backgroundSet = makeColorSet(backgroundColor, backgroundOpacity);
56
+ break;
57
+ case "webvtt.edge.color":
58
+ case "webvtt.edge.type":
59
+ var edgeTypeList = ["", "0px 0px ", "4px 4px 4px ", "-2px -2px ", "2px 2px "];
60
+ var edgeType = Services.prefs.getIntPref("webvtt.edge.type");
61
+ var edgeColor = Services.prefs.getCharPref("webvtt.edge.color");
62
+ WebVTTSet.edgeSet = edgeTypeList[edgeType] + makeColorSet(edgeColor);
63
+ break;
64
+ }
65
+ }
66
+
67
+ if(typeof Services !== "undefined") {
68
+ var WebVTTSet = {};
69
+ WebVTTPrefs.forEach(function (pref) {
70
+ observe(undefined, undefined, pref);
71
+ Services.prefs.addObserver(pref, observe, false);
72
+ });
73
+ }
74
+
75
+ var _objCreate = Object.create || (function() {
76
+ function F() {}
77
+ return function(o) {
78
+ if (arguments.length !== 1) {
79
+ throw new Error('Object.create shim only accepts one parameter.');
80
+ }
81
+ F.prototype = o;
82
+ return new F();
83
+ };
84
+ })();
85
+
86
+ // Creates a new ParserError object from an errorData object. The errorData
87
+ // object should have default code and message properties. The default message
88
+ // property can be overriden by passing in a message parameter.
89
+ // See ParsingError.Errors below for acceptable errors.
90
+ function ParsingError(errorData, message) {
91
+ this.name = "ParsingError";
92
+ this.code = errorData.code;
93
+ this.message = message || errorData.message;
94
+ }
95
+ ParsingError.prototype = _objCreate(Error.prototype);
96
+ ParsingError.prototype.constructor = ParsingError;
97
+
98
+ // ParsingError metadata for acceptable ParsingErrors.
99
+ ParsingError.Errors = {
100
+ BadSignature: {
101
+ code: 0,
102
+ message: "Malformed WebVTT signature."
103
+ },
104
+ BadTimeStamp: {
105
+ code: 1,
106
+ message: "Malformed time stamp."
107
+ }
108
+ };
109
+
110
+ // Try to parse input as a time stamp.
111
+ function parseTimeStamp(input) {
112
+
113
+ function computeSeconds(h, m, s, f) {
114
+ return (h | 0) * 3600 + (m | 0) * 60 + (s | 0) + (f | 0) / 1000;
115
+ }
116
+
117
+ var m = input.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/);
118
+ if (!m) {
119
+ return null;
120
+ }
121
+
122
+ if (m[3]) {
123
+ // Timestamp takes the form of [hours]:[minutes]:[seconds].[milliseconds]
124
+ return computeSeconds(m[1], m[2], m[3].replace(":", ""), m[4]);
125
+ } else if (m[1] > 59) {
126
+ // Timestamp takes the form of [hours]:[minutes].[milliseconds]
127
+ // First position is hours as it's over 59.
128
+ return computeSeconds(m[1], m[2], 0, m[4]);
129
+ } else {
130
+ // Timestamp takes the form of [minutes]:[seconds].[milliseconds]
131
+ return computeSeconds(0, m[1], m[2], m[4]);
132
+ }
133
+ }
134
+
135
+ // A settings object holds key/value pairs and will ignore anything but the first
136
+ // assignment to a specific key.
137
+ function Settings() {
138
+ this.values = _objCreate(null);
139
+ }
140
+
141
+ Settings.prototype = {
142
+ // Only accept the first assignment to any key.
143
+ set: function(k, v) {
144
+ if (!this.get(k) && v !== "") {
145
+ this.values[k] = v;
146
+ }
147
+ },
148
+ // Return the value for a key, or a default value.
149
+ // If 'defaultKey' is passed then 'dflt' is assumed to be an object with
150
+ // a number of possible default values as properties where 'defaultKey' is
151
+ // the key of the property that will be chosen; otherwise it's assumed to be
152
+ // a single value.
153
+ get: function(k, dflt, defaultKey) {
154
+ if (defaultKey) {
155
+ return this.has(k) ? this.values[k] : dflt[defaultKey];
156
+ }
157
+ return this.has(k) ? this.values[k] : dflt;
158
+ },
159
+ // Check whether we have a value for a key.
160
+ has: function(k) {
161
+ return k in this.values;
162
+ },
163
+ // Accept a setting if its one of the given alternatives.
164
+ alt: function(k, v, a) {
165
+ for (var n = 0; n < a.length; ++n) {
166
+ if (v === a[n]) {
167
+ this.set(k, v);
168
+ break;
169
+ }
170
+ }
171
+ },
172
+ // Accept a setting if its a valid (signed) integer.
173
+ integer: function(k, v) {
174
+ if (/^-?\d+$/.test(v)) { // integer
175
+ this.set(k, parseInt(v, 10));
176
+ }
177
+ },
178
+ // Accept a setting if its a valid percentage.
179
+ percent: function(k, v) {
180
+ var m;
181
+ if ((m = v.match(/^([\d]{1,3})(\.[\d]*)?%$/))) {
182
+ v = parseFloat(v);
183
+ if (v >= 0 && v <= 100) {
184
+ this.set(k, v);
185
+ return true;
186
+ }
187
+ }
188
+ return false;
189
+ }
190
+ };
191
+
192
+ // Helper function to parse input into groups separated by 'groupDelim', and
193
+ // interprete each group as a key/value pair separated by 'keyValueDelim'.
194
+ function parseOptions(input, callback, keyValueDelim, groupDelim) {
195
+ var groups = groupDelim ? input.split(groupDelim) : [input];
196
+ for (var i in groups) {
197
+ if (typeof groups[i] !== "string") {
198
+ continue;
199
+ }
200
+ var kv = groups[i].split(keyValueDelim);
201
+ if (kv.length !== 2) {
202
+ continue;
203
+ }
204
+ var k = kv[0];
205
+ var v = kv[1];
206
+ callback(k, v);
207
+ }
208
+ }
209
+
210
+ function parseCue(input, cue, regionList) {
211
+ // Remember the original input if we need to throw an error.
212
+ var oInput = input;
213
+ // 4.1 WebVTT timestamp
214
+ function consumeTimeStamp() {
215
+ var ts = parseTimeStamp(input);
216
+ if (ts === null) {
217
+ throw new ParsingError(ParsingError.Errors.BadTimeStamp,
218
+ "Malformed timestamp: " + oInput);
219
+ }
220
+ // Remove time stamp from input.
221
+ input = input.replace(/^[^\sa-zA-Z-]+/, "");
222
+ return ts;
223
+ }
224
+
225
+ // 4.4.2 WebVTT cue settings
226
+ function consumeCueSettings(input, cue) {
227
+ var settings = new Settings();
228
+
229
+ parseOptions(input, function (k, v) {
230
+ switch (k) {
231
+ case "region":
232
+ // Find the last region we parsed with the same region id.
233
+ for (var i = regionList.length - 1; i >= 0; i--) {
234
+ if (regionList[i].id === v) {
235
+ settings.set(k, regionList[i].region);
236
+ break;
237
+ }
238
+ }
239
+ break;
240
+ case "vertical":
241
+ settings.alt(k, v, ["rl", "lr"]);
242
+ break;
243
+ case "line":
244
+ var vals = v.split(","),
245
+ vals0 = vals[0];
246
+ settings.integer(k, vals0);
247
+ settings.percent(k, vals0) ? settings.set("snapToLines", false) : null;
248
+ settings.alt(k, vals0, ["auto"]);
249
+ if (vals.length === 2) {
250
+ settings.alt("lineAlign", vals[1], ["start", "middle", "end"]);
251
+ }
252
+ break;
253
+ case "position":
254
+ vals = v.split(",");
255
+ settings.percent(k, vals[0]);
256
+ if (vals.length === 2) {
257
+ settings.alt("positionAlign", vals[1], ["start", "middle", "end"]);
258
+ }
259
+ break;
260
+ case "size":
261
+ settings.percent(k, v);
262
+ break;
263
+ case "align":
264
+ settings.alt(k, v, ["start", "middle", "end", "left", "right"]);
265
+ break;
266
+ }
267
+ }, /:/, /\s/);
268
+
269
+ //hslee remove these fields.
270
+ //Because safari dies here always. And Player doen't use style fields.
271
+ // Apply default values for any missing fields.
272
+ /*cue.region = settings.get("region", null);
273
+ cue.vertical = settings.get("vertical", "");
274
+ cue.line = settings.get("line", "auto");
275
+ cue.lineAlign = settings.get("lineAlign", "start");
276
+ cue.snapToLines = settings.get("snapToLines", true);
277
+ cue.size = settings.get("size", 100);
278
+ //cue.align = settings.get("align", "middle");
279
+ cue.position = settings.get("position", "auto");
280
+ cue.positionAlign = settings.get("positionAlign", {
281
+ start: "start",
282
+ left: "start",
283
+ middle: "middle",
284
+ end: "end",
285
+ right: "end"
286
+ }, cue.align
287
+ );*/
288
+ }
289
+
290
+ function skipWhitespace() {
291
+ input = input.replace(/^\s+/, "");
292
+ }
293
+
294
+ // 4.1 WebVTT cue timings.
295
+ skipWhitespace();
296
+ cue.startTime = consumeTimeStamp(); // (1) collect cue start time
297
+ skipWhitespace();
298
+ if (input.substr(0, 3) !== "-->") { // (3) next characters must match "-->"
299
+ throw new ParsingError(ParsingError.Errors.BadTimeStamp,
300
+ "Malformed time stamp (time stamps must be separated by '-->'): " +
301
+ oInput);
302
+ }
303
+ input = input.substr(3);
304
+ skipWhitespace();
305
+ cue.endTime = consumeTimeStamp(); // (5) collect cue end time
306
+
307
+ // 4.1 WebVTT cue settings list.
308
+ skipWhitespace();
309
+ consumeCueSettings(input, cue);
310
+ }
311
+
312
+ var ESCAPE = {
313
+ "&amp;": "&",
314
+ "&lt;": "<",
315
+ "&gt;": ">",
316
+ "&lrm;": "\u200e",
317
+ "&rlm;": "\u200f",
318
+ "&nbsp;": "\u00a0"
319
+ };
320
+
321
+ var TAG_NAME = {
322
+ c: "span",
323
+ i: "i",
324
+ b: "b",
325
+ u: "u",
326
+ ruby: "ruby",
327
+ rt: "rt",
328
+ v: "span",
329
+ lang: "span"
330
+ };
331
+
332
+ var TAG_ANNOTATION = {
333
+ v: "title",
334
+ lang: "lang"
335
+ };
336
+
337
+ var NEEDS_PARENT = {
338
+ rt: "ruby"
339
+ };
340
+
341
+ // Parse content into a document fragment.
342
+ function parseContent(window, input) {
343
+ function nextToken() {
344
+ // Check for end-of-string.
345
+ if (!input) {
346
+ return null;
347
+ }
348
+
349
+ // Consume 'n' characters from the input.
350
+ function consume(result) {
351
+ input = input.substr(result.length);
352
+ return result;
353
+ }
354
+
355
+ var m = input.match(/^([^<]*)(<[^>]+>?)?/);
356
+ // If there is some text before the next tag, return it, otherwise return
357
+ // the tag.
358
+ return consume(m[1] ? m[1] : m[2]);
359
+ }
360
+
361
+ // Unescape a string 's'.
362
+ function unescape1(e) {
363
+ return ESCAPE[e];
364
+ }
365
+ function unescape(s) {
366
+ while ((m = s.match(/&(amp|lt|gt|lrm|rlm|nbsp);/))) {
367
+ s = s.replace(m[0], unescape1);
368
+ }
369
+ return s;
370
+ }
371
+
372
+ function shouldAdd(current, element) {
373
+ return !NEEDS_PARENT[element.localName] ||
374
+ NEEDS_PARENT[element.localName] === current.localName;
375
+ }
376
+
377
+ // Create an element for this tag.
378
+ function createElement(type, annotation) {
379
+ var tagName = TAG_NAME[type];
380
+ if (!tagName) {
381
+ return null;
382
+ }
383
+ var element = window.document.createElement(tagName);
384
+ element.localName = tagName;
385
+ var name = TAG_ANNOTATION[type];
386
+ if (name && annotation) {
387
+ element[name] = annotation.trim();
388
+ }
389
+ return element;
390
+ }
391
+
392
+ var rootDiv = window.document.createElement("div"),
393
+ current = rootDiv,
394
+ t,
395
+ tagStack = [];
396
+
397
+ while ((t = nextToken()) !== null) {
398
+ if (t[0] === '<') {
399
+ if (t[1] === "/") {
400
+ // If the closing tag matches, move back up to the parent node.
401
+ if (tagStack.length &&
402
+ tagStack[tagStack.length - 1] === t.substr(2).replace(">", "")) {
403
+ tagStack.pop();
404
+ current = current.parentNode;
405
+ }
406
+ // Otherwise just ignore the end tag.
407
+ continue;
408
+ }
409
+ var ts = parseTimeStamp(t.substr(1, t.length - 2));
410
+ var node;
411
+ if (ts) {
412
+ // Timestamps are lead nodes as well.
413
+ node = window.document.createProcessingInstruction("timestamp", ts);
414
+ current.appendChild(node);
415
+ continue;
416
+ }
417
+ var m = t.match(/^<([^.\s/0-9>]+)(\.[^\s\\>]+)?([^>\\]+)?(\\?)>?$/);
418
+ // If we can't parse the tag, skip to the next tag.
419
+ if (!m) {
420
+ continue;
421
+ }
422
+ // Try to construct an element, and ignore the tag if we couldn't.
423
+ node = createElement(m[1], m[3]);
424
+ if (!node) {
425
+ continue;
426
+ }
427
+ // Determine if the tag should be added based on the context of where it
428
+ // is placed in the cuetext.
429
+ if (!shouldAdd(current, node)) {
430
+ continue;
431
+ }
432
+ // Set the class list (as a list of classes, separated by space).
433
+ if (m[2]) {
434
+ node.className = m[2].substr(1).replace('.', ' ');
435
+ }
436
+ // Append the node to the current node, and enter the scope of the new
437
+ // node.
438
+ tagStack.push(m[1]);
439
+ current.appendChild(node);
440
+ current = node;
441
+ continue;
442
+ }
443
+
444
+ // Text nodes are leaf nodes.
445
+ current.appendChild(window.document.createTextNode(unescape(t)));
446
+ }
447
+
448
+ return rootDiv;
449
+ }
450
+
451
+ // This is a list of all the Unicode characters that have a strong
452
+ // right-to-left category. What this means is that these characters are
453
+ // written right-to-left for sure. It was generated by pulling all the strong
454
+ // right-to-left characters out of the Unicode data table. That table can
455
+ // found at: http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
456
+ var strongRTLChars = [0x05BE, 0x05C0, 0x05C3, 0x05C6, 0x05D0, 0x05D1,
457
+ 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA,
458
+ 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1, 0x05E2, 0x05E3,
459
+ 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x05F0, 0x05F1,
460
+ 0x05F2, 0x05F3, 0x05F4, 0x0608, 0x060B, 0x060D, 0x061B, 0x061E, 0x061F,
461
+ 0x0620, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628,
462
+ 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631,
463
+ 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063A,
464
+ 0x063B, 0x063C, 0x063D, 0x063E, 0x063F, 0x0640, 0x0641, 0x0642, 0x0643,
465
+ 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 0x066D, 0x066E,
466
+ 0x066F, 0x0671, 0x0672, 0x0673, 0x0674, 0x0675, 0x0676, 0x0677, 0x0678,
467
+ 0x0679, 0x067A, 0x067B, 0x067C, 0x067D, 0x067E, 0x067F, 0x0680, 0x0681,
468
+ 0x0682, 0x0683, 0x0684, 0x0685, 0x0686, 0x0687, 0x0688, 0x0689, 0x068A,
469
+ 0x068B, 0x068C, 0x068D, 0x068E, 0x068F, 0x0690, 0x0691, 0x0692, 0x0693,
470
+ 0x0694, 0x0695, 0x0696, 0x0697, 0x0698, 0x0699, 0x069A, 0x069B, 0x069C,
471
+ 0x069D, 0x069E, 0x069F, 0x06A0, 0x06A1, 0x06A2, 0x06A3, 0x06A4, 0x06A5,
472
+ 0x06A6, 0x06A7, 0x06A8, 0x06A9, 0x06AA, 0x06AB, 0x06AC, 0x06AD, 0x06AE,
473
+ 0x06AF, 0x06B0, 0x06B1, 0x06B2, 0x06B3, 0x06B4, 0x06B5, 0x06B6, 0x06B7,
474
+ 0x06B8, 0x06B9, 0x06BA, 0x06BB, 0x06BC, 0x06BD, 0x06BE, 0x06BF, 0x06C0,
475
+ 0x06C1, 0x06C2, 0x06C3, 0x06C4, 0x06C5, 0x06C6, 0x06C7, 0x06C8, 0x06C9,
476
+ 0x06CA, 0x06CB, 0x06CC, 0x06CD, 0x06CE, 0x06CF, 0x06D0, 0x06D1, 0x06D2,
477
+ 0x06D3, 0x06D4, 0x06D5, 0x06E5, 0x06E6, 0x06EE, 0x06EF, 0x06FA, 0x06FB,
478
+ 0x06FC, 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, 0x0703, 0x0704,
479
+ 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, 0x070A, 0x070B, 0x070C, 0x070D,
480
+ 0x070F, 0x0710, 0x0712, 0x0713, 0x0714, 0x0715, 0x0716, 0x0717, 0x0718,
481
+ 0x0719, 0x071A, 0x071B, 0x071C, 0x071D, 0x071E, 0x071F, 0x0720, 0x0721,
482
+ 0x0722, 0x0723, 0x0724, 0x0725, 0x0726, 0x0727, 0x0728, 0x0729, 0x072A,
483
+ 0x072B, 0x072C, 0x072D, 0x072E, 0x072F, 0x074D, 0x074E, 0x074F, 0x0750,
484
+ 0x0751, 0x0752, 0x0753, 0x0754, 0x0755, 0x0756, 0x0757, 0x0758, 0x0759,
485
+ 0x075A, 0x075B, 0x075C, 0x075D, 0x075E, 0x075F, 0x0760, 0x0761, 0x0762,
486
+ 0x0763, 0x0764, 0x0765, 0x0766, 0x0767, 0x0768, 0x0769, 0x076A, 0x076B,
487
+ 0x076C, 0x076D, 0x076E, 0x076F, 0x0770, 0x0771, 0x0772, 0x0773, 0x0774,
488
+ 0x0775, 0x0776, 0x0777, 0x0778, 0x0779, 0x077A, 0x077B, 0x077C, 0x077D,
489
+ 0x077E, 0x077F, 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0786,
490
+ 0x0787, 0x0788, 0x0789, 0x078A, 0x078B, 0x078C, 0x078D, 0x078E, 0x078F,
491
+ 0x0790, 0x0791, 0x0792, 0x0793, 0x0794, 0x0795, 0x0796, 0x0797, 0x0798,
492
+ 0x0799, 0x079A, 0x079B, 0x079C, 0x079D, 0x079E, 0x079F, 0x07A0, 0x07A1,
493
+ 0x07A2, 0x07A3, 0x07A4, 0x07A5, 0x07B1, 0x07C0, 0x07C1, 0x07C2, 0x07C3,
494
+ 0x07C4, 0x07C5, 0x07C6, 0x07C7, 0x07C8, 0x07C9, 0x07CA, 0x07CB, 0x07CC,
495
+ 0x07CD, 0x07CE, 0x07CF, 0x07D0, 0x07D1, 0x07D2, 0x07D3, 0x07D4, 0x07D5,
496
+ 0x07D6, 0x07D7, 0x07D8, 0x07D9, 0x07DA, 0x07DB, 0x07DC, 0x07DD, 0x07DE,
497
+ 0x07DF, 0x07E0, 0x07E1, 0x07E2, 0x07E3, 0x07E4, 0x07E5, 0x07E6, 0x07E7,
498
+ 0x07E8, 0x07E9, 0x07EA, 0x07F4, 0x07F5, 0x07FA, 0x0800, 0x0801, 0x0802,
499
+ 0x0803, 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809, 0x080A, 0x080B,
500
+ 0x080C, 0x080D, 0x080E, 0x080F, 0x0810, 0x0811, 0x0812, 0x0813, 0x0814,
501
+ 0x0815, 0x081A, 0x0824, 0x0828, 0x0830, 0x0831, 0x0832, 0x0833, 0x0834,
502
+ 0x0835, 0x0836, 0x0837, 0x0838, 0x0839, 0x083A, 0x083B, 0x083C, 0x083D,
503
+ 0x083E, 0x0840, 0x0841, 0x0842, 0x0843, 0x0844, 0x0845, 0x0846, 0x0847,
504
+ 0x0848, 0x0849, 0x084A, 0x084B, 0x084C, 0x084D, 0x084E, 0x084F, 0x0850,
505
+ 0x0851, 0x0852, 0x0853, 0x0854, 0x0855, 0x0856, 0x0857, 0x0858, 0x085E,
506
+ 0x08A0, 0x08A2, 0x08A3, 0x08A4, 0x08A5, 0x08A6, 0x08A7, 0x08A8, 0x08A9,
507
+ 0x08AA, 0x08AB, 0x08AC, 0x200F, 0xFB1D, 0xFB1F, 0xFB20, 0xFB21, 0xFB22,
508
+ 0xFB23, 0xFB24, 0xFB25, 0xFB26, 0xFB27, 0xFB28, 0xFB2A, 0xFB2B, 0xFB2C,
509
+ 0xFB2D, 0xFB2E, 0xFB2F, 0xFB30, 0xFB31, 0xFB32, 0xFB33, 0xFB34, 0xFB35,
510
+ 0xFB36, 0xFB38, 0xFB39, 0xFB3A, 0xFB3B, 0xFB3C, 0xFB3E, 0xFB40, 0xFB41,
511
+ 0xFB43, 0xFB44, 0xFB46, 0xFB47, 0xFB48, 0xFB49, 0xFB4A, 0xFB4B, 0xFB4C,
512
+ 0xFB4D, 0xFB4E, 0xFB4F, 0xFB50, 0xFB51, 0xFB52, 0xFB53, 0xFB54, 0xFB55,
513
+ 0xFB56, 0xFB57, 0xFB58, 0xFB59, 0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D, 0xFB5E,
514
+ 0xFB5F, 0xFB60, 0xFB61, 0xFB62, 0xFB63, 0xFB64, 0xFB65, 0xFB66, 0xFB67,
515
+ 0xFB68, 0xFB69, 0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D, 0xFB6E, 0xFB6F, 0xFB70,
516
+ 0xFB71, 0xFB72, 0xFB73, 0xFB74, 0xFB75, 0xFB76, 0xFB77, 0xFB78, 0xFB79,
517
+ 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D, 0xFB7E, 0xFB7F, 0xFB80, 0xFB81, 0xFB82,
518
+ 0xFB83, 0xFB84, 0xFB85, 0xFB86, 0xFB87, 0xFB88, 0xFB89, 0xFB8A, 0xFB8B,
519
+ 0xFB8C, 0xFB8D, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, 0xFB92, 0xFB93, 0xFB94,
520
+ 0xFB95, 0xFB96, 0xFB97, 0xFB98, 0xFB99, 0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D,
521
+ 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3, 0xFBA4, 0xFBA5, 0xFBA6,
522
+ 0xFBA7, 0xFBA8, 0xFBA9, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD, 0xFBAE, 0xFBAF,
523
+ 0xFBB0, 0xFBB1, 0xFBB2, 0xFBB3, 0xFBB4, 0xFBB5, 0xFBB6, 0xFBB7, 0xFBB8,
524
+ 0xFBB9, 0xFBBA, 0xFBBB, 0xFBBC, 0xFBBD, 0xFBBE, 0xFBBF, 0xFBC0, 0xFBC1,
525
+ 0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6, 0xFBD7, 0xFBD8, 0xFBD9, 0xFBDA, 0xFBDB,
526
+ 0xFBDC, 0xFBDD, 0xFBDE, 0xFBDF, 0xFBE0, 0xFBE1, 0xFBE2, 0xFBE3, 0xFBE4,
527
+ 0xFBE5, 0xFBE6, 0xFBE7, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEB, 0xFBEC, 0xFBED,
528
+ 0xFBEE, 0xFBEF, 0xFBF0, 0xFBF1, 0xFBF2, 0xFBF3, 0xFBF4, 0xFBF5, 0xFBF6,
529
+ 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF,
530
+ 0xFC00, 0xFC01, 0xFC02, 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFC08,
531
+ 0xFC09, 0xFC0A, 0xFC0B, 0xFC0C, 0xFC0D, 0xFC0E, 0xFC0F, 0xFC10, 0xFC11,
532
+ 0xFC12, 0xFC13, 0xFC14, 0xFC15, 0xFC16, 0xFC17, 0xFC18, 0xFC19, 0xFC1A,
533
+ 0xFC1B, 0xFC1C, 0xFC1D, 0xFC1E, 0xFC1F, 0xFC20, 0xFC21, 0xFC22, 0xFC23,
534
+ 0xFC24, 0xFC25, 0xFC26, 0xFC27, 0xFC28, 0xFC29, 0xFC2A, 0xFC2B, 0xFC2C,
535
+ 0xFC2D, 0xFC2E, 0xFC2F, 0xFC30, 0xFC31, 0xFC32, 0xFC33, 0xFC34, 0xFC35,
536
+ 0xFC36, 0xFC37, 0xFC38, 0xFC39, 0xFC3A, 0xFC3B, 0xFC3C, 0xFC3D, 0xFC3E,
537
+ 0xFC3F, 0xFC40, 0xFC41, 0xFC42, 0xFC43, 0xFC44, 0xFC45, 0xFC46, 0xFC47,
538
+ 0xFC48, 0xFC49, 0xFC4A, 0xFC4B, 0xFC4C, 0xFC4D, 0xFC4E, 0xFC4F, 0xFC50,
539
+ 0xFC51, 0xFC52, 0xFC53, 0xFC54, 0xFC55, 0xFC56, 0xFC57, 0xFC58, 0xFC59,
540
+ 0xFC5A, 0xFC5B, 0xFC5C, 0xFC5D, 0xFC5E, 0xFC5F, 0xFC60, 0xFC61, 0xFC62,
541
+ 0xFC63, 0xFC64, 0xFC65, 0xFC66, 0xFC67, 0xFC68, 0xFC69, 0xFC6A, 0xFC6B,
542
+ 0xFC6C, 0xFC6D, 0xFC6E, 0xFC6F, 0xFC70, 0xFC71, 0xFC72, 0xFC73, 0xFC74,
543
+ 0xFC75, 0xFC76, 0xFC77, 0xFC78, 0xFC79, 0xFC7A, 0xFC7B, 0xFC7C, 0xFC7D,
544
+ 0xFC7E, 0xFC7F, 0xFC80, 0xFC81, 0xFC82, 0xFC83, 0xFC84, 0xFC85, 0xFC86,
545
+ 0xFC87, 0xFC88, 0xFC89, 0xFC8A, 0xFC8B, 0xFC8C, 0xFC8D, 0xFC8E, 0xFC8F,
546
+ 0xFC90, 0xFC91, 0xFC92, 0xFC93, 0xFC94, 0xFC95, 0xFC96, 0xFC97, 0xFC98,
547
+ 0xFC99, 0xFC9A, 0xFC9B, 0xFC9C, 0xFC9D, 0xFC9E, 0xFC9F, 0xFCA0, 0xFCA1,
548
+ 0xFCA2, 0xFCA3, 0xFCA4, 0xFCA5, 0xFCA6, 0xFCA7, 0xFCA8, 0xFCA9, 0xFCAA,
549
+ 0xFCAB, 0xFCAC, 0xFCAD, 0xFCAE, 0xFCAF, 0xFCB0, 0xFCB1, 0xFCB2, 0xFCB3,
550
+ 0xFCB4, 0xFCB5, 0xFCB6, 0xFCB7, 0xFCB8, 0xFCB9, 0xFCBA, 0xFCBB, 0xFCBC,
551
+ 0xFCBD, 0xFCBE, 0xFCBF, 0xFCC0, 0xFCC1, 0xFCC2, 0xFCC3, 0xFCC4, 0xFCC5,
552
+ 0xFCC6, 0xFCC7, 0xFCC8, 0xFCC9, 0xFCCA, 0xFCCB, 0xFCCC, 0xFCCD, 0xFCCE,
553
+ 0xFCCF, 0xFCD0, 0xFCD1, 0xFCD2, 0xFCD3, 0xFCD4, 0xFCD5, 0xFCD6, 0xFCD7,
554
+ 0xFCD8, 0xFCD9, 0xFCDA, 0xFCDB, 0xFCDC, 0xFCDD, 0xFCDE, 0xFCDF, 0xFCE0,
555
+ 0xFCE1, 0xFCE2, 0xFCE3, 0xFCE4, 0xFCE5, 0xFCE6, 0xFCE7, 0xFCE8, 0xFCE9,
556
+ 0xFCEA, 0xFCEB, 0xFCEC, 0xFCED, 0xFCEE, 0xFCEF, 0xFCF0, 0xFCF1, 0xFCF2,
557
+ 0xFCF3, 0xFCF4, 0xFCF5, 0xFCF6, 0xFCF7, 0xFCF8, 0xFCF9, 0xFCFA, 0xFCFB,
558
+ 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, 0xFD00, 0xFD01, 0xFD02, 0xFD03, 0xFD04,
559
+ 0xFD05, 0xFD06, 0xFD07, 0xFD08, 0xFD09, 0xFD0A, 0xFD0B, 0xFD0C, 0xFD0D,
560
+ 0xFD0E, 0xFD0F, 0xFD10, 0xFD11, 0xFD12, 0xFD13, 0xFD14, 0xFD15, 0xFD16,
561
+ 0xFD17, 0xFD18, 0xFD19, 0xFD1A, 0xFD1B, 0xFD1C, 0xFD1D, 0xFD1E, 0xFD1F,
562
+ 0xFD20, 0xFD21, 0xFD22, 0xFD23, 0xFD24, 0xFD25, 0xFD26, 0xFD27, 0xFD28,
563
+ 0xFD29, 0xFD2A, 0xFD2B, 0xFD2C, 0xFD2D, 0xFD2E, 0xFD2F, 0xFD30, 0xFD31,
564
+ 0xFD32, 0xFD33, 0xFD34, 0xFD35, 0xFD36, 0xFD37, 0xFD38, 0xFD39, 0xFD3A,
565
+ 0xFD3B, 0xFD3C, 0xFD3D, 0xFD50, 0xFD51, 0xFD52, 0xFD53, 0xFD54, 0xFD55,
566
+ 0xFD56, 0xFD57, 0xFD58, 0xFD59, 0xFD5A, 0xFD5B, 0xFD5C, 0xFD5D, 0xFD5E,
567
+ 0xFD5F, 0xFD60, 0xFD61, 0xFD62, 0xFD63, 0xFD64, 0xFD65, 0xFD66, 0xFD67,
568
+ 0xFD68, 0xFD69, 0xFD6A, 0xFD6B, 0xFD6C, 0xFD6D, 0xFD6E, 0xFD6F, 0xFD70,
569
+ 0xFD71, 0xFD72, 0xFD73, 0xFD74, 0xFD75, 0xFD76, 0xFD77, 0xFD78, 0xFD79,
570
+ 0xFD7A, 0xFD7B, 0xFD7C, 0xFD7D, 0xFD7E, 0xFD7F, 0xFD80, 0xFD81, 0xFD82,
571
+ 0xFD83, 0xFD84, 0xFD85, 0xFD86, 0xFD87, 0xFD88, 0xFD89, 0xFD8A, 0xFD8B,
572
+ 0xFD8C, 0xFD8D, 0xFD8E, 0xFD8F, 0xFD92, 0xFD93, 0xFD94, 0xFD95, 0xFD96,
573
+ 0xFD97, 0xFD98, 0xFD99, 0xFD9A, 0xFD9B, 0xFD9C, 0xFD9D, 0xFD9E, 0xFD9F,
574
+ 0xFDA0, 0xFDA1, 0xFDA2, 0xFDA3, 0xFDA4, 0xFDA5, 0xFDA6, 0xFDA7, 0xFDA8,
575
+ 0xFDA9, 0xFDAA, 0xFDAB, 0xFDAC, 0xFDAD, 0xFDAE, 0xFDAF, 0xFDB0, 0xFDB1,
576
+ 0xFDB2, 0xFDB3, 0xFDB4, 0xFDB5, 0xFDB6, 0xFDB7, 0xFDB8, 0xFDB9, 0xFDBA,
577
+ 0xFDBB, 0xFDBC, 0xFDBD, 0xFDBE, 0xFDBF, 0xFDC0, 0xFDC1, 0xFDC2, 0xFDC3,
578
+ 0xFDC4, 0xFDC5, 0xFDC6, 0xFDC7, 0xFDF0, 0xFDF1, 0xFDF2, 0xFDF3, 0xFDF4,
579
+ 0xFDF5, 0xFDF6, 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, 0xFDFB, 0xFDFC, 0xFE70,
580
+ 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE76, 0xFE77, 0xFE78, 0xFE79, 0xFE7A,
581
+ 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F, 0xFE80, 0xFE81, 0xFE82, 0xFE83,
582
+ 0xFE84, 0xFE85, 0xFE86, 0xFE87, 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C,
583
+ 0xFE8D, 0xFE8E, 0xFE8F, 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95,
584
+ 0xFE96, 0xFE97, 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E,
585
+ 0xFE9F, 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7,
586
+ 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF, 0xFEB0,
587
+ 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, 0xFEB9,
588
+ 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0, 0xFEC1, 0xFEC2,
589
+ 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, 0xFEC9, 0xFECA, 0xFECB,
590
+ 0xFECC, 0xFECD, 0xFECE, 0xFECF, 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4,
591
+ 0xFED5, 0xFED6, 0xFED7, 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD,
592
+ 0xFEDE, 0xFEDF, 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6,
593
+ 0xFEE7, 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF,
594
+ 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, 0xFEF8,
595
+ 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0x10800, 0x10801, 0x10802, 0x10803,
596
+ 0x10804, 0x10805, 0x10808, 0x1080A, 0x1080B, 0x1080C, 0x1080D, 0x1080E,
597
+ 0x1080F, 0x10810, 0x10811, 0x10812, 0x10813, 0x10814, 0x10815, 0x10816,
598
+ 0x10817, 0x10818, 0x10819, 0x1081A, 0x1081B, 0x1081C, 0x1081D, 0x1081E,
599
+ 0x1081F, 0x10820, 0x10821, 0x10822, 0x10823, 0x10824, 0x10825, 0x10826,
600
+ 0x10827, 0x10828, 0x10829, 0x1082A, 0x1082B, 0x1082C, 0x1082D, 0x1082E,
601
+ 0x1082F, 0x10830, 0x10831, 0x10832, 0x10833, 0x10834, 0x10835, 0x10837,
602
+ 0x10838, 0x1083C, 0x1083F, 0x10840, 0x10841, 0x10842, 0x10843, 0x10844,
603
+ 0x10845, 0x10846, 0x10847, 0x10848, 0x10849, 0x1084A, 0x1084B, 0x1084C,
604
+ 0x1084D, 0x1084E, 0x1084F, 0x10850, 0x10851, 0x10852, 0x10853, 0x10854,
605
+ 0x10855, 0x10857, 0x10858, 0x10859, 0x1085A, 0x1085B, 0x1085C, 0x1085D,
606
+ 0x1085E, 0x1085F, 0x10900, 0x10901, 0x10902, 0x10903, 0x10904, 0x10905,
607
+ 0x10906, 0x10907, 0x10908, 0x10909, 0x1090A, 0x1090B, 0x1090C, 0x1090D,
608
+ 0x1090E, 0x1090F, 0x10910, 0x10911, 0x10912, 0x10913, 0x10914, 0x10915,
609
+ 0x10916, 0x10917, 0x10918, 0x10919, 0x1091A, 0x1091B, 0x10920, 0x10921,
610
+ 0x10922, 0x10923, 0x10924, 0x10925, 0x10926, 0x10927, 0x10928, 0x10929,
611
+ 0x1092A, 0x1092B, 0x1092C, 0x1092D, 0x1092E, 0x1092F, 0x10930, 0x10931,
612
+ 0x10932, 0x10933, 0x10934, 0x10935, 0x10936, 0x10937, 0x10938, 0x10939,
613
+ 0x1093F, 0x10980, 0x10981, 0x10982, 0x10983, 0x10984, 0x10985, 0x10986,
614
+ 0x10987, 0x10988, 0x10989, 0x1098A, 0x1098B, 0x1098C, 0x1098D, 0x1098E,
615
+ 0x1098F, 0x10990, 0x10991, 0x10992, 0x10993, 0x10994, 0x10995, 0x10996,
616
+ 0x10997, 0x10998, 0x10999, 0x1099A, 0x1099B, 0x1099C, 0x1099D, 0x1099E,
617
+ 0x1099F, 0x109A0, 0x109A1, 0x109A2, 0x109A3, 0x109A4, 0x109A5, 0x109A6,
618
+ 0x109A7, 0x109A8, 0x109A9, 0x109AA, 0x109AB, 0x109AC, 0x109AD, 0x109AE,
619
+ 0x109AF, 0x109B0, 0x109B1, 0x109B2, 0x109B3, 0x109B4, 0x109B5, 0x109B6,
620
+ 0x109B7, 0x109BE, 0x109BF, 0x10A00, 0x10A10, 0x10A11, 0x10A12, 0x10A13,
621
+ 0x10A15, 0x10A16, 0x10A17, 0x10A19, 0x10A1A, 0x10A1B, 0x10A1C, 0x10A1D,
622
+ 0x10A1E, 0x10A1F, 0x10A20, 0x10A21, 0x10A22, 0x10A23, 0x10A24, 0x10A25,
623
+ 0x10A26, 0x10A27, 0x10A28, 0x10A29, 0x10A2A, 0x10A2B, 0x10A2C, 0x10A2D,
624
+ 0x10A2E, 0x10A2F, 0x10A30, 0x10A31, 0x10A32, 0x10A33, 0x10A40, 0x10A41,
625
+ 0x10A42, 0x10A43, 0x10A44, 0x10A45, 0x10A46, 0x10A47, 0x10A50, 0x10A51,
626
+ 0x10A52, 0x10A53, 0x10A54, 0x10A55, 0x10A56, 0x10A57, 0x10A58, 0x10A60,
627
+ 0x10A61, 0x10A62, 0x10A63, 0x10A64, 0x10A65, 0x10A66, 0x10A67, 0x10A68,
628
+ 0x10A69, 0x10A6A, 0x10A6B, 0x10A6C, 0x10A6D, 0x10A6E, 0x10A6F, 0x10A70,
629
+ 0x10A71, 0x10A72, 0x10A73, 0x10A74, 0x10A75, 0x10A76, 0x10A77, 0x10A78,
630
+ 0x10A79, 0x10A7A, 0x10A7B, 0x10A7C, 0x10A7D, 0x10A7E, 0x10A7F, 0x10B00,
631
+ 0x10B01, 0x10B02, 0x10B03, 0x10B04, 0x10B05, 0x10B06, 0x10B07, 0x10B08,
632
+ 0x10B09, 0x10B0A, 0x10B0B, 0x10B0C, 0x10B0D, 0x10B0E, 0x10B0F, 0x10B10,
633
+ 0x10B11, 0x10B12, 0x10B13, 0x10B14, 0x10B15, 0x10B16, 0x10B17, 0x10B18,
634
+ 0x10B19, 0x10B1A, 0x10B1B, 0x10B1C, 0x10B1D, 0x10B1E, 0x10B1F, 0x10B20,
635
+ 0x10B21, 0x10B22, 0x10B23, 0x10B24, 0x10B25, 0x10B26, 0x10B27, 0x10B28,
636
+ 0x10B29, 0x10B2A, 0x10B2B, 0x10B2C, 0x10B2D, 0x10B2E, 0x10B2F, 0x10B30,
637
+ 0x10B31, 0x10B32, 0x10B33, 0x10B34, 0x10B35, 0x10B40, 0x10B41, 0x10B42,
638
+ 0x10B43, 0x10B44, 0x10B45, 0x10B46, 0x10B47, 0x10B48, 0x10B49, 0x10B4A,
639
+ 0x10B4B, 0x10B4C, 0x10B4D, 0x10B4E, 0x10B4F, 0x10B50, 0x10B51, 0x10B52,
640
+ 0x10B53, 0x10B54, 0x10B55, 0x10B58, 0x10B59, 0x10B5A, 0x10B5B, 0x10B5C,
641
+ 0x10B5D, 0x10B5E, 0x10B5F, 0x10B60, 0x10B61, 0x10B62, 0x10B63, 0x10B64,
642
+ 0x10B65, 0x10B66, 0x10B67, 0x10B68, 0x10B69, 0x10B6A, 0x10B6B, 0x10B6C,
643
+ 0x10B6D, 0x10B6E, 0x10B6F, 0x10B70, 0x10B71, 0x10B72, 0x10B78, 0x10B79,
644
+ 0x10B7A, 0x10B7B, 0x10B7C, 0x10B7D, 0x10B7E, 0x10B7F, 0x10C00, 0x10C01,
645
+ 0x10C02, 0x10C03, 0x10C04, 0x10C05, 0x10C06, 0x10C07, 0x10C08, 0x10C09,
646
+ 0x10C0A, 0x10C0B, 0x10C0C, 0x10C0D, 0x10C0E, 0x10C0F, 0x10C10, 0x10C11,
647
+ 0x10C12, 0x10C13, 0x10C14, 0x10C15, 0x10C16, 0x10C17, 0x10C18, 0x10C19,
648
+ 0x10C1A, 0x10C1B, 0x10C1C, 0x10C1D, 0x10C1E, 0x10C1F, 0x10C20, 0x10C21,
649
+ 0x10C22, 0x10C23, 0x10C24, 0x10C25, 0x10C26, 0x10C27, 0x10C28, 0x10C29,
650
+ 0x10C2A, 0x10C2B, 0x10C2C, 0x10C2D, 0x10C2E, 0x10C2F, 0x10C30, 0x10C31,
651
+ 0x10C32, 0x10C33, 0x10C34, 0x10C35, 0x10C36, 0x10C37, 0x10C38, 0x10C39,
652
+ 0x10C3A, 0x10C3B, 0x10C3C, 0x10C3D, 0x10C3E, 0x10C3F, 0x10C40, 0x10C41,
653
+ 0x10C42, 0x10C43, 0x10C44, 0x10C45, 0x10C46, 0x10C47, 0x10C48, 0x1EE00,
654
+ 0x1EE01, 0x1EE02, 0x1EE03, 0x1EE05, 0x1EE06, 0x1EE07, 0x1EE08, 0x1EE09,
655
+ 0x1EE0A, 0x1EE0B, 0x1EE0C, 0x1EE0D, 0x1EE0E, 0x1EE0F, 0x1EE10, 0x1EE11,
656
+ 0x1EE12, 0x1EE13, 0x1EE14, 0x1EE15, 0x1EE16, 0x1EE17, 0x1EE18, 0x1EE19,
657
+ 0x1EE1A, 0x1EE1B, 0x1EE1C, 0x1EE1D, 0x1EE1E, 0x1EE1F, 0x1EE21, 0x1EE22,
658
+ 0x1EE24, 0x1EE27, 0x1EE29, 0x1EE2A, 0x1EE2B, 0x1EE2C, 0x1EE2D, 0x1EE2E,
659
+ 0x1EE2F, 0x1EE30, 0x1EE31, 0x1EE32, 0x1EE34, 0x1EE35, 0x1EE36, 0x1EE37,
660
+ 0x1EE39, 0x1EE3B, 0x1EE42, 0x1EE47, 0x1EE49, 0x1EE4B, 0x1EE4D, 0x1EE4E,
661
+ 0x1EE4F, 0x1EE51, 0x1EE52, 0x1EE54, 0x1EE57, 0x1EE59, 0x1EE5B, 0x1EE5D,
662
+ 0x1EE5F, 0x1EE61, 0x1EE62, 0x1EE64, 0x1EE67, 0x1EE68, 0x1EE69, 0x1EE6A,
663
+ 0x1EE6C, 0x1EE6D, 0x1EE6E, 0x1EE6F, 0x1EE70, 0x1EE71, 0x1EE72, 0x1EE74,
664
+ 0x1EE75, 0x1EE76, 0x1EE77, 0x1EE79, 0x1EE7A, 0x1EE7B, 0x1EE7C, 0x1EE7E,
665
+ 0x1EE80, 0x1EE81, 0x1EE82, 0x1EE83, 0x1EE84, 0x1EE85, 0x1EE86, 0x1EE87,
666
+ 0x1EE88, 0x1EE89, 0x1EE8B, 0x1EE8C, 0x1EE8D, 0x1EE8E, 0x1EE8F, 0x1EE90,
667
+ 0x1EE91, 0x1EE92, 0x1EE93, 0x1EE94, 0x1EE95, 0x1EE96, 0x1EE97, 0x1EE98,
668
+ 0x1EE99, 0x1EE9A, 0x1EE9B, 0x1EEA1, 0x1EEA2, 0x1EEA3, 0x1EEA5, 0x1EEA6,
669
+ 0x1EEA7, 0x1EEA8, 0x1EEA9, 0x1EEAB, 0x1EEAC, 0x1EEAD, 0x1EEAE, 0x1EEAF,
670
+ 0x1EEB0, 0x1EEB1, 0x1EEB2, 0x1EEB3, 0x1EEB4, 0x1EEB5, 0x1EEB6, 0x1EEB7,
671
+ 0x1EEB8, 0x1EEB9, 0x1EEBA, 0x1EEBB, 0x10FFFD];
672
+
673
+ function determineBidi(cueDiv) {
674
+ var nodeStack = [],
675
+ text = "",
676
+ charCode;
677
+
678
+ if (!cueDiv || !cueDiv.childNodes) {
679
+ return "ltr";
680
+ }
681
+
682
+ function pushNodes(nodeStack, node) {
683
+ for (var i = node.childNodes.length - 1; i >= 0; i--) {
684
+ nodeStack.push(node.childNodes[i]);
685
+ }
686
+ }
687
+
688
+ function nextTextNode(nodeStack) {
689
+ if (!nodeStack || !nodeStack.length) {
690
+ return null;
691
+ }
692
+
693
+ var node = nodeStack.pop(),
694
+ text = node.textContent || node.innerText;
695
+ if (text) {
696
+ // TODO: This should match all unicode type B characters (paragraph
697
+ // separator characters). See issue #115.
698
+ var m = text.match(/^.*(\n|\r)/);
699
+ if (m) {
700
+ nodeStack.length = 0;
701
+ return m[0];
702
+ }
703
+ return text;
704
+ }
705
+ if (node.tagName === "ruby") {
706
+ return nextTextNode(nodeStack);
707
+ }
708
+ if (node.childNodes) {
709
+ pushNodes(nodeStack, node);
710
+ return nextTextNode(nodeStack);
711
+ }
712
+ }
713
+
714
+ pushNodes(nodeStack, cueDiv);
715
+ while ((text = nextTextNode(nodeStack))) {
716
+ for (var i = 0; i < text.length; i++) {
717
+ charCode = text.charCodeAt(i);
718
+ for (var j = 0; j < strongRTLChars.length; j++) {
719
+ if (strongRTLChars[j] === charCode) {
720
+ return "rtl";
721
+ }
722
+ }
723
+ }
724
+ }
725
+ return "ltr";
726
+ }
727
+
728
+ function computeLinePos(cue) {
729
+ if (typeof cue.line === "number" &&
730
+ (cue.snapToLines || (cue.line >= 0 && cue.line <= 100))) {
731
+ return cue.line;
732
+ }
733
+ if (!cue.track || !cue.track.textTrackList ||
734
+ !cue.track.textTrackList.mediaElement) {
735
+ return -1;
736
+ }
737
+ var track = cue.track,
738
+ trackList = track.textTrackList,
739
+ count = 0;
740
+ for (var i = 0; i < trackList.length && trackList[i] !== track; i++) {
741
+ if (trackList[i].mode === "showing") {
742
+ count++;
743
+ }
744
+ }
745
+ return ++count * -1;
746
+ }
747
+
748
+ function StyleBox() {
749
+ }
750
+
751
+ // Apply styles to a div. If there is no div passed then it defaults to the
752
+ // div on 'this'.
753
+ StyleBox.prototype.applyStyles = function(styles, div) {
754
+ div = div || this.div;
755
+ for (var prop in styles) {
756
+ if (styles.hasOwnProperty(prop)) {
757
+ div.style[prop] = styles[prop];
758
+ }
759
+ }
760
+ };
761
+
762
+ StyleBox.prototype.formatStyle = function(val, unit) {
763
+ return val === 0 ? 0 : val + unit;
764
+ };
765
+
766
+ // Constructs the computed display state of the cue (a div). Places the div
767
+ // into the overlay which should be a block level element (usually a div).
768
+ function CueStyleBox(window, cue, styleOptions) {
769
+ var isIE8 = (typeof navigator !== "undefined") &&
770
+ (/MSIE\s8\.0/).test(navigator.userAgent);
771
+ var color = "rgba(255, 255, 255, 1)";
772
+ var backgroundColor = "rgba(0, 0, 0, 0.8)";
773
+ var textShadow = "";
774
+
775
+ if(typeof WebVTTSet !== "undefined") {
776
+ color = WebVTTSet.fontSet;
777
+ backgroundColor = WebVTTSet.backgroundSet;
778
+ textShadow = WebVTTSet.edgeSet;
779
+ }
780
+
781
+ if (isIE8) {
782
+ color = "rgb(255, 255, 255)";
783
+ backgroundColor = "rgb(0, 0, 0)";
784
+ }
785
+
786
+ StyleBox.call(this);
787
+ this.cue = cue;
788
+
789
+ // Parse our cue's text into a DOM tree rooted at 'cueDiv'. This div will
790
+ // have inline positioning and will function as the cue background box.
791
+ this.cueDiv = parseContent(window, cue.text);
792
+ var styles = {
793
+ color: color,
794
+ backgroundColor: backgroundColor,
795
+ textShadow: textShadow,
796
+ position: "relative",
797
+ left: 0,
798
+ right: 0,
799
+ top: 0,
800
+ bottom: 0,
801
+ display: "inline"
802
+ };
803
+
804
+ if (!isIE8) {
805
+ styles.writingMode = cue.vertical === "" ? "horizontal-tb"
806
+ : cue.vertical === "lr" ? "vertical-lr"
807
+ : "vertical-rl";
808
+ styles.unicodeBidi = "plaintext";
809
+ }
810
+ this.applyStyles(styles, this.cueDiv);
811
+
812
+ // Create an absolutely positioned div that will be used to position the cue
813
+ // div. Note, all WebVTT cue-setting alignments are equivalent to the CSS
814
+ // mirrors of them except "middle" which is "center" in CSS.
815
+ this.div = window.document.createElement("div");
816
+ styles = {
817
+ textAlign: cue.align === "middle" ? "center" : cue.align,
818
+ font: styleOptions.font,
819
+ whiteSpace: "pre-line",
820
+ position: "absolute"
821
+ };
822
+
823
+ if (!isIE8) {
824
+ styles.direction = determineBidi(this.cueDiv);
825
+ styles.writingMode = cue.vertical === "" ? "horizontal-tb"
826
+ : cue.vertical === "lr" ? "vertical-lr"
827
+ : "vertical-rl".
828
+ stylesunicodeBidi = "plaintext";
829
+ }
830
+
831
+ this.applyStyles(styles);
832
+
833
+ this.div.appendChild(this.cueDiv);
834
+
835
+ // Calculate the distance from the reference edge of the viewport to the text
836
+ // position of the cue box. The reference edge will be resolved later when
837
+ // the box orientation styles are applied.
838
+ var textPos = 0;
839
+ switch (cue.positionAlign) {
840
+ case "start":
841
+ textPos = cue.position;
842
+ break;
843
+ case "middle":
844
+ textPos = cue.position - (cue.size / 2);
845
+ break;
846
+ case "end":
847
+ textPos = cue.position - cue.size;
848
+ break;
849
+ }
850
+
851
+ // Horizontal box orientation; textPos is the distance from the left edge of the
852
+ // area to the left edge of the box and cue.size is the distance extending to
853
+ // the right from there.
854
+ if (cue.vertical === "") {
855
+ this.applyStyles({
856
+ left: this.formatStyle(textPos, "%"),
857
+ width: this.formatStyle(cue.size, "%")
858
+ });
859
+ // Vertical box orientation; textPos is the distance from the top edge of the
860
+ // area to the top edge of the box and cue.size is the height extending
861
+ // downwards from there.
862
+ } else {
863
+ this.applyStyles({
864
+ top: this.formatStyle(textPos, "%"),
865
+ height: this.formatStyle(cue.size, "%")
866
+ });
867
+ }
868
+
869
+ this.move = function(box) {
870
+ this.applyStyles({
871
+ top: this.formatStyle(box.top, "px"),
872
+ bottom: this.formatStyle(box.bottom, "px"),
873
+ left: this.formatStyle(box.left, "px"),
874
+ right: this.formatStyle(box.right, "px"),
875
+ height: this.formatStyle(box.height, "px"),
876
+ width: this.formatStyle(box.width, "px")
877
+ });
878
+ };
879
+ }
880
+ CueStyleBox.prototype = _objCreate(StyleBox.prototype);
881
+ CueStyleBox.prototype.constructor = CueStyleBox;
882
+
883
+ // Represents the co-ordinates of an Element in a way that we can easily
884
+ // compute things with such as if it overlaps or intersects with another Element.
885
+ // Can initialize it with either a StyleBox or another BoxPosition.
886
+ function BoxPosition(obj) {
887
+ var isIE8 = (typeof navigator !== "undefined") &&
888
+ (/MSIE\s8\.0/).test(navigator.userAgent);
889
+
890
+ // Either a BoxPosition was passed in and we need to copy it, or a StyleBox
891
+ // was passed in and we need to copy the results of 'getBoundingClientRect'
892
+ // as the object returned is readonly. All co-ordinate values are in reference
893
+ // to the viewport origin (top left).
894
+ var lh, height, width, top;
895
+ if (obj.div) {
896
+ height = obj.div.offsetHeight;
897
+ width = obj.div.offsetWidth;
898
+ top = obj.div.offsetTop;
899
+
900
+ var rects = (rects = obj.div.childNodes) && (rects = rects[0]) &&
901
+ rects.getClientRects && rects.getClientRects();
902
+ obj = obj.div.getBoundingClientRect();
903
+ // In certain cases the outter div will be slightly larger then the sum of
904
+ // the inner div's lines. This could be due to bold text, etc, on some platforms.
905
+ // In this case we should get the average line height and use that. This will
906
+ // result in the desired behaviour.
907
+ lh = rects ? Math.max((rects[0] && rects[0].height) || 0, obj.height / rects.length)
908
+ : 0;
909
+
910
+ }
911
+ this.left = obj.left;
912
+ this.right = obj.right;
913
+ this.top = obj.top || top;
914
+ this.height = obj.height || height;
915
+ this.bottom = obj.bottom || (top + (obj.height || height));
916
+ this.width = obj.width || width;
917
+ this.lineHeight = lh !== undefined ? lh : obj.lineHeight;
918
+
919
+ if (isIE8 && !this.lineHeight) {
920
+ this.lineHeight = 13;
921
+ }
922
+ }
923
+
924
+ // Move the box along a particular axis. Optionally pass in an amount to move
925
+ // the box. If no amount is passed then the default is the line height of the
926
+ // box.
927
+ BoxPosition.prototype.move = function(axis, toMove) {
928
+ toMove = toMove !== undefined ? toMove : this.lineHeight;
929
+ switch (axis) {
930
+ case "+x":
931
+ this.left += toMove;
932
+ this.right += toMove;
933
+ break;
934
+ case "-x":
935
+ this.left -= toMove;
936
+ this.right -= toMove;
937
+ break;
938
+ case "+y":
939
+ this.top += toMove;
940
+ this.bottom += toMove;
941
+ break;
942
+ case "-y":
943
+ this.top -= toMove;
944
+ this.bottom -= toMove;
945
+ break;
946
+ }
947
+ };
948
+
949
+ // Check if this box overlaps another box, b2.
950
+ BoxPosition.prototype.overlaps = function(b2) {
951
+ return this.left < b2.right &&
952
+ this.right > b2.left &&
953
+ this.top < b2.bottom &&
954
+ this.bottom > b2.top;
955
+ };
956
+
957
+ // Check if this box overlaps any other boxes in boxes.
958
+ BoxPosition.prototype.overlapsAny = function(boxes) {
959
+ for (var i = 0; i < boxes.length; i++) {
960
+ if (this.overlaps(boxes[i])) {
961
+ return true;
962
+ }
963
+ }
964
+ return false;
965
+ };
966
+
967
+ // Check if this box is within another box.
968
+ BoxPosition.prototype.within = function(container) {
969
+ return this.top >= container.top &&
970
+ this.bottom <= container.bottom &&
971
+ this.left >= container.left &&
972
+ this.right <= container.right;
973
+ };
974
+
975
+ // Check if this box is entirely within the container or it is overlapping
976
+ // on the edge opposite of the axis direction passed. For example, if "+x" is
977
+ // passed and the box is overlapping on the left edge of the container, then
978
+ // return true.
979
+ BoxPosition.prototype.overlapsOppositeAxis = function(container, axis) {
980
+ switch (axis) {
981
+ case "+x":
982
+ return this.left < container.left;
983
+ case "-x":
984
+ return this.right > container.right;
985
+ case "+y":
986
+ return this.top < container.top;
987
+ case "-y":
988
+ return this.bottom > container.bottom;
989
+ }
990
+ };
991
+
992
+ // Find the percentage of the area that this box is overlapping with another
993
+ // box.
994
+ BoxPosition.prototype.intersectPercentage = function(b2) {
995
+ var x = Math.max(0, Math.min(this.right, b2.right) - Math.max(this.left, b2.left)),
996
+ y = Math.max(0, Math.min(this.bottom, b2.bottom) - Math.max(this.top, b2.top)),
997
+ intersectArea = x * y;
998
+ return intersectArea / (this.height * this.width);
999
+ };
1000
+
1001
+ // Convert the positions from this box to CSS compatible positions using
1002
+ // the reference container's positions. This has to be done because this
1003
+ // box's positions are in reference to the viewport origin, whereas, CSS
1004
+ // values are in referecne to their respective edges.
1005
+ BoxPosition.prototype.toCSSCompatValues = function(reference) {
1006
+ return {
1007
+ top: this.top - reference.top,
1008
+ bottom: reference.bottom - this.bottom,
1009
+ left: this.left - reference.left,
1010
+ right: reference.right - this.right,
1011
+ height: this.height,
1012
+ width: this.width
1013
+ };
1014
+ };
1015
+
1016
+ // Get an object that represents the box's position without anything extra.
1017
+ // Can pass a StyleBox, HTMLElement, or another BoxPositon.
1018
+ BoxPosition.getSimpleBoxPosition = function(obj) {
1019
+ var height = obj.div ? obj.div.offsetHeight : obj.tagName ? obj.offsetHeight : 0;
1020
+ var width = obj.div ? obj.div.offsetWidth : obj.tagName ? obj.offsetWidth : 0;
1021
+ var top = obj.div ? obj.div.offsetTop : obj.tagName ? obj.offsetTop : 0;
1022
+
1023
+ obj = obj.div ? obj.div.getBoundingClientRect() :
1024
+ obj.tagName ? obj.getBoundingClientRect() : obj;
1025
+ var ret = {
1026
+ left: obj.left,
1027
+ right: obj.right,
1028
+ top: obj.top || top,
1029
+ height: obj.height || height,
1030
+ bottom: obj.bottom || (top + (obj.height || height)),
1031
+ width: obj.width || width
1032
+ };
1033
+ return ret;
1034
+ };
1035
+
1036
+ // Move a StyleBox to its specified, or next best, position. The containerBox
1037
+ // is the box that contains the StyleBox, such as a div. boxPositions are
1038
+ // a list of other boxes that the styleBox can't overlap with.
1039
+ function moveBoxToLinePosition(window, styleBox, containerBox, boxPositions) {
1040
+
1041
+ // Find the best position for a cue box, b, on the video. The axis parameter
1042
+ // is a list of axis, the order of which, it will move the box along. For example:
1043
+ // Passing ["+x", "-x"] will move the box first along the x axis in the positive
1044
+ // direction. If it doesn't find a good position for it there it will then move
1045
+ // it along the x axis in the negative direction.
1046
+ function findBestPosition(b, axis) {
1047
+ var bestPosition,
1048
+ specifiedPosition = new BoxPosition(b),
1049
+ percentage = 1; // Highest possible so the first thing we get is better.
1050
+
1051
+ for (var i = 0; i < axis.length; i++) {
1052
+ while (b.overlapsOppositeAxis(containerBox, axis[i]) ||
1053
+ (b.within(containerBox) && b.overlapsAny(boxPositions))) {
1054
+ b.move(axis[i]);
1055
+ }
1056
+ // We found a spot where we aren't overlapping anything. This is our
1057
+ // best position.
1058
+ if (b.within(containerBox)) {
1059
+ return b;
1060
+ }
1061
+ var p = b.intersectPercentage(containerBox);
1062
+ // If we're outside the container box less then we were on our last try
1063
+ // then remember this position as the best position.
1064
+ if (percentage > p) {
1065
+ bestPosition = new BoxPosition(b);
1066
+ percentage = p;
1067
+ }
1068
+ // Reset the box position to the specified position.
1069
+ b = new BoxPosition(specifiedPosition);
1070
+ }
1071
+ return bestPosition || specifiedPosition;
1072
+ }
1073
+
1074
+ var boxPosition = new BoxPosition(styleBox),
1075
+ cue = styleBox.cue,
1076
+ linePos = computeLinePos(cue),
1077
+ axis = [];
1078
+
1079
+ // If we have a line number to align the cue to.
1080
+ if (cue.snapToLines) {
1081
+ var size;
1082
+ switch (cue.vertical) {
1083
+ case "":
1084
+ axis = [ "+y", "-y" ];
1085
+ size = "height";
1086
+ break;
1087
+ case "rl":
1088
+ axis = [ "+x", "-x" ];
1089
+ size = "width";
1090
+ break;
1091
+ case "lr":
1092
+ axis = [ "-x", "+x" ];
1093
+ size = "width";
1094
+ break;
1095
+ }
1096
+
1097
+ var step = boxPosition.lineHeight,
1098
+ position = step * Math.round(linePos),
1099
+ maxPosition = containerBox[size] + step,
1100
+ initialAxis = axis[0];
1101
+
1102
+ // If the specified intial position is greater then the max position then
1103
+ // clamp the box to the amount of steps it would take for the box to
1104
+ // reach the max position.
1105
+ if (Math.abs(position) > maxPosition) {
1106
+ position = position < 0 ? -1 : 1;
1107
+ position *= Math.ceil(maxPosition / step) * step;
1108
+ }
1109
+
1110
+ // If computed line position returns negative then line numbers are
1111
+ // relative to the bottom of the video instead of the top. Therefore, we
1112
+ // need to increase our initial position by the length or width of the
1113
+ // video, depending on the writing direction, and reverse our axis directions.
1114
+ if (linePos < 0) {
1115
+ position += cue.vertical === "" ? containerBox.height : containerBox.width;
1116
+ axis = axis.reverse();
1117
+ }
1118
+
1119
+ // Move the box to the specified position. This may not be its best
1120
+ // position.
1121
+ boxPosition.move(initialAxis, position);
1122
+
1123
+ } else {
1124
+ // If we have a percentage line value for the cue.
1125
+ var calculatedPercentage = (boxPosition.lineHeight / containerBox.height) * 100;
1126
+
1127
+ switch (cue.lineAlign) {
1128
+ case "middle":
1129
+ linePos -= (calculatedPercentage / 2);
1130
+ break;
1131
+ case "end":
1132
+ linePos -= calculatedPercentage;
1133
+ break;
1134
+ }
1135
+
1136
+ // Apply initial line position to the cue box.
1137
+ switch (cue.vertical) {
1138
+ case "":
1139
+ styleBox.applyStyles({
1140
+ top: styleBox.formatStyle(linePos, "%")
1141
+ });
1142
+ break;
1143
+ case "rl":
1144
+ styleBox.applyStyles({
1145
+ left: styleBox.formatStyle(linePos, "%")
1146
+ });
1147
+ break;
1148
+ case "lr":
1149
+ styleBox.applyStyles({
1150
+ right: styleBox.formatStyle(linePos, "%")
1151
+ });
1152
+ break;
1153
+ }
1154
+
1155
+ axis = [ "+y", "-x", "+x", "-y" ];
1156
+
1157
+ // Get the box position again after we've applied the specified positioning
1158
+ // to it.
1159
+ boxPosition = new BoxPosition(styleBox);
1160
+ }
1161
+
1162
+ var bestPosition = findBestPosition(boxPosition, axis);
1163
+ styleBox.move(bestPosition.toCSSCompatValues(containerBox));
1164
+ }
1165
+
1166
+ /*function WebVTT() {
1167
+ // Nothing
1168
+ }*/
1169
+
1170
+ // Helper to allow strings to be decoded instead of the default binary utf8 data.
1171
+ WebVTT.StringDecoder = function() {
1172
+ return {
1173
+ decode: function(data) {
1174
+ if (!data) {
1175
+ return "";
1176
+ }
1177
+ if (typeof data !== "string") {
1178
+ throw new Error("Error - expected string data.");
1179
+ }
1180
+ return decodeURIComponent(encodeURIComponent(data));
1181
+ }
1182
+ };
1183
+ };
1184
+
1185
+ WebVTT.convertCueToDOMTree = function(window, cuetext) {
1186
+ if (!window || !cuetext) {
1187
+ return null;
1188
+ }
1189
+ return parseContent(window, cuetext);
1190
+ };
1191
+
1192
+ var FONT_SIZE_PERCENT = 0.05;
1193
+ var FONT_STYLE = "sans-serif";
1194
+ var CUE_BACKGROUND_PADDING = "1.5%";
1195
+
1196
+ // Runs the processing model over the cues and regions passed to it.
1197
+ // @param overlay A block level element (usually a div) that the computed cues
1198
+ // and regions will be placed into.
1199
+ WebVTT.processCues = function(window, cues, overlay) {
1200
+ if (!window || !cues || !overlay) {
1201
+ return null;
1202
+ }
1203
+
1204
+ // Remove all previous children.
1205
+ while (overlay.firstChild) {
1206
+ overlay.removeChild(overlay.firstChild);
1207
+ }
1208
+
1209
+ var paddedOverlay = window.document.createElement("div");
1210
+ paddedOverlay.style.position = "absolute";
1211
+ paddedOverlay.style.left = "0";
1212
+ paddedOverlay.style.right = "0";
1213
+ paddedOverlay.style.top = "0";
1214
+ paddedOverlay.style.bottom = "0";
1215
+ paddedOverlay.style.margin = CUE_BACKGROUND_PADDING;
1216
+ overlay.appendChild(paddedOverlay);
1217
+
1218
+ // Determine if we need to compute the display states of the cues. This could
1219
+ // be the case if a cue's state has been changed since the last computation or
1220
+ // if it has not been computed yet.
1221
+ function shouldCompute(cues) {
1222
+ for (var i = 0; i < cues.length; i++) {
1223
+ if (cues[i].hasBeenReset || !cues[i].displayState) {
1224
+ return true;
1225
+ }
1226
+ }
1227
+ return false;
1228
+ }
1229
+
1230
+ // We don't need to recompute the cues' display states. Just reuse them.
1231
+ if (!shouldCompute(cues)) {
1232
+ for (var i = 0; i < cues.length; i++) {
1233
+ paddedOverlay.appendChild(cues[i].displayState);
1234
+ }
1235
+ return;
1236
+ }
1237
+
1238
+ var boxPositions = [],
1239
+ containerBox = BoxPosition.getSimpleBoxPosition(paddedOverlay),
1240
+ fontSize = Math.round(containerBox.height * FONT_SIZE_PERCENT * 100) / 100;
1241
+ var styleOptions = {
1242
+ font: (fontSize * fontScale) + "px " + FONT_STYLE
1243
+ };
1244
+
1245
+ (function() {
1246
+ var styleBox, cue;
1247
+
1248
+ for (var i = 0; i < cues.length; i++) {
1249
+ cue = cues[i];
1250
+
1251
+ // Compute the intial position and styles of the cue div.
1252
+ styleBox = new CueStyleBox(window, cue, styleOptions);
1253
+ paddedOverlay.appendChild(styleBox.div);
1254
+
1255
+ // Move the cue div to it's correct line position.
1256
+ moveBoxToLinePosition(window, styleBox, containerBox, boxPositions);
1257
+
1258
+ // Remember the computed div so that we don't have to recompute it later
1259
+ // if we don't have too.
1260
+ cue.displayState = styleBox.div;
1261
+
1262
+ boxPositions.push(BoxPosition.getSimpleBoxPosition(styleBox));
1263
+ }
1264
+ })();
1265
+ };
1266
+
1267
+ WebVTT.Parser = function(window, decoder) {
1268
+ this.window = window;
1269
+ this.state = "INITIAL";
1270
+ this.buffer = "";
1271
+ this.decoder = decoder || new TextDecoder("utf8");
1272
+ this.regionList = [];
1273
+ };
1274
+
1275
+ WebVTT.Parser.prototype = {
1276
+ // If the error is a ParsingError then report it to the consumer if
1277
+ // possible. If it's not a ParsingError then throw it like normal.
1278
+ reportOrThrowError: function(e) {
1279
+ if (e instanceof ParsingError) {
1280
+ this.onparsingerror && this.onparsingerror(e);
1281
+ } else {
1282
+ throw e;
1283
+ }
1284
+ },
1285
+ parse: function (data, flushing) {
1286
+ var self = this;
1287
+ // If there is no data then we won't decode it, but will just try to parse
1288
+ // whatever is in buffer already. This may occur in circumstances, for
1289
+ // example when flush() is called.
1290
+ if (data) {
1291
+ // Try to decode the data that we received.
1292
+ self.buffer += self.decoder.decode(data, {stream: true});
1293
+ }
1294
+ function collectNextLine() {
1295
+ var buffer = self.buffer;
1296
+ var pos = 0;
1297
+ while (pos < buffer.length && buffer[pos] !== '\r' && buffer[pos] !== '\n') {
1298
+ ++pos;
1299
+ }
1300
+ var line = buffer.substr(0, pos);
1301
+ // Advance the buffer early in case we fail below.
1302
+ if (buffer[pos] === '\r') {
1303
+ ++pos;
1304
+ }
1305
+ if (buffer[pos] === '\n') {
1306
+ ++pos;
1307
+ }
1308
+ self.buffer = buffer.substr(pos);
1309
+ return line;
1310
+ }
1311
+
1312
+ // 3.4 WebVTT region and WebVTT region settings syntax
1313
+ function parseRegion(input) {
1314
+ var settings = new Settings();
1315
+
1316
+ parseOptions(input, function (k, v) {
1317
+ switch (k) {
1318
+ case "id":
1319
+ settings.set(k, v);
1320
+ break;
1321
+ case "width":
1322
+ settings.percent(k, v);
1323
+ break;
1324
+ case "lines":
1325
+ settings.integer(k, v);
1326
+ break;
1327
+ case "regionanchor":
1328
+ case "viewportanchor":
1329
+ var xy = v.split(',');
1330
+ if (xy.length !== 2) {
1331
+ break;
1332
+ }
1333
+ // We have to make sure both x and y parse, so use a temporary
1334
+ // settings object here.
1335
+ var anchor = new Settings();
1336
+ anchor.percent("x", xy[0]);
1337
+ anchor.percent("y", xy[1]);
1338
+ if (!anchor.has("x") || !anchor.has("y")) {
1339
+ break;
1340
+ }
1341
+ settings.set(k + "X", anchor.get("x"));
1342
+ settings.set(k + "Y", anchor.get("y"));
1343
+ break;
1344
+ case "scroll":
1345
+ settings.alt(k, v, ["up"]);
1346
+ break;
1347
+ }
1348
+ }, /=/, /\s/);
1349
+
1350
+ // Create the region, using default values for any values that were not
1351
+ // specified.
1352
+ if (settings.has("id")) {
1353
+ var region = new VTTRegion();
1354
+ region.width = settings.get("width", 100);
1355
+ region.lines = settings.get("lines", 3);
1356
+ region.regionAnchorX = settings.get("regionanchorX", 0);
1357
+ region.regionAnchorY = settings.get("regionanchorY", 100);
1358
+ region.viewportAnchorX = settings.get("viewportanchorX", 0);
1359
+ region.viewportAnchorY = settings.get("viewportanchorY", 100);
1360
+ region.scroll = settings.get("scroll", "");
1361
+ // Register the region.
1362
+ self.onregion && self.onregion(region);
1363
+ // Remember the VTTRegion for later in case we parse any VTTCues that
1364
+ // reference it.
1365
+ self.regionList.push({
1366
+ id: settings.get("id"),
1367
+ region: region
1368
+ });
1369
+ }
1370
+ }
1371
+
1372
+ // 3.2 WebVTT metadata header syntax
1373
+ function parseHeader(input) {
1374
+ parseOptions(input, function (k, v) {
1375
+ switch (k) {
1376
+ case "Region":
1377
+ // 3.3 WebVTT region metadata header syntax
1378
+ parseRegion(v);
1379
+ break;
1380
+ }
1381
+ }, /:/);
1382
+ }
1383
+
1384
+ // 5.1 WebVTT file parsing.
1385
+ try {
1386
+ var line;
1387
+ if (self.state === "INITIAL") {
1388
+ // We can't start parsing until we have the first line.
1389
+ if (!/\r\n|\n/.test(self.buffer)) {
1390
+ return this;
1391
+ }
1392
+
1393
+ line = collectNextLine();
1394
+
1395
+ var m = line.match(/^WEBVTT([ \t].*)?$/);
1396
+ if (!m || !m[0]) {
1397
+ throw new ParsingError(ParsingError.Errors.BadSignature);
1398
+ }
1399
+
1400
+ self.state = "HEADER";
1401
+ }
1402
+
1403
+ var alreadyCollectedLine = false;
1404
+ while (self.buffer) {
1405
+ // We can't parse a line until we have the full line.
1406
+ if (!/\r\n|\n/.test(self.buffer)) {
1407
+ return this;
1408
+ }
1409
+
1410
+ if (!alreadyCollectedLine) {
1411
+ line = collectNextLine();
1412
+ } else {
1413
+ alreadyCollectedLine = false;
1414
+ }
1415
+ switch (self.state) {
1416
+ case "HEADER":
1417
+ // 13-18 - Allow a header (metadata) under the WEBVTT line.
1418
+ if (/:/.test(line)) {
1419
+ parseHeader(line);
1420
+ } else if (!line) {
1421
+ // An empty line terminates the header and starts the body (cues).
1422
+ self.state = "ID";
1423
+ }
1424
+ continue;
1425
+ case "NOTE":
1426
+ // Ignore NOTE blocks.
1427
+ if (!line) {
1428
+ self.state = "ID";
1429
+ }
1430
+ continue;
1431
+ case "ID":
1432
+ // Check for the start of NOTE blocks.
1433
+ if (/^NOTE($|[ \t])/.test(line)) {
1434
+ self.state = "NOTE";
1435
+ break;
1436
+ }
1437
+ // 19-29 - Allow any number of line terminators, then initialize new cue values.
1438
+ if (!line) {
1439
+ continue;
1440
+ }
1441
+ self.cue = new VTTCue(0, 0, "");
1442
+ self.state = "CUE";
1443
+ // 30-39 - Check if self line contains an optional identifier or timing data.
1444
+ if (line.indexOf("-->") === -1) {
1445
+ self.cue.id = line;
1446
+ continue;
1447
+ }
1448
+ // Process line as start of a cue.
1449
+ /*falls through*/
1450
+ case "CUE":
1451
+ // 40 - Collect cue timings and settings.
1452
+ try {
1453
+ parseCue(line, self.cue, self.regionList);
1454
+ } catch (e) {
1455
+ self.reportOrThrowError(e);
1456
+ // In case of an error ignore rest of the cue.
1457
+ self.cue = null;
1458
+ self.state = "BADCUE";
1459
+ continue;
1460
+ }
1461
+ self.state = "CUETEXT";
1462
+ continue;
1463
+ case "CUETEXT":
1464
+ var hasSubstring = line.indexOf("-->") !== -1;
1465
+ // 34 - If we have an empty line then report the cue.
1466
+ // 35 - If we have the special substring '-->' then report the cue,
1467
+ // but do not collect the line as we need to process the current
1468
+ // one as a new cue.
1469
+ if (!line || hasSubstring && (alreadyCollectedLine = true)) {
1470
+ // We are done parsing self cue.
1471
+ self.oncue && self.oncue(self.cue);
1472
+ self.cue = null;
1473
+ self.state = "ID";
1474
+ continue;
1475
+ }
1476
+ if (self.cue.text) {
1477
+ self.cue.text += "\n";
1478
+ }
1479
+ self.cue.text += line;
1480
+ continue;
1481
+ case "BADCUE": // BADCUE
1482
+ // 54-62 - Collect and discard the remaining cue.
1483
+ if (!line) {
1484
+ self.state = "ID";
1485
+ }
1486
+ continue;
1487
+ }
1488
+ }
1489
+
1490
+
1491
+ if (!flushing) {
1492
+ //때때로 (한긇 vtt로 추정) cue가 남아 있는채로 self.flush()를 호출해서 cue가 있기 때문에 다시 self.parse()를 타는 경우가 생김.
1493
+ //왜 이렇게 짜여 있는지 모르겠고 일단 아래와 같은 코드로 위기를 극복한다.
1494
+ if (self.state === "CUETEXT" && self.cue && self.oncue) {
1495
+ self.oncue(self.cue);
1496
+ }
1497
+ self.flush();
1498
+ return this;
1499
+ }
1500
+ } catch (e) {
1501
+ self.reportOrThrowError(e);
1502
+ // If we are currently parsing a cue, report what we have.
1503
+ if (self.state === "CUETEXT" && self.cue && self.oncue) {
1504
+ self.oncue(self.cue);
1505
+ }
1506
+ self.cue = null;
1507
+ // Enter BADWEBVTT state if header was not parsed correctly otherwise
1508
+ // another exception occurred so enter BADCUE state.
1509
+ self.state = self.state === "INITIAL" ? "BADWEBVTT" : "BADCUE";
1510
+ }
1511
+ return this;
1512
+ },
1513
+ flush: function () {
1514
+ var self = this;
1515
+
1516
+ try {
1517
+ // Finish decoding the stream.
1518
+ self.buffer += self.decoder.decode();
1519
+ // Synthesize the end of the current cue or region.
1520
+ if (self.cue || self.state === "HEADER") {
1521
+ self.buffer += "\n\n";
1522
+ self.parse(null, true);
1523
+ }
1524
+ // If we've flushed, parsed, and we're still on the INITIAL state then
1525
+ // that means we don't have enough of the stream to parse the first
1526
+ // line.
1527
+ if (self.state === "INITIAL") {
1528
+ throw new ParsingError(ParsingError.Errors.BadSignature);
1529
+ }
1530
+ } catch(e) {
1531
+ self.reportOrThrowError(e);
1532
+ }
1533
+ self.onflush && self.onflush();
1534
+ return this;
1535
+ }
1536
+ };
1537
+
1538
+
1539
+
1540
+
1541
+ export default WebVTT;