Files
NapCatQQ/.pnpm-store/v3/files/07/5bb8b11439364f0235b7ca14c7663f9c4afe05280a46ac5ccdc320109dd4a46ce4ad855513d0a97b484bfc17b1efdbc8f622b2763393b40b0742b1d9fac79d
T
TanTan e311ca3275
Build NapCat Artifacts / Type Check & Test (push) Waiting to run
docs: 仓库链接指向本镜像仓库
2026-11-13 09:25:58 +08:00

94 lines
2.1 KiB
Plaintext

/**
* @file 三次贝塞尔转二次贝塞尔
* @author mengke01(kekee000@gmail.com)
*
* references:
* https://github.com/search?utf8=%E2%9C%93&q=svg2ttf
* http://www.caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html
*
*/
function toQuad(p1, c1, c2, p2) {
// Quad control point is (3*c2 - p2 + 3*c1 - p1)/4
const x = (3 * c2.x - p2.x + 3 * c1.x - p1.x) / 4;
const y = (3 * c2.y - p2.y + 3 * c1.y - p1.y) / 4;
return [
p1,
{x, y},
p2
];
}
/**
* 三次贝塞尔转二次贝塞尔
*
* @param {Object} p1 开始点
* @param {Object} c1 控制点1
* @param {Object} c2 控制点2
* @param {Object} p2 结束点
* @return {Array} 二次贝塞尔控制点
*/
export default function bezierCubic2Q2(p1, c1, c2, p2) {
// 判断极端情况,控制点和起止点一样
if (p1.x === c1.x && p1.y === c1.y && c2.x === p2.x && c2.y === p2.y) {
return [
[
p1,
{
x: (p1.x + p2.x) / 2,
y: (p1.y + p2.y) / 2
},
p2
]
];
}
const mx = p2.x - 3 * c2.x + 3 * c1.x - p1.x;
const my = p2.y - 3 * c2.y + 3 * c1.y - p1.y;
// control points near
if (mx * mx + my * my <= 4) {
return [
toQuad(p1, c1, c2, p2)
];
}
// Split to 2 qubic beziers by midpoints
// (p2 + 3*c2 + 3*c1 + p1)/8
const mp = {
x: (p2.x + 3 * c2.x + 3 * c1.x + p1.x) / 8,
y: (p2.y + 3 * c2.y + 3 * c1.y + p1.y) / 8
};
return [
toQuad(
p1,
{
x: (p1.x + c1.x) / 2,
y: (p1.y + c1.y) / 2
},
{
x: (p1.x + 2 * c1.x + c2.x) / 4,
y: (p1.y + 2 * c1.y + c2.y) / 4
},
mp
),
toQuad(
mp,
{
x: (p2.x + c1.x + 2 * c2.x) / 4,
y: (p2.y + c1.y + 2 * c2.y) / 4
},
{
x: (p2.x + c2.x) / 2,
y: (p2.y + c2.y) / 2
},
p2
)
];
}