UNPKG

kipm

Version:

KiCad component package manager

132 lines (120 loc) 3.93 kB
// svg_path_parser.js // -------------------- Class Definitions -------------------- class SvgPathMoveTo { constructor({ start_x, start_y }) { this.start_x = parseFloat(start_x); this.start_y = parseFloat(start_y); } static get fields() { return ["start_x", "start_y"]; } } class SvgPathLineTo { constructor({ pos_x, pos_y }) { this.pos_x = parseFloat(pos_x); this.pos_y = parseFloat(pos_y); } static get fields() { return ["pos_x", "pos_y"]; } } class SvgPathEllipticalArc { constructor({ radius_x, radius_y, x_axis_rotation, flag_large_arc, flag_sweep, end_x, end_y, }) { this.radius_x = parseFloat(radius_x); this.radius_y = parseFloat(radius_y); this.x_axis_rotation = parseFloat(x_axis_rotation); // Convert flag values to booleans this.flag_large_arc = flag_large_arc === "1" || flag_large_arc === 1; this.flag_sweep = flag_sweep === "1" || flag_sweep === 1; this.end_x = parseFloat(end_x); this.end_y = parseFloat(end_y); } static get fields() { return [ "radius_x", "radius_y", "x_axis_rotation", "flag_large_arc", "flag_sweep", "end_x", "end_y", ]; } } class SvgPathClosePath { constructor() { // No properties } static get fields() { return []; } } // -------------------- Handlers Mapping -------------------- const svgPathHandlers = { "M": [SvgPathMoveTo, 2], "A": [SvgPathEllipticalArc, 7], "L": [SvgPathLineTo, 2], "Z": [SvgPathClosePath, 0], }; // -------------------- Parsing Function -------------------- /** * Parses an SVG path string into an array of command objects. * @param {string} svgPath - The SVG path string. * @returns {Array<Object>} An array of command objects. */ function parseSvgPath(svgPath) { // Ensure the path ends with a space if (!svgPath.endsWith(" ")) { svgPath += " "; } // Replace commas with spaces svgPath = svgPath.replace(/,/g, " "); // Use regex to match command letters followed by their arguments. // The regex matches a letter and a group of characters (digits, spaces, plus, minus, dots). const regex = /([a-zA-Z])([ ,\-\+.\d]+)/g; const matches = svgPath.matchAll(regex); const parsedPath = []; for (const match of matches) { const command = match[1]; const argStr = match[2]; if (svgPathHandlers.hasOwnProperty(command)) { const [CmdClass, nbArgs] = svgPathHandlers[command]; // Split arguments on whitespace (ignoring extra spaces) const args = argStr.trim().split(/\s+/); if (nbArgs === 0) { // For commands like "Z" with no arguments. parsedPath.push(new CmdClass()); } else { // Process groups of nbArgs arguments. for (let i = 0; i < args.length; i += nbArgs) { // Create an object mapping field names to corresponding argument values. const fields = CmdClass.fields; const obj = {}; for (let j = 0; j < nbArgs; j++) { // Use undefined if there are not enough arguments. obj[fields[j]] = args[i + j]; } parsedPath.push(new CmdClass(obj)); } } } else { console.warn(`SVG command "${command}" not supported`); } } return parsedPath; } module.exports = { parseSvgPath, SvgPathMoveTo, SvgPathLineTo, SvgPathEllipticalArc, SvgPathClosePath, };