From 3ba010a673a4fcfa61dfee2ad038328d07d768dd Mon Sep 17 00:00:00 2001 From: Preet Date: Thu, 12 Jan 2017 00:43:11 -0800 Subject: [PATCH] . --- docs/builds/rough.js | 2126 ++++++++++++++++++++++++++++++++++++++ docs/builds/rough.min.js | 3 + docs/builds/rough.zip | Bin 0 -> 20745 bytes 3 files changed, 2129 insertions(+) create mode 100644 docs/builds/rough.js create mode 100644 docs/builds/rough.min.js create mode 100644 docs/builds/rough.zip diff --git a/docs/builds/rough.js b/docs/builds/rough.js new file mode 100644 index 0000000..a04bd73 --- /dev/null +++ b/docs/builds/rough.js @@ -0,0 +1,2126 @@ +"use strict"; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Drawable = function () { + function Drawable(propertyNames) { + _classCallCheck(this, Drawable); + + this._fields = {}; + this._dirty = false; + this._canvas = null; + this.z = 0; + this._roughness = null; + this._bowing = null; + this._stroke = null; + this._strokeWidth = null; + + this._fill = null; + this._fillStyle = null; + this._fillWeight = null; + this._hachureAngle = null; + this._hachureGap = null; + + this._maxRandomnessOffset = null; + this._curveTightness = 0; + if (propertyNames) { + for (var i = 0; i < propertyNames.length; i++) { + this._defineRenderProperty(propertyNames[i]); + } + } + } + + _createClass(Drawable, [{ + key: '_defineRenderProperty', + value: function _defineRenderProperty(name) { + Object.defineProperty(this, name, { + get: function get() { + return this._get(name); + }, + set: function set(value) { + this._set(name, value); + } + }); + } + }, { + key: 'attach', + value: function attach(canvas, z) { + this.attached = true; + this._canvas = canvas; + this.z = z; + } + }, { + key: 'detach', + value: function detach() { + this.attached = false; + this.z = 0; + } + }, { + key: 'remove', + value: function remove() { + if (this.attached && this._canvas) { + this._canvas.remove(this); + } + } + }, { + key: '_get', + value: function _get(name) { + if (this._fields[name]) { + return this._fields[name]; + } + return null; + } + }, { + key: '_set', + value: function _set(name, value) { + var markDirty = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + + this._fields[name] = value; + if (markDirty) { + this._dirty = true; + if (this._canvas) { + this._canvas.requestDraw(); + } + } + } + }, { + key: 'draw', + value: function draw(context) { + console.log("Draw not implemented.", context); + } + }, { + key: 'getOffset', + value: function getOffset(min, max) { + return this.roughness * (Math.random() * (max - min) + min); + } + }, { + key: 'drawLine', + value: function drawLine(ctx, x1, y1, x2, y2, existingPath) { + var lengthSq = Math.pow(x1 - x2, 2) + Math.pow(x1 - x2, 2); + var offset = this.maxRandomnessOffset || 0; + if (offset * offset * 100 > lengthSq) { + offset = Math.sqrt(lengthSq) / 10; + } + var halfOffset = offset / 2; + var divergePoint = 0.2 + Math.random() * 0.2; + // Midpoint displacement value to give slightly bowed lines. + var midDispX = this.bowing * this.maxRandomnessOffset * (y2 - y1) / 200; + var midDispY = this.bowing * this.maxRandomnessOffset * (x1 - x2) / 200; + midDispX = this.getOffset(-midDispX, midDispX); + midDispY = this.getOffset(-midDispY, midDispY); + + if (!existingPath) { + ctx.beginPath(); + } + ctx.moveTo(x1 + this.getOffset(-offset, offset), y1 + this.getOffset(-offset, offset)); + ctx.bezierCurveTo(midDispX + x1 + (x2 - x1) * divergePoint + this.getOffset(-offset, offset), midDispY + y1 + (y2 - y1) * divergePoint + this.getOffset(-offset, offset), midDispX + x1 + 2 * (x2 - x1) * divergePoint + this.getOffset(-offset, offset), midDispY + y1 + 2 * (y2 - y1) * divergePoint + this.getOffset(-offset, offset), x2 + this.getOffset(-offset, offset), y2 + this.getOffset(-offset, offset)); + if (!existingPath) { + ctx.stroke(); + } + if (!existingPath) { + ctx.beginPath(); + } + ctx.moveTo(x1 + this.getOffset(-halfOffset, halfOffset), y1 + this.getOffset(-halfOffset, halfOffset)); + ctx.bezierCurveTo(midDispX + x1 + (x2 - x1) * divergePoint + this.getOffset(-halfOffset, halfOffset), midDispY + y1 + (y2 - y1) * divergePoint + this.getOffset(-halfOffset, halfOffset), midDispX + x1 + 2 * (x2 - x1) * divergePoint + this.getOffset(-halfOffset, halfOffset), midDispY + y1 + 2 * (y2 - y1) * divergePoint + this.getOffset(-halfOffset, halfOffset), x2 + this.getOffset(-halfOffset, halfOffset), y2 + this.getOffset(-halfOffset, halfOffset)); + if (!existingPath) { + ctx.stroke(); + } + } + }, { + key: 'drawLinearPath', + value: function drawLinearPath(ctx, points, close) { + var len = points.length; + if (len > 2) { + ctx.beginPath(); + for (var i = 0; i < len - 1; i++) { + this.drawLine(ctx, points[i][0], points[i][1], points[i + 1][0], points[i + 1][1], true); + } + if (close) { + this.drawLine(ctx, points[len - 1][0], points[len - 1][1], points[0][0], points[0][1], true); + } + ctx.stroke(); + } else if (len == 2) { + this.drawLine(ctx, points[0][0], points[0][1], points[1][0], points[1][1]); + } + } + }, { + key: 'drawCurve', + value: function drawCurve(ctx, vertArray, existingPath, closeToCenter, center) { + var vertArrayLength = vertArray.length; + var i; + if (vertArrayLength > 3) { + var b = []; + var s = 1 - this.curveTightness; + if (!existingPath) { + ctx.beginPath(); + } + ctx.moveTo(vertArray[1][0], vertArray[1][1]); + for (i = 1; i + 2 < vertArrayLength; i++) { + var cachedVertArray = vertArray[i]; + b[0] = [cachedVertArray[0], cachedVertArray[1]]; + b[1] = [cachedVertArray[0] + (s * vertArray[i + 1][0] - s * vertArray[i - 1][0]) / 6, cachedVertArray[1] + (s * vertArray[i + 1][1] - s * vertArray[i - 1][1]) / 6]; + b[2] = [vertArray[i + 1][0] + (s * vertArray[i][0] - s * vertArray[i + 2][0]) / 6, vertArray[i + 1][1] + (s * vertArray[i][1] - s * vertArray[i + 2][1]) / 6]; + b[3] = [vertArray[i + 1][0], vertArray[i + 1][1]]; + ctx.bezierCurveTo(b[1][0], b[1][1], b[2][0], b[2][1], b[3][0], b[3][1]); + } + if (closeToCenter && center && center.length == 2) { + var ro = this.maxRandomnessOffset || 0; + ctx.lineTo(center[0] + this.getOffset(-ro, ro), center[1] + this.getOffset(-ro, ro)); + } + if (!existingPath) { + ctx.stroke(); + } + } else if (vertArrayLength == 3) { + this.drawBezier(ctx, vertArray[0][0], vertArray[0][1], vertArray[1][0], vertArray[1][1], vertArray[2][0], vertArray[2][1], vertArray[2][0], vertArray[2][1], existingPath); + } else if (vertArrayLength == 2) { + this.drawLine(ctx, vertArray[0][0], vertArray[0][1], vertArray[1][0], vertArray[1][1], existingPath); + } + } + }, { + key: 'drawBezier', + value: function drawBezier(ctx, x1, y1, x2, y2, x3, y3, x4, y4, existingPath) { + if (!existingPath) { + ctx.beginPath(); + } + ctx.moveTo(x1, y1); + var ro = this.maxRandomnessOffset || 0; + ctx.moveTo(x1 + this.getOffset(-ro, ro), y1 + this.getOffset(-ro, ro)); + this._drawBezierTo(ctx, x2, y2, x3, y3, x4, y4); + if (!existingPath) { + ctx.stroke(); + } + } + }, { + key: '_drawBezierTo', + value: function _drawBezierTo(ctx, x1, y1, x2, y2, x, y) { + var ro = this.maxRandomnessOffset || 0; + var final = [x + this.getOffset(-ro, ro), y + this.getOffset(-ro, ro)]; + ctx.bezierCurveTo(x1 + this.getOffset(-ro, ro), y1 + this.getOffset(-ro, ro), x2 + this.getOffset(-ro, ro), y2 + this.getOffset(-ro, ro), final[0], final[1]); + return final; + } + }, { + key: '_drawQuadTo', + value: function _drawQuadTo(ctx, x1, y1, x, y) { + var ro = this.maxRandomnessOffset || 0; + var final = [x + this.getOffset(-ro, ro), y + this.getOffset(-ro, ro)]; + ctx.quadraticCurveTo(x1 + this.getOffset(-ro, ro), y1 + this.getOffset(-ro, ro), final[0], final[1]); + return final; + } + + // fill + + }, { + key: 'getIntersectingLines', + value: function getIntersectingLines(lineCoords, xCoords, yCoords) { + var intersections = []; + var s1 = new Segment(lineCoords[0], lineCoords[1], lineCoords[2], lineCoords[3]); + for (var i = 0; i < xCoords.length; i++) { + var s2 = new Segment(xCoords[i], yCoords[i], xCoords[(i + 1) % xCoords.length], yCoords[(i + 1) % xCoords.length]); + if (s1.compare(s2) == _RELATION_.INTERSECTS) { + intersections.push([s1.xi, s1.yi]); + } + } + return intersections; + } + }, { + key: 'hachureFillShape', + value: function hachureFillShape(ctx, xCoords, yCoords) { + if (xCoords && yCoords && xCoords.length && yCoords.length) { + var left = xCoords[0]; + var right = xCoords[0]; + var top = yCoords[0]; + var bottom = yCoords[0]; + for (var i = 1; i < xCoords.length; i++) { + left = Math.min(left, xCoords[i]); + right = Math.max(right, xCoords[i]); + top = Math.min(top, yCoords[i]); + bottom = Math.max(bottom, yCoords[i]); + } + + var angle = this.hachureAngle; + var gap = this.hachureGap; + if (gap < 0) { + gap = this.strokeWidth * 4; + } + gap = Math.max(gap, 0.1); + var fweight = this.fillWeight; + if (fweight < 0) { + fweight = this.strokeWidth / 2; + } + + var radPerDeg = Math.PI / 180; + var hachureAngle = angle % 180 * radPerDeg; + var cosAngle = Math.cos(hachureAngle); + var sinAngle = Math.sin(hachureAngle); + var tanAngle = Math.tan(hachureAngle); + + ctx.save(); + ctx.strokeStyle = this.fill; + ctx.lineWidth = fweight; + + var it = new HachureIterator(top - 1, bottom + 1, left - 1, right + 1, gap, sinAngle, cosAngle, tanAngle); + var rectCoords; + while ((rectCoords = it.getNextLine()) != null) { + var lines = this.getIntersectingLines(rectCoords, xCoords, yCoords); + for (var _i = 0; _i < lines.length; _i++) { + if (_i < lines.length - 1) { + var p1 = lines[_i]; + var p2 = lines[_i + 1]; + this.drawLine(ctx, p1[0], p1[1], p2[0], p2[1]); + } + } + } + + ctx.restore(); + } + } + }, { + key: 'dirty', + get: function get() { + return this._dirty; + } + }, { + key: 'roughness', + set: function set(value) { + this._roughness = value; + if (this._canvas) { + this._canvas.requestDraw(); + } + }, + get: function get() { + if (typeof this._roughness === 'number') { + if (this._roughness >= 0) { + return this._roughness; + } + } + if (this._canvas) { + return this._canvas.roughness; + } + return this._roughness; + } + }, { + key: 'bowing', + set: function set(value) { + this._bowing = value; + if (this._canvas) { + this._canvas.requestDraw(); + } + }, + get: function get() { + if (typeof this._bowing === 'number') { + if (this._bowing >= 0) { + return this._bowing; + } + } + if (this._canvas) { + return this._canvas.bowing; + } + return this._bowing; + } + }, { + key: 'stroke', + set: function set(value) { + this._stroke = value; + if (this._canvas) { + this._canvas.requestDraw(); + } + }, + get: function get() { + if (typeof this._stroke === 'string') { + if (this._stroke) { + return this._stroke; + } + } + if (this._canvas) { + return this._canvas.stroke; + } + return this._stroke; + } + }, { + key: 'strokeWidth', + set: function set(value) { + this._strokeWidth = value; + if (this._canvas) { + this._canvas.requestDraw(); + } + }, + get: function get() { + if (typeof this._strokeWidth === 'number') { + if (this._strokeWidth >= 0) { + return this._strokeWidth; + } + } + if (this._canvas) { + return this._canvas.strokeWidth; + } + return this._strokeWidth; + } + }, { + key: 'maxRandomnessOffset', + set: function set(value) { + this._maxRandomnessOffset = value; + if (this._canvas) { + this._canvas.requestDraw(); + } + }, + get: function get() { + if (typeof this._maxRandomnessOffset === 'number') { + if (this._maxRandomnessOffset >= 0) { + return this._maxRandomnessOffset; + } + } + if (this._canvas) { + return this._canvas.maxRandomnessOffset; + } + return this._maxRandomnessOffset; + } + }, { + key: 'curveTightness', + set: function set(value) { + this._curveTightness = Math.max(Math.min(value, 1), 0); + if (this._canvas) { + this._canvas.requestDraw(); + } + }, + get: function get() { + if (typeof this._curveTightness === 'number') { + if (this._curveTightness >= 0) { + return this._curveTightness; + } + } + if (this._canvas) { + return this._canvas.curveTightness || 0; + } + return this._curveTightness; + } + }, { + key: 'fill', + set: function set(value) { + this._fill = value; + if (this._canvas) { + this._canvas.requestDraw(); + } + }, + get: function get() { + if (typeof this._fill === 'string') { + if (this._fill) { + return this._fill; + } + } + if (this._canvas) { + return this._canvas.fill; + } + return this._fill; + } + }, { + key: 'fillStyle', + set: function set(value) { + this._fillStyle = value; + if (this._canvas) { + this._canvas.requestDraw(); + } + }, + get: function get() { + if (typeof this._fillStyle === 'string') { + if (this._fillStyle) { + return this._fillStyle; + } + } + if (this._canvas) { + return this._canvas.fillStyle; + } + return this._fillStyle; + } + }, { + key: 'fillWeight', + set: function set(value) { + this._fillWeight = value; + if (this._canvas) { + this._canvas.requestDraw(); + } + }, + get: function get() { + if (typeof this._fillWeight === 'number') { + if (this._fillWeight) { + return this._fillWeight; + } + } + if (this._canvas) { + return this._canvas.fillWeight; + } + return this._fillWeight; + } + }, { + key: 'hachureAngle', + set: function set(value) { + this._hachureAngle = value; + if (this._canvas) { + this._canvas.requestDraw(); + } + }, + get: function get() { + if (typeof this._hachureAngle === 'number') { + if (this._hachureAngle >= 0) { + return this._hachureAngle; + } + } + if (this._canvas) { + return this._canvas.hachureAngle; + } + return this._hachureAngle; + } + }, { + key: 'hachureGap', + set: function set(value) { + this._hachureGap = value; + if (this._canvas) { + this._canvas.requestDraw(); + } + }, + get: function get() { + if (typeof this._hachureGap === 'number') { + if (this._hachureGap >= 0) { + return this._hachureGap; + } + } + if (this._canvas) { + return this._canvas.hachureGap; + } + return this._hachureGap; + } + }]); + + return Drawable; +}(); + +"use strict"; + +var Ellipse = function (_Drawable) { + _inherits(Ellipse, _Drawable); + + function Ellipse(x, y, width, height) { + _classCallCheck(this, Ellipse); + + var _this = _possibleConstructorReturn(this, (Ellipse.__proto__ || Object.getPrototypeOf(Ellipse)).call(this, ['x', 'y', 'width', 'height', 'numSteps'])); + + _this.x = x; + _this.y = y; + _this.width = width; + _this.height = height || width; + _this.numSteps = 9; + return _this; + } + + _createClass(Ellipse, [{ + key: 'draw', + value: function draw(ctx) { + this.ellipseInc = Math.PI * 2 / this.numSteps; + var rx = Math.abs(this.width / 2); + var ry = Math.abs(this.height / 2); + rx += this.getOffset(-rx * 0.05, rx * 0.05); + ry += this.getOffset(-ry * 0.05, ry * 0.05); + + if (this.fill) { + this._doFill(ctx, rx, ry); + } + + ctx.save(); + ctx.strokeStyle = this.stroke; + ctx.lineWidth = this.strokeWidth; + this._ellipse(ctx, this.x, this.y, rx, ry, 1, this.ellipseInc * this.getOffset(0.1, this.getOffset(0.4, 1))); + this._ellipse(ctx, this.x, this.y, rx, ry, 1.5, 0); + ctx.restore(); + } + }, { + key: '_ellipse', + value: function _ellipse(ctx, cx, cy, rx, ry, offset, overlap, existingPath) { + var radOffset = this.getOffset(-0.5, 0.5) - Math.PI / 2; + var points = []; + points.push([this.getOffset(-offset, offset) + cx + 0.9 * rx * Math.cos(radOffset - this.ellipseInc), this.getOffset(-offset, offset) + cy + 0.9 * ry * Math.sin(radOffset - this.ellipseInc)]); + for (var angle = radOffset; angle < Math.PI * 2 + radOffset - 0.01; angle = angle + this.ellipseInc) { + points.push([this.getOffset(-offset, offset) + cx + rx * Math.cos(angle), this.getOffset(-offset, offset) + cy + ry * Math.sin(angle)]); + } + points.push([this.getOffset(-offset, offset) + cx + rx * Math.cos(radOffset + Math.PI * 2 + overlap * 0.5), this.getOffset(-offset, offset) + cy + ry * Math.sin(radOffset + Math.PI * 2 + overlap * 0.5)]); + points.push([this.getOffset(-offset, offset) + cx + 0.98 * rx * Math.cos(radOffset + overlap), this.getOffset(-offset, offset) + cy + 0.98 * ry * Math.sin(radOffset + overlap)]); + points.push([this.getOffset(-offset, offset) + cx + 0.9 * rx * Math.cos(radOffset + overlap * 0.5), this.getOffset(-offset, offset) + cy + 0.9 * ry * Math.sin(radOffset + overlap * 0.5)]); + this.drawCurve(ctx, points, existingPath); + } + }, { + key: '_doFill', + value: function _doFill(ctx, rx, ry) { + var fillStyle = this.fillStyle || "hachure"; + switch (fillStyle) { + case "solid": + { + ctx.save(); + ctx.fillStyle = this.fill; + ctx.strokeStyle = null; + ctx.beginPath(); + this._ellipse(ctx, this.x, this.y, rx, ry, 1, this.ellipseInc * this.getOffset(0.1, this.getOffset(0.4, 1)), true); + ctx.fill(); + ctx.restore(); + break; + } + default: + { + var angle = this.hachureAngle; + var gap = this.hachureGap; + if (gap <= 0) { + gap = this.strokeWidth * 4; + } + var fweight = this.fillWeight; + if (fweight < 0) { + fweight = this.strokeWidth / 2; + } + var radPerDeg = Math.PI / 180; + var hachureAngle = angle % 180 * radPerDeg; + var tanAngle = Math.tan(hachureAngle); + var cx = this.x, + cy = this.y; + var aspectRatio = ry / rx; + var hyp = Math.sqrt(aspectRatio * tanAngle * aspectRatio * tanAngle + 1); + var sinAnglePrime = aspectRatio * tanAngle / hyp; + var cosAnglePrime = 1 / hyp; + var gapPrime = gap / (rx * ry / Math.sqrt(ry * cosAnglePrime * (ry * cosAnglePrime) + rx * sinAnglePrime * (rx * sinAnglePrime)) / rx); + var halfLen = Math.sqrt(rx * rx - (cx - rx + gapPrime) * (cx - rx + gapPrime)); + + ctx.save(); + ctx.strokeStyle = this.fill; + ctx.lineWidth = fweight; + for (var xPos = cx - rx + gapPrime; xPos < cx + rx; xPos += gapPrime) { + halfLen = Math.sqrt(rx * rx - (cx - xPos) * (cx - xPos)); + var p1 = this.affine(xPos, cy - halfLen, cx, cy, sinAnglePrime, cosAnglePrime, aspectRatio); + var p2 = this.affine(xPos, cy + halfLen, cx, cy, sinAnglePrime, cosAnglePrime, aspectRatio); + this.drawLine(ctx, p1[0], p1[1], p2[0], p2[1]); + } + ctx.restore(); + break; + } + } + } + }, { + key: 'affine', + value: function affine(x, y, cx, cy, sinAnglePrime, cosAnglePrime, R) { + var A = -cx * cosAnglePrime - cy * sinAnglePrime + cx; + var B = R * (cx * sinAnglePrime - cy * cosAnglePrime) + cy; + var C = cosAnglePrime; + var D = sinAnglePrime; + var E = -R * sinAnglePrime; + var F = R * cosAnglePrime; + return [A + C * x + D * y, B + E * x + F * y]; + } + }]); + + return Ellipse; +}(Drawable); + +"use strict"; + +var Arc = function (_Drawable2) { + _inherits(Arc, _Drawable2); + + function Arc(x, y, width, height, start, stop, closed) { + _classCallCheck(this, Arc); + + var _this2 = _possibleConstructorReturn(this, (Arc.__proto__ || Object.getPrototypeOf(Arc)).call(this, ['x', 'y', 'width', 'height', 'start', 'stop', 'numSteps', 'closed'])); + + _this2.x = x; + _this2.y = y; + _this2.width = width; + _this2.height = height || width; + _this2.start = start; + _this2.stop = stop; + _this2.numSteps = 9; + _this2.closed = closed ? true : false; + return _this2; + } + + _createClass(Arc, [{ + key: 'draw', + value: function draw(ctx) { + var cx = this.x; + var cy = this.y; + var rx = Math.abs(this.width / 2); + var ry = Math.abs(this.height / 2); + rx += this.getOffset(-rx * 0.01, rx * 0.01); + ry += this.getOffset(-ry * 0.01, ry * 0.01); + var strt = this.start; + var stp = this.stop; + while (strt < 0) { + strt += Math.PI * 2; + stp += Math.PI * 2; + } + if (stp - strt > Math.PI * 2) { + strt = 0; + stp = Math.PI * 2; + } + var ellipseInc = Math.PI * 2 / this.numSteps; + var arcInc = Math.min(ellipseInc / 2, (stp - strt) / 2); + + var points = []; + points.push([cx + rx * Math.cos(strt), cy + ry * Math.sin(strt)]); + for (var theta = strt; theta <= stp; theta += arcInc) { + points.push([cx + rx * Math.cos(theta), cy + ry * Math.sin(theta)]); + } + points.push([cx + rx * Math.cos(stp), cy + ry * Math.sin(stp)]); + points.push([cx + rx * Math.cos(stp), cy + ry * Math.sin(stp)]); + + if (this.fill && this.closed) { + this._doFill(ctx, points, [cx, cy]); + } + + ctx.save(); + ctx.strokeStyle = this.stroke; + ctx.lineWidth = this.strokeWidth; + this.drawCurve(ctx, points); + if (this.closed) { + var lindex = points.length - 1; + this.drawLine(ctx, points[0][0], points[0][1], cx, cy); + this.drawLine(ctx, points[lindex][0], points[lindex][1], cx, cy); + } + ctx.restore(); + } + }, { + key: '_doFill', + value: function _doFill(ctx, points, center) { + var _this3 = this; + + var fillStyle = this.fillStyle || "hachure"; + switch (fillStyle) { + case "solid": + { + ctx.save(); + ctx.fillStyle = this.fill; + ctx.beginPath(); + this.drawCurve(ctx, points, true, true, center); + ctx.fill(); + ctx.restore(); + break; + } + default: + { + var vertices; + var theta; + + var _ret = function () { + var cx = _this3.x; + var cy = _this3.y; + var strt = _this3.start; + var stp = _this3.stop; + var rx = Math.abs(_this3.width / 2); + var ry = Math.abs(_this3.height / 2); + while (strt < 0) { + strt += Math.PI * 2; + stp += Math.PI * 2; + } + if (stp - strt > Math.PI * 2) { + strt = 0; + stp = Math.PI * 2; + } + var arcInc = (stp - strt) / _this3.numSteps; + vertices = []; + + vertices.push([cx, cy]); + vertices.push([cx + rx * Math.cos(strt), cy + ry * Math.sin(strt)]); + for (theta = strt; theta <= stp; theta += arcInc) { + vertices.push([cx + rx * Math.cos(theta), cy + ry * Math.sin(theta)]); + } + vertices.push([cx + rx * Math.cos(stp), cy + ry * Math.sin(stp)]); + + var xc = []; + var yc = []; + vertices.forEach(function (p) { + xc.push(p[0]); + yc.push(p[1]); + }); + _this3.hachureFillShape(ctx, xc, yc); + return 'break'; + }(); + + if (_ret === 'break') break; + } + } + } + }]); + + return Arc; +}(Drawable); + +"use strict"; + +var Circle = function (_Ellipse) { + _inherits(Circle, _Ellipse); + + function Circle(x, y, radius) { + _classCallCheck(this, Circle); + + return _possibleConstructorReturn(this, (Circle.__proto__ || Object.getPrototypeOf(Circle)).call(this, x, y, radius * 2)); + } + + _createClass(Circle, [{ + key: 'radius', + get: function get() { + return this.width / 2; + }, + set: function set(value) { + this.width = value * 2; + this.height = value * 2; + } + }]); + + return Circle; +}(Ellipse); + +"use strict"; + +var Curve = function (_Drawable3) { + _inherits(Curve, _Drawable3); + + function Curve(points) { + _classCallCheck(this, Curve); + + var _this5 = _possibleConstructorReturn(this, (Curve.__proto__ || Object.getPrototypeOf(Curve)).call(this)); + + _this5._points = points; + return _this5; + } + + _createClass(Curve, [{ + key: 'setPoint', + value: function setPoint(index, x, y) { + this._points[index] = [x, y]; + if (this._canvas) { + this._canvas.requestDraw(); + } + } + }, { + key: 'getPoint', + value: function getPoint(index) { + if (index > 0 && index < this._points.length) { + return this._points[index]; + } + return null; + } + }, { + key: 'draw', + value: function draw(ctx) { + ctx.save(); + ctx.strokeStyle = this.stroke; + ctx.lineWidth = this.strokeWidth; + var o = this.maxRandomnessOffset || 0; + var p1 = []; + var p2 = []; + p1.push(this._points[0]); + p1.push(this._points[0]); + var px = [this._points[0][0] + this.getOffset(-o, o), this._points[0][1] + this.getOffset(-o, o)]; + p2.push(px); + p2.push(px); + + var lastIndex = this._points.length - 1; + for (var i = 1; i < lastIndex; i++) { + p1.push(this._points[i]); + if (i % 3 == 0) { + p2.push([this._points[i][0] + this.getOffset(-o, o), this._points[i][1] + this.getOffset(-o, o)]); + } else { + p2.push(this._points[i]); + } + } + + p1.push(this._points[lastIndex]); + p1.push(this._points[lastIndex]); + var px2 = [this._points[lastIndex][0] + this.getOffset(-o, o), this._points[lastIndex][1] + this.getOffset(-o, o)]; + p2.push(px2); + p2.push(px2); + + this.drawCurve(ctx, p1); + this.drawCurve(ctx, p2); + ctx.restore(); + } + }]); + + return Curve; +}(Drawable); + +"use strict"; + +var ArcConverter = function () { + // Algorithm as described in https://www.w3.org/TR/SVG/implnote.html + // Code adapted from nsSVGPathDataParser.cpp in Mozilla + // https://hg.mozilla.org/mozilla-central/file/17156fbebbc8/content/svg/content/src/nsSVGPathDataParser.cpp#l887 + + function ArcConverter(from, to, radii, angle, largeArcFlag, sweepFlag) { + _classCallCheck(this, ArcConverter); + + var radPerDeg = Math.PI / 180; + this._segIndex = 0; + this._numSegs = 0; + if (from[0] == to[0] && from[1] == to[1]) { + return; + } + this._rx = Math.abs(radii[0]); + this._ry = Math.abs(radii[1]); + this._sinPhi = Math.sin(angle * radPerDeg); + this._cosPhi = Math.cos(angle * radPerDeg); + var x1dash = this._cosPhi * (from[0] - to[0]) / 2.0 + this._sinPhi * (from[1] - to[1]) / 2.0; + var y1dash = -this._sinPhi * (from[0] - to[0]) / 2.0 + this._cosPhi * (from[1] - to[1]) / 2.0; + var root; + var numerator = this._rx * this._rx * this._ry * this._ry - this._rx * this._rx * y1dash * y1dash - this._ry * this._ry * x1dash * x1dash; + if (numerator < 0) { + var s = Math.sqrt(1 - numerator / (this._rx * this._rx * this._ry * this._ry)); + this._rx = s; + this._ry = s; + root = 0; + } else { + root = (largeArcFlag == sweepFlag ? -1.0 : 1.0) * Math.sqrt(numerator / (this._rx * this._rx * y1dash * y1dash + this._ry * this._ry * x1dash * x1dash)); + } + var cxdash = root * this._rx * y1dash / this._ry; + var cydash = -root * this._ry * x1dash / this._rx; + this._C = [0, 0]; + this._C[0] = this._cosPhi * cxdash - this._sinPhi * cydash + (from[0] + to[0]) / 2.0; + this._C[1] = this._sinPhi * cxdash + this._cosPhi * cydash + (from[1] + to[1]) / 2.0; + this._theta = this.calculateVectorAngle(1.0, 0.0, (x1dash - cxdash) / this._rx, (y1dash - cydash) / this._ry); + var dtheta = this.calculateVectorAngle((x1dash - cxdash) / this._rx, (y1dash - cydash) / this._ry, (-x1dash - cxdash) / this._rx, (-y1dash - cydash) / this._ry); + if (!sweepFlag && dtheta > 0) { + dtheta -= 2 * Math.PI; + } else if (sweepFlag && dtheta < 0) { + dtheta += 2 * Math.PI; + } + this._numSegs = Math.ceil(Math.abs(dtheta / (Math.PI / 2))); + this._delta = dtheta / this._numSegs; + this._T = 8 / 3 * Math.sin(this._delta / 4) * Math.sin(this._delta / 4) / Math.sin(this._delta / 2); + this._from = from; + } + + _createClass(ArcConverter, [{ + key: 'getNextSegment', + value: function getNextSegment() { + var cp1, cp2, to; + if (this._segIndex == this._numSegs) { + return null; + } + var cosTheta1 = Math.cos(this._theta); + var sinTheta1 = Math.sin(this._theta); + var theta2 = this._theta + this._delta; + var cosTheta2 = Math.cos(theta2); + var sinTheta2 = Math.sin(theta2); + + to = [this._cosPhi * this._rx * cosTheta2 - this._sinPhi * this._ry * sinTheta2 + this._C[0], this._sinPhi * this._rx * cosTheta2 + this._cosPhi * this._ry * sinTheta2 + this._C[1]]; + cp1 = [this._from[0] + this._T * (-this._cosPhi * this._rx * sinTheta1 - this._sinPhi * this._ry * cosTheta1), this._from[1] + this._T * (-this._sinPhi * this._rx * sinTheta1 + this._cosPhi * this._ry * cosTheta1)]; + cp2 = [to[0] + this._T * (this._cosPhi * this._rx * sinTheta2 + this._sinPhi * this._ry * cosTheta2), to[1] + this._T * (this._sinPhi * this._rx * sinTheta2 - this._cosPhi * this._ry * cosTheta2)]; + + this._theta = theta2; + this._from = [to[0], to[1]]; + this._segIndex++; + + return { + cp1: cp1, + cp2: cp2, + to: to + }; + } + }, { + key: 'calculateVectorAngle', + value: function calculateVectorAngle(ux, uy, vx, vy) { + var ta = Math.atan2(uy, ux); + var tb = Math.atan2(vy, vx); + if (tb >= ta) return tb - ta; + return 2 * Math.PI - (ta - tb); + } + }]); + + return ArcConverter; +}(); + +"use strict"; + +// Path parsing adapted from http://www.kevlindev.com/geometry/index.htm + +function GeomToken(type, text) { + if (arguments.length > 0) { + this.init(type, text); + } +} +GeomToken.prototype.init = function (type, text) { + this.type = type;this.text = text; +}; +GeomToken.prototype.typeis = function (type) { + return this.type == type; +}; + +var GeomPath = function () { + function GeomPath(d) { + _classCallCheck(this, GeomPath); + + this.PARAMS = { + A: ["rx", "ry", "x-axis-rotation", "large-arc-flag", "sweep-flag", "x", "y"], + a: ["rx", "ry", "x-axis-rotation", "large-arc-flag", "sweep-flag", "x", "y"], + C: ["x1", "y1", "x2", "y2", "x", "y"], + c: ["x1", "y1", "x2", "y2", "x", "y"], + H: ["x"], + h: ["x"], + L: ["x", "y"], + l: ["x", "y"], + M: ["x", "y"], + m: ["x", "y"], + Q: ["x1", "y1", "x", "y"], + q: ["x1", "y1", "x", "y"], + S: ["x2", "y2", "x", "y"], + s: ["x2", "y2", "x", "y"], + T: ["x", "y"], + t: ["x", "y"], + V: ["y"], + v: ["y"], + Z: [], + z: [] + }; + this.COMMAND = 0; + this.NUMBER = 1; + this.EOD = 2; + + this.segments = []; + this.d = d || ""; + this.parseData(d); + } + + _createClass(GeomPath, [{ + key: 'parseData', + value: function parseData(d) { + var tokens = this.tokenize(d); + var index = 0; + var token = tokens[index]; + var mode = "BOD"; + this.segments = new Array(); + while (!token.typeis(this.EOD)) { + var param_length; + var params = new Array(); + if (mode == "BOD") { + if (token.text == "M" || token.text == "m") { + index++; + param_length = this.PARAMS[token.text].length; + mode = token.text; + } else { + console.error("Path data must begin with a MoveTo command"); + return; + } + } else { + if (token.typeis(this.NUMBER)) { + param_length = this.PARAMS[mode].length; + } else { + index++; + param_length = this.PARAMS[token.text].length; + mode = token.text; + } + } + + if (index + param_length < tokens.length) { + for (var i = index; i < index + param_length; i++) { + var number = tokens[i]; + if (number.typeis(this.NUMBER)) { + params[params.length] = number.text; + } else { + console.error("Parameter type is not a number: " + mode + "," + number.text); + return; + } + } + var segment; + if (this.PARAMS[mode]) { + segment = { key: mode, data: params }; + } else { + console.error("Unsupported segment type: " + mode); + return; + } + this.segments.push(segment); + index += param_length; + token = tokens[index]; + if (mode == "M") mode = "L"; + if (mode == "m") mode = "l"; + } else { + console.error("Path data ended before all parameters were found"); + } + } + } + }, { + key: 'tokenize', + value: function tokenize(d) { + var tokens = new Array(); + while (d != "") { + if (d.match(/^([ \t\r\n,]+)/)) { + d = d.substr(RegExp.$1.length); + } else if (d.match(/^([aAcChHlLmMqQsStTvVzZ])/)) { + tokens[tokens.length] = new GeomToken(this.COMMAND, RegExp.$1); + d = d.substr(RegExp.$1.length); + } else if (d.match(/^(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)/)) { + tokens[tokens.length] = new GeomToken(this.NUMBER, parseFloat(RegExp.$1)); + d = d.substr(RegExp.$1.length); + } else { + console.error("Unrecognized segment command: " + d); + return null; + } + } + tokens[tokens.length] = new GeomToken(this.EOD, null); + return tokens; + } + }]); + + return GeomPath; +}(); + +"use strict"; + +var HachureIterator = function () { + function HachureIterator(top, bottom, left, right, gap, sinAngle, cosAngle, tanAngle) { + _classCallCheck(this, HachureIterator); + + this.top = top; + this.bottom = bottom; + this.left = left; + this.right = right; + this.gap = gap; + this.sinAngle = sinAngle; + this.tanAngle = tanAngle; + + if (Math.abs(sinAngle) < 0.0001) { + this.pos = left + gap; + } else if (Math.abs(sinAngle) > 0.9999) { + this.pos = top + gap; + } else { + this.deltaX = (bottom - top) * Math.abs(tanAngle); + this.pos = left - Math.abs(this.deltaX); + this.hGap = Math.abs(gap / cosAngle); + this.sLeft = new Segment(left, bottom, left, top); + this.sRight = new Segment(right, bottom, right, top); + } + } + + _createClass(HachureIterator, [{ + key: 'getNextLine', + value: function getNextLine() { + if (Math.abs(this.sinAngle) < 0.0001) { + if (this.pos < this.right) { + var line = [this.pos, this.top, this.pos, this.bottom]; + this.pos += this.gap; + return line; + } + } else if (Math.abs(this.sinAngle) > 0.9999) { + if (this.pos < this.bottom) { + var _line = [this.left, this.pos, this.right, this.pos]; + this.pos += this.gap; + return _line; + } + } else { + var xLower = this.pos - this.deltaX / 2; + var xUpper = this.pos + this.deltaX / 2; + var yLower = this.bottom; + var yUpper = this.top; + if (this.pos < this.right + this.deltaX) { + while (xLower < this.left && xUpper < this.left || xLower > this.right && xUpper > this.right) { + this.pos += this.hGap; + xLower = this.pos - this.deltaX / 2; + xUpper = this.pos + this.deltaX / 2; + if (this.pos > this.right + this.deltaX) { + return null; + } + } + var s = new Segment(xLower, yLower, xUpper, yUpper); + if (s.compare(this.sLeft) == _RELATION_.INTERSECTS) { + xLower = s.xi; + yLower = s.yi; + } + if (s.compare(this.sRight) == _RELATION_.INTERSECTS) { + xUpper = s.xi; + yUpper = s.yi; + } + if (this.tanAngle > 0) { + xLower = this.right - (xLower - this.left); + xUpper = this.right - (xUpper - this.left); + } + var _line2 = [xLower, yLower, xUpper, yUpper]; + this.pos += this.hGap; + return _line2; + } + } + return null; + } + }]); + + return HachureIterator; +}(); + +"use strict"; + +var _RELATION_ = { + LEFT: 0, + RIGHT: 1, + INTERSECTS: 2, + AHEAD: 3, + BEHIND: 4, + SEPARATE: 5, + UNDEFINED: 6 +}; + +var Segment = function () { + function Segment(px1, py1, px2, py2) { + _classCallCheck(this, Segment); + + this.px1 = px1; + this.py1 = py1; + this.px2 = px2; + this.py2 = py2; + this.xi = Number.MAX_VALUE; + this.yi = Number.MAX_VALUE; + this.a = py2 - py1; + this.b = px1 - px2; + this.c = px2 * py1 - px1 * py2; + this._undefined = this.a == 0 && this.b == 0 && this.c == 0; + } + + _createClass(Segment, [{ + key: 'isUndefined', + value: function isUndefined() { + return this._undefined; + } + }, { + key: 'compare', + value: function compare(otherSegment) { + if (this.isUndefined() || otherSegment.isUndefined()) { + return _RELATION_.UNDEFINED; + } + var grad1 = Number.MAX_VALUE; + var grad2 = Number.MAX_VALUE; + var int1 = 0, + int2 = 0; + var a = this.a, + b = this.b, + c = this.c; + + if (Math.abs(b) > 0.00001) { + grad1 = -a / b; + int1 = -c / b; + } + if (Math.abs(otherSegment.b) > 0.00001) { + grad2 = -otherSegment.a / otherSegment.b; + int2 = -otherSegment.c / otherSegment.b; + } + + if (grad1 == Number.MAX_VALUE) { + if (grad2 == Number.MAX_VALUE) { + if (-c / a != -otherSegment.c / otherSegment.a) { + return _RELATION_.SEPARATE; + } + if (this.py1 >= Math.min(otherSegment.py1, otherSegment.py2) && this.py1 <= Math.max(otherSegment.py1, otherSegment.py2)) { + this.xi = this.px1; + this.yi = this.py1; + return _RELATION_.INTERSECTS; + } + if (this.py2 >= Math.min(otherSegment.py1, otherSegment.py2) && this.py2 <= Math.max(otherSegment.py1, otherSegment.py2)) { + this.xi = this.px2; + this.yi = this.py2; + return _RELATION_.INTERSECTS; + } + return _RELATION_.SEPARATE; + } + this.xi = this.px1; + this.yi = grad2 * this.xi + int2; + if ((this.py1 - this.yi) * (this.yi - this.py2) < -0.00001 || (otherSegment.py1 - this.yi) * (this.yi - otherSegment.py2) < -0.00001) { + return _RELATION_.SEPARATE; + } + if (Math.abs(otherSegment.a) < 0.00001) { + if ((otherSegment.px1 - this.xi) * (this.xi - otherSegment.px2) < -0.00001) { + return _RELATION_.SEPARATE; + } + return _RELATION_.INTERSECTS; + } + return _RELATION_.INTERSECTS; + } + + if (grad2 == Number.MAX_VALUE) { + this.xi = otherSegment.px1; + this.yi = grad1 * this.xi + int1; + if ((otherSegment.py1 - this.yi) * (this.yi - otherSegment.py2) < -0.00001 || (this.py1 - this.yi) * (this.yi - this.py2) < -0.00001) { + return _RELATION_.SEPARATE; + } + if (Math.abs(a) < 0.00001) { + if ((this.px1 - this.xi) * (this.xi - this.px2) < -0.00001) { + return _RELATION_.SEPARATE; + } + return _RELATION_.INTERSECTS; + } + return _RELATION_.INTERSECTS; + } + + if (grad1 == grad2) { + if (int1 != int2) { + return _RELATION_.SEPARATE; + } + if (this.px1 >= Math.min(otherSegment.px1, otherSegment.px2) && this.px1 <= Math.max(otherSegment.py1, otherSegment.py2)) { + this.xi = this.px1; + this.yi = this.py1; + return _RELATION_.INTERSECTS; + } + if (this.px2 >= Math.min(otherSegment.px1, otherSegment.px2) && this.px2 <= Math.max(otherSegment.px1, otherSegment.px2)) { + this.xi = this.px2; + this.yi = this.py2; + return _RELATION_.INTERSECTS; + } + return _RELATION_.SEPARATE; + } + + this.xi = (int2 - int1) / (grad1 - grad2); + this.yi = grad1 * this.xi + int1; + + if ((this.px1 - this.xi) * (this.xi - this.px2) < -0.00001 || (otherSegment.px1 - this.xi) * (this.xi - otherSegment.px2) < -0.00001) { + return _RELATION_.SEPARATE; + } + return _RELATION_.INTERSECTS; + } + }, { + key: 'getLength', + value: function getLength() { + return this._getLength(this.px1, this.py1, this.px2, this.py2); + } + }, { + key: '_getLength', + value: function _getLength(x1, y1, x2, y2) { + var dx = x2 - x1; + var dy = y2 - y1; + return Math.sqrt(dx * dx + dy * dy); + } + }]); + + return Segment; +}(); + +"use strict"; + +var Line = function (_Drawable4) { + _inherits(Line, _Drawable4); + + function Line(x1, y1, x2, y2) { + _classCallCheck(this, Line); + + var _this6 = _possibleConstructorReturn(this, (Line.__proto__ || Object.getPrototypeOf(Line)).call(this, ['x1', 'y1', 'x2', 'y2'])); + + _this6.x1 = x1; + _this6.x2 = x2; + _this6.y1 = y1; + _this6.y2 = y2; + return _this6; + } + + _createClass(Line, [{ + key: 'draw', + value: function draw(ctx) { + ctx.save(); + ctx.strokeStyle = this.stroke; + ctx.lineWidth = this.strokeWidth; + this.drawLine(ctx, this.x1, this.y1, this.x2, this.y2); + ctx.restore(); + } + }]); + + return Line; +}(Drawable); + +"use strict"; + +var LinearPath = function (_Drawable5) { + _inherits(LinearPath, _Drawable5); + + function LinearPath(points) { + _classCallCheck(this, LinearPath); + + var _this7 = _possibleConstructorReturn(this, (LinearPath.__proto__ || Object.getPrototypeOf(LinearPath)).call(this)); + + _this7._points = points; + return _this7; + } + + _createClass(LinearPath, [{ + key: 'setPoint', + value: function setPoint(index, x, y) { + this._points[index] = [x, y]; + if (this._canvas) { + this._canvas.requestDraw(); + } + } + }, { + key: 'getPoint', + value: function getPoint(index) { + if (index > 0 && index < this._points.length) { + return this._points[index]; + } + return null; + } + }, { + key: 'draw', + value: function draw(ctx) { + ctx.save(); + ctx.strokeStyle = this.stroke; + ctx.lineWidth = this.strokeWidth; + this.drawLinearPath(ctx, this._points, false); + ctx.restore(); + } + }]); + + return LinearPath; +}(Drawable); + +"use strict"; + +var Path = function (_Drawable6) { + _inherits(Path, _Drawable6); + + function Path(path) { + _classCallCheck(this, Path); + + var _this8 = _possibleConstructorReturn(this, (Path.__proto__ || Object.getPrototypeOf(Path)).call(this, ['path', 'numSteps'])); + + _this8.numSteps = 9; + _this8.path = path; + _this8._keys = ['C', 'c', 'Q', 'q', 'M', 'm', 'L', 'l', 'A', 'a', 'H', 'h', 'V', 'v', 'S', 's', 'T', 't', 'Z', 'z']; + return _this8; + } + + _createClass(Path, [{ + key: 'draw', + value: function draw(ctx) { + if (this.path) { + var path = (this.path || "").replace(/\n/g, " ").replace(/(-)/g, " -").replace(/(-\s)/g, "-").replace("/(\s\s)/g", " "); + + this.gp = new GeomPath(path); + var segments = this.gp.segments || []; + // console.log("Segments", segments); + + this._position = [0, 0]; + this._bezierReflectionPoint = null; + this._quadReflectionPoint = null; + this._first = null; + + if (this.fill) { + this._doFill(ctx, path); + } + + ctx.save(); + ctx.strokeStyle = this.stroke; + ctx.lineWidth = this.strokeWidth; + ctx.beginPath(); + for (var i = 0; i < segments.length; i++) { + var s = segments[i]; + this._processSegment(ctx, s, i > 0 ? segments[i - 1] : null); + } + ctx.stroke(); + ctx.restore(); + } + } + }, { + key: '_doFill', + value: function _doFill(ctx, path) { + var fillStyle = this.fillStyle || "hachure"; + switch (fillStyle) { + case "solid": + { + ctx.save(); + ctx.fillStyle = this.fill; + var p2d = new Path2D(path); + ctx.fill(p2d); + ctx.restore(); + break; + } + default: + { + var hc = this._canvas.getHiddenCanvas(); + if (hc) { + var hctx = hc.getContext("2d"); + var xc = [0, hc.width, hc.width, 0]; + var yc = [0, 0, hc.height, hc.height]; + this.hachureFillShape(hctx, xc, yc); + } + ctx.save(); + ctx.fillStyle = ctx.createPattern(hc, 'repeat'); + var _p2d = new Path2D(path); + ctx.fill(_p2d); + ctx.restore(); + break; + } + } + } + }, { + key: '_processSegment', + value: function _processSegment(ctx, seg, prevSeg) { + switch (seg.key) { + case 'M': + case 'm': + this._moveTo(seg); + break; + case 'L': + case 'l': + this._lineTo(ctx, seg); + break; + case 'H': + case 'h': + this._hLineTo(ctx, seg); + break; + case 'V': + case 'v': + this._vLineTo(ctx, seg); + break; + case 'Z': + case 'z': + this._closeShape(ctx); + break; + case 'C': + case 'c': + this._curveTo(ctx, seg); + break; + case 'S': + case 's': + this._shortCurveTo(ctx, seg, prevSeg); + break; + case 'Q': + case 'q': + this._quadCurveTo(ctx, seg); + break; + case 'T': + case 't': + this._shortQuadTo(ctx, seg, prevSeg); + break; + case 'A': + case 'a': + this._arcTo(ctx, seg); + break; + default: + break; + } + } + }, { + key: '_setPosition', + value: function _setPosition(x, y) { + this._position = [x, y]; + if (!this._first) { + this._first = [x, y]; + } + } + }, { + key: '_moveTo', + value: function _moveTo(seg) { + var delta = seg.key === 'm'; + if (seg.data.length >= 2) { + var x = +seg.data[0]; + var y = +seg.data[1]; + if (delta) { + this._setPosition(this._position[0] + x, this._position[1] + y); + } else { + this._setPosition(x, y); + } + } + } + }, { + key: '_closeShape', + value: function _closeShape(ctx) { + if (this._first) { + this.drawLine(ctx, this._position[0], this._position[1], this._first[0], this._first[1], true); + } + } + }, { + key: '_lineTo', + value: function _lineTo(ctx, seg) { + var delta = seg.key === 'l'; + if (seg.data.length >= 2) { + var x = +seg.data[0]; + var y = +seg.data[1]; + if (delta) { + x += this._position[0]; + y += this._position[1]; + } + this.drawLine(ctx, this._position[0], this._position[1], x, y, true); + this._setPosition(x, y); + } + } + }, { + key: '_hLineTo', + value: function _hLineTo(ctx, seg) { + var delta = seg.key === 'h'; + if (seg.data.length) { + var x = +seg.data[0]; + if (delta) { + x += this._position[0]; + } + this.drawLine(ctx, this._position[0], this._position[1], x, this._position[1], true); + this._setPosition(x, this._position[1]); + } + } + }, { + key: '_vLineTo', + value: function _vLineTo(ctx, seg) { + var delta = seg.key === 'v'; + if (seg.data.length) { + var y = +seg.data[0]; + if (delta) { + y += this._position[1]; + } + this.drawLine(ctx, this._position[0], this._position[1], this._position[0], y, true); + this._setPosition(this._position[0], y); + } + } + }, { + key: '_quadCurveTo', + value: function _quadCurveTo(ctx, seg) { + var delta = seg.key === 'q'; + if (seg.data.length >= 4) { + var x1 = +seg.data[0]; + var y1 = +seg.data[1]; + var x = +seg.data[2]; + var y = +seg.data[3]; + if (delta) { + x1 += this._position[0]; + x += this._position[0]; + y1 += this._position[1]; + y += this._position[1]; + } + var ro = this.maxRandomnessOffset || 0; + ctx.moveTo(this._position[0], this._position[1]); + this._drawQuadTo(ctx, x1, y1, x, y); + ctx.moveTo(this._position[0] + this.getOffset(-ro, ro), this._position[1] + this.getOffset(-ro, ro)); + var final = this._drawQuadTo(ctx, x1, y1, x, y); + x = final[0]; + y = final[1]; + this._setPosition(x, y); + this._quadReflectionPoint = [x + (x - x1), y + (y - y1)]; + } + } + }, { + key: '_curveTo', + value: function _curveTo(ctx, seg) { + var delta = seg.key === 'c'; + if (seg.data.length >= 6) { + var x1 = +seg.data[0]; + var y1 = +seg.data[1]; + var x2 = +seg.data[2]; + var y2 = +seg.data[3]; + var x = +seg.data[4]; + var y = +seg.data[5]; + if (delta) { + x1 += this._position[0]; + x2 += this._position[0]; + x += this._position[0]; + y1 += this._position[1]; + y2 += this._position[1]; + y += this._position[1]; + } + var ro = this.maxRandomnessOffset || 0; + ctx.moveTo(this._position[0], this._position[1]); + this._drawBezierTo(ctx, x1, y1, x2, y2, x, y); + ctx.moveTo(this._position[0] + this.getOffset(-ro, ro), this._position[1] + this.getOffset(-ro, ro)); + var final = this._drawBezierTo(ctx, x1, y1, x2, y2, x, y); + x = final[0]; + y = final[1]; + this._setPosition(x, y); + this._bezierReflectionPoint = [x + (x - x2), y + (y - y2)]; + } + } + }, { + key: '_shortCurveTo', + value: function _shortCurveTo(ctx, seg, prevSeg) { + var delta = seg.key === 's'; + if (seg.data.length >= 4) { + var x2 = +seg.data[0]; + var y2 = +seg.data[1]; + var x = +seg.data[2]; + var y = +seg.data[3]; + if (delta) { + x2 += this._position[0]; + x += this._position[0]; + y2 += this._position[1]; + y += this._position[1]; + } + var x1 = x2; + var y1 = y2; + var prevKey = prevSeg ? prevSeg.key : ""; + var ref = null; + if (prevKey == 'c' || prevKey == 'C' || prevKey == 's' || prevKey == 'S') { + ref = this._bezierReflectionPoint; + } + if (ref) { + x1 = ref[0]; + y1 = ref[1]; + } + ctx.moveTo(this._position[0], this._position[1]); + this._drawBezierTo(ctx, x1, y1, x2, y2, x, y); + ctx.moveTo(this._position[0], this._position[1]); + var final = this._drawBezierTo(ctx, x1, y1, x2, y2, x, y); + x = final[0]; + y = final[1]; + this._setPosition(x, y); + this._bezierReflectionPoint = [x + (x - x2), y + (y - y2)]; + } + } + }, { + key: '_shortQuadTo', + value: function _shortQuadTo(ctx, seg, prevSeg) { + var delta = seg.key === 't'; + if (seg.data.length >= 2) { + var x = +seg.data[0]; + var y = +seg.data[1]; + if (delta) { + x += this._position[0]; + y += this._position[1]; + } + var x1 = x; + var y1 = y; + var prevKey = prevSeg ? prevSeg.key : ""; + var ref = null; + if (prevKey == 'q' || prevKey == 'Q' || prevKey == 't' || prevKey == 'T') { + ref = this._quadReflectionPoint; + } + if (ref) { + x1 = ref[0]; + y1 = ref[1]; + } + ctx.moveTo(this._position[0], this._position[1]); + this._drawQuadTo(ctx, x1, y1, x, y); + ctx.moveTo(this._position[0], this._position[1]); + var final = this._drawQuadTo(ctx, x1, y1, x, y); + x = final[0]; + y = final[1]; + this._setPosition(x, y); + this._quadReflectionPoint = [x + (x - x1), y + (y - y1)]; + } + } + }, { + key: '_arcTo', + value: function _arcTo(ctx, seg) { + var delta = seg.key === 'a'; + if (seg.data.length >= 7) { + var rx = +seg.data[0]; + var ry = +seg.data[1]; + var angle = +seg.data[2]; + var largeArcFlag = +seg.data[3]; + var sweepFlag = +seg.data[4]; + var x = +seg.data[5]; + var y = +seg.data[6]; + if (delta) { + x += this._position[0]; + y += this._position[1]; + } + + if (x == this._position[0] && y == this._position[1]) { + return; + } + if (rx == 0 || ry == 0) { + this.drawLine(ctx, this._position[0], this._position[1], x, y, true); + this._setPosition(x, y); + } else { + var final; + for (var i = 0; i < 2; i++) { + ctx.moveTo(this._position[0], this._position[1]); + var arcConverter = new ArcConverter([this._position[0], this._position[1]], [x, y], [rx, ry], angle, largeArcFlag ? true : false, sweepFlag ? true : false); + var segment = arcConverter.getNextSegment(); + while (segment) { + final = this._drawBezierTo(ctx, segment.cp1[0], segment.cp1[1], segment.cp2[0], segment.cp2[1], segment.to[0], segment.to[1]); + segment = arcConverter.getNextSegment(); + } + } + if (final) { + x = final[0]; + y = final[1]; + } + this._setPosition(x, y); + } + } + } + + // _parse(path, index, currentWord = "", current = {}, segments) { + // if (index >= path.length) { + // if (current && current.key) { + // if (currentWord) { + // current.data.push(currentWord); + // } + // segments.push(current); + // currentWord = ""; + // current = {}; + // } + // return; + // } + // current.data = current.data || []; + // var c = path.charAt(index); + // if ((!c) || (c == ' ') || (c == ',')) { + // if (currentWord) { + // current.data.push(currentWord); + // currentWord = ""; + // } + // } else { + // if (this._keys.indexOf(c) >= 0) { + // if (current && current.key) { + // if (currentWord) { + // current.data.push(currentWord); + // } + // segments.push(current); + // currentWord = ""; + // current = {}; + // } + // current.key = c; + // current.data = []; + // } else { + // currentWord += c; + // } + // } + // this._parse(path, index + 1, currentWord, current, segments); + // } + + }]); + + return Path; +}(Drawable); + +"use strict"; + +var Polygon = function (_Drawable7) { + _inherits(Polygon, _Drawable7); + + function Polygon(points) { + _classCallCheck(this, Polygon); + + var _this9 = _possibleConstructorReturn(this, (Polygon.__proto__ || Object.getPrototypeOf(Polygon)).call(this)); + + _this9._points = points; + return _this9; + } + + _createClass(Polygon, [{ + key: 'setPoint', + value: function setPoint(index, x, y) { + this._points[index] = [x, y]; + if (this._canvas) { + this._canvas.requestDraw(); + } + } + }, { + key: 'getPoint', + value: function getPoint(index) { + if (index > 0 && index < this._points.length) { + return this._points[index]; + } + return null; + } + }, { + key: 'draw', + value: function draw(ctx) { + if (this.fill) { + this._doFill(ctx, this._points); + } + ctx.save(); + ctx.strokeStyle = this.stroke; + ctx.lineWidth = this.strokeWidth; + this.drawLinearPath(ctx, this._points, true); + ctx.restore(); + } + }, { + key: '_doFill', + value: function _doFill(ctx, points) { + var _this10 = this; + + var fillStyle = this.fillStyle || "hachure"; + switch (fillStyle) { + case "solid": + { + ctx.save(); + ctx.fillStyle = this.fill; + var o = this.maxRandomnessOffset || 0; + var len = points.length; + if (len > 2) { + ctx.beginPath(); + ctx.moveTo(points[0][0] + this.getOffset(-o, o), points[0][1] + this.getOffset(-o, o)); + for (var i = 1; i < len; i++) { + ctx.lineTo(points[i][0] + this.getOffset(-o, o), points[i][1] + this.getOffset(-o, o)); + } + ctx.fill(); + } + ctx.restore(); + break; + } + default: + { + var _ret2 = function () { + var xc = []; + var yc = []; + points.forEach(function (p) { + xc.push(p[0]); + yc.push(p[1]); + }); + _this10.hachureFillShape(ctx, xc, yc); + return 'break'; + }(); + + if (_ret2 === 'break') break; + } + } + } + }]); + + return Polygon; +}(Drawable); + +"use strict"; + +var Rectangle = function (_Drawable8) { + _inherits(Rectangle, _Drawable8); + + function Rectangle(x, y, width, height) { + _classCallCheck(this, Rectangle); + + var _this11 = _possibleConstructorReturn(this, (Rectangle.__proto__ || Object.getPrototypeOf(Rectangle)).call(this, ['x', 'y', 'width', 'height'])); + + _this11.x = x; + _this11.y = y; + _this11.width = width; + _this11.height = height; + return _this11; + } + + _createClass(Rectangle, [{ + key: 'draw', + value: function draw(ctx) { + var left = this.x; + var right = this.x + this.width; + var top = this.y; + var bottom = this.y + this.height; + + if (this.fill) { + this._doFill(ctx, left, right, top, bottom); + } + + ctx.save(); + ctx.strokeStyle = this.stroke; + ctx.lineWidth = this.strokeWidth; + this.drawLine(ctx, left, top, right, top); + this.drawLine(ctx, right, top, right, bottom); + this.drawLine(ctx, right, bottom, left, bottom); + this.drawLine(ctx, left, bottom, left, top); + ctx.restore(); + } + }, { + key: '_doFill', + value: function _doFill(ctx, left, right, top, bottom) { + var fillStyle = this.fillStyle || "hachure"; + switch (fillStyle) { + case "solid": + { + ctx.save(); + ctx.fillStyle = this.fill; + var o = this.maxRandomnessOffset || 0; + var points = [[left + this.getOffset(-o, o), top + this.getOffset(-o, o)], [right + this.getOffset(-o, o), top + this.getOffset(-o, o)], [right + this.getOffset(-o, o), bottom + this.getOffset(-o, o)], [left + this.getOffset(-o, o), bottom + this.getOffset(-o, o)]]; + ctx.beginPath(); + ctx.moveTo(points[0][0], points[0][1]); + ctx.lineTo(points[1][0], points[1][1]); + ctx.lineTo(points[2][0], points[2][1]); + ctx.lineTo(points[3][0], points[3][1]); + ctx.fill(); + ctx.restore(); + break; + } + default: + { + var xc = [left, right, right, left]; + var yc = [top, top, bottom, bottom]; + this.hachureFillShape(ctx, xc, yc); + break; + } + } + } + }]); + + return Rectangle; +}(Drawable); + +"use strict"; + +var RoughCanvas = function () { + function RoughCanvas(canvas, width, height) { + _classCallCheck(this, RoughCanvas); + + this._canvas = canvas; + this.width = width || canvas.width; + this.height = height || canvas.height; + canvas.width = this.width; + canvas.height = this.height; + this._objects = []; + this._drawRequested = false; + + this.roughness = 1; + this.bowing = 1; + + this.stroke = "#000"; + this.strokeWidth = 1; + + this.fill = null; + this.fillStyle = "hachure"; + this.fillWeight = -1; + this.hachureAngle = -41; + this.hachureGap = -1; + + this.maxRandomnessOffset = 2; + } + + _createClass(RoughCanvas, [{ + key: 'add', + value: function add(drawable) { + if (drawable instanceof Drawable) { + if (drawable.attached) { + return; + } + this._objects.push(drawable); + drawable.attach(this, this._objects.length - 1); + this.requestDraw(); + } else { + console.warn("Ignoring canvas add - the object is not drawable", drawable); + } + } + }, { + key: 'remove', + value: function remove(drawable) { + if (drawable instanceof Drawable) { + if (drawable.attached) { + this._objects.splice(drawable.z, 1); + drawable.detach(); + this.requestDraw(); + } + } else { + console.warn("Ignoring canvas remove - the object is not drawable", drawable); + } + } + }, { + key: 'clear', + value: function clear() { + if (this._objects && this._objects.length) { + this._objects.forEach(function (d) { + d.detach(); + }); + } + this._objects = []; + this.requestDraw(); + } + }, { + key: 'requestDraw', + value: function requestDraw() { + var _this12 = this; + + if (!this._drawRequested) { + this._drawRequested = true; + window.requestAnimationFrame(function () { + _this12._drawRequested = false; + _this12._draw(); + }); + } + } + }, { + key: '_draw', + value: function _draw() { + var ctx = this._canvas.getContext("2d"); + ctx.clearRect(0, 0, this.width, this.height); + for (var i = 0; i < this._objects.length; i++) { + try { + this._objects[i].draw(ctx); + } catch (ex) { + console.error(ex); + } + } + } + }, { + key: 'getHiddenCanvas', + value: function getHiddenCanvas() { + if (!this._hiddenCanvas) { + var div = document.createElement("div"); + div.setAttribute("id", "roughHiddenCanvas"); + div.style.overflow = "hidden"; + div.style.position = "absolute"; + div.style.left = "-1px"; + div.style.top = "-1px"; + div.style.width = "0px"; + div.style.height = "0px"; + div.style.opacity = 0; + div.style.pointerEvents = "none"; + document.body.appendChild(div); + this._hiddenCanvas = document.createElement("canvas"); + div.appendChild(this._hiddenCanvas); + } + var hc = this._hiddenCanvas; + hc.width = this.width; + hc.height = this.height; + var ctx = hc.getContext("2d"); + ctx.clearRect(0, 0, this.width, this.height); + return hc; + } + }, { + key: 'arc', + value: function arc(x, y, width, height, start, stop, closed) { + var d = new Arc(x, y, width, height, start, stop, closed); + this.add(d); + return d; + } + }, { + key: 'circle', + value: function circle(x, y, radius) { + var d = new Circle(x, y, radius); + this.add(d); + return d; + } + }, { + key: 'ellipse', + value: function ellipse(x, y, width, height) { + var d = new Ellipse(x, y, width, height); + this.add(d); + return d; + } + }, { + key: 'curve', + value: function curve(points) { + var d = new Curve(points); + this.add(d); + return d; + } + }, { + key: 'line', + value: function line(x1, y1, x2, y2) { + var d = new Line(x1, y1, x2, y2); + this.add(d); + return d; + } + }, { + key: 'rectangle', + value: function rectangle(x, y, width, height) { + var d = new Rectangle(x, y, width, height); + this.add(d); + return d; + } + }, { + key: 'linearPath', + value: function linearPath(points) { + var d = new LinearPath(points); + this.add(d); + return d; + } + }, { + key: 'polygon', + value: function polygon(points) { + var d = new Polygon(points); + this.add(d); + return d; + } + }, { + key: 'path', + value: function path(d) { + var p = new Path(d); + this.add(p); + return p; + } + }]); + + return RoughCanvas; +}(); +//# sourceMappingURL=rough.js.map diff --git a/docs/builds/rough.min.js b/docs/builds/rough.min.js new file mode 100644 index 0000000..5a3cbaa --- /dev/null +++ b/docs/builds/rough.min.js @@ -0,0 +1,3 @@ +"use strict";function _possibleConstructorReturn(a,b){if(!a)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!b||"object"!=typeof b&&"function"!=typeof b?a:b}function _inherits(a,b){if("function"!=typeof b&&null!==b)throw new TypeError("Super expression must either be null or a function, not "+typeof b);a.prototype=Object.create(b&&b.prototype,{constructor:{value:a,enumerable:!1,writable:!0,configurable:!0}}),b&&(Object.setPrototypeOf?Object.setPrototypeOf(a,b):a.__proto__=b)}function _classCallCheck(a,b){if(!(a instanceof b))throw new TypeError("Cannot call a class as a function")}function GeomToken(a,b){arguments.length>0&&this.init(a,b)}var _createClass=function(){function a(a,b){for(var c=0;c2&&void 0!==arguments[2])||arguments[2];this._fields[a]=b,c&&(this._dirty=!0,this._canvas&&this._canvas.requestDraw())}},{key:"draw",value:function(a){console.log("Draw not implemented.",a)}},{key:"getOffset",value:function(a,b){return this.roughness*(Math.random()*(b-a)+a)}},{key:"drawLine",value:function(a,b,c,d,e,f){var g=Math.pow(b-d,2)+Math.pow(b-d,2),h=this.maxRandomnessOffset||0;h*h*100>g&&(h=Math.sqrt(g)/10);var i=h/2,j=.2+.2*Math.random(),k=this.bowing*this.maxRandomnessOffset*(e-c)/200,l=this.bowing*this.maxRandomnessOffset*(b-d)/200;k=this.getOffset(-k,k),l=this.getOffset(-l,l),f||a.beginPath(),a.moveTo(b+this.getOffset(-h,h),c+this.getOffset(-h,h)),a.bezierCurveTo(k+b+(d-b)*j+this.getOffset(-h,h),l+c+(e-c)*j+this.getOffset(-h,h),k+b+2*(d-b)*j+this.getOffset(-h,h),l+c+2*(e-c)*j+this.getOffset(-h,h),d+this.getOffset(-h,h),e+this.getOffset(-h,h)),f||a.stroke(),f||a.beginPath(),a.moveTo(b+this.getOffset(-i,i),c+this.getOffset(-i,i)),a.bezierCurveTo(k+b+(d-b)*j+this.getOffset(-i,i),l+c+(e-c)*j+this.getOffset(-i,i),k+b+2*(d-b)*j+this.getOffset(-i,i),l+c+2*(e-c)*j+this.getOffset(-i,i),d+this.getOffset(-i,i),e+this.getOffset(-i,i)),f||a.stroke()}},{key:"drawLinearPath",value:function(a,b,c){var d=b.length;if(d>2){a.beginPath();for(var e=0;e3){var h=[],i=1-this.curveTightness;for(c||a.beginPath(),a.moveTo(b[1][0],b[1][1]),f=1;f+2=0?this._roughness:this._canvas?this._canvas.roughness:this._roughness}},{key:"bowing",set:function(a){this._bowing=a,this._canvas&&this._canvas.requestDraw()},get:function(){return"number"==typeof this._bowing&&this._bowing>=0?this._bowing:this._canvas?this._canvas.bowing:this._bowing}},{key:"stroke",set:function(a){this._stroke=a,this._canvas&&this._canvas.requestDraw()},get:function(){return"string"==typeof this._stroke&&this._stroke?this._stroke:this._canvas?this._canvas.stroke:this._stroke}},{key:"strokeWidth",set:function(a){this._strokeWidth=a,this._canvas&&this._canvas.requestDraw()},get:function(){return"number"==typeof this._strokeWidth&&this._strokeWidth>=0?this._strokeWidth:this._canvas?this._canvas.strokeWidth:this._strokeWidth}},{key:"maxRandomnessOffset",set:function(a){this._maxRandomnessOffset=a,this._canvas&&this._canvas.requestDraw()},get:function(){return"number"==typeof this._maxRandomnessOffset&&this._maxRandomnessOffset>=0?this._maxRandomnessOffset:this._canvas?this._canvas.maxRandomnessOffset:this._maxRandomnessOffset}},{key:"curveTightness",set:function(a){this._curveTightness=Math.max(Math.min(a,1),0),this._canvas&&this._canvas.requestDraw()},get:function(){return"number"==typeof this._curveTightness&&this._curveTightness>=0?this._curveTightness:this._canvas?this._canvas.curveTightness||0:this._curveTightness}},{key:"fill",set:function(a){this._fill=a,this._canvas&&this._canvas.requestDraw()},get:function(){return"string"==typeof this._fill&&this._fill?this._fill:this._canvas?this._canvas.fill:this._fill}},{key:"fillStyle",set:function(a){this._fillStyle=a,this._canvas&&this._canvas.requestDraw()},get:function(){return"string"==typeof this._fillStyle&&this._fillStyle?this._fillStyle:this._canvas?this._canvas.fillStyle:this._fillStyle}},{key:"fillWeight",set:function(a){this._fillWeight=a,this._canvas&&this._canvas.requestDraw()},get:function(){return"number"==typeof this._fillWeight&&this._fillWeight?this._fillWeight:this._canvas?this._canvas.fillWeight:this._fillWeight}},{key:"hachureAngle",set:function(a){this._hachureAngle=a,this._canvas&&this._canvas.requestDraw()},get:function(){return"number"==typeof this._hachureAngle&&this._hachureAngle>=0?this._hachureAngle:this._canvas?this._canvas.hachureAngle:this._hachureAngle}},{key:"hachureGap",set:function(a){this._hachureGap=a,this._canvas&&this._canvas.requestDraw()},get:function(){return"number"==typeof this._hachureGap&&this._hachureGap>=0?this._hachureGap:this._canvas?this._canvas.hachureGap:this._hachureGap}}]),a}(),Ellipse=function(a){function b(a,c,d,e){_classCallCheck(this,b);var f=_possibleConstructorReturn(this,(b.__proto__||Object.getPrototypeOf(b)).call(this,["x","y","width","height","numSteps"]));return f.x=a,f.y=c,f.width=d,f.height=e||d,f.numSteps=9,f}return _inherits(b,a),_createClass(b,[{key:"draw",value:function(a){this.ellipseInc=2*Math.PI/this.numSteps;var b=Math.abs(this.width/2),c=Math.abs(this.height/2);b+=this.getOffset(.05*-b,.05*b),c+=this.getOffset(.05*-c,.05*c),this.fill&&this._doFill(a,b,c),a.save(),a.strokeStyle=this.stroke,a.lineWidth=this.strokeWidth,this._ellipse(a,this.x,this.y,b,c,1,this.ellipseInc*this.getOffset(.1,this.getOffset(.4,1))),this._ellipse(a,this.x,this.y,b,c,1.5,0),a.restore()}},{key:"_ellipse",value:function(a,b,c,d,e,f,g,h){var i=this.getOffset(-.5,.5)-Math.PI/2,j=[];j.push([this.getOffset(-f,f)+b+.9*d*Math.cos(i-this.ellipseInc),this.getOffset(-f,f)+c+.9*e*Math.sin(i-this.ellipseInc)]);for(var k=i;k<2*Math.PI+i-.01;k+=this.ellipseInc)j.push([this.getOffset(-f,f)+b+d*Math.cos(k),this.getOffset(-f,f)+c+e*Math.sin(k)]);j.push([this.getOffset(-f,f)+b+d*Math.cos(i+2*Math.PI+.5*g),this.getOffset(-f,f)+c+e*Math.sin(i+2*Math.PI+.5*g)]),j.push([this.getOffset(-f,f)+b+.98*d*Math.cos(i+g),this.getOffset(-f,f)+c+.98*e*Math.sin(i+g)]),j.push([this.getOffset(-f,f)+b+.9*d*Math.cos(i+.5*g),this.getOffset(-f,f)+c+.9*e*Math.sin(i+.5*g)]),this.drawCurve(a,j,h)}},{key:"_doFill",value:function(a,b,c){var d=this.fillStyle||"hachure";switch(d){case"solid":a.save(),a.fillStyle=this.fill,a.strokeStyle=null,a.beginPath(),this._ellipse(a,this.x,this.y,b,c,1,this.ellipseInc*this.getOffset(.1,this.getOffset(.4,1)),!0),a.fill(),a.restore();break;default:var e=this.hachureAngle,f=this.hachureGap;f<=0&&(f=4*this.strokeWidth);var g=this.fillWeight;g<0&&(g=this.strokeWidth/2);var h=Math.PI/180,i=e%180*h,j=Math.tan(i),k=this.x,l=this.y,m=c/b,n=Math.sqrt(m*j*m*j+1),o=m*j/n,p=1/n,q=f/(b*c/Math.sqrt(c*p*(c*p)+b*o*(b*o))/b),r=Math.sqrt(b*b-(k-b+q)*(k-b+q));a.save(),a.strokeStyle=this.fill,a.lineWidth=g;for(var s=k-b+q;s2*Math.PI&&(f=0,g=2*Math.PI);var h=2*Math.PI/this.numSteps,i=Math.min(h/2,(g-f)/2),j=[];j.push([b+d*Math.cos(f),c+e*Math.sin(f)]);for(var k=f;k<=g;k+=i)j.push([b+d*Math.cos(k),c+e*Math.sin(k)]);if(j.push([b+d*Math.cos(g),c+e*Math.sin(g)]),j.push([b+d*Math.cos(g),c+e*Math.sin(g)]),this.fill&&this.closed&&this._doFill(a,j,[b,c]),a.save(),a.strokeStyle=this.stroke,a.lineWidth=this.strokeWidth,this.drawCurve(a,j),this.closed){var l=j.length-1;this.drawLine(a,j[0][0],j[0][1],b,c),this.drawLine(a,j[l][0],j[l][1],b,c)}a.restore()}},{key:"_doFill",value:function(a,b,c){var d=this,e=this.fillStyle||"hachure";switch(e){case"solid":a.save(),a.fillStyle=this.fill,a.beginPath(),this.drawCurve(a,b,!0,!0,c),a.fill(),a.restore();break;default:var f,g,h=function(){for(var b=d.x,c=d.y,e=d.start,h=d.stop,i=Math.abs(d.width/2),j=Math.abs(d.height/2);e<0;)e+=2*Math.PI,h+=2*Math.PI;h-e>2*Math.PI&&(e=0,h=2*Math.PI);var k=(h-e)/d.numSteps;for(f=[],f.push([b,c]),f.push([b+i*Math.cos(e),c+j*Math.sin(e)]),g=e;g<=h;g+=k)f.push([b+i*Math.cos(g),c+j*Math.sin(g)]);f.push([b+i*Math.cos(h),c+j*Math.sin(h)]);var l=[],m=[];return f.forEach(function(a){l.push(a[0]),m.push(a[1])}),d.hachureFillShape(a,l,m),"break"}();if("break"===h)break}}}]),b}(Drawable),Circle=function(a){function b(a,c,d){return _classCallCheck(this,b),_possibleConstructorReturn(this,(b.__proto__||Object.getPrototypeOf(b)).call(this,a,c,2*d))}return _inherits(b,a),_createClass(b,[{key:"radius",get:function(){return this.width/2},set:function(a){this.width=2*a,this.height=2*a}}]),b}(Ellipse),Curve=function(a){function b(a){_classCallCheck(this,b);var c=_possibleConstructorReturn(this,(b.__proto__||Object.getPrototypeOf(b)).call(this));return c._points=a,c}return _inherits(b,a),_createClass(b,[{key:"setPoint",value:function(a,b,c){this._points[a]=[b,c],this._canvas&&this._canvas.requestDraw()}},{key:"getPoint",value:function(a){return a>0&&a0?p-=2*Math.PI:g&&p<0&&(p+=2*Math.PI),this._numSegs=Math.ceil(Math.abs(p/(Math.PI/2))),this._delta=p/this._numSegs,this._T=8/3*Math.sin(this._delta/4)*Math.sin(this._delta/4)/Math.sin(this._delta/2),this._from=b}}return _createClass(a,[{key:"getNextSegment",value:function(){var a,b,c;if(this._segIndex==this._numSegs)return null;var d=Math.cos(this._theta),e=Math.sin(this._theta),f=this._theta+this._delta,g=Math.cos(f),h=Math.sin(f);return c=[this._cosPhi*this._rx*g-this._sinPhi*this._ry*h+this._C[0],this._sinPhi*this._rx*g+this._cosPhi*this._ry*h+this._C[1]],a=[this._from[0]+this._T*(-this._cosPhi*this._rx*e-this._sinPhi*this._ry*d),this._from[1]+this._T*(-this._sinPhi*this._rx*e+this._cosPhi*this._ry*d)],b=[c[0]+this._T*(this._cosPhi*this._rx*h+this._sinPhi*this._ry*g),c[1]+this._T*(this._sinPhi*this._rx*h-this._cosPhi*this._ry*g)],this._theta=f,this._from=[c[0],c[1]],this._segIndex++,{cp1:a,cp2:b,to:c}}},{key:"calculateVectorAngle",value:function(a,b,c,d){var e=Math.atan2(b,a),f=Math.atan2(d,c);return f>=e?f-e:2*Math.PI-(e-f)}}]),a}();GeomToken.prototype.init=function(a,b){this.type=a,this.text=b},GeomToken.prototype.typeis=function(a){return this.type==a};var GeomPath=function(){function a(b){_classCallCheck(this,a),this.PARAMS={A:["rx","ry","x-axis-rotation","large-arc-flag","sweep-flag","x","y"],a:["rx","ry","x-axis-rotation","large-arc-flag","sweep-flag","x","y"],C:["x1","y1","x2","y2","x","y"],c:["x1","y1","x2","y2","x","y"],H:["x"],h:["x"],L:["x","y"],l:["x","y"],M:["x","y"],m:["x","y"],Q:["x1","y1","x","y"],q:["x1","y1","x","y"],S:["x2","y2","x","y"],s:["x2","y2","x","y"],T:["x","y"],t:["x","y"],V:["y"],v:["y"],Z:[],z:[]},this.COMMAND=0,this.NUMBER=1,this.EOD=2,this.segments=[],this.d=b||"",this.parseData(b)}return _createClass(a,[{key:"parseData",value:function(a){var b=this.tokenize(a),c=0,d=b[c],e="BOD";for(this.segments=new Array;!d.typeis(this.EOD);){var f,g=new Array;if("BOD"==e){if("M"!=d.text&&"m"!=d.text)return void console.error("Path data must begin with a MoveTo command");c++,f=this.PARAMS[d.text].length,e=d.text}else d.typeis(this.NUMBER)?f=this.PARAMS[e].length:(c++,f=this.PARAMS[d.text].length,e=d.text);if(c+f.9999?this.pos=b+f:(this.deltaX=(c-b)*Math.abs(i),this.pos=d-Math.abs(this.deltaX),this.hGap=Math.abs(f/h),this.sLeft=new Segment(d,c,d,b),this.sRight=new Segment(e,c,e,b))}return _createClass(a,[{key:"getNextLine",value:function(){if(Math.abs(this.sinAngle)<1e-4){if(this.pos.9999){if(this.posthis.right&&d>this.right;)if(this.pos+=this.hGap,c=this.pos-this.deltaX/2,d=this.pos+this.deltaX/2,this.pos>this.right+this.deltaX)return null;var g=new Segment(c,e,d,f);g.compare(this.sLeft)==_RELATION_.INTERSECTS&&(c=g.xi,e=g.yi),g.compare(this.sRight)==_RELATION_.INTERSECTS&&(d=g.xi,f=g.yi),this.tanAngle>0&&(c=this.right-(c-this.left),d=this.right-(d-this.left));var h=[c,e,d,f];return this.pos+=this.hGap,h}}return null}}]),a}(),_RELATION_={LEFT:0,RIGHT:1,INTERSECTS:2,AHEAD:3,BEHIND:4,SEPARATE:5,UNDEFINED:6},Segment=function(){function a(b,c,d,e){_classCallCheck(this,a),this.px1=b,this.py1=c,this.px2=d,this.py2=e,this.xi=Number.MAX_VALUE,this.yi=Number.MAX_VALUE,this.a=e-c,this.b=b-d,this.c=d*c-b*e,this._undefined=0==this.a&&0==this.b&&0==this.c}return _createClass(a,[{key:"isUndefined",value:function(){return this._undefined}},{key:"compare",value:function(a){if(this.isUndefined()||a.isUndefined())return _RELATION_.UNDEFINED;var b=Number.MAX_VALUE,c=Number.MAX_VALUE,d=0,e=0,f=this.a,g=this.b,h=this.c;return Math.abs(g)>1e-5&&(b=-f/g,d=-h/g),Math.abs(a.b)>1e-5&&(c=-a.a/a.b,e=-a.c/a.b),b==Number.MAX_VALUE?c==Number.MAX_VALUE?-h/f!=-a.c/a.a?_RELATION_.SEPARATE:this.py1>=Math.min(a.py1,a.py2)&&this.py1<=Math.max(a.py1,a.py2)?(this.xi=this.px1,this.yi=this.py1,_RELATION_.INTERSECTS):this.py2>=Math.min(a.py1,a.py2)&&this.py2<=Math.max(a.py1,a.py2)?(this.xi=this.px2,this.yi=this.py2,_RELATION_.INTERSECTS):_RELATION_.SEPARATE:(this.xi=this.px1,this.yi=c*this.xi+e,(this.py1-this.yi)*(this.yi-this.py2)<-1e-5||(a.py1-this.yi)*(this.yi-a.py2)<-1e-5?_RELATION_.SEPARATE:Math.abs(a.a)<1e-5&&(a.px1-this.xi)*(this.xi-a.px2)<-1e-5?_RELATION_.SEPARATE:_RELATION_.INTERSECTS):c==Number.MAX_VALUE?(this.xi=a.px1,this.yi=b*this.xi+d,(a.py1-this.yi)*(this.yi-a.py2)<-1e-5||(this.py1-this.yi)*(this.yi-this.py2)<-1e-5?_RELATION_.SEPARATE:Math.abs(f)<1e-5&&(this.px1-this.xi)*(this.xi-this.px2)<-1e-5?_RELATION_.SEPARATE:_RELATION_.INTERSECTS):b==c?d!=e?_RELATION_.SEPARATE:this.px1>=Math.min(a.px1,a.px2)&&this.px1<=Math.max(a.py1,a.py2)?(this.xi=this.px1,this.yi=this.py1,_RELATION_.INTERSECTS):this.px2>=Math.min(a.px1,a.px2)&&this.px2<=Math.max(a.px1,a.px2)?(this.xi=this.px2,this.yi=this.py2,_RELATION_.INTERSECTS):_RELATION_.SEPARATE:(this.xi=(e-d)/(b-c),this.yi=b*this.xi+d,(this.px1-this.xi)*(this.xi-this.px2)<-1e-5||(a.px1-this.xi)*(this.xi-a.px2)<-1e-5?_RELATION_.SEPARATE:_RELATION_.INTERSECTS)}},{key:"getLength",value:function(){return this._getLength(this.px1,this.py1,this.px2,this.py2)}},{key:"_getLength",value:function(a,b,c,d){var e=c-a,f=d-b;return Math.sqrt(e*e+f*f)}}]),a}(),Line=function(a){function b(a,c,d,e){_classCallCheck(this,b);var f=_possibleConstructorReturn(this,(b.__proto__||Object.getPrototypeOf(b)).call(this,["x1","y1","x2","y2"]));return f.x1=a,f.x2=d,f.y1=c,f.y2=e,f}return _inherits(b,a),_createClass(b,[{key:"draw",value:function(a){a.save(),a.strokeStyle=this.stroke,a.lineWidth=this.strokeWidth,this.drawLine(a,this.x1,this.y1,this.x2,this.y2),a.restore()}}]),b}(Drawable),LinearPath=function(a){function b(a){_classCallCheck(this,b);var c=_possibleConstructorReturn(this,(b.__proto__||Object.getPrototypeOf(b)).call(this));return c._points=a,c}return _inherits(b,a),_createClass(b,[{key:"setPoint",value:function(a,b,c){this._points[a]=[b,c],this._canvas&&this._canvas.requestDraw()}},{key:"getPoint",value:function(a){return a>0&&a0?c[d-1]:null)}a.stroke(),a.restore()}}},{key:"_doFill",value:function(a,b){var c=this.fillStyle||"hachure";switch(c){case"solid":a.save(),a.fillStyle=this.fill;var d=new Path2D(b);a.fill(d),a.restore();break;default:var e=this._canvas.getHiddenCanvas();if(e){var f=e.getContext("2d"),g=[0,e.width,e.width,0],h=[0,0,e.height,e.height];this.hachureFillShape(f,g,h)}a.save(),a.fillStyle=a.createPattern(e,"repeat");var i=new Path2D(b);a.fill(i),a.restore()}}},{key:"_processSegment",value:function(a,b,c){switch(b.key){case"M":case"m":this._moveTo(b);break;case"L":case"l":this._lineTo(a,b);break;case"H":case"h":this._hLineTo(a,b);break;case"V":case"v":this._vLineTo(a,b);break;case"Z":case"z":this._closeShape(a);break;case"C":case"c":this._curveTo(a,b);break;case"S":case"s":this._shortCurveTo(a,b,c);break;case"Q":case"q":this._quadCurveTo(a,b);break;case"T":case"t":this._shortQuadTo(a,b,c);break;case"A":case"a":this._arcTo(a,b)}}},{key:"_setPosition",value:function(a,b){this._position=[a,b],this._first||(this._first=[a,b])}},{key:"_moveTo",value:function(a){var b="m"===a.key;if(a.data.length>=2){var c=+a.data[0],d=+a.data[1];b?this._setPosition(this._position[0]+c,this._position[1]+d):this._setPosition(c,d)}}},{key:"_closeShape",value:function(a){this._first&&this.drawLine(a,this._position[0],this._position[1],this._first[0],this._first[1],!0)}},{key:"_lineTo",value:function(a,b){var c="l"===b.key;if(b.data.length>=2){var d=+b.data[0],e=+b.data[1];c&&(d+=this._position[0],e+=this._position[1]),this.drawLine(a,this._position[0],this._position[1],d,e,!0),this._setPosition(d,e)}}},{key:"_hLineTo",value:function(a,b){var c="h"===b.key;if(b.data.length){var d=+b.data[0];c&&(d+=this._position[0]),this.drawLine(a,this._position[0],this._position[1],d,this._position[1],!0),this._setPosition(d,this._position[1])}}},{key:"_vLineTo",value:function(a,b){var c="v"===b.key;if(b.data.length){var d=+b.data[0];c&&(d+=this._position[1]),this.drawLine(a,this._position[0],this._position[1],this._position[0],d,!0),this._setPosition(this._position[0],d)}}},{key:"_quadCurveTo",value:function(a,b){var c="q"===b.key;if(b.data.length>=4){var d=+b.data[0],e=+b.data[1],f=+b.data[2],g=+b.data[3];c&&(d+=this._position[0],f+=this._position[0],e+=this._position[1],g+=this._position[1]);var h=this.maxRandomnessOffset||0;a.moveTo(this._position[0],this._position[1]),this._drawQuadTo(a,d,e,f,g),a.moveTo(this._position[0]+this.getOffset(-h,h),this._position[1]+this.getOffset(-h,h));var i=this._drawQuadTo(a,d,e,f,g);f=i[0],g=i[1],this._setPosition(f,g),this._quadReflectionPoint=[f+(f-d),g+(g-e)]}}},{key:"_curveTo",value:function(a,b){var c="c"===b.key;if(b.data.length>=6){var d=+b.data[0],e=+b.data[1],f=+b.data[2],g=+b.data[3],h=+b.data[4],i=+b.data[5];c&&(d+=this._position[0],f+=this._position[0],h+=this._position[0],e+=this._position[1],g+=this._position[1],i+=this._position[1]);var j=this.maxRandomnessOffset||0;a.moveTo(this._position[0],this._position[1]),this._drawBezierTo(a,d,e,f,g,h,i),a.moveTo(this._position[0]+this.getOffset(-j,j),this._position[1]+this.getOffset(-j,j));var k=this._drawBezierTo(a,d,e,f,g,h,i);h=k[0],i=k[1],this._setPosition(h,i),this._bezierReflectionPoint=[h+(h-f),i+(i-g)]}}},{key:"_shortCurveTo",value:function(a,b,c){var d="s"===b.key;if(b.data.length>=4){var e=+b.data[0],f=+b.data[1],g=+b.data[2],h=+b.data[3];d&&(e+=this._position[0],g+=this._position[0],f+=this._position[1],h+=this._position[1]);var i=e,j=f,k=c?c.key:"",l=null;"c"!=k&&"C"!=k&&"s"!=k&&"S"!=k||(l=this._bezierReflectionPoint),l&&(i=l[0],j=l[1]),a.moveTo(this._position[0],this._position[1]),this._drawBezierTo(a,i,j,e,f,g,h),a.moveTo(this._position[0],this._position[1]);var m=this._drawBezierTo(a,i,j,e,f,g,h);g=m[0],h=m[1],this._setPosition(g,h),this._bezierReflectionPoint=[g+(g-e),h+(h-f)]}}},{key:"_shortQuadTo",value:function(a,b,c){var d="t"===b.key;if(b.data.length>=2){var e=+b.data[0],f=+b.data[1];d&&(e+=this._position[0],f+=this._position[1]);var g=e,h=f,i=c?c.key:"",j=null;"q"!=i&&"Q"!=i&&"t"!=i&&"T"!=i||(j=this._quadReflectionPoint),j&&(g=j[0],h=j[1]),a.moveTo(this._position[0],this._position[1]),this._drawQuadTo(a,g,h,e,f),a.moveTo(this._position[0],this._position[1]);var k=this._drawQuadTo(a,g,h,e,f);e=k[0],f=k[1],this._setPosition(e,f),this._quadReflectionPoint=[e+(e-g),f+(f-h)]}}},{key:"_arcTo",value:function(a,b){var c="a"===b.key;if(b.data.length>=7){var d=+b.data[0],e=+b.data[1],f=+b.data[2],g=+b.data[3],h=+b.data[4],i=+b.data[5],j=+b.data[6];if(c&&(i+=this._position[0],j+=this._position[1]),i==this._position[0]&&j==this._position[1])return;if(0==d||0==e)this.drawLine(a,this._position[0],this._position[1],i,j,!0),this._setPosition(i,j);else{for(var k,l=0;l<2;l++){a.moveTo(this._position[0],this._position[1]);for(var m=new ArcConverter([this._position[0],this._position[1]],[i,j],[d,e],f,!!g,!!h),n=m.getNextSegment();n;)k=this._drawBezierTo(a,n.cp1[0],n.cp1[1],n.cp2[0],n.cp2[1],n.to[0],n.to[1]),n=m.getNextSegment()}k&&(i=k[0],j=k[1]),this._setPosition(i,j)}}}}]),b}(Drawable),Polygon=function(a){function b(a){_classCallCheck(this,b);var c=_possibleConstructorReturn(this,(b.__proto__||Object.getPrototypeOf(b)).call(this));return c._points=a,c}return _inherits(b,a),_createClass(b,[{key:"setPoint",value:function(a,b,c){this._points[a]=[b,c],this._canvas&&this._canvas.requestDraw()}},{key:"getPoint",value:function(a){return a>0&&a2){a.beginPath(),a.moveTo(b[0][0]+this.getOffset(-e,e),b[0][1]+this.getOffset(-e,e));for(var g=1;gZgdr-|p~atYVE?4> z%_=q5==D)Hj%lT2W`(UG<&>x1V>ys44K@=)1rdrp)YvoCn|D7wK$n}Zp_1O%0UZd$ zA~ofdL{Fn`o*;s6Hr7Svl{m}DxJbg4TM9Rr|5FzrW-(DM8|QrJ>z|%$Fqy38H1W{X zM0KM}-Za&WYUTp6Qz}*$Qw@mz_WTeyZ^yy1GpI;UN$xA9{n*-$vtJ7k)7Haq8C(eQ zo%IahGA9~ur-3XnOOPU~XuQXrkS5Zw@X$L!6$J&WR*y+7x_V&8^}MYALv|&-2n}X~ z@+oiws8NFF);coFWR6E}Z_@-YEUjxX;!rka+RkGpf+7BE9g3FnQ>&x^7#I~Ark*&p-gMa2h*q%| zFvZaYbJMu`j&c^Kz2*|3db>f_sPq`3Q}45roSd}Om9o@gF-9Ti@EU4Usq`+z9=oHt z7tD|5gR7I5ZLW=^8JBZ6L;fIHCd#1ST@ShY{aA0du~F33U|nn)p5wlk*QYiaP1on&?Z`#RKq*`k|k1i-T6uw_f8NvP%-(F2$piKXA?O{Z(v5E#%l+W4rXO$ak<* zu#d5)V<`?eq!G9^{AkgiWNHLthoyHi`ejdxREr^34~^7LFCqbl0;lDq$Wof;B2s;5 zToR8Wcn5e~zEGrAkyk!OHW%?Q3SK7RVs=o|1lA<@4KN;`XlhUrE?-A^L3Z_)Dk6LD z3k$0PV+CduhXYh=YNTh+Pb&Ti@ucwBR4^BJaJb) zdERY_cSKUukMl7isg&k$vOMevYU0ts7MQ$^=qHjsY0#E?S!LY#9`QKaqat{Bw!Csg zFdE6niZ&@UDhWx8w4HWQXc2F)^|4eGk$b8{sVIL?xF)>ih*qD;H>#+Ls z=^?YBm+s^f5^sXIzzmviOV?QYspA}v9%$U~xM}=C*YK5v)&}jwNWDP{vEVTP^yFU} zm7UH9H?psN06lHJOhX+i#B(k>loijO@s3Oy1Fas5r|3H!{`A9RJLtbc+H^fSb81J* zTsZEtN5hH&tW1J?Ct}66$pl8g$#ny;n2O-DR6+w{@td2n93(gbZ}loKSU6**!3>jY zW;v9>zWp4|Lo{?}IC>&}LX{b#HiFMW^tVp@8pme_LsO&i&^xYrUxlk~&yJsAve*H} zyIVINAgkaE>hA;jEec!*9$!O8Z%~@o=cekEXjDYf2lLjBISzwWp>#<-DfV$hQ8e2c z2Cb!s5|LHb^z3p01Cy;7sq`~hm-IT_gIwMWu%!=EvK;w=QAOkQiux0GHXV|0a$1ZQ zK-}&iII@zL+XAcD8DeM97M=Mu>Ujb?MUtz)k2ky9u=H1_QN~jXacJ5^x)FzYv@U#p zXW`|gHsicG@IuGPRyYz>E;n_p&;#SWrZeHt^mi)5spR;3Do`uVJ zWLIk-G45#eD_67WQbop87v<4TSo}O(sr7zZ!1S6aSZ*J$dhB{^eXl349RSlOP+{x`k>9y)E%dSVV=Zfi?HLfcT9t2PR155<;a7wGodPn?`UZp-=>x)P+%PfWnVwO> z@+5MF34BzYiiEH}Hvn#VMg612n0hNAVo^l9CA?&`uUg-6z3{^9hm%Z65m=Zxrve1g zt(>4Tp<~?AlLsc$s+1&6dSr`>vl5pEB^F)AHYFnRKNKOYWIN?4M#-BlXXgE}!f@c+BFHyAYsWRj@@nNNd8OMk`XolLkSFy5gO&&MVBf^EGK5oeR!a zGtbrqB-N)T-BCmc<^ym78P%anrsZ)7bi^WpikK|>Q^QqhJ}JAY>YYU+Kr$X>3`&J; zhlpB<$IO#>gq{6FJJ`T1&4h`XKd2rGA5fzIeueVGAYarhQeAaIl`AjECxj+}$Va9o z$$F8g5NJuCHKaG9icA~XekT({ZyGxF&^@%O2(4rMA!`tKJknKt5!5;23vZ{DgTWLA zqFSpD|FO%qK*^d9-(WWIDMMBk|HMU0G-E71W=9Ec4Z72W%VKII7Pljgeen?|RyfQO zFZs00%CGKhh-PUsuP@qaGa;UmxXS+4;Wyt+5NSyA$z~Qj7Vj?cgS5)>`m4X6Yqhp5 z6nc;5Q7}au(CzyU#$T=EahDb%lTR=3V)lV{%>^@WvCbQWsU$I_ogU7TP~j^p;_Jf< zenQ%5Ysb(E?SuI%Hr=HQ3Vgo*hpqm*e9Bar5eva6>bMDI3{u<(_>$^Igv7=fy|1;E z#M9=zA6L;IIz%HgzK}Kuo_?so43ah6=z(Z120D9&{x|{s*9eA4#q80`%5(S(5piG6 z;=c!3W{x;m3duxg;&9#ywA)#mOzQ)qbV#m z5K?HoKmHOYJjBVrK{A?^VV!Dhv@@kGqV8q4@9RDyWnhYMhp^Yr!}IPZ_nZpT=H$H#s{8IpAFf`OtbLfM<#!(>R9C%s0d zG(y2Vu}z8uNv_V+L!+m)QzaM6e+VyYF|Ck8wNg{-ExNryp3lJuDFo0b^QLL#u1T2O z2<6eH4;1wJC8x>59E|&B3rlt>+&0kAr?>gQ@h#f>OjEIs%7dilFL)}v7@(83_JK{O z+;=q01M5xj_S^;&Y0PE|2${Mn#c%c?LHHRmZeS@Mas=jSOtZU>9|nM~G*vHP7zCBO zyyX+Qw>W$_6|dU?QB|0Upgdze1-2z?zkz9zTS)G2@2m#*;f7fgQ!{k9HGz^Tm~xVB z`=>DN0gD-ldvrW6zGH-HoTf3?#hog;xhSj?d8XN@+qaTqE+<*URYyp)KW3oL(U?qv zq-P6J*b_=fq#!}eAh?s5ym$}edx;US5?@xP;UIgrCqcKbaTT6o+5kOE^v>BQnBq=! z!BG-8Iy5}|e>`qMtxjx-U0X9+AM?&>(H8I_mR>Hf6O*bDL?;2Z(~OMr>&@vawbV=X zbFa3vR`v40;d)7(FF5U{O?Igq{Fz#c1ReLQOPA1cH6mYhWE2%vXc<7ZiRclX0z#Q@ z-O5Eo1jzRTCVa>h=!N-Vkz{N{Bx{xfXtRtY2%4n$2#x`Z%=ccUB0|B715TgpB*~yZ z7G#t{$|eCt^YFRRfjezia3yRYWR3*X-h(8UQcHc_?@fu78O`G7AJS}+>ncY-C3+!S zw9iD{5+5hD7=$7+A^P5{;(Yr;#;dDI* zuM7K0ywig#DQ#;k_gYW3@-l~iVGP+wSS*S>(9uRt(qbW?#zD&`E@8!HYXxv8pn|od zAdPTMLz!M_sX)yXwZUkJ00e^C2Ikh33l^lTQcA^I%l+`iO(8a~#2ly=ijHV>cnhQT zbKZ?jMXvc_PqJA!#}ByTUgW>$9@KWd(>-Q&A1=VEKmOiEGU4c<8Gqi@jj8D9GDt@^ZY=OnG;L zt^v~_;n~q~crT2?@YlZQWLNZJ`6;UHsGS#Wao$LOB(@Hq==)wLgK6fr6+y2Wlla%1 zM)8`^j8WZ(AYb*5dt)yfcy%Jtnu|nt;i^iFufc7!w^V9t^Kl+~>d%fH%}fqiqS=W- z*eQ!JSN5gWPgr56yf|p_L`A28QmqLRV|U7Vv_Z>+eRFRrcqe^S#8h{SsdtV`V>bAd zU(ZJaxgjv>d71VE2GAPE4kNyT%k4eKVq-NL%&j@}x>pFwhl+BN>wXWvN-M8~crdrV z5o~;|5lB*HyR1obMByCpFOhuIoyRj~D%WZyz0IFKXCe>G^eo$}q91PM%Gnn)?T6S> z3^b*DX8-W+hh3vTyb7hCOqPu>7Uo(y=53|lwVt^x*;nK%*r2JZwWb^M*DT1!-Oq-$ z75eC5FMCum-6Hq2LeaE1hc4pvUPUBHM=lQ@KZl@M%{(Qp4&$be7$Qyj- zdYpdUroP+sEs%Xb_$B9&XEf1F-=t54kXa6)5WlHRh2}&de6?uNnz9S2ZySpxR`a*h zK>cjg!ab-g7zZVS>3Jk2(yba(C+L}Wr_N}-RG)|&28o_b(r2c^vR8R!Gr0hnyhO8= zX?kxoD#x@s((=*2D5`uh!I<_>N@G^(?mw1|GbD=r4C*NMlrI>oCDQT10RwVVm;Mu+(~&X|8qh8_NHQ2nzfAD5o4+tZ{SloPIY@F{Gnq^T>D*0Rd4vT z>lE&g=+&rgLl}32?}JcB4ZGc9?vf5i!%yP!iVkS87jYY*&*GpZu&T(tHF&zl2nOPv zxX@_W-RK36Ut_CZs$=-xUzqSX@n1?Js!5v?aP%4BFW3nzk6jTk5!|YOd$K+h_Z1^x zX5{>2gQ93Fk0@E9nsR98#H(#bi_&9atg^*J-7-uWK)jx2Km?z;icZm1D$EmZ#*a%@ z3c_EuD4=rCOh6D})u1pang~kUX-nG0hi6cOg=F~*p1@pqnd_{x)S=y3DFpAI;0Q1u ztXveD$*_hWkb=d&Q}3$7fl}M-VicEx8&Wn4h+#^Mw9ti=Y@XtTE ze-Cx;<12!Ng*rdmnsas$&LOcqmYW8z+G@B%t!&(|>FcCDG&HOVv8zG4Yz&#CB1l&+ zq}^XbNk8euzCMjBShpeF4ht{tA{=Qa&Ul%pr03OYL^6v5oE}h=ur^Eecgz-CCuod& zVE7u48Z?{GcA^(p=HHY&WdRv1+1b^j^4QEZ>w&D^wWGPpT`=(y{g6syf-#F!a-J022 z?SK3KM5;W@8@hcz%C2jgR8GXybU58@_yRjN&0aLybn=AbNV=HCr(G*S?BLBqlJMqp z2jcE0tnfNN0UJtnpCr{Foh3t!wd$h+Ek=#=TA?QmG}bf&(-Kb_j;iFr$uEb-|2mqW zD1dYhVjKO1NueV6#d0(?bC30J@-v0bZyF~BUuc3*ffAg=+nKr$UH#>+EC1Xo*wh^! zKP8(hw)+!zA7LS`!h6b&H3b$2vAGn%ewtH<4)Zab!pj?>ebUC|24O(^=d{T1EngHf z-1je_T@0e7%vTgT?>q^7Utpi^R;)ue(ovW)hFDYXOft6O<2yA;^vnqVuQ&C7S6Hu5 zMSGVTx3b-(KRg3F)9*+cJ5A zd-8Q0V5w)g??NOFCdstRZSXo?xvSbwVVsj+T3WhaqVN7=sBf31ar)uGyaTiRRldGd zZm{lPkLF=altnE$+f!dXmcjU>slhO-0`Y!L$8{@q?3Tr_XK|Q~7naG51Rq1)?wx+# z!OADjEla%Qa_NjugsVVr=1vnqXq!0HTqui6u!&HhPV2T4f{Y~yVF^nwsLn7x4`$?2 z$+1L7a@s~_oD^!^20TY$0j5u{^wfWtYRf4l&DK0Ih{y)}kpqf_LTEdMKwps@C<4rx z8rT`0R$X{Yk6k-hR9Y5IGDrJ8%!qf$0ZSvq`}C!|kpB%-O=R$W<|8AJ8k;K6%wXjl zJ08c2qsgcgC=$$em(J~3oayP~$4aAbRa#?-<0xCz%|;V7{l{Hd(dVCBab59GqLekI zalRhgdxUtiW#G)hj62@7yA|T0kzk>gWPM#ceV9Vkm?!!30-boJ>PULC$pFt+@wGk~ zA}DIbm#c}48Mu{SS6k#HN6Ui)&ZL7ef%P=b(4t{h?ZPlG+MfviX#mKG0XJFG{c-G! zgTIu~V3-V)F@=U^$SnUs>9UW$ONL{_ai#viC1nS#u^Gh-+fFY*`eq&DmP1*xfno(( z&bp7#qsxYsn05f712B?F+(HDC{)N!vbcp#<#3&D|lS-a>lV%(`$XI&&a>OmNA`kg+ zOucKku0}nCKFoWb5T6-P!n9$bcq2OB&B}>g*n>EP)Y-_@zTri_!IIEUmU#?m+ptmG zz7#ERbj?4Y7^4Kg*nV=S)0GXeH5RVp%;Cl3{-*1gGG$=pjoO%+C}@B@V3L(igiDeOq0}b^nZ}5Qn#`>Kg5r9u^P-u@E(FVA z?y~|+Xkb}XnUR0!dj{FSH5|!qR=lzdO4J%Q2G@vWBPRU1cN?Z(-yP0*PcV@#t6mE# z@@!!L)yHfAze+77`@(g470h2u#UZc!+1X?x5qEL}_+CGNr6WRL#Wa|$#^CTbE(*;q zEHY7#G0cOq!wCXOo7&Di_n}bOYZ6fJm$Zyo?_Tw72YkmDW^ApEW$L)c8e_=wflh(XM|Y{4r~k#!Wi!hy0gLdkE^PABc_lALdUuF+*gJ?LyLP$~R5D~_3JjCLf~aLsKPCi9Ntu&PJF#GLS5Y`{R6$13`(@cptZ>nR>O z$|JpMt^zMnFv73ziTnB4sKfCaR4COQVw;67fT}n2xU%4#ks5_5SsjU(a(d;CuEsm! z*mo7OqK%GxVZvl5O7f;oaL?!^0rW%^G-NCxNJao}`ljs398?SH0@!=l7cJP1;;!x) zf1UZe6auMiU`QV$7Oo*~448fwtY=ZqS+j)Z7jNX7Ho6_#HN*?JdIB*8)PlSR{ zOd3F%V%oG}Cs}-2>WCglji&fAwKVrQqioxHYl%FfysS9YDT$jB}$*%9AZYyz%RD+=6?O$XwFpv zV%hGTzFzmwoyvQycfj-1SO6YR8Wb?D`?)4-^t5s0=28qAeYpH~+}7LQKCiFm1^3^& zvF!Ug(69UY&*wfSEnWxr!{VpAKZ5Rky)q%~|1O<0&Nj93RI_ew^fuIsCj{nVTyye6 zgwGKe#dUU0DaB{<1oM2vS8(ji2~-kxfeq!Vz4rHbwY@XhB8;>+h?eC(c{9kzV^H46 zp$~#X*)vF&XK`zyW6w!<8OqXSOtLz?Lw||54(!q1NGcvsQiX4EMqPU!e|ZbrC&)1$ zC@08q_m35X=$_Ef6*I`Ykg5o69UM|Fk>5gr+o(ueva^5|&w2mm4Q1kA&Beg19T@|F zm}_A@ieh54@6gYL#SWYvGyO8cbG{!%{n1o}R^ zCOH_rqRnbY%ICH=YRY=@Lb!OZ4_q?uRa9uKQydJR+%{(^D%w(-|U6~y3v?|!6$F#LU zDe>ebJFE6anMQu?=+c-_#bKE4Rlev|-?h)ZIdkUaQk}(M&O-7vQD@xpel+y}x6T(Q z05$svS*bK%!fl3V#VJ>eQ5`-v!1w?3r`!k!zP+Bh?X~E;|4vVTl@G0Jd+8I{3TQy( z3*Ozu^Z$K-e7VCS*uftp`~KdSe*z;2_}L%XZ(|JLG+j5S)IhvlR^>Yjp1f%aq~*qR zlsE;sk=Lshe~0V@t$~8hx33MpLCwB^-EojvIvhennQC^2mH@3)XQ?gb+GIob&dldX(M-!#H?lR zec2c9@UV835rwz;tFZb@OC9+x0!s8unof*-LGMzHii5wfEq{>p_#Z2MNj3axOkW`j zm5~Tm7>5hr6d*EJ<${)nOs~x8KZjtXxQt`I43siME7&BLFlB5-$`e?(!cUI&pz4Ll z>Q=oXh5fmkcI!U*-D0~`hmRA_guNRy6}tLuO~O}48?8_-(=15u$f`q7W#a7ex;(YROPh@`>#pc;;he7 z1q7QifrX@B$@?2Ctpfyo+L zsKtZM`4j(MK4W?51uJ7z-gMFWJN2=`82nu@~K|oFUa$ot|@=_UxK--gOY=@c3Xrg~MPkM|mS3)pgUv7+Ar5$Z z>yvl)sJ^~|39ENbz=U;sCJ=<5cS-$Yub!4HzF#1O8h7^y3U=WMuXjNaoWG#_{PuWV z7^fAx2cEVw+SYXz_)+WV@4~i6p%8mhJ6*EWm`$cRqdI-FZL|NO6Gc`|eN(8P<`;G3 z3gr{IHE*jZEZlhTTnlhEdeq>@rCUmT07(S(pf)`+&^m5Z(qz?(Pu5?~PinVU#QQ!AV-!WrcF2)@d$%XB>Wm#h$?8xU>CCL?PK;waL*-YLVUn zS#FulvrZVN#&q$Vtpw>%o)RlUVf-Z(~O?3HuliGp!H0K5( z^fa3z@S8JWI&st*h=+$dyjT`Qai#^hVzM6W>sN%03drlHf1REIPIvlVcltGPuY?FY z2?X7q2%X&4E!dYqA#PVgFk?P7V%I#74(9_p@{dK_^@%n$Hr2`od+WpWCv{s|v zI|F)Q+IOf`d+zXS9yC(CX=EeqZ6TyAFml@vp9_#J#cCe!5pgl#$Snwud zw}>Z3w#fy9=MqY%+14i#%88mRl48fC=d+=Bartz&s5n=DVVksdQjxmovk&FlK$Kra zA*_n|;BS=Nh>5oQNS29w=&aO>*86m#p4_-n!SKrJaZ!?4030$_+LWa)Af2U9HxUE9{0qVR@(mau?Uk5;hl8xJd)D~C)hp=z zw*~tIf7x+vX;*}ShMl0H2QD{RVGl%7dc3b(BaC_ma3JW@H#5asR&JDHYT0dBJ?P3c8oCRqGUH_Iqk^=AehbbJ%6($jfTQf!1IY z^2{Dh%SaIEC%~TjgTo`$Y241hh;4MUI>!%@yT9V^ca%Au;A;0GHQpAxHwQ2AR$s*| z(wDao$K<~6rhIN9ia+8xVO~VrFa>I_M-*<#F%$gD<8P`?6HH-y2MW5EW*nJEEUeI1 zNZwG_BIb4AjETj=!?0Q!kXQ?lbHrC6`Lg1~JAU@~Dmie9cirxKGx+^>@zWVM8#pQv zCcN=7p@Kgc6T{H7o?5=b02@jXW)mo4-Y4D9ASYC^oG5{61=Nu8(&r`JoAs-?c@_F6 z{~Qe-gV5CHnP+_hXIn~n*XJhYCR6`uy#3~C9r$b3sKG!0vg4GW`=~*R;DhG~z6ehC zLYDpoI4jdo9{a^{-Ej^F0GT+Ban0Jv_W$O+!}M}Mxp`ie3cDaGWO=`7xFa%Nba^7* z9Jb%9deM1NZTIeAXL*wU3S>>Qb(=+#nTl5eUn;Ed!Bz84}((V5D*!Z+uRnm*eJ? zD&K(X!!;Z~d0Fx%RDUHUF(Ob=CgkBtIQ$!&ho^BtXR{?UAfbCNRJNw^`hM07=hq<)#Va`+f|kJ42N-w2UpC@Qo`+x0WD6plD#W zA@N^)#s`@P0$0xYl1v*N07mpFx$B~Mi+lfzF|y$7j-8GAV{00dWVS3;LrjsRy8)sJ zB1$*`BNI9TOF9g)G2oen_UY{RR!bfJ7Q>u3fpmzChPwdacVXu`L~{S&MbEJ69Lu^@ z-w}#bJ6=!X8EE%;PiG$IB@Y3e@6TGHjBBRdR2VPZqFNzdTB$@^F286#PtZqK;*33c zlo2SkRTlR!S~X<6)^H8=NEi`LuY@?7Y#0PVpWFh}cfI)O+sZvwN|g8S)qtz&mWx#@ z@HedoC|{&`!<^JGH|#CIt_>+a!@dQ>KoxCE?{O8Q%f^wf*P^D&bRwX2<*TrD1q`zq zwk?V-sO-qiZje8Lo;!S(V589GlWkAjf`ZSjonDgTrvF=n0mb(85#{iZ~Z!UCw!)EVN+@KQkig4h1lbaz`Ib2!g?g7=-!M9d;F**dR8@}DH z`h{AvAYgQ2fz|;zxbEmH>1k9$SMSiqBwNA{FtkSt5bM3*YoY- zkRCB$Z(!&RBfPaK@Fk=oW;*6o{?Vp=3Ki9jhLDx`;;sDp`g*oDmsCQt80iVw1UZO} z>T2C2c=9*f)-6AoBJkLb@Ovyz)_*~4w_wO({q;@jiGV})GVC~#JZ1iVl8!P@vXs4u z4!}0~Cn9@#%*r35$B{^GO-Na-n)!S<2Rv*y4kxSMLI`zxge)~o-xai}+EZaC;S63( zSFgK}_4B)&cVeI0h~M}0_??$gFjF+c*miJfZ836{vW_t&)y+Fe#Dhs&qlBph3~Z1^ zphs5r=06CIeWe9~|ApkTj53o&N(t;{)0{Co%1P~YD+al_ga}940C}ua0rb#*|i;)xrj+%bDhbmHHt@) z*Euq+ukc{A9{=s-9`t(Y54+kmQusHnfSOYgjOdc{I@dV#o%{|v=YWzEi}`C_3&HaY z_zbTdgIOR|D4~##TfY*}>xRXj<|-Vh)&TSRS$ySLV15wFSB-h_72ZoHI2ji+vshY} zAAx0!pMdPIW<*eA^dw#Aq5@*X7@cLR5i647>pP(#u=nQ4DdRLC9C5tJ!nSr82w(Au z{&*nISjBo%&xO170Y^$*Iz$bo-yf*;_rNyYpqM9c9-k0vy?t9s9vf6kPG1oD=jiY1x*(bt|;9Pq=MUkx!~ zoHR=bxnw)q9eXvYl_mkMMcUG!0fE*b!Dy>vjlUsmME;joY~*lB{G%EzUqZ%CaE6+p z?fl&s2Y?R=@2eauvZKfR62|XiyOE6c298R%WoW4HS;}4OV}kDvXeX@Fm3<1sERrrs2UCxIf~WdFjPqo`Jp<{Mi1DQdR#mnb z$%EJgqj$v~gFkeIY}7;hTF;W^=!x&_v)NO^Fj@0gd%qU$$RWmN?TiokpIH&KJ7y)u z7rFeIve)e*ateWs*F5QhD~OP{H~p;L&c=s|>Pf~3 zr{4?&DZ9`6`*juH6F$T*sLSg}$SR59GUQMoyc##EPg^Plo4J2|+nk4D&GV`_1Cs|QJR>bMEnFL~#J z!Fx38i0&!qRyIAF+t+L9^1)tC>00A`yCmB#6>`zPm%SuRI!mh(_3hg(YyQzM(%qK$ z_kPqBp(=J>m{wJfe~G0p{XKMj$cEq6b|;rOW5i&+*!V9ObV1|gbzL3E0nwMxcj_y= zY)8c-^dOJdzRDDUCXm@`Qj>1eN}^SjGmB5q;D{MXIt9nU)<~qH@=Ty|Kif8!2|@*O z_e#OU&q4>nMY=IOpY`6n=Rx5-uU-)=-^^fJs})$YT^+$8?Y_mP4sn$E4%SxmQ=~|q zGnzP=IMoSo5~1WTtjZ?e{+NeJDMo$=BfEbk4!Uwm-->MBKP;95Dk8rax4I7j`}XrS zk2UMgd<#J&#KIut2O?y}2!|DzV=NG3P{z^Eu(N-kPxjgukzqlZ>F&DI7>BV{+CvQa zckdFXrdLzjxA6R6?I#yz`o0PFS0DY|P)I{6iJy>wu$UEIF<3KwOeX*q3m~pfWUDaP zcr^!8JvT5ChR&)Q!0O4dk7*bzzVt_ciH{L>VPkdWXfgPAZ- zfgBSeOXlg@Z2Mq*8DNZ_Wpz5E<{*AVdT%%Q_D(!|Ml#tmmq3DN7FY&(^k8^aXaBt= z!gb2r=Pi=dthY;c4)Y`|^Nmz3U{)oX02~$Wz8&}OgMnT_fNv2a#`o3RZZPkCv}=`K z5=M~yVdULZdRkSIr8E3HvwPMc^Lvxq7ri1Q`t!*NkvpF_OnvS@3ToO%TpzJ4w{}K3o4R^%Q_JP zh(N0L6nFy3PAH6tu+Qbsnqkos2f3bcsK)qLS=}|2C^B%s(eryZGZ0U zC-aJq9xha%2oKK*HCmp`ZyFUfhTiJb^XH?fN!v5HNO^Elu0BykSHE9ry&~})*i72KFc#VV_M;vmcthbzHR1%mirtG-tNt(+LnGuV76hA z6ItqTPE*vFpxsJ7kfi9Sdmjcx#TX3-)#uRAyqu4f11lcCLSQL%L|VWWhPrWnY~DM2j=7`3-olQc2!kru1MZ8KQ=<7k+U9%Xbz^m2x7#1s)J&+HMCfa zaeR=1d3=_rK&tfv_zn#08yM#2-v-RbGYGYm9STlygRWq}%-KsY_CSl_O^a~U^g?qG+$iGCoTkE|yf^^WgXzO+%P4T8eF)I(A~9fj zf-u!Mg^$rQg)c82#=|pt>X0O3j;?x>d<8Pl7nzqZV6^mpIr)<;93Z7YYH_5zt~RNS zw39kpHiR7zzt$v>%=`x7v?tY3$Yh&V1f*(e=1~2nI1Fc|RFouz$ux}Zqi-6lPLC~1 zZVS;dNwV@X0}<^)MIjX?G4W`@OZ;5MlI%qqv9IXHhP63pu2o|sX6$e@`h9N&5)ekp z11Z6t*Fk;sSmrX#7g5cUJZM0$(AG$Bv>)rf#&cTY_duDhHN~_Dh-Cr=!2u-#7c^xs zdLBbb4=#L&ZRUm9V!_wdvTQB3sUQ+KK4Ove^rRb{6Me&WU`3lbH1YO@i<1}Aab(bI zbBF&i1U3d{Qzo0Y45LmqlWrg!ineDi^f~dG$V~3&1601q;PZ}=@Un-C_<*F6D_~eq zX(C(3E9zv(pd=^9PG8SGnxBK!-w;pRHFw80b){!Cs3FLsbpj2nCN)iLSuWFvZCItk zYy|ULGC=)ppp=eXU|~*JsE~O~={zof_9q(}o&6IvUK#s#Kbo+yMii?-3yb2=86ywp zp9zc~yP|oAT)F!phQaO<1iWz!5+k2j8@iBo=6^RX zBxd2-gHvAqTTY~W_yj2U@DPbIn-c>`@umIt99Zk^zKm)G3|8L23+8x!tZ4<>R;D-}-Aqv(q{da0=8((ZU8*D~> z3Vig|pp!d%cT6VEg?dcLOXSZ=IfS>a8wTm@W~9 z-ryU$CR*`F|5Mx4`3{8uF%9g&5!NjYj0 z^a>V=j^=XCW@3@1I{r1AQx*GnH8cEX^AIftulT+p5tv$LcKPukk48 zKx6cm6gfEKOE7~eWgNMpEm(| zt>PqKHM{c2^X+3i4GSDnJXFF_=StyciJ?E1A5fFHy6`q|y%^n1Mtioei|3 zdcApc_)VG%)}TgMfv&3GFs5|;11ke$=lNY|cD0*7N(l$r1{%)-uMhnD<6_+K&2A1F ziXS9LgQ+Znjt`BmatBn@22VG}iPZ{s?LKmHzLtLw4TosFEmVB#evB_W7&)eZJi^<} zR}6vv1lJLA8BB}zZlEnxF3QFPz{N#2d7TY*Br;%Y0S`lj*xQ1?{-@oVJ-5S!IZA0R zE`{s6K;TV=@uEV=?PU4C$3ZEvTbv{w0?TCv6+-Vdd4y_%3IyG%6Omf>vI;$Lj46TZJro?)x7LCP`qc)w2%!!9H^k*Jj&mCDJs*UZl-+K1z-YVff z9By|`_4p|6z;1%RuQ7PfUCA`=3p?KzX!5GgE0L4kCZ*v~8%}otCg(~E>XX0*-@Wg_ zm+nEjixpg8cE0{AD95c2;Q-ru4Xp*+F}sD_z`zHy{bqx6qhsq)7TtK3?f4=E$MaEd zUN_5_`rfp5kc+K#YmHHSoCvRN&k(dv1M0J-KxnH>VmVrHK?!oRA>6fi;Y3b}MBzZP zKAmo))kgm7*N+<`kyZe(!<0UgiNErl<%FLVJJ)Wwk1zRpQ?r-s`ftrxD&|kRz$)%` z5XrVm<_k23aS3E)J^Y%*n%CQp^!5Gg40t#!u}y4!MAjeXCtr?@!P)L?k&fFO0g zUC~;1`AB6!Jf8;eCR?0`itH=eer6(DPM4dm=R`LH$rMbb(U!O7@DWV50AhbI zJf{|k&7d2s%)AJ~=9x^iV7&w8@u&$jD;`XXAYIC0eyO0nil%`djfDqO53?s?+S>5t zR>S)U-na%Zm$%NO-M;$Caf?WcS%`n-rc{~#T*rJcq|I&W57L+(vEQHhw=ob8ogLG1 z-l3aKQMhtiB@3HmRS4k2`Cbv(1{Qwx0e_0pABcx7V4(=i!~G3|^w^z-Q)hpG$%O5W zJa+_xiQP=@fGNGQ>q$b1uf$D*;afG4u`By)tE$oZUoRJ;n-v$>TIsFV^1(i=Qz~)k zi>R9Ds>YR`0i09{{ncRrVnTTt!LoL(G?D`|cgmQqzZ>l7GSq+=pW4}?As>~rtS=y+4-7VoH^n2(dZD~?GIlQ? z?VB9>rkjon{AmR%BRJj?567Qk)gEx^+y2S|&CkVG6b^d-P#fPZ^XLxvPTMKBEEfEP zH6P@ryMZD7& zFVd{4#oCi&DHuN$`h`p<7Hnjdp9R@piM#8E?OB9N^@QZ2rK9-x_Ty?T!IYJbBHdGv za!cCXR!bUzmFjaAYarq8cUaI>2}LbP4sINOC$)9=U&Rf9OzH#tHbWhP#UB#pcpW@3 z&WrB=-%Q;p=H1s)rnPJ1YwbY|_p+U)OWI#XP@|vN*)*eN;dvaa!(uH~j6+o5(*yL| z7_OVH>EeW(Yst39lkqX`d>VjA}Mvm%8K)we6InUzuArq>cTKI3BLywzQ}1b)Yv5 zet!{$knk>S<|@i>(CCb;!AIzT5?8DGwyH2KIOg1LH`XUsvtLifFGkK2ef(tX4Edcg zC|7{f){Xn)@C?#r^@AhWj&QkH5WDdhxm?6klD27Wm{tdAQ+?9!Nllov?$S|*C-Q2 z%i#F0yUso5-nAe0-Y>uXu%GtY-|zcCVH`3Qi^$zb7cHPRJ z{uI9^VtOjRteBle!) zd(gM3Jl{Ms;p-8CP9B=t#~F)12wOqfXlcmt&%a=~ z4F4v{$mSmYA?ZFe#^)~e(d>ZhxaIkL)bncz-__{6W&2HD4WL+iiJZbVnk0=p%m>(s zciqggHgBQ{I4eST`vw-TUIdH1av|TpN<3|w{0S-VWT<(VSaT@qe>ZZ0@!i)cedj|^ zm$aN`&vD*;#t0l4q?=Umpi`%nHyuaKt zZ>I6^A`-{bpHT7VBM&Sfs{`_}2oDJ!(i1w!i)Gls^!(b$N&;;jCLreXAXi%y97Heu zRH9b&tm3|8(H6Ld|8%on#Dzj@ectSzI5|yxIfj`oT{^T|1)t6mCeW|6xohuiXklFP zID*Gz5#&A4m|u6A%`~FNv}q}-pAIE1ykLa|cMi=2Bs5s3-I?9@)o4YQ5QrF4(D-}C zEDXMqcCLXejE-b9oQ)un4A^NKOWI}bXqoza?-gZS2*#MW=RF#o>_Hdk07lqwhFx%G z(>&u*-tnzHNle?>`oh^ODpi$=UW55LGx6Eye|oK3Rm|opO5rTuh?vnh@FuRI zNU5Dj*|&Z42pppJa$luP6m>DF5w4Yn$hjtt+SYdsB;-MfQj~fv*Lvm(kiu8mMU1@N zk#|@bymz98mYs)5BG1*hPY|S&6V)kKY?Z^e)nM3W@dTwV9c5piK2u;INgj-dL!Df7 z!mNj#+}JfE;tPERg_bNSbOq2%Ah`Lblda`ta>d7i@Yma26K#9GLTvA zvC~Ht97&RUlFEtru#TDcyfXJue57oak{Lp0_)ML0&9|(W?%cjjJdu0w=hifA$x=IJ zeG!5FhRXb)rrv3}%STdSZ=3spQg`;lR6`n9rYdG&wjO|=ENDf-1aKYS|)%f^Eoj@$TaZq3Km7P@R zrh%i6U6G;-RtRNO%*-*Ra9?Z6#J0mBR&~XL78|xqP*cs&wlGE0k1$r`4-US$(|ck5 zX}|sLYU&*u$sKiD*i{yY#4va4EiN2Fpsxo&#hjB_BAX&Hrp|GM{lAkRZ{@j63h;mK zJV7mRuiB+AFVzUqPqDAo%fuEsN!AtBtCPMm;L*HScsXCY`@5~IFV;x5(pc7`Y_2=r zQL)>qr?p%+o*V9?R3_w@cF-eX(Y-g>ar!QBd7Ihi(oDjx&Ut*f?tt}chiW-%ctVta zU;bi);+y3Nb$eO{92q%5PedH65*;-}vSiMbT9CLODvFhV-|lHc==?H}o-L?eS>eEy z%%?93TbVZAT2;&*uom)anpVl-+>Ffj_NoWSSewU87(R8)$N%bwrMZT{Z=SIL_J3I$ zsvzbRXT)ChzJ6zPp!cRUU&4>&xtuRe@_oZ#!bT63cl8g?>IY0CMy}DTvza*qm|fFM z8fmRAndHEB@cqF2r$-JShru=O?|dGL-WP+vUxlC8p`2<^D6ZY5EU#;8w@&yVz%!U% znSjnme2(kcjoA^w^KY+V*-W~9(U+ThUSU%DnZysnFwMYyt7RRp^D7c`l4W*(_kiYj zNTMJQRysBhfQBLAtf8Q;L;BD|Z+xOqV{F&e#!b{x6;kdGah8>$oI-sJB61~uK=QWtJz;<;R z{&Xj;$mBTvEJTUREea5~(oi(^Oxd!^B=dc{L;BS zR(NjqMM1bu+W_;rZ^Pfiol=V&?o5F*lxZw2t3{T?5FU92=~S5?-_RKau=;sJMB+#` zvXrJ$7qy}a2t~o@(qNkGpR)+eXr>G^|DT?Q1$j$_j#|BOqVU-CN|`9zBH1^t`L2S% zKLQ2(1SmQ)@xH8sC|Q_g5IhPgrhRLAX`^qZ7lR=isEFi8&kWWz9okMBq}E0`*D8hr z=Rf_<<6Nr}vTr7qN7*FPa< zPw{Oun4dbaq+M#Z6~=JDUXu_p(j!I)IC=-t)Iu86o2u)v+t{-+F)=ccqR45v;AD7Q zzjYjgRLUYG7UNlm{gYZ)6@`UCY;baG-^MjBHM`caJtNl%N7n##_o9QQd$lanN;ATT z;)PvHTH=ypMd?`nXPO0M$v-qnSp01_6~r3kP=hJs3KfB7^?xWw4Ef!>$U2w(jU@*kD2Fvnckby zS!<({rm+%s<)&(IYKfPX7wD9LpHFx~$*?W<%PgoN6XLdzGE@;-GfwRXpXqTGr>Qn@ zR8FC7bGO?b0e;;$NCb8N(+Uq5_5er6>JKuexJM#f=9&z68^a5YHXqSRO|aFRzJ)HM z_JN9q3{55sO-c++hCs!0@6VQS#>}ElJ{PXkqQuFbLPOTKfYDC;!e-6$05uD}e6GXG zb4HxW^-#~TtXxNUYAoXiw+7M=(iKDI)rI9)#^E{p4Vzg^zeP?agjojmFmZ-_N*l$E zKJ#;dmKKSpQr_c!Oiz>2z@_gFq!A1kpu!F@6P1~|Y2D*IY|9TMW-wI0AJa@7lQg!? zBz~Q=Y8tmiC#S%;PQx6@-87KBm@m3zk#i%gueV511`4HK1Cn$!z~@u27K4-;3-)>@ zUvD2tJ)RHbM|)eU>c`LB9#74=T(~D*FIj(?h#-cBgKA_mX5#lxg-W|s?us7!*FAVR z8epsH1L6K5dV(UkI(CsqM5%#Wf=@1C>O+0S{P;Pf%p)3hwl3Bu$D_N1 ztO{K4=sC6YAnlBemFFuh{LfI8brDS4hVBNKSd|s>@4qFQr8QW6_ZG8LE*l zUZO?aWF=kTykX?LmF4<4xAqg0_St6AJdpnH_k$SQwrBZA16EUQkCj6-UVhXS*rUy1 z8Dtsl%WBM24G~nTMy}!;QTc=%eHq~VmGCqGV zr3_rzmnoB$0#$8Q01bt<(9ioO;Z4X+=i9kz*A)l7AYi7i01XI?8qcP%iC$BU?wK-! zm+~7psrca`GYC3`kR}BOAU>l_g_dI5(qd*?Z);jcpdN2Z}cuJas2B{}D&!vHu`-+-m!#p$d`P54R*q-JVYWmc$= zo}w>E->q)BINylj(z6o{e+f^M2HJEIv-i#i)?D9d{NS)%M%$3N_=hl`sQt6cUX=MX zll#G-qzsjD!Yc7M>B+SyfyF6iKn(v}q@OPc3uI|| zFFfu>V_J6n-SkI4qIx}os=NI}b$F?~2zl4v*j9{vhED4l6r?7ne(~7>!t%g>7Lncq z=QbK42^Z>3_&lilEov{f<+Rx>3UgSODlM?f-k~fsTD{loX`!>vIjQMaC8j%vPhq8T zp&v1Z^V5-1vvEGs{Nj&K^jwue=xl3un;!@Ud6-M3OW&zvzF;E(e?QtV$_Wm6Zwnxo z05>Aoa?|h41KgfC?n@5*lD=MBUkBuXL+U7ZSo93H!yv(Db9S2)qa+lY+d%hghJV0_ z2TBzrqwIKiV-a|_U<5t^9pQgugZ~Xpkl<1LTRkXW6#mchKk7k}|5XqE|AhZer}#e! j2DdQA|0MhywIIR!H)^4$Nksh52?Vzz?sk5o_s{NM`P5CW literal 0 HcmV?d00001