Further cleanup of point types
This commit is contained in:
parent
82cea0e06d
commit
e58a6965db
14 changed files with 231 additions and 252 deletions
|
@ -34,47 +34,6 @@ exports.OffsetCurve = class OffsetCurve {
|
|||
}
|
||||
};
|
||||
|
||||
exports.convertContourToCubic = function convertContourToCubic(contour) {
|
||||
if (!contour || !contour.length) return [];
|
||||
|
||||
const newContour = [];
|
||||
let z0 = contour[0];
|
||||
newContour.push(Point.cornerFrom(z0));
|
||||
|
||||
for (let j = 1; j < contour.length; j++) {
|
||||
const z = contour[j];
|
||||
if (z.on) {
|
||||
newContour.push(Point.cornerFrom(z));
|
||||
z0 = z;
|
||||
} else if (z.cubic) {
|
||||
const z1 = z;
|
||||
const z2 = contour[j + 1];
|
||||
const z3 = contour[j + 2];
|
||||
|
||||
newContour.push(Point.cubicOffFrom(z1));
|
||||
newContour.push(Point.cubicOffFrom(z2));
|
||||
newContour.push(Point.cornerFrom(z3));
|
||||
|
||||
z0 = z3;
|
||||
j += 2;
|
||||
} else {
|
||||
const zc = z;
|
||||
let zf = contour[j + 1] || contour[0];
|
||||
const zfIsCorner = zf.on;
|
||||
if (!zfIsCorner) zf = Point.cornerFrom(zc).mix(0.5, zf);
|
||||
|
||||
newContour.push(Point.cubicOffFrom(z0).mix(2 / 3, zc));
|
||||
newContour.push(Point.cubicOffFrom(zf).mix(2 / 3, zc));
|
||||
newContour.push(Point.cornerFrom(zf));
|
||||
|
||||
z0 = zf;
|
||||
if (zfIsCorner) j++;
|
||||
}
|
||||
}
|
||||
|
||||
return newContour;
|
||||
};
|
||||
|
||||
exports.convertShapeToArcs = function convertShapeToArcs(shape) {
|
||||
return shape.map(convertContourToArcs);
|
||||
};
|
||||
|
@ -83,48 +42,55 @@ function convertContourToArcs(contour) {
|
|||
if (!contour || !contour.length) return [];
|
||||
|
||||
const newContour = [];
|
||||
let z0 = Point.cornerFrom(contour[0]);
|
||||
let z0 = Point.from(Point.Type.Corner, contour[0]);
|
||||
|
||||
for (let j = 1; j < contour.length; j++) {
|
||||
const z = contour[j];
|
||||
if (z.on) {
|
||||
newContour.push(
|
||||
TypoGeom.Arcs.Bez3.fromStraightSegment(
|
||||
new TypoGeom.Arcs.StraightSegment(z0, Point.cornerFrom(z))
|
||||
)
|
||||
);
|
||||
z0 = z;
|
||||
} else if (z.cubic) {
|
||||
const z1 = z;
|
||||
const z2 = contour[j + 1];
|
||||
const z3 = contour[j + 2];
|
||||
newContour.push(
|
||||
new TypoGeom.Arcs.Bez3(
|
||||
z0,
|
||||
Point.cubicOffFrom(z1),
|
||||
Point.cubicOffFrom(z2),
|
||||
Point.cornerFrom(z3)
|
||||
)
|
||||
);
|
||||
z0 = z3;
|
||||
j += 2;
|
||||
} else {
|
||||
const zc = z;
|
||||
let zf = contour[j + 1] || contour[0];
|
||||
const zfIsCorner = zf.on;
|
||||
if (!zfIsCorner) zf = Point.cornerFrom(zc).mix(0.5, zf);
|
||||
switch (z.type) {
|
||||
case Point.Type.CubicStart: {
|
||||
const z1 = z;
|
||||
const z2 = contour[j + 1];
|
||||
const z3 = contour[j + 2];
|
||||
newContour.push(
|
||||
new TypoGeom.Arcs.Bez3(
|
||||
z0,
|
||||
Point.from(Point.Type.CubicStart, z1),
|
||||
Point.from(Point.Type.CubicEnd, z2),
|
||||
Point.from(Point.Type.Corner, z3)
|
||||
)
|
||||
);
|
||||
z0 = z3;
|
||||
j += 2;
|
||||
break;
|
||||
}
|
||||
case Point.Type.Quadratic: {
|
||||
const zc = z;
|
||||
let zf = contour[j + 1] || contour[0];
|
||||
const zfIsCorner = zf.type === Point.Type.contour;
|
||||
if (!zfIsCorner) zf = Point.from(Point.Type.Corner, zc).mix(0.5, zf);
|
||||
|
||||
newContour.push(
|
||||
new TypoGeom.Arcs.Bez3(
|
||||
z0,
|
||||
Point.cubicOffFrom(z0).mix(2 / 3, zc),
|
||||
Point.cubicOffFrom(zf).mix(2 / 3, zc),
|
||||
Point.cornerFrom(zf)
|
||||
)
|
||||
);
|
||||
newContour.push(
|
||||
new TypoGeom.Arcs.Bez3(
|
||||
z0,
|
||||
Point.from(Point.Type.CubicStart, z0).mix(2 / 3, zc),
|
||||
Point.from(Point.Type.CubicEnd, zf).mix(2 / 3, zc),
|
||||
Point.from(Point.Type.Corner, zf)
|
||||
)
|
||||
);
|
||||
|
||||
z0 = zf;
|
||||
if (zfIsCorner) j++;
|
||||
z0 = zf;
|
||||
if (zfIsCorner) j++;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
newContour.push(
|
||||
TypoGeom.Arcs.Bez3.fromStraightSegment(
|
||||
new TypoGeom.Arcs.StraightSegment(z0, Point.from(Point.Type.Corner, z))
|
||||
)
|
||||
);
|
||||
z0 = z;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,18 +112,18 @@ exports.BezToContoursSink = class BezToContoursSink {
|
|||
}
|
||||
moveTo(x, y) {
|
||||
this.endShape();
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, x, y, true));
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Corner, x, y));
|
||||
}
|
||||
lineTo(x, y) {
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, x, y, true));
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Corner, x, y));
|
||||
}
|
||||
curveTo(xc, yc, x, y) {
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, xc, yc, false, false));
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, x, y, true));
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Quadratic, xc, yc));
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Corner, x, y));
|
||||
}
|
||||
cubicTo(x1, y1, x2, y2, x, y) {
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, x1, y1, false, true));
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, x2, y2, false, true));
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, x, y, true));
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.CubicStart, x1, y1));
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.CubicEnd, x2, y2));
|
||||
this.lastContour.push(Point.transformedXY(this.gizmo, Point.Type.Corner, x, y));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -216,7 +216,7 @@ module.exports = class Glyph {
|
|||
for (let k = 0; k < c1.length; k++) {
|
||||
const z1 = c1[k],
|
||||
z2 = c2[k];
|
||||
if (z1.x !== z2.x || z1.y !== z2.y || z1.on !== z2.on) return;
|
||||
if (z1.x !== z2.x || z1.y !== z2.y || z1.type !== z2.type) return;
|
||||
}
|
||||
}
|
||||
this.semanticInclusions = [
|
||||
|
|
|
@ -1,71 +1,63 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = class Point {
|
||||
constructor(x, y, on, cubic) {
|
||||
class Point {
|
||||
constructor(type, x, y) {
|
||||
this.type = type;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.on = on;
|
||||
this.cubic = cubic;
|
||||
}
|
||||
get on() {
|
||||
throw new Error("Unreachable");
|
||||
}
|
||||
get cubic() {
|
||||
throw new Error("Unreachable");
|
||||
}
|
||||
add(z2) {
|
||||
return this.addScale(1, z2);
|
||||
}
|
||||
addScale(scale, z2) {
|
||||
return new Point(this.x + scale * z2.x, this.y + scale * z2.y, this.on, this.cubic);
|
||||
return new Point(this.type, this.x + scale * z2.x, this.y + scale * z2.y);
|
||||
}
|
||||
mix(scale, z2) {
|
||||
return new Point(
|
||||
this.type,
|
||||
this.x + scale * (z2.x - this.x),
|
||||
this.y + scale * (z2.y - this.y),
|
||||
this.on,
|
||||
this.cubic
|
||||
this.y + scale * (z2.y - this.y)
|
||||
);
|
||||
}
|
||||
scale(t) {
|
||||
return new Point(t * this.x, t * this.y, this.on, this.cubic);
|
||||
return new Point(this.type, t * this.x, t * this.y);
|
||||
}
|
||||
round(d) {
|
||||
return new Point(
|
||||
Math.round(d * this.x) / d,
|
||||
Math.round(d * this.y) / d,
|
||||
this.on,
|
||||
this.cubic
|
||||
);
|
||||
return new Point(this.type, Math.round(d * this.x) / d, Math.round(d * this.y) / d);
|
||||
}
|
||||
|
||||
static from(z, on, cubic) {
|
||||
return new Point(z.x || 0, z.y || 0, on, cubic);
|
||||
static from(type, z) {
|
||||
return new Point(type, z.x || 0, z.y || 0);
|
||||
}
|
||||
static cornerFrom(z) {
|
||||
return new Point(z.x || 0, z.y || 0, true, false);
|
||||
}
|
||||
static offFrom(z) {
|
||||
return new Point(z.x || 0, z.y || 0, false, false);
|
||||
}
|
||||
static cubicOffFrom(z) {
|
||||
return new Point(z.x || 0, z.y || 0, false, true);
|
||||
}
|
||||
static cornerFromXY(x, y) {
|
||||
return new Point(x || 0, y || 0, true, false);
|
||||
}
|
||||
static offFromXY(x, y) {
|
||||
return new Point(x || 0, y || 0, false, false);
|
||||
}
|
||||
static cubicOffFromXY(x, y) {
|
||||
return new Point(x || 0, y || 0, false, true);
|
||||
static fromXY(type, x, y) {
|
||||
return new Point(type, x || 0, y || 0);
|
||||
}
|
||||
static transformed(tfm, z) {
|
||||
return Point.transformedXY(tfm, z.x, z.y, z.on, z.cubic);
|
||||
return Point.transformedXY(tfm, z.type, z.x, z.y);
|
||||
}
|
||||
static transformedXY(tfm, x, y, on, cubic) {
|
||||
static transformedXY(tfm, type, x, y) {
|
||||
return new Point(
|
||||
type,
|
||||
x * tfm.xx + y * tfm.yx + tfm.x || 0,
|
||||
x * tfm.xy + y * tfm.yy + tfm.y || 0,
|
||||
on,
|
||||
cubic
|
||||
x * tfm.xy + y * tfm.yy + tfm.y || 0
|
||||
);
|
||||
}
|
||||
static translated(z, dx, dy) {
|
||||
return new Point(z.x + dx || 0, z.y + dy || 0, z.on, z.cubic);
|
||||
return new Point(z.type, z.x + dx || 0, z.y + dy || 0);
|
||||
}
|
||||
}
|
||||
|
||||
Point.Type = {
|
||||
Corner: 0,
|
||||
CubicStart: 1,
|
||||
CubicEnd: 2,
|
||||
Quadratic: 3
|
||||
};
|
||||
|
||||
module.exports = Point;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue