You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.4 KiB
130 lines
3.4 KiB
2 years ago
|
'use strict';
|
||
|
|
||
|
var _ = require('lodash');
|
||
|
var math = require('../math');
|
||
|
|
||
|
// Remove points, that looks like straight line
|
||
|
function simplify(contours, accuracy) {
|
||
|
return _.map(contours, function (contour) {
|
||
|
var i, curr, prev, next;
|
||
|
var p, pPrev, pNext;
|
||
|
|
||
|
// run from the end, to simplify array elements removal
|
||
|
for (i = contour.length - 2; i > 1; i--) {
|
||
|
prev = contour[i - 1];
|
||
|
next = contour[i + 1];
|
||
|
curr = contour[i];
|
||
|
|
||
|
// skip point (both oncurve & offcurve),
|
||
|
// if [prev,next] is straight line
|
||
|
if (prev.onCurve && next.onCurve) {
|
||
|
p = new math.Point(curr.x, curr.y);
|
||
|
pPrev = new math.Point(prev.x, prev.y);
|
||
|
pNext = new math.Point(next.x, next.y);
|
||
|
if (math.isInLine(pPrev, p, pNext, accuracy)) {
|
||
|
contour.splice(i, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return contour;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Remove interpolateable oncurve points
|
||
|
// Those should be in the middle of nebor offcurve points
|
||
|
function interpolate(contours, accuracy) {
|
||
|
return _.map(contours, function (contour) {
|
||
|
var resContour = [];
|
||
|
|
||
|
_.forEach(contour, function (point, idx) {
|
||
|
// Never skip first and last points
|
||
|
if (idx === 0 || idx === (contour.length - 1)) {
|
||
|
resContour.push(point);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var prev = contour[idx - 1];
|
||
|
var next = contour[idx + 1];
|
||
|
|
||
|
var p, pPrev, pNext;
|
||
|
|
||
|
// skip interpolateable oncurve points (if exactly between previous and next offcurves)
|
||
|
if (!prev.onCurve && point.onCurve && !next.onCurve) {
|
||
|
p = new math.Point(point.x, point.y);
|
||
|
pPrev = new math.Point(prev.x, prev.y);
|
||
|
pNext = new math.Point(next.x, next.y);
|
||
|
if (pPrev.add(pNext).div(2).sub(p).dist() < accuracy) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
// keep the rest
|
||
|
resContour.push(point);
|
||
|
});
|
||
|
return resContour;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function roundPoints(contours) {
|
||
|
return _.map(contours, function (contour) {
|
||
|
return _.map(contour, function (point) {
|
||
|
return { x: Math.round(point.x), y: Math.round(point.y), onCurve: point.onCurve };
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Remove closing point if it is the same as first point of contour.
|
||
|
// TTF doesn't need this point when drawing contours.
|
||
|
function removeClosingReturnPoints(contours) {
|
||
|
return _.map(contours, function (contour) {
|
||
|
var length = contour.length;
|
||
|
|
||
|
if (length > 1 &&
|
||
|
contour[0].x === contour[length - 1].x &&
|
||
|
contour[0].y === contour[length - 1].y) {
|
||
|
contour.splice(length - 1);
|
||
|
}
|
||
|
return contour;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function toRelative(contours) {
|
||
|
var prevPoint = { x: 0, y: 0 };
|
||
|
var resContours = [];
|
||
|
var resContour;
|
||
|
|
||
|
_.forEach(contours, function (contour) {
|
||
|
resContour = [];
|
||
|
resContours.push(resContour);
|
||
|
_.forEach(contour, function (point) {
|
||
|
resContour.push({
|
||
|
x: point.x - prevPoint.x,
|
||
|
y: point.y - prevPoint.y,
|
||
|
onCurve: point.onCurve
|
||
|
});
|
||
|
prevPoint = point;
|
||
|
});
|
||
|
});
|
||
|
return resContours;
|
||
|
}
|
||
|
|
||
|
function identifier(string, littleEndian) {
|
||
|
var result = 0;
|
||
|
|
||
|
for (var i = 0; i < string.length; i++) {
|
||
|
result = result << 8;
|
||
|
var index = littleEndian ? string.length - i - 1 : i;
|
||
|
|
||
|
result += string.charCodeAt(index);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
module.exports.interpolate = interpolate;
|
||
|
module.exports.simplify = simplify;
|
||
|
module.exports.roundPoints = roundPoints;
|
||
|
module.exports.removeClosingReturnPoints = removeClosingReturnPoints;
|
||
|
module.exports.toRelative = toRelative;
|
||
|
module.exports.identifier = identifier;
|
||
|
|