From 0126d044e6220bcc5ef1676386da69774250b64e Mon Sep 17 00:00:00 2001 From: Belleve Invis Date: Sun, 19 Jul 2015 16:23:09 +0800 Subject: [PATCH] Switched interpolation of stroke width into monotonic cubic interpolation --- font.js | 13 +- font.patel | 16 +- support/monotonic-interpolate.js | 72 +++++ support/smooth.js | 411 --------------------------- support/stroke.js | 463 ++++++++++++++++--------------- support/stroke.patel | 12 +- 6 files changed, 334 insertions(+), 653 deletions(-) create mode 100644 support/monotonic-interpolate.js delete mode 100644 support/smooth.js diff --git a/font.js b/font.js index ff4dc3c..550a380 100644 --- a/font.js +++ b/font.js @@ -117,14 +117,13 @@ r13_xn$assignunicode$7Hrq('A'); r13_TURN = r0_XH * 0.1; r13_leftbar = new r0_Stroke(); - r13_leftbar['start-from'](r0_SB, 0)['line-to'](r0_SB, r13_TURN)['curve-to'](r0_SB, r13_TURN + 0.27 * (r0_CAP - r13_TURN), r0_MIDDLE - r0_STROKE / 2, r0_CAP); + r13_leftbar['start-from'](r0_SB, 0)['set-width'](0, r0_STROKE)['line-to'](r0_SB, r13_TURN)['curve-to'](r0_SB, r13_TURN + 0.27 * (r0_CAP - r13_TURN), r0_MIDDLE - r0_STROKE / 2, r0_CAP)['set-width'](0, r0_STROKE * 0.8); r13_rightbar = new r0_Stroke(); - r13_rightbar['start-from'](r0_RIGHTSB, 0)['line-to'](r0_RIGHTSB, r13_TURN)['curve-to'](r0_RIGHTSB, r13_TURN + 0.27 * (r0_CAP - r13_TURN), r0_MIDDLE + r0_STROKE / 2, r0_CAP); - r13_hbar = new r0_Stroke(); - r13_hbar['start-from'](r0_SB + r0_STROKE, r0_XH / 2)['line-to'](r0_RIGHTSB - r0_STROKE, r0_XH / 2); - r13_xn$putshapes$9Jrj(r13_leftbar['form-stroke'](0, r0_STROKE)); - r13_xn$putshapes$9Jrj(r13_hbar['form-stroke'](0, r0_STROKE)); - r13_xn$putshapes$9Jrj(r13_rightbar['form-stroke'](r0_STROKE, 0)); + r13_rightbar['start-from'](r0_RIGHTSB, 0)['set-width'](r0_STROKE, 0)['line-to'](r0_RIGHTSB, r13_TURN)['curve-to'](r0_RIGHTSB, r13_TURN + 0.27 * (r0_CAP - r13_TURN), r0_MIDDLE + r0_STROKE / 2, r0_CAP)['set-width'](r0_STROKE * 0.8, 0); + r13_hbar = new r0_Stroke()['start-from'](r0_SB + r0_STROKE, r0_XH / 2)['set-width'](0, r0_STROKE)['line-to'](r0_RIGHTSB - r0_STROKE, r0_XH / 2); + r13_xn$putshapes$9Jrj(r13_leftbar['form-stroke']()); + r13_xn$putshapes$9Jrj(r13_hbar['form-stroke']()); + r13_xn$putshapes$9Jrj(r13_rightbar['form-stroke']()); r13_xn$startfrom$1aao(r0_MIDDLE - r0_STROKE / 2, r0_CAP); r13_xn$lineto$5sIl(r0_MIDDLE + r0_STROKE / 2, r0_CAP); r13_xn$lineto$5sIl(r0_MIDDLE, r0_CAP - r0_STROKE); diff --git a/font.patel b/font.patel index dfd89aa..e26d1ae 100644 --- a/font.patel +++ b/font.patel @@ -133,20 +133,26 @@ create-glyph 'A' : glyph-construction { local leftbar : new Stroke leftbar.start-from SB 0 + :.set-width 0 STROKE :.line-to SB TURN :.curve-to SB [TURN + 0.27 * [CAP - TURN]] [MIDDLE - STROKE / 2] CAP + :.set-width 0 [STROKE * 0.8] local rightbar : new Stroke rightbar.start-from RIGHTSB 0 + :.set-width STROKE 0 :.line-to RIGHTSB TURN :.curve-to RIGHTSB [TURN + 0.27 * [CAP - TURN]] [MIDDLE + STROKE / 2] CAP + :.set-width [STROKE * 0.8] 0 - local hbar : new Stroke - hbar.start-from [SB + STROKE] [XH / 2] :.line-to [RIGHTSB - STROKE] [XH / 2] + local hbar : new Stroke + :.start-from [SB + STROKE] [XH / 2] + :.set-width 0 STROKE + :.line-to [RIGHTSB - STROKE] [XH / 2] - put-shapes : leftbar.form-stroke 0 STROKE - put-shapes : hbar.form-stroke 0 STROKE - put-shapes : rightbar.form-stroke STROKE 0 + put-shapes : leftbar.form-stroke + put-shapes : hbar.form-stroke + put-shapes : rightbar.form-stroke #top cap start-from [MIDDLE - STROKE / 2] CAP diff --git a/support/monotonic-interpolate.js b/support/monotonic-interpolate.js new file mode 100644 index 0000000..fedb6ed --- /dev/null +++ b/support/monotonic-interpolate.js @@ -0,0 +1,72 @@ +exports.createInterpolant = function(xs, ys) { + var i, length = xs.length; + + // Deal with length issues + if (length != ys.length) { throw 'Need an equal count of xs and ys.'; } + if (length === 0) { return function(x) { return 0; }; } + if (length === 1) { + // Impl: Precomputing the result prevents problems if ys is mutated later and allows garbage collection of ys + // Impl: Unary plus properly converts values to numbers + var result = +ys[0]; + return function(x) { return result; }; + } + + // Rearrange xs and ys so that xs is sorted + var indexes = []; + for (i = 0; i < length; i++) { indexes.push(i); } + indexes.sort(function(a, b) { return xs[a] < xs[b] ? -1 : 1; }); + var oldXs = xs, oldYs = ys; + // Impl: Creating new arrays also prevents problems if the input arrays are mutated later + xs = []; ys = []; + // Impl: Unary plus properly converts values to numbers + for (i = 0; i < length; i++) { xs.push(+oldXs[indexes[i]]); ys.push(+oldYs[indexes[i]]); } + + // Get consecutive differences and slopes + var dys = [], dxs = [], ms = []; + for (i = 0; i < length - 1; i++) { + var dx = xs[i + 1] - xs[i], dy = ys[i + 1] - ys[i]; + dxs.push(dx); dys.push(dy); ms.push(dy/dx); + } + + // Get degree-1 coefficients + var c1s = [ms[0]]; + for (i = 0; i < dxs.length - 1; i++) { + var m = ms[i], mNext = ms[i + 1]; + if (m*mNext <= 0) { + c1s.push(0); + } else { + var dx = dxs[i], dxNext = dxs[i + 1], common = dx + dxNext; + c1s.push(3*common/((common + dxNext)/m + (common + dx)/mNext)); + } + } + c1s.push(ms[ms.length - 1]); + + // Get degree-2 and degree-3 coefficients + var c2s = [], c3s = []; + for (i = 0; i < c1s.length - 1; i++) { + var c1 = c1s[i], m = ms[i], invDx = 1/dxs[i], common = c1 + c1s[i + 1] - m - m; + c2s.push((m - c1 - common)*invDx); c3s.push(common*invDx*invDx); + } + + // Return interpolant function + return function(x) { + // The rightmost point in the dataset should give an exact result + var i = xs.length - 1; + if (x == xs[i]) { return ys[i]; } + + // Search for the interval x is in, returning the corresponding y if x is one of the original xs + var low = 0, mid, high = c3s.length - 1; + while (low <= high) { + mid = Math.floor(0.5*(low + high)); + var xHere = xs[mid]; + if (xHere < x) { low = mid + 1; } + else if (xHere > x) { high = mid - 1; } + else { return ys[mid]; } + } + i = Math.max(0, high); + + // Interpolate + var diff = x - xs[i], diffSq = diff*diff; + return ys[i] + c1s[i]*diff + c2s[i]*diffSq + c3s[i]*diff*diffSq; + }; +}; \ No newline at end of file diff --git a/support/smooth.js b/support/smooth.js deleted file mode 100644 index b63f32c..0000000 --- a/support/smooth.js +++ /dev/null @@ -1,411 +0,0 @@ - -/* -Smooth.js version 0.1.7 - -Turn arrays into smooth functions. - -Copyright 2012 Spencer Cohen -Licensed under MIT license (see "Smooth.js MIT license.txt") -*/ - -/*Constants (these are accessible by Smooth.WHATEVER in user space) -*/ - -(function() { - var AbstractInterpolator, CubicInterpolator, Enum, LinearInterpolator, NearestInterpolator, PI, SincFilterInterpolator, Smooth, clipClamp, clipMirror, clipPeriodic, defaultConfig, getColumn, getType, isValidNumber, k, makeLanczosWindow, makeScaledFunction, makeSincKernel, normalizeScaleTo, shallowCopy, sin, sinc, v, validateNumber, validateVector, - __hasProp = Object.prototype.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }; - - Enum = { - /*Interpolation methods - */ - METHOD_NEAREST: 'nearest', - METHOD_LINEAR: 'linear', - METHOD_CUBIC: 'cubic', - METHOD_LANCZOS: 'lanczos', - METHOD_SINC: 'sinc', - /*Input clipping modes - */ - CLIP_CLAMP: 'clamp', - CLIP_ZERO: 'zero', - CLIP_PERIODIC: 'periodic', - CLIP_MIRROR: 'mirror', - /* Constants for control over the cubic interpolation tension - */ - CUBIC_TENSION_DEFAULT: 0, - CUBIC_TENSION_CATMULL_ROM: 0 - }; - - defaultConfig = { - method: Enum.METHOD_CUBIC, - cubicTension: Enum.CUBIC_TENSION_DEFAULT, - clip: Enum.CLIP_CLAMP, - scaleTo: 0, - sincFilterSize: 2, - sincWindow: void 0 - }; - - /*Index clipping functions - */ - - clipClamp = function(i, n) { - return Math.max(0, Math.min(i, n - 1)); - }; - - clipPeriodic = function(i, n) { - i = i % n; - if (i < 0) i += n; - return i; - }; - - clipMirror = function(i, n) { - var period; - period = 2 * (n - 1); - i = clipPeriodic(i, period); - if (i > n - 1) i = period - i; - return i; - }; - - /* - Abstract scalar interpolation class which provides common functionality for all interpolators - - Subclasses must override interpolate(). - */ - - AbstractInterpolator = (function() { - - function AbstractInterpolator(array, config) { - this.array = array.slice(0); - this.length = this.array.length; - if (!(this.clipHelper = { - clamp: this.clipHelperClamp, - zero: this.clipHelperZero, - periodic: this.clipHelperPeriodic, - mirror: this.clipHelperMirror - }[config.clip])) { - throw "Invalid clip: " + config.clip; - } - } - - AbstractInterpolator.prototype.getClippedInput = function(i) { - if ((0 <= i && i < this.length)) { - return this.array[i]; - } else { - return this.clipHelper(i); - } - }; - - AbstractInterpolator.prototype.clipHelperClamp = function(i) { - return this.array[clipClamp(i, this.length)]; - }; - - AbstractInterpolator.prototype.clipHelperZero = function(i) { - return 0; - }; - - AbstractInterpolator.prototype.clipHelperPeriodic = function(i) { - return this.array[clipPeriodic(i, this.length)]; - }; - - AbstractInterpolator.prototype.clipHelperMirror = function(i) { - return this.array[clipMirror(i, this.length)]; - }; - - AbstractInterpolator.prototype.interpolate = function(t) { - throw 'Subclasses of AbstractInterpolator must override the interpolate() method.'; - }; - - return AbstractInterpolator; - - })(); - - NearestInterpolator = (function(_super) { - - __extends(NearestInterpolator, _super); - - function NearestInterpolator() { - NearestInterpolator.__super__.constructor.apply(this, arguments); - } - - NearestInterpolator.prototype.interpolate = function(t) { - return this.getClippedInput(Math.round(t)); - }; - - return NearestInterpolator; - - })(AbstractInterpolator); - - LinearInterpolator = (function(_super) { - - __extends(LinearInterpolator, _super); - - function LinearInterpolator() { - LinearInterpolator.__super__.constructor.apply(this, arguments); - } - - LinearInterpolator.prototype.interpolate = function(t) { - var k; - k = Math.floor(t); - t -= k; - return (1 - t) * this.getClippedInput(k) + t * this.getClippedInput(k + 1); - }; - - return LinearInterpolator; - - })(AbstractInterpolator); - - CubicInterpolator = (function(_super) { - - __extends(CubicInterpolator, _super); - - function CubicInterpolator(array, config) { - this.tangentFactor = 1 - Math.max(0, Math.min(1, config.cubicTension)); - CubicInterpolator.__super__.constructor.apply(this, arguments); - } - - CubicInterpolator.prototype.getTangent = function(k) { - return this.tangentFactor * (this.getClippedInput(k + 1) - this.getClippedInput(k - 1)) / 2; - }; - - CubicInterpolator.prototype.interpolate = function(t) { - var k, m, p, t2, t3; - k = Math.floor(t); - m = [this.getTangent(k), this.getTangent(k + 1)]; - p = [this.getClippedInput(k), this.getClippedInput(k + 1)]; - t -= k; - t2 = t * t; - t3 = t * t2; - return (2 * t3 - 3 * t2 + 1) * p[0] + (t3 - 2 * t2 + t) * m[0] + (-2 * t3 + 3 * t2) * p[1] + (t3 - t2) * m[1]; - }; - - return CubicInterpolator; - - })(AbstractInterpolator); - - sin = Math.sin, PI = Math.PI; - - sinc = function(x) { - if (x === 0) { - return 1; - } else { - return sin(PI * x) / (PI * x); - } - }; - - makeLanczosWindow = function(a) { - return function(x) { - return sinc(x / a); - }; - }; - - makeSincKernel = function(window) { - return function(x) { - return sinc(x) * window(x); - }; - }; - - SincFilterInterpolator = (function(_super) { - - __extends(SincFilterInterpolator, _super); - - function SincFilterInterpolator(array, config) { - SincFilterInterpolator.__super__.constructor.apply(this, arguments); - this.a = config.sincFilterSize; - if (!config.sincWindow) throw 'No sincWindow provided'; - this.kernel = makeSincKernel(config.sincWindow); - } - - SincFilterInterpolator.prototype.interpolate = function(t) { - var k, n, sum, _ref, _ref2; - k = Math.floor(t); - sum = 0; - for (n = _ref = k - this.a + 1, _ref2 = k + this.a; _ref <= _ref2 ? n <= _ref2 : n >= _ref2; _ref <= _ref2 ? n++ : n--) { - sum += this.kernel(t - n) * this.getClippedInput(n); - } - return sum; - }; - - return SincFilterInterpolator; - - })(AbstractInterpolator); - - getColumn = function(arr, i) { - var row, _i, _len, _results; - _results = []; - for (_i = 0, _len = arr.length; _i < _len; _i++) { - row = arr[_i]; - _results.push(row[i]); - } - return _results; - }; - - makeScaledFunction = function(f, baseScale, scaleRange) { - var scaleFactor, translation; - if (scaleRange.join === '0,1') { - return f; - } else { - scaleFactor = baseScale / (scaleRange[1] - scaleRange[0]); - translation = scaleRange[0]; - return function(t) { - return f(scaleFactor * (t - translation)); - }; - } - }; - - getType = function(x) { - return Object.prototype.toString.call(x).slice('[object '.length, -1); - }; - - validateNumber = function(n) { - if (isNaN(n)) throw 'NaN in Smooth() input'; - if (getType(n) !== 'Number') throw 'Non-number in Smooth() input'; - if (!isFinite(n)) throw 'Infinity in Smooth() input'; - }; - - validateVector = function(v, dimension) { - var n, _i, _len; - if (getType(v) !== 'Array') throw 'Non-vector in Smooth() input'; - if (v.length !== dimension) throw 'Inconsistent dimension in Smooth() input'; - for (_i = 0, _len = v.length; _i < _len; _i++) { - n = v[_i]; - validateNumber(n); - } - }; - - isValidNumber = function(n) { - return (getType(n) === 'Number') && isFinite(n) && !isNaN(n); - }; - - normalizeScaleTo = function(s) { - var invalidErr; - invalidErr = "scaleTo param must be number or array of two numbers"; - switch (getType(s)) { - case 'Number': - if (!isValidNumber(s)) throw invalidErr; - s = [0, s]; - break; - case 'Array': - if (s.length !== 2) throw invalidErr; - if (!(isValidNumber(s[0]) && isValidNumber(s[1]))) throw invalidErr; - break; - default: - throw invalidErr; - } - return s; - }; - - shallowCopy = function(obj) { - var copy, k, v; - copy = {}; - for (k in obj) { - if (!__hasProp.call(obj, k)) continue; - v = obj[k]; - copy[k] = v; - } - return copy; - }; - - Smooth = function(arr, config) { - var baseDomainEnd, dimension, i, interpolator, interpolatorClass, interpolators, k, n, properties, smoothFunc, v; - if (config == null) config = {}; - properties = {}; - config = shallowCopy(config); - properties.config = shallowCopy(config); - if (config.scaleTo == null) config.scaleTo = config.period; - if (config.sincFilterSize == null) { - config.sincFilterSize = config.lanczosFilterSize; - } - for (k in defaultConfig) { - if (!__hasProp.call(defaultConfig, k)) continue; - v = defaultConfig[k]; - if (config[k] == null) config[k] = v; - } - if (!(interpolatorClass = { - nearest: NearestInterpolator, - linear: LinearInterpolator, - cubic: CubicInterpolator, - lanczos: SincFilterInterpolator, - sinc: SincFilterInterpolator - }[config.method])) { - throw "Invalid method: " + config.method; - } - if (config.method === 'lanczos') { - config.sincWindow = makeLanczosWindow(config.sincFilterSize); - } - if (arr.length < 2) throw 'Array must have at least two elements'; - properties.count = arr.length; - smoothFunc = (function() { - var _i, _j, _len, _len2; - switch (getType(arr[0])) { - case 'Number': - properties.dimension = 'scalar'; - if (Smooth.deepValidation) { - for (_i = 0, _len = arr.length; _i < _len; _i++) { - n = arr[_i]; - validateNumber(n); - } - } - interpolator = new interpolatorClass(arr, config); - return function(t) { - return interpolator.interpolate(t); - }; - case 'Array': - properties.dimension = dimension = arr[0].length; - if (!dimension) throw 'Vectors must be non-empty'; - if (Smooth.deepValidation) { - for (_j = 0, _len2 = arr.length; _j < _len2; _j++) { - v = arr[_j]; - validateVector(v, dimension); - } - } - interpolators = (function() { - var _results; - _results = []; - for (i = 0; 0 <= dimension ? i < dimension : i > dimension; 0 <= dimension ? i++ : i--) { - _results.push(new interpolatorClass(getColumn(arr, i), config)); - } - return _results; - })(); - return function(t) { - var interpolator, _k, _len3, _results; - _results = []; - for (_k = 0, _len3 = interpolators.length; _k < _len3; _k++) { - interpolator = interpolators[_k]; - _results.push(interpolator.interpolate(t)); - } - return _results; - }; - default: - throw "Invalid element type: " + (getType(arr[0])); - } - })(); - if (config.clip === 'periodic') { - baseDomainEnd = arr.length; - } else { - baseDomainEnd = arr.length - 1; - } - config.scaleTo || (config.scaleTo = baseDomainEnd); - properties.domain = normalizeScaleTo(config.scaleTo); - smoothFunc = makeScaledFunction(smoothFunc, baseDomainEnd, properties.domain); - properties.domain.sort(); - /*copy properties - */ - for (k in properties) { - if (!__hasProp.call(properties, k)) continue; - v = properties[k]; - smoothFunc[k] = v; - } - return smoothFunc; - }; - - for (k in Enum) { - if (!__hasProp.call(Enum, k)) continue; - v = Enum[k]; - Smooth[k] = v; - } - - Smooth.deepValidation = true; - - (typeof exports !== "undefined" && exports !== null ? exports : window).Smooth = Smooth; - -}).call(this); \ No newline at end of file diff --git a/support/stroke.js b/support/stroke.js index 75f0ceb..f824877 100644 --- a/support/stroke.js +++ b/support/stroke.js @@ -1,8 +1,17 @@ { - var r0_Smooth, r0_intersection, r0_Bezier, r0_SAMPLES, r0_TINY, r0_LITTLE, r0_KAPPA, r0_COKAPPA, r0_BKAPPA, r0_COBKAPPA, r0_Stroke, r0_dforward, r0_dbackward, r0_nonlinear, _r0_t0, _r0_t1, _r0_t2, _r0_t3, _r0_t4, _r0_t5, _r0_t6, _r0_t7, _r0_t8, _r0_t9, _r0_t10, _r0_t11, _r0_t12; - r0_Smooth = require('./smooth')['Smooth']; + var r0_smooth, r0_intersection, r0_Bezier, r0_xn$rangearray$1aao, r0_SAMPLES, r0_TINY, r0_LITTLE, r0_KAPPA, r0_COKAPPA, r0_BKAPPA, r0_COBKAPPA, r0_Stroke, r0_dforward, r0_dbackward, r0_nonlinear, _r0_t0, _r0_t1, _r0_t2, _r0_t3, _r0_t4, _r0_t5, _r0_t6, _r0_t7, _r0_t8, _r0_t9, _r0_t10, _r0_t11, _r0_t12, _r0_t13; + r0_smooth = require('./monotonic-interpolate')['createInterpolant']; r0_intersection = require('./intersection')['intersection']; r0_Bezier = require('bezier-js'); + r0_xn$rangearray$1aao = function _r0_t0(r1_low, r1_high) { + var r1_low, r1_high, r1_a, r1_j; + r1_a = []; + r1_j = r1_low; + for (; r1_j < r1_high; r1_j = r1_j + 1) { + r1_a['push'](r1_j); + } + return r1_a; + }; r0_SAMPLES = 4; r0_TINY = 0.0001; r0_LITTLE = 0.01; @@ -10,74 +19,54 @@ r0_COKAPPA = 1 - r0_KAPPA; r0_BKAPPA = r0_KAPPA + 0.1; r0_COBKAPPA = r0_COKAPPA - 0.1; - r0_Stroke = function _r0_t0() { - var _r1_t0; - _r1_t0 = this; - _r1_t0['points'] = []; - return _r1_t0; + r0_Stroke = function _r0_t1() { + var _r2_t0; + _r2_t0 = this; + _r2_t0['points'] = []; + return _r2_t0; }; - r0_Stroke['bindParameters'] = function _r0_t1(r2_para) { - var r2_para; - r0_KAPPA = r2_para['kappa']; + r0_Stroke['bindParameters'] = function _r0_t2(r3_para) { + var r3_para; + r0_KAPPA = r3_para['kappa']; r0_COKAPPA = 1 - r0_KAPPA; r0_COBKAPPA = r0_COKAPPA - 0.1; return r0_BKAPPA = r0_KAPPA + 0.1; }; - r0_Stroke['prototype']['set-width'] = function _r0_t2(r3_d1, r3_d2) { - var r3_d1, r3_d2, r3_point, _r3_t0; - _r3_t0 = this; - r3_point = _r3_t0['points'][_r3_t0['points']['length'] - 1]; - r3_point['d1'] = r3_d1; - r3_point['d2'] = r3_d2; - return _r3_t0; - }; - r0_Stroke['prototype']['start-from'] = function _r0_t3(r4_x, r4_y) { - var r4_x, r4_y, _r4_t0; + r0_Stroke['prototype']['set-width'] = function _r0_t3(r4_d1, r4_d2) { + var r4_d1, r4_d2, r4_point, _r4_t0; _r4_t0 = this; - _r4_t0['points'] = [{ - 'x': r4_x, - 'y': r4_y, - 'onCurve': true - }]; + r4_point = _r4_t0['points'][_r4_t0['points']['length'] - 1]; + r4_point['d1'] = r4_d1; + r4_point['d2'] = r4_d2; return _r4_t0; }; - r0_Stroke['prototype']['line-to'] = function _r0_t4(r5_x, r5_y) { + r0_Stroke['prototype']['start-from'] = function _r0_t4(r5_x, r5_y) { var r5_x, r5_y, _r5_t0; _r5_t0 = this; - _r5_t0['points']['push']({ - 'x': r5_x, - 'y': r5_y, - 'onCurve': true - }); + _r5_t0['points'] = [{ + 'x': r5_x, + 'y': r5_y, + 'onCurve': true + }]; return _r5_t0; }; - r0_Stroke['prototype']['curve-to'] = function _r0_t5(r6_xc, r6_yc, r6_x, r6_y) { - var r6_xc, r6_yc, r6_x, r6_y, _r6_t0; + r0_Stroke['prototype']['line-to'] = function _r0_t5(r6_x, r6_y) { + var r6_x, r6_y, _r6_t0; _r6_t0 = this; _r6_t0['points']['push']({ - 'x': r6_xc, - 'y': r6_yc, - 'onCurve': false - }, { 'x': r6_x, 'y': r6_y, 'onCurve': true }); return _r6_t0; }; - r0_Stroke['prototype']['cubic-to'] = function _r0_t6(r7_x1, r7_y1, r7_x2, r7_y2, r7_x, r7_y) { - var r7_x1, r7_y1, r7_x2, r7_y2, r7_x, r7_y, _r7_t0; + r0_Stroke['prototype']['curve-to'] = function _r0_t6(r7_xc, r7_yc, r7_x, r7_y) { + var r7_xc, r7_yc, r7_x, r7_y, _r7_t0; _r7_t0 = this; _r7_t0['points']['push']({ - 'x': r7_x1, - 'y': r7_y1, - 'onCurve': false, - 'cubic': true - }, { - 'x': r7_x2, - 'y': r7_y2, - 'onCurve': false, - 'cubic': true + 'x': r7_xc, + 'y': r7_yc, + 'onCurve': false }, { 'x': r7_x, 'y': r7_y, @@ -85,242 +74,262 @@ }); return _r7_t0; }; - r0_Stroke['prototype']['arc-vh-to'] = function _r0_t7(r8_x, r8_y) { - var r8_x, r8_y, r8_last, _r8_t0; + r0_Stroke['prototype']['cubic-to'] = function _r0_t7(r8_x1, r8_y1, r8_x2, r8_y2, r8_x, r8_y) { + var r8_x1, r8_y1, r8_x2, r8_y2, r8_x, r8_y, _r8_t0; _r8_t0 = this; - r8_last = _r8_t0['points'][_r8_t0['points']['length'] - 1]; - _r8_t0['cubic-to'](r8_last['x'], r8_last['y'] + r0_BKAPPA * (r8_y - r8_last['y']), r8_x + r0_BKAPPA * (r8_last['x'] - r8_x), r8_y, r8_x, r8_y); + _r8_t0['points']['push']({ + 'x': r8_x1, + 'y': r8_y1, + 'onCurve': false, + 'cubic': true + }, { + 'x': r8_x2, + 'y': r8_y2, + 'onCurve': false, + 'cubic': true + }, { + 'x': r8_x, + 'y': r8_y, + 'onCurve': true + }); return _r8_t0; }; - r0_Stroke['prototype']['arc-hv-to'] = function _r0_t8(r9_x, r9_y) { + r0_Stroke['prototype']['arc-vh-to'] = function _r0_t8(r9_x, r9_y) { var r9_x, r9_y, r9_last, _r9_t0; _r9_t0 = this; r9_last = _r9_t0['points'][_r9_t0['points']['length'] - 1]; - _r9_t0['cubic-to'](r9_last['x'] + r0_BKAPPA * (r9_x - r9_last['x']), r9_last['y'], r9_x, r9_y + r0_BKAPPA * (r9_last['y'] - r9_y), r9_x, r9_y); + _r9_t0['cubic-to'](r9_last['x'], r9_last['y'] + r0_BKAPPA * (r9_y - r9_last['y']), r9_x + r0_BKAPPA * (r9_last['x'] - r9_x), r9_y, r9_x, r9_y); return _r9_t0; }; - r0_dforward = function _r0_t9(r10_p0, r10_p1, r10_p2, r10_p3) { - var r10_p0, r10_p1, r10_p2, r10_p3; - return { - 'x': r10_p0['x'] + (-11 / 6 * r10_p0['x'] + 3 * r10_p1['x'] - 3 / 2 * r10_p2['x'] + r10_p3['x'] / 3) / r0_TINY * r0_LITTLE, - 'y': r10_p0['y'] + (-11 / 6 * r10_p0['y'] + 3 * r10_p1['y'] - 3 / 2 * r10_p2['y'] + r10_p3['y'] / 3) / r0_TINY * r0_LITTLE - }; + r0_Stroke['prototype']['arc-hv-to'] = function _r0_t9(r10_x, r10_y) { + var r10_x, r10_y, r10_last, _r10_t0; + _r10_t0 = this; + r10_last = _r10_t0['points'][_r10_t0['points']['length'] - 1]; + _r10_t0['cubic-to'](r10_last['x'] + r0_BKAPPA * (r10_x - r10_last['x']), r10_last['y'], r10_x, r10_y + r0_BKAPPA * (r10_last['y'] - r10_y), r10_x, r10_y); + return _r10_t0; }; - r0_dbackward = function _r0_t10(r11_p0, r11_p1, r11_p2, r11_p3) { + r0_dforward = function _r0_t10(r11_p0, r11_p1, r11_p2, r11_p3) { var r11_p0, r11_p1, r11_p2, r11_p3; return { - 'x': r11_p0['x'] + (11 / 6 * r11_p0['x'] - 3 * r11_p1['x'] + 3 / 2 * r11_p2['x'] - r11_p3['x'] / 3) / r0_TINY * r0_LITTLE, - 'y': r11_p0['y'] + (11 / 6 * r11_p0['y'] - 3 * r11_p1['y'] + 3 / 2 * r11_p2['y'] - r11_p3['y'] / 3) / r0_TINY * r0_LITTLE + 'x': r11_p0['x'] + (-11 / 6 * r11_p0['x'] + 3 * r11_p1['x'] - 3 / 2 * r11_p2['x'] + r11_p3['x'] / 3) / r0_TINY * r0_LITTLE, + 'y': r11_p0['y'] + (-11 / 6 * r11_p0['y'] + 3 * r11_p1['y'] - 3 / 2 * r11_p2['y'] + r11_p3['y'] / 3) / r0_TINY * r0_LITTLE }; }; - r0_nonlinear = function _r0_t11(r12_a, r12_b, r12_c) { - var r12_a, r12_b, r12_c; - return Math['abs']((r12_c['y'] - r12_a['y']) * (r12_b['x'] - r12_a['x']) - (r12_c['x'] - r12_a['x']) * (r12_b['y'] - r12_a['y'])) > r0_TINY; + r0_dbackward = function _r0_t11(r12_p0, r12_p1, r12_p2, r12_p3) { + var r12_p0, r12_p1, r12_p2, r12_p3; + return { + 'x': r12_p0['x'] + (11 / 6 * r12_p0['x'] - 3 * r12_p1['x'] + 3 / 2 * r12_p2['x'] - r12_p3['x'] / 3) / r0_TINY * r0_LITTLE, + 'y': r12_p0['y'] + (11 / 6 * r12_p0['y'] - 3 * r12_p1['y'] + 3 / 2 * r12_p2['y'] - r12_p3['y'] / 3) / r0_TINY * r0_LITTLE + }; }; - r0_Stroke['prototype']['form-stroke'] = function _r0_t12(r13_d1, r13_d2) { - var r13_d1, r13_d2, r13_d1s, r13_d2s, r13_subSegments, r13_p0, r13_j, r13_p1, r13_p2, r13_p3, r13_f1, r13_f2, r13_left, r13_right, r13_seg, r13_curve, r13_sample, r13_t, r13_tn, r13_lthis, r13_rthis, r13_lnext, r13_rnext, r13_lnthis1, r13_rnthis1, r13_lnnext1, r13_rnnext1, r13_lnthis2, r13_rnthis2, r13_lnnext2, r13_rnnext2, r13_lnthis3, r13_rnthis3, r13_lnnext3, r13_rnnext3, r13_dlthis, r13_drthis, r13_dlnext, r13_drnext, r13_il, r13_ir, r13_last, r13_shape, _r13_t0, _r13_t1, _r13_t2, _r13_t3, _r13_t4, _r13_t5, _r13_t6, _r13_t7, _r13_t8, _r13_t9, _r13_t10, _r13_t11, _r13_t12, _r13_t13, _r13_t14, _r13_t15, _r13_t16, _r13_t17, _r13_t18, _r13_t19, _r13_t20, _r13_t21, _r13_t22, _r13_t23, _r13_t24, _r13_t25, _r13_t26, _r13_t27, _r13_t28, _r13_t29, _r13_t30, _r13_t31, _r13_t32, _r13_t33, _r13_t34, _r13_t35, _r13_t36, _r13_t37, _r13_t38; - _r13_t2 = this; - if (_r13_t2['points'][0]['d1'] >= 0) - _r13_t3 = _r13_t2['points'][0]['d1']; + r0_nonlinear = function _r0_t12(r13_a, r13_b, r13_c) { + var r13_a, r13_b, r13_c; + return Math['abs']((r13_c['y'] - r13_a['y']) * (r13_b['x'] - r13_a['x']) - (r13_c['x'] - r13_a['x']) * (r13_b['y'] - r13_a['y'])) > r0_TINY; + }; + r0_Stroke['prototype']['form-stroke'] = function _r0_t13(r14_d1, r14_d2) { + var r14_d1, r14_d2, r14_d1s, r14_d2s, r14_subSegments, r14_p0, r14_j, r14_p1, r14_p2, r14_p3, r14_f1, r14_f2, r14_left, r14_right, r14_seg, r14_curve, r14_sample, r14_t, r14_tn, r14_lthis, r14_rthis, r14_lnext, r14_rnext, r14_lnthis1, r14_rnthis1, r14_lnnext1, r14_rnnext1, r14_lnthis2, r14_rnthis2, r14_lnnext2, r14_rnnext2, r14_lnthis3, r14_rnthis3, r14_lnnext3, r14_rnnext3, r14_dlthis, r14_drthis, r14_dlnext, r14_drnext, r14_il, r14_ir, r14_last, r14_shape, _r14_t0, _r14_t1, _r14_t2, _r14_t3, _r14_t4, _r14_t5, _r14_t6, _r14_t7, _r14_t8, _r14_t9, _r14_t10, _r14_t11, _r14_t12, _r14_t13, _r14_t14, _r14_t15, _r14_t16, _r14_t17, _r14_t18, _r14_t19, _r14_t20, _r14_t21, _r14_t22, _r14_t23, _r14_t24, _r14_t25, _r14_t26, _r14_t27, _r14_t28, _r14_t29, _r14_t30, _r14_t31, _r14_t32, _r14_t33, _r14_t34, _r14_t35, _r14_t36, _r14_t37, _r14_t38; + _r14_t2 = this; + if (_r14_t2['points'][0]['d1'] >= 0) + _r14_t3 = _r14_t2['points'][0]['d1']; else - _r13_t3 = r13_d1; - _r13_t4 = r13_d1 = _r13_t3; - r13_d1s = [_r13_t4]; - if (_r13_t2['points'][0]['d2'] >= 0) - _r13_t5 = _r13_t2['points'][0]['d2']; + _r14_t3 = r14_d1; + _r14_t4 = r14_d1 = _r14_t3; + r14_d1s = [_r14_t4]; + if (_r14_t2['points'][0]['d2'] >= 0) + _r14_t5 = _r14_t2['points'][0]['d2']; else - _r13_t5 = r13_d2; - _r13_t6 = r13_d2 = _r13_t5; - r13_d2s = [_r13_t6]; - r13_subSegments = []; - r13_p0 = _r13_t2['points'][0]; - r13_j = 1; - for (; r13_j < this['points']['length']; r13_j = r13_j + 1) { - r13_p1 = _r13_t2['points'][r13_j]; - if (r13_p1['onCurve']) { - r13_subSegments['push']([ - r13_p0, + _r14_t5 = r14_d2; + _r14_t6 = r14_d2 = _r14_t5; + r14_d2s = [_r14_t6]; + r14_subSegments = []; + r14_p0 = _r14_t2['points'][0]; + r14_j = 1; + for (; r14_j < this['points']['length']; r14_j = r14_j + 1) { + r14_p1 = _r14_t2['points'][r14_j]; + if (r14_p1['onCurve']) { + r14_subSegments['push']([ + r14_p0, { - 'x': (r13_p0['x'] + r13_p1['x']) / 2, - 'y': (r13_p0['y'] + r13_p1['y']) / 2 + 'x': (r14_p0['x'] + r14_p1['x']) / 2, + 'y': (r14_p0['y'] + r14_p1['y']) / 2 }, - r13_p1 + r14_p1 ]); - _r13_t7 = r13_d1s; - _r13_t8 = _r13_t7['push']; - if (r13_p1['d1'] >= 0) - _r13_t9 = r13_p1['d1']; + _r14_t7 = r14_d1s; + _r14_t8 = _r14_t7['push']; + if (r14_p1['d1'] >= 0) + _r14_t9 = r14_p1['d1']; else - _r13_t9 = r13_d1; - _r13_t10 = r13_d1 = _r13_t9; - _r13_t8['call'](_r13_t7, _r13_t10); - _r13_t11 = r13_d2s; - _r13_t12 = _r13_t11['push']; - if (r13_p1['d2'] >= 0) - _r13_t13 = r13_p1['d2']; + _r14_t9 = r14_d1; + _r14_t10 = r14_d1 = _r14_t9; + _r14_t8['call'](_r14_t7, _r14_t10); + _r14_t11 = r14_d2s; + _r14_t12 = _r14_t11['push']; + if (r14_p1['d2'] >= 0) + _r14_t13 = r14_p1['d2']; else - _r13_t13 = r13_d2; - _r13_t14 = r13_d2 = _r13_t13; - _r13_t12['call'](_r13_t11, _r13_t14); - r13_p0 = r13_p1; - } else if (r13_p1['cubic']) { - r13_p2 = _r13_t2['points'][r13_j + 1]; - r13_p3 = _r13_t2['points'][r13_j + 2]; - _r13_t15 = r13_d1s; - _r13_t16 = _r13_t15['push']; - if (r13_p3['d1'] >= 0) - _r13_t17 = r13_p3['d1']; + _r14_t13 = r14_d2; + _r14_t14 = r14_d2 = _r14_t13; + _r14_t12['call'](_r14_t11, _r14_t14); + r14_p0 = r14_p1; + } else if (r14_p1['cubic']) { + r14_p2 = _r14_t2['points'][r14_j + 1]; + r14_p3 = _r14_t2['points'][r14_j + 2]; + _r14_t15 = r14_d1s; + _r14_t16 = _r14_t15['push']; + if (r14_p3['d1'] >= 0) + _r14_t17 = r14_p3['d1']; else - _r13_t17 = r13_d1; - _r13_t18 = r13_d1 = _r13_t17; - _r13_t16['call'](_r13_t15, _r13_t18); - _r13_t19 = r13_d2s; - _r13_t20 = _r13_t19['push']; - if (r13_p3['d2'] >= 0) - _r13_t21 = r13_p3['d2']; + _r14_t17 = r14_d1; + _r14_t18 = r14_d1 = _r14_t17; + _r14_t16['call'](_r14_t15, _r14_t18); + _r14_t19 = r14_d2s; + _r14_t20 = _r14_t19['push']; + if (r14_p3['d2'] >= 0) + _r14_t21 = r14_p3['d2']; else - _r13_t21 = r13_d2; - _r13_t22 = r13_d2 = _r13_t21; - _r13_t20['call'](_r13_t19, _r13_t22); - r13_subSegments['push']([ - r13_p0, - r13_p1, - r13_p2, - r13_p3 + _r14_t21 = r14_d2; + _r14_t22 = r14_d2 = _r14_t21; + _r14_t20['call'](_r14_t19, _r14_t22); + r14_subSegments['push']([ + r14_p0, + r14_p1, + r14_p2, + r14_p3 ]); - r13_p0 = r13_p3; - r13_j = r13_j + 2; + r14_p0 = r14_p3; + r14_j = r14_j + 2; } else if (true) { - r13_p2 = _r13_t2['points'][r13_j + 1]; - _r13_t23 = r13_d1s; - _r13_t24 = _r13_t23['push']; - if (r13_p2['d1'] >= 0) - _r13_t25 = r13_p2['d1']; + r14_p2 = _r14_t2['points'][r14_j + 1]; + _r14_t23 = r14_d1s; + _r14_t24 = _r14_t23['push']; + if (r14_p2['d1'] >= 0) + _r14_t25 = r14_p2['d1']; else - _r13_t25 = r13_d1; - _r13_t26 = r13_d1 = _r13_t25; - _r13_t24['call'](_r13_t23, _r13_t26); - _r13_t27 = r13_d2s; - _r13_t28 = _r13_t27['push']; - if (r13_p2['d2'] >= 0) - _r13_t29 = r13_p2['d2']; + _r14_t25 = r14_d1; + _r14_t26 = r14_d1 = _r14_t25; + _r14_t24['call'](_r14_t23, _r14_t26); + _r14_t27 = r14_d2s; + _r14_t28 = _r14_t27['push']; + if (r14_p2['d2'] >= 0) + _r14_t29 = r14_p2['d2']; else - _r13_t29 = r13_d2; - _r13_t30 = r13_d2 = _r13_t29; - _r13_t28['call'](_r13_t27, _r13_t30); - r13_subSegments['push']([ - r13_p0, - r13_p1, - r13_p2 + _r14_t29 = r14_d2; + _r14_t30 = r14_d2 = _r14_t29; + _r14_t28['call'](_r14_t27, _r14_t30); + r14_subSegments['push']([ + r14_p0, + r14_p1, + r14_p2 ]); - r13_p0 = r13_p2; - r13_j = r13_j + 1; + r14_p0 = r14_p2; + r14_j = r14_j + 1; } else void 0; } - r13_f1 = r0_Smooth(r13_d1s, { 'method': 'cubic' }); - r13_f2 = r0_Smooth(r13_d2s, { 'method': 'cubic' }); - r13_left = []; - r13_right = []; - r13_j = 0; - for (; r13_j < r13_subSegments['length']; r13_j = r13_j + 1) { - r13_seg = r13_subSegments[r13_j]; - if (r13_seg['length'] > 3) - _r13_t31 = new r0_Bezier(r13_seg[0]['x'], r13_seg[0]['y'], r13_seg[1]['x'], r13_seg[1]['y'], r13_seg[2]['x'], r13_seg[2]['y'], r13_seg[3]['x'], r13_seg[3]['y']); + r14_f1 = r0_smooth(r0_xn$rangearray$1aao(0, r14_d1s['length']), r14_d1s); + r14_f2 = r0_smooth(r0_xn$rangearray$1aao(0, r14_d2s['length']), r14_d2s); + r14_left = []; + r14_right = []; + r14_j = 0; + for (; r14_j < r14_subSegments['length']; r14_j = r14_j + 1) { + r14_seg = r14_subSegments[r14_j]; + if (r14_seg['length'] > 3) + _r14_t31 = new r0_Bezier(r14_seg[0]['x'], r14_seg[0]['y'], r14_seg[1]['x'], r14_seg[1]['y'], r14_seg[2]['x'], r14_seg[2]['y'], r14_seg[3]['x'], r14_seg[3]['y']); else - _r13_t31 = new r0_Bezier(r13_seg[0]['x'], r13_seg[0]['y'], r13_seg[1]['x'], r13_seg[1]['y'], r13_seg[2]['x'], r13_seg[2]['y']); - r13_curve = _r13_t31; - _r13_t0 = 0; - _r13_t1 = r0_SAMPLES; - r13_sample = _r13_t0; - for (; r13_sample < _r13_t1; r13_sample = r13_sample + 1) { - r13_t = r13_j + r13_sample / r0_SAMPLES; - r13_tn = r13_j + (r13_sample + 1) / r0_SAMPLES; - r13_lthis = r13_curve['offset'](r13_sample / r0_SAMPLES, r13_f1(r13_t)); - r13_rthis = r13_curve['offset'](r13_sample / r0_SAMPLES, -r13_f2(r13_t)); - r13_lnext = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES, r13_f1(r13_tn)); - r13_rnext = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES, -r13_f2(r13_tn)); - r13_lnthis1 = r13_curve['offset'](r13_sample / r0_SAMPLES + r0_TINY, r13_f1(r13_t + r0_TINY)); - r13_rnthis1 = r13_curve['offset'](r13_sample / r0_SAMPLES + r0_TINY, -r13_f2(r13_t + r0_TINY)); - r13_lnnext1 = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES - r0_TINY, r13_f1(r13_tn - r0_TINY)); - r13_rnnext1 = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES - r0_TINY, -r13_f2(r13_tn - r0_TINY)); - r13_lnthis2 = r13_curve['offset'](r13_sample / r0_SAMPLES + r0_TINY * 2, r13_f1(r13_t + r0_TINY * 2)); - r13_rnthis2 = r13_curve['offset'](r13_sample / r0_SAMPLES + r0_TINY * 2, -r13_f2(r13_t + r0_TINY * 2)); - r13_lnnext2 = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES - r0_TINY * 2, r13_f1(r13_tn - r0_TINY * 2)); - r13_rnnext2 = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES - r0_TINY * 2, -r13_f2(r13_tn - r0_TINY * 2)); - r13_lnthis3 = r13_curve['offset'](r13_sample / r0_SAMPLES + r0_TINY * 3, r13_f1(r13_t + r0_TINY * 3)); - r13_rnthis3 = r13_curve['offset'](r13_sample / r0_SAMPLES + r0_TINY * 3, -r13_f2(r13_t + r0_TINY * 3)); - r13_lnnext3 = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES - r0_TINY * 3, r13_f1(r13_tn - r0_TINY * 3)); - r13_rnnext3 = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES - r0_TINY * 3, -r13_f2(r13_tn - r0_TINY * 3)); - r13_dlthis = r0_dforward(r13_lthis, r13_lnthis1, r13_lnthis2, r13_lnthis3); - r13_drthis = r0_dforward(r13_rthis, r13_rnthis1, r13_rnthis2, r13_rnthis3); - r13_dlnext = r0_dbackward(r13_lnext, r13_lnnext1, r13_lnnext2, r13_lnnext3); - r13_drnext = r0_dbackward(r13_rnext, r13_rnnext2, r13_rnnext2, r13_rnnext3); - r13_il = r0_intersection(r13_lthis['x'], r13_lthis['y'], r13_dlthis['x'], r13_dlthis['y'], r13_lnext['x'], r13_lnext['y'], r13_dlnext['x'], r13_dlnext['y']); - r13_ir = r0_intersection(r13_rthis['x'], r13_rthis['y'], r13_drthis['x'], r13_drthis['y'], r13_rnext['x'], r13_rnext['y'], r13_drnext['x'], r13_drnext['y']); - if (r13_il['x'] !== null && r13_il['y'] !== null && r0_nonlinear(r13_lthis, r13_il, r13_lnext)) { - r13_left['push']({ - 'x': r13_lthis['x'], - 'y': r13_lthis['y'], + _r14_t31 = new r0_Bezier(r14_seg[0]['x'], r14_seg[0]['y'], r14_seg[1]['x'], r14_seg[1]['y'], r14_seg[2]['x'], r14_seg[2]['y']); + r14_curve = _r14_t31; + _r14_t0 = 0; + _r14_t1 = r0_SAMPLES; + r14_sample = _r14_t0; + for (; r14_sample < _r14_t1; r14_sample = r14_sample + 1) { + r14_t = r14_j + r14_sample / r0_SAMPLES; + r14_tn = r14_j + (r14_sample + 1) / r0_SAMPLES; + r14_lthis = r14_curve['offset'](r14_sample / r0_SAMPLES, r14_f1(r14_t)); + r14_rthis = r14_curve['offset'](r14_sample / r0_SAMPLES, -r14_f2(r14_t)); + r14_lnext = r14_curve['offset']((r14_sample + 1) / r0_SAMPLES, r14_f1(r14_tn)); + r14_rnext = r14_curve['offset']((r14_sample + 1) / r0_SAMPLES, -r14_f2(r14_tn)); + r14_lnthis1 = r14_curve['offset'](r14_sample / r0_SAMPLES + r0_TINY, r14_f1(r14_t + r0_TINY)); + r14_rnthis1 = r14_curve['offset'](r14_sample / r0_SAMPLES + r0_TINY, -r14_f2(r14_t + r0_TINY)); + r14_lnnext1 = r14_curve['offset']((r14_sample + 1) / r0_SAMPLES - r0_TINY, r14_f1(r14_tn - r0_TINY)); + r14_rnnext1 = r14_curve['offset']((r14_sample + 1) / r0_SAMPLES - r0_TINY, -r14_f2(r14_tn - r0_TINY)); + r14_lnthis2 = r14_curve['offset'](r14_sample / r0_SAMPLES + r0_TINY * 2, r14_f1(r14_t + r0_TINY * 2)); + r14_rnthis2 = r14_curve['offset'](r14_sample / r0_SAMPLES + r0_TINY * 2, -r14_f2(r14_t + r0_TINY * 2)); + r14_lnnext2 = r14_curve['offset']((r14_sample + 1) / r0_SAMPLES - r0_TINY * 2, r14_f1(r14_tn - r0_TINY * 2)); + r14_rnnext2 = r14_curve['offset']((r14_sample + 1) / r0_SAMPLES - r0_TINY * 2, -r14_f2(r14_tn - r0_TINY * 2)); + r14_lnthis3 = r14_curve['offset'](r14_sample / r0_SAMPLES + r0_TINY * 3, r14_f1(r14_t + r0_TINY * 3)); + r14_rnthis3 = r14_curve['offset'](r14_sample / r0_SAMPLES + r0_TINY * 3, -r14_f2(r14_t + r0_TINY * 3)); + r14_lnnext3 = r14_curve['offset']((r14_sample + 1) / r0_SAMPLES - r0_TINY * 3, r14_f1(r14_tn - r0_TINY * 3)); + r14_rnnext3 = r14_curve['offset']((r14_sample + 1) / r0_SAMPLES - r0_TINY * 3, -r14_f2(r14_tn - r0_TINY * 3)); + r14_dlthis = r0_dforward(r14_lthis, r14_lnthis1, r14_lnthis2, r14_lnthis3); + r14_drthis = r0_dforward(r14_rthis, r14_rnthis1, r14_rnthis2, r14_rnthis3); + r14_dlnext = r0_dbackward(r14_lnext, r14_lnnext1, r14_lnnext2, r14_lnnext3); + r14_drnext = r0_dbackward(r14_rnext, r14_rnnext2, r14_rnnext2, r14_rnnext3); + r14_il = r0_intersection(r14_lthis['x'], r14_lthis['y'], r14_dlthis['x'], r14_dlthis['y'], r14_lnext['x'], r14_lnext['y'], r14_dlnext['x'], r14_dlnext['y']); + r14_ir = r0_intersection(r14_rthis['x'], r14_rthis['y'], r14_drthis['x'], r14_drthis['y'], r14_rnext['x'], r14_rnext['y'], r14_drnext['x'], r14_drnext['y']); + if (r14_il['x'] !== null && r14_il['y'] !== null && r0_nonlinear(r14_lthis, r14_il, r14_lnext)) { + r14_left['push']({ + 'x': r14_lthis['x'], + 'y': r14_lthis['y'], 'onCurve': true }, { - 'x': r13_il['x'], - 'y': r13_il['y'], + 'x': r14_il['x'], + 'y': r14_il['y'], 'onCurve': false }); } else { - r13_left['push']({ - 'x': r13_lthis['x'], - 'y': r13_lthis['y'], + r14_left['push']({ + 'x': r14_lthis['x'], + 'y': r14_lthis['y'], 'onCurve': true }); } - if (r13_ir['x'] !== null && r13_ir['y'] !== null && r0_nonlinear(r13_rthis, r13_ir, r13_rnext)) { - r13_right['push']({ - 'x': r13_rthis['x'], - 'y': r13_rthis['y'], + if (r14_ir['x'] !== null && r14_ir['y'] !== null && r0_nonlinear(r14_rthis, r14_ir, r14_rnext)) { + r14_right['push']({ + 'x': r14_rthis['x'], + 'y': r14_rthis['y'], 'onCurve': true }, { - 'x': r13_ir['x'], - 'y': r13_ir['y'], + 'x': r14_ir['x'], + 'y': r14_ir['y'], 'onCurve': false }); } else { - r13_right['push']({ - 'x': r13_rthis['x'], - 'y': r13_rthis['y'], + r14_right['push']({ + 'x': r14_rthis['x'], + 'y': r14_rthis['y'], 'onCurve': true }); } } - _r13_t32 = r13_left; - _r13_t33 = _r13_t32['push']; - r13_last = r13_curve['offset'](1, r13_f1(r13_j + 1)); - _r13_t34 = { - 'x': r13_last['x'], - 'y': r13_last['y'], + _r14_t32 = r14_left; + _r14_t33 = _r14_t32['push']; + r14_last = r14_curve['offset'](1, r14_f1(r14_j + 1)); + _r14_t34 = { + 'x': r14_last['x'], + 'y': r14_last['y'], 'onCurve': true }; - _r13_t33['call'](_r13_t32, _r13_t34); - _r13_t35 = r13_right; - _r13_t36 = _r13_t35['push']; - r13_last = r13_curve['offset'](1, -r13_f2(r13_j + 1)); - _r13_t37 = { - 'x': r13_last['x'], - 'y': r13_last['y'], + _r14_t33['call'](_r14_t32, _r14_t34); + _r14_t35 = r14_right; + _r14_t36 = _r14_t35['push']; + r14_last = r14_curve['offset'](1, -r14_f2(r14_j + 1)); + _r14_t37 = { + 'x': r14_last['x'], + 'y': r14_last['y'], 'onCurve': true }; - _r13_t36['call'](_r13_t35, _r13_t37); + _r14_t36['call'](_r14_t35, _r14_t37); } - r13_shape = r13_left['concat'](r13_right['reverse']())['map'](function _r13_t38(r15_p) { - var r15_p; + r14_shape = r14_left['concat'](r14_right['reverse']())['map'](function _r14_t38(r16_p) { + var r16_p; return { - 'x': r15_p['x'], - 'y': r15_p['y'], - 'onCurve': r15_p['onCurve'] + 'x': r16_p['x'], + 'y': r16_p['y'], + 'onCurve': r16_p['onCurve'] }; }); - return [r13_shape]; + return [r14_shape]; }; exports['Stroke'] = r0_Stroke; } diff --git a/support/stroke.patel b/support/stroke.patel index 3b2b710..1234a25 100644 --- a/support/stroke.patel +++ b/support/stroke.patel @@ -1,7 +1,13 @@ -define Smooth [require './smooth'].Smooth +define smooth [require './monotonic-interpolate'].createInterpolant define intersection [require './intersection'].intersection define Bezier [require 'bezier-js'] +define [range-array low high] : begin { + local a () + for [local j low] [j < high] [inc j] : a.push j + return a +} + define SAMPLES 4 define TINY 0.0001 define LITTLE 0.01 @@ -97,8 +103,8 @@ define [Stroke.prototype.form-stroke d1 d2] : begin { } } } - local f1 : Smooth d1s (.method 'cubic') - local f2 : Smooth d2s (.method 'cubic') + local f1 : smooth [range-array 0 d1s.length] d1s + local f2 : smooth [range-array 0 d2s.length] d2s local left () local right () for [local j 0] [j < subSegments.length] [inc j] : begin {