ngx-spine
Version:
[](https://travis-ci.org/PoiScript/ngx-spine)
443 lines • 39 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 { Pool, Utils } from "./Utils";
import { BoundingBoxAttachment } from "./attachments/BoundingBoxAttachment";
var SkeletonBounds = /** @class */ (function () {
function SkeletonBounds() {
this.minX = 0;
this.minY = 0;
this.maxX = 0;
this.maxY = 0;
this.boundingBoxes = new Array();
this.polygons = new Array();
this.polygonPool = new Pool((/**
* @return {?}
*/
function () {
return Utils.newFloatArray(16);
}));
}
/**
* @param {?} skeleton
* @param {?} updateAabb
* @return {?}
*/
SkeletonBounds.prototype.update = /**
* @param {?} skeleton
* @param {?} updateAabb
* @return {?}
*/
function (skeleton, updateAabb) {
if (skeleton == null)
throw new Error("skeleton cannot be null.");
/** @type {?} */
var boundingBoxes = this.boundingBoxes;
/** @type {?} */
var polygons = this.polygons;
/** @type {?} */
var polygonPool = this.polygonPool;
/** @type {?} */
var slots = skeleton.slots;
/** @type {?} */
var slotCount = slots.length;
boundingBoxes.length = 0;
polygonPool.freeAll(polygons);
polygons.length = 0;
for (var i = 0; i < slotCount; i++) {
/** @type {?} */
var slot = slots[i];
if (!slot.bone.active)
continue;
/** @type {?} */
var attachment = slot.getAttachment();
if (attachment instanceof BoundingBoxAttachment) {
/** @type {?} */
var boundingBox = (/** @type {?} */ (attachment));
boundingBoxes.push(boundingBox);
/** @type {?} */
var polygon = polygonPool.obtain();
if (polygon.length != boundingBox.worldVerticesLength) {
polygon = Utils.newFloatArray(boundingBox.worldVerticesLength);
}
polygons.push(polygon);
boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2);
}
}
if (updateAabb) {
this.aabbCompute();
}
else {
this.minX = Number.POSITIVE_INFINITY;
this.minY = Number.POSITIVE_INFINITY;
this.maxX = Number.NEGATIVE_INFINITY;
this.maxY = Number.NEGATIVE_INFINITY;
}
};
/**
* @return {?}
*/
SkeletonBounds.prototype.aabbCompute = /**
* @return {?}
*/
function () {
/** @type {?} */
var minX = Number.POSITIVE_INFINITY;
/** @type {?} */
var minY = Number.POSITIVE_INFINITY;
/** @type {?} */
var maxX = Number.NEGATIVE_INFINITY;
/** @type {?} */
var maxY = Number.NEGATIVE_INFINITY;
/** @type {?} */
var polygons = this.polygons;
for (var i = 0, n = polygons.length; i < n; i++) {
/** @type {?} */
var polygon = polygons[i];
/** @type {?} */
var vertices = polygon;
for (var ii = 0, nn = polygon.length; ii < nn; ii += 2) {
/** @type {?} */
var x = vertices[ii];
/** @type {?} */
var y = vertices[ii + 1];
minX = Math.min(minX, x);
minY = Math.min(minY, y);
maxX = Math.max(maxX, x);
maxY = Math.max(maxY, y);
}
}
this.minX = minX;
this.minY = minY;
this.maxX = maxX;
this.maxY = maxY;
};
/** Returns true if the axis aligned bounding box contains the point. */
/**
* Returns true if the axis aligned bounding box contains the point.
* @param {?} x
* @param {?} y
* @return {?}
*/
SkeletonBounds.prototype.aabbContainsPoint = /**
* Returns true if the axis aligned bounding box contains the point.
* @param {?} x
* @param {?} y
* @return {?}
*/
function (x, y) {
return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY;
};
/** Returns true if the axis aligned bounding box intersects the line segment. */
/**
* Returns true if the axis aligned bounding box intersects the line segment.
* @param {?} x1
* @param {?} y1
* @param {?} x2
* @param {?} y2
* @return {?}
*/
SkeletonBounds.prototype.aabbIntersectsSegment = /**
* Returns true if the axis aligned bounding box intersects the line segment.
* @param {?} x1
* @param {?} y1
* @param {?} x2
* @param {?} y2
* @return {?}
*/
function (x1, y1, x2, y2) {
/** @type {?} */
var minX = this.minX;
/** @type {?} */
var minY = this.minY;
/** @type {?} */
var maxX = this.maxX;
/** @type {?} */
var maxY = this.maxY;
if ((x1 <= minX && x2 <= minX) ||
(y1 <= minY && y2 <= minY) ||
(x1 >= maxX && x2 >= maxX) ||
(y1 >= maxY && y2 >= maxY))
return false;
/** @type {?} */
var m = (y2 - y1) / (x2 - x1);
/** @type {?} */
var y = m * (minX - x1) + y1;
if (y > minY && y < maxY)
return true;
y = m * (maxX - x1) + y1;
if (y > minY && y < maxY)
return true;
/** @type {?} */
var x = (minY - y1) / m + x1;
if (x > minX && x < maxX)
return true;
x = (maxY - y1) / m + x1;
if (x > minX && x < maxX)
return true;
return false;
};
/** Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. */
/**
* Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds.
* @param {?} bounds
* @return {?}
*/
SkeletonBounds.prototype.aabbIntersectsSkeleton = /**
* Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds.
* @param {?} bounds
* @return {?}
*/
function (bounds) {
return (this.minX < bounds.maxX &&
this.maxX > bounds.minX &&
this.minY < bounds.maxY &&
this.maxY > bounds.minY);
};
/** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more
* efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */
/**
* Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more
* efficient to only call this method if {\@link #aabbContainsPoint(float, float)} returns true.
* @param {?} x
* @param {?} y
* @return {?}
*/
SkeletonBounds.prototype.containsPoint = /**
* Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more
* efficient to only call this method if {\@link #aabbContainsPoint(float, float)} returns true.
* @param {?} x
* @param {?} y
* @return {?}
*/
function (x, y) {
/** @type {?} */
var polygons = this.polygons;
for (var i = 0, n = polygons.length; i < n; i++)
if (this.containsPointPolygon(polygons[i], x, y))
return this.boundingBoxes[i];
return null;
};
/** Returns true if the polygon contains the point. */
/**
* Returns true if the polygon contains the point.
* @param {?} polygon
* @param {?} x
* @param {?} y
* @return {?}
*/
SkeletonBounds.prototype.containsPointPolygon = /**
* Returns true if the polygon contains the point.
* @param {?} polygon
* @param {?} x
* @param {?} y
* @return {?}
*/
function (polygon, x, y) {
/** @type {?} */
var vertices = polygon;
/** @type {?} */
var nn = polygon.length;
/** @type {?} */
var prevIndex = nn - 2;
/** @type {?} */
var inside = false;
for (var ii = 0; ii < nn; ii += 2) {
/** @type {?} */
var vertexY = vertices[ii + 1];
/** @type {?} */
var prevY = vertices[prevIndex + 1];
if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) {
/** @type {?} */
var vertexX = vertices[ii];
if (vertexX +
((y - vertexY) / (prevY - vertexY)) *
(vertices[prevIndex] - vertexX) <
x)
inside = !inside;
}
prevIndex = ii;
}
return inside;
};
/** Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it
* is usually more efficient to only call this method if {@link #aabbIntersectsSegment(float, float, float, float)} returns
* true. */
/**
* Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it
* is usually more efficient to only call this method if {\@link #aabbIntersectsSegment(float, float, float, float)} returns
* true.
* @param {?} x1
* @param {?} y1
* @param {?} x2
* @param {?} y2
* @return {?}
*/
SkeletonBounds.prototype.intersectsSegment = /**
* Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it
* is usually more efficient to only call this method if {\@link #aabbIntersectsSegment(float, float, float, float)} returns
* true.
* @param {?} x1
* @param {?} y1
* @param {?} x2
* @param {?} y2
* @return {?}
*/
function (x1, y1, x2, y2) {
/** @type {?} */
var polygons = this.polygons;
for (var i = 0, n = polygons.length; i < n; i++)
if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2))
return this.boundingBoxes[i];
return null;
};
/** Returns true if the polygon contains any part of the line segment. */
/**
* Returns true if the polygon contains any part of the line segment.
* @param {?} polygon
* @param {?} x1
* @param {?} y1
* @param {?} x2
* @param {?} y2
* @return {?}
*/
SkeletonBounds.prototype.intersectsSegmentPolygon = /**
* Returns true if the polygon contains any part of the line segment.
* @param {?} polygon
* @param {?} x1
* @param {?} y1
* @param {?} x2
* @param {?} y2
* @return {?}
*/
function (polygon, x1, y1, x2, y2) {
/** @type {?} */
var vertices = polygon;
/** @type {?} */
var nn = polygon.length;
/** @type {?} */
var width12 = x1 - x2;
/** @type {?} */
var height12 = y1 - y2;
/** @type {?} */
var det1 = x1 * y2 - y1 * x2;
/** @type {?} */
var x3 = vertices[nn - 2];
/** @type {?} */
var y3 = vertices[nn - 1];
for (var ii = 0; ii < nn; ii += 2) {
/** @type {?} */
var x4 = vertices[ii];
/** @type {?} */
var y4 = vertices[ii + 1];
/** @type {?} */
var det2 = x3 * y4 - y3 * x4;
/** @type {?} */
var width34 = x3 - x4;
/** @type {?} */
var height34 = y3 - y4;
/** @type {?} */
var det3 = width12 * height34 - height12 * width34;
/** @type {?} */
var x = (det1 * width34 - width12 * det2) / det3;
if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) &&
((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) {
/** @type {?} */
var y = (det1 * height34 - height12 * det2) / det3;
if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) &&
((y >= y1 && y <= y2) || (y >= y2 && y <= y1)))
return true;
}
x3 = x4;
y3 = y4;
}
return false;
};
/** Returns the polygon for the specified bounding box, or null. */
/**
* Returns the polygon for the specified bounding box, or null.
* @param {?} boundingBox
* @return {?}
*/
SkeletonBounds.prototype.getPolygon = /**
* Returns the polygon for the specified bounding box, or null.
* @param {?} boundingBox
* @return {?}
*/
function (boundingBox) {
if (boundingBox == null)
throw new Error("boundingBox cannot be null.");
/** @type {?} */
var index = this.boundingBoxes.indexOf(boundingBox);
return index == -1 ? null : this.polygons[index];
};
/**
* @return {?}
*/
SkeletonBounds.prototype.getWidth = /**
* @return {?}
*/
function () {
return this.maxX - this.minX;
};
/**
* @return {?}
*/
SkeletonBounds.prototype.getHeight = /**
* @return {?}
*/
function () {
return this.maxY - this.minY;
};
return SkeletonBounds;
}());
export { SkeletonBounds };
if (false) {
/** @type {?} */
SkeletonBounds.prototype.minX;
/** @type {?} */
SkeletonBounds.prototype.minY;
/** @type {?} */
SkeletonBounds.prototype.maxX;
/** @type {?} */
SkeletonBounds.prototype.maxY;
/** @type {?} */
SkeletonBounds.prototype.boundingBoxes;
/** @type {?} */
SkeletonBounds.prototype.polygons;
/**
* @type {?}
* @private
*/
SkeletonBounds.prototype.polygonPool;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2tlbGV0b25Cb3VuZHMuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtc3BpbmUvIiwic291cmNlcyI6WyJsaWIvc3BpbmUtdHMvY29yZS9Ta2VsZXRvbkJvdW5kcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTZCQSxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUN0QyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUc1RTtJQUFBO1FBQ0UsU0FBSSxHQUFHLENBQUMsQ0FBQztRQUNULFNBQUksR0FBRyxDQUFDLENBQUM7UUFDVCxTQUFJLEdBQUcsQ0FBQyxDQUFDO1FBQ1QsU0FBSSxHQUFHLENBQUMsQ0FBQztRQUNULGtCQUFhLEdBQUcsSUFBSSxLQUFLLEVBQXlCLENBQUM7UUFDbkQsYUFBUSxHQUFHLElBQUksS0FBSyxFQUFxQixDQUFDO1FBQ2xDLGdCQUFXLEdBQUcsSUFBSSxJQUFJOzs7UUFBb0I7WUFDaEQsT0FBTyxLQUFLLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ2pDLENBQUMsRUFBQyxDQUFDO0lBbU1MLENBQUM7Ozs7OztJQWxNQywrQkFBTTs7Ozs7SUFBTixVQUFPLFFBQWtCLEVBQUUsVUFBbUI7UUFDNUMsSUFBSSxRQUFRLElBQUksSUFBSTtZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsMEJBQTBCLENBQUMsQ0FBQzs7WUFDOUQsYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhOztZQUNsQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVE7O1lBQ3hCLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVzs7WUFDOUIsS0FBSyxHQUFHLFFBQVEsQ0FBQyxLQUFLOztZQUN0QixTQUFTLEdBQUcsS0FBSyxDQUFDLE1BQU07UUFDNUIsYUFBYSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDekIsV0FBVyxDQUFDLE9B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QUFDO1NBQ1Q7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRCxtRUFBbUU7Ozs7OztJQUNuRSxtQ0FBVTs7Ozs7SUFBVixVQUFXLFdBQWtDO1FBQzNDLElBQUksV0FBVyxJQUFJLElBQUk7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLDZCQUE2QixDQUFDLENBQUM7O1lBQ3BFLEtBQUssR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUM7UUFDbkQsT0FBTyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNuRCxDQUFDOzs7O0lBQ0QsaUNBQVE7OztJQUFSO1FBQ0UsT0FBTyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDL0IsQ0FBQzs7OztJQUNELGtDQUFTOzs7SUFBVDtRQUNFLE9BQU8sSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO0lBQy9CLENBQUM7SUFDSCxxQkFBQztBQUFELENBQUMsQUE1TUQsSUE0TUM7Ozs7SUEzTUMsOEJBQVM7O0lBQ1QsOEJBQVM7O0lBQ1QsOEJBQVM7O0lBQ1QsOEJBQVM7O0lBQ1QsdUNBQW1EOztJQUNuRCxrQ0FBMEM7Ozs7O0lBQzFDLHFDQUVHIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gKiBTcGluZSBSdW50aW1lcyBMaWNlbnNlIEFncmVlbWVudFxyXG4gKiBMYXN0IHVwZGF0ZWQgTWF5IDEsIDIwMTkuIFJlcGxhY2VzIGFsbCBwcmlvciB2ZXJzaW9ucy5cclxuICpcclxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMTksIEVzb3RlcmljIFNvZnR3YXJlIExMQ1xyXG4gKlxyXG4gKiBJbnRlZ3JhdGlvbiBvZiB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZSBvciBvdGhlcndpc2UgY3JlYXRpbmdcclxuICogZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgaXMgcGVybWl0dGVkIHVuZGVyIHRoZSB0ZXJtcyBhbmRcclxuICogY29uZGl0aW9ucyBvZiBTZWN0aW9uIDIgb2YgdGhlIFNwaW5lIEVkaXRvciBMaWNlbnNlIEFncmVlbWVudDpcclxuICogaHR0cDovL2Vzb3Rlcmljc29mdHdhcmUuY29tL3NwaW5lLWVkaXRvci1saWNlbnNlXHJcbiAqXHJcbiAqIE90aGVyd2lzZSwgaXQgaXMgcGVybWl0dGVkIHRvIGludGVncmF0ZSB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZVxyXG4gKiBvciBvdGhlcndpc2UgY3JlYXRlIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIChjb2xsZWN0aXZlbHksXHJcbiAqIFwiUHJvZHVjdHNcIiksIHByb3ZpZGVkIHRoYXQgZWFjaCB1c2VyIG9mIHRoZSBQcm9kdWN0cyBtdXN0IG9idGFpbiB0aGVpciBvd25cclxuICogU3BpbmUgRWRpdG9yIGxpY2Vuc2UgYW5kIHJlZGlzdHJpYnV0aW9uIG9mIHRoZSBQcm9kdWN0cyBpbiBhbnkgZm9ybSBtdXN0XHJcbiAqIGluY2x1ZGUgdGhpcyBsaWNlbnNlIGFuZCBjb3B5cmlnaHQgbm90aWNlLlxyXG4gKlxyXG4gKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIEVTT1RFUklDIFNPRlRXQVJFIExMQyBcIkFTIElTXCIgQU5EIEFOWSBFWFBSRVNTXHJcbiAqIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVNcclxuICogT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgRElTQ0xBSU1FRC4gSU5cclxuICogTk8gRVZFTlQgU0hBTEwgRVNPVEVSSUMgU09GVFdBUkUgTExDIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsXHJcbiAqIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNMVURJTkcsXHJcbiAqIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUywgQlVTSU5FU1NcclxuICogSU5URVJSVVBUSU9OLCBPUiBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUykgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWVxyXG4gKiBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkdcclxuICogTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTIFNPRlRXQVJFLFxyXG4gKiBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxyXG4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXHJcblxyXG5pbXBvcnQgeyBQb29sLCBVdGlscyB9IGZyb20gXCIuL1V0aWxzXCI7XHJcbmltcG9ydCB7IEJvdW5kaW5nQm94QXR0YWNobWVudCB9IGZyb20gXCIuL2F0dGFjaG1lbnRzL0JvdW5kaW5nQm94QXR0YWNobWVudFwiO1xyXG5pbXBvcnQgeyBTa2VsZXRvbiB9IGZyb20gXCIuL1NrZWxldG9uXCI7XHJcblxyXG5leHBvcnQgY2xhc3MgU2tlbGV0b25Cb3VuZHMge1xyXG4gIG1pblggPSAwO1xyXG4gIG1pblkgPSAwO1xyXG4gIG1heFggPSAwO1xyXG4gIG1heFkgPSAwO1xyXG4gIGJvdW5kaW5nQm94ZXMgPSBuZXcgQXJyYXk8Qm91bmRpbmdCb3hBdHRhY2htZW50PigpO1xyXG4gIHBvbHlnb25zID0gbmV3IEFycmF5PEFycmF5TGlrZTxudW1iZXI+PigpO1xyXG4gIHByaXZhdGUgcG9seWdvblBvb2wgPSBuZXcgUG9vbDxBcnJheUxpa2U8bnVtYmVyPj4oKCkgPT4ge1xyXG4gICAgcmV0dXJuIFV0aWxzLm5ld0Zsb2F0QXJyYXkoMTYpO1xyXG4gIH0pO1xyXG4gIHVwZGF0ZShza2VsZXRvbjogU2tlbGV0b24sIHVwZGF0ZUFhYmI6IGJvb2xlYW4pIHtcclxuICAgIGlmIChza2VsZXRvbiA9PSBudWxsKSB0aHJvdyBuZXcgRXJyb3IoXCJza2VsZXRvbiBjYW5ub3QgYmUgbnVsbC5cIik7XHJcbiAgICBsZXQgYm91bmRpbmdCb3hlcyA9IHRoaXMuYm91bmRpbmdCb3hlcztcclxuICAgIGxldCBwb2x5Z29ucyA9IHRoaXMucG9seWdvbnM7XHJcbiAgICBsZXQgcG9seWdvblBvb2wgPSB0aGlzLnBvbHlnb25Qb29sO1xyXG4gICAgbGV0IHNsb3RzID0gc2tlbGV0b24uc2xvdHM7XHJcbiAgICBsZXQgc2xvdENvdW50ID0gc2xvdHMubGVuZ3RoO1xyXG4gICAgYm91bmRpbmdCb3hlcy5sZW5ndGggPSAwO1xyXG4gICAgcG9seWdvblBvb2wuZnJlZUFsbChwb2x5Z29ucyk7XHJcbiAgICBwb2x5Z29ucy5sZW5ndGggPSAwO1xyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbG90Q291bnQ7IGkrKykge1xyXG4gICAgICBsZXQgc2xvdCA9IHNsb3RzW2ldO1xyXG4gICAgICBpZiAoIXNsb3QuYm9uZS5hY3RpdmUpIGNvbnRpbnVlO1xyXG4gICAgICBsZXQgYXR0YWNobWVudCA9IHNsb3QuZ2V0QXR0YWNobWVudCgpO1xyXG4gICAgICBpZiAoYXR0YWNobWVudCBpbnN0YW5jZW9mIEJvdW5kaW5nQm94QXR0YWNobWVudCkge1xyXG4gICAgICAgIGxldCBib3VuZGluZ0JveCA9IGF0dGFjaG1lbnQgYXMgQm91bmRpbmdCb3hBdHRhY2htZW50O1xyXG4gICAgICAgIGJvdW5kaW5nQm94ZXMucHVzaChib3VuZGluZ0JveCk7XHJcbiAgICAgICAgbGV0IHBvbHlnb24gPSBwb2x5Z29uUG9vbC5vYnRhaW4oKTtcclxuICAgICAgICBpZiAocG9seWdvbi5sZW5ndGggIT0gYm91bmRpbmdCb3gud29ybGRWZXJ0aWNlc0xlbmd0aCkge1xyXG4gICAgICAgICAgcG9seWdvbiA9IFV0aWxzLm5ld0Zsb2F0QXJyYXkoYm91bmRpbmdCb3gud29ybGRWZXJ0aWNlc0xlbmd0aCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHBvbHlnb25zLnB1c2gocG9seWdvbik7XHJcbiAgICAgICAgYm91bmRpbmdCb3guY29tcHV0ZVdvcmxkVmVydGljZXMoXHJcbiAgICAgICAgICBzbG90LFxyXG4gICAgICAgICAgMCxcclxuICAgICAgICAgIGJvdW5kaW5nQm94LndvcmxkVmVydGljZXNMZW5ndGgsXHJcbiAgICAgICAgICBwb2x5Z29uLFxyXG4gICAgICAgICAgMCxcclxuICAgICAgICAgIDJcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAodXBkYXRlQWFiYikge1xyXG4gICAgICB0aGlzLmFhYmJDb21wdXRlKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLm1pblggPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XHJcbiAgICAgIHRoaXMubWluWSA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcclxuICAgICAgdGhpcy5tYXhYID0gTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZO1xyXG4gICAgICB0aGlzLm1heFkgPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7XHJcbiAgICB9XHJcbiAgfVxyXG4gIGFhYmJDb21wdXRlKCkge1xyXG4gICAgbGV0IG1pblggPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksXHJcbiAgICAgIG1pblkgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksXHJcbiAgICAgIG1heFggPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFksXHJcbiAgICAgIG1heFkgPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7XHJcbiAgICBsZXQgcG9seWdvbnMgPSB0aGlzLnBvbHlnb25zO1xyXG4gICAgZm9yIChsZXQgaSA9IDAsIG4gPSBwb2x5Z29ucy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgbGV0IHBvbHlnb24gPSBwb2x5Z29uc1tpXTtcclxuICAgICAgbGV0IHZlcnRpY2VzID0gcG9seWdvbjtcclxuICAgICAgZm9yIChsZXQgaWkgPSAwLCBubiA9IHBvbHlnb24ubGVuZ3RoOyBpaSA8IG5uOyBpaSArPSAyKSB7XHJcbiAgICAgICAgbGV0IHggPSB2ZXJ0aWNlc1tpaV07XHJcbiAgICAgICAgbGV0IHkgPSB2ZXJ0aWNlc1tpaSArIDFdO1xyXG4gICAgICAgIG1pblggPSBNYXRoLm1pbihtaW5YLCB4KTtcclxuICAgICAgICBtaW5ZID0gTWF0aC5taW4obWluWSwgeSk7XHJcbiAgICAgICAgbWF4WCA9IE1hdGgubWF4KG1heFgsIHgpO1xyXG4gICAgICAgIG1heFkgPSBNYXRoLm1heChtYXhZLCB5KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgdGhpcy5taW5YID0gbWluWDtcclxuICAgIHRoaXMubWluWSA9IG1pblk7XHJcbiAgICB0aGlzLm1heFggPSBtYXhYO1xyXG4gICAgdGhpcy5tYXhZID0gbWF4WTtcclxuICB9XHJcbiAgLyoqIFJldHVybnMgdHJ1ZSBpZiB0aGUgYXhpcyBhbGlnbmVkIGJvdW5kaW5nIGJveCBjb250YWlucyB0aGUgcG9pbnQuICovXHJcbiAgYWFiYkNvbnRhaW5zUG9pbnQoeDogbnVtYmVyLCB5OiBudW1iZXIpIHtcclxuICAgIHJldHVybiB4ID49IHRoaXMubWluWCAmJiB4IDw9IHRoaXMubWF4WCAmJiB5ID49IHRoaXMubWluWSAmJiB5IDw9IHRoaXMubWF4WTtcclxuICB9XHJcbiAgLyoqIFJldHVybnMgdHJ1ZSBpZiB0aGUgYXhpcyBhbGlnbmVkIGJvdW5kaW5nIGJveCBpbnRlcnNlY3RzIHRoZSBsaW5lIHNlZ21lbnQuICovXHJcbiAgYWFiYkludGVyc2VjdHNTZWdtZW50KHgxOiBudW1iZXIsIHkxOiBudW1iZXIsIHgyOiBudW1iZXIsIHkyOiBudW1iZXIpIHtcclxuICAgIGxldCBtaW5YID0gdGhpcy5taW5YO1xyXG4gICAgbGV0IG1pblkgPSB0aGlzLm1pblk7XHJcbiAgICBsZXQgbWF4WCA9IHRoaXMubWF4WDtcclxuICAgIGxldCBtYXhZID0gdGhpcy5tYXhZO1xyXG4gICAgaWYgKFxyXG4gICAgICAoeDEgPD0gbWluWCAmJiB4MiA8PSBtaW5YKSB8fFxyXG4gICAgICAoeTEgPD0gbWluWSAmJiB5MiA8PSBtaW5ZKSB8fFxyXG4gICAgICAoeDEgPj0gbWF4WCAmJiB4MiA+PSBtYXhYKSB8fFxyXG4gICAgICAoeTEgPj0gbWF4WSAmJiB5MiA+PSBtYXhZKVxyXG4gICAgKVxyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICBsZXQgbSA9ICh5MiAtIHkxKSAvICh4MiAtIHgxKTtcclxuICAgIGxldCB5ID0gbSAqIChtaW5YIC0geDEpICsgeTE7XHJcbiAgICBpZiAoeSA+IG1pblkgJiYgeSA8IG1heFkpIHJldHVybiB0cnVlO1xyXG4gICAgeSA9IG0gKiAobWF4WCAtIHgxKSArIHkxO1xyXG4gICAgaWYgKHkgPiBtaW5ZICYmIHkgPCBtYXhZKSByZXR1cm4gdHJ1ZTtcclxuICAgIGxldCB4ID0gKG1pblkgLSB5MSkgLyBtICsgeDE7XHJcbiAgICBpZiAoeCA+IG1pblggJiYgeCA8IG1heFgpIHJldHVybiB0cnVlO1xyXG4gICAgeCA9IChtYXhZIC0geTEpIC8gbSArIHgxO1xyXG4gICAgaWYgKHggPiBtaW5YICYmIHggPCBtYXhYKSByZXR1cm4gdHJ1ZTtcclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcbiAgLyoqIFJldHVybnMgdHJ1ZSBpZiB0aGUgYXhpcyBhbGlnbmVkIGJvdW5kaW5nIGJveCBpbnRlcnNlY3RzIHRoZSBheGlzIGFsaWduZWQgYm91bmRpbmcgYm94IG9mIHRoZSBzcGVjaWZpZWQgYm91bmRzLiAqL1xyXG4gIGFhYmJJbnRlcnNlY3RzU2tlbGV0b24oYm91bmRzOiBTa2VsZXRvbkJvdW5kcykge1xyXG4gICAgcmV0dXJuIChcclxuICAgICAgdGhpcy5taW5YIDwgYm91bmRzLm1heFggJiZcclxuICAgICAgdGhpcy5tYXhYID4gYm91bmRzLm1pblggJiZcclxuICAgICAgdGhpcy5taW5ZIDwgYm91bmRzLm1heFkgJiZcclxuICAgICAgdGhpcy5tYXhZID4gYm91bmRzLm1pbllcclxuICAgICk7XHJcbiAgfVxyXG4gIC8qKiBSZXR1cm5zIHRoZSBmaXJzdCBib3VuZGluZyBib3ggYXR0YWNobWVudCB0aGF0IGNvbnRhaW5zIHRoZSBwb2ludCwgb3IgbnVsbC4gV2hlbiBkb2luZyBtYW55IGNoZWNrcywgaXQgaXMgdXN1YWxseSBtb3JlXHJcbiAgICogZWZmaWNpZW50IHRvIG9ubHkgY2FsbCB0aGlzIG1ldGhvZCBpZiB7QGxpbmsgI2FhYmJDb250YWluc1BvaW50KGZsb2F0LCBmbG9hdCl9IHJldHVybnMgdHJ1ZS4gKi9cclxuICBjb250YWluc1BvaW50KHg6IG51bWJlciwgeTogbnVtYmVyKTogQm91bmRpbmdCb3hBdHRhY2htZW50IHtcclxuICAgIGxldCBwb2x5Z29ucyA9IHRoaXMucG9seWdvbnM7XHJcbiAgICBmb3IgKGxldCBpID0gMCwgbiA9IHBvbHlnb25zLmxlbmd0aDsgaSA8IG47IGkrKylcclxuICAgICAgaWYgKHRoaXMuY29udGFpbnNQb2ludFBvbHlnb24ocG9seWdvbnNbaV0sIHgsIHkpKVxyXG4gICAgICAgIHJldHVybiB0aGlzLmJvdW5kaW5nQm94ZXNbaV07XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcbiAgLyoqIFJldHVybnMgdHJ1ZSBpZiB0aGUgcG9seWdvbiBjb250YWlucyB0aGUgcG9pbnQuICovXHJcbiAgY29udGFpbnNQb2ludFBvbHlnb24ocG9seWdvbjogQXJyYXlMaWtlPG51bWJlcj4sIHg6IG51bWJlciwgeTogbnVtYmVyKSB7XHJcbiAgICBsZXQgdmVydGljZXMgPSBwb2x5Z29uO1xyXG4gICAgbGV0IG5uID0gcG9seWdvbi5sZW5ndGg7XHJcbiAgICBsZXQgcHJldkluZGV4ID0gbm4gLSAyO1xyXG4gICAgbGV0IGluc2lkZSA9IGZhbHNlO1xyXG4gICAgZm9yIChsZXQgaWkgPSAwOyBpaSA8IG5uOyBpaSArPSAyKSB7XHJcbiAgICAgIGxldCB2ZXJ0ZXhZID0gdmVydGljZXNbaWkgKyAxXTtcclxuICAgICAgbGV0IHByZXZZID0gdmVydGljZXNbcHJldkluZGV4ICsgMV07XHJcbiAgICAgIGlmICgodmVydGV4WSA8IHkgJiYgcHJldlkgPj0geSkgfHwgKHByZXZZIDwgeSAmJiB2ZXJ0ZXhZID49IHkpKSB7XHJcbiAgICAgICAgbGV0IHZlcnRleFggPSB2ZXJ0aWNlc1tpaV07XHJcbiAgICAgICAgaWYgKFxyXG4gICAgICAgICAgdmVydGV4WCArXHJcbiAgICAgICAgICAgICgoeSAtIHZlcnRleFkpIC8gKHByZXZZIC0gdmVydGV4WSkpICpcclxuICAgICAgICAgICAgICAodmVydGljZXNbcHJldkluZGV4XSAtIHZlcnRleFgpIDxcclxuICAgICAgICAgIHhcclxuICAgICAgICApXHJcbiAgICAgICAgICBpbnNpZGUgPSAhaW5zaWRlO1xyXG4gICAgICB9XHJcbiAgICAgIHByZXZJbmRleCA9IGlpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGluc2lkZTtcclxuICB9XHJcbiAgLyoqIFJldHVybnMgdGhlIGZpcnN0IGJvdW5kaW5nIGJveCBhdHRhY2htZW50IHRoYXQgY29udGFpbnMgYW55IHBhcnQgb2YgdGhlIGxpbmUgc2VnbWVudCwgb3IgbnVsbC4gV2hlbiBkb2luZyBtYW55IGNoZWNrcywgaXRcclxuICAgKiBpcyB1c3VhbGx5IG1vcmUgZWZmaWNpZW50IHRvIG9ubHkgY2FsbCB0aGlzIG1ldGhvZCBpZiB7QGxpbmsgI2FhYmJJbnRlcnNlY3RzU2VnbWVudChmbG9hdCwgZmxvYXQsIGZsb2F0LCBmbG9hdCl9IHJldHVybnNcclxuICAgKiB0cnVlLiAqL1xyXG4gIGludGVyc2VjdHNTZWdtZW50KHgxOiBudW1iZXIsIHkxOiBudW1iZXIsIHgyOiBudW1iZXIsIHkyOiBudW1iZXIpIHtcclxuICAgIGxldCBwb2x5Z29ucyA9IHRoaXMucG9seWdvbnM7XHJcbiAgICBmb3IgKGxldCBpID0gMCwgbiA9IHBvbHlnb25zLmxlbmd0aDsgaSA8IG47IGkrKylcclxuICAgICAgaWYgKHRoaXMuaW50ZXJzZWN0c1NlZ21lbnRQb2x5Z29uKHBvbHlnb25zW2ldLCB4MSwgeTEsIHgyLCB5MikpXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuYm91bmRpbmdCb3hlc1tpXTtcclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuICAvKiogUmV0dXJucyB0cnVlIGlmIHRoZSBwb2x5Z29uIGNvbnRhaW5zIGFueSBwYXJ0IG9mIHRoZSBsaW5lIHNlZ21lbnQuICovXHJcbiAgaW50ZXJzZWN0c1NlZ21lbnRQb2x5Z29uKFxyXG4gICAgcG9seWdvbjogQXJyYXlMaWtlPG51bWJlcj4sXHJcbiAgICB4MTogbnVtYmVyLFxyXG4gICAgeTE6IG51bWJlcixcclxuICAgIHgyOiBudW1iZXIsXHJcbiAgICB5MjogbnVtYmVyXHJcbiAgKSB7XHJcbiAgICBsZXQgdmVydGljZXMgPSBwb2x5Z29uO1xyXG4gICAgbGV0IG5uID0gcG9seWdvbi5sZW5ndGg7XHJcbiAgICBsZXQgd2lkdGgxMiA9IHgxIC0geDIsXHJcbiAgICAgIGhlaWdodDEyID0geTEgLSB5MjtcclxuICAgIGxldCBkZXQxID0geDEgKiB5MiAtIHkxICogeDI7XHJcbiAgICBsZXQgeDMgPSB2ZXJ0aWNlc1tubiAtIDJdLFxyXG4gICAgICB5MyA9IHZlcnRpY2VzW25uIC0gMV07XHJcbiAgICBmb3IgKGxldCBpaSA9IDA7IGlpIDwgbm47IGlpICs9IDIpIHtcclxuICAgICAgbGV0IHg0ID0gdmVydGljZXNbaWldLFxyXG4gICAgICAgIHk0ID0gdmVydGljZXNbaWkgKyAxXTtcclxuICAgICAgbGV0IGRldDIgPSB4MyAqIHk0IC0geTMgKiB4NDtcclxuICAgICAgbGV0IHdpZHRoMzQgPSB4MyAtIHg0LFxyXG4gICAgICAgIGhlaWdodDM0ID0geTMgLSB5NDtcclxuICAgICAgbGV0IGRldDMgPSB3aWR0aDEyICogaGVpZ2h0MzQgLSBoZWlnaHQxMiAqIHdpZHRoMzQ7XHJcbiAgICAgIGxldCB4ID0gKGRldDEgKiB3aWR0aDM0IC0gd2lkdGgxMiAqIGRldDIpIC8gZGV0MztcclxuICAgICAgaWYgKFxyXG4gICAgICAgICgoeCA+PSB4MyAmJiB4IDw9IHg0KSB8fCAoeCA+PSB4NCAmJiB4IDw9IHgzKSkgJiZcclxuICAgICAgICAoKHggPj0geDEgJiYgeCA8PSB4MikgfHwgKHggPj0geDIgJiYgeCA8PSB4MSkpXHJcbiAgICAgICkge1xyXG4gICAgICAgIGxldCB5ID0gKGRldDEgKiBoZWlnaHQzNCAtIGhlaWdodDEyICogZGV0MikgLyBkZXQzO1xyXG4gICAgICAgIGlmIChcclxuICAgICAgICAgICgoeSA+PSB5MyAmJiB5IDw9IHk0KSB8fCAoeSA+PSB5NCAmJiB5IDw9IHkzKSkgJiZcclxuICAgICAgICAgICgoeSA+PSB5MSAmJiB5IDw9IHkyKSB8fCAoeSA+PSB5MiAmJiB5IDw9IHkxKSlcclxuICAgICAgICApXHJcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgfVxyXG4gICAgICB4MyA9IHg0O1xyXG4gICAgICB5MyA9IHk0O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuICAvKiogUmV0dXJucyB0aGUgcG9seWdvbiBmb3IgdGhlIHNwZWNpZmllZCBib3VuZGluZyBib3gsIG9yIG51bGwuICovXHJcbiAgZ2V0UG9seWdvbihib3VuZGluZ0JveDogQm91bmRpbmdCb3hBdHRhY2htZW50KSB7XHJcbiAgICBpZiAoYm91bmRpbmdCb3ggPT0gbnVsbCkgdGhyb3cgbmV3IEVycm9yKFwiYm91bmRpbmdCb3ggY2Fubm90IGJlIG51bGwuXCIpO1xyXG4gICAgbGV0IGluZGV4ID0gdGhpcy5ib3VuZGluZ0JveGVzLmluZGV4T2YoYm91bmRpbmdCb3gpO1xyXG4gICAgcmV0dXJuIGluZGV4ID09IC0xID8gbnVsbCA6IHRoaXMucG9seWdvbnNbaW5kZXhdO1xyXG4gIH1cclxuICBnZXRXaWR0aCgpIHtcclxuICAgIHJldHVybiB0aGlzLm1heFggLSB0aGlzLm1pblg7XHJcbiAgfVxyXG4gIGdldEhlaWdodCgpIHtcclxuICAgIHJldHVybiB0aGlzLm1heFkgLSB0aGlzLm1pblk7XHJcbiAgfVxyXG59XHJcbiJdfQ==