ngx-spine
Version:
[](https://travis-ci.org/PoiScript/ngx-spine)
517 lines • 60.5 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions.
*
* Copyright (c) 2013-2019, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS
* INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
import { Utils } from "./Utils";
import { Triangulator } from "./Triangulator";
export class SkeletonClipping {
constructor() {
this.triangulator = new Triangulator();
this.clippingPolygon = new Array();
this.clipOutput = new Array();
this.clippedVertices = new Array();
this.clippedTriangles = new Array();
this.scratch = new Array();
}
/**
* @param {?} slot
* @param {?} clip
* @return {?}
*/
clipStart(slot, clip) {
if (this.clipAttachment != null)
return 0;
this.clipAttachment = clip;
/** @type {?} */
let n = clip.worldVerticesLength;
/** @type {?} */
let vertices = Utils.setArraySize(this.clippingPolygon, n);
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
/** @type {?} */
let clippingPolygon = this.clippingPolygon;
SkeletonClipping.makeClockwise(clippingPolygon);
/** @type {?} */
let clippingPolygons = (this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon)));
for (let i = 0, n = clippingPolygons.length; i < n; i++) {
/** @type {?} */
let polygon = clippingPolygons[i];
SkeletonClipping.makeClockwise(polygon);
polygon.push(polygon[0]);
polygon.push(polygon[1]);
}
return clippingPolygons.length;
}
/**
* @param {?} slot
* @return {?}
*/
clipEndWithSlot(slot) {
if (this.clipAttachment != null && this.clipAttachment.endSlot == slot.data)
this.clipEnd();
}
/**
* @return {?}
*/
clipEnd() {
if (this.clipAttachment == null)
return;
this.clipAttachment = null;
this.clippingPolygons = null;
this.clippedVertices.length = 0;
this.clippedTriangles.length = 0;
this.clippingPolygon.length = 0;
}
/**
* @return {?}
*/
isClipping() {
return this.clipAttachment != null;
}
/**
* @param {?} vertices
* @param {?} verticesLength
* @param {?} triangles
* @param {?} trianglesLength
* @param {?} uvs
* @param {?} light
* @param {?} dark
* @param {?} twoColor
* @return {?}
*/
clipTriangles(vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) {
/** @type {?} */
let clipOutput = this.clipOutput;
/** @type {?} */
let clippedVertices = this.clippedVertices;
/** @type {?} */
let clippedTriangles = this.clippedTriangles;
/** @type {?} */
let polygons = this.clippingPolygons;
/** @type {?} */
let polygonsCount = this.clippingPolygons.length;
/** @type {?} */
let vertexSize = twoColor ? 12 : 8;
/** @type {?} */
let index = 0;
clippedVertices.length = 0;
clippedTriangles.length = 0;
outer: for (let i = 0; i < trianglesLength; i += 3) {
/** @type {?} */
let vertexOffset = triangles[i] << 1;
/** @type {?} */
let x1 = vertices[vertexOffset];
/** @type {?} */
let y1 = vertices[vertexOffset + 1];
/** @type {?} */
let u1 = uvs[vertexOffset];
/** @type {?} */
let v1 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 1] << 1;
/** @type {?} */
let x2 = vertices[vertexOffset];
/** @type {?} */
let y2 = vertices[vertexOffset + 1];
/** @type {?} */
let u2 = uvs[vertexOffset];
/** @type {?} */
let v2 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 2] << 1;
/** @type {?} */
let x3 = vertices[vertexOffset];
/** @type {?} */
let y3 = vertices[vertexOffset + 1];
/** @type {?} */
let u3 = uvs[vertexOffset];
/** @type {?} */
let v3 = uvs[vertexOffset + 1];
for (let p = 0; p < polygonsCount; p++) {
/** @type {?} */
let s = clippedVertices.length;
if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
/** @type {?} */
let clipOutputLength = clipOutput.length;
if (clipOutputLength == 0)
continue;
/** @type {?} */
let d0 = y2 - y3;
/** @type {?} */
let d1 = x3 - x2;
/** @type {?} */
let d2 = x1 - x3;
/** @type {?} */
let d4 = y3 - y1;
/** @type {?} */
let d = 1 / (d0 * d2 + d1 * (y1 - y3));
/** @type {?} */
let clipOutputCount = clipOutputLength >> 1;
/** @type {?} */
let clipOutputItems = this.clipOutput;
/** @type {?} */
let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize);
for (let ii = 0; ii < clipOutputLength; ii += 2) {
/** @type {?} */
let x = clipOutputItems[ii];
/** @type {?} */
let y = clipOutputItems[ii + 1];
clippedVerticesItems[s] = x;
clippedVerticesItems[s + 1] = y;
clippedVerticesItems[s + 2] = light.r;
clippedVerticesItems[s + 3] = light.g;
clippedVerticesItems[s + 4] = light.b;
clippedVerticesItems[s + 5] = light.a;
/** @type {?} */
let c0 = x - x3;
/** @type {?} */
let c1 = y - y3;
/** @type {?} */
let a = (d0 * c0 + d1 * c1) * d;
/** @type {?} */
let b = (d4 * c0 + d2 * c1) * d;
/** @type {?} */
let c = 1 - a - b;
clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c;
clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c;
if (twoColor) {
clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 9] = dark.g;
clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = dark.a;
}
s += vertexSize;
}
s = clippedTriangles.length;
/** @type {?} */
let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));
clipOutputCount--;
for (let ii = 1; ii < clipOutputCount; ii++) {
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = index + ii;
clippedTrianglesItems[s + 2] = index + ii + 1;
s += 3;
}
index += clipOutputCount + 1;
}
else {
/** @type {?} */
let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * vertexSize);
clippedVerticesItems[s] = x1;
clippedVerticesItems[s + 1] = y1;
clippedVerticesItems[s + 2] = light.r;
clippedVerticesItems[s + 3] = light.g;
clippedVerticesItems[s + 4] = light.b;
clippedVerticesItems[s + 5] = light.a;
if (!twoColor) {
clippedVerticesItems[s + 6] = u1;
clippedVerticesItems[s + 7] = v1;
clippedVerticesItems[s + 8] = x2;
clippedVerticesItems[s + 9] = y2;
clippedVerticesItems[s + 10] = light.r;
clippedVerticesItems[s + 11] = light.g;
clippedVerticesItems[s + 12] = light.b;
clippedVerticesItems[s + 13] = light.a;
clippedVerticesItems[s + 14] = u2;
clippedVerticesItems[s + 15] = v2;
clippedVerticesItems[s + 16] = x3;
clippedVerticesItems[s + 17] = y3;
clippedVerticesItems[s + 18] = light.r;
clippedVerticesItems[s + 19] = light.g;
clippedVerticesItems[s + 20] = light.b;
clippedVerticesItems[s + 21] = light.a;
clippedVerticesItems[s + 22] = u3;
clippedVerticesItems[s + 23] = v3;
}
else {
clippedVerticesItems[s + 6] = u1;
clippedVerticesItems[s + 7] = v1;
clippedVerticesItems[s + 8] = dark.r;
clippedVerticesItems[s + 9] = dark.g;
clippedVerticesItems[s + 10] = dark.b;
clippedVerticesItems[s + 11] = dark.a;
clippedVerticesItems[s + 12] = x2;
clippedVerticesItems[s + 13] = y2;
clippedVerticesItems[s + 14] = light.r;
clippedVerticesItems[s + 15] = light.g;
clippedVerticesItems[s + 16] = light.b;
clippedVerticesItems[s + 17] = light.a;
clippedVerticesItems[s + 18] = u2;
clippedVerticesItems[s + 19] = v2;
clippedVerticesItems[s + 20] = dark.r;
clippedVerticesItems[s + 21] = dark.g;
clippedVerticesItems[s + 22] = dark.b;
clippedVerticesItems[s + 23] = dark.a;
clippedVerticesItems[s + 24] = x3;
clippedVerticesItems[s + 25] = y3;
clippedVerticesItems[s + 26] = light.r;
clippedVerticesItems[s + 27] = light.g;
clippedVerticesItems[s + 28] = light.b;
clippedVerticesItems[s + 29] = light.a;
clippedVerticesItems[s + 30] = u3;
clippedVerticesItems[s + 31] = v3;
clippedVerticesItems[s + 32] = dark.r;
clippedVerticesItems[s + 33] = dark.g;
clippedVerticesItems[s + 34] = dark.b;
clippedVerticesItems[s + 35] = dark.a;
}
s = clippedTriangles.length;
/** @type {?} */
let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3);
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = index + 1;
clippedTrianglesItems[s + 2] = index + 2;
index += 3;
continue outer;
}
}
}
}
/**
* Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping
* area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list.
* @param {?} x1
* @param {?} y1
* @param {?} x2
* @param {?} y2
* @param {?} x3
* @param {?} y3
* @param {?} clippingArea
* @param {?} output
* @return {?}
*/
clip(x1, y1, x2, y2, x3, y3, clippingArea, output) {
/** @type {?} */
let originalOutput = output;
/** @type {?} */
let clipped = false;
// Avoid copy at the end.
/** @type {?} */
let input = null;
if (clippingArea.length % 4 >= 2) {
input = output;
output = this.scratch;
}
else
input = this.scratch;
input.length = 0;
input.push(x1);
input.push(y1);
input.push(x2);
input.push(y2);
input.push(x3);
input.push(y3);
input.push(x1);
input.push(y1);
output.length = 0;
/** @type {?} */
let clippingVertices = clippingArea;
/** @type {?} */
let clippingVerticesLast = clippingArea.length - 4;
for (let i = 0;; i += 2) {
/** @type {?} */
let edgeX = clippingVertices[i];
/** @type {?} */
let edgeY = clippingVertices[i + 1];
/** @type {?} */
let edgeX2 = clippingVertices[i + 2];
/** @type {?} */
let edgeY2 = clippingVertices[i + 3];
/** @type {?} */
let deltaX = edgeX - edgeX2;
/** @type {?} */
let deltaY = edgeY - edgeY2;
/** @type {?} */
let inputVertices = input;
/** @type {?} */
let inputVerticesLength = input.length - 2;
/** @type {?} */
let outputStart = output.length;
for (let ii = 0; ii < inputVerticesLength; ii += 2) {
/** @type {?} */
let inputX = inputVertices[ii];
/** @type {?} */
let inputY = inputVertices[ii + 1];
/** @type {?} */
let inputX2 = inputVertices[ii + 2];
/** @type {?} */
let inputY2 = inputVertices[ii + 3];
/** @type {?} */
let side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) {
if (side2) {
// v1 inside, v2 inside
output.push(inputX2);
output.push(inputY2);
continue;
}
// v1 inside, v2 outside
/** @type {?} */
let c0 = inputY2 - inputY;
/** @type {?} */
let c2 = inputX2 - inputX;
/** @type {?} */
let s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY);
if (Math.abs(s) > 0.000001) {
/** @type {?} */
let ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s;
output.push(edgeX + (edgeX2 - edgeX) * ua);
output.push(edgeY + (edgeY2 - edgeY) * ua);
}
else {
output.push(edgeX);
output.push(edgeY);
}
}
else if (side2) {
// v1 outside, v2 inside
/** @type {?} */
let c0 = inputY2 - inputY;
/** @type {?} */
let c2 = inputX2 - inputX;
/** @type {?} */
let s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY);
if (Math.abs(s) > 0.000001) {
/** @type {?} */
let ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s;
output.push(edgeX + (edgeX2 - edgeX) * ua);
output.push(edgeY + (edgeY2 - edgeY) * ua);
}
else {
output.push(edgeX);
output.push(edgeY);
}
output.push(inputX2);
output.push(inputY2);
}
clipped = true;
}
if (outputStart == output.length) {
// All edges outside.
originalOutput.length = 0;
return true;
}
output.push(output[0]);
output.push(output[1]);
if (i == clippingVerticesLast)
break;
/** @type {?} */
let temp = output;
output = input;
output.length = 0;
input = temp;
}
if (originalOutput != output) {
originalOutput.length = 0;
for (let i = 0, n = output.length - 2; i < n; i++)
originalOutput[i] = output[i];
}
else
originalOutput.length = originalOutput.length - 2;
return clipped;
}
/**
* @param {?} polygon
* @return {?}
*/
static makeClockwise(polygon) {
/** @type {?} */
let vertices = polygon;
/** @type {?} */
let verticeslength = polygon.length;
/** @type {?} */
let area = vertices[verticeslength - 2] * vertices[1] -
vertices[0] * vertices[verticeslength - 1];
/** @type {?} */
let p1x = 0;
/** @type {?} */
let p1y = 0;
/** @type {?} */
let p2x = 0;
/** @type {?} */
let p2y = 0;
for (let i = 0, n = verticeslength - 3; i < n; i += 2) {
p1x = vertices[i];
p1y = vertices[i + 1];
p2x = vertices[i + 2];
p2y = vertices[i + 3];
area += p1x * p2y - p2x * p1y;
}
if (area < 0)
return;
for (let i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
/** @type {?} */
let x = vertices[i];
/** @type {?} */
let y = vertices[i + 1];
/** @type {?} */
let other = lastX - i;
vertices[i] = vertices[other];
vertices[i + 1] = vertices[other + 1];
vertices[other] = x;
vertices[other + 1] = y;
}
}
}
if (false) {
/**
* @type {?}
* @private
*/
SkeletonClipping.prototype.triangulator;
/**
* @type {?}
* @private
*/
SkeletonClipping.prototype.clippingPolygon;
/**
* @type {?}
* @private
*/
SkeletonClipping.prototype.clipOutput;
/** @type {?} */
SkeletonClipping.prototype.clippedVertices;
/** @type {?} */
SkeletonClipping.prototype.clippedTriangles;
/**
* @type {?}
* @private
*/
SkeletonClipping.prototype.scratch;
/**
* @type {?}
* @private
*/
SkeletonClipping.prototype.clipAttachment;
/**
* @type {?}
* @private
*/
SkeletonClipping.prototype.clippingPolygons;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2tlbGV0b25DbGlwcGluZy5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25neC1zcGluZS8iLCJzb3VyY2VzIjpbImxpYi9zcGluZS10cy9jb3JlL1NrZWxldG9uQ2xpcHBpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUE2QkEsT0FBTyxFQUFhLEtBQUssRUFBUyxNQUFNLFNBQVMsQ0FBQztBQUNsRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFJOUMsTUFBTSxPQUFPLGdCQUFnQjtJQUE3QjtRQUNVLGlCQUFZLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUNsQyxvQkFBZSxHQUFHLElBQUksS0FBSyxFQUFVLENBQUM7UUFDdEMsZUFBVSxHQUFHLElBQUksS0FBSyxFQUFVLENBQUM7UUFDekMsb0JBQWUsR0FBRyxJQUFJLEtBQUssRUFBVSxDQUFDO1FBQ3RDLHFCQUFnQixHQUFHLElBQUksS0FBSyxFQUFVLENBQUM7UUFDL0IsWUFBTyxHQUFHLElBQUksS0FBSyxFQUFVLENBQUM7SUFvWHhDLENBQUM7Ozs7OztJQS9XQyxTQUFTLENBQUMsSUFBVSxFQUFFLElBQXdCO1FBQzVDLElBQUksSUFBSSxDQUFDLGNBQWMsSUFBSSxJQUFJO1lBQUUsT0FBTyxDQUFDLENBQUM7UUFDMUMsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUM7O1lBRXZCLENBQUMsR0FBRyxJQUFJLENBQUMsbUJBQW1COztZQUM1QixRQUFRLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQzs7WUFDbEQsZUFBZSxHQUFHLElBQUksQ0FBQyxlQUFlO1FBQzFDLGdCQUFnQixDQUFDLGFB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QUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO3dCQUNqQyxvQkFBb0IsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQzt3QkFDckMsb0JBQW9CLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7d0JBQ3JDLG9CQUFvQixDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO3dCQUN0QyxvQkFBb0IsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQzt3QkFFdEMsb0JBQW9CLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQzt3QkFDbEMsb0JBQW9CLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQzt3QkFDbEMsb0JBQW9CLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7d0JBQ3ZDLG9CQUFvQixDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO3dCQUN2QyxvQkFBb0IsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQzt3QkFDdkMsb0JBQW9CLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7d0JBQ3ZDLG9CQUFvQixDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUM7d0JBQ2xDLG9CQUFvQixDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUM7d0JBQ2xDLG9CQUFvQixDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO3dCQUN0QyxvQkFBb0IsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQzt3QkFDdEMsb0JBQW9CLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7d0JBQ3RDLG9CQUFvQixDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO3dCQUV0QyxvQkFBb0IsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDO3dCQUNsQyxvQkFBb0IsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDO3dCQUNsQyxvQkFBb0IsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQzt3QkFDdkMsb0JBQW9CLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7d0JBQ3ZDLG9CQUFvQixDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO3dCQUN2QyxvQkFBb0IsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQzt3QkFDdkMsb0JBQW9CLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQzt3QkFDbEMsb0JBQW9CLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQzt3QkFDbEMsb0JBQW9CLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7d0JBQ3RDLG9CQUFvQixDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO3dCQUN0QyxvQkFBb0IsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQzt3QkFDdEMsb0JBQW9CLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7cUJBQ3ZDO29CQUVELENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUM7O3dCQUN4Qixx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O0lBQzlDLHNDQUF5Qzs7SUFDekMsMkNBQXNDOztJQUN0Qyw0Q0FBdUM7Ozs7O0lBQ3ZDLG1DQUFzQzs7Ozs7SUFFdEMsMENBQTJDOzs7OztJQUMzQyw0Q0FBK0MiLCJzb3VyY2VzQ29udGVudCI6WyIvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gKiBTcGluZSBSdW50aW1lcyBMaWNlbnNlIEFncmVlbWVudFxuICogTGFzdCB1cGRhdGVkIE1heSAxLCAyMDE5LiBSZXBsYWNlcyBhbGwgcHJpb3IgdmVyc2lvbnMuXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTksIEVzb3RlcmljIFNvZnR3YXJlIExMQ1xuICpcbiAqIEludGVncmF0aW9uIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlIG9yIG90aGVyd2lzZSBjcmVhdGluZ1xuICogZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgaXMgcGVybWl0dGVkIHVuZGVyIHRoZSB0ZXJtcyBhbmRcbiAqIGNvbmRpdGlvbnMgb2YgU2VjdGlvbiAyIG9mIHRoZSBTcGluZSBFZGl0b3IgTGljZW5zZSBBZ3JlZW1lbnQ6XG4gKiBodHRwOi8vZXNvdGVyaWNzb2Z0d2FyZS5jb20vc3BpbmUtZWRpdG9yLWxpY2Vuc2VcbiAqXG4gKiBPdGhlcndpc2UsIGl0IGlzIHBlcm1pdHRlZCB0byBpbnRlZ3JhdGUgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmVcbiAqIG9yIG90aGVyd2lzZSBjcmVhdGUgZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgKGNvbGxlY3RpdmVseSxcbiAqIFwiUHJvZHVjdHNcIiksIHByb3ZpZGVkIHRoYXQgZWFjaCB1c2VyIG9mIHRoZSBQcm9kdWN0cyBtdXN0IG9idGFpbiB0aGVpciBvd25cbiAqIFNwaW5lIEVkaXRvciBsaWNlbnNlIGFuZCByZWRpc3RyaWJ1dGlvbiBvZiB0aGUgUHJvZHVjdHMgaW4gYW55IGZvcm0gbXVzdFxuICogaW5jbHVkZSB0aGlzIGxpY2Vuc2UgYW5kIGNvcHlyaWdodCBub3RpY2UuXG4gKlxuICogVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBFU09URVJJQyBTT0ZUV0FSRSBMTEMgXCJBUyBJU1wiIEFORCBBTlkgRVhQUkVTU1xuICogT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRUQgV0FSUkFOVElFU1xuICogT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgRElTQ0xBSU1FRC4gSU5cbiAqIE5PIEVWRU5UIFNIQUxMIEVTT1RFUklDIFNPRlRXQVJFIExMQyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNULFxuICogSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORyxcbiAqIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUywgQlVTSU5FU1NcbiAqIElOVEVSUlVQVElPTiwgT1IgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFMpIEhPV0VWRVIgQ0FVU0VEIEFORCBPTiBBTllcbiAqIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQgKElOQ0xVRElOR1xuICogTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTIFNPRlRXQVJFLFxuICogRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cbiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuaW1wb3J0IHsgQXJyYXlMaWtlLCBVdGlscywgQ29sb3IgfSBmcm9tIFwiLi9VdGlsc1wiO1xuaW1wb3J0IHsgVHJpYW5ndWxhdG9yIH0gZnJvbSBcIi4vVHJpYW5ndWxhdG9yXCI7XG5pbXBvcnQgeyBDbGlwcGluZ0F0dGFjaG1lbnQgfSBmcm9tIFwiLi9hdHRhY2htZW50cy9DbGlwcGluZ0F0dGFjaG1lbnRcIjtcbmltcG9ydCB7IFNsb3QgfSBmcm9tIFwiLi9TbG90XCI7XG5cbmV4cG9ydCBjbGFzcyBTa2VsZXRvbkNsaXBwaW5nIHtcbiAgcHJpdmF0ZSB0cmlhbmd1bGF0b3IgPSBuZXcgVHJpYW5ndWxhdG9yKCk7XG4gIHByaXZhdGUgY2xpcHBpbmdQb2x5Z29uID0gbmV3IEFycmF5PG51bWJlcj4oKTtcbiAgcHJpdmF0ZSBjbGlwT3V0cHV0ID0gbmV3IEFycmF5PG51bWJlcj4oKTtcbiAgY2xpcHBlZFZlcnRpY2VzID0gbmV3IEFycmF5PG51bWJlcj4oKTtcbiAgY2xpcHBlZFRyaWFuZ2xlcyA9IG5ldyBBcnJheTxudW1iZXI+KCk7XG4gIHByaXZhdGUgc2NyYXRjaCA9IG5ldyBBcnJheTxudW1iZXI+KCk7XG5cbiAgcHJpdmF0ZSBjbGlwQXR0YWNobWVudDogQ2xpcHBpbmdBdHRhY2htZW50O1xuICBwcml2YXRlIGNsaXBwaW5nUG9seWdvbnM6IEFycmF5PEFycmF5PG51bWJlcj4+O1xuXG4gIGNsaXBTdGFydChzbG90OiBTbG90LCBjbGlwOiBDbGlwcGluZ0F0dGFjaG1lbnQpOiBudW1iZXIge1xuICAgIGlmICh0aGlzLmNsaXBBdHRhY2htZW50ICE9IG51bGwpIHJldHVybiAwO1xuICAgIHRoaXMuY2xpcEF0dGFjaG1lbnQgPSBjbGlwO1xuXG4gICAgbGV0IG4gPSBjbGlwLndvcmxkVmVydGljZXNMZW5ndGg7XG4gICAgbGV0IHZlcnRpY2VzID0gVXRpbHMuc2V0QXJyYXlTaXplKHRoaXMuY2xpcHBpbmdQb2x5Z29uLCBuKTtcbiAgICBjbGlwLmNvbXB1dGVXb3JsZFZlcnRpY2VzKHNsb3QsIDAsIG4sIHZlcnRpY2VzLCAwLCAyKTtcbiAgICBsZXQgY2xpcHBpbmdQb2x5Z29uID0gdGhpcy5jbGlwcGluZ1BvbHlnb247XG4gICAgU2tlbGV0b25DbGlwcGluZy5tYWtlQ2xvY2t3aXNlKGNsaXBwaW5nUG9seWdvbik7XG4gICAgbGV0IGNsaXBwaW5nUG9seWdvbnMgPSAodGhpcy5jbGlwcGluZ1BvbHlnb25zID0gdGhpcy50cmlhbmd1bGF0b3IuZGVjb21wb3NlKFxuICAgICAgY2xpcHBpbmdQb2x5Z29uLFxuICAgICAgdGhpcy50cmlhbmd1bGF0b3IudHJpYW5ndWxhdGUoY2xpcHBpbmdQb2x5Z29uKVxuICAgICkpO1xuICAgIGZvciAobGV0IGkgPSAwLCBuID0gY2xpcHBpbmdQb2x5Z29ucy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcbiAgICAgIGxldCBwb2x5Z29uID0gY2xpcHBpbmdQb2x5Z29uc1tpXTtcbiAgICAgIFNrZWxldG9uQ2xpcHBpbmcubWFrZUNsb2Nrd2lzZShwb2x5Z29uKTtcbiAgICAgIHBvbHlnb24ucHVzaChwb2x5Z29uWzBdKTtcbiAgICAgIHBvbHlnb24ucHVzaChwb2x5Z29uWzFdKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2xpcHBpbmdQb2x5Z29ucy5sZW5ndGg7XG4gIH1cblxuICBjbGlwRW5kV2l0aFNsb3Qoc2xvdDogU2xvdCkge1xuICAgIGlmICh0aGlzLmNsaXBBdHRhY2htZW50ICE9IG51bGwgJiYgdGhpcy5jbGlwQXR0YWNobWVudC5lbmRTbG90ID09IHNsb3QuZGF0YSlcbiAgICAgIHRoaXMuY2xpcEVuZCgpO1xuICB9XG5cbiAgY2xpcEVuZCgpIHtcbiAgICBpZiAodGhpcy5jbGlwQXR0YWNobWVudCA9PSBudWxsKSByZXR1cm47XG4gICAgdGhpcy5jbGlwQXR0YWNobWVudCA9IG51bGw7XG4gICAgdGhpcy5jbGlwcGluZ1BvbHlnb25zID0gbnVsbDtcbiAgICB0aGlzLmNsaXBwZWRWZXJ0aWNlcy5sZW5ndGggPSAwO1xuICAgIHRoaXMuY2xpcHBlZFRyaWFuZ2xlcy5sZW5ndGggPSAwO1xuICAgIHRoaXMuY2xpcHBpbmdQb2x5Z29uLmxlbmd0aCA9IDA7XG4gIH1cblxuICBpc0NsaXBwaW5nKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNsaXBBdHRhY2htZW50ICE9IG51bGw7XG4gIH1cblxuICBjbGlwVHJpYW5nbGVzKFxuICAgIHZlcnRpY2VzOiBBcnJheUxpa2U8bnVtYmVyPixcbiAgICB2ZXJ0aWNlc0xlbmd0aDogbnVtYmVyLFxuICAgIHRyaWFuZ2xlczogQXJyYXlMaWtlPG51bWJlcj4sXG4gICAgdHJpYW5nbGVzTGVuZ3RoOiBudW1iZXIsXG4gICAgdXZzOiBBcnJheUxpa2U8bnVtYmVyPixcbiAgICBsaWdodDogQ29sb3IsXG4gICAgZGFyazogQ29sb3IsXG4gICAgdHdvQ29sb3I6IGJvb2xlYW5cbiAgKSB7XG4gICAgbGV0IGNsaXBPdXRwdXQgPSB0aGlzLmNsaXBPdXRwdXQsXG4gICAgICBjbGlwcGVkVmVydGljZXMgPSB0aGlzLmNsaXBwZWRWZXJ0aWNlcztcbiAgICBsZXQgY2xpcHBlZFRyaWFuZ2xlcyA9IHRoaXMuY2xpcHBlZFRyaWFuZ2xlcztcbiAgICBsZXQgcG9seWdvbnMgPSB0aGlzLmNsaXBwaW5nUG9seWdvbnM7XG4gICAgbGV0IHBvbHlnb25zQ291bnQgPSB0aGlzLmNsaXBwaW5nUG9seWdvbnMubGVuZ3RoO1xuICAgIGxldCB2ZXJ0ZXhTaXplID0gdHdvQ29sb3IgPyAxMiA6IDg7XG5cbiAgICBsZXQgaW5kZXggPSAwO1xuICAgIGNsaXBwZWRWZXJ0aWNlcy5sZW5ndGggPSAwO1xuICAgIGNsaXBwZWRUcmlhbmdsZXMubGVuZ3RoID0gMDtcbiAgICBvdXRlcjogZm9yIChsZXQgaSA9IDA7IGkgPCB0cmlhbmdsZXNMZW5ndGg7IGkgKz0gMykge1xuICAgICAgbGV0IHZlcnRleE9mZnNldCA9IHRyaWFuZ2xlc1tpXSA8PCAxO1xuICAgICAgbGV0IHgxID0gdmVydGljZXNbdmVydGV4T2Zmc2V0XSxcbiAgICAgICAgeTEgPSB2ZXJ0aWNlc1t2ZXJ0ZXhPZmZzZXQgKyAxXTtcbiAgICAgIGxldCB1MSA9IHV2c1t2ZXJ0ZXhPZmZzZXRdLFxuICAgICAgICB2MSA9IHV2c1t2ZXJ0ZXhPZmZzZXQgKyAxXTtcblxuICAgICAgdmVydGV4T2Zmc2V0ID0gdHJpYW5nbGVzW2kgKyAxXSA8PCAxO1xuICAgICAgbGV0IHgyID0gdmVydGljZXNbdmVydGV4T2Zmc2V0XSxcbiAgICAgICAgeTIgPSB2ZXJ0aWNlc1t2ZXJ0ZXhPZmZzZXQgKyAxXTtcbiAgICAgIGxldCB1MiA9IHV2c1t2ZXJ0ZXhPZmZzZXRdLFxuICAgICAgICB2MiA9IHV2c1t2ZXJ0ZXhPZmZzZXQgKyAxXTtcblxuICAgICAgdmVydGV4T2Zmc2V0ID0gdHJpYW5nbGVzW2kgKyAyXSA8PCAxO1xuICAgICAgbGV0IHgzID0gdmVydGljZXNbdmVydGV4T2Zmc2V0XSxcbiAgICAgICAgeTMgPSB2ZXJ0aWNlc1t2ZXJ0ZXhPZmZzZXQgKyAxXTtcbiAgICAgIGxldCB1MyA9IHV2c1t2ZXJ0ZXhPZmZzZXRdLFxuICAgICAgICB2MyA9IHV2c1t2ZXJ0ZXhPZmZzZXQgKyAxXTtcblxuICAgICAgZm9yIChsZXQgcCA9IDA7IHAgPCBwb2x5Z29uc0NvdW50OyBwKyspIHtcbiAgICAgICAgbGV0IHMgPSBjbGlwcGVkVmVydGljZXMubGVuZ3RoO1xuICAgICAgICBpZiAodGhpcy5jbGlwKHgxLCB5MSwgeDIsIHkyLCB4MywgeTMsIHBvbHlnb25zW3BdLCBjbGlwT3V0cHV0KSkge1xuICAgICAgICAgIGxldCBjbGlwT3V0cHV0TGVuZ3RoID0gY2xpcE91dHB1dC5sZW5ndGg7XG4gICAgICAgICAgaWYgKGNsaXBPdXRwdXRMZW5ndGggPT0gMCkgY29udGludWU7XG4gICAgICAgICAgbGV0IGQwID0geTIgLSB5MyxcbiAgICAgICAgICAgIGQxID0geDMgLSB4MixcbiAgICAgICAgICAgIGQyID0geDEgLSB4MyxcbiAgICAgICAgICAgIGQ0ID0geTMgLSB5MTtcbiAgICAgICAgICBsZXQgZCA9IDEgLyAoZDAgKiBkMiArIGQxICogKHkxIC0geTMpKTtcblxuICAgICAgICAgIGxldCBjbGlwT3V0cHV0Q291bnQgPSBjbGlwT3V0cHV0TGVuZ3RoID4+IDE7XG4gICAgICAgICAgbGV0IGNsaXBPdXRwdXRJdGVtcyA9IHRoaXMuY2xpcE91dHB1dDtcbiAgICAgICAgICBsZXQgY2xpcHBlZFZlcnRpY2VzSXRlbXMgPSBVdGlscy5zZXRBcnJheVNpemUoXG4gICAgICAgICAgICBjbGlwcGVkVmVydGljZXMsXG4gICAgICAgICAgICBzICsgY2xpcE91dHB1dENvdW50ICogdmVydGV4U2l6ZVxuICAgICAgICAgICk7XG4gICAgICAgICAgZm9yIChsZXQgaWkgPSAwOyBpaSA8IGNsaXBPdXRwdXRMZW5ndGg7IGlpICs9IDIpIHtcbiAgICAgICAgICAgIGxldCB4ID0gY2xpcE91dHB1dEl0ZW1zW2lpXSxcbiAgICAgICAgICAgICAgeSA9IGNsaXBPdXRwdXRJdGVtc1tpaSArIDFdO1xuICAgICAgICAgICAgY2xpcHBlZFZlcnRpY2VzSXRlbXNbc10gPSB4O1xuICAgICAgICAgICAgY2xpcHBlZFZlcnRpY2VzSXRlbXNbcyArIDFdID0geTtcbiAgICAgICAgICAgIGNsaXBwZWRWZXJ0aWNlc0l0ZW1zW3MgKyAyXSA9IGxpZ2h0LnI7XG4gICAgICAgICAgICBjbGlwcGVkVmVydGljZXNJdGVtc1tzICsgM10gPSBsaWdodC5nO1xuICAgICAgICAgICAgY2xpcHBlZFZlcnRpY2VzSXRlbXNbcyArIDRdID0gbGlnaHQuYjtcbiAgICAgICAgICAgIGNsaXBwZWRWZXJ0aWNlc0l0ZW1zW3MgKyA1XSA9IGxpZ2h0LmE7XG4gICAgICAgICAgICBsZXQgYzAgPSB4IC0geDMsXG4gICAgICAgICAgICAgIGMxID0geSAtIHkzO1xuICAgICAgICAgICAgbGV0IGEgPSAoZDAgKiBjMCArIGQxICogYzEpICogZDtcbiAgICAgICAgICAgIGxldCBiID0gKGQ0ICogYzAgKyBkMiAqIGMxKSAqIGQ7XG4gICAgICAgICAgICBsZXQgYyA9IDEgLSBhIC0gYjtcbiAgICAgICAgICAgIGNsaXBwZWRWZXJ0aWNlc0l0ZW1zW3MgKyA2XSA9IHUxICogYSArIHUyICogYiArIHUzICogYztcbiAgICAgICAgICAgIGNsaXBwZWRWZXJ0aWNlc0l0ZW1zW3MgKyA3XSA9IHYxICogYSArIHYyICogYiArIHYzICogYztcbiAgICAgICAgICAgIGlmICh0d29Db2xvcikge1xuICAgICAgICAgICAgICBjbGlwcGVkVmVydGljZXNJdGVtc1tzICsgOF0gPSBkYXJrLnI7XG4gICAgICAgICAgICAgIGNsaXBwZWRWZXJ0aWNlc0l0ZW1zW3MgKyA5XSA9IGRhcmsuZztcbiAgICAgICAgICAgICAgY2xpcHBlZFZlcnRpY2VzSXRlbXNbcyArIDEwXSA9IGRhcmsuYjtcbiAgICAgICAgICAgICAgY2xpcHBlZFZlcnRpY2VzSXRlbXNbcyArIDExXSA9IGRhcmsuYTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHMgKz0gdmVydGV4U2l6ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzID0gY2xpcHBlZFRyaWFuZ2xlcy5sZW5ndGg7XG4gICAgICAgICAgbGV0IGNsaXBwZWRUcmlhbmdsZXNJdGVtcyA9IFV0aWxzLnNldEFycmF5U2l6ZShcbiAgICAgICAgICAgIGNsaXBwZWRUcmlhbmdsZXMsXG4gICAgICAgICAgICBzICsgMyAqIChjbGlwT3V0cHV0Q291bnQgLSAyKVxuICAgICAgICAgICk7XG4gICAgICAgICAgY2xpcE91dHB1dENvdW50LS07XG4gICAgICAgICAgZm9yIChsZXQgaWkgPSAxOyBpaSA8IGNsaXBPdXRwdXRDb3VudDsgaWkrKykge1xuICAgICAgICAgICAgY2xpcHBlZFRyaWFuZ2xlc0l0ZW1zW3NdID0gaW5kZXg7XG4gICAgICAgICAgICBjbGlwcGVkVHJpYW5nbGVzSXRlbXNbcyArIDFdID0gaW5kZXggKyBpaTtcbiAgICAgICAgICAgIGNsaXBwZWRUcmlhbmdsZXNJdGVtc1tzICsgMl0gPSBpbmRleCArIGlpICsgMTtcbiAgICAgICAgICAgIHMgKz0gMztcbiAgICAgICAgICB9XG4gICAgICAgICAgaW5kZXggKz0gY2xpcE91dHB1dENvdW50ICsgMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsZXQgY2xpcHBlZFZlcnRpY2VzSXRlbXMgPSBVdGlscy5zZXRBcnJheVNpemUoXG4gICAgICAgICAgICBjbGlwcGVkVmVydGljZXM