Move font building related files to font-src
This commit is contained in:
parent
9a2f862631
commit
c48bc20aa2
56 changed files with 18 additions and 18 deletions
114
font-src/support/monotonic-interpolate.js
Normal file
114
font-src/support/monotonic-interpolate.js
Normal file
|
@ -0,0 +1,114 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = function (xs, ys) {
|
||||
let 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 () {
|
||||
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
|
||||
let result = +ys[0];
|
||||
return function () {
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
// Rearrange xs and ys so that xs is sorted
|
||||
let indexes = [];
|
||||
for (i = 0; i < length; i++) {
|
||||
indexes.push(i);
|
||||
}
|
||||
indexes.sort(function (a, b) {
|
||||
return xs[a] < xs[b] ? -1 : 1;
|
||||
});
|
||||
let 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
|
||||
let dys = [],
|
||||
dxs = [],
|
||||
ms = [];
|
||||
for (i = 0; i < length - 1; i++) {
|
||||
const 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
|
||||
let c1s = [ms[0]];
|
||||
for (i = 0; i < dxs.length - 1; i++) {
|
||||
const m = ms[i],
|
||||
mNext = ms[i + 1];
|
||||
if (m * mNext <= 0) {
|
||||
c1s.push(0);
|
||||
} else {
|
||||
const 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
|
||||
let c2s = [],
|
||||
c3s = [];
|
||||
for (i = 0; i < c1s.length - 1; i++) {
|
||||
const 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
|
||||
let 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
|
||||
let low = 0,
|
||||
mid,
|
||||
high = c3s.length - 1;
|
||||
while (low <= high) {
|
||||
mid = Math.floor(0.5 * (low + high));
|
||||
let 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
|
||||
let diff = x - xs[i],
|
||||
diffSq = diff * diff;
|
||||
return ys[i] + c1s[i] * diff + c2s[i] * diffSq + c3s[i] * diff * diffSq;
|
||||
};
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue