Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /*
2 * Copyright 2013 Mozilla Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
17 // This file is automatically generated
19 (function (global) {
20 if (global.DataView)
21 return;
22 if (!global.ArrayBuffer)
23 fail('ArrayBuffer not supported');
24 if (!Object.defineProperties)
25 fail('This module requires ECMAScript 5');
26 var nativele = new Int8Array(new Int32Array([
27 1
28 ]).buffer)[0] === 1;
29 var temp = new Uint8Array(8);
30 global.DataView = function DataView(buffer, offset, length) {
31 if (!(buffer instanceof ArrayBuffer))
32 fail('Bad ArrayBuffer');
33 offset = offset || 0;
34 length = length || buffer.byteLength - offset;
35 if (offset < 0 || length < 0 || offset + length > buffer.byteLength)
36 fail('Illegal offset and/or length');
37 Object.defineProperties(this, {
38 buffer: {
39 value: buffer,
40 enumerable: false,
41 writable: false,
42 configurable: false
43 },
44 byteOffset: {
45 value: offset,
46 enumerable: false,
47 writable: false,
48 configurable: false
49 },
50 byteLength: {
51 value: length,
52 enumerable: false,
53 writable: false,
54 configurable: false
55 },
56 _bytes: {
57 value: new Uint8Array(buffer, offset, length),
58 enumerable: false,
59 writable: false,
60 configurable: false
61 }
62 });
63 };
64 global.DataView.prototype = {
65 constructor: DataView,
66 getInt8: function getInt8(offset) {
67 return get(this, Int8Array, 1, offset);
68 },
69 getUint8: function getUint8(offset) {
70 return get(this, Uint8Array, 1, offset);
71 },
72 getInt16: function getInt16(offset, le) {
73 return get(this, Int16Array, 2, offset, le);
74 },
75 getUint16: function getUint16(offset, le) {
76 return get(this, Uint16Array, 2, offset, le);
77 },
78 getInt32: function getInt32(offset, le) {
79 return get(this, Int32Array, 4, offset, le);
80 },
81 getUint32: function getUint32(offset, le) {
82 return get(this, Uint32Array, 4, offset, le);
83 },
84 getFloat32: function getFloat32(offset, le) {
85 return get(this, Float32Array, 4, offset, le);
86 },
87 getFloat64: function getFloat32(offset, le) {
88 return get(this, Float64Array, 8, offset, le);
89 },
90 setInt8: function setInt8(offset, value) {
91 set(this, Int8Array, 1, offset, value);
92 },
93 setUint8: function setUint8(offset, value) {
94 set(this, Uint8Array, 1, offset, value);
95 },
96 setInt16: function setInt16(offset, value, le) {
97 set(this, Int16Array, 2, offset, value, le);
98 },
99 setUint16: function setUint16(offset, value, le) {
100 set(this, Uint16Array, 2, offset, value, le);
101 },
102 setInt32: function setInt32(offset, value, le) {
103 set(this, Int32Array, 4, offset, value, le);
104 },
105 setUint32: function setUint32(offset, value, le) {
106 set(this, Uint32Array, 4, offset, value, le);
107 },
108 setFloat32: function setFloat32(offset, value, le) {
109 set(this, Float32Array, 4, offset, value, le);
110 },
111 setFloat64: function setFloat64(offset, value, le) {
112 set(this, Float64Array, 8, offset, value, le);
113 }
114 };
115 function get(view, type, size, offset, le) {
116 if (offset === undefined)
117 fail('Missing required offset argument');
118 if (offset < 0 || offset + size > view.byteLength)
119 fail('Invalid index: ' + offset);
120 if (size === 1 || !(!le) === nativele) {
121 if ((view.byteOffset + offset) % size === 0)
122 return new type(view.buffer, view.byteOffset + offset, 1)[0];
123 else {
124 for (var i = 0; i < size; i++)
125 temp[i] = view._bytes[offset + i];
126 return new type(temp.buffer)[0];
127 }
128 } else {
129 for (var i = 0; i < size; i++)
130 temp[size - i - 1] = view._bytes[offset + i];
131 return new type(temp.buffer)[0];
132 }
133 }
134 function set(view, type, size, offset, value, le) {
135 if (offset === undefined)
136 fail('Missing required offset argument');
137 if (value === undefined)
138 fail('Missing required value argument');
139 if (offset < 0 || offset + size > view.byteLength)
140 fail('Invalid index: ' + offset);
141 if (size === 1 || !(!le) === nativele) {
142 if ((view.byteOffset + offset) % size === 0) {
143 new type(view.buffer, view.byteOffset + offset, 1)[0] = value;
144 } else {
145 new type(temp.buffer)[0] = value;
146 for (var i = 0; i < size; i++)
147 view._bytes[i + offset] = temp[i];
148 }
149 } else {
150 new type(temp.buffer)[0] = value;
151 for (var i = 0; i < size; i++)
152 view._bytes[offset + i] = temp[size - 1 - i];
153 }
154 }
155 function fail(msg) {
156 throw new Error(msg);
157 }
158 }(this));
159 var create = Object.create;
160 var defineProperty = Object.defineProperty;
161 var keys = Object.keys;
162 var isArray = Array.isArray;
163 var fromCharCode = String.fromCharCode;
164 var logE = Math.log;
165 var max = Math.max;
166 var min = Math.min;
167 var pow = Math.pow;
168 var push = Array.prototype.push;
169 var slice = Array.prototype.slice;
170 var splice = Array.prototype.splice;
171 function fail(msg, context) {
172 throw new Error((context ? context + ': ' : '') + msg);
173 }
174 function assert(cond, msg, context) {
175 if (!cond)
176 fail(msg, context);
177 }
178 function scriptProperties(namespace, props) {
179 return props.reduce(function (o, p) {
180 o[p] = namespace + ' ' + p;
181 return o;
182 }, {});
183 }
184 function cloneObject(obj) {
185 var clone = Object.create(null);
186 for (var prop in obj)
187 clone[prop] = obj[prop];
188 return clone;
189 }
190 function sortNumeric(a, b) {
191 return a - b;
192 }
193 function sortByZindex(a, b) {
194 return a._zindex - b._zindex;
195 }
196 function rgbaObjToStr(color) {
197 return 'rgba(' + color.red + ',' + color.green + ',' + color.blue + ',' + color.alpha / 255 + ')';
198 }
199 function rgbIntAlphaToStr(color, alpha) {
200 color |= 0;
201 if (alpha >= 1) {
202 var colorStr = color.toString(16);
203 while (colorStr.length < 6) {
204 colorStr = '0' + colorStr;
205 }
206 return '#' + colorStr;
207 }
208 var red = color >> 16 & 255;
209 var green = color >> 8 & 255;
210 var blue = color & 255;
211 return 'rgba(' + red + ',' + green + ',' + blue + ',' + alpha + ')';
212 }
213 function argbUintToStr(argb) {
214 return 'rgba(' + (argb >>> 16 & 255) + ',' + (argb >>> 8 & 255) + ',' + (argb & 255) + ',' + (argb >>> 24 & 255) / 255 + ')';
215 }
216 (function functionNameSupport() {
217 if (eval('function t() {} t.name === \'t\'')) {
218 return;
219 }
220 Object.defineProperty(Function.prototype, 'name', {
221 get: function () {
222 if (this.__name) {
223 return this.__name;
224 }
225 var m = /function\s([^\(]+)/.exec(this.toString());
226 var name = m && m[1] !== 'anonymous' ? m[1] : null;
227 this.__name = name;
228 return name;
229 },
230 configurable: true,
231 enumerable: false
232 });
233 }());
234 var randomStyleCache;
235 var nextStyle = 0;
236 function randomStyle() {
237 if (!randomStyleCache) {
238 randomStyleCache = [
239 '#ff5e3a',
240 '#ff9500',
241 '#ffdb4c',
242 '#87fc70',
243 '#52edc7',
244 '#1ad6fd',
245 '#c644fc',
246 '#ef4db6',
247 '#4a4a4a',
248 '#dbddde',
249 '#ff3b30',
250 '#ff9500',
251 '#ffcc00',
252 '#4cd964',
253 '#34aadc',
254 '#007aff',
255 '#5856d6',
256 '#ff2d55',
257 '#8e8e93',
258 '#c7c7cc',
259 '#5ad427',
260 '#c86edf',
261 '#d1eefc',
262 '#e0f8d8',
263 '#fb2b69',
264 '#f7f7f7',
265 '#1d77ef',
266 '#d6cec3',
267 '#55efcb',
268 '#ff4981',
269 '#ffd3e0',
270 '#f7f7f7',
271 '#ff1300',
272 '#1f1f21',
273 '#bdbec2',
274 '#ff3a2d'
275 ];
276 }
277 return randomStyleCache[nextStyle++ % randomStyleCache.length];
278 }
279 (function PromiseClosure() {
280 var global = Function('return this')();
281 if (global.Promise) {
282 if (typeof global.Promise.all !== 'function') {
283 global.Promise.all = function (iterable) {
284 var count = 0, results = [], resolve, reject;
285 var promise = new global.Promise(function (resolve_, reject_) {
286 resolve = resolve_;
287 reject = reject_;
288 });
289 iterable.forEach(function (p, i) {
290 count++;
291 p.then(function (result) {
292 results[i] = result;
293 count--;
294 if (count === 0) {
295 resolve(results);
296 }
297 }, reject);
298 });
299 if (count === 0) {
300 resolve(results);
301 }
302 return promise;
303 };
304 }
305 if (typeof global.Promise.resolve !== 'function') {
306 global.Promise.resolve = function (x) {
307 return new global.Promise(function (resolve) {
308 resolve(x);
309 });
310 };
311 }
312 return;
313 }
314 function getDeferred(C) {
315 if (typeof C !== 'function') {
316 throw new TypeError('Invalid deferred constructor');
317 }
318 var resolver = createDeferredConstructionFunctions();
319 var promise = new C(resolver);
320 var resolve = resolver.resolve;
321 if (typeof resolve !== 'function') {
322 throw new TypeError('Invalid resolve construction function');
323 }
324 var reject = resolver.reject;
325 if (typeof reject !== 'function') {
326 throw new TypeError('Invalid reject construction function');
327 }
328 return {
329 promise: promise,
330 resolve: resolve,
331 reject: reject
332 };
333 }
334 function updateDeferredFromPotentialThenable(x, deferred) {
335 if (typeof x !== 'object' || x === null) {
336 return false;
337 }
338 try {
339 var then = x.then;
340 if (typeof then !== 'function') {
341 return false;
342 }
343 var thenCallResult = then.call(x, deferred.resolve, deferred.reject);
344 } catch (e) {
345 var reject = deferred.reject;
346 reject(e);
347 }
348 return true;
349 }
350 function isPromise(x) {
351 return typeof x === 'object' && x !== null && typeof x.promiseStatus !== 'undefined';
352 }
353 function rejectPromise(promise, reason) {
354 if (promise.promiseStatus !== 'unresolved') {
355 return;
356 }
357 var reactions = promise.rejectReactions;
358 promise.result = reason;
359 promise.resolveReactions = undefined;
360 promise.rejectReactions = undefined;
361 promise.promiseStatus = 'has-rejection';
362 triggerPromiseReactions(reactions, reason);
363 }
364 function resolvePromise(promise, resolution) {
365 if (promise.promiseStatus !== 'unresolved') {
366 return;
367 }
368 var reactions = promise.resolveReactions;
369 promise.result = resolution;
370 promise.resolveReactions = undefined;
371 promise.rejectReactions = undefined;
372 promise.promiseStatus = 'has-resolution';
373 triggerPromiseReactions(reactions, resolution);
374 }
375 function triggerPromiseReactions(reactions, argument) {
376 for (var i = 0; i < reactions.length; i++) {
377 queueMicrotask({
378 reaction: reactions[i],
379 argument: argument
380 });
381 }
382 }
383 function queueMicrotask(task) {
384 if (microtasksQueue.length === 0) {
385 setTimeout(handleMicrotasksQueue, 0);
386 }
387 microtasksQueue.push(task);
388 }
389 function executePromiseReaction(reaction, argument) {
390 var deferred = reaction.deferred;
391 var handler = reaction.handler;
392 var handlerResult, updateResult;
393 try {
394 handlerResult = handler(argument);
395 } catch (e) {
396 var reject = deferred.reject;
397 return reject(e);
398 }
399 if (handlerResult === deferred.promise) {
400 var reject = deferred.reject;
401 return reject(new TypeError('Self resolution'));
402 }
403 try {
404 updateResult = updateDeferredFromPotentialThenable(handlerResult, deferred);
405 if (!updateResult) {
406 var resolve = deferred.resolve;
407 return resolve(handlerResult);
408 }
409 } catch (e) {
410 var reject = deferred.reject;
411 return reject(e);
412 }
413 }
414 var microtasksQueue = [];
415 function handleMicrotasksQueue() {
416 while (microtasksQueue.length > 0) {
417 var task = microtasksQueue[0];
418 try {
419 executePromiseReaction(task.reaction, task.argument);
420 } catch (e) {
421 if (typeof Promise.onerror === 'function') {
422 Promise.onerror(e);
423 }
424 }
425 microtasksQueue.shift();
426 }
427 }
428 function throwerFunction(e) {
429 throw e;
430 }
431 function identityFunction(x) {
432 return x;
433 }
434 function createRejectPromiseFunction(promise) {
435 return function (reason) {
436 rejectPromise(promise, reason);
437 };
438 }
439 function createResolvePromiseFunction(promise) {
440 return function (resolution) {
441 resolvePromise(promise, resolution);
442 };
443 }
444 function createDeferredConstructionFunctions() {
445 var fn = function (resolve, reject) {
446 fn.resolve = resolve;
447 fn.reject = reject;
448 };
449 return fn;
450 }
451 function createPromiseResolutionHandlerFunctions(promise, fulfillmentHandler, rejectionHandler) {
452 return function (x) {
453 if (x === promise) {
454 return rejectionHandler(new TypeError('Self resolution'));
455 }
456 var cstr = promise.promiseConstructor;
457 if (isPromise(x)) {
458 var xConstructor = x.promiseConstructor;
459 if (xConstructor === cstr) {
460 return x.then(fulfillmentHandler, rejectionHandler);
461 }
462 }
463 var deferred = getDeferred(cstr);
464 var updateResult = updateDeferredFromPotentialThenable(x, deferred);
465 if (updateResult) {
466 var deferredPromise = deferred.promise;
467 return deferredPromise.then(fulfillmentHandler, rejectionHandler);
468 }
469 return fulfillmentHandler(x);
470 };
471 }
472 function createPromiseAllCountdownFunction(index, values, deferred, countdownHolder) {
473 return function (x) {
474 values[index] = x;
475 countdownHolder.countdown--;
476 if (countdownHolder.countdown === 0) {
477 deferred.resolve(values);
478 }
479 };
480 }
481 function Promise(resolver) {
482 if (typeof resolver !== 'function') {
483 throw new TypeError('resolver is not a function');
484 }
485 var promise = this;
486 if (typeof promise !== 'object') {
487 throw new TypeError('Promise to initialize is not an object');
488 }
489 promise.promiseStatus = 'unresolved';
490 promise.resolveReactions = [];
491 promise.rejectReactions = [];
492 promise.result = undefined;
493 var resolve = createResolvePromiseFunction(promise);
494 var reject = createRejectPromiseFunction(promise);
495 try {
496 var result = resolver(resolve, reject);
497 } catch (e) {
498 rejectPromise(promise, e);
499 }
500 promise.promiseConstructor = Promise;
501 return promise;
502 }
503 Promise.all = function (iterable) {
504 var deferred = getDeferred(this);
505 var values = [];
506 var countdownHolder = {
507 countdown: 0
508 };
509 var index = 0;
510 iterable.forEach(function (nextValue) {
511 var nextPromise = this.cast(nextValue);
512 var fn = createPromiseAllCountdownFunction(index, values, deferred, countdownHolder);
513 nextPromise.then(fn, deferred.reject);
514 index++;
515 countdownHolder.countdown++;
516 }, this);
517 if (index === 0) {
518 deferred.resolve(values);
519 }
520 return deferred.promise;
521 };
522 Promise.cast = function (x) {
523 if (isPromise(x)) {
524 return x;
525 }
526 var deferred = getDeferred(this);
527 deferred.resolve(x);
528 return deferred.promise;
529 };
530 Promise.reject = function (r) {
531 var deferred = getDeferred(this);
532 var rejectResult = deferred.reject(r);
533 return deferred.promise;
534 };
535 Promise.resolve = function (x) {
536 var deferred = getDeferred(this);
537 var rejectResult = deferred.resolve(x);
538 return deferred.promise;
539 };
540 Promise.prototype = {
541 'catch': function (onRejected) {
542 this.then(undefined, onRejected);
543 },
544 then: function (onFulfilled, onRejected) {
545 var promise = this;
546 if (!isPromise(promise)) {
547 throw new TypeError('this is not a Promises');
548 }
549 var cstr = promise.promiseConstructor;
550 var deferred = getDeferred(cstr);
551 var rejectionHandler = typeof onRejected === 'function' ? onRejected : throwerFunction;
552 var fulfillmentHandler = typeof onFulfilled === 'function' ? onFulfilled : identityFunction;
553 var resolutionHandler = createPromiseResolutionHandlerFunctions(promise, fulfillmentHandler, rejectionHandler);
554 var resolveReaction = {
555 deferred: deferred,
556 handler: resolutionHandler
557 };
558 var rejectReaction = {
559 deferred: deferred,
560 handler: rejectionHandler
561 };
562 switch (promise.promiseStatus) {
563 case 'unresolved':
564 promise.resolveReactions.push(resolveReaction);
565 promise.rejectReactions.push(rejectReaction);
566 break;
567 case 'has-resolution':
568 var resolution = promise.result;
569 queueMicrotask({
570 reaction: resolveReaction,
571 argument: resolution
572 });
573 break;
574 case 'has-rejection':
575 var rejection = promise.result;
576 queueMicrotask({
577 reaction: rejectReaction,
578 argument: rejection
579 });
580 break;
581 }
582 return deferred.promise;
583 }
584 };
585 global.Promise = Promise;
586 }());
587 var QuadTree = function (x, y, width, height, parent) {
588 this.x = x | 0;
589 this.y = y | 0;
590 this.width = width | 0;
591 this.height = height | 0;
592 if (parent) {
593 this.root = parent.root;
594 this.parent = parent;
595 this.level = parent.level + 1;
596 } else {
597 this.root = this;
598 this.parent = null;
599 this.level = 0;
600 }
601 this.reset();
602 };
603 QuadTree.prototype.reset = function () {
604 this.stuckObjects = null;
605 this.objects = null;
606 this.nodes = [];
607 };
608 QuadTree.prototype._findIndex = function (xMin, xMax, yMin, yMax) {
609 var midX = this.x + (this.width / 2 | 0);
610 var midY = this.y + (this.height / 2 | 0);
611 var top = yMin < midY && yMax < midY;
612 var bottom = yMin > midY;
613 if (xMin < midX && xMax < midX) {
614 if (top) {
615 return 1;
616 } else if (bottom) {
617 return 2;
618 }
619 } else if (xMin > midX) {
620 if (top) {
621 return 0;
622 } else if (bottom) {
623 return 3;
624 }
625 }
626 return -1;
627 };
628 QuadTree.prototype.insert = function (obj) {
629 var nodes = this.nodes;
630 if (nodes.length) {
631 var index = this._findIndex(obj.xMin, obj.xMax, obj.yMin, obj.yMax);
632 if (index > -1) {
633 nodes[index].insert(obj);
634 } else {
635 obj.prev = null;
636 if (this.stuckObjects) {
637 obj.next = this.stuckObjects;
638 this.stuckObjects.prev = obj;
639 } else {
640 obj.next = null;
641 }
642 this.stuckObjects = obj;
643 obj.parent = this;
644 }
645 return;
646 }
647 var numChildren = 1;
648 var item = this.objects;
649 if (!item) {
650 obj.prev = null;
651 obj.next = null;
652 this.objects = obj;
653 } else {
654 while (item.next) {
655 numChildren++;
656 item = item.next;
657 }
658 obj.prev = item;
659 obj.next = null;
660 item.next = obj;
661 }
662 if (numChildren > 4 && this.level < 10) {
663 this._subdivide();
664 item = this.objects;
665 while (item) {
666 var next = item.next;
667 this.insert(item);
668 item = next;
669 }
670 this.objects = null;
671 return;
672 }
673 obj.parent = this;
674 };
675 QuadTree.prototype.update = function (obj) {
676 var node = obj.parent;
677 if (node) {
678 if (obj.xMin >= node.x && obj.xMax <= node.x + node.width && obj.yMin >= node.y && obj.yMax <= node.y + node.height) {
679 if (node.nodes.length) {
680 var index = this._findIndex(obj.xMin, obj.xMax, obj.yMin, obj.yMax);
681 if (index > -1) {
682 node.remove(obj);
683 node = this.nodes[index];
684 node.insert(obj);
685 }
686 } else {
687 node.remove(obj);
688 node.insert(obj);
689 }
690 return;
691 }
692 node.remove(obj);
693 }
694 this.root.insert(obj);
695 };
696 QuadTree.prototype.remove = function (obj) {
697 var prev = obj.prev;
698 var next = obj.next;
699 if (prev) {
700 prev.next = next;
701 obj.prev = null;
702 } else {
703 var node = obj.parent;
704 if (node.objects === obj) {
705 node.objects = next;
706 } else if (node.stuckObjects === obj) {
707 node.stuckObjects = next;
708 }
709 }
710 if (next) {
711 next.prev = prev;
712 obj.next = null;
713 }
714 obj.parent = null;
715 };
716 QuadTree.prototype.retrieve = function (xMin, xMax, yMin, yMax) {
717 var stack = [];
718 var out = [];
719 var node = this;
720 do {
721 if (node.nodes.length) {
722 var index = node._findIndex(xMin, xMax, yMin, yMax);
723 if (index > -1) {
724 stack.push(node.nodes[index]);
725 } else {
726 stack.push.apply(stack, node.nodes);
727 }
728 }
729 var item = node.objects;
730 for (var i = 0; i < 2; i++) {
731 while (item) {
732 if (!(item.xMin > xMax || item.xMax < xMin || item.yMin > yMax || item.yMax < yMin)) {
733 out.push(item);
734 }
735 item = item.next;
736 }
737 item = node.stuckObjects;
738 }
739 node = stack.pop();
740 } while (node);
741 return out;
742 };
743 QuadTree.prototype._subdivide = function () {
744 var halfWidth = this.width / 2 | 0;
745 var halfHeight = this.height / 2 | 0;
746 var midX = this.x + halfWidth;
747 var midY = this.y + halfHeight;
748 this.nodes[0] = new QuadTree(midX, this.y, halfWidth, halfHeight, this);
749 this.nodes[1] = new QuadTree(this.x, this.y, halfWidth, halfHeight, this);
750 this.nodes[2] = new QuadTree(this.x, midY, halfWidth, halfHeight, this);
751 this.nodes[3] = new QuadTree(midX, midY, halfWidth, halfHeight, this);
752 };
753 var RegionCluster = function () {
754 this.regions = [];
755 };
756 RegionCluster.prototype.reset = function () {
757 this.regions.length = 0;
758 };
759 RegionCluster.prototype.insert = function (region) {
760 var regions = this.regions;
761 if (regions.length < 3) {
762 regions.push({
763 xMin: region.xMin,
764 xMax: region.xMax,
765 yMin: region.yMin,
766 yMax: region.yMax
767 });
768 return;
769 }
770 var a = region;
771 var b = regions[0];
772 var c = regions[1];
773 var d = regions[2];
774 var ab = (max(a.xMax, b.xMax) - min(a.xMin, b.xMin)) * (max(a.yMax, b.yMax) - min(a.yMin, b.yMin));
775 var rb = regions[0];
776 var ac = (max(a.xMax, c.xMax) - min(a.xMin, c.xMin)) * (max(a.yMax, c.yMax) - min(a.yMin, c.yMin));
777 var ad = (max(a.xMax, d.xMax) - min(a.xMin, d.xMin)) * (max(a.yMax, d.yMax) - min(a.yMin, d.yMin));
778 if (ac < ab) {
779 ab = ac;
780 rb = c;
781 }
782 if (ad < ab) {
783 ab = ad;
784 rb = d;
785 }
786 var bc = (max(b.xMax, c.xMax) - min(b.xMin, c.xMin)) * (max(b.yMax, c.yMax) - min(b.yMin, c.yMin));
787 var bd = (max(b.xMax, d.xMax) - min(b.xMin, d.xMin)) * (max(b.yMax, d.yMax) - min(b.yMin, d.yMin));
788 var cd = (max(c.xMax, d.xMax) - min(c.xMin, d.xMin)) * (max(c.yMax, d.yMax) - min(c.yMin, d.yMin));
789 if (ab < bc && ab < bd && ab < cd) {
790 if (a.xMin < rb.xMin) {
791 rb.xMin = a.xMin;
792 }
793 if (a.xMax > rb.xMax) {
794 rb.xMax = a.xMax;
795 }
796 if (a.yMin < rb.yMin) {
797 rb.yMin = a.yMin;
798 }
799 if (a.yMax > rb.yMax) {
800 rb.yMax = a.yMax;
801 }
802 return;
803 }
804 rb = regions[0];
805 var rc = regions[1];
806 if (bd < bc) {
807 bc = bd;
808 rc = regions[2];
809 }
810 if (cd < bc) {
811 rb = regions[1];
812 rc = regions[2];
813 }
814 if (rc.xMin < rb.xMin) {
815 rb.xMin = rc.xMin;
816 }
817 if (rc.xMax > rb.xMax) {
818 rb.xMax = rc.xMax;
819 }
820 if (rc.yMin < rb.yMin) {
821 rb.yMin = rc.yMin;
822 }
823 if (rc.yMax > rb.yMax) {
824 rb.yMax = rc.yMax;
825 }
826 rc.xMin = a.xMin;
827 rc.xMax = a.xMax;
828 rc.yMin = a.yMin;
829 rc.yMax = a.yMax;
830 };
831 RegionCluster.prototype.retrieve = function () {
832 return this.regions;
833 };
834 var EXTERNAL_INTERFACE_FEATURE = 1;
835 var CLIPBOARD_FEATURE = 2;
836 var SHAREDOBJECT_FEATURE = 3;
837 var VIDEO_FEATURE = 4;
838 var SOUND_FEATURE = 5;
839 var NETCONNECTION_FEATURE = 6;
840 if (!this.performance) {
841 this.performance = {};
842 }
843 if (!this.performance.now) {
844 this.performance.now = Date.now;
845 }
846 var SWF_TAG_CODE_CSM_TEXT_SETTINGS = 74;
847 var SWF_TAG_CODE_DEFINE_BINARY_DATA = 87;
848 var SWF_TAG_CODE_DEFINE_BITS = 6;
849 var SWF_TAG_CODE_DEFINE_BITS_JPEG2 = 21;
850 var SWF_TAG_CODE_DEFINE_BITS_JPEG3 = 35;
851 var SWF_TAG_CODE_DEFINE_BITS_JPEG4 = 90;
852 var SWF_TAG_CODE_DEFINE_BITS_LOSSLESS = 20;
853 var SWF_TAG_CODE_DEFINE_BITS_LOSSLESS2 = 36;
854 var SWF_TAG_CODE_DEFINE_BUTTON = 7;
855 var SWF_TAG_CODE_DEFINE_BUTTON2 = 34;
856 var SWF_TAG_CODE_DEFINE_BUTTON_CXFORM = 23;
857 var SWF_TAG_CODE_DEFINE_BUTTON_SOUND = 17;
858 var SWF_TAG_CODE_DEFINE_EDIT_TEXT = 37;
859 var SWF_TAG_CODE_DEFINE_FONT = 10;
860 var SWF_TAG_CODE_DEFINE_FONT2 = 48;
861 var SWF_TAG_CODE_DEFINE_FONT3 = 75;
862 var SWF_TAG_CODE_DEFINE_FONT4 = 91;
863 var SWF_TAG_CODE_DEFINE_FONT_ALIGN_ZONES = 73;
864 var SWF_TAG_CODE_DEFINE_FONT_INFO = 13;
865 var SWF_TAG_CODE_DEFINE_FONT_INFO2 = 62;
866 var SWF_TAG_CODE_DEFINE_FONT_NAME = 88;
867 var SWF_TAG_CODE_DEFINE_MORPH_SHAPE = 46;
868 var SWF_TAG_CODE_DEFINE_MORPH_SHAPE2 = 84;
869 var SWF_TAG_CODE_DEFINE_SCALING_GRID = 78;
870 var SWF_TAG_CODE_DEFINE_SCENE_AND_FRAME_LABEL_DATA = 86;
871 var SWF_TAG_CODE_DEFINE_SHAPE = 2;
872 var SWF_TAG_CODE_DEFINE_SHAPE2 = 22;
873 var SWF_TAG_CODE_DEFINE_SHAPE3 = 32;
874 var SWF_TAG_CODE_DEFINE_SHAPE4 = 83;
875 var SWF_TAG_CODE_DEFINE_SOUND = 14;
876 var SWF_TAG_CODE_DEFINE_SPRITE = 39;
877 var SWF_TAG_CODE_DEFINE_TEXT = 11;
878 var SWF_TAG_CODE_DEFINE_TEXT2 = 33;
879 var SWF_TAG_CODE_DEFINE_VIDEO_STREAM = 60;
880 var SWF_TAG_CODE_DO_ABC = 82;
881 var SWF_TAG_CODE_DO_ABC_ = 72;
882 var SWF_TAG_CODE_DO_ACTION = 12;
883 var SWF_TAG_CODE_DO_INIT_ACTION = 59;
884 var SWF_TAG_CODE_ENABLE_DEBUGGER = 58;
885 var SWF_TAG_CODE_ENABLE_DEBUGGER2 = 64;
886 var SWF_TAG_CODE_END = 0;
887 var SWF_TAG_CODE_EXPORT_ASSETS = 56;
888 var SWF_TAG_CODE_FILE_ATTRIBUTES = 69;
889 var SWF_TAG_CODE_FRAME_LABEL = 43;
890 var SWF_TAG_CODE_IMPORT_ASSETS = 57;
891 var SWF_TAG_CODE_IMPORT_ASSETS2 = 71;
892 var SWF_TAG_CODE_JPEG_TABLES = 8;
893 var SWF_TAG_CODE_METADATA = 77;
894 var SWF_TAG_CODE_PLACE_OBJECT = 4;
895 var SWF_TAG_CODE_PLACE_OBJECT2 = 26;
896 var SWF_TAG_CODE_PLACE_OBJECT3 = 70;
897 var SWF_TAG_CODE_PROTECT = 24;
898 var SWF_TAG_CODE_REMOVE_OBJECT = 5;
899 var SWF_TAG_CODE_REMOVE_OBJECT2 = 28;
900 var SWF_TAG_CODE_SCRIPT_LIMITS = 65;
901 var SWF_TAG_CODE_SET_BACKGROUND_COLOR = 9;
902 var SWF_TAG_CODE_SET_TAB_INDEX = 66;
903 var SWF_TAG_CODE_SHOW_FRAME = 1;
904 var SWF_TAG_CODE_SOUND_STREAM_BLOCK = 19;
905 var SWF_TAG_CODE_SOUND_STREAM_HEAD = 18;
906 var SWF_TAG_CODE_SOUND_STREAM_HEAD2 = 45;
907 var SWF_TAG_CODE_START_SOUND = 15;
908 var SWF_TAG_CODE_START_SOUND2 = 89;
909 var SWF_TAG_CODE_SYMBOL_CLASS = 76;
910 var SWF_TAG_CODE_VIDEO_FRAME = 61;
911 self.SWF = {};
912 var FORMAT_COLORMAPPED = 3;
913 var FORMAT_15BPP = 4;
914 var FORMAT_24BPP = 5;
915 var FACTOR_5BBP = 255 / 31;
916 var crcTable = [];
917 for (var i = 0; i < 256; i++) {
918 var c = i;
919 for (var h = 0; h < 8; h++) {
920 if (c & 1)
921 c = 3988292384 ^ c >> 1 & 2147483647;
922 else
923 c = c >> 1 & 2147483647;
924 }
925 crcTable[i] = c;
926 }
927 function crc32(data, start, end) {
928 var crc = -1;
929 for (var i = start; i < end; i++) {
930 var a = (crc ^ data[i]) & 255;
931 var b = crcTable[a];
932 crc = crc >>> 8 ^ b;
933 }
934 return crc ^ -1;
935 }
936 function createPngChunk(type, data) {
937 var chunk = new Uint8Array(12 + data.length);
938 var p = 0;
939 var len = data.length;
940 chunk[p] = len >> 24 & 255;
941 chunk[p + 1] = len >> 16 & 255;
942 chunk[p + 2] = len >> 8 & 255;
943 chunk[p + 3] = len & 255;
944 chunk[p + 4] = type.charCodeAt(0) & 255;
945 chunk[p + 5] = type.charCodeAt(1) & 255;
946 chunk[p + 6] = type.charCodeAt(2) & 255;
947 chunk[p + 7] = type.charCodeAt(3) & 255;
948 if (data instanceof Uint8Array)
949 chunk.set(data, 8);
950 p = 8 + len;
951 var crc = crc32(chunk, 4, p);
952 chunk[p] = crc >> 24 & 255;
953 chunk[p + 1] = crc >> 16 & 255;
954 chunk[p + 2] = crc >> 8 & 255;
955 chunk[p + 3] = crc & 255;
956 return chunk;
957 }
958 function adler32(data, start, end) {
959 var a = 1;
960 var b = 0;
961 for (var i = start; i < end; ++i) {
962 a = (a + (data[i] & 255)) % 65521;
963 b = (b + a) % 65521;
964 }
965 return b << 16 | a;
966 }
967 function defineBitmap(tag) {
968 var width = tag.width;
969 var height = tag.height;
970 var hasAlpha = tag.hasAlpha;
971 var plte = '';
972 var trns = '';
973 var literals;
974 var bmpData = tag.bmpData;
975 switch (tag.format) {
976 case FORMAT_COLORMAPPED:
977 var colorType = 3;
978 var bytesPerLine = width + 3 & ~3;
979 var colorTableSize = tag.colorTableSize + 1;
980 var paletteSize = colorTableSize * (tag.hasAlpha ? 4 : 3);
981 var datalen = paletteSize + bytesPerLine * height;
982 var stream = createInflatedStream(bmpData, datalen);
983 var bytes = stream.bytes;
984 var pos = 0;
985 stream.ensure(paletteSize);
986 if (hasAlpha) {
987 var palette = new Uint8Array(paletteSize / 4 * 3);
988 var pp = 0;
989 var alphaValues = new Uint8Array(paletteSize / 4);
990 var pa = 0;
991 while (pos < paletteSize) {
992 palette[pp++] = bytes[pos];
993 palette[pp++] = bytes[pos + 1];
994 palette[pp++] = bytes[pos + 2];
995 alphaValues[pa++] = bytes[pos + 3];
996 pos += 4;
997 }
998 plte = createPngChunk('PLTE', palette);
999 trns = createPngChunk('tRNS', alphaValues);
1000 } else {
1001 plte = createPngChunk('PLTE', bytes.subarray(pos, pos + paletteSize));
1002 pos += paletteSize;
1003 }
1004 literals = new Uint8Array(width * height + height);
1005 var pl = 0;
1006 while (pos < datalen) {
1007 stream.ensure(bytesPerLine);
1008 var begin = pos;
1009 var end = begin + width;
1010 pl++;
1011 literals.set(bytes.subarray(begin, end), pl);
1012 pl += end - begin;
1013 stream.pos = pos += bytesPerLine;
1014 }
1015 break;
1016 case FORMAT_15BPP:
1017 var colorType = 2;
1018 var bytesPerLine = width * 2 + 3 & ~3;
1019 var stream = createInflatedStream(bmpData, bytesPerLine * height);
1020 var pos = 0;
1021 literals = new Uint8Array(width * height * 3 + height);
1022 var pl = 0;
1023 for (var y = 0; y < height; ++y) {
1024 pl++;
1025 stream.ensure(bytesPerLine);
1026 for (var x = 0; x < width; ++x) {
1027 var word = stream.getUint16(pos);
1028 pos += 2;
1029 literals[pl++] = 0 | FACTOR_5BBP * (word >> 10 & 31);
1030 literals[pl++] = 0 | FACTOR_5BBP * (word >> 5 & 31);
1031 literals[pl++] = 0 | FACTOR_5BBP * (word & 31);
1032 }
1033 stream.pos = pos += bytesPerLine;
1034 }
1035 break;
1036 case FORMAT_24BPP:
1037 var padding;
1038 if (hasAlpha) {
1039 var colorType = 6;
1040 padding = 0;
1041 literals = new Uint8Array(width * height * 4 + height);
1042 } else {
1043 var colorType = 2;
1044 padding = 1;
1045 literals = new Uint8Array(width * height * 3 + height);
1046 }
1047 var bytesPerLine = width * 4;
1048 var stream = createInflatedStream(bmpData, bytesPerLine * height);
1049 var bytes = stream.bytes;
1050 var pos = 0;
1051 var pl = 0;
1052 for (var y = 0; y < height; ++y) {
1053 stream.ensure(bytesPerLine);
1054 pl++;
1055 for (var x = 0; x < width; ++x) {
1056 pos += padding;
1057 if (hasAlpha) {
1058 var alpha = bytes[pos];
1059 if (alpha) {
1060 var opacity = alpha / 255;
1061 literals[pl++] = 0 | bytes[pos + 1] / opacity;
1062 literals[pl++] = 0 | bytes[pos + 2] / opacity;
1063 literals[pl++] = 0 | bytes[pos + 3] / opacity;
1064 literals[pl++] = alpha;
1065 } else {
1066 pl += 4;
1067 }
1068 } else {
1069 literals[pl++] = bytes[pos];
1070 literals[pl++] = bytes[pos + 1];
1071 literals[pl++] = bytes[pos + 2];
1072 }
1073 pos += 4 - padding;
1074 }
1075 stream.pos = pos;
1076 }
1077 break;
1078 default:
1079 fail('invalid format', 'bitmap');
1080 }
1081 var ihdr = new Uint8Array([
1082 width >> 24 & 255,
1083 width >> 16 & 255,
1084 width >> 8 & 255,
1085 width & 255,
1086 height >> 24 & 255,
1087 height >> 16 & 255,
1088 height >> 8 & 255,
1089 height & 255,
1090 8,
1091 colorType,
1092 0,
1093 0,
1094 0
1095 ]);
1096 var len = literals.length;
1097 var maxBlockLength = 65535;
1098 var idat = new Uint8Array(2 + len + Math.ceil(len / maxBlockLength) * 5 + 4);
1099 var pi = 0;
1100 idat[pi++] = 120;
1101 idat[pi++] = 156;
1102 var pos = 0;
1103 while (len > maxBlockLength) {
1104 idat[pi++] = 0;
1105 idat[pi++] = 255;
1106 idat[pi++] = 255;
1107 idat[pi++] = 0;
1108 idat[pi++] = 0;
1109 idat.set(literals.subarray(pos, pos + maxBlockLength), pi);
1110 pi += maxBlockLength;
1111 pos += maxBlockLength;
1112 len -= maxBlockLength;
1113 }
1114 idat[pi++] = 1;
1115 idat[pi++] = len & 255;
1116 idat[pi++] = len >> 8 & 255;
1117 idat[pi++] = ~len & 65535 & 255;
1118 idat[pi++] = (~len & 65535) >> 8 & 255;
1119 idat.set(literals.subarray(pos), pi);
1120 pi += literals.length - pos;
1121 var adler = adler32(literals, 0, literals.length);
1122 idat[pi++] = adler >> 24 & 255;
1123 idat[pi++] = adler >> 16 & 255;
1124 idat[pi++] = adler >> 8 & 255;
1125 idat[pi++] = adler & 255;
1126 var chunks = [
1127 new Uint8Array([
1128 137,
1129 80,
1130 78,
1131 71,
1132 13,
1133 10,
1134 26,
1135 10
1136 ]),
1137 createPngChunk('IHDR', ihdr),
1138 plte,
1139 trns,
1140 createPngChunk('IDAT', idat),
1141 createPngChunk('IEND', '')
1142 ];
1143 return {
1144 type: 'image',
1145 id: tag.id,
1146 width: width,
1147 height: height,
1148 mimeType: 'image/png',
1149 data: new Blob(chunks, {
1150 type: 'image/png'
1151 })
1152 };
1153 }
1154 function defineButton(tag, dictionary) {
1155 var characters = tag.characters;
1156 var states = {
1157 up: {},
1158 over: {},
1159 down: {},
1160 hitTest: {}
1161 };
1162 var i = 0, character;
1163 while (character = characters[i++]) {
1164 if (character.eob)
1165 break;
1166 var characterItem = dictionary[character.symbolId];
1167 var entry = {
1168 symbolId: characterItem.id,
1169 hasMatrix: !(!character.matrix),
1170 matrix: character.matrix
1171 };
1172 if (character.stateUp)
1173 states.up[character.depth] = entry;
1174 if (character.stateOver)
1175 states.over[character.depth] = entry;
1176 if (character.stateDown)
1177 states.down[character.depth] = entry;
1178 if (character.stateHitTest)
1179 states.hitTest[character.depth] = entry;
1180 }
1181 var button = {
1182 type: 'button',
1183 id: tag.id,
1184 buttonActions: tag.buttonActions,
1185 states: states
1186 };
1187 return button;
1188 }
1189 var nextFontId = 1;
1190 function maxPower2(num) {
1191 var maxPower = 0;
1192 var val = num;
1193 while (val >= 2) {
1194 val /= 2;
1195 ++maxPower;
1196 }
1197 return pow(2, maxPower);
1198 }
1199 function toString16(val) {
1200 return fromCharCode(val >> 8 & 255, val & 255);
1201 }
1202 function toString32(val) {
1203 return toString16(val >> 16) + toString16(val);
1204 }
1205 function defineFont(tag, dictionary) {
1206 var tables = {};
1207 var codes = [];
1208 var glyphIndex = {};
1209 var ranges = [];
1210 var glyphs = tag.glyphs;
1211 var glyphCount = glyphs.length;
1212 if (tag.codes) {
1213 codes = codes.concat(tag.codes);
1214 for (var i = 0, code; code = codes[i]; ++i)
1215 glyphIndex[code] = i;
1216 codes.sort(function (a, b) {
1217 return a - b;
1218 });
1219 var i = 0;
1220 var code;
1221 while (code = codes[i++]) {
1222 var start = code;
1223 var end = start;
1224 var indices = [
1225 i - 1
1226 ];
1227 while ((code = codes[i]) && end + 1 === code) {
1228 ++end;
1229 indices.push(i);
1230 ++i;
1231 }
1232 ranges.push([
1233 start,
1234 end,
1235 indices
1236 ]);
1237 }
1238 } else {
1239 var indices = [];
1240 var UAC_OFFSET = 57344;
1241 for (var i = 0; i < glyphCount; i++) {
1242 var code = UAC_OFFSET + i;
1243 codes.push(code);
1244 glyphIndex[code] = i;
1245 indices.push(i);
1246 }
1247 ranges.push([
1248 UAC_OFFSET,
1249 UAC_OFFSET + glyphCount - 1,
1250 indices
1251 ]);
1252 }
1253 var resolution = tag.resolution || 1;
1254 var ascent = Math.ceil(tag.ascent / resolution) || 1024;
1255 var descent = -Math.ceil(tag.descent / resolution) | 0;
1256 var leading = tag.leading / resolution | 0;
1257 tables['OS/2'] = '\0\x01\0\0' + toString16(tag.bold ? 700 : 400) + '\0\x05' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0\0\0\0\0\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + '\0\0\0\0' + 'ALF ' + toString16((tag.italic ? 1 : 0) | (tag.bold ? 32 : 0)) + toString16(codes[0]) + toString16(codes[codes.length - 1]) + toString16(ascent) + toString16(descent) + toString16(leading) + toString16(ascent) + toString16(-descent) + '\0\0\0\0' + '\0\0\0\0';
1258 ;
1259 var startCount = '';
1260 var endCount = '';
1261 var idDelta = '';
1262 var idRangeOffset = '';
1263 var i = 0;
1264 var range;
1265 while (range = ranges[i++]) {
1266 var start = range[0];
1267 var end = range[1];
1268 var code = range[2][0];
1269 startCount += toString16(start);
1270 endCount += toString16(end);
1271 idDelta += toString16(code - start + 1 & 65535);
1272 idRangeOffset += toString16(0);
1273 }
1274 endCount += '\xff\xff';
1275 startCount += '\xff\xff';
1276 idDelta += '\0\x01';
1277 idRangeOffset += '\0\0';
1278 var segCount = ranges.length + 1;
1279 var searchRange = maxPower2(segCount) * 2;
1280 var rangeShift = 2 * segCount - searchRange;
1281 var format314 = '\0\0' + toString16(segCount * 2) + toString16(searchRange) + toString16(logE(segCount) / logE(2)) + toString16(rangeShift) + endCount + '\0\0' + startCount + idDelta + idRangeOffset;
1282 ;
1283 tables['cmap'] = '\0\0\0\x01\0\x03\0\x01\0\0\0\f\0\x04' + toString16(format314.length + 4) + format314;
1284 ;
1285 var glyf = '\0\x01\0\0\0\0\0\0\0\0\0\0\0\x001\0';
1286 var loca = '\0\0';
1287 var offset = 16;
1288 var maxPoints = 0;
1289 var xMins = [];
1290 var xMaxs = [];
1291 var yMins = [];
1292 var yMaxs = [];
1293 var maxContours = 0;
1294 var i = 0;
1295 var code;
1296 while (code = codes[i++]) {
1297 var glyph = glyphs[glyphIndex[code]];
1298 var records = glyph.records;
1299 var numberOfContours = 1;
1300 var endPoint = 0;
1301 var endPtsOfContours = '';
1302 var flags = '';
1303 var xCoordinates = '';
1304 var yCoordinates = '';
1305 var x = 0;
1306 var y = 0;
1307 var xMin = 1024;
1308 var xMax = -1024;
1309 var yMin = 1024;
1310 var yMax = -1024;
1311 for (var j = 0, record; record = records[j]; ++j) {
1312 if (record.type) {
1313 if (record.isStraight) {
1314 if (record.isGeneral) {
1315 flags += '\x01';
1316 var dx = record.deltaX / resolution;
1317 var dy = -record.deltaY / resolution;
1318 xCoordinates += toString16(dx);
1319 yCoordinates += toString16(dy);
1320 x += dx;
1321 y += dy;
1322 } else if (record.isVertical) {
1323 flags += '\x11';
1324 var dy = -record.deltaY / resolution;
1325 yCoordinates += toString16(dy);
1326 y += dy;
1327 } else {
1328 flags += '!';
1329 var dx = record.deltaX / resolution;
1330 xCoordinates += toString16(dx);
1331 x += dx;
1332 }
1333 } else {
1334 flags += '\0';
1335 var cx = record.controlDeltaX / resolution;
1336 var cy = -record.controlDeltaY / resolution;
1337 xCoordinates += toString16(cx);
1338 yCoordinates += toString16(cy);
1339 flags += '\x01';
1340 var dx = record.anchorDeltaX / resolution;
1341 var dy = -record.anchorDeltaY / resolution;
1342 xCoordinates += toString16(dx);
1343 yCoordinates += toString16(dy);
1344 ++endPoint;
1345 x += cx + dx;
1346 y += cy + dy;
1347 }
1348 if (x < xMin)
1349 xMin = x;
1350 if (x > xMax)
1351 xMax = x;
1352 if (y < yMin)
1353 yMin = y;
1354 if (y > yMax)
1355 yMax = y;
1356 ++endPoint;
1357 } else {
1358 if (record.eos)
1359 break;
1360 if (record.move) {
1361 if (endPoint) {
1362 ++numberOfContours;
1363 endPtsOfContours += toString16(endPoint - 1);
1364 }
1365 flags += '\x01';
1366 var moveX = record.moveX / resolution;
1367 var moveY = -record.moveY / resolution;
1368 var dx = moveX - x;
1369 var dy = moveY - y;
1370 xCoordinates += toString16(dx);
1371 yCoordinates += toString16(dy);
1372 x = moveX;
1373 y = moveY;
1374 if (endPoint > maxPoints)
1375 maxPoints = endPoint;
1376 if (x < xMin)
1377 xMin = x;
1378 if (x > xMax)
1379 xMax = x;
1380 if (y < yMin)
1381 yMin = y;
1382 if (y > yMax)
1383 yMax = y;
1384 ++endPoint;
1385 }
1386 }
1387 }
1388 endPtsOfContours += toString16((endPoint || 1) - 1);
1389 if (!j) {
1390 xMin = xMax = yMin = yMax = 0;
1391 flags += '1';
1392 }
1393 var entry = toString16(numberOfContours) + toString16(xMin) + toString16(yMin) + toString16(xMax) + toString16(yMax) + endPtsOfContours + '\0\0' + flags + xCoordinates + yCoordinates;
1394 ;
1395 if (entry.length & 1)
1396 entry += '\0';
1397 glyf += entry;
1398 loca += toString16(offset / 2);
1399 offset += entry.length;
1400 xMins.push(xMin);
1401 xMaxs.push(xMax);
1402 yMins.push(yMin);
1403 yMaxs.push(yMax);
1404 if (numberOfContours > maxContours)
1405 maxContours = numberOfContours;
1406 if (endPoint > maxPoints)
1407 maxPoints = endPoint;
1408 }
1409 loca += toString16(offset / 2);
1410 tables['glyf'] = glyf;
1411 tables['head'] = '\0\x01\0\0\0\x01\0\0\0\0\0\0_\x0f<\xf5\0\v\x04\0\0\0\0\0' + toString32(Date.now()) + '\0\0\0\0' + toString32(Date.now()) + toString16(min.apply(null, xMins)) + toString16(min.apply(null, yMins)) + toString16(max.apply(null, xMaxs)) + toString16(max.apply(null, yMaxs)) + toString16((tag.italic ? 2 : 0) | (tag.bold ? 1 : 0)) + '\0\b' + '\0\x02' + '\0\0' + '\0\0';
1412 ;
1413 var advance = tag.advance;
1414 tables['hhea'] = '\0\x01\0\0' + toString16(ascent) + toString16(descent) + toString16(leading) + toString16(advance ? max.apply(null, advance) : 1024) + '\0\0' + '\0\0' + '\x03\xb8' + '\0\x01' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + toString16(glyphCount + 1);
1415 ;
1416 var hmtx = '\0\0\0\0';
1417 for (var i = 0; i < glyphCount; ++i)
1418 hmtx += toString16(advance ? advance[i] / resolution : 1024) + '\0\0';
1419 tables['hmtx'] = hmtx;
1420 if (tag.kerning) {
1421 var kerning = tag.kerning;
1422 var nPairs = kerning.length;
1423 var searchRange = maxPower2(nPairs) * 2;
1424 var kern = '\0\0\0\x01\0\0' + toString16(14 + nPairs * 6) + '\0\x01' + toString16(nPairs) + toString16(searchRange) + toString16(logE(nPairs) / logE(2)) + toString16(2 * nPairs - searchRange);
1425 ;
1426 var i = 0;
1427 var record;
1428 while (record = kerning[i++]) {
1429 kern += toString16(glyphIndex[record.code1]) + toString16(glyphIndex[record.code2]) + toString16(record.adjustment);
1430 ;
1431 }
1432 tables['kern'] = kern;
1433 }
1434 tables['loca'] = loca;
1435 tables['maxp'] = '\0\x01\0\0' + toString16(glyphCount + 1) + toString16(maxPoints) + toString16(maxContours) + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0' + '\0\0';
1436 ;
1437 var uniqueId = 'swf-font-' + nextFontId++;
1438 var fontName = tag.name || uniqueId;
1439 var psName = fontName.replace(/ /g, '');
1440 var strings = [
1441 tag.copyright || 'Original licence',
1442 fontName,
1443 'Unknown',
1444 uniqueId,
1445 fontName,
1446 '1.0',
1447 psName,
1448 'Unknown',
1449 'Unknown',
1450 'Unknown'
1451 ];
1452 var count = strings.length;
1453 var name = '\0\0' + toString16(count) + toString16(count * 12 + 6);
1454 var offset = 0;
1455 var i = 0;
1456 var str;
1457 while (str = strings[i++]) {
1458 name += '\0\x01\0\0\0\0' + toString16(i - 1) + toString16(str.length) + toString16(offset);
1459 offset += str.length;
1460 }
1461 tables['name'] = name + strings.join('');
1462 tables['post'] = '\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0';
1463 ;
1464 var names = keys(tables);
1465 var numTables = names.length;
1466 var header = '\0\x01\0\0' + toString16(numTables) + '\0\x80' + '\0\x03' + '\0 ';
1467 ;
1468 var data = '';
1469 var offset = numTables * 16 + header.length;
1470 var i = 0;
1471 var name;
1472 while (name = names[i++]) {
1473 var table = tables[name];
1474 var length = table.length;
1475 header += name + '\0\0\0\0' + toString32(offset) + toString32(length);
1476 ;
1477 while (length & 3) {
1478 table += '\0';
1479 ++length;
1480 }
1481 data += table;
1482 while (offset & 3)
1483 ++offset;
1484 offset += length;
1485 }
1486 var otf = header + data;
1487 var unitPerEm = 1024;
1488 var metrics = {
1489 ascent: ascent / unitPerEm,
1490 descent: -descent / unitPerEm,
1491 leading: leading / unitPerEm
1492 };
1493 return {
1494 type: 'font',
1495 id: tag.id,
1496 name: fontName,
1497 uniqueName: psName + uniqueId,
1498 codes: codes,
1499 metrics: metrics,
1500 bold: tag.bold === 1,
1501 italic: tag.italic === 1,
1502 data: otf
1503 };
1504 }
1505 function getUint16(buff, pos) {
1506 return buff[pos] << 8 | buff[pos + 1];
1507 }
1508 function parseJpegChunks(imgDef, bytes) {
1509 var i = 0;
1510 var n = bytes.length;
1511 var chunks = [];
1512 var code;
1513 do {
1514 var begin = i;
1515 while (i < n && bytes[i] !== 255)
1516 ++i;
1517 while (i < n && bytes[i] === 255)
1518 ++i;
1519 code = bytes[i++];
1520 if (code === 218) {
1521 i = n;
1522 } else if (code === 217) {
1523 i += 2;
1524 continue;
1525 } else if (code < 208 || code > 216) {
1526 var length = getUint16(bytes, i);
1527 if (code >= 192 && code <= 195) {
1528 imgDef.height = getUint16(bytes, i + 3);
1529 imgDef.width = getUint16(bytes, i + 5);
1530 }
1531 i += length;
1532 }
1533 chunks.push(bytes.subarray(begin, i));
1534 } while (i < n);
1535 return chunks;
1536 }
1537 function defineImage(tag, dictionary) {
1538 var img = {
1539 type: 'image',
1540 id: tag.id,
1541 mimeType: tag.mimeType
1542 };
1543 var imgData = tag.imgData;
1544 var chunks;
1545 if (tag.mimeType === 'image/jpeg') {
1546 chunks = parseJpegChunks(img, imgData);
1547 var alphaData = tag.alphaData;
1548 if (alphaData) {
1549 img.mask = createInflatedStream(alphaData, img.width * img.height).bytes;
1550 }
1551 if (tag.incomplete) {
1552 var tables = dictionary[0];
1553 var header = tables.data;
1554 if (header && header.size) {
1555 chunks[0] = chunks[0].subarray(2);
1556 chunks.unshift(header.slice(0, header.size - 2));
1557 }
1558 }
1559 } else {
1560 chunks = [
1561 imgData
1562 ];
1563 }
1564 img.data = new Blob(chunks, {
1565 type: tag.mimeType
1566 });
1567 return img;
1568 }
1569 function defineLabel(tag, dictionary) {
1570 var records = tag.records;
1571 var m = tag.matrix;
1572 var cmds = [
1573 'c.save()',
1574 'c.transform(' + [
1575 m.a,
1576 m.b,
1577 m.c,
1578 m.d,
1579 m.tx / 20,
1580 m.ty / 20
1581 ].join(',') + ')',
1582 'c.scale(0.05, 0.05)'
1583 ];
1584 var dependencies = [];
1585 var x = 0;
1586 var y = 0;
1587 var i = 0;
1588 var record;
1589 var codes;
1590 while (record = records[i++]) {
1591 if (record.eot)
1592 break;
1593 if (record.hasFont) {
1594 var font = dictionary[record.fontId];
1595 codes = font.codes;
1596 cmds.push('c.font="' + record.fontHeight + 'px \'' + font.uniqueName + '\'"');
1597 dependencies.push(font.id);
1598 }
1599 if (record.hasColor) {
1600 cmds.push('ct.setFillStyle(c,"' + rgbaObjToStr(record.color) + '")');
1601 cmds.push('ct.setAlpha(c)');
1602 } else {
1603 cmds.push('ct.setAlpha(c,true)');
1604 }
1605 if (record.hasMoveX)
1606 x = record.moveX;
1607 if (record.hasMoveY)
1608 y = record.moveY;
1609 var entries = record.entries;
1610 var j = 0;
1611 var entry;
1612 while (entry = entries[j++]) {
1613 var code = codes[entry.glyphIndex];
1614 var text = code >= 32 && code != 34 && code != 92 ? fromCharCode(code) : '\\u' + (code + 65536).toString(16).substring(1);
1615 cmds.push('c.fillText("' + text + '",' + x + ',' + y + ')');
1616 x += entry.advance;
1617 }
1618 }
1619 cmds.push('c.restore()');
1620 var label = {
1621 type: 'label',
1622 id: tag.id,
1623 bbox: tag.bbox,
1624 data: cmds.join('\n')
1625 };
1626 if (dependencies.length)
1627 label.require = dependencies;
1628 return label;
1629 }
1630 var GRAPHICS_FILL_CLIPPED_BITMAP = 65;
1631 var GRAPHICS_FILL_FOCAL_RADIAL_GRADIENT = 19;
1632 var GRAPHICS_FILL_LINEAR_GRADIENT = 16;
1633 var GRAPHICS_FILL_NONSMOOTHED_CLIPPED_BITMAP = 67;
1634 var GRAPHICS_FILL_NONSMOOTHED_REPEATING_BITMAP = 66;
1635 var GRAPHICS_FILL_RADIAL_GRADIENT = 18;
1636 var GRAPHICS_FILL_REPEATING_BITMAP = 64;
1637 var GRAPHICS_FILL_SOLID = 0;
1638 function applySegmentToStyles(segment, styles, linePaths, fillPaths, isMorph) {
1639 if (!segment) {
1640 return;
1641 }
1642 var commands = segment.commands;
1643 var data = segment.data;
1644 var morphData = segment.morphData;
1645 if (morphData) {
1646 }
1647 var path;
1648 var targetSegment;
1649 var command;
1650 var i;
1651 if (styles.fill0) {
1652 path = fillPaths[styles.fill0 - 1];
1653 if (!(styles.fill1 || styles.line)) {
1654 targetSegment = path.head();
1655 targetSegment.commands = [];
1656 targetSegment.data = [];
1657 targetSegment.morphData = isMorph ? [] : null;
1658 } else {
1659 targetSegment = path.addSegment([], [], isMorph ? [] : null);
1660 }
1661 var targetCommands = targetSegment.commands;
1662 var targetData = targetSegment.data;
1663 var targetMorphData = targetSegment.morphData;
1664 targetCommands.push(SHAPE_MOVE_TO);
1665 var j = data.length - 2;
1666 targetData.push(data[j], data[j + 1]);
1667 if (isMorph) {
1668 targetMorphData.push(morphData[j], morphData[j + 1]);
1669 }
1670 for (i = commands.length; i-- > 1; j -= 2) {
1671 command = commands[i];
1672 targetCommands.push(command);
1673 targetData.push(data[j - 2], data[j - 1]);
1674 if (isMorph) {
1675 targetMorphData.push(morphData[j - 2], morphData[j - 1]);
1676 }
1677 if (command === SHAPE_CURVE_TO) {
1678 targetData.push(data[j - 4], data[j - 3]);
1679 if (isMorph) {
1680 targetMorphData.push(morphData[j - 4], morphData[j - 3]);
1681 }
1682 j -= 2;
1683 }
1684 }
1685 if (isMorph) {
1686 }
1687 }
1688 if (styles.line && styles.fill1) {
1689 path = linePaths[styles.line - 1];
1690 path.addSegment(commands, data, morphData);
1691 }
1692 }
1693 function convertRecordsToStyledPaths(records, fillPaths, linePaths, dictionary, dependencies, recordsMorph, transferables) {
1694 var isMorph = recordsMorph !== null;
1695 var styles = {
1696 fill0: 0,
1697 fill1: 0,
1698 line: 0
1699 };
1700 var segment = null;
1701 var allPaths;
1702 var defaultPath;
1703 var numRecords = records.length - 1;
1704 var x = 0;
1705 var y = 0;
1706 var morphX = 0;
1707 var morphY = 0;
1708 var path;
1709 for (var i = 0, j = 0; i < numRecords; i++) {
1710 var record = records[i];
1711 var morphRecord;
1712 if (isMorph) {
1713 morphRecord = recordsMorph[j++];
1714 }
1715 if (record.type === 0) {
1716 if (segment) {
1717 applySegmentToStyles(segment, styles, linePaths, fillPaths, isMorph);
1718 }
1719 if (record.hasNewStyles) {
1720 if (!allPaths) {
1721 allPaths = [];
1722 }
1723 push.apply(allPaths, fillPaths);
1724 fillPaths = createPathsList(record.fillStyles, false, dictionary, dependencies);
1725 push.apply(allPaths, linePaths);
1726 linePaths = createPathsList(record.lineStyles, true, dictionary, dependencies);
1727 if (defaultPath) {
1728 allPaths.push(defaultPath);
1729 defaultPath = null;
1730 }
1731 styles = {
1732 fill0: 0,
1733 fill1: 0,
1734 line: 0
1735 };
1736 }
1737 if (record.hasFillStyle0) {
1738 styles.fill0 = record.fillStyle0;
1739 }
1740 if (record.hasFillStyle1) {
1741 styles.fill1 = record.fillStyle1;
1742 }
1743 if (record.hasLineStyle) {
1744 styles.line = record.lineStyle;
1745 }
1746 if (styles.fill1) {
1747 path = fillPaths[styles.fill1 - 1];
1748 } else if (styles.line) {
1749 path = linePaths[styles.line - 1];
1750 } else if (styles.fill0) {
1751 path = fillPaths[styles.fill0 - 1];
1752 }
1753 if (record.move) {
1754 x = record.moveX | 0;
1755 y = record.moveY | 0;
1756 }
1757 if (path) {
1758 segment = path.addSegment([], [], isMorph ? [] : null);
1759 segment.commands.push(SHAPE_MOVE_TO);
1760 segment.data.push(x, y);
1761 if (isMorph) {
1762 if (morphRecord.type === 0) {
1763 morphX = morphRecord.moveX | 0;
1764 morphY = morphRecord.moveY | 0;
1765 } else {
1766 morphX = x;
1767 morphY = y;
1768 j--;
1769 }
1770 segment.morphData.push(morphX, morphY);
1771 }
1772 }
1773 } else {
1774 if (!segment) {
1775 if (!defaultPath) {
1776 var style = {
1777 color: {
1778 red: 0,
1779 green: 0,
1780 blue: 0,
1781 alpha: 255
1782 },
1783 width: 20
1784 };
1785 defaultPath = new SegmentedPath(null, processStyle(style, true));
1786 }
1787 segment = defaultPath.addSegment([], [], isMorph ? [] : null);
1788 segment.commands.push(SHAPE_MOVE_TO);
1789 segment.data.push(x, y);
1790 if (isMorph) {
1791 segment.morphData.push(morphX, morphY);
1792 }
1793 }
1794 if (isMorph) {
1795 while (morphRecord && morphRecord.type === 0) {
1796 morphRecord = recordsMorph[j++];
1797 }
1798 if (!morphRecord) {
1799 morphRecord = record;
1800 }
1801 }
1802 if (record.isStraight && (!isMorph || morphRecord.isStraight)) {
1803 x += record.deltaX | 0;
1804 y += record.deltaY | 0;
1805 segment.commands.push(SHAPE_LINE_TO);
1806 segment.data.push(x, y);
1807 if (isMorph) {
1808 morphX += morphRecord.deltaX | 0;
1809 morphY += morphRecord.deltaY | 0;
1810 segment.morphData.push(morphX, morphY);
1811 }
1812 } else {
1813 var cx, cy;
1814 var deltaX, deltaY;
1815 if (!record.isStraight) {
1816 cx = x + record.controlDeltaX | 0;
1817 cy = y + record.controlDeltaY | 0;
1818 x = cx + record.anchorDeltaX | 0;
1819 y = cy + record.anchorDeltaY | 0;
1820 } else {
1821 deltaX = record.deltaX | 0;
1822 deltaY = record.deltaY | 0;
1823 cx = x + (deltaX >> 1);
1824 cy = y + (deltaY >> 1);
1825 x += deltaX;
1826 y += deltaY;
1827 }
1828 segment.commands.push(SHAPE_CURVE_TO);
1829 segment.data.push(cx, cy, x, y);
1830 if (isMorph) {
1831 if (!morphRecord.isStraight) {
1832 cx = morphX + morphRecord.controlDeltaX | 0;
1833 cy = morphY + morphRecord.controlDeltaY | 0;
1834 morphX = cx + morphRecord.anchorDeltaX | 0;
1835 morphY = cy + morphRecord.anchorDeltaY | 0;
1836 } else {
1837 deltaX = morphRecord.deltaX | 0;
1838 deltaY = morphRecord.deltaY | 0;
1839 cx = morphX + (deltaX >> 1);
1840 cy = morphY + (deltaY >> 1);
1841 morphX += deltaX;
1842 morphY += deltaY;
1843 }
1844 segment.morphData.push(cx, cy, morphX, morphY);
1845 }
1846 }
1847 }
1848 }
1849 applySegmentToStyles(segment, styles, linePaths, fillPaths, isMorph);
1850 if (allPaths) {
1851 push.apply(allPaths, fillPaths);
1852 } else {
1853 allPaths = fillPaths;
1854 }
1855 push.apply(allPaths, linePaths);
1856 if (defaultPath) {
1857 allPaths.push(defaultPath);
1858 }
1859 var removeCount = 0;
1860 for (i = 0; i < allPaths.length; i++) {
1861 path = allPaths[i];
1862 if (!path.head()) {
1863 removeCount++;
1864 continue;
1865 }
1866 allPaths[i - removeCount] = segmentedPathToShapePath(path, isMorph, transferables);
1867 }
1868 allPaths.length -= removeCount;
1869 return allPaths;
1870 }
1871 function segmentedPathToShapePath(path, isMorph, transferables) {
1872 var start = path.head();
1873 var end = start;
1874 var finalRoot = null;
1875 var finalHead = null;
1876 var skippedMoves = 0;
1877 var current = start.prev;
1878 while (start) {
1879 while (current) {
1880 if (path.segmentsConnect(current, start)) {
1881 if (current.next !== start) {
1882 path.removeSegment(current);
1883 path.insertSegment(current, start);
1884 }
1885 start = current;
1886 current = start.prev;
1887 skippedMoves++;
1888 continue;
1889 }
1890 if (path.segmentsConnect(end, current)) {
1891 path.removeSegment(current);
1892 end.next = current;
1893 current = current.prev;
1894 end.next.prev = end;
1895 end.next.next = null;
1896 end = end.next;
1897 skippedMoves++;
1898 continue;
1899 }
1900 current = current.prev;
1901 }
1902 current = start.prev;
1903 if (!finalRoot) {
1904 finalRoot = start;
1905 finalHead = end;
1906 } else {
1907 finalHead.next = start;
1908 start.prev = finalHead;
1909 finalHead = end;
1910 finalHead.next = null;
1911 }
1912 if (!current) {
1913 break;
1914 }
1915 start = end = current;
1916 current = start.prev;
1917 }
1918 var totalCommandsLength = -skippedMoves;
1919 var totalDataLength = -skippedMoves << 1;
1920 current = finalRoot;
1921 while (current) {
1922 totalCommandsLength += current.commands.length;
1923 totalDataLength += current.data.length;
1924 current = current.next;
1925 }
1926 var shape = new ShapePath(path.fillStyle, path.lineStyle, totalCommandsLength, totalDataLength, isMorph, transferables);
1927 var allCommands = shape.commands;
1928 var allData = shape.data;
1929 var allMorphData = shape.morphData;
1930 var commandsIndex = 0;
1931 var dataIndex = 0;
1932 current = finalRoot;
1933 while (current) {
1934 var commands = current.commands;
1935 var data = current.data;
1936 var morphData = current.morphData;
1937 var offset = +(data[0] === allData[dataIndex - 2] && data[1] === allData[dataIndex - 1]);
1938 for (var i = offset; i < commands.length; i++, commandsIndex++) {
1939 allCommands[commandsIndex] = commands[i];
1940 }
1941 for (i = offset << 1; i < data.length; i++, dataIndex++) {
1942 allData[dataIndex] = data[i];
1943 if (isMorph) {
1944 allMorphData[dataIndex] = morphData[i];
1945 }
1946 }
1947 current = current.next;
1948 }
1949 return shape;
1950 }
1951 var CAPS_STYLE_TYPES = [
1952 'round',
1953 'none',
1954 'square'
1955 ];
1956 var JOIN_STYLE_TYPES = [
1957 'round',
1958 'bevel',
1959 'miter'
1960 ];
1961 function processStyle(style, isLineStyle, dictionary, dependencies) {
1962 if (isLineStyle) {
1963 style.lineCap = CAPS_STYLE_TYPES[style.endCapStyle | 0];
1964 style.lineJoin = JOIN_STYLE_TYPES[style.joinStyle | 0];
1965 style.miterLimit = (style.miterLimitFactor || 1.5) * 2;
1966 if (!style.color && style.hasFill) {
1967 var fillStyle = processStyle(style.fillStyle, false, dictionary, dependencies);
1968 style.style = fillStyle.style;
1969 style.type = fillStyle.type;
1970 style.transform = fillStyle.transform;
1971 style.records = fillStyle.records;
1972 style.focalPoint = fillStyle.focalPoint;
1973 style.bitmapId = fillStyle.bitmapId;
1974 style.repeat = fillStyle.repeat;
1975 style.fillStyle = null;
1976 return style;
1977 }
1978 }
1979 var color;
1980 if (style.type === undefined || style.type === GRAPHICS_FILL_SOLID) {
1981 color = style.color;
1982 style.style = 'rgba(' + color.red + ',' + color.green + ',' + color.blue + ',' + color.alpha / 255 + ')';
1983 style.color = null;
1984 return style;
1985 }
1986 var scale;
1987 switch (style.type) {
1988 case GRAPHICS_FILL_LINEAR_GRADIENT:
1989 case GRAPHICS_FILL_RADIAL_GRADIENT:
1990 case GRAPHICS_FILL_FOCAL_RADIAL_GRADIENT:
1991 scale = 819.2;
1992 break;
1993 case GRAPHICS_FILL_REPEATING_BITMAP:
1994 case GRAPHICS_FILL_CLIPPED_BITMAP:
1995 case GRAPHICS_FILL_NONSMOOTHED_REPEATING_BITMAP:
1996 case GRAPHICS_FILL_NONSMOOTHED_CLIPPED_BITMAP:
1997 if (dictionary[style.bitmapId]) {
1998 dependencies.push(dictionary[style.bitmapId].id);
1999 scale = 0.05;
2000 }
2001 break;
2002 default:
2003 fail('invalid fill style', 'shape');
2004 }
2005 if (!style.matrix) {
2006 return style;
2007 }
2008 var matrix = style.matrix;
2009 style.transform = {
2010 a: matrix.a * scale,
2011 b: matrix.b * scale,
2012 c: matrix.c * scale,
2013 d: matrix.d * scale,
2014 e: matrix.tx,
2015 f: matrix.ty
2016 };
2017 style.matrix = null;
2018 return style;
2019 }
2020 function createPathsList(styles, isLineStyle, dictionary, dependencies) {
2021 var paths = [];
2022 for (var i = 0; i < styles.length; i++) {
2023 var style = processStyle(styles[i], isLineStyle, dictionary, dependencies);
2024 if (!isLineStyle) {
2025 paths[i] = new SegmentedPath(style, null);
2026 } else {
2027 paths[i] = new SegmentedPath(null, style);
2028 }
2029 }
2030 return paths;
2031 }
2032 function defineShape(tag, dictionary) {
2033 var dependencies = [];
2034 var transferables = [];
2035 var fillPaths = createPathsList(tag.fillStyles, false, dictionary, dependencies);
2036 var linePaths = createPathsList(tag.lineStyles, true, dictionary, dependencies);
2037 var paths = convertRecordsToStyledPaths(tag.records, fillPaths, linePaths, dictionary, dependencies, tag.recordsMorph || null, transferables);
2038 if (tag.bboxMorph) {
2039 var mbox = tag.bboxMorph;
2040 extendBoundsByPoint(tag.bbox, mbox.xMin, mbox.yMin);
2041 extendBoundsByPoint(tag.bbox, mbox.xMax, mbox.yMax);
2042 mbox = tag.strokeBboxMorph;
2043 if (mbox) {
2044 extendBoundsByPoint(tag.strokeBbox, mbox.xMin, mbox.yMin);
2045 extendBoundsByPoint(tag.strokeBbox, mbox.xMax, mbox.yMax);
2046 }
2047 }
2048 return {
2049 type: 'shape',
2050 id: tag.id,
2051 strokeBbox: tag.strokeBbox,
2052 strokeBboxMorph: tag.strokeBboxMorph,
2053 bbox: tag.bbox,
2054 bboxMorph: tag.bboxMorph,
2055 isMorph: tag.isMorph,
2056 paths: paths,
2057 require: dependencies.length ? dependencies : null,
2058 transferables: transferables
2059 };
2060 }
2061 function logShape(paths, bbox) {
2062 var output = '{"bounds":' + JSON.stringify(bbox) + ',"paths":[' + paths.map(function (path) {
2063 return path.serialize();
2064 }).join() + ']}';
2065 console.log(output);
2066 }
2067 function SegmentedPath(fillStyle, lineStyle) {
2068 this.fillStyle = fillStyle;
2069 this.lineStyle = lineStyle;
2070 this._head = null;
2071 }
2072 SegmentedPath.prototype = {
2073 addSegment: function (commands, data, morphData) {
2074 var segment = {
2075 commands: commands,
2076 data: data,
2077 morphData: morphData,
2078 prev: this._head,
2079 next: null
2080 };
2081 if (this._head) {
2082 this._head.next = segment;
2083 }
2084 this._head = segment;
2085 return segment;
2086 },
2087 removeSegment: function (segment) {
2088 if (segment.prev) {
2089 segment.prev.next = segment.next;
2090 }
2091 if (segment.next) {
2092 segment.next.prev = segment.prev;
2093 }
2094 },
2095 insertSegment: function (segment, next) {
2096 var prev = next.prev;
2097 segment.prev = prev;
2098 segment.next = next;
2099 if (prev) {
2100 prev.next = segment;
2101 }
2102 next.prev = segment;
2103 },
2104 head: function () {
2105 return this._head;
2106 },
2107 segmentsConnect: function (first, second) {
2108 var firstLength = first.data.length;
2109 return first.data[firstLength - 2] === second.data[0] && first.data[firstLength - 1] === second.data[1];
2110 }
2111 };
2112 var SHAPE_MOVE_TO = 1;
2113 var SHAPE_LINE_TO = 2;
2114 var SHAPE_CURVE_TO = 3;
2115 var SHAPE_WIDE_MOVE_TO = 4;
2116 var SHAPE_WIDE_LINE_TO = 5;
2117 var SHAPE_CUBIC_CURVE_TO = 6;
2118 var SHAPE_CIRCLE = 7;
2119 var SHAPE_ELLIPSE = 8;
2120 function ShapePath(fillStyle, lineStyle, commandsCount, dataLength, isMorph, transferables) {
2121 this.fillStyle = fillStyle;
2122 this.lineStyle = lineStyle;
2123 if (commandsCount) {
2124 this.commands = new Uint8Array(commandsCount);
2125 this.data = new Int32Array(dataLength);
2126 this.morphData = isMorph ? new Int32Array(dataLength) : null;
2127 } else {
2128 this.commands = [];
2129 this.data = [];
2130 }
2131 this.bounds = null;
2132 this.strokeBounds = null;
2133 this.isMorph = !(!isMorph);
2134 this.fullyInitialized = false;
2135 if (inWorker) {
2136 this.buffers = [
2137 this.commands.buffer,
2138 this.data.buffer
2139 ];
2140 transferables.push(this.commands.buffer, this.data.buffer);
2141 if (isMorph) {
2142 this.buffers.push(this.morphData.buffer);
2143 transferables.push(this.morphData.buffer);
2144 }
2145 } else {
2146 this.buffers = null;
2147 }
2148 }
2149 ShapePath.prototype = {
2150 get isEmpty() {
2151 return this.commands.length === 0;
2152 },
2153 moveTo: function (x, y) {
2154 if (this.commands[this.commands.length - 1] === SHAPE_MOVE_TO) {
2155 this.data[this.data.length - 2] = x;
2156 this.data[this.data.length - 1] = y;
2157 return;
2158 }
2159 this.commands.push(SHAPE_MOVE_TO);
2160 this.data.push(x, y);
2161 },
2162 lineTo: function (x, y) {
2163 this.commands.push(SHAPE_LINE_TO);
2164 this.data.push(x, y);
2165 },
2166 curveTo: function (controlX, controlY, anchorX, anchorY) {
2167 this.commands.push(SHAPE_CURVE_TO);
2168 this.data.push(controlX, controlY, anchorX, anchorY);
2169 },
2170 cubicCurveTo: function (control1X, control1Y, control2X, control2Y, anchorX, anchorY) {
2171 this.commands.push(SHAPE_CUBIC_CURVE_TO);
2172 this.data.push(control1X, control1Y, control2X, control2Y, anchorX, anchorY);
2173 },
2174 rect: function (x, y, w, h) {
2175 var x2 = x + w;
2176 var y2 = y + h;
2177 this.commands.push(SHAPE_MOVE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO, SHAPE_LINE_TO);
2178 this.data.push(x, y, x2, y, x2, y2, x, y2, x, y);
2179 },
2180 circle: function (x, y, radius) {
2181 this.commands.push(SHAPE_CIRCLE);
2182 this.data.push(x, y, radius);
2183 },
2184 ellipse: function (x, y, radiusX, radiusY) {
2185 this.commands.push(SHAPE_ELLIPSE);
2186 this.data.push(x, y, radiusX, radiusY);
2187 },
2188 draw: function (ctx, clip, ratio, colorTransform) {
2189 if (clip && !this.fillStyle) {
2190 return;
2191 }
2192 ctx.beginPath();
2193 var commands = this.commands;
2194 var data = this.data;
2195 var morphData = this.morphData;
2196 var formOpen = false;
2197 var formOpenX = 0;
2198 var formOpenY = 0;
2199 if (!this.isMorph) {
2200 for (var j = 0, k = 0; j < commands.length; j++) {
2201 switch (commands[j]) {
2202 case SHAPE_MOVE_TO:
2203 formOpen = true;
2204 formOpenX = data[k++] / 20;
2205 formOpenY = data[k++] / 20;
2206 ctx.moveTo(formOpenX, formOpenY);
2207 break;
2208 case SHAPE_WIDE_MOVE_TO:
2209 ctx.moveTo(data[k++] / 20, data[k++] / 20);
2210 k += 2;
2211 break;
2212 case SHAPE_LINE_TO:
2213 ctx.lineTo(data[k++] / 20, data[k++] / 20);
2214 break;
2215 case SHAPE_WIDE_LINE_TO:
2216 ctx.lineTo(data[k++] / 20, data[k++] / 20);
2217 k += 2;
2218 break;
2219 case SHAPE_CURVE_TO:
2220 ctx.quadraticCurveTo(data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20);
2221 break;
2222 case SHAPE_CUBIC_CURVE_TO:
2223 ctx.bezierCurveTo(data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20, data[k++] / 20);
2224 break;
2225 case SHAPE_CIRCLE:
2226 if (formOpen) {
2227 ctx.lineTo(formOpenX, formOpenY);
2228 formOpen = false;
2229 }
2230 ctx.moveTo((data[k] + data[k + 2]) / 20, data[k + 1] / 20);
2231 ctx.arc(data[k++] / 20, data[k++] / 20, data[k++] / 20, 0, Math.PI * 2, false);
2232 break;
2233 case SHAPE_ELLIPSE:
2234 if (formOpen) {
2235 ctx.lineTo(formOpenX, formOpenY);
2236 formOpen = false;
2237 }
2238 var x = data[k++];
2239 var y = data[k++];
2240 var rX = data[k++];
2241 var rY = data[k++];
2242 var radius;
2243 if (rX !== rY) {
2244 ctx.save();
2245 var ellipseScale;
2246 if (rX > rY) {
2247 ellipseScale = rX / rY;
2248 radius = rY;
2249 x /= ellipseScale;
2250 ctx.scale(ellipseScale, 1);
2251 } else {
2252 ellipseScale = rY / rX;
2253 radius = rX;
2254 y /= ellipseScale;
2255 ctx.scale(1, ellipseScale);
2256 }
2257 }
2258 ctx.moveTo((x + radius) / 20, y / 20);
2259 ctx.arc(x / 20, y / 20, radius / 20, 0, Math.PI * 2, false);
2260 if (rX !== rY) {
2261 ctx.restore();
2262 }
2263 break;
2264 default:
2265 if (commands[j] === 0 && j === commands.length - 1) {
2266 break;
2267 }
2268 console.warn('Unknown drawing command encountered: ' + commands[j]);
2269 }
2270 }
2271 } else {
2272 for (var j = 0, k = 0; j < commands.length; j++) {
2273 switch (commands[j]) {
2274 case SHAPE_MOVE_TO:
2275 ctx.moveTo(morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio));
2276 break;
2277 case SHAPE_LINE_TO:
2278 ctx.lineTo(morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio));
2279 break;
2280 case SHAPE_CURVE_TO:
2281 ctx.quadraticCurveTo(morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio), morph(data[k] / 20, morphData[k++] / 20, ratio));
2282 break;
2283 default:
2284 console.warn('Drawing command not supported for morph shapes: ' + commands[j]);
2285 }
2286 }
2287 }
2288 if (!clip) {
2289 var fillStyle = this.fillStyle;
2290 if (fillStyle) {
2291 colorTransform.setFillStyle(ctx, fillStyle.style);
2292 ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = fillStyle.smooth;
2293 var m = fillStyle.transform;
2294 ctx.save();
2295 colorTransform.setAlpha(ctx);
2296 if (m) {
2297 ctx.transform(m.a, m.b, m.c, m.d, m.e / 20, m.f / 20);
2298 }
2299 ctx.fill();
2300 ctx.restore();
2301 }
2302 var lineStyle = this.lineStyle;
2303 if (lineStyle) {
2304 colorTransform.setStrokeStyle(ctx, lineStyle.style);
2305 ctx.save();
2306 colorTransform.setAlpha(ctx);
2307 ctx.lineWidth = Math.max(lineStyle.width / 20, 1);
2308 ctx.lineCap = lineStyle.lineCap;
2309 ctx.lineJoin = lineStyle.lineJoin;
2310 ctx.miterLimit = lineStyle.miterLimit;
2311 ctx.stroke();
2312 ctx.restore();
2313 }
2314 } else {
2315 ctx.fill();
2316 }
2317 ctx.closePath();
2318 },
2319 isPointInPath: function (x, y) {
2320 if (!(this.fillStyle || this.lineStyle)) {
2321 return false;
2322 }
2323 var bounds = this.strokeBounds || this.bounds || this._calculateBounds();
2324 if (x < bounds.xMin || x > bounds.xMax || y < bounds.yMin || y > bounds.yMax) {
2325 return false;
2326 }
2327 if (this.fillStyle && this.isPointInFill(x, y)) {
2328 return true;
2329 }
2330 return this.lineStyle && this.lineStyle.width !== undefined && this.isPointInStroke(x, y);
2331 },
2332 isPointInFill: function (x, y) {
2333 var commands = this.commands;
2334 var data = this.data;
2335 var length = commands.length;
2336 var inside = false;
2337 var fromX = 0;
2338 var fromY = 0;
2339 var toX = 0;
2340 var toY = 0;
2341 var localX;
2342 var localY;
2343 var cpX;
2344 var cpY;
2345 var rX;
2346 var rY;
2347 var formOpen = false;
2348 var formOpenX = 0;
2349 var formOpenY = 0;
2350 for (var commandIndex = 0, dataIndex = 0; commandIndex < length; commandIndex++) {
2351 switch (commands[commandIndex]) {
2352 case SHAPE_WIDE_MOVE_TO:
2353 dataIndex += 2;
2354 case SHAPE_MOVE_TO:
2355 toX = data[dataIndex++];
2356 toY = data[dataIndex++];
2357 if (formOpen && intersectsLine(x, y, fromX, fromY, formOpenX, formOpenY)) {
2358 inside = !inside;
2359 }
2360 formOpen = true;
2361 formOpenX = toX;
2362 formOpenY = toY;
2363 break;
2364 case SHAPE_WIDE_LINE_TO:
2365 dataIndex += 2;
2366 case SHAPE_LINE_TO:
2367 toX = data[dataIndex++];
2368 toY = data[dataIndex++];
2369 if (intersectsLine(x, y, fromX, fromY, toX, toY)) {
2370 inside = !inside;
2371 }
2372 break;
2373 case SHAPE_CURVE_TO:
2374 cpX = data[dataIndex++];
2375 cpY = data[dataIndex++];
2376 toX = data[dataIndex++];
2377 toY = data[dataIndex++];
2378 if (cpY > y === fromY > y && toY > y === fromY > y) {
2379 break;
2380 }
2381 if (fromX >= x && cpX >= x && toX >= x) {
2382 inside = !inside;
2383 break;
2384 }
2385 var a = fromY - 2 * cpY + toY;
2386 var c = fromY - y;
2387 var b = 2 * (cpY - fromY);
2388 var d = b * b - 4 * a * c;
2389 if (d < 0) {
2390 break;
2391 }
2392 d = Math.sqrt(d);
2393 a = 1 / (a + a);
2394 var t1 = (d - b) * a;
2395 var t2 = (-b - d) * a;
2396 if (t1 >= 0 && t1 <= 1 && quadraticBezier(fromX, cpX, toX, t1) > x) {
2397 inside = !inside;
2398 }
2399 if (t2 >= 0 && t2 <= 1 && quadraticBezier(fromX, cpX, toX, t2) > x) {
2400 inside = !inside;
2401 }
2402 break;
2403 case SHAPE_CUBIC_CURVE_TO:
2404 cpX = data[dataIndex++];
2405 cpY = data[dataIndex++];
2406 var cp2X = data[dataIndex++];
2407 var cp2Y = data[dataIndex++];
2408 toX = data[dataIndex++];
2409 toY = data[dataIndex++];
2410 if (cpY > y === fromY > y && cp2Y > y === fromY > y && toY > y === fromY > y) {
2411 break;
2412 }
2413 if (fromX >= x && cpX >= x && cp2X >= x && toX >= x) {
2414 inside = !inside;
2415 break;
2416 }
2417 var roots = cubicXAtY(fromX, fromY, cpX, cpY, cp2X, cp2Y, toX, toY, y);
2418 for (var i = roots.length; i--;) {
2419 if (roots[i] >= x) {
2420 inside = !inside;
2421 }
2422 }
2423 break;
2424 case SHAPE_CIRCLE:
2425 toX = data[dataIndex++];
2426 toY = data[dataIndex++];
2427 var r = data[dataIndex++];
2428 localX = x - toX;
2429 localY = y - toY;
2430 if (localX * localX + localY * localY < r * r) {
2431 inside = !inside;
2432 }
2433 toX += r;
2434 break;
2435 case SHAPE_ELLIPSE:
2436 cpX = data[dataIndex++];
2437 cpY = data[dataIndex++];
2438 rX = data[dataIndex++];
2439 rY = data[dataIndex++];
2440 localX = x - cpX;
2441 localY = y - cpY;
2442 if (localX * localX / (rX * rX) + localY * localY / (rY * rY) <= 1) {
2443 inside = !inside;
2444 }
2445 toX = cpX + rX;
2446 toY = cpY;
2447 break;
2448 default:
2449 if (!inWorker) {
2450 console.warn('Drawing command not handled in isPointInPath: ' + commands[commandIndex]);
2451 }
2452 }
2453 fromX = toX;
2454 fromY = toY;
2455 }
2456 if (formOpen && intersectsLine(x, y, fromX, fromY, formOpenX, formOpenY)) {
2457 inside = !inside;
2458 }
2459 return inside;
2460 },
2461 isPointInStroke: function (x, y) {
2462 var commands = this.commands;
2463 var data = this.data;
2464 var length = commands.length;
2465 var width = this.lineStyle.width;
2466 var halfWidth = width / 2;
2467 var halfWidthSq = halfWidth * halfWidth;
2468 var minX = x - halfWidth;
2469 var maxX = x + halfWidth;
2470 var minY = y - halfWidth;
2471 var maxY = y + halfWidth;
2472 var fromX = 0;
2473 var fromY = 0;
2474 var toX = 0;
2475 var toY = 0;
2476 var localX;
2477 var localY;
2478 var cpX;
2479 var cpY;
2480 var rX;
2481 var rY;
2482 var curveX;
2483 var curveY;
2484 var t;
2485 for (var commandIndex = 0, dataIndex = 0; commandIndex < length; commandIndex++) {
2486 switch (commands[commandIndex]) {
2487 case SHAPE_WIDE_MOVE_TO:
2488 dataIndex += 2;
2489 case SHAPE_MOVE_TO:
2490 toX = data[dataIndex++];
2491 toY = data[dataIndex++];
2492 break;
2493 case SHAPE_WIDE_LINE_TO:
2494 dataIndex += 2;
2495 case SHAPE_LINE_TO:
2496 toX = data[dataIndex++];
2497 toY = data[dataIndex++];
2498 if (fromX === toX && fromY === toY) {
2499 break;
2500 }
2501 if (maxX < fromX && maxX < toX || minX > fromX && minX > toX || maxY < fromY && maxY < toY || minY > fromY && minY > toY) {
2502 break;
2503 }
2504 if (toX === fromX || toY === fromY) {
2505 return true;
2506 }
2507 t = ((x - fromX) * (toX - fromX) + (y - fromY) * (toY - fromY)) / distanceSq(fromX, fromY, toX, toY);
2508 if (t < 0) {
2509 if (distanceSq(x, y, fromX, fromY) <= halfWidthSq) {
2510 return true;
2511 }
2512 break;
2513 }
2514 if (t > 1) {
2515 if (distanceSq(x, y, toX, toY) <= halfWidthSq) {
2516 return true;
2517 }
2518 break;
2519 }
2520 if (distanceSq(x, y, fromX + t * (toX - fromX), fromY + t * (toY - fromY)) <= halfWidthSq) {
2521 return true;
2522 }
2523 break;
2524 case SHAPE_CURVE_TO:
2525 cpX = data[dataIndex++];
2526 cpY = data[dataIndex++];
2527 toX = data[dataIndex++];
2528 toY = data[dataIndex++];
2529 var extremeX = quadraticBezierExtreme(fromX, cpX, toX);
2530 if (maxX < fromX && maxX < extremeX && maxX < toX || minX > fromX && minX > extremeX && minX > toX) {
2531 break;
2532 }
2533 var extremeY = quadraticBezierExtreme(fromY, cpY, toY);
2534 if (maxY < fromY && maxY < extremeY && maxY < toY || minY > fromY && minY > extremeY && minY > toY) {
2535 break;
2536 }
2537 for (t = 0; t < 1; t += 0.02) {
2538 curveX = quadraticBezier(fromX, cpX, toX, t);
2539 if (curveX < minX || curveX > maxX) {
2540 continue;
2541 }
2542 curveY = quadraticBezier(fromY, cpY, toY, t);
2543 if (curveY < minY || curveY > maxY) {
2544 continue;
2545 }
2546 if ((x - curveX) * (x - curveX) + (y - curveY) * (y - curveY) < halfWidthSq) {
2547 return true;
2548 }
2549 }
2550 break;
2551 case SHAPE_CUBIC_CURVE_TO:
2552 cpX = data[dataIndex++];
2553 cpY = data[dataIndex++];
2554 var cp2X = data[dataIndex++];
2555 var cp2Y = data[dataIndex++];
2556 toX = data[dataIndex++];
2557 toY = data[dataIndex++];
2558 var extremesX = cubicBezierExtremes(fromX, cpX, cp2X, toX);
2559 while (extremesX.length < 2) {
2560 extremesX.push(toX);
2561 }
2562 if (maxX < fromX && maxX < toX && maxX < extremesX[0] && maxX < extremesX[1] || minX > fromX && minX > toX && minX > extremesX[0] && minX > extremesX[1]) {
2563 break;
2564 }
2565 var extremesY = cubicBezierExtremes(fromY, cpY, cp2Y, toY);
2566 while (extremesY.length < 2) {
2567 extremesY.push(toY);
2568 }
2569 if (maxY < fromY && maxY < toY && maxY < extremesY[0] && maxY < extremesY[1] || minY > fromY && minY > toY && minY > extremesY[0] && minY > extremesY[1]) {
2570 break;
2571 }
2572 for (t = 0; t < 1; t += 0.02) {
2573 curveX = cubicBezier(fromX, cpX, cp2X, toX, t);
2574 if (curveX < minX || curveX > maxX) {
2575 continue;
2576 }
2577 curveY = cubicBezier(fromY, cpY, cp2Y, toY, t);
2578 if (curveY < minY || curveY > maxY) {
2579 continue;
2580 }
2581 if ((x - curveX) * (x - curveX) + (y - curveY) * (y - curveY) < halfWidthSq) {
2582 return true;
2583 }
2584 }
2585 break;
2586 case SHAPE_CIRCLE:
2587 cpX = data[dataIndex++];
2588 cpY = data[dataIndex++];
2589 var r = data[dataIndex++];
2590 toX = cpX + r;
2591 toY = cpY;
2592 if (maxX < cpX - r || minX > cpX + r || maxY < cpY - r || minY > cpY + r) {
2593 break;
2594 }
2595 localX = x - cpX;
2596 localY = y - cpY;
2597 var rMin = r - halfWidth;
2598 var rMax = r + halfWidth;
2599 var distSq = localX * localX + localY * localY;
2600 if (distSq >= rMin * rMin && distSq <= rMax * rMax) {
2601 return true;
2602 }
2603 break;
2604 case SHAPE_ELLIPSE:
2605 cpX = data[dataIndex++];
2606 cpY = data[dataIndex++];
2607 rX = data[dataIndex++];
2608 rY = data[dataIndex++];
2609 toX = cpX + rX;
2610 toY = cpY;
2611 localX = Math.abs(x - cpX);
2612 localY = Math.abs(y - cpY);
2613 localX -= halfWidth;
2614 localY -= halfWidth;
2615 if (localX * localX / (rX * rX) + localY * localY / (rY * rY) > 1) {
2616 break;
2617 }
2618 localX += width;
2619 localY += width;
2620 if (localX * localX / (rX * rX) + localY * localY / (rY * rY) > 1) {
2621 return true;
2622 }
2623 break;
2624 default:
2625 if (!inWorker) {
2626 console.warn('Drawing command not handled in isPointInPath: ' + commands[commandIndex]);
2627 }
2628 }
2629 fromX = toX;
2630 fromY = toY;
2631 }
2632 return false;
2633 },
2634 getBounds: function (includeStroke) {
2635 var bounds = includeStroke ? this.strokeBounds : this.bounds;
2636 if (!bounds) {
2637 this._calculateBounds();
2638 bounds = includeStroke ? this.strokeBounds : this.bounds;
2639 }
2640 return bounds;
2641 },
2642 _calculateBounds: function () {
2643 var commands = this.commands;
2644 var data = this.data;
2645 var length = commands.length;
2646 var bounds;
2647 if (commands[0] === SHAPE_MOVE_TO || commands[0] > SHAPE_CUBIC_CURVE_TO) {
2648 bounds = {
2649 xMin: data[0],
2650 yMin: data[1]
2651 };
2652 } else {
2653 bounds = {
2654 xMin: 0,
2655 yMin: 0
2656 };
2657 }
2658 bounds.xMax = bounds.xMin;
2659 bounds.yMax = bounds.yMin;
2660 var fromX = bounds.xMin;
2661 var fromY = bounds.yMin;
2662 for (var commandIndex = 0, dataIndex = 0; commandIndex < length; commandIndex++) {
2663 var toX;
2664 var toY;
2665 var cpX;
2666 var cpY;
2667 switch (commands[commandIndex]) {
2668 case SHAPE_WIDE_MOVE_TO:
2669 dataIndex += 2;
2670 case SHAPE_MOVE_TO:
2671 toX = data[dataIndex++];
2672 toY = data[dataIndex++];
2673 extendBoundsByPoint(bounds, toX, toY);
2674 break;
2675 case SHAPE_WIDE_LINE_TO:
2676 dataIndex += 2;
2677 case SHAPE_LINE_TO:
2678 toX = data[dataIndex++];
2679 toY = data[dataIndex++];
2680 extendBoundsByPoint(bounds, toX, toY);
2681 break;
2682 case SHAPE_CURVE_TO:
2683 cpX = data[dataIndex++];
2684 cpY = data[dataIndex++];
2685 toX = data[dataIndex++];
2686 toY = data[dataIndex++];
2687 extendBoundsByPoint(bounds, toX, toY);
2688 if (cpX < fromX || cpX > toX) {
2689 extendBoundsByX(bounds, quadraticBezierExtreme(fromX, cpX, toX));
2690 }
2691 if (cpY < fromY || cpY > toY) {
2692 extendBoundsByY(bounds, quadraticBezierExtreme(fromY, cpY, toY));
2693 }
2694 break;
2695 case SHAPE_CUBIC_CURVE_TO:
2696 cpX = data[dataIndex++];
2697 cpY = data[dataIndex++];
2698 var cp2X = data[dataIndex++];
2699 var cp2Y = data[dataIndex++];
2700 toX = data[dataIndex++];
2701 toY = data[dataIndex++];
2702 extendBoundsByPoint(bounds, toX, toY);
2703 var extremes;
2704 var i;
2705 if (cpX < fromX || cp2X < fromX || cpX > toX || cp2X > toX) {
2706 extremes = cubicBezierExtremes(fromX, cpX, cp2X, toX);
2707 for (i = extremes.length; i--;) {
2708 extendBoundsByX(bounds, extremes[i]);
2709 }
2710 }
2711 if (cpY < fromY || cp2Y < fromY || cpY > toY || cp2Y > toY) {
2712 extremes = cubicBezierExtremes(fromY, cpY, cp2Y, toY);
2713 for (i = extremes.length; i--;) {
2714 extendBoundsByY(bounds, extremes[i]);
2715 }
2716 }
2717 break;
2718 case SHAPE_CIRCLE:
2719 toX = data[dataIndex++];
2720 toY = data[dataIndex++];
2721 var radius = data[dataIndex++];
2722 extendBoundsByPoint(bounds, toX - radius, toY - radius);
2723 extendBoundsByPoint(bounds, toX + radius, toY + radius);
2724 toX += radius;
2725 break;
2726 case SHAPE_ELLIPSE:
2727 toX = data[dataIndex++];
2728 toY = data[dataIndex++];
2729 var radiusX = data[dataIndex++];
2730 var radiusY = data[dataIndex++];
2731 extendBoundsByPoint(bounds, toX - radiusX, toY - radiusY);
2732 extendBoundsByPoint(bounds, toX + radiusX, toY + radiusY);
2733 toX += radiusX;
2734 break;
2735 default:
2736 if (!inWorker) {
2737 console.warn('Drawing command not handled in bounds calculation: ' + commands[commandIndex]);
2738 }
2739 }
2740 fromX = toX;
2741 fromY = toY;
2742 }
2743 this.bounds = bounds;
2744 if (this.lineStyle) {
2745 var halfLineWidth = this.lineStyle.width / 2;
2746 this.strokeBounds = {
2747 xMin: bounds.xMin - halfLineWidth,
2748 yMin: bounds.yMin - halfLineWidth,
2749 xMax: bounds.xMax + halfLineWidth,
2750 yMax: bounds.yMax + halfLineWidth
2751 };
2752 return this.strokeBounds;
2753 } else {
2754 this.strokeBounds = bounds;
2755 }
2756 return bounds;
2757 },
2758 serialize: function () {
2759 var output = '{';
2760 if (this.fillStyle) {
2761 output += '"fill":' + JSON.stringify(this.fillStyle) + ',';
2762 }
2763 if (this.lineStyle) {
2764 output += '"stroke":' + JSON.stringify(this.lineStyle) + ',';
2765 }
2766 output += '"commands":[' + Array.apply([], this.commands).join() + '],';
2767 output += '"data":[' + Array.apply([], this.data).join() + ']';
2768 return output + '}';
2769 }
2770 };
2771 ShapePath.fromPlainObject = function (obj) {
2772 var path = new ShapePath(obj.fill || null, obj.stroke || null);
2773 path.commands = new Uint8Array(obj.commands);
2774 path.data = new Int32Array(obj.data);
2775 if (!inWorker) {
2776 finishShapePath(path);
2777 }
2778 return path;
2779 };
2780 function distanceSq(x1, y1, x2, y2) {
2781 var dX = x2 - x1;
2782 var dY = y2 - y1;
2783 return dX * dX + dY * dY;
2784 }
2785 function intersectsLine(x, y, x1, y1, x2, y2) {
2786 return y2 > y !== y1 > y && x < (x1 - x2) * (y - y2) / (y1 - y2) + x2;
2787 }
2788 function quadraticBezier(from, cp, to, t) {
2789 var inverseT = 1 - t;
2790 return from * inverseT * inverseT + 2 * cp * inverseT * t + to * t * t;
2791 }
2792 function quadraticBezierExtreme(from, cp, to) {
2793 var t = (from - cp) / (from - 2 * cp + to);
2794 if (t < 0) {
2795 return from;
2796 }
2797 if (t > 1) {
2798 return to;
2799 }
2800 return quadraticBezier(from, cp, to, t);
2801 }
2802 function cubicBezier(from, cp, cp2, to, t) {
2803 var tSq = t * t;
2804 var inverseT = 1 - t;
2805 var inverseTSq = inverseT * inverseT;
2806 return from * inverseT * inverseTSq + 3 * cp * t * inverseTSq + 3 * cp2 * inverseT * tSq + to * t * tSq;
2807 }
2808 function cubicBezierExtremes(from, cp, cp2, to) {
2809 var d1 = cp - from;
2810 var d2 = cp2 - cp;
2811 d2 *= 2;
2812 var d3 = to - cp2;
2813 if (d1 + d3 === d2) {
2814 d3 *= 1.0001;
2815 }
2816 var fHead = 2 * d1 - d2;
2817 var part1 = d2 - 2 * d1;
2818 var fCenter = Math.sqrt(part1 * part1 - 4 * d1 * (d1 - d2 + d3));
2819 var fTail = 2 * (d1 - d2 + d3);
2820 var t1 = (fHead + fCenter) / fTail;
2821 var t2 = (fHead - fCenter) / fTail;
2822 var result = [];
2823 if (t1 >= 0 && t1 <= 1) {
2824 result.push(cubicBezier(from, cp, cp2, to, t1));
2825 }
2826 if (t2 >= 0 && t2 <= 1) {
2827 result.push(cubicBezier(from, cp, cp2, to, t2));
2828 }
2829 return result;
2830 }
2831 function cubicXAtY(x0, y0, cx, cy, cx1, cy1, x1, y1, y) {
2832 var dX = 3 * (cx - x0);
2833 var dY = 3 * (cy - y0);
2834 var bX = 3 * (cx1 - cx) - dX;
2835 var bY = 3 * (cy1 - cy) - dY;
2836 var c3X = x1 - x0 - dX - bX;
2837 var c3Y = y1 - y0 - dY - bY;
2838 function f(t) {
2839 return t * (dY + t * (bY + t * c3Y)) + y0 - y;
2840 }
2841 function pointAt(t) {
2842 if (t < 0) {
2843 t = 0;
2844 } else if (t > 1) {
2845 t = 1;
2846 }
2847 return x0 + t * (dX + t * (bX + t * c3X));
2848 }
2849 function bisectCubicBezierRange(f, l, r, limit) {
2850 if (Math.abs(r - l) <= limit) {
2851 return;
2852 }
2853 var middle = 0.5 * (l + r);
2854 if (f(l) * f(r) <= 0) {
2855 left = l;
2856 right = r;
2857 return;
2858 }
2859 bisectCubicBezierRange(f, l, middle, limit);
2860 bisectCubicBezierRange(f, middle, r, limit);
2861 }
2862 var left = 0;
2863 var right = 1;
2864 bisectCubicBezierRange(f, 0, 1, 0.05);
2865 var t0 = findRoot(left, right, f, 50, 0.000001);
2866 var evalResult = Math.abs(f(t0));
2867 if (evalResult > 0.00001) {
2868 return [];
2869 }
2870 var result = [];
2871 if (t0 <= 1) {
2872 result.push(pointAt(t0));
2873 }
2874 var a = c3Y;
2875 var b = t0 * a + bY;
2876 var c = t0 * b + dY;
2877 var d = b * b - 4 * a * c;
2878 if (d < 0) {
2879 return result;
2880 }
2881 d = Math.sqrt(d);
2882 a = 1 / (a + a);
2883 var t1 = (d - b) * a;
2884 var t2 = (-b - d) * a;
2885 if (t1 >= 0 && t1 <= 1) {
2886 result.push(pointAt(t1));
2887 }
2888 if (t2 >= 0 && t2 <= 1) {
2889 result.push(pointAt(t2));
2890 }
2891 return result;
2892 }
2893 function findRoot(x0, x2, f, maxIterations, epsilon) {
2894 var x1;
2895 var y0;
2896 var y1;
2897 var y2;
2898 var b;
2899 var c;
2900 var y10;
2901 var y20;
2902 var y21;
2903 var xm;
2904 var ym;
2905 var temp;
2906 var xmlast = x0;
2907 y0 = f(x0);
2908 if (y0 === 0) {
2909 return x0;
2910 }
2911 y2 = f(x2);
2912 if (y2 === 0) {
2913 return x2;
2914 }
2915 if (y2 * y0 > 0) {
2916 return x0;
2917 }
2918 var __iter = 0;
2919 for (var i = 0; i < maxIterations; ++i) {
2920 __iter++;
2921 x1 = 0.5 * (x2 + x0);
2922 y1 = f(x1);
2923 if (y1 === 0) {
2924 return x1;
2925 }
2926 if (Math.abs(x1 - x0) < epsilon) {
2927 return x1;
2928 }
2929 if (y1 * y0 > 0) {
2930 temp = x0;
2931 x0 = x2;
2932 x2 = temp;
2933 temp = y0;
2934 y0 = y2;
2935 y2 = temp;
2936 }
2937 y10 = y1 - y0;
2938 y21 = y2 - y1;
2939 y20 = y2 - y0;
2940 if (y2 * y20 < 2 * y1 * y10) {
2941 x2 = x1;
2942 y2 = y1;
2943 } else {
2944 b = (x1 - x0) / y10;
2945 c = (y10 - y21) / (y21 * y20);
2946 xm = x0 - b * y0 * (1 - c * y1);
2947 ym = f(xm);
2948 if (ym === 0) {
2949 return xm;
2950 }
2951 if (Math.abs(xm - xmlast) < epsilon) {
2952 return xm;
2953 }
2954 xmlast = xm;
2955 if (ym * y0 < 0) {
2956 x2 = xm;
2957 y2 = ym;
2958 } else {
2959 x0 = xm;
2960 y0 = ym;
2961 x2 = x1;
2962 y2 = y1;
2963 }
2964 }
2965 }
2966 return x1;
2967 }
2968 function extendBoundsByPoint(bounds, x, y) {
2969 if (x < bounds.xMin) {
2970 bounds.xMin = x;
2971 } else if (x > bounds.xMax) {
2972 bounds.xMax = x;
2973 }
2974 if (y < bounds.yMin) {
2975 bounds.yMin = y;
2976 } else if (y > bounds.yMax) {
2977 bounds.yMax = y;
2978 }
2979 }
2980 function extendBoundsByX(bounds, x) {
2981 if (x < bounds.xMin) {
2982 bounds.xMin = x;
2983 } else if (x > bounds.xMax) {
2984 bounds.xMax = x;
2985 }
2986 }
2987 function extendBoundsByY(bounds, y) {
2988 if (y < bounds.yMin) {
2989 bounds.yMin = y;
2990 } else if (y > bounds.yMax) {
2991 bounds.yMax = y;
2992 }
2993 }
2994 function morph(start, end, ratio) {
2995 return start + (end - start) * ratio;
2996 }
2997 function finishShapePath(path, dictionaryResolved) {
2998 if (path.fullyInitialized) {
2999 return path;
3000 }
3001 if (!(path instanceof ShapePath)) {
3002 var untypedPath = path;
3003 path = new ShapePath(path.fillStyle, path.lineStyle, 0, 0, path.isMorph);
3004 path.commands = new Uint8Array(untypedPath.buffers[0]);
3005 path.data = new Int32Array(untypedPath.buffers[1]);
3006 if (untypedPath.isMorph) {
3007 path.morphData = new Int32Array(untypedPath.buffers[2]);
3008 }
3009 path.buffers = null;
3010 }
3011 path.fillStyle && initStyle(path.fillStyle, dictionaryResolved);
3012 path.lineStyle && initStyle(path.lineStyle, dictionaryResolved);
3013 path.fullyInitialized = true;
3014 return path;
3015 }
3016 var inWorker = typeof window === 'undefined';
3017 var factoryCtx = !inWorker ? document.createElement('canvas').getContext('2d') : null;
3018 function buildLinearGradientFactory(colorStops) {
3019 var defaultGradient = factoryCtx.createLinearGradient(-1, 0, 1, 0);
3020 for (var i = 0; i < colorStops.length; i++) {
3021 defaultGradient.addColorStop(colorStops[i].ratio, colorStops[i].color);
3022 }
3023 var fn = function createLinearGradient(ctx, colorTransform) {
3024 var gradient = ctx.createLinearGradient(-1, 0, 1, 0);
3025 for (var i = 0; i < colorStops.length; i++) {
3026 colorTransform.addGradientColorStop(gradient, colorStops[i].ratio, colorStops[i].color);
3027 }
3028 return gradient;
3029 };
3030 fn.defaultFillStyle = defaultGradient;
3031 return fn;
3032 }
3033 function buildRadialGradientFactory(focalPoint, colorStops) {
3034 var defaultGradient = factoryCtx.createRadialGradient(focalPoint, 0, 0, 0, 0, 1);
3035 for (var i = 0; i < colorStops.length; i++) {
3036 defaultGradient.addColorStop(colorStops[i].ratio, colorStops[i].color);
3037 }
3038 var fn = function createRadialGradient(ctx, colorTransform) {
3039 var gradient = ctx.createRadialGradient(focalPoint, 0, 0, 0, 0, 1);
3040 for (var i = 0; i < colorStops.length; i++) {
3041 colorTransform.addGradientColorStop(gradient, colorStops[i].ratio, colorStops[i].color);
3042 }
3043 return gradient;
3044 };
3045 fn.defaultFillStyle = defaultGradient;
3046 return fn;
3047 }
3048 function buildBitmapPatternFactory(img, repeat) {
3049 var defaultPattern = factoryCtx.createPattern(img, repeat);
3050 var cachedTransform, cachedTransformKey;
3051 var fn = function createBitmapPattern(ctx, colorTransform) {
3052 if (!colorTransform.mode) {
3053 return defaultPattern;
3054 }
3055 var key = colorTransform.getTransformFingerprint();
3056 if (key === cachedTransformKey) {
3057 return cachedTransform;
3058 }
3059 var canvas = document.createElement('canvas');
3060 canvas.width = img.width;
3061 canvas.height = img.height;
3062 var ctx = canvas.getContext('2d');
3063 colorTransform.setAlpha(ctx, true);
3064 ctx.drawImage(img, 0, 0);
3065 cachedTransform = ctx.createPattern(canvas, repeat);
3066 cachedTransformKey = key;
3067 return cachedTransform;
3068 };
3069 fn.defaultFillStyle = defaultPattern;
3070 return fn;
3071 }
3072 function initStyle(style, dictionaryResolved) {
3073 if (style.type === undefined) {
3074 return;
3075 }
3076 switch (style.type) {
3077 case GRAPHICS_FILL_SOLID:
3078 break;
3079 case GRAPHICS_FILL_LINEAR_GRADIENT:
3080 case GRAPHICS_FILL_RADIAL_GRADIENT:
3081 case GRAPHICS_FILL_FOCAL_RADIAL_GRADIENT:
3082 var records = style.records, colorStops = [];
3083 for (var j = 0, n = records.length; j < n; j++) {
3084 var record = records[j];
3085 var colorStr = rgbaObjToStr(record.color);
3086 colorStops.push({
3087 ratio: record.ratio / 255,
3088 color: colorStr
3089 });
3090 }
3091 var gradientConstructor;
3092 var isLinear = style.type === GRAPHICS_FILL_LINEAR_GRADIENT;
3093 if (isLinear) {
3094 gradientConstructor = buildLinearGradientFactory(colorStops);
3095 } else {
3096 gradientConstructor = buildRadialGradientFactory((style.focalPoint | 0) / 20, colorStops);
3097 }
3098 style.style = gradientConstructor;
3099 break;
3100 case GRAPHICS_FILL_REPEATING_BITMAP:
3101 case GRAPHICS_FILL_CLIPPED_BITMAP:
3102 case GRAPHICS_FILL_NONSMOOTHED_REPEATING_BITMAP:
3103 case GRAPHICS_FILL_NONSMOOTHED_CLIPPED_BITMAP:
3104 var bitmap = dictionaryResolved[style.bitmapId];
3105 var repeat = style.type === GRAPHICS_FILL_REPEATING_BITMAP || style.type === GRAPHICS_FILL_NONSMOOTHED_REPEATING_BITMAP;
3106 style.style = buildBitmapPatternFactory(bitmap.props.img, repeat ? 'repeat' : 'no-repeat');
3107 break;
3108 default:
3109 fail('invalid fill style', 'shape');
3110 }
3111 }
3112 var SOUND_SIZE_8_BIT = 0;
3113 var SOUND_SIZE_16_BIT = 1;
3114 var SOUND_TYPE_MONO = 0;
3115 var SOUND_TYPE_STEREO = 1;
3116 var SOUND_FORMAT_PCM_BE = 0;
3117 var SOUND_FORMAT_ADPCM = 1;
3118 var SOUND_FORMAT_MP3 = 2;
3119 var SOUND_FORMAT_PCM_LE = 3;
3120 var SOUND_FORMAT_NELLYMOSER_16 = 4;
3121 var SOUND_FORMAT_NELLYMOSER_8 = 5;
3122 var SOUND_FORMAT_NELLYMOSER = 6;
3123 var SOUND_FORMAT_SPEEX = 11;
3124 var SOUND_RATES = [
3125 5512,
3126 11250,
3127 22500,
3128 44100
3129 ];
3130 var WaveHeader = new Uint8Array([
3131 82,
3132 73,
3133 70,
3134 70,
3135 0,
3136 0,
3137 0,
3138 0,
3139 87,
3140 65,
3141 86,
3142 69,
3143 102,
3144 109,
3145 116,
3146 32,
3147 16,
3148 0,
3149 0,
3150 0,
3151 1,
3152 0,
3153 2,
3154 0,
3155 68,
3156 172,
3157 0,
3158 0,
3159 16,
3160 177,
3161 2,
3162 0,
3163 4,
3164 0,
3165 16,
3166 0,
3167 100,
3168 97,
3169 116,
3170 97,
3171 0,
3172 0,
3173 0,
3174 0
3175 ]);
3176 function packageWave(data, sampleRate, channels, size, swapBytes) {
3177 var sizeInBytes = size >> 3;
3178 var sizePerSecond = channels * sampleRate * sizeInBytes;
3179 var sizePerSample = channels * sizeInBytes;
3180 var dataLength = data.length + (data.length & 1);
3181 var buffer = new ArrayBuffer(WaveHeader.length + dataLength);
3182 var bytes = new Uint8Array(buffer);
3183 bytes.set(WaveHeader);
3184 if (swapBytes) {
3185 for (var i = 0, j = WaveHeader.length; i < data.length; i += 2, j += 2) {
3186 bytes[j] = data[i + 1];
3187 bytes[j + 1] = data[i];
3188 }
3189 } else {
3190 bytes.set(data, WaveHeader.length);
3191 }
3192 var view = new DataView(buffer);
3193 view.setUint32(4, dataLength + 36, true);
3194 view.setUint16(22, channels, true);
3195 view.setUint32(24, sampleRate, true);
3196 view.setUint32(28, sizePerSecond, true);
3197 view.setUint16(32, sizePerSample, true);
3198 view.setUint16(34, size, true);
3199 view.setUint32(40, dataLength, true);
3200 return {
3201 data: bytes,
3202 mimeType: 'audio/wav'
3203 };
3204 }
3205 function defineSound(tag, dictionary) {
3206 var channels = tag.soundType == SOUND_TYPE_STEREO ? 2 : 1;
3207 var samplesCount = tag.samplesCount;
3208 var sampleRate = SOUND_RATES[tag.soundRate];
3209 var data = tag.soundData;
3210 var pcm, packaged;
3211 switch (tag.soundFormat) {
3212 case SOUND_FORMAT_PCM_BE:
3213 pcm = new Float32Array(samplesCount * channels);
3214 if (tag.soundSize == SOUND_SIZE_16_BIT) {
3215 for (var i = 0, j = 0; i < pcm.length; i++, j += 2)
3216 pcm[i] = (data[j] << 24 | data[j + 1] << 16) / 2147483648;
3217 packaged = packageWave(data, sampleRate, channels, 16, true);
3218 } else {
3219 for (var i = 0; i < pcm.length; i++)
3220 pcm[i] = (data[i] - 128) / 128;
3221 packaged = packageWave(data, sampleRate, channels, 8, false);
3222 }
3223 break;
3224 case SOUND_FORMAT_PCM_LE:
3225 pcm = new Float32Array(samplesCount * channels);
3226 if (tag.soundSize == SOUND_SIZE_16_BIT) {
3227 for (var i = 0, j = 0; i < pcm.length; i++, j += 2)
3228 pcm[i] = (data[j + 1] << 24 | data[j] << 16) / 2147483648;
3229 packaged = packageWave(data, sampleRate, channels, 16, false);
3230 } else {
3231 for (var i = 0; i < pcm.length; i++)
3232 pcm[i] = (data[i] - 128) / 128;
3233 packaged = packageWave(data, sampleRate, channels, 8, false);
3234 }
3235 break;
3236 case SOUND_FORMAT_MP3:
3237 packaged = {
3238 data: new Uint8Array(data.subarray(2)),
3239 mimeType: 'audio/mpeg'
3240 };
3241 break;
3242 case SOUND_FORMAT_ADPCM:
3243 var pcm16 = new Int16Array(samplesCount * channels);
3244 decodeACPCMSoundData(data, pcm16, channels);
3245 pcm = new Float32Array(samplesCount * channels);
3246 for (var i = 0; i < pcm.length; i++)
3247 pcm[i] = pcm16[i] / 32768;
3248 packaged = packageWave(new Uint8Array(pcm16.buffer), sampleRate, channels, 16, !new Uint8Array(new Uint16Array([
3249 1
3250 ]).buffer)[0]);
3251 break;
3252 default:
3253 throw new Error('Unsupported audio format: ' + tag.soundFormat);
3254 }
3255 var sound = {
3256 type: 'sound',
3257 id: tag.id,
3258 sampleRate: sampleRate,
3259 channels: channels,
3260 pcm: pcm
3261 };
3262 if (packaged)
3263 sound.packaged = packaged;
3264 return sound;
3265 }
3266 var ACPCMIndexTables = [
3267 [
3268 -1,
3269 2
3270 ],
3271 [
3272 -1,
3273 -1,
3274 2,
3275 4
3276 ],
3277 [
3278 -1,
3279 -1,
3280 -1,
3281 -1,
3282 2,
3283 4,
3284 6,
3285 8
3286 ],
3287 [
3288 -1,
3289 -1,
3290 -1,
3291 -1,
3292 -1,
3293 -1,
3294 -1,
3295 -1,
3296 1,
3297 2,
3298 4,
3299 6,
3300 8,
3301 10,
3302 13,
3303 16
3304 ]
3305 ];
3306 var ACPCMStepSizeTable = [
3307 7,
3308 8,
3309 9,
3310 10,
3311 11,
3312 12,
3313 13,
3314 14,
3315 16,
3316 17,
3317 19,
3318 21,
3319 23,
3320 25,
3321 28,
3322 31,
3323 34,
3324 37,
3325 41,
3326 45,
3327 50,
3328 55,
3329 60,
3330 66,
3331 73,
3332 80,
3333 88,
3334 97,
3335 107,
3336 118,
3337 130,
3338 143,
3339 157,
3340 173,
3341 190,
3342 209,
3343 230,
3344 253,
3345 279,
3346 307,
3347 337,
3348 371,
3349 408,
3350 449,
3351 494,
3352 544,
3353 598,
3354 658,
3355 724,
3356 796,
3357 876,
3358 963,
3359 1060,
3360 1166,
3361 1282,
3362 1411,
3363 1552,
3364 1707,
3365 1878,
3366 2066,
3367 2272,
3368 2499,
3369 2749,
3370 3024,
3371 3327,
3372 3660,
3373 4026,
3374 4428,
3375 4871,
3376 5358,
3377 5894,
3378 6484,
3379 7132,
3380 7845,
3381 8630,
3382 9493,
3383 10442,
3384 11487,
3385 12635,
3386 13899,
3387 15289,
3388 16818,
3389 18500,
3390 20350,
3391 22385,
3392 24623,
3393 27086,
3394 29794,
3395 32767
3396 ];
3397 function decodeACPCMSoundData(data, pcm16, channels) {
3398 function readBits(n, signed) {
3399 while (dataBufferLength < n) {
3400 dataBuffer = dataBuffer << 8 | data[dataPosition++];
3401 dataBufferLength += 8;
3402 }
3403 dataBufferLength -= n;
3404 return dataBuffer >>> dataBufferLength & (1 << n) - 1;
3405 }
3406 var dataPosition = 0;
3407 var dataBuffer = 0;
3408 var dataBufferLength = 0;
3409 var pcmPosition = 0;
3410 var codeSize = readBits(2);
3411 var indexTable = ACPCMIndexTables[codeSize];
3412 while (pcmPosition < pcm16.length) {
3413 var x = pcm16[pcmPosition++] = readBits(16) << 16 >> 16, x2;
3414 var stepIndex = readBits(6), stepIndex2;
3415 if (channels > 1) {
3416 x2 = pcm16[pcmPosition++] = readBits(16) << 16 >> 16;
3417 stepIndex2 = readBits(6);
3418 }
3419 var signMask = 1 << codeSize + 1;
3420 for (var i = 0; i < 4095; i++) {
3421 var nibble = readBits(codeSize + 2);
3422 var step = ACPCMStepSizeTable[stepIndex];
3423 var sum = 0;
3424 for (var currentBit = signMask >> 1; currentBit; currentBit >>= 1, step >>= 1) {
3425 if (nibble & currentBit)
3426 sum += step;
3427 }
3428 x += (nibble & signMask ? -1 : 1) * (sum + step);
3429 pcm16[pcmPosition++] = x = x < -32768 ? -32768 : x > 32767 ? 32767 : x;
3430 stepIndex += indexTable[nibble & ~signMask];
3431 stepIndex = stepIndex < 0 ? 0 : stepIndex > 88 ? 88 : stepIndex;
3432 if (channels > 1) {
3433 nibble = readBits(codeSize + 2);
3434 step = ACPCMStepSizeTable[stepIndex2];
3435 sum = 0;
3436 for (var currentBit = signMask >> 1; currentBit; currentBit >>= 1, step >>= 1) {
3437 if (nibble & currentBit)
3438 sum += step;
3439 }
3440 x2 += (nibble & signMask ? -1 : 1) * (sum + step);
3441 pcm16[pcmPosition++] = x2 = x2 < -32768 ? -32768 : x2 > 32767 ? 32767 : x2;
3442 stepIndex2 += indexTable[nibble & ~signMask];
3443 stepIndex2 = stepIndex2 < 0 ? 0 : stepIndex2 > 88 ? 88 : stepIndex2;
3444 }
3445 }
3446 }
3447 }
3448 var nextSoundStreamId = 0;
3449 function SwfSoundStream(samplesCount, sampleRate, channels) {
3450 this.streamId = nextSoundStreamId++;
3451 this.samplesCount = samplesCount;
3452 this.sampleRate = sampleRate;
3453 this.channels = channels;
3454 this.format = null;
3455 this.currentSample = 0;
3456 }
3457 SwfSoundStream.prototype = {
3458 get info() {
3459 return {
3460 samplesCount: this.samplesCount,
3461 sampleRate: this.sampleRate,
3462 channels: this.channels,
3463 format: this.format,
3464 streamId: this.streamId
3465 };
3466 },
3467 decode: function (data) {
3468 throw new Error('SwfSoundStream.decode: not implemented');
3469 }
3470 };
3471 function SwfSoundStream_decode_PCM(data) {
3472 var pcm = new Float32Array(data.length);
3473 for (var i = 0; i < pcm.length; i++)
3474 pcm[i] = (data[i] - 128) / 128;
3475 this.currentSample += pcm.length / this.channels;
3476 return {
3477 streamId: this.streamId,
3478 samplesCount: pcm.length / this.channels,
3479 pcm: pcm
3480 };
3481 }
3482 function SwfSoundStream_decode_PCM_be(data) {
3483 var pcm = new Float32Array(data.length / 2);
3484 for (var i = 0, j = 0; i < pcm.length; i++, j += 2)
3485 pcm[i] = (data[j] << 24 | data[j + 1] << 16) / 2147483648;
3486 this.currentSample += pcm.length / this.channels;
3487 return {
3488 streamId: this.streamId,
3489 samplesCount: pcm.length / this.channels,
3490 pcm: pcm
3491 };
3492 }
3493 function SwfSoundStream_decode_PCM_le(data) {
3494 var pcm = new Float32Array(data.length / 2);
3495 for (var i = 0, j = 0; i < pcm.length; i++, j += 2)
3496 pcm[i] = (data[j + 1] << 24 | data[j] << 16) / 2147483648;
3497 this.currentSample += pcm.length / this.channels;
3498 return {
3499 streamId: this.streamId,
3500 samplesCount: pcm.length / this.channels,
3501 pcm: pcm
3502 };
3503 }
3504 function SwfSoundStream_decode_MP3(data) {
3505 var samplesCount = data[1] << 8 | data[0];
3506 var seek = data[3] << 8 | data[2];
3507 this.currentSample += samplesCount;
3508 return {
3509 streamId: this.streamId,
3510 samplesCount: samplesCount,
3511 data: new Uint8Array(data.subarray(4)),
3512 seek: seek
3513 };
3514 }
3515 function createSoundStream(tag) {
3516 var channels = tag.streamType == SOUND_TYPE_STEREO ? 2 : 1;
3517 var samplesCount = tag.samplesCount;
3518 var sampleRate = SOUND_RATES[tag.streamRate];
3519 var stream = new SwfSoundStream(samplesCount, sampleRate, channels);
3520 switch (tag.streamCompression) {
3521 case SOUND_FORMAT_PCM_BE:
3522 stream.format = 'wave';
3523 if (tag.soundSize == SOUND_SIZE_16_BIT) {
3524 stream.decode = SwfSoundStream_decode_PCM_be;
3525 } else {
3526 stream.decode = SwfSoundStream_decode_PCM;
3527 }
3528 break;
3529 case SOUND_FORMAT_PCM_LE:
3530 stream.format = 'wave';
3531 if (tag.soundSize == SOUND_SIZE_16_BIT) {
3532 stream.decode = SwfSoundStream_decode_PCM_le;
3533 } else {
3534 stream.decode = SwfSoundStream_decode_PCM;
3535 }
3536 break;
3537 case SOUND_FORMAT_MP3:
3538 stream.format = 'mp3';
3539 stream.decode = SwfSoundStream_decode_MP3;
3540 break;
3541 default:
3542 throw new Error('Unsupported audio format: ' + tag.soundFormat);
3543 }
3544 return stream;
3545 }
3546 function defineText(tag, dictionary) {
3547 var dependencies = [];
3548 if (tag.hasFont) {
3549 var font = dictionary[tag.fontId];
3550 tag.font = font.uniqueName;
3551 dependencies.push(font.id);
3552 }
3553 var props = {
3554 type: 'text',
3555 id: tag.id,
3556 variableName: tag.variableName,
3557 tag: tag
3558 };
3559 if (dependencies.length)
3560 props.require = dependencies;
3561 return props;
3562 }
3563 var $RELEASE = false;
3564 var isWorker = typeof window === 'undefined';
3565 if (isWorker && !true) {
3566 importScripts.apply(null, [
3567 '../../lib/DataView.js/DataView.js',
3568 '../flash/util.js',
3569 'config.js',
3570 'swf.js',
3571 'types.js',
3572 'structs.js',
3573 'tags.js',
3574 'inflate.js',
3575 'stream.js',
3576 'templates.js',
3577 'generator.js',
3578 'handlers.js',
3579 'parser.js',
3580 'bitmap.js',
3581 'button.js',
3582 'font.js',
3583 'image.js',
3584 'label.js',
3585 'shape.js',
3586 'sound.js',
3587 'text.js'
3588 ]);
3589 }
3590 function defineSymbol(swfTag, symbols) {
3591 var symbol;
3592 switch (swfTag.code) {
3593 case SWF_TAG_CODE_DEFINE_BITS:
3594 case SWF_TAG_CODE_DEFINE_BITS_JPEG2:
3595 case SWF_TAG_CODE_DEFINE_BITS_JPEG3:
3596 case SWF_TAG_CODE_DEFINE_BITS_JPEG4:
3597 case SWF_TAG_CODE_JPEG_TABLES:
3598 symbol = defineImage(swfTag, symbols);
3599 break;
3600 case SWF_TAG_CODE_DEFINE_BITS_LOSSLESS:
3601 case SWF_TAG_CODE_DEFINE_BITS_LOSSLESS2:
3602 symbol = defineBitmap(swfTag);
3603 break;
3604 case SWF_TAG_CODE_DEFINE_BUTTON:
3605 case SWF_TAG_CODE_DEFINE_BUTTON2:
3606 symbol = defineButton(swfTag, symbols);
3607 break;
3608 case SWF_TAG_CODE_DEFINE_EDIT_TEXT:
3609 symbol = defineText(swfTag, symbols);
3610 break;
3611 case SWF_TAG_CODE_DEFINE_FONT:
3612 case SWF_TAG_CODE_DEFINE_FONT2:
3613 case SWF_TAG_CODE_DEFINE_FONT3:
3614 case SWF_TAG_CODE_DEFINE_FONT4:
3615 symbol = defineFont(swfTag, symbols);
3616 break;
3617 case SWF_TAG_CODE_DEFINE_MORPH_SHAPE:
3618 case SWF_TAG_CODE_DEFINE_MORPH_SHAPE2:
3619 case SWF_TAG_CODE_DEFINE_SHAPE:
3620 case SWF_TAG_CODE_DEFINE_SHAPE2:
3621 case SWF_TAG_CODE_DEFINE_SHAPE3:
3622 case SWF_TAG_CODE_DEFINE_SHAPE4:
3623 symbol = defineShape(swfTag, symbols);
3624 break;
3625 case SWF_TAG_CODE_DEFINE_SOUND:
3626 symbol = defineSound(swfTag, symbols);
3627 break;
3628 case SWF_TAG_CODE_DEFINE_BINARY_DATA:
3629 symbol = {
3630 type: 'binary',
3631 id: swfTag.id,
3632 data: swfTag.data
3633 };
3634 break;
3635 case SWF_TAG_CODE_DEFINE_SPRITE:
3636 var depths = {};
3637 var frame = {
3638 type: 'frame'
3639 };
3640 var frames = [];
3641 var tags = swfTag.tags;
3642 var frameScripts = null;
3643 var frameIndex = 0;
3644 var soundStream = null;
3645 for (var i = 0, n = tags.length; i < n; i++) {
3646 var tag = tags[i];
3647 switch (tag.code) {
3648 case SWF_TAG_CODE_DO_ACTION:
3649 if (!frameScripts)
3650 frameScripts = [];
3651 frameScripts.push(frameIndex);
3652 frameScripts.push(tag.actionsData);
3653 break;
3654 case SWF_TAG_CODE_START_SOUND:
3655 var startSounds = frame.startSounds || (frame.startSounds = []);
3656 startSounds.push(tag);
3657 break;
3658 case SWF_TAG_CODE_SOUND_STREAM_HEAD:
3659 try {
3660 soundStream = createSoundStream(tag);
3661 frame.soundStream = soundStream.info;
3662 } catch (e) {
3663 }
3664 break;
3665 case SWF_TAG_CODE_SOUND_STREAM_BLOCK:
3666 if (soundStream) {
3667 frame.soundStreamBlock = soundStream.decode(tag.data);
3668 }
3669 break;
3670 case SWF_TAG_CODE_FRAME_LABEL:
3671 frame.labelName = tag.name;
3672 break;
3673 case SWF_TAG_CODE_PLACE_OBJECT:
3674 case SWF_TAG_CODE_PLACE_OBJECT2:
3675 case SWF_TAG_CODE_PLACE_OBJECT3:
3676 depths[tag.depth] = tag;
3677 break;
3678 case SWF_TAG_CODE_REMOVE_OBJECT:
3679 case SWF_TAG_CODE_REMOVE_OBJECT2:
3680 depths[tag.depth] = null;
3681 break;
3682 case SWF_TAG_CODE_SHOW_FRAME:
3683 frameIndex += tag.repeat;
3684 frame.repeat = tag.repeat;
3685 frame.depths = depths;
3686 frames.push(frame);
3687 depths = {};
3688 frame = {
3689 type: 'frame'
3690 };
3691 break;
3692 }
3693 }
3694 symbol = {
3695 type: 'sprite',
3696 id: swfTag.id,
3697 frameCount: swfTag.frameCount,
3698 frames: frames,
3699 frameScripts: frameScripts
3700 };
3701 break;
3702 case SWF_TAG_CODE_DEFINE_TEXT:
3703 case SWF_TAG_CODE_DEFINE_TEXT2:
3704 symbol = defineLabel(swfTag, symbols);
3705 break;
3706 }
3707 if (!symbol) {
3708 return {
3709 command: 'error',
3710 message: 'unknown symbol type: ' + swfTag.code
3711 };
3712 }
3713 symbol.isSymbol = true;
3714 symbols[swfTag.id] = symbol;
3715 return symbol;
3716 }
3717 function createParsingContext(commitData) {
3718 var depths = {};
3719 var symbols = {};
3720 var frame = {
3721 type: 'frame'
3722 };
3723 var tagsProcessed = 0;
3724 var soundStream = null;
3725 var lastProgressSent = 0;
3726 return {
3727 onstart: function (result) {
3728 commitData({
3729 command: 'init',
3730 result: result
3731 });
3732 },
3733 onprogress: function (result) {
3734 if (Date.now() - lastProgressSent > 1000 / 24 || result.bytesLoaded === result.bytesTotal) {
3735 commitData({
3736 command: 'progress',
3737 result: {
3738 bytesLoaded: result.bytesLoaded,
3739 bytesTotal: result.bytesTotal
3740 }
3741 });
3742 lastProgressSent = Date.now();
3743 }
3744 var tags = result.tags;
3745 for (var n = tags.length; tagsProcessed < n; tagsProcessed++) {
3746 var tag = tags[tagsProcessed];
3747 if ('id' in tag) {
3748 var symbol = defineSymbol(tag, symbols);
3749 commitData(symbol, symbol.transferables);
3750 continue;
3751 }
3752 switch (tag.code) {
3753 case SWF_TAG_CODE_DEFINE_SCENE_AND_FRAME_LABEL_DATA:
3754 frame.sceneData = tag;
3755 break;
3756 case SWF_TAG_CODE_DEFINE_SCALING_GRID:
3757 var symbolUpdate = {
3758 isSymbol: true,
3759 id: tag.symbolId,
3760 updates: {
3761 scale9Grid: tag.splitter
3762 }
3763 };
3764 commitData(symbolUpdate);
3765 break;
3766 case SWF_TAG_CODE_DO_ABC:
3767 case SWF_TAG_CODE_DO_ABC_:
3768 var abcBlocks = frame.abcBlocks;
3769 if (abcBlocks)
3770 abcBlocks.push({
3771 data: tag.data,
3772 flags: tag.flags
3773 });
3774 else
3775 frame.abcBlocks = [
3776 {
3777 data: tag.data,
3778 flags: tag.flags
3779 }
3780 ];
3781 break;
3782 case SWF_TAG_CODE_DO_ACTION:
3783 var actionBlocks = frame.actionBlocks;
3784 if (actionBlocks)
3785 actionBlocks.push(tag.actionsData);
3786 else
3787 frame.actionBlocks = [
3788 tag.actionsData
3789 ];
3790 break;
3791 case SWF_TAG_CODE_DO_INIT_ACTION:
3792 var initActionBlocks = frame.initActionBlocks || (frame.initActionBlocks = []);
3793 initActionBlocks.push({
3794 spriteId: tag.spriteId,
3795 actionsData: tag.actionsData
3796 });
3797 break;
3798 case SWF_TAG_CODE_START_SOUND:
3799 var startSounds = frame.startSounds;
3800 if (!startSounds)
3801 frame.startSounds = startSounds = [];
3802 startSounds.push(tag);
3803 break;
3804 case SWF_TAG_CODE_SOUND_STREAM_HEAD:
3805 try {
3806 soundStream = createSoundStream(tag);
3807 frame.soundStream = soundStream.info;
3808 } catch (e) {
3809 }
3810 break;
3811 case SWF_TAG_CODE_SOUND_STREAM_BLOCK:
3812 if (soundStream) {
3813 frame.soundStreamBlock = soundStream.decode(tag.data);
3814 }
3815 break;
3816 case SWF_TAG_CODE_EXPORT_ASSETS:
3817 var exports = frame.exports;
3818 if (exports)
3819 frame.exports = exports.concat(tag.exports);
3820 else
3821 frame.exports = tag.exports.slice(0);
3822 break;
3823 case SWF_TAG_CODE_SYMBOL_CLASS:
3824 var symbolClasses = frame.symbolClasses;
3825 if (symbolClasses)
3826 frame.symbolClasses = symbolClasses.concat(tag.exports);
3827 else
3828 frame.symbolClasses = tag.exports.slice(0);
3829 break;
3830 case SWF_TAG_CODE_FRAME_LABEL:
3831 frame.labelName = tag.name;
3832 break;
3833 case SWF_TAG_CODE_PLACE_OBJECT:
3834 case SWF_TAG_CODE_PLACE_OBJECT2:
3835 case SWF_TAG_CODE_PLACE_OBJECT3:
3836 depths[tag.depth] = tag;
3837 break;
3838 case SWF_TAG_CODE_REMOVE_OBJECT:
3839 case SWF_TAG_CODE_REMOVE_OBJECT2:
3840 depths[tag.depth] = null;
3841 break;
3842 case SWF_TAG_CODE_SET_BACKGROUND_COLOR:
3843 frame.bgcolor = tag.color;
3844 break;
3845 case SWF_TAG_CODE_SHOW_FRAME:
3846 frame.repeat = tag.repeat;
3847 frame.depths = depths;
3848 frame.complete = !(!tag.finalTag);
3849 commitData(frame);
3850 depths = {};
3851 frame = {
3852 type: 'frame'
3853 };
3854 break;
3855 }
3856 }
3857 },
3858 oncomplete: function (result) {
3859 commitData(result);
3860 var stats;
3861 if (typeof result.swfVersion === 'number') {
3862 var bbox = result.bbox;
3863 stats = {
3864 topic: 'parseInfo',
3865 parseTime: result.parseTime,
3866 bytesTotal: result.bytesTotal,
3867 swfVersion: result.swfVersion,
3868 frameRate: result.frameRate,
3869 width: (bbox.xMax - bbox.xMin) / 20,
3870 height: (bbox.yMax - bbox.yMin) / 20,
3871 isAvm2: !(!result.fileAttributes.doAbc)
3872 };
3873 }
3874 commitData({
3875 command: 'complete',
3876 stats: stats
3877 });
3878 },
3879 onexception: function (e) {
3880 commitData({
3881 type: 'exception',
3882 message: e.message,
3883 stack: e.stack
3884 });
3885 }
3886 };
3887 }
3888 function parseBytes(bytes, commitData) {
3889 SWF.parse(bytes, createParsingContext(commitData));
3890 }
3891 function ResourceLoader(scope) {
3892 this.subscription = null;
3893 var self = this;
3894 if (!isWorker) {
3895 this.messenger = {
3896 postMessage: function (data) {
3897 self.onmessage({
3898 data: data
3899 });
3900 }
3901 };
3902 } else {
3903 this.messenger = scope;
3904 scope.onmessage = function (event) {
3905 self.listener(event.data);
3906 };
3907 }
3908 }
3909 ResourceLoader.prototype = {
3910 terminate: function () {
3911 this.messenger = null;
3912 this.listener = null;
3913 },
3914 onmessage: function (event) {
3915 this.listener(event.data);
3916 },
3917 postMessage: function (data) {
3918 this.listener && this.listener(data);
3919 },
3920 listener: function (data) {
3921 if (this.subscription) {
3922 this.subscription.callback(data.data, data.progress);
3923 } else if (data === 'pipe:') {
3924 this.subscription = {
3925 subscribe: function (callback) {
3926 this.callback = callback;
3927 }
3928 };
3929 this.parseLoadedData(this.messenger, this.subscription);
3930 } else {
3931 this.parseLoadedData(this.messenger, data);
3932 }
3933 },
3934 parseLoadedData: function (loader, request, context) {
3935 function commitData(data, transferables) {
3936 try {
3937 loader.postMessage(data, transferables);
3938 } catch (ex) {
3939 if (ex != 'DataCloneError') {
3940 throw ex;
3941 }
3942 loader.postMessage(data);
3943 }
3944 }
3945 if (request instanceof ArrayBuffer) {
3946 parseBytes(request, commitData);
3947 } else if ('subscribe' in request) {
3948 var pipe = SWF.parseAsync(createParsingContext(commitData));
3949 request.subscribe(function (data, progress) {
3950 if (data) {
3951 pipe.push(data, progress);
3952 } else {
3953 pipe.close();
3954 }
3955 });
3956 } else if (typeof FileReaderSync !== 'undefined') {
3957 var reader = new FileReaderSync();
3958 var buffer = reader.readAsArrayBuffer(request);
3959 parseBytes(buffer, commitData);
3960 } else {
3961 var reader = new FileReader();
3962 reader.onload = function () {
3963 parseBytes(this.result, commitData);
3964 };
3965 reader.readAsArrayBuffer(request);
3966 }
3967 }
3968 };
3969 if (isWorker) {
3970 var loader = new ResourceLoader(this);
3971 }
3972 var codeLengthOrder = [
3973 16,
3974 17,
3975 18,
3976 0,
3977 8,
3978 7,
3979 9,
3980 6,
3981 10,
3982 5,
3983 11,
3984 4,
3985 12,
3986 3,
3987 13,
3988 2,
3989 14,
3990 1,
3991 15
3992 ];
3993 var distanceCodes = [];
3994 var distanceExtraBits = [];
3995 for (var i = 0, j = 0, code = 1; i < 30; ++i) {
3996 distanceCodes[i] = code;
3997 code += 1 << (distanceExtraBits[i] = ~(~((j += i > 2 ? 1 : 0) / 2)));
3998 }
3999 var bitLengths = [];
4000 for (var i = 0; i < 32; ++i)
4001 bitLengths[i] = 5;
4002 var fixedDistanceTable = makeHuffmanTable(bitLengths);
4003 var lengthCodes = [];
4004 var lengthExtraBits = [];
4005 for (var i = 0, j = 0, code = 3; i < 29; ++i) {
4006 lengthCodes[i] = code - (i == 28 ? 1 : 0);
4007 code += 1 << (lengthExtraBits[i] = ~(~((j += i > 4 ? 1 : 0) / 4 % 6)));
4008 }
4009 for (var i = 0; i < 288; ++i)
4010 bitLengths[i] = i < 144 || i > 279 ? 8 : i < 256 ? 9 : 7;
4011 var fixedLiteralTable = makeHuffmanTable(bitLengths);
4012 function makeHuffmanTable(bitLengths) {
4013 var maxBits = Math.max.apply(null, bitLengths);
4014 var numLengths = bitLengths.length;
4015 var size = 1 << maxBits;
4016 var codes = new Uint32Array(size);
4017 for (var code = 0, len = 1, skip = 2; len <= maxBits; code <<= 1, ++len, skip <<= 1) {
4018 for (var val = 0; val < numLengths; ++val) {
4019 if (bitLengths[val] === len) {
4020 var lsb = 0;
4021 for (var i = 0; i < len; ++i)
4022 lsb = lsb * 2 + (code >> i & 1);
4023 for (var i = lsb; i < size; i += skip)
4024 codes[i] = len << 16 | val;
4025 ++code;
4026 }
4027 }
4028 }
4029 return {
4030 codes: codes,
4031 maxBits: maxBits
4032 };
4033 }
4034 function verifyDeflateHeader(bytes) {
4035 var header = bytes[0] << 8 | bytes[1];
4036 }
4037 function createInflatedStream(bytes, outputLength) {
4038 verifyDeflateHeader(bytes);
4039 var stream = new Stream(bytes, 2);
4040 var output = {
4041 data: new Uint8Array(outputLength),
4042 available: 0,
4043 completed: false
4044 };
4045 var state = {
4046 header: null,
4047 distanceTable: null,
4048 literalTable: null,
4049 sym: null,
4050 len: null,
4051 sym2: null
4052 };
4053 do {
4054 inflateBlock(stream, output, state);
4055 } while (!output.completed && stream.pos < stream.end);
4056 return new Stream(output.data, 0, output.available);
4057 }
4058 var InflateNoDataError = {};
4059 function inflateBlock(stream, output, state) {
4060 var header = state.header !== null ? state.header : state.header = readBits(stream.bytes, stream, 3);
4061 switch (header >> 1) {
4062 case 0:
4063 stream.align();
4064 var pos = stream.pos;
4065 if (stream.end - pos < 4) {
4066 throw InflateNoDataError;
4067 }
4068 var len = stream.getUint16(pos, true);
4069 var nlen = stream.getUint16(pos + 2, true);
4070 if (stream.end - pos < 4 + len) {
4071 throw InflateNoDataError;
4072 }
4073 var begin = pos + 4;
4074 var end = stream.pos = begin + len;
4075 var sbytes = stream.bytes, dbytes = output.data;
4076 dbytes.set(sbytes.subarray(begin, end), output.available);
4077 output.available += len;
4078 break;
4079 case 1:
4080 inflate(stream, output, fixedLiteralTable, fixedDistanceTable, state);
4081 break;
4082 case 2:
4083 var distanceTable, literalTable;
4084 if (state.distanceTable !== null) {
4085 distanceTable = state.distanceTable;
4086 literalTable = state.literalTable;
4087 } else {
4088 var sbytes = stream.bytes;
4089 var savedBufferPos = stream.pos;
4090 var savedBitBuffer = stream.bitBuffer;
4091 var savedBitLength = stream.bitLength;
4092 var bitLengths = [];
4093 var numLiteralCodes, numDistanceCodes;
4094 try {
4095 numLiteralCodes = readBits(sbytes, stream, 5) + 257;
4096 numDistanceCodes = readBits(sbytes, stream, 5) + 1;
4097 var numCodes = numLiteralCodes + numDistanceCodes;
4098 var numLengthCodes = readBits(sbytes, stream, 4) + 4;
4099 for (var i = 0; i < 19; ++i)
4100 bitLengths[codeLengthOrder[i]] = i < numLengthCodes ? readBits(sbytes, stream, 3) : 0;
4101 var codeLengthTable = makeHuffmanTable(bitLengths);
4102 bitLengths = [];
4103 var i = 0;
4104 var prev = 0;
4105 while (i < numCodes) {
4106 var j = 1;
4107 var sym = readCode(sbytes, stream, codeLengthTable);
4108 switch (sym) {
4109 case 16:
4110 j = readBits(sbytes, stream, 2) + 3;
4111 sym = prev;
4112 break;
4113 case 17:
4114 j = readBits(sbytes, stream, 3) + 3;
4115 sym = 0;
4116 break;
4117 case 18:
4118 j = readBits(sbytes, stream, 7) + 11;
4119 sym = 0;
4120 break;
4121 default:
4122 prev = sym;
4123 }
4124 while (j--)
4125 bitLengths[i++] = sym;
4126 }
4127 } catch (e) {
4128 stream.pos = savedBufferPos;
4129 stream.bitBuffer = savedBitBuffer;
4130 stream.bitLength = savedBitLength;
4131 throw e;
4132 }
4133 distanceTable = state.distanceTable = makeHuffmanTable(bitLengths.splice(numLiteralCodes, numDistanceCodes));
4134 literalTable = state.literalTable = makeHuffmanTable(bitLengths);
4135 }
4136 inflate(stream, output, literalTable, distanceTable, state);
4137 state.distanceTable = null;
4138 state.literalTable = null;
4139 break;
4140 default:
4141 fail('unknown block type', 'inflate');
4142 }
4143 state.header = null;
4144 output.completed = !(!(header & 1));
4145 }
4146 function readBits(bytes, stream, size) {
4147 var bitBuffer = stream.bitBuffer;
4148 var bitLength = stream.bitLength;
4149 if (size > bitLength) {
4150 var pos = stream.pos;
4151 var end = stream.end;
4152 do {
4153 if (pos >= end) {
4154 stream.pos = pos;
4155 stream.bitBuffer = bitBuffer;
4156 stream.bitLength = bitLength;
4157 throw InflateNoDataError;
4158 }
4159 bitBuffer |= bytes[pos++] << bitLength;
4160 bitLength += 8;
4161 } while (size > bitLength);
4162 stream.pos = pos;
4163 }
4164 stream.bitBuffer = bitBuffer >>> size;
4165 stream.bitLength = bitLength - size;
4166 return bitBuffer & (1 << size) - 1;
4167 }
4168 function inflate(stream, output, literalTable, distanceTable, state) {
4169 var pos = output.available;
4170 var dbytes = output.data;
4171 var sbytes = stream.bytes;
4172 var sym = state.sym !== null ? state.sym : readCode(sbytes, stream, literalTable);
4173 while (sym !== 256) {
4174 if (sym < 256) {
4175 dbytes[pos++] = sym;
4176 } else {
4177 state.sym = sym;
4178 sym -= 257;
4179 var len = state.len !== null ? state.len : state.len = lengthCodes[sym] + readBits(sbytes, stream, lengthExtraBits[sym]);
4180 var sym2 = state.sym2 !== null ? state.sym2 : state.sym2 = readCode(sbytes, stream, distanceTable);
4181 var distance = distanceCodes[sym2] + readBits(sbytes, stream, distanceExtraBits[sym2]);
4182 var i = pos - distance;
4183 while (len--)
4184 dbytes[pos++] = dbytes[i++];
4185 state.sym2 = null;
4186 state.len = null;
4187 state.sym = null;
4188 }
4189 output.available = pos;
4190 sym = readCode(sbytes, stream, literalTable);
4191 }
4192 }
4193 function readCode(bytes, stream, codeTable) {
4194 var bitBuffer = stream.bitBuffer;
4195 var bitLength = stream.bitLength;
4196 var maxBits = codeTable.maxBits;
4197 if (maxBits > bitLength) {
4198 var pos = stream.pos;
4199 var end = stream.end;
4200 do {
4201 if (pos >= end) {
4202 stream.pos = pos;
4203 stream.bitBuffer = bitBuffer;
4204 stream.bitLength = bitLength;
4205 throw InflateNoDataError;
4206 }
4207 bitBuffer |= bytes[pos++] << bitLength;
4208 bitLength += 8;
4209 } while (maxBits > bitLength);
4210 stream.pos = pos;
4211 }
4212 var code = codeTable.codes[bitBuffer & (1 << maxBits) - 1];
4213 var len = code >> 16;
4214 stream.bitBuffer = bitBuffer >>> len;
4215 stream.bitLength = bitLength - len;
4216 return code & 65535;
4217 }
4218 (function (global) {
4219 global['createInflatedStream'] = createInflatedStream;
4220 }(this));
4221 var StreamNoDataError = {};
4222 var Stream = function StreamClosure() {
4223 function Stream_align() {
4224 this.bitBuffer = this.bitLength = 0;
4225 }
4226 function Stream_ensure(size) {
4227 if (this.pos + size > this.end) {
4228 throw StreamNoDataError;
4229 }
4230 }
4231 function Stream_remaining() {
4232 return this.end - this.pos;
4233 }
4234 function Stream_substream(begin, end) {
4235 var stream = new Stream(this.bytes);
4236 stream.pos = begin;
4237 stream.end = end;
4238 return stream;
4239 }
4240 function Stream_push(data) {
4241 var bytes = this.bytes;
4242 var newBytesLength = this.end + data.length;
4243 if (newBytesLength > bytes.length) {
4244 throw 'stream buffer overfow';
4245 }
4246 bytes.set(data, this.end);
4247 this.end = newBytesLength;
4248 }
4249 function Stream(buffer, offset, length, maxLength) {
4250 if (offset === undefined)
4251 offset = 0;
4252 if (buffer.buffer instanceof ArrayBuffer) {
4253 offset += buffer.byteOffset;
4254 buffer = buffer.buffer;
4255 }
4256 if (length === undefined)
4257 length = buffer.byteLength - offset;
4258 if (maxLength === undefined)
4259 maxLength = length;
4260 var bytes = new Uint8Array(buffer, offset, maxLength);
4261 var stream = new DataView(buffer, offset, maxLength);
4262 stream.bytes = bytes;
4263 stream.pos = 0;
4264 stream.end = length;
4265 stream.bitBuffer = 0;
4266 stream.bitLength = 0;
4267 stream.align = Stream_align;
4268 stream.ensure = Stream_ensure;
4269 stream.remaining = Stream_remaining;
4270 stream.substream = Stream_substream;
4271 stream.push = Stream_push;
4272 return stream;
4273 }
4274 return Stream;
4275 }();
4276 (function (global) {
4277 global['Stream'] = Stream;
4278 }(this));
4279 function readSi8($bytes, $stream) {
4280 return $stream.getInt8($stream.pos++);
4281 }
4282 function readSi16($bytes, $stream) {
4283 return $stream.getInt16($stream.pos, $stream.pos += 2);
4284 }
4285 function readSi32($bytes, $stream) {
4286 return $stream.getInt32($stream.pos, $stream.pos += 4);
4287 }
4288 function readUi8($bytes, $stream) {
4289 return $bytes[$stream.pos++];
4290 }
4291 function readUi16($bytes, $stream) {
4292 return $stream.getUint16($stream.pos, $stream.pos += 2);
4293 }
4294 function readUi32($bytes, $stream) {
4295 return $stream.getUint32($stream.pos, $stream.pos += 4);
4296 }
4297 function readFixed($bytes, $stream) {
4298 return $stream.getInt32($stream.pos, $stream.pos += 4) / 65536;
4299 }
4300 function readFixed8($bytes, $stream) {
4301 return $stream.getInt16($stream.pos, $stream.pos += 2) / 256;
4302 }
4303 function readFloat16($bytes, $stream) {
4304 var ui16 = $stream.getUint16($stream.pos);
4305 $stream.pos += 2;
4306 var sign = ui16 >> 15 ? -1 : 1;
4307 var exponent = (ui16 & 31744) >> 10;
4308 var fraction = ui16 & 1023;
4309 if (!exponent)
4310 return sign * pow(2, -14) * (fraction / 1024);
4311 if (exponent === 31)
4312 return fraction ? NaN : sign * Infinity;
4313 return sign * pow(2, exponent - 15) * (1 + fraction / 1024);
4314 }
4315 function readFloat($bytes, $stream) {
4316 return $stream.getFloat32($stream.pos, $stream.pos += 4);
4317 }
4318 function readDouble($bytes, $stream) {
4319 return $stream.getFloat64($stream.pos, $stream.pos += 8);
4320 }
4321 function readEncodedU32($bytes, $stream) {
4322 var val = $bytes[$stream.pos++];
4323 if (!(val & 128))
4324 return val;
4325 val |= $bytes[$stream.pos++] << 7;
4326 if (!(val & 16384))
4327 return val;
4328 val |= $bytes[$stream.pos++] << 14;
4329 if (!(val & 2097152))
4330 return val;
4331 val |= $bytes[$stream.pos++] << 21;
4332 if (!(val & 268435456))
4333 return val;
4334 return val | $bytes[$stream.pos++] << 28;
4335 }
4336 function readBool($bytes, $stream) {
4337 return !(!$bytes[$stream.pos++]);
4338 }
4339 function align($bytes, $stream) {
4340 $stream.align();
4341 }
4342 function readSb($bytes, $stream, size) {
4343 return readUb($bytes, $stream, size) << 32 - size >> 32 - size;
4344 }
4345 var masks = new Uint32Array(33);
4346 for (var i = 1, mask = 0; i <= 32; ++i)
4347 masks[i] = mask = mask << 1 | 1;
4348 function readUb($bytes, $stream, size) {
4349 var buffer = $stream.bitBuffer;
4350 var bitlen = $stream.bitLength;
4351 while (size > bitlen) {
4352 buffer = buffer << 8 | $bytes[$stream.pos++];
4353 bitlen += 8;
4354 }
4355 bitlen -= size;
4356 var val = buffer >>> bitlen & masks[size];
4357 $stream.bitBuffer = buffer;
4358 $stream.bitLength = bitlen;
4359 return val;
4360 }
4361 function readFb($bytes, $stream, size) {
4362 return readSb($bytes, $stream, size) / 65536;
4363 }
4364 function readString($bytes, $stream, length) {
4365 var codes = [];
4366 var pos = $stream.pos;
4367 if (length) {
4368 codes = slice.call($bytes, pos, pos += length);
4369 } else {
4370 length = 0;
4371 for (var code; code = $bytes[pos++]; length++)
4372 codes[length] = code;
4373 }
4374 $stream.pos = pos;
4375 var numChunks = length / 65536;
4376 var str = '';
4377 for (var i = 0; i < numChunks; ++i) {
4378 var begin = i * 65536;
4379 var end = begin + 65536;
4380 var chunk = codes.slice(begin, end);
4381 str += fromCharCode.apply(null, chunk);
4382 }
4383 return decodeURIComponent(escape(str.replace('\0', '', 'g')));
4384 }
4385 function readBinary($bytes, $stream, size) {
4386 return $bytes.subarray($stream.pos, $stream.pos = size ? $stream.pos + size : $stream.end);
4387 }
4388 (function (global) {
4389 global['readSi8'] = readSi8;
4390 global['readUi16'] = readUi16;
4391 global['readUi32'] = readUi32;
4392 }(this));
4393 var tagHandler = function (global) {
4394 function defineShape($bytes, $stream, $, swfVersion, tagCode) {
4395 $ || ($ = {});
4396 $.id = readUi16($bytes, $stream);
4397 var $0 = $.bbox = {};
4398 bbox($bytes, $stream, $0, swfVersion, tagCode);
4399 var isMorph = $.isMorph = tagCode === 46 || tagCode === 84;
4400 if (isMorph) {
4401 var $1 = $.bboxMorph = {};
4402 bbox($bytes, $stream, $1, swfVersion, tagCode);
4403 }
4404 var hasStrokes = $.hasStrokes = tagCode === 83 || tagCode === 84;
4405 if (hasStrokes) {
4406 var $2 = $.strokeBbox = {};
4407 bbox($bytes, $stream, $2, swfVersion, tagCode);
4408 if (isMorph) {
4409 var $3 = $.strokeBboxMorph = {};
4410 bbox($bytes, $stream, $3, swfVersion, tagCode);
4411 }
4412 var reserved = readUb($bytes, $stream, 5);
4413 $.fillWinding = readUb($bytes, $stream, 1);
4414 $.nonScalingStrokes = readUb($bytes, $stream, 1);
4415 $.scalingStrokes = readUb($bytes, $stream, 1);
4416 }
4417 if (isMorph) {
4418 $.offsetMorph = readUi32($bytes, $stream);
4419 morphShapeWithStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
4420 } else {
4421 shapeWithStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
4422 }
4423 return $;
4424 }
4425 function placeObject($bytes, $stream, $, swfVersion, tagCode) {
4426 var flags, hasEvents, clip, hasName, hasRatio, hasCxform, hasMatrix, place;
4427 var move, hasBackgroundColor, hasVisibility, hasImage, hasClassName, cache;
4428 var blend, hasFilters, eoe;
4429 $ || ($ = {});
4430 if (tagCode > 4) {
4431 if (tagCode > 26) {
4432 flags = readUi16($bytes, $stream);
4433 } else {
4434 flags = readUi8($bytes, $stream);
4435 }
4436 hasEvents = $.hasEvents = flags >> 7 & 1;
4437 clip = $.clip = flags >> 6 & 1;
4438 hasName = $.hasName = flags >> 5 & 1;
4439 hasRatio = $.hasRatio = flags >> 4 & 1;
4440 hasCxform = $.hasCxform = flags >> 3 & 1;
4441 hasMatrix = $.hasMatrix = flags >> 2 & 1;
4442 place = $.place = flags >> 1 & 1;
4443 move = $.move = flags & 1;
4444 if (tagCode === 70) {
4445 hasBackgroundColor = $.hasBackgroundColor = flags >> 15 & 1;
4446 hasVisibility = $.hasVisibility = flags >> 14 & 1;
4447 hasImage = $.hasImage = flags >> 12 & 1;
4448 hasClassName = $.hasClassName = flags >> 11 & 1;
4449 cache = $.cache = flags >> 10 & 1;
4450 blend = $.blend = flags >> 9 & 1;
4451 hasFilters = $.hasFilters = flags >> 8 & 1;
4452 } else {
4453 cache = $.cache = 0;
4454 blend = $.blend = 0;
4455 hasFilters = $.hasFilters = 0;
4456 }
4457 $.depth = readUi16($bytes, $stream);
4458 if (hasClassName) {
4459 $.className = readString($bytes, $stream, 0);
4460 }
4461 if (place) {
4462 $.symbolId = readUi16($bytes, $stream);
4463 }
4464 if (hasMatrix) {
4465 var $0 = $.matrix = {};
4466 matrix($bytes, $stream, $0, swfVersion, tagCode);
4467 }
4468 if (hasCxform) {
4469 var $1 = $.cxform = {};
4470 cxform($bytes, $stream, $1, swfVersion, tagCode);
4471 }
4472 if (hasRatio) {
4473 $.ratio = readUi16($bytes, $stream);
4474 }
4475 if (hasName) {
4476 $.name = readString($bytes, $stream, 0);
4477 }
4478 if (clip) {
4479 $.clipDepth = readUi16($bytes, $stream);
4480 }
4481 if (hasFilters) {
4482 var count = readUi8($bytes, $stream);
4483 var $2 = $.filters = [];
4484 var $3 = count;
4485 while ($3--) {
4486 var $4 = {};
4487 anyFilter($bytes, $stream, $4, swfVersion, tagCode);
4488 $2.push($4);
4489 }
4490 }
4491 if (blend) {
4492 $.blendMode = readUi8($bytes, $stream);
4493 }
4494 if (cache) {
4495 $.bmpCache = readUi8($bytes, $stream);
4496 }
4497 if (hasEvents) {
4498 var reserved = readUi16($bytes, $stream);
4499 if (swfVersion >= 6) {
4500 var allFlags = readUi32($bytes, $stream);
4501 } else {
4502 var allFlags = readUi16($bytes, $stream);
4503 }
4504 var $28 = $.events = [];
4505 do {
4506 var $29 = {};
4507 var temp = events($bytes, $stream, $29, swfVersion, tagCode);
4508 eoe = temp.eoe;
4509 $28.push($29);
4510 } while (!eoe);
4511 }
4512 if (hasBackgroundColor) {
4513 var $126 = $.backgroundColor = {};
4514 argb($bytes, $stream, $126, swfVersion, tagCode);
4515 }
4516 if (hasVisibility) {
4517 $.visibility = readUi8($bytes, $stream);
4518 }
4519 } else {
4520 $.place = 1;
4521 $.symbolId = readUi16($bytes, $stream);
4522 $.depth = readUi16($bytes, $stream);
4523 $.hasMatrix = 1;
4524 var $30 = $.matrix = {};
4525 matrix($bytes, $stream, $30, swfVersion, tagCode);
4526 if ($stream.remaining()) {
4527 $.hasCxform = 1;
4528 var $31 = $.cxform = {};
4529 cxform($bytes, $stream, $31, swfVersion, tagCode);
4530 }
4531 }
4532 return $;
4533 }
4534 function removeObject($bytes, $stream, $, swfVersion, tagCode) {
4535 $ || ($ = {});
4536 if (tagCode === 5) {
4537 $.symbolId = readUi16($bytes, $stream);
4538 }
4539 $.depth = readUi16($bytes, $stream);
4540 return $;
4541 }
4542 function defineImage($bytes, $stream, $, swfVersion, tagCode) {
4543 var imgData;
4544 $ || ($ = {});
4545 $.id = readUi16($bytes, $stream);
4546 if (tagCode > 21) {
4547 var alphaDataOffset = readUi32($bytes, $stream);
4548 if (tagCode === 90) {
4549 $.deblock = readFixed8($bytes, $stream);
4550 }
4551 imgData = $.imgData = readBinary($bytes, $stream, alphaDataOffset);
4552 $.alphaData = readBinary($bytes, $stream, 0);
4553 } else {
4554 imgData = $.imgData = readBinary($bytes, $stream, 0);
4555 }
4556 switch (imgData[0] << 8 | imgData[1]) {
4557 case 65496:
4558 case 65497:
4559 $.mimeType = 'image/jpeg';
4560 break;
4561 case 35152:
4562 $.mimeType = 'image/png';
4563 break;
4564 case 18249:
4565 $.mimeType = 'image/gif';
4566 break;
4567 default:
4568 $.mimeType = 'application/octet-stream';
4569 }
4570 if (tagCode === 6) {
4571 $.incomplete = 1;
4572 }
4573 return $;
4574 }
4575 function defineButton($bytes, $stream, $, swfVersion, tagCode) {
4576 var eob, hasFilters, count, blend;
4577 $ || ($ = {});
4578 $.id = readUi16($bytes, $stream);
4579 if (tagCode == 7) {
4580 var $0 = $.characters = [];
4581 do {
4582 var $1 = {};
4583 var temp = button($bytes, $stream, $1, swfVersion, tagCode);
4584 eob = temp.eob;
4585 $0.push($1);
4586 } while (!eob);
4587 $.actionsData = readBinary($bytes, $stream, 0);
4588 } else {
4589 var trackFlags = readUi8($bytes, $stream);
4590 $.trackAsMenu = trackFlags >> 7 & 1;
4591 var actionOffset = readUi16($bytes, $stream);
4592 var $28 = $.characters = [];
4593 do {
4594 var $29 = {};
4595 var flags = readUi8($bytes, $stream);
4596 var eob = $29.eob = !flags;
4597 if (swfVersion >= 8) {
4598 blend = $29.blend = flags >> 5 & 1;
4599 hasFilters = $29.hasFilters = flags >> 4 & 1;
4600 } else {
4601 blend = $29.blend = 0;
4602 hasFilters = $29.hasFilters = 0;
4603 }
4604 $29.stateHitTest = flags >> 3 & 1;
4605 $29.stateDown = flags >> 2 & 1;
4606 $29.stateOver = flags >> 1 & 1;
4607 $29.stateUp = flags & 1;
4608 if (!eob) {
4609 $29.symbolId = readUi16($bytes, $stream);
4610 $29.depth = readUi16($bytes, $stream);
4611 var $30 = $29.matrix = {};
4612 matrix($bytes, $stream, $30, swfVersion, tagCode);
4613 if (tagCode === 34) {
4614 var $31 = $29.cxform = {};
4615 cxform($bytes, $stream, $31, swfVersion, tagCode);
4616 }
4617 if (hasFilters) {
4618 var count = readUi8($bytes, $stream);
4619 var $2 = $.filters = [];
4620 var $3 = count;
4621 while ($3--) {
4622 var $4 = {};
4623 anyFilter($bytes, $stream, $4, swfVersion, tagCode);
4624 $2.push($4);
4625 }
4626 }
4627 if (blend) {
4628 $29.blendMode = readUi8($bytes, $stream);
4629 }
4630 }
4631 $28.push($29);
4632 } while (!eob);
4633 if (!(!actionOffset)) {
4634 var $56 = $.buttonActions = [];
4635 do {
4636 var $57 = {};
4637 buttonCondAction($bytes, $stream, $57, swfVersion, tagCode);
4638 $56.push($57);
4639 } while ($stream.remaining() > 0);
4640 }
4641 }
4642 return $;
4643 }
4644 function defineJPEGTables($bytes, $stream, $, swfVersion, tagCode) {
4645 $ || ($ = {});
4646 $.id = 0;
4647 $.imgData = readBinary($bytes, $stream, 0);
4648 $.mimeType = 'application/octet-stream';
4649 return $;
4650 }
4651 function setBackgroundColor($bytes, $stream, $, swfVersion, tagCode) {
4652 $ || ($ = {});
4653 var $0 = $.color = {};
4654 rgb($bytes, $stream, $0, swfVersion, tagCode);
4655 return $;
4656 }
4657 function defineBinaryData($bytes, $stream, $, swfVersion, tagCode) {
4658 $ || ($ = {});
4659 $.id = readUi16($bytes, $stream);
4660 var reserved = readUi32($bytes, $stream);
4661 $.data = readBinary($bytes, $stream, 0);
4662 return $;
4663 }
4664 function defineFont($bytes, $stream, $, swfVersion, tagCode) {
4665 $ || ($ = {});
4666 $.id = readUi16($bytes, $stream);
4667 var firstOffset = readUi16($bytes, $stream);
4668 var glyphCount = $.glyphCount = firstOffset / 2;
4669 var restOffsets = [];
4670 var $0 = glyphCount - 1;
4671 while ($0--) {
4672 restOffsets.push(readUi16($bytes, $stream));
4673 }
4674 $.offsets = [
4675 firstOffset
4676 ].concat(restOffsets);
4677 var $1 = $.glyphs = [];
4678 var $2 = glyphCount;
4679 while ($2--) {
4680 var $3 = {};
4681 shape($bytes, $stream, $3, swfVersion, tagCode);
4682 $1.push($3);
4683 }
4684 return $;
4685 }
4686 function defineLabel($bytes, $stream, $, swfVersion, tagCode) {
4687 var eot;
4688 $ || ($ = {});
4689 $.id = readUi16($bytes, $stream);
4690 var $0 = $.bbox = {};
4691 bbox($bytes, $stream, $0, swfVersion, tagCode);
4692 var $1 = $.matrix = {};
4693 matrix($bytes, $stream, $1, swfVersion, tagCode);
4694 var glyphBits = $.glyphBits = readUi8($bytes, $stream);
4695 var advanceBits = $.advanceBits = readUi8($bytes, $stream);
4696 var $2 = $.records = [];
4697 do {
4698 var $3 = {};
4699 var temp = textRecord($bytes, $stream, $3, swfVersion, tagCode, glyphBits, advanceBits);
4700 eot = temp.eot;
4701 $2.push($3);
4702 } while (!eot);
4703 return $;
4704 }
4705 function doAction($bytes, $stream, $, swfVersion, tagCode) {
4706 $ || ($ = {});
4707 if (tagCode === 59) {
4708 $.spriteId = readUi16($bytes, $stream);
4709 }
4710 $.actionsData = readBinary($bytes, $stream, 0);
4711 return $;
4712 }
4713 function defineSound($bytes, $stream, $, swfVersion, tagCode) {
4714 $ || ($ = {});
4715 $.id = readUi16($bytes, $stream);
4716 var soundFlags = readUi8($bytes, $stream);
4717 $.soundFormat = soundFlags >> 4 & 15;
4718 $.soundRate = soundFlags >> 2 & 3;
4719 $.soundSize = soundFlags >> 1 & 1;
4720 $.soundType = soundFlags & 1;
4721 $.samplesCount = readUi32($bytes, $stream);
4722 $.soundData = readBinary($bytes, $stream, 0);
4723 return $;
4724 }
4725 function startSound($bytes, $stream, $, swfVersion, tagCode) {
4726 $ || ($ = {});
4727 if (tagCode == 15) {
4728 $.soundId = readUi16($bytes, $stream);
4729 }
4730 if (tagCode == 89) {
4731 $.soundClassName = readString($bytes, $stream, 0);
4732 }
4733 var $0 = $.soundInfo = {};
4734 soundInfo($bytes, $stream, $0, swfVersion, tagCode);
4735 return $;
4736 }
4737 function soundStreamHead($bytes, $stream, $, swfVersion, tagCode) {
4738 $ || ($ = {});
4739 var playbackFlags = readUi8($bytes, $stream);
4740 $.playbackRate = playbackFlags >> 2 & 3;
4741 $.playbackSize = playbackFlags >> 1 & 1;
4742 $.playbackType = playbackFlags & 1;
4743 var streamFlags = readUi8($bytes, $stream);
4744 var streamCompression = $.streamCompression = streamFlags >> 4 & 15;
4745 $.streamRate = streamFlags >> 2 & 3;
4746 $.streamSize = streamFlags >> 1 & 1;
4747 $.streamType = streamFlags & 1;
4748 $.samplesCount = readUi32($bytes, $stream);
4749 if (streamCompression == 2) {
4750 $.latencySeek = readSi16($bytes, $stream);
4751 }
4752 return $;
4753 }
4754 function soundStreamBlock($bytes, $stream, $, swfVersion, tagCode) {
4755 $ || ($ = {});
4756 $.data = readBinary($bytes, $stream, 0);
4757 return $;
4758 }
4759 function defineBitmap($bytes, $stream, $, swfVersion, tagCode) {
4760 $ || ($ = {});
4761 $.id = readUi16($bytes, $stream);
4762 var format = $.format = readUi8($bytes, $stream);
4763 $.width = readUi16($bytes, $stream);
4764 $.height = readUi16($bytes, $stream);
4765 $.hasAlpha = tagCode === 36;
4766 if (format === 3) {
4767 $.colorTableSize = readUi8($bytes, $stream);
4768 }
4769 $.bmpData = readBinary($bytes, $stream, 0);
4770 return $;
4771 }
4772 function defineText($bytes, $stream, $, swfVersion, tagCode) {
4773 $ || ($ = {});
4774 $.id = readUi16($bytes, $stream);
4775 var $0 = $.bbox = {};
4776 bbox($bytes, $stream, $0, swfVersion, tagCode);
4777 var flags = readUi16($bytes, $stream);
4778 var hasText = $.hasText = flags >> 7 & 1;
4779 $.wordWrap = flags >> 6 & 1;
4780 $.multiline = flags >> 5 & 1;
4781 $.password = flags >> 4 & 1;
4782 $.readonly = flags >> 3 & 1;
4783 var hasColor = $.hasColor = flags >> 2 & 1;
4784 var hasMaxLength = $.hasMaxLength = flags >> 1 & 1;
4785 var hasFont = $.hasFont = flags & 1;
4786 var hasFontClass = $.hasFontClass = flags >> 15 & 1;
4787 $.autoSize = flags >> 14 & 1;
4788 var hasLayout = $.hasLayout = flags >> 13 & 1;
4789 $.noSelect = flags >> 12 & 1;
4790 $.border = flags >> 11 & 1;
4791 $.wasStatic = flags >> 10 & 1;
4792 $.html = flags >> 9 & 1;
4793 $.useOutlines = flags >> 8 & 1;
4794 if (hasFont) {
4795 $.fontId = readUi16($bytes, $stream);
4796 }
4797 if (hasFontClass) {
4798 $.fontClass = readString($bytes, $stream, 0);
4799 }
4800 if (hasFont) {
4801 $.fontHeight = readUi16($bytes, $stream);
4802 }
4803 if (hasColor) {
4804 var $1 = $.color = {};
4805 rgba($bytes, $stream, $1, swfVersion, tagCode);
4806 }
4807 if (hasMaxLength) {
4808 $.maxLength = readUi16($bytes, $stream);
4809 }
4810 if (hasLayout) {
4811 $.align = readUi8($bytes, $stream);
4812 $.leftMargin = readUi16($bytes, $stream);
4813 $.rightMargin = readUi16($bytes, $stream);
4814 $.indent = readSi16($bytes, $stream);
4815 $.leading = readSi16($bytes, $stream);
4816 }
4817 $.variableName = readString($bytes, $stream, 0);
4818 if (hasText) {
4819 $.initialText = readString($bytes, $stream, 0);
4820 }
4821 return $;
4822 }
4823 function frameLabel($bytes, $stream, $, swfVersion, tagCode) {
4824 $ || ($ = {});
4825 $.name = readString($bytes, $stream, 0);
4826 return $;
4827 }
4828 function defineFont2($bytes, $stream, $, swfVersion, tagCode) {
4829 $ || ($ = {});
4830 $.id = readUi16($bytes, $stream);
4831 var hasLayout = $.hasLayout = readUb($bytes, $stream, 1);
4832 if (swfVersion > 5) {
4833 $.shiftJis = readUb($bytes, $stream, 1);
4834 } else {
4835 var reserved = readUb($bytes, $stream, 1);
4836 }
4837 $.smallText = readUb($bytes, $stream, 1);
4838 $.ansi = readUb($bytes, $stream, 1);
4839 var wideOffset = $.wideOffset = readUb($bytes, $stream, 1);
4840 var wide = $.wide = readUb($bytes, $stream, 1);
4841 $.italic = readUb($bytes, $stream, 1);
4842 $.bold = readUb($bytes, $stream, 1);
4843 if (swfVersion > 5) {
4844 $.language = readUi8($bytes, $stream);
4845 } else {
4846 var reserved = readUi8($bytes, $stream);
4847 $.language = 0;
4848 }
4849 var nameLength = readUi8($bytes, $stream);
4850 $.name = readString($bytes, $stream, nameLength);
4851 if (tagCode === 75) {
4852 $.resolution = 20;
4853 }
4854 var glyphCount = $.glyphCount = readUi16($bytes, $stream);
4855 if (wideOffset) {
4856 var $0 = $.offsets = [];
4857 var $1 = glyphCount;
4858 while ($1--) {
4859 $0.push(readUi32($bytes, $stream));
4860 }
4861 $.mapOffset = readUi32($bytes, $stream);
4862 } else {
4863 var $2 = $.offsets = [];
4864 var $3 = glyphCount;
4865 while ($3--) {
4866 $2.push(readUi16($bytes, $stream));
4867 }
4868 $.mapOffset = readUi16($bytes, $stream);
4869 }
4870 var $4 = $.glyphs = [];
4871 var $5 = glyphCount;
4872 while ($5--) {
4873 var $6 = {};
4874 shape($bytes, $stream, $6, swfVersion, tagCode);
4875 $4.push($6);
4876 }
4877 if (wide) {
4878 var $47 = $.codes = [];
4879 var $48 = glyphCount;
4880 while ($48--) {
4881 $47.push(readUi16($bytes, $stream));
4882 }
4883 } else {
4884 var $49 = $.codes = [];
4885 var $50 = glyphCount;
4886 while ($50--) {
4887 $49.push(readUi8($bytes, $stream));
4888 }
4889 }
4890 if (hasLayout) {
4891 $.ascent = readUi16($bytes, $stream);
4892 $.descent = readUi16($bytes, $stream);
4893 $.leading = readSi16($bytes, $stream);
4894 var $51 = $.advance = [];
4895 var $52 = glyphCount;
4896 while ($52--) {
4897 $51.push(readSi16($bytes, $stream));
4898 }
4899 var $53 = $.bbox = [];
4900 var $54 = glyphCount;
4901 while ($54--) {
4902 var $55 = {};
4903 bbox($bytes, $stream, $55, swfVersion, tagCode);
4904 $53.push($55);
4905 }
4906 var kerningCount = readUi16($bytes, $stream);
4907 var $56 = $.kerning = [];
4908 var $57 = kerningCount;
4909 while ($57--) {
4910 var $58 = {};
4911 kerning($bytes, $stream, $58, swfVersion, tagCode, wide);
4912 $56.push($58);
4913 }
4914 }
4915 return $;
4916 }
4917 function fileAttributes($bytes, $stream, $, swfVersion, tagCode) {
4918 $ || ($ = {});
4919 var reserved = readUb($bytes, $stream, 1);
4920 $.useDirectBlit = readUb($bytes, $stream, 1);
4921 $.useGpu = readUb($bytes, $stream, 1);
4922 $.hasMetadata = readUb($bytes, $stream, 1);
4923 $.doAbc = readUb($bytes, $stream, 1);
4924 $.noCrossDomainCaching = readUb($bytes, $stream, 1);
4925 $.relativeUrls = readUb($bytes, $stream, 1);
4926 $.network = readUb($bytes, $stream, 1);
4927 var pad = readUb($bytes, $stream, 24);
4928 return $;
4929 }
4930 function doABC($bytes, $stream, $, swfVersion, tagCode) {
4931 $ || ($ = {});
4932 if (tagCode === 82) {
4933 $.flags = readUi32($bytes, $stream);
4934 } else {
4935 $.flags = 0;
4936 }
4937 if (tagCode === 82) {
4938 $.name = readString($bytes, $stream, 0);
4939 } else {
4940 $.name = '';
4941 }
4942 $.data = readBinary($bytes, $stream, 0);
4943 return $;
4944 }
4945 function exportAssets($bytes, $stream, $, swfVersion, tagCode) {
4946 $ || ($ = {});
4947 var exportsCount = readUi16($bytes, $stream);
4948 var $0 = $.exports = [];
4949 var $1 = exportsCount;
4950 while ($1--) {
4951 var $2 = {};
4952 $2.symbolId = readUi16($bytes, $stream);
4953 $2.className = readString($bytes, $stream, 0);
4954 $0.push($2);
4955 }
4956 return $;
4957 }
4958 function symbolClass($bytes, $stream, $, swfVersion, tagCode) {
4959 $ || ($ = {});
4960 var symbolCount = readUi16($bytes, $stream);
4961 var $0 = $.exports = [];
4962 var $1 = symbolCount;
4963 while ($1--) {
4964 var $2 = {};
4965 $2.symbolId = readUi16($bytes, $stream);
4966 $2.className = readString($bytes, $stream, 0);
4967 $0.push($2);
4968 }
4969 return $;
4970 }
4971 function defineScalingGrid($bytes, $stream, $, swfVersion, tagCode) {
4972 $ || ($ = {});
4973 $.symbolId = readUi16($bytes, $stream);
4974 var $0 = $.splitter = {};
4975 bbox($bytes, $stream, $0, swfVersion, tagCode);
4976 return $;
4977 }
4978 function defineScene($bytes, $stream, $, swfVersion, tagCode) {
4979 $ || ($ = {});
4980 var sceneCount = readEncodedU32($bytes, $stream);
4981 var $0 = $.scenes = [];
4982 var $1 = sceneCount;
4983 while ($1--) {
4984 var $2 = {};
4985 $2.offset = readEncodedU32($bytes, $stream);
4986 $2.name = readString($bytes, $stream, 0);
4987 $0.push($2);
4988 }
4989 var labelCount = readEncodedU32($bytes, $stream);
4990 var $3 = $.labels = [];
4991 var $4 = labelCount;
4992 while ($4--) {
4993 var $5 = {};
4994 $5.frame = readEncodedU32($bytes, $stream);
4995 $5.name = readString($bytes, $stream, 0);
4996 $3.push($5);
4997 }
4998 return $;
4999 }
5000 function bbox($bytes, $stream, $, swfVersion, tagCode) {
5001 align($bytes, $stream);
5002 var bits = readUb($bytes, $stream, 5);
5003 var xMin = readSb($bytes, $stream, bits);
5004 var xMax = readSb($bytes, $stream, bits);
5005 var yMin = readSb($bytes, $stream, bits);
5006 var yMax = readSb($bytes, $stream, bits);
5007 $.xMin = xMin;
5008 $.xMax = xMax;
5009 $.yMin = yMin;
5010 $.yMax = yMax;
5011 align($bytes, $stream);
5012 }
5013 function rgb($bytes, $stream, $, swfVersion, tagCode) {
5014 $.red = readUi8($bytes, $stream);
5015 $.green = readUi8($bytes, $stream);
5016 $.blue = readUi8($bytes, $stream);
5017 $.alpha = 255;
5018 return;
5019 }
5020 function rgba($bytes, $stream, $, swfVersion, tagCode) {
5021 $.red = readUi8($bytes, $stream);
5022 $.green = readUi8($bytes, $stream);
5023 $.blue = readUi8($bytes, $stream);
5024 $.alpha = readUi8($bytes, $stream);
5025 return;
5026 }
5027 function argb($bytes, $stream, $, swfVersion, tagCode) {
5028 $.alpha = readUi8($bytes, $stream);
5029 $.red = readUi8($bytes, $stream);
5030 $.green = readUi8($bytes, $stream);
5031 $.blue = readUi8($bytes, $stream);
5032 }
5033 function fillSolid($bytes, $stream, $, swfVersion, tagCode, isMorph) {
5034 if (tagCode > 22 || isMorph) {
5035 var $125 = $.color = {};
5036 rgba($bytes, $stream, $125, swfVersion, tagCode);
5037 } else {
5038 var $126 = $.color = {};
5039 rgb($bytes, $stream, $126, swfVersion, tagCode);
5040 }
5041 if (isMorph) {
5042 var $127 = $.colorMorph = {};
5043 rgba($bytes, $stream, $127, swfVersion, tagCode);
5044 }
5045 return;
5046 }
5047 function matrix($bytes, $stream, $, swfVersion, tagCode) {
5048 align($bytes, $stream);
5049 var hasScale = readUb($bytes, $stream, 1);
5050 if (hasScale) {
5051 var bits = readUb($bytes, $stream, 5);
5052 $.a = readFb($bytes, $stream, bits);
5053 $.d = readFb($bytes, $stream, bits);
5054 } else {
5055 $.a = 1;
5056 $.d = 1;
5057 }
5058 var hasRotate = readUb($bytes, $stream, 1);
5059 if (hasRotate) {
5060 var bits = readUb($bytes, $stream, 5);
5061 $.b = readFb($bytes, $stream, bits);
5062 $.c = readFb($bytes, $stream, bits);
5063 } else {
5064 $.b = 0;
5065 $.c = 0;
5066 }
5067 var bits = readUb($bytes, $stream, 5);
5068 var e = readSb($bytes, $stream, bits);
5069 var f = readSb($bytes, $stream, bits);
5070 $.tx = e;
5071 $.ty = f;
5072 align($bytes, $stream);
5073 }
5074 function cxform($bytes, $stream, $, swfVersion, tagCode) {
5075 align($bytes, $stream);
5076 var hasOffsets = readUb($bytes, $stream, 1);
5077 var hasMultipliers = readUb($bytes, $stream, 1);
5078 var bits = readUb($bytes, $stream, 4);
5079 if (hasMultipliers) {
5080 $.redMultiplier = readSb($bytes, $stream, bits);
5081 $.greenMultiplier = readSb($bytes, $stream, bits);
5082 $.blueMultiplier = readSb($bytes, $stream, bits);
5083 if (tagCode > 4) {
5084 $.alphaMultiplier = readSb($bytes, $stream, bits);
5085 } else {
5086 $.alphaMultiplier = 256;
5087 }
5088 } else {
5089 $.redMultiplier = 256;
5090 $.greenMultiplier = 256;
5091 $.blueMultiplier = 256;
5092 $.alphaMultiplier = 256;
5093 }
5094 if (hasOffsets) {
5095 $.redOffset = readSb($bytes, $stream, bits);
5096 $.greenOffset = readSb($bytes, $stream, bits);
5097 $.blueOffset = readSb($bytes, $stream, bits);
5098 if (tagCode > 4) {
5099 $.alphaOffset = readSb($bytes, $stream, bits);
5100 } else {
5101 $.alphaOffset = 0;
5102 }
5103 } else {
5104 $.redOffset = 0;
5105 $.greenOffset = 0;
5106 $.blueOffset = 0;
5107 $.alphaOffset = 0;
5108 }
5109 align($bytes, $stream);
5110 }
5111 function fillGradient($bytes, $stream, $, swfVersion, tagCode, isMorph, type) {
5112 var $128 = $.matrix = {};
5113 matrix($bytes, $stream, $128, swfVersion, tagCode);
5114 if (isMorph) {
5115 var $129 = $.matrixMorph = {};
5116 matrix($bytes, $stream, $129, swfVersion, tagCode);
5117 }
5118 gradient($bytes, $stream, $, swfVersion, tagCode, isMorph, type);
5119 }
5120 function gradient($bytes, $stream, $, swfVersion, tagCode, isMorph, type) {
5121 if (tagCode === 83) {
5122 $.spreadMode = readUb($bytes, $stream, 2);
5123 $.interpolationMode = readUb($bytes, $stream, 2);
5124 } else {
5125 var pad = readUb($bytes, $stream, 4);
5126 }
5127 var count = $.count = readUb($bytes, $stream, 4);
5128 var $130 = $.records = [];
5129 var $131 = count;
5130 while ($131--) {
5131 var $132 = {};
5132 gradientRecord($bytes, $stream, $132, swfVersion, tagCode, isMorph);
5133 $130.push($132);
5134 }
5135 if (type === 19) {
5136 $.focalPoint = readFixed8($bytes, $stream);
5137 if (isMorph) {
5138 $.focalPointMorph = readFixed8($bytes, $stream);
5139 }
5140 }
5141 }
5142 function gradientRecord($bytes, $stream, $, swfVersion, tagCode, isMorph) {
5143 $.ratio = readUi8($bytes, $stream);
5144 if (tagCode > 22) {
5145 var $133 = $.color = {};
5146 rgba($bytes, $stream, $133, swfVersion, tagCode);
5147 } else {
5148 var $134 = $.color = {};
5149 rgb($bytes, $stream, $134, swfVersion, tagCode);
5150 }
5151 if (isMorph) {
5152 $.ratioMorph = readUi8($bytes, $stream);
5153 var $135 = $.colorMorph = {};
5154 rgba($bytes, $stream, $135, swfVersion, tagCode);
5155 }
5156 }
5157 function morphShapeWithStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
5158 var eos, bits;
5159 var temp = styles($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
5160 var lineBits = temp.lineBits;
5161 var fillBits = temp.fillBits;
5162 var $160 = $.records = [];
5163 do {
5164 var $161 = {};
5165 var temp = shapeRecord($bytes, $stream, $161, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits);
5166 var eos = temp.eos;
5167 var flags = temp.flags;
5168 var type = temp.type;
5169 var fillBits = temp.fillBits;
5170 var lineBits = temp.lineBits;
5171 var bits = temp.bits;
5172 $160.push($161);
5173 } while (!eos);
5174 var temp = styleBits($bytes, $stream, $, swfVersion, tagCode);
5175 var fillBits = temp.fillBits;
5176 var lineBits = temp.lineBits;
5177 var $162 = $.recordsMorph = [];
5178 do {
5179 var $163 = {};
5180 var temp = shapeRecord($bytes, $stream, $163, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits);
5181 eos = temp.eos;
5182 var flags = temp.flags;
5183 var type = temp.type;
5184 var fillBits = temp.fillBits;
5185 var lineBits = temp.lineBits;
5186 bits = temp.bits;
5187 $162.push($163);
5188 } while (!eos);
5189 }
5190 function shapeWithStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
5191 var eos;
5192 var temp = styles($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
5193 var fillBits = temp.fillBits;
5194 var lineBits = temp.lineBits;
5195 var $160 = $.records = [];
5196 do {
5197 var $161 = {};
5198 var temp = shapeRecord($bytes, $stream, $161, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits);
5199 eos = temp.eos;
5200 var flags = temp.flags;
5201 var type = temp.type;
5202 var fillBits = temp.fillBits;
5203 var lineBits = temp.lineBits;
5204 var bits = temp.bits;
5205 $160.push($161);
5206 } while (!eos);
5207 }
5208 function shapeRecord($bytes, $stream, $, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits) {
5209 var type = $.type = readUb($bytes, $stream, 1);
5210 var flags = readUb($bytes, $stream, 5);
5211 var eos = $.eos = !(type || flags);
5212 if (type) {
5213 var temp = shapeRecordEdge($bytes, $stream, $, swfVersion, tagCode, flags, bits);
5214 var bits = temp.bits;
5215 } else {
5216 var temp = shapeRecordSetup($bytes, $stream, $, swfVersion, tagCode, flags, isMorph, fillBits, lineBits, hasStrokes, bits);
5217 var fillBits = temp.fillBits;
5218 var lineBits = temp.lineBits;
5219 var bits = temp.bits;
5220 }
5221 return {
5222 type: type,
5223 flags: flags,
5224 eos: eos,
5225 fillBits: fillBits,
5226 lineBits: lineBits,
5227 bits: bits
5228 };
5229 }
5230 function shapeRecordEdge($bytes, $stream, $, swfVersion, tagCode, flags, bits) {
5231 var isStraight = 0, tmp = 0, bits = 0, isGeneral = 0, isVertical = 0;
5232 isStraight = $.isStraight = flags >> 4;
5233 tmp = flags & 15;
5234 bits = tmp + 2;
5235 if (isStraight) {
5236 isGeneral = $.isGeneral = readUb($bytes, $stream, 1);
5237 if (isGeneral) {
5238 $.deltaX = readSb($bytes, $stream, bits);
5239 $.deltaY = readSb($bytes, $stream, bits);
5240 } else {
5241 isVertical = $.isVertical = readUb($bytes, $stream, 1);
5242 if (isVertical) {
5243 $.deltaY = readSb($bytes, $stream, bits);
5244 } else {
5245 $.deltaX = readSb($bytes, $stream, bits);
5246 }
5247 }
5248 } else {
5249 $.controlDeltaX = readSb($bytes, $stream, bits);
5250 $.controlDeltaY = readSb($bytes, $stream, bits);
5251 $.anchorDeltaX = readSb($bytes, $stream, bits);
5252 $.anchorDeltaY = readSb($bytes, $stream, bits);
5253 }
5254 return {
5255 bits: bits
5256 };
5257 }
5258 function shapeRecordSetup($bytes, $stream, $, swfVersion, tagCode, flags, isMorph, fillBits, lineBits, hasStrokes, bits) {
5259 var hasNewStyles = 0, hasLineStyle = 0, hasFillStyle1 = 0;
5260 var hasFillStyle0 = 0, move = 0;
5261 if (tagCode > 2) {
5262 hasNewStyles = $.hasNewStyles = flags >> 4;
5263 } else {
5264 hasNewStyles = $.hasNewStyles = 0;
5265 }
5266 hasLineStyle = $.hasLineStyle = flags >> 3 & 1;
5267 hasFillStyle1 = $.hasFillStyle1 = flags >> 2 & 1;
5268 hasFillStyle0 = $.hasFillStyle0 = flags >> 1 & 1;
5269 move = $.move = flags & 1;
5270 if (move) {
5271 bits = readUb($bytes, $stream, 5);
5272 $.moveX = readSb($bytes, $stream, bits);
5273 $.moveY = readSb($bytes, $stream, bits);
5274 }
5275 if (hasFillStyle0) {
5276 $.fillStyle0 = readUb($bytes, $stream, fillBits);
5277 }
5278 if (hasFillStyle1) {
5279 $.fillStyle1 = readUb($bytes, $stream, fillBits);
5280 }
5281 if (hasLineStyle) {
5282 $.lineStyle = readUb($bytes, $stream, lineBits);
5283 }
5284 if (hasNewStyles) {
5285 var temp = styles($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
5286 var lineBits = temp.lineBits;
5287 var fillBits = temp.fillBits;
5288 }
5289 return {
5290 lineBits: lineBits,
5291 fillBits: fillBits,
5292 bits: bits
5293 };
5294 }
5295 function styles($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
5296 fillStyleArray($bytes, $stream, $, swfVersion, tagCode, isMorph);
5297 lineStyleArray($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes);
5298 var temp = styleBits($bytes, $stream, $, swfVersion, tagCode);
5299 var fillBits = temp.fillBits;
5300 var lineBits = temp.lineBits;
5301 return {
5302 fillBits: fillBits,
5303 lineBits: lineBits
5304 };
5305 }
5306 function fillStyleArray($bytes, $stream, $, swfVersion, tagCode, isMorph) {
5307 var count;
5308 var tmp = readUi8($bytes, $stream);
5309 if (tagCode > 2 && tmp === 255) {
5310 count = readUi16($bytes, $stream);
5311 } else {
5312 count = tmp;
5313 }
5314 var $4 = $.fillStyles = [];
5315 var $5 = count;
5316 while ($5--) {
5317 var $6 = {};
5318 fillStyle($bytes, $stream, $6, swfVersion, tagCode, isMorph);
5319 $4.push($6);
5320 }
5321 }
5322 function lineStyleArray($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
5323 var count;
5324 var tmp = readUi8($bytes, $stream);
5325 if (tagCode > 2 && tmp === 255) {
5326 count = readUi16($bytes, $stream);
5327 } else {
5328 count = tmp;
5329 }
5330 var $138 = $.lineStyles = [];
5331 var $139 = count;
5332 while ($139--) {
5333 var $140 = {};
5334 lineStyle($bytes, $stream, $140, swfVersion, tagCode, isMorph, hasStrokes);
5335 $138.push($140);
5336 }
5337 }
5338 function styleBits($bytes, $stream, $, swfVersion, tagCode) {
5339 align($bytes, $stream);
5340 var fillBits = readUb($bytes, $stream, 4);
5341 var lineBits = readUb($bytes, $stream, 4);
5342 return {
5343 fillBits: fillBits,
5344 lineBits: lineBits
5345 };
5346 }
5347 function fillStyle($bytes, $stream, $, swfVersion, tagCode, isMorph) {
5348 var type = $.type = readUi8($bytes, $stream);
5349 switch (type) {
5350 case 0:
5351 fillSolid($bytes, $stream, $, swfVersion, tagCode, isMorph);
5352 break;
5353 case 16:
5354 case 18:
5355 case 19:
5356 fillGradient($bytes, $stream, $, swfVersion, tagCode, isMorph, type);
5357 break;
5358 case 64:
5359 case 65:
5360 case 66:
5361 case 67:
5362 fillBitmap($bytes, $stream, $, swfVersion, tagCode, isMorph, type);
5363 break;
5364 default:
5365 }
5366 }
5367 function lineStyle($bytes, $stream, $, swfVersion, tagCode, isMorph, hasStrokes) {
5368 $.width = readUi16($bytes, $stream);
5369 if (isMorph) {
5370 $.widthMorph = readUi16($bytes, $stream);
5371 }
5372 if (hasStrokes) {
5373 align($bytes, $stream);
5374 $.startCapStyle = readUb($bytes, $stream, 2);
5375 var joinStyle = $.joinStyle = readUb($bytes, $stream, 2);
5376 var hasFill = $.hasFill = readUb($bytes, $stream, 1);
5377 $.noHscale = readUb($bytes, $stream, 1);
5378 $.noVscale = readUb($bytes, $stream, 1);
5379 $.pixelHinting = readUb($bytes, $stream, 1);
5380 var reserved = readUb($bytes, $stream, 5);
5381 $.noClose = readUb($bytes, $stream, 1);
5382 $.endCapStyle = readUb($bytes, $stream, 2);
5383 if (joinStyle === 2) {
5384 $.miterLimitFactor = readFixed8($bytes, $stream);
5385 }
5386 if (hasFill) {
5387 var $141 = $.fillStyle = {};
5388 fillStyle($bytes, $stream, $141, swfVersion, tagCode, isMorph);
5389 } else {
5390 var $155 = $.color = {};
5391 rgba($bytes, $stream, $155, swfVersion, tagCode);
5392 if (isMorph) {
5393 var $156 = $.colorMorph = {};
5394 rgba($bytes, $stream, $156, swfVersion, tagCode);
5395 }
5396 }
5397 } else {
5398 if (tagCode > 22) {
5399 var $157 = $.color = {};
5400 rgba($bytes, $stream, $157, swfVersion, tagCode);
5401 } else {
5402 var $158 = $.color = {};
5403 rgb($bytes, $stream, $158, swfVersion, tagCode);
5404 }
5405 if (isMorph) {
5406 var $159 = $.colorMorph = {};
5407 rgba($bytes, $stream, $159, swfVersion, tagCode);
5408 }
5409 }
5410 }
5411 function fillBitmap($bytes, $stream, $, swfVersion, tagCode, isMorph, type) {
5412 $.bitmapId = readUi16($bytes, $stream);
5413 var $18 = $.matrix = {};
5414 matrix($bytes, $stream, $18, swfVersion, tagCode);
5415 if (isMorph) {
5416 var $19 = $.matrixMorph = {};
5417 matrix($bytes, $stream, $19, swfVersion, tagCode);
5418 }
5419 $.condition = type === 64 || type === 67;
5420 }
5421 function filterGlow($bytes, $stream, $, swfVersion, tagCode, type) {
5422 var count;
5423 if (type === 4 || type === 7) {
5424 count = readUi8($bytes, $stream);
5425 } else {
5426 count = 1;
5427 }
5428 var $5 = $.colors = [];
5429 var $6 = count;
5430 while ($6--) {
5431 var $7 = {};
5432 rgba($bytes, $stream, $7, swfVersion, tagCode);
5433 $5.push($7);
5434 }
5435 if (type === 3) {
5436 var $8 = $.higlightColor = {};
5437 rgba($bytes, $stream, $8, swfVersion, tagCode);
5438 }
5439 if (type === 4 || type === 7) {
5440 var $9 = $.ratios = [];
5441 var $10 = count;
5442 while ($10--) {
5443 $9.push(readUi8($bytes, $stream));
5444 }
5445 }
5446 $.blurX = readFixed($bytes, $stream);
5447 $.blurY = readFixed($bytes, $stream);
5448 if (type !== 2) {
5449 $.angle = readFixed($bytes, $stream);
5450 $.distance = readFixed($bytes, $stream);
5451 }
5452 $.strength = readFixed8($bytes, $stream);
5453 $.innerShadow = readUb($bytes, $stream, 1);
5454 $.knockout = readUb($bytes, $stream, 1);
5455 $.compositeSource = readUb($bytes, $stream, 1);
5456 if (type === 3) {
5457 $.onTop = readUb($bytes, $stream, 1);
5458 } else {
5459 var reserved = readUb($bytes, $stream, 1);
5460 }
5461 if (type === 4 || type === 7) {
5462 $.passes = readUb($bytes, $stream, 4);
5463 } else {
5464 var reserved = readUb($bytes, $stream, 4);
5465 }
5466 }
5467 function filterBlur($bytes, $stream, $, swfVersion, tagCode) {
5468 $.blurX = readFixed($bytes, $stream);
5469 $.blurY = readFixed($bytes, $stream);
5470 $.passes = readUb($bytes, $stream, 5);
5471 var reserved = readUb($bytes, $stream, 3);
5472 }
5473 function filterConvolution($bytes, $stream, $, swfVersion, tagCode) {
5474 var columns = $.columns = readUi8($bytes, $stream);
5475 var rows = $.rows = readUi8($bytes, $stream);
5476 $.divisor = readFloat($bytes, $stream);
5477 $.bias = readFloat($bytes, $stream);
5478 var $17 = $.weights = [];
5479 var $18 = columns * rows;
5480 while ($18--) {
5481 $17.push(readFloat($bytes, $stream));
5482 }
5483 var $19 = $.defaultColor = {};
5484 rgba($bytes, $stream, $19, swfVersion, tagCode);
5485 var reserved = readUb($bytes, $stream, 6);
5486 $.clamp = readUb($bytes, $stream, 1);
5487 $.preserveAlpha = readUb($bytes, $stream, 1);
5488 }
5489 function filterColorMatrix($bytes, $stream, $, swfVersion, tagCode) {
5490 var $20 = $.matrix = [];
5491 var $21 = 20;
5492 while ($21--) {
5493 $20.push(readFloat($bytes, $stream));
5494 }
5495 }
5496 function anyFilter($bytes, $stream, $, swfVersion, tagCode) {
5497 var type = $.type = readUi8($bytes, $stream);
5498 switch (type) {
5499 case 0:
5500 case 2:
5501 case 3:
5502 case 4:
5503 case 7:
5504 filterGlow($bytes, $stream, $, swfVersion, tagCode, type);
5505 break;
5506 case 1:
5507 filterBlur($bytes, $stream, $, swfVersion, tagCode);
5508 break;
5509 case 5:
5510 filterConvolution($bytes, $stream, $, swfVersion, tagCode);
5511 break;
5512 case 6:
5513 filterColorMatrix($bytes, $stream, $, swfVersion, tagCode);
5514 break;
5515 default:
5516 }
5517 }
5518 function events($bytes, $stream, $, swfVersion, tagCode) {
5519 var flags, keyPress;
5520 if (swfVersion >= 6) {
5521 flags = readUi32($bytes, $stream);
5522 } else {
5523 flags = readUi16($bytes, $stream);
5524 }
5525 var eoe = $.eoe = !flags;
5526 $.onKeyUp = flags >> 7 & 1;
5527 $.onKeyDown = flags >> 6 & 1;
5528 $.onMouseUp = flags >> 5 & 1;
5529 $.onMouseDown = flags >> 4 & 1;
5530 $.onMouseMove = flags >> 3 & 1;
5531 $.onUnload = flags >> 2 & 1;
5532 $.onEnterFrame = flags >> 1 & 1;
5533 $.onLoad = flags & 1;
5534 if (swfVersion >= 6) {
5535 $.onDragOver = flags >> 15 & 1;
5536 $.onRollOut = flags >> 14 & 1;
5537 $.onRollOver = flags >> 13 & 1;
5538 $.onReleaseOutside = flags >> 12 & 1;
5539 $.onRelease = flags >> 11 & 1;
5540 $.onPress = flags >> 10 & 1;
5541 $.onInitialize = flags >> 9 & 1;
5542 $.onData = flags >> 8 & 1;
5543 if (swfVersion >= 7) {
5544 $.onConstruct = flags >> 18 & 1;
5545 } else {
5546 $.onConstruct = 0;
5547 }
5548 keyPress = $.keyPress = flags >> 17 & 1;
5549 $.onDragOut = flags >> 16 & 1;
5550 }
5551 if (!eoe) {
5552 var length = $.length = readUi32($bytes, $stream);
5553 if (keyPress) {
5554 $.keyCode = readUi8($bytes, $stream);
5555 }
5556 $.actionsData = readBinary($bytes, $stream, length - (keyPress ? 1 : 0));
5557 }
5558 return {
5559 eoe: eoe
5560 };
5561 }
5562 function kerning($bytes, $stream, $, swfVersion, tagCode, wide) {
5563 if (wide) {
5564 $.code1 = readUi16($bytes, $stream);
5565 $.code2 = readUi16($bytes, $stream);
5566 } else {
5567 $.code1 = readUi8($bytes, $stream);
5568 $.code2 = readUi8($bytes, $stream);
5569 }
5570 $.adjustment = readUi16($bytes, $stream);
5571 }
5572 function textEntry($bytes, $stream, $, swfVersion, tagCode, glyphBits, advanceBits) {
5573 $.glyphIndex = readUb($bytes, $stream, glyphBits);
5574 $.advance = readSb($bytes, $stream, advanceBits);
5575 }
5576 function textRecordSetup($bytes, $stream, $, swfVersion, tagCode, flags) {
5577 var hasFont = $.hasFont = flags >> 3 & 1;
5578 var hasColor = $.hasColor = flags >> 2 & 1;
5579 var hasMoveY = $.hasMoveY = flags >> 1 & 1;
5580 var hasMoveX = $.hasMoveX = flags & 1;
5581 if (hasFont) {
5582 $.fontId = readUi16($bytes, $stream);
5583 }
5584 if (hasColor) {
5585 if (tagCode === 33) {
5586 var $4 = $.color = {};
5587 rgba($bytes, $stream, $4, swfVersion, tagCode);
5588 } else {
5589 var $5 = $.color = {};
5590 rgb($bytes, $stream, $5, swfVersion, tagCode);
5591 }
5592 }
5593 if (hasMoveX) {
5594 $.moveX = readSi16($bytes, $stream);
5595 }
5596 if (hasMoveY) {
5597 $.moveY = readSi16($bytes, $stream);
5598 }
5599 if (hasFont) {
5600 $.fontHeight = readUi16($bytes, $stream);
5601 }
5602 }
5603 function textRecord($bytes, $stream, $, swfVersion, tagCode, glyphBits, advanceBits) {
5604 var glyphCount;
5605 align($bytes, $stream);
5606 var flags = readUb($bytes, $stream, 8);
5607 var eot = $.eot = !flags;
5608 textRecordSetup($bytes, $stream, $, swfVersion, tagCode, flags);
5609 if (!eot) {
5610 var tmp = readUi8($bytes, $stream);
5611 if (swfVersion > 6) {
5612 glyphCount = $.glyphCount = tmp;
5613 } else {
5614 glyphCount = $.glyphCount = tmp & 127;
5615 }
5616 var $6 = $.entries = [];
5617 var $7 = glyphCount;
5618 while ($7--) {
5619 var $8 = {};
5620 textEntry($bytes, $stream, $8, swfVersion, tagCode, glyphBits, advanceBits);
5621 $6.push($8);
5622 }
5623 }
5624 return {
5625 eot: eot
5626 };
5627 }
5628 function soundEnvelope($bytes, $stream, $, swfVersion, tagCode) {
5629 $.pos44 = readUi32($bytes, $stream);
5630 $.volumeLeft = readUi16($bytes, $stream);
5631 $.volumeRight = readUi16($bytes, $stream);
5632 }
5633 function soundInfo($bytes, $stream, $, swfVersion, tagCode) {
5634 var reserved = readUb($bytes, $stream, 2);
5635 $.stop = readUb($bytes, $stream, 1);
5636 $.noMultiple = readUb($bytes, $stream, 1);
5637 var hasEnvelope = $.hasEnvelope = readUb($bytes, $stream, 1);
5638 var hasLoops = $.hasLoops = readUb($bytes, $stream, 1);
5639 var hasOutPoint = $.hasOutPoint = readUb($bytes, $stream, 1);
5640 var hasInPoint = $.hasInPoint = readUb($bytes, $stream, 1);
5641 if (hasInPoint) {
5642 $.inPoint = readUi32($bytes, $stream);
5643 }
5644 if (hasOutPoint) {
5645 $.outPoint = readUi32($bytes, $stream);
5646 }
5647 if (hasLoops) {
5648 $.loopCount = readUi16($bytes, $stream);
5649 }
5650 if (hasEnvelope) {
5651 var envelopeCount = $.envelopeCount = readUi8($bytes, $stream);
5652 var $1 = $.envelopes = [];
5653 var $2 = envelopeCount;
5654 while ($2--) {
5655 var $3 = {};
5656 soundEnvelope($bytes, $stream, $3, swfVersion, tagCode);
5657 $1.push($3);
5658 }
5659 }
5660 }
5661 function button($bytes, $stream, $, swfVersion, tagCode) {
5662 var hasFilters, blend;
5663 var flags = readUi8($bytes, $stream);
5664 var eob = $.eob = !flags;
5665 if (swfVersion >= 8) {
5666 blend = $.blend = flags >> 5 & 1;
5667 hasFilters = $.hasFilters = flags >> 4 & 1;
5668 } else {
5669 blend = $.blend = 0;
5670 hasFilters = $.hasFilters = 0;
5671 }
5672 $.stateHitTest = flags >> 3 & 1;
5673 $.stateDown = flags >> 2 & 1;
5674 $.stateOver = flags >> 1 & 1;
5675 $.stateUp = flags & 1;
5676 if (!eob) {
5677 $.symbolId = readUi16($bytes, $stream);
5678 $.depth = readUi16($bytes, $stream);
5679 var $2 = $.matrix = {};
5680 matrix($bytes, $stream, $2, swfVersion, tagCode);
5681 if (tagCode === 34) {
5682 var $3 = $.cxform = {};
5683 cxform($bytes, $stream, $3, swfVersion, tagCode);
5684 }
5685 if (hasFilters) {
5686 $.filterCount = readUi8($bytes, $stream);
5687 var $4 = $.filters = {};
5688 anyFilter($bytes, $stream, $4, swfVersion, tagCode);
5689 }
5690 if (blend) {
5691 $.blendMode = readUi8($bytes, $stream);
5692 }
5693 }
5694 return {
5695 eob: eob
5696 };
5697 }
5698 function buttonCondAction($bytes, $stream, $, swfVersion, tagCode) {
5699 var buttonCondSize = readUi16($bytes, $stream);
5700 var buttonConditions = readUi16($bytes, $stream);
5701 $.idleToOverDown = buttonConditions >> 7 & 1;
5702 $.outDownToIdle = buttonConditions >> 6 & 1;
5703 $.outDownToOverDown = buttonConditions >> 5 & 1;
5704 $.overDownToOutDown = buttonConditions >> 4 & 1;
5705 $.overDownToOverUp = buttonConditions >> 3 & 1;
5706 $.overUpToOverDown = buttonConditions >> 2 & 1;
5707 $.overUpToIdle = buttonConditions >> 1 & 1;
5708 $.idleToOverUp = buttonConditions & 1;
5709 $.mouseEventFlags = buttonConditions & 511;
5710 $.keyPress = buttonConditions >> 9 & 127;
5711 $.overDownToIdle = buttonConditions >> 8 & 1;
5712 if (!buttonCondSize) {
5713 $.actionsData = readBinary($bytes, $stream, 0);
5714 } else {
5715 $.actionsData = readBinary($bytes, $stream, buttonCondSize - 4);
5716 }
5717 }
5718 function shape($bytes, $stream, $, swfVersion, tagCode) {
5719 var eos;
5720 var temp = styleBits($bytes, $stream, $, swfVersion, tagCode);
5721 var fillBits = temp.fillBits;
5722 var lineBits = temp.lineBits;
5723 var $4 = $.records = [];
5724 do {
5725 var $5 = {};
5726 var isMorph = false;
5727 var hasStrokes = false;
5728 var temp = shapeRecord($bytes, $stream, $5, swfVersion, tagCode, isMorph, fillBits, lineBits, hasStrokes, bits);
5729 eos = temp.eos;
5730 var fillBits = temp.fillBits;
5731 var lineBits = temp.lineBits;
5732 var bits = bits;
5733 $4.push($5);
5734 } while (!eos);
5735 }
5736 return {
5737 0: undefined,
5738 1: undefined,
5739 2: defineShape,
5740 4: placeObject,
5741 5: removeObject,
5742 6: defineImage,
5743 7: defineButton,
5744 8: defineJPEGTables,
5745 9: setBackgroundColor,
5746 10: defineFont,
5747 11: defineLabel,
5748 12: doAction,
5749 13: undefined,
5750 14: defineSound,
5751 15: startSound,
5752 17: undefined,
5753 18: soundStreamHead,
5754 19: soundStreamBlock,
5755 20: defineBitmap,
5756 21: defineImage,
5757 22: defineShape,
5758 23: undefined,
5759 24: undefined,
5760 26: placeObject,
5761 28: removeObject,
5762 32: defineShape,
5763 33: defineLabel,
5764 34: defineButton,
5765 35: defineImage,
5766 36: defineBitmap,
5767 37: defineText,
5768 39: undefined,
5769 43: frameLabel,
5770 45: soundStreamHead,
5771 46: defineShape,
5772 48: defineFont2,
5773 56: exportAssets,
5774 57: undefined,
5775 58: undefined,
5776 59: doAction,
5777 60: undefined,
5778 61: undefined,
5779 62: undefined,
5780 64: undefined,
5781 65: undefined,
5782 66: undefined,
5783 69: fileAttributes,
5784 70: placeObject,
5785 71: undefined,
5786 72: doABC,
5787 73: undefined,
5788 74: undefined,
5789 75: defineFont2,
5790 76: symbolClass,
5791 77: undefined,
5792 78: defineScalingGrid,
5793 82: doABC,
5794 83: defineShape,
5795 84: defineShape,
5796 86: defineScene,
5797 87: defineBinaryData,
5798 88: undefined,
5799 89: startSound,
5800 90: defineImage,
5801 91: undefined
5802 };
5803 }(this);
5804 var readHeader = function readHeader($bytes, $stream, $, swfVersion, tagCode) {
5805 $ || ($ = {});
5806 var $0 = $.bbox = {};
5807 align($bytes, $stream);
5808 var bits = readUb($bytes, $stream, 5);
5809 var xMin = readSb($bytes, $stream, bits);
5810 var xMax = readSb($bytes, $stream, bits);
5811 var yMin = readSb($bytes, $stream, bits);
5812 var yMax = readSb($bytes, $stream, bits);
5813 $0.xMin = xMin;
5814 $0.xMax = xMax;
5815 $0.yMin = yMin;
5816 $0.yMax = yMax;
5817 align($bytes, $stream);
5818 var frameRateFraction = readUi8($bytes, $stream);
5819 $.frameRate = readUi8($bytes, $stream) + frameRateFraction / 256;
5820 $.frameCount = readUi16($bytes, $stream);
5821 return $;
5822 };
5823 (function (global) {
5824 global['tagHandler'] = tagHandler;
5825 global['readHeader'] = readHeader;
5826 }(this));
5827 function readTags(context, stream, swfVersion, final, onprogress, onexception) {
5828 var tags = context.tags;
5829 var bytes = stream.bytes;
5830 var lastSuccessfulPosition;
5831 var tag = null;
5832 if (context._readTag) {
5833 tag = context._readTag;
5834 context._readTag = null;
5835 }
5836 try {
5837 while (stream.pos < stream.end) {
5838 lastSuccessfulPosition = stream.pos;
5839 stream.ensure(2);
5840 var tagCodeAndLength = readUi16(bytes, stream);
5841 if (!tagCodeAndLength) {
5842 final = true;
5843 break;
5844 }
5845 var tagCode = tagCodeAndLength >> 6;
5846 var length = tagCodeAndLength & 63;
5847 if (length === 63) {
5848 stream.ensure(4);
5849 length = readUi32(bytes, stream);
5850 }
5851 if (tag) {
5852 if (tagCode === 1 && tag.code === 1) {
5853 tag.repeat++;
5854 stream.pos += length;
5855 continue;
5856 }
5857 tags.push(tag);
5858 if (onprogress && tag.id !== undefined) {
5859 onprogress(context);
5860 }
5861 tag = null;
5862 }
5863 stream.ensure(length);
5864 var substream = stream.substream(stream.pos, stream.pos += length);
5865 var subbytes = substream.bytes;
5866 var nextTag = {
5867 code: tagCode
5868 };
5869 if (tagCode === 39) {
5870 nextTag.type = 'sprite';
5871 nextTag.id = readUi16(subbytes, substream);
5872 nextTag.frameCount = readUi16(subbytes, substream);
5873 nextTag.tags = [];
5874 readTags(nextTag, substream, swfVersion, true);
5875 } else if (tagCode === 1) {
5876 nextTag.repeat = 1;
5877 } else {
5878 var handler = tagHandler[tagCode];
5879 if (handler) {
5880 handler(subbytes, substream, nextTag, swfVersion, tagCode);
5881 }
5882 }
5883 tag = nextTag;
5884 }
5885 if (tag && final) {
5886 tag.finalTag = true;
5887 tags.push(tag);
5888 if (onprogress) {
5889 onprogress(context);
5890 }
5891 } else {
5892 context._readTag = tag;
5893 }
5894 } catch (e) {
5895 if (e !== StreamNoDataError) {
5896 onexception && onexception(e);
5897 throw e;
5898 }
5899 stream.pos = lastSuccessfulPosition;
5900 context._readTag = tag;
5901 }
5902 }
5903 function HeadTailBuffer(defaultSize) {
5904 this.bufferSize = defaultSize || 16;
5905 this.buffer = new Uint8Array(this.bufferSize);
5906 this.pos = 0;
5907 }
5908 HeadTailBuffer.prototype = {
5909 push: function (data, need) {
5910 var bufferLengthNeed = this.pos + data.length;
5911 if (this.bufferSize < bufferLengthNeed) {
5912 var newBufferSize = this.bufferSize;
5913 while (newBufferSize < bufferLengthNeed) {
5914 newBufferSize <<= 1;
5915 }
5916 var newBuffer = new Uint8Array(newBufferSize);
5917 if (this.bufferSize > 0) {
5918 newBuffer.set(this.buffer);
5919 }
5920 this.buffer = newBuffer;
5921 this.bufferSize = newBufferSize;
5922 }
5923 this.buffer.set(data, this.pos);
5924 this.pos += data.length;
5925 if (need)
5926 return this.pos >= need;
5927 },
5928 getHead: function (size) {
5929 return this.buffer.subarray(0, size);
5930 },
5931 getTail: function (offset) {
5932 return this.buffer.subarray(offset, this.pos);
5933 },
5934 removeHead: function (size) {
5935 var tail = this.getTail(size);
5936 this.buffer = new Uint8Array(this.bufferSize);
5937 this.buffer.set(tail);
5938 this.pos = tail.length;
5939 },
5940 get arrayBuffer() {
5941 return this.buffer.buffer;
5942 },
5943 get length() {
5944 return this.pos;
5945 },
5946 createStream: function () {
5947 return new Stream(this.arrayBuffer, 0, this.length);
5948 }
5949 };
5950 function CompressedPipe(target, length) {
5951 this.target = target;
5952 this.length = length;
5953 this.initialize = true;
5954 this.buffer = new HeadTailBuffer(8096);
5955 this.state = {
5956 bitBuffer: 0,
5957 bitLength: 0,
5958 compression: {
5959 header: null,
5960 distanceTable: null,
5961 literalTable: null,
5962 sym: null,
5963 len: null,
5964 sym2: null
5965 }
5966 };
5967 this.output = {
5968 data: new Uint8Array(length),
5969 available: 0,
5970 completed: false
5971 };
5972 }
5973 CompressedPipe.prototype = {
5974 push: function (data, progressInfo) {
5975 var buffer = this.buffer;
5976 if (this.initialize) {
5977 if (!buffer.push(data, 2))
5978 return;
5979 var headerBytes = buffer.getHead(2);
5980 verifyDeflateHeader(headerBytes);
5981 buffer.removeHead(2);
5982 this.initialize = false;
5983 } else {
5984 buffer.push(data);
5985 }
5986 var stream = buffer.createStream();
5987 stream.bitBuffer = this.state.bitBuffer;
5988 stream.bitLength = this.state.bitLength;
5989 var output = this.output;
5990 var lastAvailable = output.available;
5991 try {
5992 do {
5993 inflateBlock(stream, output, this.state.compression);
5994 } while (stream.pos < buffer.length && !output.completed);
5995 } catch (e) {
5996 if (e !== InflateNoDataError)
5997 throw e;
5998 } finally {
5999 this.state.bitBuffer = stream.bitBuffer;
6000 this.state.bitLength = stream.bitLength;
6001 }
6002 buffer.removeHead(stream.pos);
6003 this.target.push(output.data.subarray(lastAvailable, output.available), progressInfo);
6004 }
6005 };
6006 function BodyParser(swfVersion, length, options) {
6007 this.swf = {
6008 swfVersion: swfVersion,
6009 parseTime: 0
6010 };
6011 this.buffer = new HeadTailBuffer(32768);
6012 this.initialize = true;
6013 this.totalRead = 0;
6014 this.length = length;
6015 this.options = options;
6016 }
6017 BodyParser.prototype = {
6018 push: function (data, progressInfo) {
6019 if (data.length === 0)
6020 return;
6021 var swf = this.swf;
6022 var swfVersion = swf.swfVersion;
6023 var buffer = this.buffer;
6024 var options = this.options;
6025 var stream;
6026 if (this.initialize) {
6027 var PREFETCH_SIZE = 27;
6028 if (!buffer.push(data, PREFETCH_SIZE))
6029 return;
6030 stream = buffer.createStream();
6031 var bytes = stream.bytes;
6032 readHeader(bytes, stream, swf);
6033 var nextTagHeader = readUi16(bytes, stream);
6034 var FILE_ATTRIBUTES_LENGTH = 4;
6035 if (nextTagHeader == (SWF_TAG_CODE_FILE_ATTRIBUTES << 6 | FILE_ATTRIBUTES_LENGTH)) {
6036 stream.ensure(FILE_ATTRIBUTES_LENGTH);
6037 var substream = stream.substream(stream.pos, stream.pos += FILE_ATTRIBUTES_LENGTH);
6038 var handler = tagHandler[SWF_TAG_CODE_FILE_ATTRIBUTES];
6039 var fileAttributesTag = {
6040 code: SWF_TAG_CODE_FILE_ATTRIBUTES
6041 };
6042 handler(substream.bytes, substream, fileAttributesTag, swfVersion, SWF_TAG_CODE_FILE_ATTRIBUTES);
6043 swf.fileAttributes = fileAttributesTag;
6044 } else {
6045 stream.pos -= 2;
6046 swf.fileAttributes = {};
6047 }
6048 if (options.onstart)
6049 options.onstart(swf);
6050 swf.tags = [];
6051 this.initialize = false;
6052 } else {
6053 buffer.push(data);
6054 stream = buffer.createStream();
6055 }
6056 var finalBlock = false;
6057 if (progressInfo) {
6058 swf.bytesLoaded = progressInfo.bytesLoaded;
6059 swf.bytesTotal = progressInfo.bytesTotal;
6060 finalBlock = progressInfo.bytesLoaded >= progressInfo.bytesTotal;
6061 }
6062 var readStartTime = performance.now();
6063 readTags(swf, stream, swfVersion, finalBlock, options.onprogress, options.onexception);
6064 swf.parseTime += performance.now() - readStartTime;
6065 var read = stream.pos;
6066 buffer.removeHead(read);
6067 this.totalRead += read;
6068 if (options.oncomplete && swf.tags[swf.tags.length - 1].finalTag) {
6069 options.oncomplete(swf);
6070 }
6071 }
6072 };
6073 SWF.parseAsync = function swf_parseAsync(options) {
6074 var buffer = new HeadTailBuffer();
6075 var pipe = {
6076 push: function (data, progressInfo) {
6077 if (this.target !== undefined) {
6078 return this.target.push(data, progressInfo);
6079 }
6080 if (!buffer.push(data, 8)) {
6081 return null;
6082 }
6083 var bytes = buffer.getHead(8);
6084 var magic1 = bytes[0];
6085 var magic2 = bytes[1];
6086 var magic3 = bytes[2];
6087 if ((magic1 === 70 || magic1 === 67) && magic2 === 87 && magic3 === 83) {
6088 var swfVersion = bytes[3];
6089 var compressed = magic1 === 67;
6090 parseSWF(compressed, swfVersion, progressInfo);
6091 buffer = null;
6092 return;
6093 }
6094 var isImage = false;
6095 var imageType;
6096 if (magic1 === 255 && magic2 === 216 && magic3 === 255) {
6097 isImage = true;
6098 imageType = 'image/jpeg';
6099 } else if (magic1 === 137 && magic2 === 80 && magic3 === 78) {
6100 isImage = true;
6101 imageType = 'image/png';
6102 }
6103 if (isImage) {
6104 parseImage(data, progressInfo.bytesTotal, imageType);
6105 }
6106 buffer = null;
6107 },
6108 close: function () {
6109 if (buffer) {
6110 var symbol = {
6111 command: 'empty',
6112 data: buffer.buffer.subarray(0, buffer.pos)
6113 };
6114 options.oncomplete && options.oncomplete(symbol);
6115 }
6116 if (this.target !== undefined && this.target.close) {
6117 this.target.close();
6118 }
6119 }
6120 };
6121 function parseSWF(compressed, swfVersion, progressInfo) {
6122 var stream = buffer.createStream();
6123 stream.pos += 4;
6124 var fileLength = readUi32(null, stream);
6125 var bodyLength = fileLength - 8;
6126 var target = new BodyParser(swfVersion, bodyLength, options);
6127 if (compressed) {
6128 target = new CompressedPipe(target, bodyLength);
6129 }
6130 target.push(buffer.getTail(8), progressInfo);
6131 pipe['target'] = target;
6132 }
6133 function parseImage(data, bytesTotal, type) {
6134 var buffer = new Uint8Array(bytesTotal);
6135 buffer.set(data);
6136 var bufferPos = data.length;
6137 pipe['target'] = {
6138 push: function (data) {
6139 buffer.set(data, bufferPos);
6140 bufferPos += data.length;
6141 },
6142 close: function () {
6143 var props = {};
6144 var chunks;
6145 if (type == 'image/jpeg') {
6146 chunks = parseJpegChunks(props, buffer);
6147 } else {
6148 chunks = [
6149 buffer
6150 ];
6151 }
6152 var symbol = {
6153 type: 'image',
6154 props: props,
6155 data: new Blob(chunks, {
6156 type: type
6157 })
6158 };
6159 options.oncomplete && options.oncomplete(symbol);
6160 }
6161 };
6162 }
6163 return pipe;
6164 };
6165 SWF.parse = function (buffer, options) {
6166 if (!options)
6167 options = {};
6168 var pipe = SWF.parseAsync(options);
6169 var bytes = new Uint8Array(buffer);
6170 var progressInfo = {
6171 bytesLoaded: bytes.length,
6172 bytesTotal: bytes.length
6173 };
6174 pipe.push(bytes, progressInfo);
6175 pipe.close();
6176 };
6177 (function (global) {
6178 global['SWF']['parse'] = SWF.parse;
6179 global['SWF']['parseAsync'] = SWF.parseAsync;
6180 }(this));