├── static ├── lib │ └── .gitignore ├── .gitignore ├── index.html ├── library.html ├── schematic.html ├── js │ ├── library.js │ ├── schematic.js │ ├── viewer.js │ ├── worker.js │ ├── common.js │ └── pcb.js ├── pcb.html └── viewer.html ├── .gitattributes ├── .gitignore ├── Procfile ├── dist ├── src │ ├── kicad-utils.js.map │ ├── kicad-utils.js │ ├── server.js.map │ ├── server.js │ ├── kicad-utils_cui.js.map │ ├── kicad-utils_cui.js │ ├── kicad_strokefont.js.map │ ├── kicad_strokefont.js │ ├── kicad_pcb_token.js.map │ ├── kicad_pcb_token.js │ ├── kicad_plotter.js.map │ └── kicad_lib.js.map ├── sketch.js.map ├── sketch2.js ├── sketch2.js.map ├── sketch3.js.map ├── sketch3.js └── sketch.js ├── src ├── kicad-utils.ts ├── server.ts ├── kicad-utils_cui.ts ├── kicad_strokefont.ts └── kicad_pcb_token.ts ├── tsconfig.json ├── README.md ├── package.json ├── test ├── kicad_strokefont.ts ├── kicad_pcb.ts ├── kicad_common.ts ├── kicad_sch.ts └── kicad_lib.ts ├── webpack.config.js ├── sketch2.ts ├── sketch3.ts └── sketch.ts /static/lib/.gitignore: -------------------------------------------------------------------------------- 1 | *.lib 2 | -------------------------------------------------------------------------------- /static/.gitignore: -------------------------------------------------------------------------------- 1 | kicad-library/ 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bundle.js binary 2 | *.js.map binary 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/test/ 3 | text.png 4 | text.svg 5 | tmp 6 | * (* *).* 7 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | devserver: node dist/src/server.js static/ 2 | watch-web: ./node_modules/.bin/webpack --watch 3 | watch-cui: tsc --watch 4 | -------------------------------------------------------------------------------- /dist/src/kicad-utils.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"kicad-utils.js","sourceRoot":"","sources":["../../src/kicad-utils.ts"],"names":[],"mappings":";;;;;AACA,mCAAmC;AAG1B,kBAAG;AAFZ,mCAAmC;AAErB,kBAAG;AADjB,mCAAmC;AAChB,kBAAG;AACtB,oCAA+B;AAC/B,wCAAmC;AACnC,qCAAgC;AAChC,yCAAoC;AACpC,yCAAoC"} -------------------------------------------------------------------------------- /src/kicad-utils.ts: -------------------------------------------------------------------------------- 1 | 2 | import * as Lib from "./kicad_lib"; 3 | import * as Sch from "./kicad_sch"; 4 | import * as Pcb from "./kicad_pcb"; 5 | export { Lib, Sch, Pcb }; 6 | export * from "./kicad_common"; 7 | export * from "./kicad_strokefont"; 8 | export * from "./kicad_plotter"; 9 | export * from "./kicad_sch_plotter"; 10 | export * from "./kicad_pcb_plotter"; 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strictNullChecks": true, 4 | "noUnusedLocals" : false, 5 | "noImplicitThis": true, 6 | "alwaysStrict": true, 7 | "outDir": "./dist/", 8 | "sourceMap": true, 9 | "noImplicitAny": true, 10 | "lib": ["dom", "ES2017"], 11 | "moduleResolution": "node", 12 | "module": "commonjs", 13 | "target": "esnext", 14 | "baseUrl": ".", 15 | "paths": { 16 | "*": [ 17 | "*", 18 | "src/*" 19 | ] 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /dist/src/kicad-utils.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function __export(m) { 3 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; 4 | } 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const Lib = require("./kicad_lib"); 7 | exports.Lib = Lib; 8 | const Sch = require("./kicad_sch"); 9 | exports.Sch = Sch; 10 | const Pcb = require("./kicad_pcb"); 11 | exports.Pcb = Pcb; 12 | __export(require("./kicad_common")); 13 | __export(require("./kicad_strokefont")); 14 | __export(require("./kicad_plotter")); 15 | __export(require("./kicad_sch_plotter")); 16 | __export(require("./kicad_pcb_plotter")); 17 | //# sourceMappingURL=kicad-utils.js.map -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | kicad-utils 2 | ======== 3 | 4 | KiCAD library / schematic / pcb parser and plotter written in TypeScript (JavaScript) 5 | 6 | DEMO 7 | ==== 8 | 9 | - Library Viewer 10 | - Schematic/PCB Viewer 11 | 12 | Setup bookmarklet for github: https://cho45.stfuawsc.com/kicad-utils/static/ . 13 | 14 | .sch to .svg/.png in command-line 15 | ================================= 16 | 17 | ``` 18 | npx kicad-utils sch2svg path/to/file.sch 19 | ``` 20 | 21 | or latest from github: 22 | 23 | ``` 24 | npx -p github:cho45/kicad-utils kicad-utils sch2svg 25 | ``` 26 | 27 | Development 28 | =========== 29 | 30 | Edit .ts files. 31 | 32 | ## start foreman 33 | 34 | ``` 35 | npm install 36 | ./node_modules/.bin/nf start 37 | ``` 38 | 39 | ## For only web assets (static/) 40 | 41 | ``` 42 | npm install 43 | ./node_modules/.bin/webpack --watch 44 | ``` 45 | 46 | ## For only CUI assets (bin/) 47 | ``` 48 | npm install 49 | tsc --watch 50 | ``` 51 | -------------------------------------------------------------------------------- /static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 |

18 | bookmarklet: 19 | KiCAD Viewer 20 |

21 | 22 |

23 | for development: 24 | KiCAD Schematic Viewer 25 | KiCAD PCB Viewer 26 |

27 | 28 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/server.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import * as http from "http"; 4 | import * as fs from "fs"; 5 | import * as path from "path"; 6 | 7 | const mimeTypes: { [key: string]: string } = { 8 | "js" : "application/javascript", 9 | "css" : "text/css", 10 | "json" : "application/json", 11 | "png" : "image/png", 12 | "jpg" : "image/jpeg", 13 | "html" : "text/html", 14 | }; 15 | 16 | const args = process.argv.slice(2); 17 | 18 | const root = args.shift() || "."; 19 | 20 | const server = http.createServer( function (req, res) { 21 | console.log(req.method, req.url); 22 | let base = (req.url || "/").replace(/[.]{1,2}\//g, '').replace(/\?.*$/, ''); 23 | if (base.endsWith("/")) base += "index.html"; 24 | 25 | const ext = path.extname(base).slice(1); 26 | const target = path.join(root, base); 27 | const contentType = mimeTypes[ext] || 'application/octet-stream'; 28 | console.log('serving', root, target, ext, contentType); 29 | 30 | fs.readFile(target, function (e, content) { 31 | if (e) { 32 | if (e.code === 'ENOENT') { 33 | res.writeHead(404, { 'Content-Type': 'text/plain' }); 34 | res.end('404 Not Found', 'utf-8'); 35 | } else { 36 | res.writeHead(500, { 'Content-Type': 'text/plain' }); 37 | res.end(`500 Internal Server Error\n${e}`, 'utf-8'); 38 | } 39 | return; 40 | } 41 | 42 | res.writeHead(200, { 'Content-Type': contentType }); 43 | res.end(content, 'utf-8'); 44 | }); 45 | }); 46 | 47 | 48 | const port = 5000; 49 | server.listen(port); 50 | console.log('Local Development Server running at http://127.0.0.1:' + port + '/'); 51 | -------------------------------------------------------------------------------- /static/library.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | KiCAD library Viewer 8 | 9 | 32 | 33 | 34 |
35 |

KiCAD library Viewer

36 |
37 |

Load from file:

38 |

Select .lib file

39 | 40 | 41 |

Load from url:

42 |

Requesting url must be supports CORS header

43 |
44 | 45 | 46 |
47 |
48 |

{{ status }}

49 |
50 |
51 | {{ component.name }} 52 | 53 |
54 |
55 |
56 | 57 |
58 | source code 59 | 60 | 61 | -------------------------------------------------------------------------------- /dist/src/server.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":";;;AAEA,6BAA6B;AAC7B,yBAAyB;AACzB,6BAA6B;AAE7B,MAAM,SAAS,GAA8B;IAC5C,IAAI,EAAK,wBAAwB;IACjC,KAAK,EAAI,UAAU;IACnB,MAAM,EAAG,kBAAkB;IAC3B,KAAK,EAAI,WAAW;IACpB,KAAK,EAAI,YAAY;IACrB,MAAM,EAAG,WAAW;CACpB,CAAC;AAEF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC;AAEjC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAE,UAAU,GAAG,EAAE,GAAG;IACnD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC5E,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,IAAI,IAAI,YAAY,CAAC;IAE7C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrC,MAAM,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,0BAA0B,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;IAEvD,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO;QACvC,IAAI,CAAC,EAAE;YACN,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE;gBACxB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;gBACrD,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;aAClC;iBAAM;gBACN,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;gBACrD,GAAG,CAAC,GAAG,CAAC,8BAA8B,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;aACpD;YACD,OAAO;SACP;QAED,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;QACpD,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAGH,MAAM,IAAI,GAAG,IAAI,CAAC;AAClB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACpB,OAAO,CAAC,GAAG,CAAC,uDAAuD,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC"} -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kicad-utils", 3 | "version": "0.2.0", 4 | "description": "", 5 | "main": "dist/src/kicad-utils.js", 6 | "bin": { 7 | "kicad-utils": "dist/src/kicad-utils_cui.js" 8 | }, 9 | "dependencies": { 10 | "@types/minimist": "^1.2.0", 11 | "@types/node": "^12.7.5", 12 | "babel-polyfill": "^6.23.0", 13 | "express": "^4.15.3", 14 | "minimist": "^1.2.0", 15 | "options": "0.0.6", 16 | "url-search-params-polyfill": "^7.0.0", 17 | "vue": "^2.4.2", 18 | "whatwg-fetch": "^3.0.0" 19 | }, 20 | "devDependencies": { 21 | "@babel/core": "^7.6.0", 22 | "@babel/preset-env": "^7.6.0", 23 | "@types/mocha": "^5.2.7", 24 | "babel-loader": "^8.0.6", 25 | "babel-preset-env": "^1.6.0", 26 | "babel-preset-es2015": "^6.24.1", 27 | "canvas": "^2.6.0", 28 | "espower-typescript": "^9.0.2", 29 | "foreman": "^3.0.1", 30 | "mocha": "^6.2.0", 31 | "power-assert": "^1.4.4", 32 | "source-map": "^0.7.3", 33 | "ts-loader": "^6.1.0", 34 | "typescript": "^3.6.3", 35 | "uglify-save-license": "^0.4.1", 36 | "uglifyjs-webpack-plugin": "^2.2.0", 37 | "webpack": "^4.40.2", 38 | "webpack-cli": "^3.3.9" 39 | }, 40 | "scripts": { 41 | "watch": "./node_modules/.bin/nf start", 42 | "test-one": "mocha --compilers ts:espower-typescript/guess ", 43 | "test": "mocha --compilers ts:espower-typescript/guess test/**/*.ts # /* mocha must be installed as global... */ ", 44 | "test__": "./node_modules/.bin/mocha --compilers ts:espower-typescript/guess test/**/*.ts" 45 | }, 46 | "repository": "cho45/kicad-utils", 47 | "author": "cho45 (http://www.lowreal.net/)", 48 | "license": "GPL-2.0" 49 | } 50 | -------------------------------------------------------------------------------- /dist/src/server.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | const http = require("http"); 5 | const fs = require("fs"); 6 | const path = require("path"); 7 | const mimeTypes = { 8 | "js": "application/javascript", 9 | "css": "text/css", 10 | "json": "application/json", 11 | "png": "image/png", 12 | "jpg": "image/jpeg", 13 | "html": "text/html", 14 | }; 15 | const args = process.argv.slice(2); 16 | const root = args.shift() || "."; 17 | const server = http.createServer(function (req, res) { 18 | console.log(req.method, req.url); 19 | let base = (req.url || "/").replace(/[.]{1,2}\//g, '').replace(/\?.*$/, ''); 20 | if (base.endsWith("/")) 21 | base += "index.html"; 22 | const ext = path.extname(base).slice(1); 23 | const target = path.join(root, base); 24 | const contentType = mimeTypes[ext] || 'application/octet-stream'; 25 | console.log('serving', root, target, ext, contentType); 26 | fs.readFile(target, function (e, content) { 27 | if (e) { 28 | if (e.code === 'ENOENT') { 29 | res.writeHead(404, { 'Content-Type': 'text/plain' }); 30 | res.end('404 Not Found', 'utf-8'); 31 | } 32 | else { 33 | res.writeHead(500, { 'Content-Type': 'text/plain' }); 34 | res.end(`500 Internal Server Error\n${e}`, 'utf-8'); 35 | } 36 | return; 37 | } 38 | res.writeHead(200, { 'Content-Type': contentType }); 39 | res.end(content, 'utf-8'); 40 | }); 41 | }); 42 | const port = 5000; 43 | server.listen(port); 44 | console.log('Local Development Server running at http://127.0.0.1:' + port + '/'); 45 | //# sourceMappingURL=server.js.map -------------------------------------------------------------------------------- /test/kicad_strokefont.ts: -------------------------------------------------------------------------------- 1 | //#!npm run test-one 2 | 3 | import * as assert from "assert"; 4 | import * as mocha from 'mocha'; 5 | 6 | import { 7 | Glyph, 8 | StrokeFont, 9 | } from "../src/kicad_strokefont"; 10 | 11 | 12 | /* 13 | describe("", () => { 14 | it("", () => { 15 | }); 16 | }); 17 | */ 18 | 19 | describe("Glyph", () => { 20 | const glyph_f = { 21 | "lines": [ 22 | [ 23 | { 24 | "x": 0.23809523809523808, 25 | "y": -0.7142857142857142 26 | }, 27 | { 28 | "x": 0.23809523809523808, 29 | "y": 0.14285714285714285 30 | }, 31 | { 32 | "x": 0.19047619047619047, 33 | "y": 0.23809523809523808 34 | }, 35 | { 36 | "x": 0.09523809523809523, 37 | "y": 0.2857142857142857 38 | }, 39 | { 40 | "x": 0.047619047619047616, 41 | "y": 0.2857142857142857 42 | } 43 | ], 44 | [ 45 | { 46 | "x": 0.23809523809523808, 47 | "y": -1.0476190476190474 48 | }, 49 | { 50 | "x": 0.19047619047619047, 51 | "y": -1 52 | }, 53 | { 54 | "x": 0.23809523809523808, 55 | "y": -0.9523809523809523 56 | }, 57 | { 58 | "x": 0.2857142857142857, 59 | "y": -1 60 | }, 61 | { 62 | "x": 0.23809523809523808, 63 | "y": -1.0476190476190474 64 | }, 65 | { 66 | "x": 0.23809523809523808, 67 | "y": -0.9523809523809523 68 | } 69 | ] 70 | ], 71 | "startX": -0.23809523809523808, 72 | "endX": 0.23809523809523808 73 | }; 74 | 75 | it("can computeBoundingBox", () => { 76 | const glyph = new Glyph(); 77 | Object.assign(glyph, glyph_f); 78 | 79 | glyph.computeBoundingBox(); 80 | assert.deepEqual(glyph.boundingBox.pos1, { 81 | x: 0, 82 | y: -1.0476190476190474, 83 | }); 84 | assert.deepEqual(glyph.boundingBox.pos2, { 85 | x: 0.47619047619047616, 86 | y: 0.2857142857142857, 87 | }); 88 | }); 89 | }); 90 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 2 | const path = require('path'); 3 | //const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); 4 | //const saveLicense = require('uglify-save-license'); 5 | 6 | 7 | const babelOptions = { 8 | "presets": [ [ "@babel/preset-env", { 9 | modules: false, 10 | targets: { 11 | browsers: ["last 2 versions"] 12 | } 13 | } ] ] 14 | }; 15 | 16 | module.exports = { 17 | mode: 'development', 18 | 19 | entry: { 20 | library: ['url-search-params-polyfill', 'babel-polyfill', 'whatwg-fetch', './static/js/library.js'], 21 | schematic: ['url-search-params-polyfill', 'babel-polyfill', 'whatwg-fetch', './static/js/common.js', './static/js/schematic.js'], 22 | pcb: ['url-search-params-polyfill', 'babel-polyfill', 'whatwg-fetch', './static/js/common.js', './static/js/pcb.js'], 23 | viewer: ['url-search-params-polyfill', 'babel-polyfill', 'whatwg-fetch', './static/js/common.js', './static/js/viewer.js'], 24 | worker: ['babel-polyfill', './static/js/common.js', './static/js/worker.js'], 25 | }, 26 | 27 | output: { 28 | path: __dirname + "/static/js", 29 | filename: '[name].bundle.js', 30 | }, 31 | 32 | node: { 33 | 'fs': 'empty', 34 | }, 35 | 36 | devtool: 'source-map', 37 | 38 | resolve: { 39 | alias: { 40 | 'vue$': 'vue/dist/vue.common.js' 41 | }, 42 | extensions: ['.ts', '.js'], 43 | modules: [ 44 | path.join(__dirname, "src"), 45 | "node_modules" 46 | ] 47 | }, 48 | 49 | module: { 50 | rules: [ 51 | { 52 | test: /\.html?$/, 53 | use: [ 54 | { 55 | loader: 'raw-loader', 56 | }, 57 | ] 58 | }, 59 | { 60 | test: /\.js?$/, 61 | exclude: /node_modules/, 62 | use: [ 63 | { 64 | loader: 'babel-loader', 65 | options: babelOptions, 66 | } 67 | ] 68 | }, 69 | { 70 | test: /\.ts?$/, 71 | use: [ 72 | /* 73 | { 74 | loader: 'babel-loader', 75 | options: babelOptions, 76 | }, 77 | */ 78 | { 79 | loader: 'ts-loader' 80 | } 81 | ], 82 | exclude: /node_modules/ 83 | }, 84 | ] 85 | }, 86 | 87 | plugins: [ 88 | // new UglifyJSPlugin({ 89 | // sourceMap: true, 90 | // parallel: true, 91 | // output: { 92 | // comments: saveLicense 93 | // } 94 | // }) 95 | ] 96 | }; 97 | -------------------------------------------------------------------------------- /static/schematic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | KiCAD Schematic Viewer 8 | 9 | 54 | 55 | 56 |
57 |

KiCAD Schematic Viewer

58 |
59 |

Load from file:

60 |

Select .sch and .lib files (Typically select target .sch and -cache.lib)

61 | 62 | 63 |

Load from URLs:

64 |

Input space delimited URLs

65 |

Requesting url must be supports CORS header

66 |
67 | 68 | 69 |
70 |
71 |

{{ status }}

72 |
73 |

{{ error }}

74 |
75 |
76 |

{{ basename(result.url.name) }}

77 |
78 |
79 | 80 |
81 |
82 |
83 |
84 | 85 |
86 | source code 87 | 88 | 89 | -------------------------------------------------------------------------------- /dist/sketch.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"sketch.js","sourceRoot":"","sources":["../sketch.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /sketch2.ts: -------------------------------------------------------------------------------- 1 | //#!tsc && NODE_PATH=dist/src node dist/sketch2.js 2 | 3 | import { 4 | Point, 5 | Rect, 6 | TextHjustify, 7 | TextVjustify, 8 | Transform, 9 | DECIDEG2RAD, 10 | TextAngle, 11 | } from "./src/kicad_common"; 12 | import { StrokeFont } from "./src/kicad_strokefont"; 13 | import { Plotter, CanvasPlotter } from "./src/kicad_plotter"; 14 | 15 | import * as fs from "fs"; 16 | { 17 | const font = StrokeFont.instance; 18 | 19 | const width = 2000, height = 2000; 20 | const Canvas = require('canvas'); 21 | const canvas = Canvas.createCanvas ? Canvas.createCanvas(width, height) : new Canvas(width, height); 22 | const ctx = canvas.getContext('2d'); 23 | 24 | ctx.strokeStyle = "#666666"; 25 | ctx.lineWidth = 1; 26 | ctx.beginPath(); 27 | ctx.moveTo(canvas.width / 2, 0); 28 | ctx.lineTo(canvas.width / 2, canvas.height); 29 | ctx.stroke(); 30 | ctx.beginPath(); 31 | ctx.moveTo(0, canvas.height / 2); 32 | ctx.lineTo(canvas.width, canvas.height / 2); 33 | ctx.stroke(); 34 | ctx.lineCap = "round"; 35 | ctx.lineJoin = 'round'; 36 | 37 | 38 | // ctx.translate(canvas.width / 2, canvas.height / 2); 39 | 40 | const plotter = new CanvasPlotter(ctx); 41 | 42 | const text = 'jeyjmcNV'; 43 | const size = 100; 44 | const lineWidth = 20; 45 | const bold = false; 46 | const italic = false; 47 | const pos = { x: canvas.width / 2, y: canvas.height / 2 }; 48 | const vjustify = TextVjustify.CENTER; 49 | 50 | { 51 | const boundingbox = font.computeStringBoundaryLimits(text, size, lineWidth, italic); 52 | ctx.save(); 53 | ctx.translate(pos.x, pos.y); 54 | ctx.translate(0, size / 2); 55 | ctx.fillStyle = "rgba(255, 0, 0, 0.3)"; 56 | ctx.fillRect(0, 0, boundingbox.width, -boundingbox.height); 57 | ctx.fillStyle = "rgba(0, 0, 255, 0.3)"; 58 | ctx.fillRect(0, 0, boundingbox.width, boundingbox.topLimit); 59 | ctx.fillRect(0, 0, boundingbox.width, boundingbox.bottomLimit); 60 | { 61 | const n = text.charCodeAt(0) - ' '.charCodeAt(0); 62 | const glyph = font.glyphs[n]; 63 | console.log(JSON.stringify(glyph)); 64 | ctx.fillStyle = "rgba(0, 255, 0, 0.3)"; 65 | ctx.fillRect( 66 | glyph.boundingBox.pos1.x * size, 67 | glyph.boundingBox.pos1.y * size, 68 | glyph.boundingBox.width * size, 69 | glyph.boundingBox.height * size 70 | ); 71 | ctx.restore(); 72 | } 73 | } 74 | font.drawText(plotter, pos, text, size, lineWidth, TextAngle.HORIZ, TextHjustify.LEFT, vjustify, italic, bold); 75 | 76 | const out = fs.createWriteStream('text.png'), stream = canvas.pngStream(); 77 | stream.on('data', function (chunk: any) { 78 | out.write(chunk); 79 | }); 80 | stream.on('end', function(){ 81 | console.log('saved png'); 82 | }); 83 | } 84 | -------------------------------------------------------------------------------- /dist/sketch2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | //#!tsc && NODE_PATH=dist/src node dist/sketch2.js 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | const kicad_common_1 = require("./src/kicad_common"); 5 | const kicad_strokefont_1 = require("./src/kicad_strokefont"); 6 | const kicad_plotter_1 = require("./src/kicad_plotter"); 7 | const fs = require("fs"); 8 | { 9 | const font = kicad_strokefont_1.StrokeFont.instance; 10 | const width = 2000, height = 2000; 11 | const Canvas = require('canvas'); 12 | const canvas = Canvas.createCanvas ? Canvas.createCanvas(width, height) : new Canvas(width, height); 13 | const ctx = canvas.getContext('2d'); 14 | ctx.strokeStyle = "#666666"; 15 | ctx.lineWidth = 1; 16 | ctx.beginPath(); 17 | ctx.moveTo(canvas.width / 2, 0); 18 | ctx.lineTo(canvas.width / 2, canvas.height); 19 | ctx.stroke(); 20 | ctx.beginPath(); 21 | ctx.moveTo(0, canvas.height / 2); 22 | ctx.lineTo(canvas.width, canvas.height / 2); 23 | ctx.stroke(); 24 | ctx.lineCap = "round"; 25 | ctx.lineJoin = 'round'; 26 | // ctx.translate(canvas.width / 2, canvas.height / 2); 27 | const plotter = new kicad_plotter_1.CanvasPlotter(ctx); 28 | const text = 'jeyjmcNV'; 29 | const size = 100; 30 | const lineWidth = 20; 31 | const bold = false; 32 | const italic = false; 33 | const pos = { x: canvas.width / 2, y: canvas.height / 2 }; 34 | const vjustify = kicad_common_1.TextVjustify.CENTER; 35 | { 36 | const boundingbox = font.computeStringBoundaryLimits(text, size, lineWidth, italic); 37 | ctx.save(); 38 | ctx.translate(pos.x, pos.y); 39 | ctx.translate(0, size / 2); 40 | ctx.fillStyle = "rgba(255, 0, 0, 0.3)"; 41 | ctx.fillRect(0, 0, boundingbox.width, -boundingbox.height); 42 | ctx.fillStyle = "rgba(0, 0, 255, 0.3)"; 43 | ctx.fillRect(0, 0, boundingbox.width, boundingbox.topLimit); 44 | ctx.fillRect(0, 0, boundingbox.width, boundingbox.bottomLimit); 45 | { 46 | const n = text.charCodeAt(0) - ' '.charCodeAt(0); 47 | const glyph = font.glyphs[n]; 48 | console.log(JSON.stringify(glyph)); 49 | ctx.fillStyle = "rgba(0, 255, 0, 0.3)"; 50 | ctx.fillRect(glyph.boundingBox.pos1.x * size, glyph.boundingBox.pos1.y * size, glyph.boundingBox.width * size, glyph.boundingBox.height * size); 51 | ctx.restore(); 52 | } 53 | } 54 | font.drawText(plotter, pos, text, size, lineWidth, kicad_common_1.TextAngle.HORIZ, kicad_common_1.TextHjustify.LEFT, vjustify, italic, bold); 55 | const out = fs.createWriteStream('text.png'), stream = canvas.pngStream(); 56 | stream.on('data', function (chunk) { 57 | out.write(chunk); 58 | }); 59 | stream.on('end', function () { 60 | console.log('saved png'); 61 | }); 62 | } 63 | //# sourceMappingURL=sketch2.js.map -------------------------------------------------------------------------------- /dist/sketch2.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"sketch2.js","sourceRoot":"","sources":["../sketch2.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /static/js/library.js: -------------------------------------------------------------------------------- 1 | 2 | const { 3 | Transform, 4 | CanvasPlotter, 5 | SchPlotter, 6 | Lib, 7 | } = require("kicad-utils"); 8 | 9 | const Vue = require("vue"); 10 | 11 | const app = new Vue({ 12 | el: '#app', 13 | data: { 14 | url: "https://raw.githubusercontent.com/KiCad/kicad-library/master/library/device.lib", 15 | fileName : "", 16 | status: "init", 17 | lib: {}, 18 | components: [], 19 | }, 20 | 21 | created: function () { 22 | if (location.search) { 23 | const params = new URLSearchParams(location.search); 24 | if (params.has('url')) { 25 | this.url = params.get('url'); 26 | } 27 | } 28 | }, 29 | 30 | mounted: function () { 31 | console.log(this.$refs); 32 | this.onSubmit(); 33 | }, 34 | 35 | methods: { 36 | fileSelected: function () { 37 | const file = this.$refs.fileInput.files[0]; 38 | this.fileName = file.name; 39 | const objectURL = window.URL.createObjectURL(file); 40 | this.loadLibrary(objectURL); 41 | }, 42 | 43 | onSubmit: function () { 44 | const url = this.url; 45 | if (!url) { 46 | this.status = "url is required"; 47 | return; 48 | } 49 | const params = new URLSearchParams(); 50 | params.set('url', this.url); 51 | history.pushState(null, '', '?' + params); 52 | this.loadLibrary(url).catch( (e) => { 53 | this.status = e; 54 | }); 55 | }, 56 | 57 | loadLibrary: async function (url) { 58 | this.status = "loading"; 59 | console.log('loadLibrary'); 60 | const res = await fetch(url); 61 | const text = await res.text(); 62 | this.status = "parsing"; 63 | const lib = Lib.Library.load(text); 64 | this.lib = lib; 65 | this.components = lib.components; 66 | await Vue.nextTick(); 67 | this.status = "rendering"; 68 | console.log(this.$refs); 69 | const canvasElements = this.$refs.canvas; 70 | for (let canvas of canvasElements) { 71 | const name = canvas.getAttribute('data-name'); 72 | const component = lib.findByName(name); 73 | const rect = component.draw.getBoundingRect(); 74 | if (!rect) { 75 | return "data:"; 76 | } 77 | 78 | const PADDING = 500; 79 | const width = rect.width + PADDING, height = rect.height + PADDING; 80 | 81 | canvas.width = 500; 82 | canvas.height = 500; 83 | 84 | const scale = Math.min(canvas.width / width, canvas.height / height); 85 | // console.log('plot', component.name, rect, width, height, scale); 86 | 87 | const ctx = canvas.getContext('2d'); 88 | ctx.translate(canvas.width / 2, canvas.height / 2); 89 | ctx.scale(scale, scale); 90 | ctx.stokeStyle = '#000'; 91 | ctx.fillStyle = '#000'; 92 | 93 | const plotter = new CanvasPlotter(ctx); 94 | const schPlotter = new SchPlotter(plotter); 95 | schPlotter.plotLibComponent(component, 1, 1, new Transform()); 96 | schPlotter.plotLibComponentField(component, 1, 1, new Transform()); 97 | } 98 | this.status = "done"; 99 | } 100 | } 101 | }) 102 | -------------------------------------------------------------------------------- /dist/sketch3.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"sketch3.js","sourceRoot":"","sources":["../sketch3.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /test/kicad_pcb.ts: -------------------------------------------------------------------------------- 1 | //#!npm run test-one 2 | 3 | import * as assert from "assert"; 4 | import * as mocha from 'mocha'; 5 | 6 | import { 7 | TextHjustify, 8 | TextVjustify, 9 | TextAngle, 10 | Fill, 11 | PinOrientation, 12 | PinType, 13 | } from "../src/kicad_common"; 14 | 15 | import { 16 | LSET, 17 | PCB_LAYER_ID, 18 | } from "../src/kicad_pcb"; 19 | 20 | function indent (literals: TemplateStringsArray, ...placeholders: Array):string { 21 | let result = ""; 22 | 23 | for (let i = 0; i < placeholders.length; i++) { 24 | result += literals[i]; 25 | result += String(placeholders[i]); 26 | } 27 | 28 | result += literals[literals.length - 1]; 29 | 30 | result = result.replace(/^\n|\s+$/g, ''); 31 | const indent = result.match(/^\s+/); 32 | if (indent) { 33 | result = result.replace(new RegExp("^" + indent[0], "gm"), ""); 34 | } 35 | 36 | return result; 37 | } 38 | 39 | /* 40 | describe("", () => { 41 | it("", () => { 42 | }); 43 | }); 44 | */ 45 | 46 | 47 | describe("LSET", () => { 48 | const L = PCB_LAYER_ID; 49 | 50 | it("can insitanciate with multiple values", () => { 51 | const lset = new LSET(L.F_Cu, L.B_Cu); 52 | assert( lset.length === 2 ); 53 | }); 54 | 55 | it("has `has` method", () => { 56 | const lset = new LSET(L.F_Cu, L.B_Cu); 57 | assert( lset.has(L.F_Cu) ); 58 | assert( lset.has(L.B_Cu) ); 59 | assert( !lset.has(L.In1_Cu) ); 60 | }); 61 | 62 | it("can be used with for-of", () => { 63 | const lset = new LSET(L.F_Cu, L.B_Cu); 64 | { 65 | const ret = []; 66 | for (let l of lset) { 67 | ret.push(l); 68 | } 69 | assert( ret[0] === L.F_Cu ); 70 | assert( ret[1] === L.B_Cu ); 71 | } 72 | { 73 | const ret = []; 74 | for (let l of lset) { 75 | ret.push(l); 76 | } 77 | assert( ret[0] === L.F_Cu ); 78 | assert( ret[1] === L.B_Cu ); 79 | } 80 | }); 81 | 82 | it("has intersect method", () => { 83 | { 84 | const lset1 = new LSET(L.F_Cu, L.B_Cu); 85 | const lset2 = new LSET(L.In1_Cu, L.In2_Cu); 86 | lset1.intersect(lset2); 87 | assert( lset1.length === 0); 88 | } 89 | { 90 | const lset1 = new LSET(L.F_Cu, L.B_Cu, L.In1_Cu); 91 | const lset2 = new LSET(L.In1_Cu, L.In2_Cu); 92 | lset1.intersect(lset2); 93 | assert.deepEqual( lset1.entries(), [ L.In1_Cu ]); 94 | } 95 | }); 96 | 97 | it("has except method", () => { 98 | { 99 | const lset1 = new LSET(L.F_Cu, L.B_Cu); 100 | const lset2 = new LSET(L.F_Cu, L.B_Cu); 101 | lset1.except(lset2); 102 | assert( lset1.length === 0); 103 | } 104 | { 105 | const lset1 = new LSET(L.F_Cu, L.B_Cu, L.In1_Cu); 106 | const lset2 = new LSET(L.In1_Cu, L.In2_Cu); 107 | lset1.except(lset2); 108 | assert.deepEqual( lset1.entries(), [ L.F_Cu, L.B_Cu ]); 109 | } 110 | }); 111 | 112 | it("has union method", () => { 113 | { 114 | const lset1 = new LSET(L.F_Cu, L.B_Cu); 115 | const lset2 = new LSET(L.In1_Cu, L.In2_Cu); 116 | lset1.union(lset2); 117 | assert.deepEqual( lset1.entries(), [ L.F_Cu, L.B_Cu, L.In1_Cu, L.In2_Cu]); 118 | } 119 | }); 120 | }); 121 | -------------------------------------------------------------------------------- /static/pcb.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | KiCAD Schematic Viewer 8 | 9 | 77 | 78 | 79 |
80 |

KiCAD PCB Viewer

81 |
82 |

Load from file:

83 |

Select .kicad_pcb file

84 | 85 | 86 |

Load from URLs:

87 |

Input space delimited URLs

88 |

Requesting url must be supports CORS header

89 |
90 | 91 | 92 |
93 |
94 |

{{ status }}

95 |
96 |

{{ error }}

97 |
98 |
99 |

{{ basename(result.url.name) }} 100 | 103 |

104 | 107 |
108 |
109 |
110 | 111 |
112 |
113 |
114 |
115 |
116 | 117 |
118 | source code 119 | 120 | 121 | -------------------------------------------------------------------------------- /static/viewer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | KiCAD Schematic/PCB Viewer 8 | 9 | 82 | 83 | 84 |
85 |

KiCAD Schematic/PCB Viewer

86 |
87 |

Load from file:

88 |

Select .kicad_pcb, .lib, .sch files

89 | 90 | 91 |

Load from URLs:

92 |

Input space delimited URLs

93 |

Requesting url must be supports CORS header

94 |
95 | 96 | 97 |
98 |
99 |

{{ status }}

100 |
101 |

{{ error }}

102 |
103 |
104 |

{{ basename(result.url.name) }}

105 |
106 |
107 | 108 |
109 |
110 |
111 |
112 |

{{ basename(result.url.name) }} 113 | 116 |

117 | 120 |
121 |
122 |
123 | 124 |
125 |
126 |
127 |
128 |
129 | 130 |
131 | source code 132 | 133 | 134 | -------------------------------------------------------------------------------- /static/js/schematic.js: -------------------------------------------------------------------------------- 1 | const { 2 | Transform, 3 | CanvasPlotter, 4 | SVGPlotter, 5 | SchPlotter, 6 | Lib, 7 | Sch, 8 | } = require("kicad-utils"); 9 | 10 | const Vue = require("vue"); 11 | 12 | const app = new Vue({ 13 | el: '#app', 14 | data: { 15 | url: [ 16 | "https://github.com/cho45/Keble/blob/master/Root-cache.lib", 17 | "https://github.com/cho45/Keble/blob/master/Root.sch", 18 | "https://github.com/cho45/Keble/blob/master/_keymodule_l.sch", 19 | "https://github.com/cho45/Keble/blob/master/_keymodule_r.sch", 20 | "https://github.com/cho45/Keble/blob/master/_main.sch", 21 | ].join("\n"), 22 | status: "init", 23 | lib: {}, 24 | results: [], 25 | errors: [], 26 | }, 27 | 28 | created: function () { 29 | if (location.search) { 30 | const params = new URLSearchParams(location.search); 31 | if (params.has('url')) { 32 | this.url = params.get('url'); 33 | } 34 | } 35 | }, 36 | 37 | mounted: function () { 38 | console.log(this.$refs); 39 | this.onSubmit(); 40 | }, 41 | 42 | methods: { 43 | fileSelected: function () { 44 | const files = Array.from(this.$refs.fileInput.files).map( (f) => ({ name: f.name, url: window.URL.createObjectURL(f) }) ); 45 | this.loadFiles(files); 46 | }, 47 | 48 | onSubmit: function () { 49 | const urls = this.url.replace(/^\s+|\s+$/g, '').split(/\s+/).map( (u) => ({ name: u, url: u.replace(/github\.com\/(.+)\/blob\/(.+)/, 'raw.githubusercontent.com/$1/$2') })); 50 | console.log(urls); 51 | if (!urls.length) { 52 | this.status = "url is required"; 53 | return; 54 | } 55 | const params = new URLSearchParams(); 56 | params.set('url', this.url); 57 | history.pushState(null, '', '?' + params); 58 | this.loadFiles(urls); 59 | }, 60 | 61 | loadFiles: async function (urls) { 62 | console.log('loadFiles', urls); 63 | urls = urls.filter( (url) => /[.](sch|lib)$/i.test(url.name) ); 64 | 65 | const res = await Promise.all(urls.map( (url) => fetch(url.url))); 66 | const text = await Promise.all(res.map( (r) => r.text())); 67 | const files = text.map( (t, i) => ({ url: urls[i], content: t }) ); 68 | 69 | const schFiles = []; 70 | const libFiles = []; 71 | for (let file of files) { 72 | if (file.url.name.toLowerCase().endsWith(".sch")) { 73 | schFiles.push(file); 74 | } else 75 | if (file.url.name.toLowerCase().endsWith(".lib")) { 76 | libFiles.push(file); 77 | } 78 | } 79 | 80 | if (!schFiles.length) { 81 | this.status = ".sch file is needed"; 82 | return; 83 | } 84 | 85 | if (!libFiles.length) { 86 | this.status = ".lib file is needed"; 87 | } 88 | 89 | const libs = libFiles.map( (file) => Lib.Library.load(file.content) ); 90 | 91 | this.results = []; 92 | for (let schFile of schFiles) { 93 | this.status = 'loading ' + schFile; 94 | const sch = Sch.Schematic.load(schFile.content); 95 | 96 | const svgPlotter = new SVGPlotter(); 97 | svgPlotter.pageInfo = sch.descr.pageInfo; 98 | svgPlotter.startPlot(); 99 | new SchPlotter(svgPlotter).plotSchematic(sch, libs); 100 | svgPlotter.endPlot(); 101 | const svg = svgPlotter.output; 102 | for (let error of svgPlotter.errors) { 103 | this.errors.push(error); 104 | } 105 | 106 | let src; 107 | if (typeof Blob !== 'undefined') { 108 | const blob = new Blob([svg], {type : 'image/svg+xml'}); 109 | src = URL.createObjectURL(blob); 110 | } else { 111 | src = 'data:image/svg+xml,' + encodeURIComponent(svg); 112 | } 113 | this.results.push({ 114 | url: schFile.url, 115 | src: src 116 | }); 117 | } 118 | this.status = 'done'; 119 | }, 120 | 121 | basename: function (url) { 122 | const matched = url.replace(/[#?].+$/, '').match(/[^/]+$/); 123 | return decodeURIComponent(matched[0] || ''); 124 | } 125 | } 126 | }) 127 | -------------------------------------------------------------------------------- /sketch3.ts: -------------------------------------------------------------------------------- 1 | //#!tsc && NODE_PATH=dist/src node dist/sketch3.js 2 | 3 | import { 4 | Fill, 5 | Color, 6 | Point, 7 | PageInfo, 8 | } from "./src/kicad_common"; 9 | 10 | import { 11 | PCB, 12 | Board, 13 | Module, 14 | PadShape, 15 | LSET, 16 | PCB_LAYER_ID, 17 | } from "./src/kicad_pcb"; 18 | 19 | import { 20 | PCBPlotter, 21 | } from "./src/kicad_pcb_plotter"; 22 | 23 | import { 24 | Plotter, 25 | SVGPlotter, 26 | CanvasPlotter, 27 | } from "./src/kicad_plotter"; 28 | 29 | // console.log(Foo["xxx" as Foo]); 30 | 31 | 32 | import * as fs from "fs"; 33 | // const content = fs.readFileSync('../keyboard-schematic/Main.kicad_pcb', 'utf-8'); 34 | // const content = fs.readFileSync('../keyboard-schematic/KeyModule-L.kicad_pcb', 'utf-8'); 35 | const content = fs.readFileSync('../ledlight/ledlight.kicad_pcb', 'utf-8'); 36 | // const content = fs.readFileSync('../../KiCad/footprint.pretty/ESP-WROOM-32.kicad_mod', 'utf-8'); 37 | // const content = fs.readFileSync('../../../Documents/KiCAD/my/myfootprint.pretty/BLE_NANO.kicad_mod', 'utf-8'); 38 | // const content = fs.readFileSync('../../KiCad/footprint.pretty/RJ45-7810-XPXC.kicad_mod', 'utf-8'); 39 | 40 | 41 | const genSVG = true; 42 | const genCanvas = false; 43 | 44 | function render(plotter: Plotter, item: Board) { 45 | const pcbPlotter = new PCBPlotter(plotter); 46 | // pcbPlotter.layerMask = new LSET(...item.visibleLayers); 47 | // pcbPlotter.plotStandardLayer(item); 48 | // pcbPlotter.plotSilkScreen(item); 49 | 50 | plotter.save(); 51 | plotter.translate(0, 0); 52 | plotter.plotPageInfo(item.pageInfo); 53 | pcbPlotter.plotBoardLayers(item, new LSET( 54 | PCB_LAYER_ID.F_Cu, 55 | PCB_LAYER_ID.F_Fab, 56 | PCB_LAYER_ID.F_CrtYd, 57 | PCB_LAYER_ID.F_Adhes, 58 | PCB_LAYER_ID.F_Paste, 59 | PCB_LAYER_ID.F_SilkS, 60 | PCB_LAYER_ID.Dwgs_User, 61 | PCB_LAYER_ID.Edge_Cuts, 62 | )); 63 | plotter.restore(); 64 | 65 | plotter.save(); 66 | plotter.translate(0, item.pageInfo.height * 2); 67 | plotter.scale(1, -1); 68 | plotter.plotPageInfo(item.pageInfo); 69 | pcbPlotter.plotBoardLayers(item, new LSET( 70 | PCB_LAYER_ID.B_Cu, 71 | PCB_LAYER_ID.B_Fab, 72 | PCB_LAYER_ID.B_CrtYd, 73 | PCB_LAYER_ID.B_Adhes, 74 | PCB_LAYER_ID.B_Paste, 75 | PCB_LAYER_ID.B_SilkS, 76 | PCB_LAYER_ID.Dwgs_User, 77 | PCB_LAYER_ID.Edge_Cuts, 78 | )); 79 | plotter.restore(); 80 | } 81 | 82 | if (genSVG) { 83 | const item = PCB.load(content); 84 | if (item instanceof Board) { 85 | const plotter = new SVGPlotter(); 86 | plotter.scale(0.5, 0.5); 87 | plotter.startPlot(); 88 | plotter.pageInfo = item.pageInfo; 89 | plotter.pageInfo = new PageInfo("User", false, item.pageInfo.width, item.pageInfo.height * 2); 90 | render(plotter, item); 91 | plotter.endPlot(); 92 | fs.writeFileSync("text.svg", plotter.output); 93 | } else 94 | if (item instanceof Module) { 95 | } 96 | } 97 | if (genCanvas) { 98 | 99 | const item = PCB.load(content); 100 | if (item instanceof Board) { 101 | const scale = 0.5; 102 | const width = item.pageInfo.width * scale; 103 | const height = item.pageInfo.height * scale * 2; 104 | const Canvas = require('canvas'); 105 | const canvas = Canvas.createCanvas ? Canvas.createCanvas(width, height) : new Canvas(width, height); 106 | const ctx = canvas.getContext('2d'); 107 | ctx.fillStyle = "#000"; 108 | ctx.fillRect(0, 0, canvas.width, canvas.height); 109 | ctx.scale(scale, scale); 110 | const plotter = new CanvasPlotter(ctx); 111 | plotter.setColor(Color.BLACK); 112 | 113 | render(plotter, item); 114 | 115 | const out = fs.createWriteStream('text.png'), stream = canvas.pngStream(); 116 | stream.on('data', function (chunk: any) { 117 | out.write(chunk); 118 | }); 119 | stream.on('end', function(){ 120 | console.log('saved png'); 121 | }); 122 | } else 123 | if (item instanceof Module) { 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /static/js/viewer.js: -------------------------------------------------------------------------------- 1 | const { 2 | Transform, 3 | CanvasPlotter, 4 | Color, 5 | SVGPlotter, 6 | PCBPlotter, 7 | SchPlotter, 8 | Lib, 9 | Sch, 10 | Pcb, 11 | } = require("kicad-utils"); 12 | 13 | const Vue = require("vue"); 14 | 15 | const worker = new MethodWorker("./js/worker.bundle.js"); 16 | 17 | const app = new Vue({ 18 | el: '#app', 19 | data: { 20 | url: [ 21 | "https://github.com/cho45/Keble/blob/master/Root-cache.lib", 22 | "https://github.com/cho45/Keble/blob/master/Root.sch", 23 | "https://github.com/cho45/Keble/blob/master/_keymodule_l.sch", 24 | "https://github.com/cho45/Keble/blob/master/_keymodule_r.sch", 25 | "https://github.com/cho45/Keble/blob/master/_main.sch", 26 | "https://github.com/cho45/Keble/blob/master/KeyModule-L.kicad_pcb", 27 | "https://github.com/cho45/Keble/blob/master/KeyModule-R.kicad_pcb", 28 | "https://github.com/cho45/Keble/blob/master/Main.kicad_pcb", 29 | ].join("\n"), 30 | status: "init", 31 | lib: {}, 32 | pcbs: [], 33 | schs: [], 34 | errors: [], 35 | }, 36 | 37 | created: function () { 38 | if (location.search) { 39 | const params = new URLSearchParams(location.search); 40 | if (params.has('url')) { 41 | this.url = params.get('url'); 42 | } 43 | } 44 | }, 45 | 46 | mounted: function () { 47 | console.log(this.$refs); 48 | this.onSubmit(); 49 | }, 50 | 51 | methods: { 52 | fileSelected: function () { 53 | const files = Array.from(this.$refs.fileInput.files).map( (f) => ({ name: f.name, url: window.URL.createObjectURL(f) }) ); 54 | this.loadFiles(files); 55 | }, 56 | 57 | onSubmit: function () { 58 | const urls = this.url.replace(/^\s+|\s+$/g, '').split(/\s+/).map( (u) => ({ name: u, url: u.replace(/github\.com\/(.+)\/blob\/(.+)/, 'raw.githubusercontent.com/$1/$2') })); 59 | console.log(urls); 60 | if (!urls.length) { 61 | this.status = "url is required"; 62 | return; 63 | } 64 | const params = new URLSearchParams(); 65 | params.set('url', this.url); 66 | history.pushState(null, '', '?' + params); 67 | this.loadFiles(urls); 68 | }, 69 | 70 | loadFiles: async function (urls) { 71 | console.log('loadFiles', urls); 72 | urls = urls.filter( (url) => /[.](kicad_pcb|lib|sch)$/i.test(url.name) ); 73 | 74 | const res = await Promise.all(urls.map( (url) => fetch(url.url))); 75 | const text = await Promise.all(res.map( (r) => r.text())); 76 | const files = text.map( (t, i) => ({ url: urls[i], content: t }) ); 77 | 78 | const schFiles = []; 79 | const libFiles = []; 80 | const pcbFiles = []; 81 | for (let file of files) { 82 | if (file.url.name.toLowerCase().endsWith(".kicad_pcb")) { 83 | pcbFiles.push(file); 84 | } else 85 | if (file.url.name.toLowerCase().endsWith(".sch")) { 86 | schFiles.push(file); 87 | } else 88 | if (file.url.name.toLowerCase().endsWith(".lib")) { 89 | libFiles.push(file); 90 | } 91 | } 92 | 93 | this.pcbs = []; 94 | this.schs = []; 95 | 96 | for (let pcbFile of pcbFiles) { 97 | this.status = 'loading ' + pcbFile.url.name; 98 | const res = await worker.call('renderPCB', pcbFile.content); 99 | this.errors.concat(res.errors); 100 | 101 | this.pcbs.push({ 102 | url: pcbFile.url, 103 | mirror: false, 104 | layers: res.layers, 105 | }); 106 | } 107 | 108 | 109 | await worker.call('loadLibs', libFiles.map((file) => file.content)); 110 | 111 | this.schs = []; 112 | for (let schFile of schFiles) { 113 | this.status = 'loading ' + schFile.url.name; 114 | 115 | const res = await worker.call('renderSch', schFile.content); 116 | 117 | this.schs.push({ 118 | url: schFile.url, 119 | src: res.src, 120 | }); 121 | } 122 | 123 | await worker.call('unloadLibs'); 124 | 125 | this.status = 'done'; 126 | }, 127 | 128 | basename: function (url) { 129 | const matched = url.replace(/[#?].+$/, '').match(/[^/]+$/); 130 | return decodeURIComponent(matched[0] || ''); 131 | } 132 | } 133 | }) 134 | 135 | -------------------------------------------------------------------------------- /dist/sketch3.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | //#!tsc && NODE_PATH=dist/src node dist/sketch3.js 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | const kicad_common_1 = require("./src/kicad_common"); 5 | const kicad_pcb_1 = require("./src/kicad_pcb"); 6 | const kicad_pcb_plotter_1 = require("./src/kicad_pcb_plotter"); 7 | const kicad_plotter_1 = require("./src/kicad_plotter"); 8 | // console.log(Foo["xxx" as Foo]); 9 | const fs = require("fs"); 10 | // const content = fs.readFileSync('../keyboard-schematic/Main.kicad_pcb', 'utf-8'); 11 | // const content = fs.readFileSync('../keyboard-schematic/KeyModule-L.kicad_pcb', 'utf-8'); 12 | const content = fs.readFileSync('../ledlight/ledlight.kicad_pcb', 'utf-8'); 13 | // const content = fs.readFileSync('../../KiCad/footprint.pretty/ESP-WROOM-32.kicad_mod', 'utf-8'); 14 | // const content = fs.readFileSync('../../../Documents/KiCAD/my/myfootprint.pretty/BLE_NANO.kicad_mod', 'utf-8'); 15 | // const content = fs.readFileSync('../../KiCad/footprint.pretty/RJ45-7810-XPXC.kicad_mod', 'utf-8'); 16 | const genSVG = true; 17 | const genCanvas = false; 18 | function render(plotter, item) { 19 | const pcbPlotter = new kicad_pcb_plotter_1.PCBPlotter(plotter); 20 | // pcbPlotter.layerMask = new LSET(...item.visibleLayers); 21 | // pcbPlotter.plotStandardLayer(item); 22 | // pcbPlotter.plotSilkScreen(item); 23 | plotter.save(); 24 | plotter.translate(0, 0); 25 | plotter.plotPageInfo(item.pageInfo); 26 | pcbPlotter.plotBoardLayers(item, new kicad_pcb_1.LSET(kicad_pcb_1.PCB_LAYER_ID.F_Cu, kicad_pcb_1.PCB_LAYER_ID.F_Fab, kicad_pcb_1.PCB_LAYER_ID.F_CrtYd, kicad_pcb_1.PCB_LAYER_ID.F_Adhes, kicad_pcb_1.PCB_LAYER_ID.F_Paste, kicad_pcb_1.PCB_LAYER_ID.F_SilkS, kicad_pcb_1.PCB_LAYER_ID.Dwgs_User, kicad_pcb_1.PCB_LAYER_ID.Edge_Cuts)); 27 | plotter.restore(); 28 | plotter.save(); 29 | plotter.translate(0, item.pageInfo.height * 2); 30 | plotter.scale(1, -1); 31 | plotter.plotPageInfo(item.pageInfo); 32 | pcbPlotter.plotBoardLayers(item, new kicad_pcb_1.LSET(kicad_pcb_1.PCB_LAYER_ID.B_Cu, kicad_pcb_1.PCB_LAYER_ID.B_Fab, kicad_pcb_1.PCB_LAYER_ID.B_CrtYd, kicad_pcb_1.PCB_LAYER_ID.B_Adhes, kicad_pcb_1.PCB_LAYER_ID.B_Paste, kicad_pcb_1.PCB_LAYER_ID.B_SilkS, kicad_pcb_1.PCB_LAYER_ID.Dwgs_User, kicad_pcb_1.PCB_LAYER_ID.Edge_Cuts)); 33 | plotter.restore(); 34 | } 35 | if (genSVG) { 36 | const item = kicad_pcb_1.PCB.load(content); 37 | if (item instanceof kicad_pcb_1.Board) { 38 | const plotter = new kicad_plotter_1.SVGPlotter(); 39 | plotter.scale(0.5, 0.5); 40 | plotter.startPlot(); 41 | plotter.pageInfo = item.pageInfo; 42 | plotter.pageInfo = new kicad_common_1.PageInfo("User", false, item.pageInfo.width, item.pageInfo.height * 2); 43 | render(plotter, item); 44 | plotter.endPlot(); 45 | fs.writeFileSync("text.svg", plotter.output); 46 | } 47 | else if (item instanceof kicad_pcb_1.Module) { 48 | } 49 | } 50 | if (genCanvas) { 51 | const item = kicad_pcb_1.PCB.load(content); 52 | if (item instanceof kicad_pcb_1.Board) { 53 | const scale = 0.5; 54 | const width = item.pageInfo.width * scale; 55 | const height = item.pageInfo.height * scale * 2; 56 | const Canvas = require('canvas'); 57 | const canvas = Canvas.createCanvas ? Canvas.createCanvas(width, height) : new Canvas(width, height); 58 | const ctx = canvas.getContext('2d'); 59 | ctx.fillStyle = "#000"; 60 | ctx.fillRect(0, 0, canvas.width, canvas.height); 61 | ctx.scale(scale, scale); 62 | const plotter = new kicad_plotter_1.CanvasPlotter(ctx); 63 | plotter.setColor(kicad_common_1.Color.BLACK); 64 | render(plotter, item); 65 | const out = fs.createWriteStream('text.png'), stream = canvas.pngStream(); 66 | stream.on('data', function (chunk) { 67 | out.write(chunk); 68 | }); 69 | stream.on('end', function () { 70 | console.log('saved png'); 71 | }); 72 | } 73 | else if (item instanceof kicad_pcb_1.Module) { 74 | } 75 | } 76 | //# sourceMappingURL=sketch3.js.map -------------------------------------------------------------------------------- /sketch.ts: -------------------------------------------------------------------------------- 1 | //#!tsc && NODE_PATH=dist/src node dist/sketch.js 2 | 3 | import { Transform } from "kicad_common"; 4 | import { CanvasPlotter, SVGPlotter } from "kicad_plotter"; 5 | import { SchPlotter } from "kicad_sch_plotter"; 6 | import { Library } from "kicad_lib"; 7 | import { Schematic } from "kicad_sch"; 8 | 9 | import * as fs from "fs"; 10 | 11 | function ensure(arg: T | null | undefined): T { 12 | if (!arg) throw "arg is falsy"; 13 | return arg; 14 | } 15 | 16 | { // do sch 17 | // const lib = Library.load(fs.readFileSync('../keyboard-schematic/Root-cache.lib', 'utf-8')); 18 | // const sch = Schematic.load(fs.readFileSync('../keyboard-schematic/Root.sch', 'utf-8')); 19 | // const lib = Library.load(fs.readFileSync('../keyboard-schematic/KeyModule-L-cache.lib', 'utf-8')); 20 | // const sch = Schematic.load(fs.readFileSync('../keyboard-schematic/KeyModule-L.sch', 'utf-8')); 21 | const lib = Library.load(fs.readFileSync('../keyboard-schematic/Root-cache.lib', 'utf-8')); 22 | const sch = Schematic.load(fs.readFileSync('../keyboard-schematic/_keymodule_l.sch', 'utf-8')); 23 | // const lib = Library.load(fs.readFileSync('../schematic-test/schematic-test-cache.lib', 'utf-8')); 24 | // const sch = Schematic.load(fs.readFileSync('../schematic-test/file59827D42.sch', 'utf-8')); 25 | // const sch = Schematic.load(fs.readFileSync('../schematic-test/schematic-test.sch', 'utf-8')); 26 | // 27 | // const lib = Library.load(fs.readFileSync('tmp/TinyFPGA-A-Programmer-cache.lib', 'utf-8')); 28 | // const sch = Schematic.load(fs.readFileSync('tmp/TinyFPGA-A-Programmer.sch', 'utf-8')); 29 | console.log(sch); 30 | console.log(lib.findByName("GND")); 31 | 32 | const MAX_WIDTH = 1920 * 2; 33 | const MAX_HEIGHT = 1080 * 2; 34 | 35 | const scale = Math.min(MAX_WIDTH / sch.descr.width, MAX_HEIGHT / sch.descr.height); 36 | 37 | 38 | const Canvas = require('canvas'); 39 | 40 | const canvas = Canvas.createCanvas ? Canvas.createCanvas(sch.descr.width * scale, sch.descr.height * scale) : new Canvas(sch.descr.width * scale, sch.descr.height * scale); 41 | const ctx = canvas.getContext('2d'); 42 | console.log(scale, canvas); 43 | ctx.fillStyle = "#fff"; 44 | ctx.fillRect(0, 0, canvas.width, canvas.height); 45 | ctx.translate(0, 0); 46 | ctx.scale(scale, scale); 47 | 48 | const plotter = new CanvasPlotter(ctx); 49 | // plotter.translate(-sch.descr.width, 0); 50 | // plotter.scale(-1, 1); 51 | // plotter.plotLibComponent(lib.findByName("RJ45"), 1, 1, { x: 500, y: 500 }, new Transform(0, 1, 1, 0)); 52 | plotter.startPlot(); 53 | new SchPlotter(plotter).plotSchematic(sch, [ lib ]); 54 | plotter.endPlot(); 55 | 56 | const out = fs.createWriteStream('text.png'), stream = canvas.pngStream(); 57 | 58 | stream.on('data', function (chunk: any) { 59 | out.write(chunk); 60 | }); 61 | 62 | stream.on('end', function(){ 63 | console.log('saved png'); 64 | }); 65 | 66 | const svgPlotter = new SVGPlotter(); 67 | // svgPlotter.translate(-sch.descr.width, 0); 68 | // svgPlotter.scale(-1, 1); 69 | plotter.pageInfo = sch.descr.pageInfo; 70 | plotter.startPlot(); 71 | new SchPlotter(svgPlotter).plotSchematic(sch, [ lib ]); 72 | plotter.endPlot(); 73 | 74 | let dpi = 72; // 72 dpi == 72000 dot/mil 75 | // sch.descr.{width,height} is mil 76 | // 1000mil = 1inch = 72dot 77 | 78 | fs.writeFileSync("text.svg", svgPlotter.output); 79 | } 80 | 81 | /* 82 | //{ 83 | // const content = fs.readFileSync('/Library/Application Support/kicad/library/74xx.lib', 'utf-8') 84 | // const lib = Library.load(content); 85 | // const component = lib.findByName("74LS00"); 86 | // console.log(component); 87 | // console.log(component.draw); 88 | //}; 89 | 90 | const Canvas = require('canvas'); 91 | const canvas = new Canvas(2000, 2000); 92 | 93 | const ctx = canvas.getContext('2d'); 94 | const content = fs.readFileSync('../keyboard-schematic/Root-cache.lib', 'utf-8') 95 | const lib = Library.load(content); 96 | 97 | // const component = lib.findByName("INDUCTOR"); 98 | // const component = lib.findByName("JUMPER3"); 99 | // const component = lib.findByName("LED_RGB"); 100 | // const component = lib.findByName("Led_x2"); 101 | 102 | const plotter = new CanvasPlotter(ctx); 103 | plotter.plotLibComponent(ensure(lib.findByName("RJ45")), 1, 1, new Transform(0, 1, 1, 0, 1000, 1000)); 104 | // plotter.plotLibComponent(ensure(lib.findByName("RJ45")), 1, 1, new Transform().translate(1000, 1000)); 105 | 106 | const out = fs.createWriteStream('text.png'), stream = canvas.pngStream(); 107 | 108 | stream.on('data', function (chunk: any) { 109 | out.write(chunk); 110 | }); 111 | 112 | stream.on('end', function(){ 113 | console.log('saved png'); 114 | }); 115 | 116 | //const svgPlotter = new SVGPlotter(); 117 | //svgPlotter.plotLibComponent(ensure(lib.findByName("RJ45")), 1, 1, new Transform(0, 1, 1, 0).translate(1000, 1000)); 118 | //fs.writeFileSync("text.svg", svgPlotter.output); 119 | //*/ 120 | -------------------------------------------------------------------------------- /dist/sketch.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | //#!tsc && NODE_PATH=dist/src node dist/sketch.js 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | const kicad_plotter_1 = require("kicad_plotter"); 5 | const kicad_sch_plotter_1 = require("kicad_sch_plotter"); 6 | const kicad_lib_1 = require("kicad_lib"); 7 | const kicad_sch_1 = require("kicad_sch"); 8 | const fs = require("fs"); 9 | function ensure(arg) { 10 | if (!arg) 11 | throw "arg is falsy"; 12 | return arg; 13 | } 14 | { // do sch 15 | // const lib = Library.load(fs.readFileSync('../keyboard-schematic/Root-cache.lib', 'utf-8')); 16 | // const sch = Schematic.load(fs.readFileSync('../keyboard-schematic/Root.sch', 'utf-8')); 17 | // const lib = Library.load(fs.readFileSync('../keyboard-schematic/KeyModule-L-cache.lib', 'utf-8')); 18 | // const sch = Schematic.load(fs.readFileSync('../keyboard-schematic/KeyModule-L.sch', 'utf-8')); 19 | const lib = kicad_lib_1.Library.load(fs.readFileSync('../keyboard-schematic/Root-cache.lib', 'utf-8')); 20 | const sch = kicad_sch_1.Schematic.load(fs.readFileSync('../keyboard-schematic/_keymodule_l.sch', 'utf-8')); 21 | // const lib = Library.load(fs.readFileSync('../schematic-test/schematic-test-cache.lib', 'utf-8')); 22 | // const sch = Schematic.load(fs.readFileSync('../schematic-test/file59827D42.sch', 'utf-8')); 23 | // const sch = Schematic.load(fs.readFileSync('../schematic-test/schematic-test.sch', 'utf-8')); 24 | // 25 | // const lib = Library.load(fs.readFileSync('tmp/TinyFPGA-A-Programmer-cache.lib', 'utf-8')); 26 | // const sch = Schematic.load(fs.readFileSync('tmp/TinyFPGA-A-Programmer.sch', 'utf-8')); 27 | console.log(sch); 28 | console.log(lib.findByName("GND")); 29 | const MAX_WIDTH = 1920 * 2; 30 | const MAX_HEIGHT = 1080 * 2; 31 | const scale = Math.min(MAX_WIDTH / sch.descr.width, MAX_HEIGHT / sch.descr.height); 32 | const Canvas = require('canvas'); 33 | const canvas = Canvas.createCanvas ? Canvas.createCanvas(sch.descr.width * scale, sch.descr.height * scale) : new Canvas(sch.descr.width * scale, sch.descr.height * scale); 34 | const ctx = canvas.getContext('2d'); 35 | console.log(scale, canvas); 36 | ctx.fillStyle = "#fff"; 37 | ctx.fillRect(0, 0, canvas.width, canvas.height); 38 | ctx.translate(0, 0); 39 | ctx.scale(scale, scale); 40 | const plotter = new kicad_plotter_1.CanvasPlotter(ctx); 41 | // plotter.translate(-sch.descr.width, 0); 42 | // plotter.scale(-1, 1); 43 | // plotter.plotLibComponent(lib.findByName("RJ45"), 1, 1, { x: 500, y: 500 }, new Transform(0, 1, 1, 0)); 44 | plotter.startPlot(); 45 | new kicad_sch_plotter_1.SchPlotter(plotter).plotSchematic(sch, [lib]); 46 | plotter.endPlot(); 47 | const out = fs.createWriteStream('text.png'), stream = canvas.pngStream(); 48 | stream.on('data', function (chunk) { 49 | out.write(chunk); 50 | }); 51 | stream.on('end', function () { 52 | console.log('saved png'); 53 | }); 54 | const svgPlotter = new kicad_plotter_1.SVGPlotter(); 55 | // svgPlotter.translate(-sch.descr.width, 0); 56 | // svgPlotter.scale(-1, 1); 57 | plotter.pageInfo = sch.descr.pageInfo; 58 | plotter.startPlot(); 59 | new kicad_sch_plotter_1.SchPlotter(svgPlotter).plotSchematic(sch, [lib]); 60 | plotter.endPlot(); 61 | let dpi = 72; // 72 dpi == 72000 dot/mil 62 | // sch.descr.{width,height} is mil 63 | // 1000mil = 1inch = 72dot 64 | fs.writeFileSync("text.svg", svgPlotter.output); 65 | } 66 | /* 67 | //{ 68 | // const content = fs.readFileSync('/Library/Application Support/kicad/library/74xx.lib', 'utf-8') 69 | // const lib = Library.load(content); 70 | // const component = lib.findByName("74LS00"); 71 | // console.log(component); 72 | // console.log(component.draw); 73 | //}; 74 | 75 | const Canvas = require('canvas'); 76 | const canvas = new Canvas(2000, 2000); 77 | 78 | const ctx = canvas.getContext('2d'); 79 | const content = fs.readFileSync('../keyboard-schematic/Root-cache.lib', 'utf-8') 80 | const lib = Library.load(content); 81 | 82 | // const component = lib.findByName("INDUCTOR"); 83 | // const component = lib.findByName("JUMPER3"); 84 | // const component = lib.findByName("LED_RGB"); 85 | // const component = lib.findByName("Led_x2"); 86 | 87 | const plotter = new CanvasPlotter(ctx); 88 | plotter.plotLibComponent(ensure(lib.findByName("RJ45")), 1, 1, new Transform(0, 1, 1, 0, 1000, 1000)); 89 | // plotter.plotLibComponent(ensure(lib.findByName("RJ45")), 1, 1, new Transform().translate(1000, 1000)); 90 | 91 | const out = fs.createWriteStream('text.png'), stream = canvas.pngStream(); 92 | 93 | stream.on('data', function (chunk: any) { 94 | out.write(chunk); 95 | }); 96 | 97 | stream.on('end', function(){ 98 | console.log('saved png'); 99 | }); 100 | 101 | //const svgPlotter = new SVGPlotter(); 102 | //svgPlotter.plotLibComponent(ensure(lib.findByName("RJ45")), 1, 1, new Transform(0, 1, 1, 0).translate(1000, 1000)); 103 | //fs.writeFileSync("text.svg", svgPlotter.output); 104 | //*/ 105 | //# sourceMappingURL=sketch.js.map -------------------------------------------------------------------------------- /src/kicad-utils_cui.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { 4 | Transform, 5 | CanvasPlotter, 6 | SVGPlotter, 7 | SchPlotter, 8 | Lib, 9 | Sch, 10 | } from "./kicad-utils"; 11 | 12 | import * as fs from "fs"; 13 | import * as path from "path"; 14 | import * as minimist from "minimist"; 15 | 16 | let verbose = 0; 17 | function v (...a: any[]) { if (verbose >= 1) console.log(...a); } 18 | function vv (...a: any[]) { if (verbose >= 2) console.log(...a); } 19 | function vvv (...a: any[]) { if (verbose >= 3) console.log(...a); } 20 | 21 | const commands : { [key: string]: (argv: any[]) => void } = { 22 | sch2svg : function (_argv: any[]) { 23 | const argv = minimist(_argv, { 24 | boolean: true, 25 | alias: { 26 | "o": "output", 27 | "h": "help", 28 | } 29 | }); 30 | if (argv.help || !argv._.length) { 31 | console.log('Usage: sch2svg [options] [file.lib] file.sch'); 32 | console.log('Options:'); 33 | console.log(' -h --help: show help'); 34 | console.log(' --force: force overwrite'); 35 | console.log(' -o --output: output file (default=basename-of-sch.svg)'); 36 | console.log(' -png: set output format to png (require npm install canvas)'); 37 | console.log(' -v -vv -vvv: verbose mode'); 38 | process.exit(argv.help ? 0 : 1); 39 | } 40 | vv(argv); 41 | const libFiles : Array = []; 42 | const schFiles : Array = []; 43 | for (let arg of argv._) { 44 | if (arg.endsWith(".sch")) { 45 | v("Add SCH file", arg); 46 | schFiles.push(arg); 47 | } else 48 | if (arg.endsWith(".lib")) { 49 | v("Add LIB file", arg); 50 | libFiles.push(arg); 51 | } else { 52 | console.warn("WARN: unkown file type: " + arg); 53 | } 54 | } 55 | 56 | const _libs: { [key: string]: Lib.Library } = {}; 57 | function lib(path: string): Lib.Library { 58 | if (!_libs[path]) { 59 | v("Loading LIB", path); 60 | try { 61 | const content = fs.readFileSync(path, 'utf-8'); 62 | _libs[path] = Lib.Library.load(content); 63 | } catch (e) { 64 | console.warn(e); 65 | } 66 | } 67 | return _libs[path]; 68 | } 69 | 70 | for (let schFile of schFiles) { 71 | 72 | const outFile = argv.output || schFile.replace(/\.sch$/, argv.png ? '.png' : '.svg'); 73 | v("Checking output file", outFile); 74 | try { 75 | const stat = fs.statSync(outFile); 76 | if (stat) { 77 | if (!argv.force) { 78 | console.warn(outFile + " is already exists. skip"); 79 | continue; 80 | } 81 | } 82 | } catch (e) { 83 | if (e.code === 'ENOENT') { 84 | // ok 85 | } else { 86 | throw e; 87 | } 88 | } 89 | 90 | const libs = libFiles.map( (i) => lib(i) ); 91 | if (!libs.length) { 92 | v("Autoload .lib files from directory because .lib files are not specified"); 93 | const dir = path.dirname(schFile); 94 | const files = fs.readdirSync(dir); 95 | for (let file of files) { 96 | if (file.endsWith(".lib")) { 97 | libs.push(lib(path.join(dir, file))); 98 | } 99 | } 100 | } 101 | 102 | 103 | v("Loading SCH", schFile); 104 | const sch = Sch.Schematic.load(fs.readFileSync(schFile, 'utf-8')); 105 | 106 | if (argv.png) { 107 | const MAX_WIDTH = 1920 * 2; 108 | const MAX_HEIGHT = 1080 * 2; 109 | const scale = Math.min(MAX_WIDTH / sch.descr.width, MAX_HEIGHT / sch.descr.height); 110 | 111 | const Canvas = require('canvas'); 112 | const canvas = Canvas.createCanvas ? Canvas.createCanvas(sch.descr.width * scale, sch.descr.height * scale) : new Canvas(sch.descr.width * scale, sch.descr.height * scale); 113 | const ctx = canvas.getContext('2d'); 114 | ctx.fillStyle = "#fff"; 115 | ctx.fillRect(0, 0, canvas.width, canvas.height); 116 | ctx.translate(0, 0); 117 | ctx.scale(scale, scale); 118 | 119 | const plotter = new CanvasPlotter(ctx); 120 | plotter.startPlot(); 121 | new SchPlotter(plotter).plotSchematic(sch, libs); 122 | plotter.endPlot(); 123 | const out = fs.createWriteStream(outFile), stream = canvas.pngStream(); 124 | stream.on('data', function (chunk: any) { 125 | out.write(chunk); 126 | }); 127 | stream.on('end', function(){ 128 | console.log('saved png'); 129 | }); 130 | } else { 131 | console.log('Plotting with SVGPlotter'); 132 | const svgPlotter = new SVGPlotter(); 133 | svgPlotter.startPlot(); 134 | new SchPlotter(svgPlotter).plotSchematic(sch, libs); 135 | svgPlotter.endPlot(); 136 | console.log(`Writing output to ${outFile}`); 137 | fs.writeFileSync(outFile, svgPlotter.output); 138 | } 139 | } 140 | } 141 | }; 142 | 143 | const argv = minimist(process.argv.slice(2), { 144 | stopEarly: true, // do not parse subcommand args 145 | boolean: true, 146 | alias: { 147 | "h": "help", 148 | } 149 | }); 150 | verbose = (Object.keys(argv).find( (i) => /^v+$/.test(i) ) || "").length; 151 | 152 | vv(argv);; 153 | 154 | const subcommand = argv._.shift() as string; 155 | if (!subcommand || argv.help) { 156 | console.log("Usage: kicad-utils [opts] [subcommand]"); 157 | console.log('Options:'); 158 | console.log(' -h --help: show help'); 159 | console.log(' --v --vv --vvv: verbose mode'); 160 | console.log('Sub commands:'); 161 | process.exit(argv.help ? 0 : 1); 162 | } 163 | 164 | const func = commands[subcommand]; 165 | if (!func) { 166 | console.warn(`Unknown subcommand ${subcommand}`); 167 | process.exit(1); 168 | } 169 | 170 | func(argv._); 171 | 172 | -------------------------------------------------------------------------------- /dist/src/kicad-utils_cui.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"kicad-utils_cui.js","sourceRoot":"","sources":["../../src/kicad-utils_cui.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /static/js/worker.js: -------------------------------------------------------------------------------- 1 | 2 | const { 3 | Transform, 4 | CanvasPlotter, 5 | Color, 6 | SVGPlotter, 7 | PCBPlotter, 8 | SchPlotter, 9 | Lib, 10 | Sch, 11 | Pcb, 12 | } = require("kicad-utils"); 13 | 14 | let libs = []; 15 | 16 | MethodWorker.work({ 17 | echo: function (arg) { 18 | return ['echo'].concat(Array.from(arguments)); 19 | }, 20 | 21 | loadLibs: function (contents) { 22 | libs = libs.concat(contents.map((content) => Lib.Library.load(content) )); 23 | }, 24 | 25 | unloadLibs: function () { 26 | libs = []; 27 | }, 28 | 29 | renderPCB: function (content) { 30 | const L = Pcb.PCB_LAYER_ID; 31 | const pcb = Pcb.PCB.load(content); 32 | const render = (pcb, cb) => { 33 | const plotter = new SVGPlotter(); 34 | plotter.pageInfo = pcb.pageInfo; 35 | plotter.startPlot(); 36 | const pcbPlotter = new PCBPlotter(plotter); 37 | plotter.save(); 38 | plotter.translate(0, 0); 39 | plotter.setColor(Color.WHITE); 40 | plotter.plotPageInfo(pcb.pageInfo); 41 | cb(plotter, pcbPlotter); 42 | plotter.restore(); 43 | plotter.endPlot(); 44 | const svg = plotter.output; 45 | for (let error of plotter.errors) { 46 | this.errors.push(error); 47 | } 48 | 49 | let src; 50 | if (typeof Blob !== 'undefined') { 51 | const blob = new Blob([svg], {type : 'image/svg+xml'}); 52 | src = URL.createObjectURL(blob); 53 | } else { 54 | src = 'data:image/svg+xml,' + encodeURIComponent(svg); 55 | } 56 | return src; 57 | }; 58 | const layers = [ 59 | { 60 | name: "F_Cu", 61 | src: render(pcb, (plotter, pcbPlotter) => { 62 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 63 | L.F_Cu, 64 | )); 65 | }), 66 | visible: true, 67 | }, 68 | { 69 | name: "B_Cu", 70 | src: render(pcb, (plotter, pcbPlotter) => { 71 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 72 | L.B_Cu, 73 | )); 74 | }), 75 | visible: true, 76 | }, 77 | { 78 | name: "F_Adhes", 79 | src: render(pcb, (plotter, pcbPlotter) => { 80 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 81 | L.F_Adhes, 82 | )); 83 | }), 84 | visible: true, 85 | }, 86 | { 87 | name: "B_Adhes", 88 | src: render(pcb, (plotter, pcbPlotter) => { 89 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 90 | L.B_Adhes, 91 | )); 92 | }), 93 | visible: true, 94 | }, 95 | { 96 | name: "F_Paste", 97 | src: render(pcb, (plotter, pcbPlotter) => { 98 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 99 | L.F_Paste, 100 | )); 101 | }), 102 | visible: true, 103 | }, 104 | { 105 | name: "B_Paste", 106 | src: render(pcb, (plotter, pcbPlotter) => { 107 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 108 | L.B_Paste, 109 | )); 110 | }), 111 | visible: true, 112 | }, 113 | { 114 | name: "F_SilkS", 115 | src: render(pcb, (plotter, pcbPlotter) => { 116 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 117 | L.F_SilkS, 118 | )); 119 | }), 120 | visible: true, 121 | }, 122 | { 123 | name: "B_SilkS", 124 | src: render(pcb, (plotter, pcbPlotter) => { 125 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 126 | L.B_SilkS, 127 | )); 128 | }), 129 | visible: true, 130 | }, 131 | { 132 | name: "F_Mask", 133 | src: render(pcb, (plotter, pcbPlotter) => { 134 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 135 | L.F_Mask, 136 | )); 137 | }), 138 | visible: true, 139 | }, 140 | { 141 | name: "B_Mask", 142 | src: render(pcb, (plotter, pcbPlotter) => { 143 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 144 | L.B_Mask, 145 | )); 146 | }), 147 | visible: true, 148 | }, 149 | { 150 | name: "Dwgs_User", 151 | src: render(pcb, (plotter, pcbPlotter) => { 152 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 153 | L.Dwgs_User, 154 | )); 155 | }), 156 | visible: true, 157 | }, 158 | { 159 | name: "Eco1.User", 160 | src: render(pcb, (plotter, pcbPlotter) => { 161 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 162 | L.Eco1_User 163 | )); 164 | }), 165 | visible: true, 166 | }, 167 | { 168 | name: "Eco2.User", 169 | src: render(pcb, (plotter, pcbPlotter) => { 170 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 171 | L.Eco2_User 172 | )); 173 | }), 174 | visible: true, 175 | }, 176 | { 177 | name: "Edge_Cuts", 178 | src: render(pcb, (plotter, pcbPlotter) => { 179 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 180 | L.Edge_Cuts, 181 | )); 182 | }), 183 | visible: true, 184 | }, 185 | { 186 | name: "F_CrtYd", 187 | src: render(pcb, (plotter, pcbPlotter) => { 188 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 189 | L.F_CrtYd, 190 | )); 191 | }), 192 | visible: true, 193 | }, 194 | { 195 | name: "B_CrtYd", 196 | src: render(pcb, (plotter, pcbPlotter) => { 197 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 198 | L.B_CrtYd, 199 | )); 200 | }), 201 | visible: true, 202 | }, 203 | { 204 | name: "F_Fab", 205 | src: render(pcb, (plotter, pcbPlotter) => { 206 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 207 | L.F_Fab, 208 | )); 209 | }), 210 | visible: true, 211 | }, 212 | { 213 | name: "B_Fab", 214 | src: render(pcb, (plotter, pcbPlotter) => { 215 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 216 | L.B_Fab, 217 | )); 218 | }), 219 | visible: true, 220 | }, 221 | ]; 222 | 223 | return { 224 | errors: [], 225 | layers: layers, 226 | }; 227 | }, 228 | 229 | renderSch: function (content) { 230 | const sch = Sch.Schematic.load(content); 231 | 232 | const svgPlotter = new SVGPlotter(); 233 | svgPlotter.pageInfo = sch.descr.pageInfo; 234 | svgPlotter.startPlot(); 235 | new SchPlotter(svgPlotter).plotSchematic(sch, libs); 236 | svgPlotter.endPlot(); 237 | const svg = svgPlotter.output; 238 | 239 | let src; 240 | if (typeof Blob !== 'undefined') { 241 | const blob = new Blob([svg], {type : 'image/svg+xml'}); 242 | src = URL.createObjectURL(blob); 243 | } else { 244 | src = 'data:image/svg+xml,' + encodeURIComponent(svg); 245 | } 246 | 247 | return { 248 | src: src, 249 | errors: svgPlotter.errors, 250 | }; 251 | } 252 | 253 | }); 254 | -------------------------------------------------------------------------------- /test/kicad_common.ts: -------------------------------------------------------------------------------- 1 | //#!npm run test-one 2 | 3 | import * as assert from "assert"; 4 | import * as mocha from 'mocha'; 5 | 6 | import { 7 | DECIDEG2RAD, 8 | RAD2DECIDEG, 9 | NORMALIZE_ANGLE_POS, 10 | MM2MIL, 11 | MIL2MM, 12 | ReadDelimitedText, 13 | 14 | RotatePoint, 15 | RotatePointWithCenter, 16 | Point, 17 | Rect, 18 | Transform, 19 | } from "../src/kicad_common"; 20 | 21 | describe("DECIDEG2RAD", () => { 22 | it("converts deci degrees to radian", () => { 23 | assert( DECIDEG2RAD(0) === 0); 24 | assert( DECIDEG2RAD(900) === Math.PI / 2 * 1); 25 | assert( DECIDEG2RAD(1800) === Math.PI / 2 * 2); 26 | assert( DECIDEG2RAD(2700) === Math.PI / 2 * 3); 27 | assert( DECIDEG2RAD(3600) === Math.PI / 2 * 4); 28 | }); 29 | }); 30 | 31 | describe("RAD2DECIDEG", () => { 32 | it("converts radian to deci degree", () => { 33 | assert( ~~RAD2DECIDEG(0) === 0 ); 34 | assert( ~~RAD2DECIDEG(Math.PI / 2 * 1) === 900 ); 35 | assert( ~~RAD2DECIDEG(Math.PI / 2 * 2) === 1800 ); 36 | assert( ~~RAD2DECIDEG(Math.PI / 2 * 3) === 2700 ); 37 | assert( ~~RAD2DECIDEG(Math.PI / 2 * 4) === 3600 ); 38 | }); 39 | }); 40 | 41 | describe("NORMALIZE_ANGLE_POS", () => { 42 | it("normalize angle to 0..3600", () => { 43 | assert( NORMALIZE_ANGLE_POS(0) === 0 ); 44 | assert( NORMALIZE_ANGLE_POS(-1) === 3599 ); 45 | assert( NORMALIZE_ANGLE_POS(3599) === 3599 ); 46 | assert( NORMALIZE_ANGLE_POS(3600) === 0 ); 47 | }); 48 | }); 49 | 50 | describe("RotatePoint", () => { 51 | it("rotate a point with angle", () => { 52 | // edge cases 53 | assert.deepEqual(RotatePoint(new Point(1, 2), 0), new Point(1, 2)); 54 | assert.deepEqual(RotatePoint(new Point(1, 2), 900), new Point(2, -1)); 55 | assert.deepEqual(RotatePoint(new Point(1, 2), 1800), new Point(-1, -2)); 56 | assert.deepEqual(RotatePoint(new Point(1, 2), 2700), new Point(-2, 1)); 57 | assert.deepEqual(RotatePoint(new Point(1, 2), 3600), new Point(1, 2)); 58 | 59 | // fallback 60 | const p = new Point(1, 2); 61 | RotatePoint(p, 450); 62 | assert(2.121 < p.x && p.x < 2.122); 63 | assert(0.707 < p.y && p.y < 0.708); 64 | }); 65 | }); 66 | 67 | describe("RotatePointWithCenter", () => { 68 | it("rotate a point with angle: center = 0,0 is same as RotatePoint", () => { 69 | // edge cases 70 | assert.deepEqual(RotatePointWithCenter(new Point(1, 2), new Point(0, 0), 0), new Point(1, 2)); 71 | assert.deepEqual(RotatePointWithCenter(new Point(1, 2), new Point(0, 0), 900), new Point(2, -1)); 72 | assert.deepEqual(RotatePointWithCenter(new Point(1, 2), new Point(0, 0), 1800), new Point(-1, -2)); 73 | assert.deepEqual(RotatePointWithCenter(new Point(1, 2), new Point(0, 0), 2700), new Point(-2, 1)); 74 | assert.deepEqual(RotatePointWithCenter(new Point(1, 2), new Point(0, 0), 3600), new Point(1, 2)); 75 | 76 | // fallback 77 | const p = new Point(1, 2); 78 | RotatePointWithCenter(p, new Point(0, 0), 450); 79 | assert(2.121 < p.x && p.x < 2.122); 80 | assert(0.707 < p.y && p.y < 0.708); 81 | }); 82 | it("rotate a point with angle and center", () => { 83 | // edge cases 84 | assert.deepEqual(RotatePointWithCenter(new Point(1, 2), new Point(3, 4), 0), new Point(1, 2)); 85 | assert.deepEqual(RotatePointWithCenter(new Point(1, 2), new Point(3, 4), 900), new Point(1, 6)); 86 | assert.deepEqual(RotatePointWithCenter(new Point(1, 2), new Point(3, 4), 1800), new Point(5, 6)); 87 | assert.deepEqual(RotatePointWithCenter(new Point(1, 2), new Point(3, 4), 2700), new Point(5, 2)); 88 | assert.deepEqual(RotatePointWithCenter(new Point(1, 2), new Point(3, 4), 3600), new Point(1, 2)); 89 | 90 | // fallback 91 | const p = new Point(1, 2); 92 | RotatePointWithCenter(p, new Point(3, 4), 450); 93 | assert(0.171 < p.x && p.x < 0.172); 94 | assert(3.999 < p.y && p.y < 4.001); 95 | }); 96 | }); 97 | 98 | describe("MM2MIL", () => { 99 | it("convert unit mm to mil (1/1000 inches)", () => { 100 | assert(~~MM2MIL(100) === 3937); 101 | }); 102 | }); 103 | 104 | describe("MIL2MM", () => { 105 | it("convert unit mil (1/1000 inches) to mm", () => { 106 | assert(~~MIL2MM(100000) === 2540); 107 | }); 108 | }); 109 | 110 | describe("ReadDelimitedText", () => { 111 | it("convert parsed string to original value", () => { 112 | assert(ReadDelimitedText(`foo`) === ""); 113 | assert(ReadDelimitedText(`"foo"`) === "foo"); 114 | assert(ReadDelimitedText(`foo"bar"`) === "bar"); 115 | assert(ReadDelimitedText(`"foo\\"bar"`) === `foo"bar`); 116 | assert(ReadDelimitedText(`"foo\\\\bar"`) === `foo\\bar`); 117 | assert(ReadDelimitedText(`"foo\\bar"`) === `foo\\bar`); 118 | }); 119 | }); 120 | 121 | describe("Transform", () => { 122 | it("has default transform value", () => { 123 | // y-inverted transform by default (from KiCAD) 124 | const t = new Transform(); 125 | assert(t.x1 === 1); 126 | assert(t.y1 === 0); 127 | assert(t.x2 === 0); 128 | assert(t.y2 === -1); 129 | }); 130 | 131 | it("has transformCoordinate method", () => { 132 | const t = new Transform(); 133 | const p = t.transformCoordinate(new Point(1, 1)); 134 | assert( p.x === 1); 135 | assert( p.y === -1); 136 | }); 137 | 138 | it("has mapAngles method", () => { 139 | const t = new Transform(); 140 | assert.deepEqual( t.mapAngles(0, 1800), [2, 1798, 0]); 141 | assert.deepEqual( t.mapAngles(900, 1800), [1800, 2700, 1]); 142 | }); 143 | }); 144 | 145 | describe("Point", () => { 146 | it("has default value", () => { 147 | assert.deepEqual( new Point(), new Point(0, 0) ); 148 | }); 149 | 150 | it("has static add function", () => { 151 | assert.deepEqual( Point.add(new Point(1, 2), new Point(3, 4)) , new Point(4, 6) ); 152 | }); 153 | 154 | it("has static sub function", () => { 155 | assert.deepEqual( Point.sub(new Point(1, 2), new Point(3, 4)) , new Point(-2, -2) ); 156 | }); 157 | 158 | it("has static isZero function", () => { 159 | assert(Point.isZero(new Point())); 160 | assert(!Point.isZero(new Point(1, 0))); 161 | assert(!Point.isZero(new Point(0, 1))); 162 | assert(!Point.isZero(new Point(-1, 0))); 163 | assert(!Point.isZero(new Point(0, -1))); 164 | }); 165 | }); 166 | 167 | describe("Rect", () => { 168 | it("has merge function", () => { 169 | const rect1 = new Rect(1, 2, 3, 4); 170 | 171 | assert.deepEqual(rect1.merge(new Rect(3, 4, 5, 6)), new Rect(1, 2, 5, 6)); 172 | assert.deepEqual(rect1.merge(new Rect(-3, -4, -5, -6)), new Rect(-5, -6, 3, 4)); 173 | }); 174 | 175 | it("has inflate function", () => { 176 | assert.deepEqual( new Rect(0, 0, 0, 0).inflate(1), new Rect(-1, -1, 1, 1)); 177 | }); 178 | }); 179 | 180 | -------------------------------------------------------------------------------- /dist/src/kicad-utils_cui.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | const kicad_utils_1 = require("./kicad-utils"); 5 | const fs = require("fs"); 6 | const path = require("path"); 7 | const minimist = require("minimist"); 8 | let verbose = 0; 9 | function v(...a) { if (verbose >= 1) 10 | console.log(...a); } 11 | function vv(...a) { if (verbose >= 2) 12 | console.log(...a); } 13 | function vvv(...a) { if (verbose >= 3) 14 | console.log(...a); } 15 | const commands = { 16 | sch2svg: function (_argv) { 17 | const argv = minimist(_argv, { 18 | boolean: true, 19 | alias: { 20 | "o": "output", 21 | "h": "help", 22 | } 23 | }); 24 | if (argv.help || !argv._.length) { 25 | console.log('Usage: sch2svg [options] [file.lib] file.sch'); 26 | console.log('Options:'); 27 | console.log(' -h --help: show help'); 28 | console.log(' --force: force overwrite'); 29 | console.log(' -o --output: output file (default=basename-of-sch.svg)'); 30 | console.log(' -png: set output format to png (require npm install canvas)'); 31 | console.log(' -v -vv -vvv: verbose mode'); 32 | process.exit(argv.help ? 0 : 1); 33 | } 34 | vv(argv); 35 | const libFiles = []; 36 | const schFiles = []; 37 | for (let arg of argv._) { 38 | if (arg.endsWith(".sch")) { 39 | v("Add SCH file", arg); 40 | schFiles.push(arg); 41 | } 42 | else if (arg.endsWith(".lib")) { 43 | v("Add LIB file", arg); 44 | libFiles.push(arg); 45 | } 46 | else { 47 | console.warn("WARN: unkown file type: " + arg); 48 | } 49 | } 50 | const _libs = {}; 51 | function lib(path) { 52 | if (!_libs[path]) { 53 | v("Loading LIB", path); 54 | try { 55 | const content = fs.readFileSync(path, 'utf-8'); 56 | _libs[path] = kicad_utils_1.Lib.Library.load(content); 57 | } 58 | catch (e) { 59 | console.warn(e); 60 | } 61 | } 62 | return _libs[path]; 63 | } 64 | for (let schFile of schFiles) { 65 | const outFile = argv.output || schFile.replace(/\.sch$/, argv.png ? '.png' : '.svg'); 66 | v("Checking output file", outFile); 67 | try { 68 | const stat = fs.statSync(outFile); 69 | if (stat) { 70 | if (!argv.force) { 71 | console.warn(outFile + " is already exists. skip"); 72 | continue; 73 | } 74 | } 75 | } 76 | catch (e) { 77 | if (e.code === 'ENOENT') { 78 | // ok 79 | } 80 | else { 81 | throw e; 82 | } 83 | } 84 | const libs = libFiles.map((i) => lib(i)); 85 | if (!libs.length) { 86 | v("Autoload .lib files from directory because .lib files are not specified"); 87 | const dir = path.dirname(schFile); 88 | const files = fs.readdirSync(dir); 89 | for (let file of files) { 90 | if (file.endsWith(".lib")) { 91 | libs.push(lib(path.join(dir, file))); 92 | } 93 | } 94 | } 95 | v("Loading SCH", schFile); 96 | const sch = kicad_utils_1.Sch.Schematic.load(fs.readFileSync(schFile, 'utf-8')); 97 | if (argv.png) { 98 | const MAX_WIDTH = 1920 * 2; 99 | const MAX_HEIGHT = 1080 * 2; 100 | const scale = Math.min(MAX_WIDTH / sch.descr.width, MAX_HEIGHT / sch.descr.height); 101 | const Canvas = require('canvas'); 102 | const canvas = Canvas.createCanvas ? Canvas.createCanvas(sch.descr.width * scale, sch.descr.height * scale) : new Canvas(sch.descr.width * scale, sch.descr.height * scale); 103 | const ctx = canvas.getContext('2d'); 104 | ctx.fillStyle = "#fff"; 105 | ctx.fillRect(0, 0, canvas.width, canvas.height); 106 | ctx.translate(0, 0); 107 | ctx.scale(scale, scale); 108 | const plotter = new kicad_utils_1.CanvasPlotter(ctx); 109 | plotter.startPlot(); 110 | new kicad_utils_1.SchPlotter(plotter).plotSchematic(sch, libs); 111 | plotter.endPlot(); 112 | const out = fs.createWriteStream(outFile), stream = canvas.pngStream(); 113 | stream.on('data', function (chunk) { 114 | out.write(chunk); 115 | }); 116 | stream.on('end', function () { 117 | console.log('saved png'); 118 | }); 119 | } 120 | else { 121 | console.log('Plotting with SVGPlotter'); 122 | const svgPlotter = new kicad_utils_1.SVGPlotter(); 123 | svgPlotter.startPlot(); 124 | new kicad_utils_1.SchPlotter(svgPlotter).plotSchematic(sch, libs); 125 | svgPlotter.endPlot(); 126 | console.log(`Writing output to ${outFile}`); 127 | fs.writeFileSync(outFile, svgPlotter.output); 128 | } 129 | } 130 | } 131 | }; 132 | const argv = minimist(process.argv.slice(2), { 133 | stopEarly: true, 134 | boolean: true, 135 | alias: { 136 | "h": "help", 137 | } 138 | }); 139 | verbose = (Object.keys(argv).find((i) => /^v+$/.test(i)) || "").length; 140 | vv(argv); 141 | ; 142 | const subcommand = argv._.shift(); 143 | if (!subcommand || argv.help) { 144 | console.log("Usage: kicad-utils [opts] [subcommand]"); 145 | console.log('Options:'); 146 | console.log(' -h --help: show help'); 147 | console.log(' --v --vv --vvv: verbose mode'); 148 | console.log('Sub commands:'); 149 | process.exit(argv.help ? 0 : 1); 150 | } 151 | const func = commands[subcommand]; 152 | if (!func) { 153 | console.warn(`Unknown subcommand ${subcommand}`); 154 | process.exit(1); 155 | } 156 | func(argv._); 157 | //# sourceMappingURL=kicad-utils_cui.js.map -------------------------------------------------------------------------------- /dist/src/kicad_strokefont.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"kicad_strokefont.js","sourceRoot":"","sources":["../../src/kicad_strokefont.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /static/js/common.js: -------------------------------------------------------------------------------- 1 | const Vue = require("vue"); 2 | 3 | Vue.directive('imgarea', { 4 | bind: function (el) { 5 | el.style.display = "relative"; 6 | el.style.transformOrigin = "0 0"; 7 | el.style.cursor = 'all-scroll'; 8 | 9 | let translateX = 0; 10 | let translateY = 0; 11 | let scale = 1; 12 | const updateTransform = () => { 13 | const maxWidth = el.offsetWidth; 14 | const maxHeight = el.offsetHeight; 15 | const width = el.offsetWidth * scale; 16 | const height = el.offsetHeight * scale; 17 | 18 | const restWidth = maxWidth - width; 19 | const restHeight = maxHeight - height; 20 | 21 | if (translateY > 0) { 22 | translateY = 0; 23 | } else 24 | if (translateY < restHeight) { 25 | translateY = restHeight; 26 | } 27 | 28 | if (translateX > 0) { 29 | translateX = 0; 30 | } else 31 | if (translateX < restWidth) { 32 | translateX = restWidth; 33 | } 34 | 35 | const transform = `translate(${translateX}px, ${translateY}px) scale(${scale}, ${scale})`; 36 | el.style.transform = transform; 37 | }; 38 | 39 | let down = null; 40 | el.addEventListener('mousedown', function (e) { 41 | const offsetX = e.pageX - el.offsetLeft - translateX; 42 | const offsetY = e.pageY - el.offsetTop - translateY; 43 | 44 | down = { 45 | tX: translateX, 46 | tY: translateY, 47 | clientX: e.clientX, 48 | clientY: e.clientY, 49 | }; 50 | e.preventDefault(); 51 | }); 52 | el.addEventListener('mousemove', function (e) { 53 | if (!down) return; 54 | e.preventDefault(); 55 | requestAnimationFrame( () => { 56 | if (!down) return; // ensure mouse down 57 | const moveX = e.clientX - down.clientX; 58 | const moveY = e.clientY - down.clientY; 59 | translateX = down.tX + moveX; 60 | translateY = down.tY + moveY; 61 | updateTransform(); 62 | }); 63 | }); 64 | window.addEventListener('mouseup', function (e) { 65 | if (!down) return; 66 | e.preventDefault(); 67 | const moveX = e.clientX - down.clientX; 68 | const moveY = e.clientY - down.clientY; 69 | translateX = down.tX + moveX; 70 | translateY = down.tY + moveY; 71 | down = null; 72 | updateTransform(); 73 | }); 74 | el.addEventListener('wheel', function (e) { 75 | e.preventDefault(); 76 | let newScale = scale - e.deltaY / 100; 77 | // let newScale = scale * (e.deltaY > 0 ? 0.8 : 1.2); 78 | if (newScale < 1) newScale = 1; 79 | if (newScale > 10) newScale = 10; 80 | // position from left top corner in translated origin 81 | const offsetX = e.pageX - el.offsetLeft - translateX; 82 | const offsetY = e.pageY - el.offsetTop - translateY; 83 | 84 | const s = newScale / scale; // current scale to new scale 85 | const pX = offsetX * -s + offsetX; 86 | const pY = offsetY * -s + offsetY; 87 | translateX += pX; 88 | translateY += pY; 89 | scale = newScale; 90 | requestAnimationFrame( () => { 91 | updateTransform(); 92 | }); 93 | }); 94 | 95 | let touch = null; 96 | el.addEventListener("touchstart", function (e) { 97 | if (e.touches.length === 1 || 98 | e.touches.length === 2) { 99 | e.preventDefault(); 100 | touch = e; 101 | touch._state = { 102 | tX: translateX, 103 | tY: translateY, 104 | }; 105 | } 106 | }); 107 | el.addEventListener("touchmove", function (e) { 108 | if (touch && e.touches.length === 1) { 109 | e.preventDefault(); 110 | const moveX = e.touches[0].clientX - touch.touches[0].clientX; 111 | const moveY = e.touches[0].clientY - touch.touches[0].clientY; 112 | 113 | requestAnimationFrame( () => { 114 | translateX = touch._state.tX + moveX; 115 | translateY = touch._state.tY + moveY; 116 | updateTransform(); 117 | }); 118 | } else 119 | if (touch && e.touches.length === 2) { 120 | e.preventDefault(); 121 | const distance0 = Math.sqrt( 122 | (touch.touches[0].pageX-touch.touches[1].pageX) * (touch.touches[0].pageX-touch.touches[1].pageX) + 123 | (touch.touches[0].pageY-touch.touches[1].pageY) * (touch.touches[0].pageY-touch.touches[1].pageY) 124 | ); 125 | const distance = Math.sqrt( 126 | (e.touches[0].pageX-e.touches[1].pageX) * (e.touches[0].pageX-e.touches[1].pageX) + 127 | (e.touches[0].pageY-e.touches[1].pageY) * (e.touches[0].pageY-e.touches[1].pageY) 128 | ); 129 | let newScale = scale + (distance - distance0) / 200; 130 | if (newScale < 1) newScale = 1; 131 | if (newScale > 10) newScale = 10; 132 | 133 | const centerX = (touch.touches[0].pageX + touch.touches[1].pageX) / 2; 134 | const centerY = (touch.touches[0].pageY + touch.touches[1].pageY) / 2; 135 | const offsetX = centerX - el.offsetLeft - translateX; 136 | const offsetY = centerY - el.offsetTop - translateY; 137 | 138 | const s = newScale / scale; // current scale to new scale 139 | const pX = offsetX * -s + offsetX; 140 | const pY = offsetY * -s + offsetY; 141 | // console.log('offset', offsetX, offsetY, 'p', pX, pY, 'scale', newScale); 142 | translateX += pX; 143 | translateY += pY; 144 | scale = newScale; 145 | requestAnimationFrame( () => { 146 | updateTransform(); 147 | }); 148 | } 149 | }); 150 | el.addEventListener("touchend", function (e) { 151 | touch = null; 152 | }); 153 | }, 154 | inserted: function (el) { 155 | }, 156 | update: function (el) { 157 | }, 158 | componentUpdated: function (el) { 159 | }, 160 | unbind: function (el) { 161 | } 162 | }); 163 | 164 | 165 | function MethodWorker (uri) { 166 | this.worker = new Worker(uri); 167 | this.id = 1; 168 | this.reqs = {}; 169 | this.call = async function (name, args) { 170 | const id = this.id++; 171 | await this.init; 172 | return await new Promise( (resolve, reject) => { 173 | this.reqs[id] = { resolve, reject }; 174 | this.worker.postMessage({ 175 | id: id, 176 | args: Array.from(arguments), 177 | }); 178 | }); 179 | }; 180 | this.init = new Promise( (initialized) => { 181 | this.worker.onerror = (e) => { 182 | throw e; 183 | }; 184 | this.worker.onmessage = (e) => { 185 | const id = e.data.id; 186 | if (id < 0) { 187 | if (id === MethodWorker.ID_INIT) { 188 | console.log('worker is initialized'); 189 | initialized(); 190 | } 191 | return; 192 | } 193 | 194 | if (!this.reqs[id]) { 195 | console.log('unknown id', id); 196 | return; 197 | } 198 | 199 | const result = e.data.result; 200 | const error = e.data.error; 201 | if (typeof error !== 'undefined') { 202 | this.reqs[id].reject(error); 203 | } else { 204 | this.reqs[id].resolve(result); 205 | } 206 | delete this.reqs[id]; 207 | }; 208 | }); 209 | } 210 | MethodWorker.ID_INIT = -1; 211 | MethodWorker.work = function (methods) { 212 | onmessage = function (e) { 213 | const id = e.data.id; 214 | const name = e.data.args[0]; 215 | const args = e.data.args.slice(1); 216 | try { 217 | const res = methods[name].apply(null, args); 218 | postMessage({ 219 | id: id, 220 | result: res, 221 | }); 222 | } catch (e) { 223 | postMessage({ 224 | id: id, 225 | error: String(e), 226 | }); 227 | } 228 | }; 229 | 230 | self.postMessage({ 231 | id: MethodWorker.ID_INIT, 232 | }); 233 | } 234 | self.MethodWorker = MethodWorker; 235 | 236 | 237 | -------------------------------------------------------------------------------- /src/kicad_strokefont.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * This program source code file is part of kicad-utils. 3 | * Copyright (C) 2017 cho45 . 4 | * 5 | * And this program source code file is imported from KiCad, a free EDA CAD application. 6 | * 7 | * Original Author Copyright: 8 | * 9 | * Copyright (C) 2015 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com 10 | * Copyright (C) 1992-2017 KiCad Developers, see KiCAD AUTHORS.txt for contributors. 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public License 14 | * as published by the Free Software Foundation; either version 2 15 | * of the License, or (at your option) any later version. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License 23 | * along with this program; if not, you may find one here: 24 | * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 25 | * or you may search the http://www.gnu.org website for the version 2 license, 26 | * or you may write to the Free Software Foundation, Inc., 27 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 28 | */ 29 | 30 | import { 31 | Point, 32 | Rect, 33 | TextHjustify, 34 | TextVjustify, 35 | Transform, 36 | DECIDEG2RAD, 37 | TextAngle, 38 | } from "./kicad_common"; 39 | import { STROKE_FONT } from "./kicad_strokefont_data"; 40 | import { Plotter, } from "./kicad_plotter"; 41 | 42 | const INTERLINE_PITCH_RATIO = 1.5; 43 | const OVERBAR_POSITION_FACTOR = 1.22; 44 | const BOLD_FACTOR = 1.3; 45 | const STROKE_FONT_SCALE = 1.0 / 21.0; 46 | const ITALIC_TILT = 1.0 / 8; 47 | 48 | // common/drawtxt.cpp 49 | // common/gal/stroke_font.cpp 50 | export class Glyph { 51 | lines: Array< Array >; 52 | startX: number; 53 | endX: number; 54 | boundingBox: Rect; 55 | 56 | constructor() { 57 | this.lines = []; 58 | } 59 | 60 | computeBoundingBox() { 61 | let points: Array = []; 62 | let rect = new Rect(0, 0, this.endX - this.startX, 0); 63 | for (let line of this.lines) { 64 | for (let point of line) { 65 | rect = rect.merge(new Rect(0, 0, this.endX - this.startX, point.y).normalize()); 66 | } 67 | } 68 | this.boundingBox = rect; 69 | } 70 | } 71 | 72 | export class StrokeFont { 73 | glyphs : Array< Glyph > = []; 74 | 75 | private static _instance: StrokeFont; 76 | 77 | public static get instance(): StrokeFont { 78 | if (!this._instance) this._instance = new StrokeFont(); 79 | return this._instance; 80 | } 81 | 82 | private constructor() { 83 | for (let def of STROKE_FONT) { 84 | const glyph = new Glyph(); 85 | let points: Array = []; 86 | 87 | const SERIALIZE_OFFSET = 'R'.charCodeAt(0); 88 | const FONT_OFFSET = -10; 89 | 90 | const glyphStartX = (def.charCodeAt(0) - SERIALIZE_OFFSET) * STROKE_FONT_SCALE; 91 | const glyphEndX = (def.charCodeAt(1) - SERIALIZE_OFFSET) * STROKE_FONT_SCALE; 92 | 93 | for (let i = 2; i < def.length; i += 2) { 94 | if (def[i] === ' ' && def[i+1] === 'R') { 95 | // raise pen 96 | if (points.length) { 97 | glyph.lines.push(points.slice(0)); 98 | points.length = 0; 99 | } 100 | } else { 101 | const x = (def.charCodeAt(i) - SERIALIZE_OFFSET) * STROKE_FONT_SCALE - glyphStartX; 102 | const y = (def.charCodeAt(i + 1) - SERIALIZE_OFFSET + FONT_OFFSET) * STROKE_FONT_SCALE; 103 | 104 | points.push(new Point(x, y)); 105 | } 106 | } 107 | 108 | if (points.length) { 109 | glyph.lines.push(points.slice(0)); 110 | } 111 | 112 | glyph.startX = glyphStartX; 113 | glyph.endX = glyphEndX; 114 | glyph.computeBoundingBox(); 115 | 116 | this.glyphs.push(glyph); 117 | } 118 | } 119 | 120 | getInterline(size: number, lineWidth:number): number { 121 | return (size * INTERLINE_PITCH_RATIO ) + lineWidth; 122 | } 123 | 124 | computeTextLineSize(line: string, size: number, lineWidth: number, italic: boolean = false): number { 125 | return this.computeStringBoundaryLimits(line, size, lineWidth, italic).width; 126 | } 127 | 128 | computeStringBoundaryLimits(line: string, size: number, lineWidth: number, italic: boolean = false) { 129 | let ymax = 0; 130 | let ymin = 0; 131 | 132 | let width = 0; 133 | for (let i = 0, len = line.length; i < len; i++) { 134 | const c = line.charCodeAt(i); 135 | const n = c - ' '.charCodeAt(0); 136 | const glyph = this.glyphs[n] || this.glyphs['?'.charCodeAt(0) - ' '.charCodeAt(0)]; 137 | width += glyph.boundingBox.width; 138 | ymax = Math.max(ymax, glyph.boundingBox.pos1.y, glyph.boundingBox.pos2.y); 139 | ymin = Math.min(ymin, glyph.boundingBox.pos1.y, glyph.boundingBox.pos2.y); 140 | } 141 | 142 | width = width * size + lineWidth; 143 | 144 | let height = size + lineWidth; 145 | 146 | if (italic) { 147 | width += height * ITALIC_TILT; 148 | } 149 | 150 | return { 151 | width, 152 | height, 153 | topLimit: ymax * size, 154 | bottomLimit: ymin * size, 155 | }; 156 | } 157 | 158 | drawGlyph(plotter: Plotter, p: Point, glyph: Glyph, size: number, italic: boolean) { 159 | for (let line of glyph.lines) { 160 | { 161 | let x = line[0].x * size + p.x; 162 | let y = line[0].y * size + p.y; 163 | if (italic) { 164 | x -= y * ITALIC_TILT; 165 | } 166 | plotter.moveTo(x, y); 167 | } 168 | for (let i = 1, len = line.length; i < len; i++) { 169 | const point = line[i]; 170 | let x = point.x * size + p.x; 171 | let y = point.y * size + p.y; 172 | if (italic) { 173 | x -= y * ITALIC_TILT; 174 | } 175 | plotter.lineTo(x, y); 176 | } 177 | plotter.finishPen(); 178 | } 179 | } 180 | 181 | drawLineText(plotter: Plotter, p: Point, line: string, size: number, lineWidth: number, hjustify: TextHjustify, vjustify: TextVjustify, italic: boolean) { 182 | let offset = lineWidth / 2; 183 | 184 | if (hjustify === TextHjustify.LEFT) { 185 | offset += 0; 186 | } else 187 | if (hjustify === TextHjustify.CENTER) { 188 | offset += -this.computeTextLineSize(line, size, lineWidth) / 2; 189 | } else 190 | if (hjustify === TextHjustify.RIGHT) { 191 | offset += -this.computeTextLineSize(line, size, lineWidth); 192 | } 193 | 194 | for (let i = 0, len = line.length; i < len; i++) { 195 | const c = line.charCodeAt(i); 196 | const n = c - ' '.charCodeAt(0); 197 | const glyph = this.glyphs[n]; 198 | this.drawGlyph(plotter, { x: offset + p.x, y: p.y }, glyph, size, italic); 199 | offset += glyph.boundingBox.pos2.x * size; 200 | } 201 | } 202 | 203 | drawText(plotter: Plotter, p: Point, text: string, size: number, lineWidth: number, angle: number, hjustify: TextHjustify, vjustify: TextVjustify, italic: boolean, bold: boolean) { 204 | if (lineWidth === 0 && bold) { 205 | lineWidth = size / 5.0; 206 | } 207 | 208 | lineWidth = this.clampTextPenSize(lineWidth, size, bold); 209 | 210 | plotter.save(); 211 | plotter.setCurrentLineWidth(lineWidth * BOLD_FACTOR); 212 | plotter.translate(p.x, p.y); 213 | if (size < 0) { 214 | size = -size; 215 | plotter.scale(-1, 1); 216 | } 217 | plotter.rotate(-DECIDEG2RAD(angle)); 218 | let offset = 0; 219 | const lines = text.split(/\n/); 220 | if (vjustify === TextVjustify.TOP) { 221 | offset = (size * lines.length); 222 | } else 223 | if (vjustify === TextVjustify.CENTER) { 224 | offset = (size * lines.length) / 2; 225 | } else 226 | if (vjustify === TextVjustify.BOTTOM) { 227 | offset = 0; 228 | } 229 | for (let line of lines) { 230 | this.drawLineText(plotter, { x: 0, y: offset}, line, size, lineWidth, hjustify, vjustify, italic); 231 | offset += size * INTERLINE_PITCH_RATIO + lineWidth; 232 | } 233 | plotter.restore(); 234 | } 235 | 236 | clampTextPenSize(lineWidth: number, size: number, bold: boolean): number { 237 | const scale = bold ? 4.0 : 6.0; 238 | const max = Math.abs(size) / scale; 239 | if (lineWidth > max) { 240 | return max; 241 | } else { 242 | return lineWidth; 243 | } 244 | } 245 | } 246 | 247 | -------------------------------------------------------------------------------- /static/js/pcb.js: -------------------------------------------------------------------------------- 1 | const { 2 | Transform, 3 | CanvasPlotter, 4 | Color, 5 | SVGPlotter, 6 | PCBPlotter, 7 | Pcb, 8 | } = require("kicad-utils"); 9 | 10 | const Vue = require("vue"); 11 | 12 | const app = new Vue({ 13 | el: '#app', 14 | data: { 15 | url: [ 16 | "https://github.com/cho45/Keble/blob/master/KeyModule-L.kicad_pcb", 17 | "https://github.com/cho45/Keble/blob/master/KeyModule-R.kicad_pcb", 18 | "https://github.com/cho45/Keble/blob/master/Main.kicad_pcb", 19 | ].join("\n"), 20 | status: "init", 21 | lib: {}, 22 | components: [], 23 | results: [], 24 | errors: [], 25 | }, 26 | 27 | created: function () { 28 | if (location.search) { 29 | const params = new URLSearchParams(location.search); 30 | if (params.has('url')) { 31 | this.url = params.get('url'); 32 | } 33 | } 34 | }, 35 | 36 | mounted: function () { 37 | console.log(this.$refs); 38 | this.onSubmit(); 39 | }, 40 | 41 | methods: { 42 | fileSelected: function () { 43 | const files = Array.from(this.$refs.fileInput.files).map( (f) => ({ name: f.name, url: window.URL.createObjectURL(f) }) ); 44 | this.loadFiles(files); 45 | }, 46 | 47 | onSubmit: function () { 48 | const urls = this.url.replace(/^\s+|\s+$/g, '').split(/\s+/).map( (u) => ({ name: u, url: u.replace(/github\.com\/(.+)\/blob\/(.+)/, 'raw.githubusercontent.com/$1/$2') })); 49 | console.log(urls); 50 | if (!urls.length) { 51 | this.status = "url is required"; 52 | return; 53 | } 54 | const params = new URLSearchParams(); 55 | params.set('url', this.url); 56 | history.pushState(null, '', '?' + params); 57 | this.loadFiles(urls); 58 | }, 59 | 60 | loadFiles: async function (urls) { 61 | console.log('loadFiles', urls); 62 | urls = urls.filter( (url) => /[.](kicad_pcb)$/i.test(url.name) ); 63 | 64 | const res = await Promise.all(urls.map( (url) => fetch(url.url))); 65 | const text = await Promise.all(res.map( (r) => r.text())); 66 | const files = text.map( (t, i) => ({ url: urls[i], content: t }) ); 67 | 68 | const pcbFiles = []; 69 | for (let file of files) { 70 | if (file.url.name.toLowerCase().endsWith(".kicad_pcb")) { 71 | pcbFiles.push(file); 72 | } 73 | } 74 | 75 | if (!pcbFiles.length) { 76 | this.status = ".kicad_pcb file is needed"; 77 | return; 78 | } 79 | 80 | this.results = []; 81 | const render = (pcb, cb) => { 82 | const plotter = new SVGPlotter(); 83 | plotter.pageInfo = pcb.pageInfo; 84 | plotter.startPlot(); 85 | const pcbPlotter = new PCBPlotter(plotter); 86 | plotter.save(); 87 | plotter.translate(0, 0); 88 | plotter.setColor(Color.WHITE); 89 | plotter.plotPageInfo(pcb.pageInfo); 90 | cb(plotter, pcbPlotter); 91 | plotter.restore(); 92 | plotter.endPlot(); 93 | const svg = plotter.output; 94 | for (let error of plotter.errors) { 95 | this.errors.push(error); 96 | } 97 | 98 | let src; 99 | if (typeof Blob !== 'undefined') { 100 | const blob = new Blob([svg], {type : 'image/svg+xml'}); 101 | src = URL.createObjectURL(blob); 102 | } else { 103 | src = 'data:image/svg+xml,' + encodeURIComponent(svg); 104 | } 105 | return src; 106 | }; 107 | 108 | const L = Pcb.PCB_LAYER_ID; 109 | for (let pcbFile of pcbFiles) { 110 | this.status = 'loading ' + pcbFile; 111 | const pcb = Pcb.PCB.load(pcbFile.content); 112 | 113 | this.results.push({ 114 | url: pcbFile.url, 115 | mirror: false, 116 | layers: [ 117 | { 118 | name: "F_Cu", 119 | src: render(pcb, (plotter, pcbPlotter) => { 120 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 121 | L.F_Cu, 122 | )); 123 | }), 124 | visible: true, 125 | }, 126 | { 127 | name: "B_Cu", 128 | src: render(pcb, (plotter, pcbPlotter) => { 129 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 130 | L.B_Cu, 131 | )); 132 | }), 133 | visible: true, 134 | }, 135 | { 136 | name: "F_Adhes", 137 | src: render(pcb, (plotter, pcbPlotter) => { 138 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 139 | L.F_Adhes, 140 | )); 141 | }), 142 | visible: true, 143 | }, 144 | { 145 | name: "B_Adhes", 146 | src: render(pcb, (plotter, pcbPlotter) => { 147 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 148 | L.B_Adhes, 149 | )); 150 | }), 151 | visible: true, 152 | }, 153 | { 154 | name: "F_Paste", 155 | src: render(pcb, (plotter, pcbPlotter) => { 156 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 157 | L.F_Paste, 158 | )); 159 | }), 160 | visible: true, 161 | }, 162 | { 163 | name: "B_Paste", 164 | src: render(pcb, (plotter, pcbPlotter) => { 165 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 166 | L.B_Paste, 167 | )); 168 | }), 169 | visible: true, 170 | }, 171 | { 172 | name: "F_SilkS", 173 | src: render(pcb, (plotter, pcbPlotter) => { 174 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 175 | L.F_SilkS, 176 | )); 177 | }), 178 | visible: true, 179 | }, 180 | { 181 | name: "B_SilkS", 182 | src: render(pcb, (plotter, pcbPlotter) => { 183 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 184 | L.B_SilkS, 185 | )); 186 | }), 187 | visible: true, 188 | }, 189 | { 190 | name: "F_Mask", 191 | src: render(pcb, (plotter, pcbPlotter) => { 192 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 193 | L.F_Mask, 194 | )); 195 | }), 196 | visible: true, 197 | }, 198 | { 199 | name: "B_Mask", 200 | src: render(pcb, (plotter, pcbPlotter) => { 201 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 202 | L.B_Mask, 203 | )); 204 | }), 205 | visible: true, 206 | }, 207 | { 208 | name: "Dwgs_User", 209 | src: render(pcb, (plotter, pcbPlotter) => { 210 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 211 | L.Dwgs_User, 212 | )); 213 | }), 214 | visible: true, 215 | }, 216 | { 217 | name: "Eco1.User", 218 | src: render(pcb, (plotter, pcbPlotter) => { 219 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 220 | L.Eco1_User 221 | )); 222 | }), 223 | visible: true, 224 | }, 225 | { 226 | name: "Eco2.User", 227 | src: render(pcb, (plotter, pcbPlotter) => { 228 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 229 | L.Eco2_User 230 | )); 231 | }), 232 | visible: true, 233 | }, 234 | { 235 | name: "Edge_Cuts", 236 | src: render(pcb, (plotter, pcbPlotter) => { 237 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 238 | L.Edge_Cuts, 239 | )); 240 | }), 241 | visible: true, 242 | }, 243 | { 244 | name: "F_CrtYd", 245 | src: render(pcb, (plotter, pcbPlotter) => { 246 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 247 | L.F_CrtYd, 248 | )); 249 | }), 250 | visible: true, 251 | }, 252 | { 253 | name: "B_CrtYd", 254 | src: render(pcb, (plotter, pcbPlotter) => { 255 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 256 | L.B_CrtYd, 257 | )); 258 | }), 259 | visible: true, 260 | }, 261 | { 262 | name: "F_Fab", 263 | src: render(pcb, (plotter, pcbPlotter) => { 264 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 265 | L.F_Fab, 266 | )); 267 | }), 268 | visible: true, 269 | }, 270 | { 271 | name: "B_Fab", 272 | src: render(pcb, (plotter, pcbPlotter) => { 273 | pcbPlotter.plotBoardLayers(pcb, new Pcb.LSET( 274 | L.B_Fab, 275 | )); 276 | }), 277 | visible: true, 278 | }, 279 | ] 280 | }); 281 | } 282 | this.status = 'done'; 283 | }, 284 | 285 | basename: function (url) { 286 | const matched = url.replace(/[#?].+$/, '').match(/[^/]+$/); 287 | return decodeURIComponent(matched[0] || ''); 288 | } 289 | } 290 | }) 291 | -------------------------------------------------------------------------------- /dist/src/kicad_strokefont.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | * This program source code file is part of kicad-utils. 4 | * Copyright (C) 2017 cho45 . 5 | * 6 | * And this program source code file is imported from KiCad, a free EDA CAD application. 7 | * 8 | * Original Author Copyright: 9 | * 10 | * Copyright (C) 2015 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com 11 | * Copyright (C) 1992-2017 KiCad Developers, see KiCAD AUTHORS.txt for contributors. 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU General Public License 15 | * as published by the Free Software Foundation; either version 2 16 | * of the License, or (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program; if not, you may find one here: 25 | * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 26 | * or you may search the http://www.gnu.org website for the version 2 license, 27 | * or you may write to the Free Software Foundation, Inc., 28 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 29 | */ 30 | Object.defineProperty(exports, "__esModule", { value: true }); 31 | const kicad_common_1 = require("./kicad_common"); 32 | const kicad_strokefont_data_1 = require("./kicad_strokefont_data"); 33 | const INTERLINE_PITCH_RATIO = 1.5; 34 | const OVERBAR_POSITION_FACTOR = 1.22; 35 | const BOLD_FACTOR = 1.3; 36 | const STROKE_FONT_SCALE = 1.0 / 21.0; 37 | const ITALIC_TILT = 1.0 / 8; 38 | // common/drawtxt.cpp 39 | // common/gal/stroke_font.cpp 40 | class Glyph { 41 | constructor() { 42 | this.lines = []; 43 | } 44 | computeBoundingBox() { 45 | let points = []; 46 | let rect = new kicad_common_1.Rect(0, 0, this.endX - this.startX, 0); 47 | for (let line of this.lines) { 48 | for (let point of line) { 49 | rect = rect.merge(new kicad_common_1.Rect(0, 0, this.endX - this.startX, point.y).normalize()); 50 | } 51 | } 52 | this.boundingBox = rect; 53 | } 54 | } 55 | exports.Glyph = Glyph; 56 | class StrokeFont { 57 | constructor() { 58 | this.glyphs = []; 59 | for (let def of kicad_strokefont_data_1.STROKE_FONT) { 60 | const glyph = new Glyph(); 61 | let points = []; 62 | const SERIALIZE_OFFSET = 'R'.charCodeAt(0); 63 | const FONT_OFFSET = -10; 64 | const glyphStartX = (def.charCodeAt(0) - SERIALIZE_OFFSET) * STROKE_FONT_SCALE; 65 | const glyphEndX = (def.charCodeAt(1) - SERIALIZE_OFFSET) * STROKE_FONT_SCALE; 66 | for (let i = 2; i < def.length; i += 2) { 67 | if (def[i] === ' ' && def[i + 1] === 'R') { 68 | // raise pen 69 | if (points.length) { 70 | glyph.lines.push(points.slice(0)); 71 | points.length = 0; 72 | } 73 | } 74 | else { 75 | const x = (def.charCodeAt(i) - SERIALIZE_OFFSET) * STROKE_FONT_SCALE - glyphStartX; 76 | const y = (def.charCodeAt(i + 1) - SERIALIZE_OFFSET + FONT_OFFSET) * STROKE_FONT_SCALE; 77 | points.push(new kicad_common_1.Point(x, y)); 78 | } 79 | } 80 | if (points.length) { 81 | glyph.lines.push(points.slice(0)); 82 | } 83 | glyph.startX = glyphStartX; 84 | glyph.endX = glyphEndX; 85 | glyph.computeBoundingBox(); 86 | this.glyphs.push(glyph); 87 | } 88 | } 89 | static get instance() { 90 | if (!this._instance) 91 | this._instance = new StrokeFont(); 92 | return this._instance; 93 | } 94 | getInterline(size, lineWidth) { 95 | return (size * INTERLINE_PITCH_RATIO) + lineWidth; 96 | } 97 | computeTextLineSize(line, size, lineWidth, italic = false) { 98 | return this.computeStringBoundaryLimits(line, size, lineWidth, italic).width; 99 | } 100 | computeStringBoundaryLimits(line, size, lineWidth, italic = false) { 101 | let ymax = 0; 102 | let ymin = 0; 103 | let width = 0; 104 | for (let i = 0, len = line.length; i < len; i++) { 105 | const c = line.charCodeAt(i); 106 | const n = c - ' '.charCodeAt(0); 107 | const glyph = this.glyphs[n] || this.glyphs['?'.charCodeAt(0) - ' '.charCodeAt(0)]; 108 | width += glyph.boundingBox.width; 109 | ymax = Math.max(ymax, glyph.boundingBox.pos1.y, glyph.boundingBox.pos2.y); 110 | ymin = Math.min(ymin, glyph.boundingBox.pos1.y, glyph.boundingBox.pos2.y); 111 | } 112 | width = width * size + lineWidth; 113 | let height = size + lineWidth; 114 | if (italic) { 115 | width += height * ITALIC_TILT; 116 | } 117 | return { 118 | width, 119 | height, 120 | topLimit: ymax * size, 121 | bottomLimit: ymin * size, 122 | }; 123 | } 124 | drawGlyph(plotter, p, glyph, size, italic) { 125 | for (let line of glyph.lines) { 126 | { 127 | let x = line[0].x * size + p.x; 128 | let y = line[0].y * size + p.y; 129 | if (italic) { 130 | x -= y * ITALIC_TILT; 131 | } 132 | plotter.moveTo(x, y); 133 | } 134 | for (let i = 1, len = line.length; i < len; i++) { 135 | const point = line[i]; 136 | let x = point.x * size + p.x; 137 | let y = point.y * size + p.y; 138 | if (italic) { 139 | x -= y * ITALIC_TILT; 140 | } 141 | plotter.lineTo(x, y); 142 | } 143 | plotter.finishPen(); 144 | } 145 | } 146 | drawLineText(plotter, p, line, size, lineWidth, hjustify, vjustify, italic) { 147 | let offset = lineWidth / 2; 148 | if (hjustify === kicad_common_1.TextHjustify.LEFT) { 149 | offset += 0; 150 | } 151 | else if (hjustify === kicad_common_1.TextHjustify.CENTER) { 152 | offset += -this.computeTextLineSize(line, size, lineWidth) / 2; 153 | } 154 | else if (hjustify === kicad_common_1.TextHjustify.RIGHT) { 155 | offset += -this.computeTextLineSize(line, size, lineWidth); 156 | } 157 | for (let i = 0, len = line.length; i < len; i++) { 158 | const c = line.charCodeAt(i); 159 | const n = c - ' '.charCodeAt(0); 160 | const glyph = this.glyphs[n]; 161 | this.drawGlyph(plotter, { x: offset + p.x, y: p.y }, glyph, size, italic); 162 | offset += glyph.boundingBox.pos2.x * size; 163 | } 164 | } 165 | drawText(plotter, p, text, size, lineWidth, angle, hjustify, vjustify, italic, bold) { 166 | if (lineWidth === 0 && bold) { 167 | lineWidth = size / 5.0; 168 | } 169 | lineWidth = this.clampTextPenSize(lineWidth, size, bold); 170 | plotter.save(); 171 | plotter.setCurrentLineWidth(lineWidth * BOLD_FACTOR); 172 | plotter.translate(p.x, p.y); 173 | if (size < 0) { 174 | size = -size; 175 | plotter.scale(-1, 1); 176 | } 177 | plotter.rotate(-kicad_common_1.DECIDEG2RAD(angle)); 178 | let offset = 0; 179 | const lines = text.split(/\n/); 180 | if (vjustify === kicad_common_1.TextVjustify.TOP) { 181 | offset = (size * lines.length); 182 | } 183 | else if (vjustify === kicad_common_1.TextVjustify.CENTER) { 184 | offset = (size * lines.length) / 2; 185 | } 186 | else if (vjustify === kicad_common_1.TextVjustify.BOTTOM) { 187 | offset = 0; 188 | } 189 | for (let line of lines) { 190 | this.drawLineText(plotter, { x: 0, y: offset }, line, size, lineWidth, hjustify, vjustify, italic); 191 | offset += size * INTERLINE_PITCH_RATIO + lineWidth; 192 | } 193 | plotter.restore(); 194 | } 195 | clampTextPenSize(lineWidth, size, bold) { 196 | const scale = bold ? 4.0 : 6.0; 197 | const max = Math.abs(size) / scale; 198 | if (lineWidth > max) { 199 | return max; 200 | } 201 | else { 202 | return lineWidth; 203 | } 204 | } 205 | } 206 | exports.StrokeFont = StrokeFont; 207 | //# sourceMappingURL=kicad_strokefont.js.map -------------------------------------------------------------------------------- /dist/src/kicad_pcb_token.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"kicad_pcb_token.js","sourceRoot":"","sources":["../../src/kicad_pcb_token.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/src/kicad_pcb_token.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // based on: 3 | // include/dsnlexer.h 4 | // common/dsnlexer.cpp 5 | /* 6 | * This program source code file is part of kicad-utils 7 | * Copyright (C) 2017 cho45 . 8 | * 9 | * And this program source code file is imported from KiCad, a free EDA CAD application. 10 | * 11 | * Original Author Copyright: 12 | * 13 | * Copyright (C) 2007-2013 SoftPLC Corporation, Dick Hollenbeck 14 | * Copyright (C) 1992-2017 KiCad Developers, see KiCAD AUTHORS.txt for contributors. 15 | * 16 | * This program is free software; you can redistribute it and/or 17 | * modify it under the terms of the GNU General Public License 18 | * as published by the Free Software Foundation; either version 2 19 | * of the License, or (at your option) any later version. 20 | * 21 | * This program is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with this program; if not, you may find one here: 28 | * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 29 | * or you may search the http://www.gnu.org website for the version 2 license, 30 | * or you may write to the Free Software Foundation, Inc., 31 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 32 | */ 33 | Object.defineProperty(exports, "__esModule", { value: true }); 34 | class Token { 35 | constructor(token, line = 0) { 36 | this.token = token; 37 | this.line = line; 38 | } 39 | is(t) { 40 | return this.token === t.token; 41 | } 42 | isNUMBER() { 43 | return /^[-+]?([0-9]*\.?[0-9]+|[0-9]+)?([eE][-+]?[0-9]+)?$/.test(this.token); 44 | } 45 | isSYMBOL() { 46 | // XXX : symbol is not a keyword 47 | return /^.+$/i.test(this.token); 48 | } 49 | toString() { 50 | return this.token; 51 | } 52 | } 53 | Token.LEFT = new Token("("); 54 | Token.RIGHT = new Token(")"); 55 | // common/pcb.keywords 56 | Token.add_net = new Token("add_net"); 57 | Token.allowed = new Token("allowed"); 58 | Token.angle = new Token("angle"); 59 | Token.arc = new Token("arc"); 60 | Token.arc_segments = new Token("arc_segments"); 61 | Token.area = new Token("area"); 62 | Token.arrow1a = new Token("arrow1a"); 63 | Token.arrow1b = new Token("arrow1b"); 64 | Token.arrow2a = new Token("arrow2a"); 65 | Token.arrow2b = new Token("arrow2b"); 66 | Token.at = new Token("at"); 67 | Token.attr = new Token("attr"); 68 | Token.autoplace_cost90 = new Token("autoplace_cost90"); 69 | Token.autoplace_cost180 = new Token("autoplace_cost180"); 70 | Token.aux_axis_origin = new Token("aux_axis_origin"); 71 | Token.blind = new Token("blind"); 72 | Token.blind_buried_vias_allowed = new Token("blind_buried_vias_allowed"); 73 | Token.bold = new Token("bold"); 74 | Token.bottom = new Token("bottom"); 75 | Token.center = new Token("center"); 76 | Token.chamfer = new Token("chamfer"); 77 | Token.circle = new Token("circle"); 78 | Token.clearance = new Token("clearance"); 79 | Token.comment = new Token("comment"); 80 | Token.company = new Token("company"); 81 | Token.connect = new Token("connect"); 82 | Token.connect_pads = new Token("connect_pads"); 83 | Token.copperpour = new Token("copperpour"); 84 | Token.crossbar = new Token("crossbar"); 85 | Token.date = new Token("date"); 86 | Token.descr = new Token("descr"); 87 | Token.die_length = new Token("die_length"); 88 | Token.dimension = new Token("dimension"); 89 | Token.diff_pair_width = new Token("diff_pair_width"); 90 | Token.diff_pair_gap = new Token("diff_pair_gap"); 91 | Token.drawings = new Token("drawings"); 92 | Token.drill = new Token("drill"); 93 | Token.edge = new Token("edge"); 94 | Token.edge_width = new Token("edge_width"); 95 | Token.effects = new Token("effects"); 96 | Token.end = new Token("end"); 97 | Token.feature1 = new Token("feature1"); 98 | Token.feature2 = new Token("feature2"); 99 | Token.fill = new Token("fill"); 100 | Token.fill_segments = new Token("fill_segments"); 101 | Token.filled_polygon = new Token("filled_polygon"); 102 | Token.fillet = new Token("fillet"); 103 | Token.font = new Token("font"); 104 | Token.fp_arc = new Token("fp_arc"); 105 | Token.fp_circle = new Token("fp_circle"); 106 | Token.fp_curve = new Token("fp_curve"); 107 | Token.fp_line = new Token("fp_line"); 108 | Token.fp_poly = new Token("fp_poly"); 109 | Token.fp_text = new Token("fp_text"); 110 | Token.full = new Token("full"); 111 | Token.general = new Token("general"); 112 | Token.grid_origin = new Token("grid_origin"); 113 | Token.gr_arc = new Token("gr_arc"); 114 | Token.gr_circle = new Token("gr_circle"); 115 | Token.gr_curve = new Token("gr_curve"); 116 | Token.gr_line = new Token("gr_line"); 117 | Token.gr_poly = new Token("gr_poly"); 118 | Token.gr_text = new Token("gr_text"); 119 | Token.hatch = new Token("hatch"); 120 | Token.hide = new Token("hide"); 121 | Token.italic = new Token("italic"); 122 | Token.justify = new Token("justify"); 123 | Token.keepout = new Token("keepout"); 124 | Token.kicad_pcb = new Token("kicad_pcb"); 125 | Token.last_trace_width = new Token("last_trace_width"); 126 | Token.layer = new Token("layer"); 127 | Token.layers = new Token("layers"); 128 | Token.left = new Token("left"); 129 | Token.links = new Token("links"); 130 | Token.locked = new Token("locked"); 131 | Token.micro = new Token("micro"); 132 | Token.min_thickness = new Token("min_thickness"); 133 | Token.mirror = new Token("mirror"); 134 | Token.mod_edge_width = new Token("mod_edge_width"); 135 | Token.mod_text_size = new Token("mod_text_size"); 136 | Token.mod_text_width = new Token("mod_text_width"); 137 | Token.mode = new Token("mode"); 138 | Token.model = new Token("model"); 139 | Token.module = new Token("module"); 140 | Token.net = new Token("net"); 141 | Token.net_class = new Token("net_class"); 142 | Token.net_name = new Token("net_name"); 143 | Token.nets = new Token("nets"); 144 | Token.no = new Token("no"); 145 | Token.no_connects = new Token("no_connects"); 146 | Token.none = new Token("none"); 147 | Token.not_allowed = new Token("not_allowed"); 148 | Token.np_thru_hole = new Token("np_thru_hole"); 149 | Token.offset = new Token("offset"); 150 | Token.oval = new Token("oval"); 151 | Token.pad = new Token("pad"); 152 | Token.pads = new Token("pads"); 153 | Token.pad_drill = new Token("pad_drill"); 154 | Token.pad_size = new Token("pad_size"); 155 | Token.pad_to_mask_clearance = new Token("pad_to_mask_clearance"); 156 | Token.solder_mask_min_width = new Token("solder_mask_min_width"); 157 | Token.pad_to_paste_clearance = new Token("pad_to_paste_clearance"); 158 | Token.pad_to_paste_clearance_ratio = new Token("pad_to_paste_clearance_ratio"); 159 | Token.page = new Token("page"); 160 | Token.path = new Token("path"); 161 | Token.pcb_text_size = new Token("pcb_text_size"); 162 | Token.pcb_text_width = new Token("pcb_text_width"); 163 | Token.pcbplotparams = new Token("pcbplotparams"); 164 | Token.placed = new Token("placed"); 165 | Token.plus = new Token("plus"); 166 | Token.polygon = new Token("polygon"); 167 | Token.portrait = new Token("portrait"); 168 | Token.priority = new Token("priority"); 169 | Token.pts = new Token("pts"); 170 | Token.radius = new Token("radius"); 171 | Token.rev = new Token("rev"); 172 | Token.rect = new Token("rect"); 173 | Token.rect_delta = new Token("rect_delta"); 174 | Token.reference = new Token("reference"); 175 | Token.right = new Token("right"); 176 | Token.rotate = new Token("rotate"); 177 | Token.roundrect = new Token("roundrect"); 178 | Token.roundrect_rratio = new Token("roundrect_rratio"); 179 | Token.scale = new Token("scale"); 180 | Token.segment = new Token("segment"); 181 | Token.segment_width = new Token("segment_width"); 182 | Token.setup = new Token("setup"); 183 | Token.size = new Token("size"); 184 | Token.smd = new Token("smd"); 185 | Token.smoothing = new Token("smoothing"); 186 | Token.solder_mask_margin = new Token("solder_mask_margin"); 187 | Token.solder_paste_margin = new Token("solder_paste_margin"); 188 | Token.solder_paste_margin_ratio = new Token("solder_paste_margin_ratio"); 189 | Token.solder_paste_ratio = new Token("solder_paste_ratio"); 190 | Token.start = new Token("start"); 191 | Token.status = new Token("status"); 192 | Token.tags = new Token("tags"); 193 | Token.target = new Token("target"); 194 | Token.title = new Token("title"); 195 | Token.title_block = new Token("title_block"); 196 | Token.tedit = new Token("tedit"); 197 | Token.thermal_width = new Token("thermal_width"); 198 | Token.thermal_gap = new Token("thermal_gap"); 199 | Token.thermal_bridge_width = new Token("thermal_bridge_width"); 200 | Token.thickness = new Token("thickness"); 201 | Token.top = new Token("top"); 202 | Token.trace_width = new Token("trace_width"); 203 | Token.tracks = new Token("tracks"); 204 | Token.trace_min = new Token("trace_min"); 205 | Token.trace_clearance = new Token("trace_clearance"); 206 | Token.trapezoid = new Token("trapezoid"); 207 | Token.thru = new Token("thru"); 208 | Token.thru_hole = new Token("thru_hole"); 209 | Token.thru_hole_only = new Token("thru_hole_only"); 210 | Token.tstamp = new Token("tstamp"); 211 | Token.user = new Token("user"); 212 | Token.user_trace_width = new Token("user_trace_width"); 213 | Token.user_via = new Token("user_via"); 214 | Token.uvia_dia = new Token("uvia_dia"); 215 | Token.uvia_drill = new Token("uvia_drill"); 216 | Token.uvia_min_drill = new Token("uvia_min_drill"); 217 | Token.uvia_min_size = new Token("uvia_min_size"); 218 | Token.uvia_size = new Token("uvia_size"); 219 | Token.uvias_allowed = new Token("uvias_allowed"); 220 | Token.value = new Token("value"); 221 | Token.version = new Token("version"); 222 | Token.via = new Token("via"); 223 | Token.vias = new Token("vias"); 224 | Token.via_dia = new Token("via_dia"); 225 | Token.via_drill = new Token("via_drill"); 226 | Token.via_min_drill = new Token("via_min_drill"); 227 | Token.via_min_size = new Token("via_min_size"); 228 | Token.via_size = new Token("via_size"); 229 | Token.virtual = new Token("virtual"); 230 | Token.visible_elements = new Token("visible_elements"); 231 | Token.width = new Token("width"); 232 | Token.x = new Token("x"); 233 | Token.xy = new Token("xy"); 234 | Token.xyz = new Token("xyz"); 235 | Token.yes = new Token("yes"); 236 | Token.zone = new Token("zone"); 237 | Token.zone_45_only = new Token("zone_45_only"); 238 | Token.zone_clearance = new Token("zone_clearance"); 239 | Token.zone_connect = new Token("zone_connect"); 240 | Token.zone_type = new Token("zone_type"); 241 | Token.zones = new Token("zones"); 242 | exports.Token = Token; 243 | //# sourceMappingURL=kicad_pcb_token.js.map -------------------------------------------------------------------------------- /test/kicad_sch.ts: -------------------------------------------------------------------------------- 1 | //#!npm run test-one 2 | 3 | import * as assert from "assert"; 4 | import * as mocha from 'mocha'; 5 | 6 | import { 7 | TextHjustify, 8 | TextVjustify, 9 | TextAngle, 10 | Fill, 11 | PinOrientation, 12 | PinType, 13 | SheetSide, 14 | Net, 15 | } from "../src/kicad_common"; 16 | 17 | import { 18 | Schematic, 19 | SchComponent, 20 | Sheet, 21 | Text, 22 | Bitmap, 23 | Wire, 24 | Connection, 25 | NoConn, 26 | Entry, 27 | TextOrientationType, 28 | } from "../src/kicad_sch"; 29 | 30 | function indent (literals: TemplateStringsArray, ...placeholders: Array):string { 31 | let result = ""; 32 | 33 | for (let i = 0; i < placeholders.length; i++) { 34 | result += literals[i]; 35 | result += String(placeholders[i]); 36 | } 37 | 38 | result += literals[literals.length - 1]; 39 | 40 | result = result.replace(/^\n|\s+$/g, ''); 41 | const indent = result.match(/^\s+/); 42 | if (indent) { 43 | result = result.replace(new RegExp("^" + indent[0], "gm"), ""); 44 | } 45 | 46 | return result; 47 | } 48 | 49 | /* 50 | describe("", () => { 51 | it("", () => { 52 | }); 53 | }); 54 | */ 55 | 56 | describe("Schematic.load", () => { 57 | it("has version check", () => { 58 | assert.doesNotThrow( () => { 59 | Schematic.load(indent ` 60 | EESchema Schematic File Version 2 61 | `); 62 | }); 63 | assert.doesNotThrow( () => { 64 | Schematic.load(indent ` 65 | EESchema Schematic File Version 1 66 | `); 67 | }); 68 | assert.throws( () => { 69 | Schematic.load(indent ` 70 | EESchema Schematic File Version 3 71 | `); 72 | }, 'schematic format version is greater than supported version: 3 > 2'); 73 | }); 74 | 75 | it("can parse basic format", () => { 76 | const sch = Schematic.load(indent ` 77 | EESchema Schematic File Version 2 78 | LIBS:power 79 | LIBS:device 80 | EELAYER 25 0 81 | EELAYER END 82 | $Descr A4 11693 8268 83 | encoding utf-8 84 | Sheet 1 4 85 | Title "keyboard-proto" 86 | Date "" 87 | Rev "" 88 | Comp "" 89 | Comment1 "" 90 | Comment2 "" 91 | Comment3 "" 92 | Comment4 "" 93 | $EndDescr 94 | $Comp 95 | L VDD #PWR011 96 | U 1 1 5782C5AC 97 | P 1000 1850 98 | AR Path="/5782E0AD/5782C5AC" Ref="#PWR011" Part="1" 99 | AR Path="/5783096D/5782C5AC" Ref="#PWR05" Part="1" 100 | AR Path="/578B2796/5782C5AC" Ref="#PWR017" Part="1" 101 | F 0 "#PWR05" H 1000 1700 50 0001 C CNN 102 | F 1 "VDD" H 1000 2000 50 0000 C CIB 103 | F 2 "" H 1000 1850 50 0000 C CNN 104 | F 3 "" H 1000 1850 50 0000 C CNN 105 | 1 1000 1850 106 | 1 0 0 -1 107 | $EndComp 108 | $Sheet 109 | S 4050 3650 2250 1100 110 | U 5783096D 111 | F0 "KeyModule-L" 60 112 | F1 "_keymodule_l.sch" 60 113 | F2 "sheetppp" I L 8250 5400 60 114 | F3 "sheetpr" I R 10050 5450 60 115 | $EndSheet 116 | Wire Wire Line 117 | 2901 2650 3000 2750 118 | Wire Bus Bus 119 | 3501 3502 3603 3604 120 | Connection ~ 1150 2050 121 | NoConn ~ 2750 2200 122 | Text Notes 2300 3200 0 60 ~ 0 123 | fooabar foobar 124 | Entry Wire Line 125 | 2901 2650 3000 2750 126 | Entry Bus Bus 127 | 3501 3502 3603 3604 128 | $Bitmap 129 | Pos 3500 4800 130 | Scale 1.000000 131 | Data 132 | 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 00 00 00 10 00 00 00 10 08 03 00 00 00 28 2D 0F 133 | 53 00 00 00 03 73 42 49 54 08 08 08 DB E1 4F E0 00 00 01 6B 50 4C 54 45 FF FF FF F1 D4 E2 E4 AC 134 | C8 DE 9A BC E0 A0 C0 EA BD D4 F9 EA F1 DA DA DA 82 82 82 FC F5 F9 DF 9D BE C0 40 80 B2 17 64 AE 135 | 0B 5C AE 09 5B B0 0F 5F B7 26 6E CD 66 9A F0 CF DF FA FA FA FB FB FB BD 38 7B AC 04 58 AE 08 5A 136 | B1 11 60 B1 10 60 AF 0D 5D AC 03 57 D6 80 AB FF FE FE F9 FA F9 87 87 87 7A 7A 7A AD 0A 5C AE 0A 137 | 5C AE 08 5B AF 0C 5D B1 12 61 B0 0E 5F AB 00 55 CB 60 95 FF FD FE EC ED EC 27 27 27 B0 12 61 AF 138 | 0B 5D B2 15 63 BC 34 78 C3 47 85 C1 41 81 B7 25 6E AD 05 59 B0 10 60 D3 77 A5 D8 D8 D8 AB 03 57 139 | B8 28 70 DB 90 B5 F7 DD EA FF F6 FC EB BD D4 CA 5D 93 AD 08 5B EC C1 D6 CC 65 99 FB EB F3 F4 F9 140 | F6 BF C0 C0 A5 A6 A5 AD AE AD D7 DA D8 E6 B1 CC B5 1D 69 AD 06 59 C5 4E 8A 8A 8A 8A 1F 1F 1F 00 141 | 00 00 05 05 05 4A 4A 4A CD CE CD EF CC DE B3 19 66 F2 D4 E3 F9 FA FA 57 57 57 0C 0C 0C B5 B5 B5 142 | E2 A5 C4 AD 06 5A AD 07 5A DD 98 BB 67 67 67 0F 0F 0F DE DF DE C2 44 83 AA 01 54 D1 71 A1 65 65 143 | 65 DF 9B BD A9 00 51 CD 66 99 19 19 19 F6 F9 F8 F5 D6 E6 AC 05 59 D1 73 A2 04 04 04 DD E1 DF FF 144 | F2 F9 B2 14 63 DE 99 BB DE E1 DF FF EF F8 F3 D7 E4 1B 1B 1B F0 C7 DC C8 59 91 03 03 03 64 64 64 145 | E9 BB D2 B5 14 BD DA 00 00 00 CE 49 44 41 54 18 95 63 60 60 60 60 64 62 66 61 65 63 00 01 76 0E 146 | 06 4E 2E 6E 1E 5E 3E 3E 7E 01 41 21 06 06 61 11 06 06 51 31 71 7E 09 09 09 49 29 69 7E 19 59 39 147 | 79 05 06 45 09 09 7E 25 71 65 15 49 55 35 75 0D 4D 2D 6D 06 1D 5D 31 3D 7D 03 43 23 25 63 13 09 148 | 75 53 06 33 06 73 0B 4B 2B A0 69 D6 36 B6 4A BA 26 76 F6 0C 0C 0E 8E 0C 4E CE 2E AE 6E 0C 0C EE 149 | 1E 4A 9E 5E 20 AB BC 7D 7C 7D 7D FD FC 03 18 02 83 78 F5 82 19 42 42 7D 21 20 2C 9C 21 22 32 2A 150 | 9A 21 C6 17 06 62 E3 18 E2 13 12 19 7C 11 20 89 21 39 25 15 59 20 2D 3D 23 33 0B 59 20 3B 27 37 151 | 2F 1F 45 A0 A0 D0 A8 08 59 A0 38 BD A4 94 81 A1 0C 21 50 CE C0 5C C1 00 00 62 1F 38 7D 11 C4 5E 152 | 6C 00 00 00 00 49 45 4E 44 AE 42 60 82 FF 153 | EndData 154 | $EndBitmap 155 | Kmarq B 1600 1100 "Warning Pin power_in not driven (Net 5)" F=1 156 | $EndSCHEMATC 157 | `); 158 | assert(sch); 159 | 160 | assert.deepEqual(sch.libs, ['power', 'device']); 161 | assert(sch.descr.pageInfo.pageType === 'A4'); 162 | assert(sch.descr.width === 11693); 163 | assert(sch.descr.height === 8268); 164 | 165 | assert(sch.items[0] instanceof SchComponent); 166 | { 167 | const item = sch.items[0] as SchComponent; 168 | assert( item.fields[0].text === '#PWR05' ); 169 | assert( item.fields[0].visibility === false); 170 | assert( item.fields[0].hjustify === TextHjustify.CENTER); 171 | assert( item.fields[0].vjustify === TextVjustify.CENTER); 172 | assert( item.fields[0].italic == false); 173 | assert( item.fields[0].bold === false); 174 | 175 | assert( item.fields[1].text === 'VDD' ); 176 | assert( item.fields[1].visibility === true); 177 | assert( item.fields[1].hjustify === TextHjustify.CENTER); 178 | assert( item.fields[1].vjustify === TextVjustify.CENTER); 179 | assert( item.fields[1].italic == true); 180 | assert( item.fields[1].bold === true); 181 | } 182 | assert(sch.items[1] instanceof Sheet); 183 | { 184 | const item = sch.items[1] as Sheet; 185 | assert( item.sheetPins[0].text === "sheetppp" ); 186 | assert( item.sheetPins[0].shape === Net.INPUT); 187 | assert( item.sheetPins[0].sheetSide === SheetSide.LEFT ); 188 | assert( item.sheetPins[0].pos.x == 8250); 189 | assert( item.sheetPins[0].pos.y === 5400); 190 | assert( item.sheetPins[0].size === 60); 191 | assert( item.sheetPins[0].orientationType === 2); 192 | assert( item.sheetPins[0].orientation === TextAngle.HORIZ); 193 | assert( item.sheetPins[0].hjustify === TextHjustify.LEFT); 194 | assert( item.sheetPins[0].vjustify === TextVjustify.CENTER); 195 | 196 | assert( item.sheetPins[1].text === "sheetpr" ); 197 | assert( item.sheetPins[1].shape === Net.INPUT); 198 | assert( item.sheetPins[1].sheetSide === SheetSide.RIGHT ); 199 | assert( item.sheetPins[1].pos.x === 10050); 200 | assert( item.sheetPins[1].pos.y === 5450); 201 | assert( item.sheetPins[1].size === 60); 202 | assert( item.sheetPins[1].orientationType === 0); 203 | assert( item.sheetPins[1].orientation === TextAngle.HORIZ); 204 | assert( item.sheetPins[1].hjustify === TextHjustify.RIGHT); 205 | assert( item.sheetPins[1].vjustify === TextVjustify.CENTER); 206 | } 207 | 208 | assert(sch.items[2] instanceof Wire); 209 | { 210 | const item = sch.items[2] as Wire; 211 | assert( item.name1 === "Wire" ); 212 | assert( item.name2 === "Line" ); 213 | assert( item.start.x === 2901 ); 214 | assert( item.start.y === 2650 ); 215 | assert( item.end.x === 3000 ); 216 | assert( item.end.y === 2750 ); 217 | } 218 | 219 | assert(sch.items[3] instanceof Wire); 220 | { 221 | const item = sch.items[3] as Wire; 222 | assert( item.name1 === "Bus" ); 223 | assert( item.name2 === "Bus" ); 224 | assert( item.start.x === 3501 ); 225 | assert( item.start.y === 3502 ); 226 | assert( item.end.x === 3603 ); 227 | assert( item.end.y === 3604 ); 228 | } 229 | 230 | assert(sch.items[4] instanceof Connection); 231 | { 232 | const item = sch.items[4] as Connection; 233 | assert( item.name1 === "~"); 234 | assert( item.pos.x === 1150); 235 | assert( item.pos.y === 2050); 236 | } 237 | 238 | assert(sch.items[5] instanceof NoConn); 239 | { 240 | const item = sch.items[5] as Connection; 241 | assert( item.name1 === "~"); 242 | assert( item.pos.x === 2750); 243 | assert( item.pos.y === 2200); 244 | } 245 | 246 | assert(sch.items[6] instanceof Text); 247 | { 248 | const item = sch.items[6] as Text; 249 | console.log(item); 250 | assert( item.name1 === "Notes" ); 251 | assert( item.pos.x === 2300 ); 252 | assert( item.pos.y === 3200 ); 253 | assert( item.orientationType === TextOrientationType.HORIZ_LEFT ); 254 | assert( item.orientation === TextAngle.HORIZ ); 255 | assert( item.hjustify === TextHjustify.LEFT ); 256 | assert( item.vjustify === TextVjustify.BOTTOM ); 257 | assert( item.size === 60 ); 258 | assert( !item.bold ); 259 | assert( !item.italic ); 260 | assert( item.text === "fooabar foobar" ); 261 | assert( item.shape === Net.INPUT ); 262 | } 263 | 264 | assert(sch.items[7] instanceof Entry); 265 | { 266 | const item = sch.items[7] as Entry; 267 | assert( item.name1 === "Wire" ); 268 | assert( item.name2 === "Line" ); 269 | assert( item.pos.x === 2901 ); 270 | assert( item.pos.y === 2650 ); 271 | assert( item.size.width === 99 ); 272 | assert( item.size.height === 100 ); 273 | } 274 | assert(sch.items[8] instanceof Entry); 275 | { 276 | const item = sch.items[8] as Entry; 277 | assert( item.name1 === "Bus" ); 278 | assert( item.name2 === "Bus" ); 279 | assert( item.pos.x === 3501 ); 280 | assert( item.pos.y === 3502 ); 281 | assert( item.size.width === 102 ); 282 | assert( item.size.height === 102 ); 283 | } 284 | 285 | assert(sch.items[9] instanceof Bitmap); 286 | { 287 | const item = sch.items[9] as Bitmap; 288 | assert(item.data.slice(-1)[0] === 0xff); 289 | assert(item.isValidPNG); 290 | assert.doesNotThrow( () => { 291 | item.parseIHDR(); 292 | assert(item.size.width === 16); 293 | assert(item.size.height === 16); 294 | }); 295 | } 296 | }); 297 | }); 298 | -------------------------------------------------------------------------------- /src/kicad_pcb_token.ts: -------------------------------------------------------------------------------- 1 | // based on: 2 | // include/dsnlexer.h 3 | // common/dsnlexer.cpp 4 | /* 5 | * This program source code file is part of kicad-utils 6 | * Copyright (C) 2017 cho45 . 7 | * 8 | * And this program source code file is imported from KiCad, a free EDA CAD application. 9 | * 10 | * Original Author Copyright: 11 | * 12 | * Copyright (C) 2007-2013 SoftPLC Corporation, Dick Hollenbeck 13 | * Copyright (C) 1992-2017 KiCad Developers, see KiCAD AUTHORS.txt for contributors. 14 | * 15 | * This program is free software; you can redistribute it and/or 16 | * modify it under the terms of the GNU General Public License 17 | * as published by the Free Software Foundation; either version 2 18 | * of the License, or (at your option) any later version. 19 | * 20 | * This program is distributed in the hope that it will be useful, 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | * GNU General Public License for more details. 24 | * 25 | * You should have received a copy of the GNU General Public License 26 | * along with this program; if not, you may find one here: 27 | * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 28 | * or you may search the http://www.gnu.org website for the version 2 license, 29 | * or you may write to the Free Software Foundation, Inc., 30 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 31 | */ 32 | 33 | 34 | export class Token { 35 | static LEFT = new Token("("); 36 | static RIGHT = new Token(")"); 37 | // common/pcb.keywords 38 | static add_net = new Token("add_net"); 39 | static allowed = new Token("allowed"); 40 | static angle = new Token("angle"); 41 | static arc = new Token("arc"); 42 | static arc_segments = new Token("arc_segments"); 43 | static area = new Token("area"); 44 | static arrow1a = new Token("arrow1a"); 45 | static arrow1b = new Token("arrow1b"); 46 | static arrow2a = new Token("arrow2a"); 47 | static arrow2b = new Token("arrow2b"); 48 | static at = new Token("at"); 49 | static attr = new Token("attr"); 50 | static autoplace_cost90 = new Token("autoplace_cost90"); 51 | static autoplace_cost180 = new Token("autoplace_cost180"); 52 | static aux_axis_origin = new Token("aux_axis_origin"); 53 | static blind = new Token("blind"); 54 | static blind_buried_vias_allowed = new Token("blind_buried_vias_allowed"); 55 | static bold = new Token("bold"); 56 | static bottom = new Token("bottom"); 57 | static center = new Token("center"); 58 | static chamfer = new Token("chamfer"); 59 | static circle = new Token("circle"); 60 | static clearance = new Token("clearance"); 61 | static comment = new Token("comment"); 62 | static company = new Token("company"); 63 | static connect = new Token("connect"); 64 | static connect_pads = new Token("connect_pads"); 65 | static copperpour = new Token("copperpour"); 66 | static crossbar = new Token("crossbar"); 67 | static date = new Token("date"); 68 | static descr = new Token("descr"); 69 | static die_length = new Token("die_length"); 70 | static dimension = new Token("dimension"); 71 | static diff_pair_width = new Token("diff_pair_width"); 72 | static diff_pair_gap = new Token("diff_pair_gap"); 73 | static drawings = new Token("drawings"); 74 | static drill = new Token("drill"); 75 | static edge = new Token("edge"); 76 | static edge_width = new Token("edge_width"); 77 | static effects = new Token("effects"); 78 | static end = new Token("end"); 79 | static feature1 = new Token("feature1"); 80 | static feature2 = new Token("feature2"); 81 | static fill = new Token("fill"); 82 | static fill_segments = new Token("fill_segments"); 83 | static filled_polygon = new Token("filled_polygon"); 84 | static fillet = new Token("fillet"); 85 | static font = new Token("font"); 86 | static fp_arc = new Token("fp_arc"); 87 | static fp_circle = new Token("fp_circle"); 88 | static fp_curve = new Token("fp_curve"); 89 | static fp_line = new Token("fp_line"); 90 | static fp_poly = new Token("fp_poly"); 91 | static fp_text = new Token("fp_text"); 92 | static full = new Token("full"); 93 | static general = new Token("general"); 94 | static grid_origin = new Token("grid_origin"); 95 | static gr_arc = new Token("gr_arc"); 96 | static gr_circle = new Token("gr_circle"); 97 | static gr_curve = new Token("gr_curve"); 98 | static gr_line = new Token("gr_line"); 99 | static gr_poly = new Token("gr_poly"); 100 | static gr_text = new Token("gr_text"); 101 | static hatch = new Token("hatch"); 102 | static hide = new Token("hide"); 103 | static italic = new Token("italic"); 104 | static justify = new Token("justify"); 105 | static keepout = new Token("keepout"); 106 | static kicad_pcb = new Token("kicad_pcb"); 107 | static last_trace_width = new Token("last_trace_width"); 108 | static layer = new Token("layer"); 109 | static layers = new Token("layers"); 110 | static left = new Token("left"); 111 | static links = new Token("links"); 112 | static locked = new Token("locked"); 113 | static micro = new Token("micro"); 114 | static min_thickness = new Token("min_thickness"); 115 | static mirror = new Token("mirror"); 116 | static mod_edge_width = new Token("mod_edge_width"); 117 | static mod_text_size = new Token("mod_text_size"); 118 | static mod_text_width = new Token("mod_text_width"); 119 | static mode = new Token("mode"); 120 | static model = new Token("model"); 121 | static module = new Token("module"); 122 | static net = new Token("net"); 123 | static net_class = new Token("net_class"); 124 | static net_name = new Token("net_name"); 125 | static nets = new Token("nets"); 126 | static no = new Token("no"); 127 | static no_connects = new Token("no_connects"); 128 | static none = new Token("none"); 129 | static not_allowed = new Token("not_allowed"); 130 | static np_thru_hole = new Token("np_thru_hole"); 131 | static offset = new Token("offset"); 132 | static oval = new Token("oval"); 133 | static pad = new Token("pad"); 134 | static pads = new Token("pads"); 135 | static pad_drill = new Token("pad_drill"); 136 | static pad_size = new Token("pad_size"); 137 | static pad_to_mask_clearance = new Token("pad_to_mask_clearance"); 138 | static solder_mask_min_width = new Token("solder_mask_min_width"); 139 | static pad_to_paste_clearance = new Token("pad_to_paste_clearance"); 140 | static pad_to_paste_clearance_ratio = new Token("pad_to_paste_clearance_ratio"); 141 | static page = new Token("page"); 142 | static path = new Token("path"); 143 | static pcb_text_size = new Token("pcb_text_size"); 144 | static pcb_text_width = new Token("pcb_text_width"); 145 | static pcbplotparams = new Token("pcbplotparams"); 146 | static placed = new Token("placed"); 147 | static plus = new Token("plus"); 148 | static polygon = new Token("polygon"); 149 | static portrait = new Token("portrait"); 150 | static priority = new Token("priority"); 151 | static pts = new Token("pts"); 152 | static radius = new Token("radius"); 153 | static rev = new Token("rev"); 154 | static rect = new Token("rect"); 155 | static rect_delta = new Token("rect_delta"); 156 | static reference = new Token("reference"); 157 | static right = new Token("right"); 158 | static rotate = new Token("rotate"); 159 | static roundrect = new Token("roundrect"); 160 | static roundrect_rratio = new Token("roundrect_rratio"); 161 | static scale = new Token("scale"); 162 | static segment = new Token("segment"); 163 | static segment_width = new Token("segment_width"); 164 | static setup = new Token("setup"); 165 | static size = new Token("size"); 166 | static smd = new Token("smd"); 167 | static smoothing = new Token("smoothing"); 168 | static solder_mask_margin = new Token("solder_mask_margin"); 169 | static solder_paste_margin = new Token("solder_paste_margin"); 170 | static solder_paste_margin_ratio = new Token("solder_paste_margin_ratio"); 171 | static solder_paste_ratio = new Token("solder_paste_ratio"); 172 | static start = new Token("start"); 173 | static status = new Token("status"); 174 | static tags = new Token("tags"); 175 | static target = new Token("target"); 176 | static title = new Token("title"); 177 | static title_block = new Token("title_block"); 178 | static tedit = new Token("tedit"); 179 | static thermal_width = new Token("thermal_width"); 180 | static thermal_gap = new Token("thermal_gap"); 181 | static thermal_bridge_width = new Token("thermal_bridge_width"); 182 | static thickness = new Token("thickness"); 183 | static top = new Token("top"); 184 | static trace_width = new Token("trace_width"); 185 | static tracks = new Token("tracks"); 186 | static trace_min = new Token("trace_min"); 187 | static trace_clearance = new Token("trace_clearance"); 188 | static trapezoid = new Token("trapezoid"); 189 | static thru = new Token("thru"); 190 | static thru_hole = new Token("thru_hole"); 191 | static thru_hole_only = new Token("thru_hole_only"); 192 | static tstamp = new Token("tstamp"); 193 | static user = new Token("user"); 194 | static user_trace_width = new Token("user_trace_width"); 195 | static user_via = new Token("user_via"); 196 | static uvia_dia = new Token("uvia_dia"); 197 | static uvia_drill = new Token("uvia_drill"); 198 | static uvia_min_drill = new Token("uvia_min_drill"); 199 | static uvia_min_size = new Token("uvia_min_size"); 200 | static uvia_size = new Token("uvia_size"); 201 | static uvias_allowed = new Token("uvias_allowed"); 202 | static value = new Token("value"); 203 | static version = new Token("version"); 204 | static via = new Token("via"); 205 | static vias = new Token("vias"); 206 | static via_dia = new Token("via_dia"); 207 | static via_drill = new Token("via_drill"); 208 | static via_min_drill = new Token("via_min_drill"); 209 | static via_min_size = new Token("via_min_size"); 210 | static via_size = new Token("via_size"); 211 | static virtual = new Token("virtual"); 212 | static visible_elements = new Token("visible_elements"); 213 | static width = new Token("width"); 214 | static x = new Token("x"); 215 | static xy = new Token("xy"); 216 | static xyz = new Token("xyz"); 217 | static yes = new Token("yes"); 218 | static zone = new Token("zone"); 219 | static zone_45_only = new Token("zone_45_only"); 220 | static zone_clearance = new Token("zone_clearance"); 221 | static zone_connect = new Token("zone_connect"); 222 | static zone_type = new Token("zone_type"); 223 | static zones = new Token("zones"); 224 | 225 | constructor( public token: string, public line: number = 0) { 226 | } 227 | 228 | is(t: Token): boolean { 229 | return this.token === t.token; 230 | } 231 | 232 | isNUMBER():boolean { 233 | return /^[-+]?([0-9]*\.?[0-9]+|[0-9]+)?([eE][-+]?[0-9]+)?$/.test(this.token); 234 | } 235 | 236 | isSYMBOL():boolean { 237 | // XXX : symbol is not a keyword 238 | return /^.+$/i.test(this.token); 239 | } 240 | 241 | toString(): string { 242 | return this.token; 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /dist/src/kicad_plotter.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"kicad_plotter.js","sourceRoot":"","sources":["../../src/kicad_plotter.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /test/kicad_lib.ts: -------------------------------------------------------------------------------- 1 | //#!npm run test-one 2 | 3 | import * as assert from "assert"; 4 | import * as mocha from 'mocha'; 5 | 6 | import { 7 | TextHjustify, 8 | TextVjustify, 9 | TextAngle, 10 | Fill, 11 | PinOrientation, 12 | PinType, 13 | } from "../src/kicad_common"; 14 | 15 | import { 16 | Library, 17 | LibComponent, 18 | DrawArc, 19 | DrawPin, 20 | DrawPolyline, 21 | DrawCircle, 22 | DrawSquare, 23 | DrawText, 24 | } from "../src/kicad_lib"; 25 | 26 | function indent (literals: TemplateStringsArray, ...placeholders: Array):string { 27 | let result = ""; 28 | 29 | for (let i = 0; i < placeholders.length; i++) { 30 | result += literals[i]; 31 | result += String(placeholders[i]); 32 | } 33 | 34 | result += literals[literals.length - 1]; 35 | 36 | result = result.replace(/^\n|\s+$/g, ''); 37 | const indent = result.match(/^\s+/); 38 | if (indent) { 39 | result = result.replace(new RegExp("^" + indent[0], "gm"), ""); 40 | } 41 | 42 | return result; 43 | } 44 | 45 | /* 46 | describe("", () => { 47 | it("", () => { 48 | }); 49 | }); 50 | */ 51 | 52 | 53 | describe("Library.load", () => { 54 | it("has version check", () => { 55 | assert.doesNotThrow( () => { 56 | Library.load(indent ` 57 | EESchema-LIBRARY Version 2.3 58 | `); 59 | }); 60 | assert.doesNotThrow( () => { 61 | Library.load(indent ` 62 | EESchema-LIBRARY Version 2.2 63 | `); 64 | }); 65 | assert.throws( () => { 66 | Library.load(indent ` 67 | EESchema-LIBRARY Version 2.4 68 | `); 69 | }, 'library format version is greater than supported version: 2.4 > 2.3'); 70 | 71 | assert.throws( () => { 72 | Library.load(indent ` 73 | invalid format 74 | `); 75 | }, 'unknown library format'); 76 | }); 77 | 78 | it("can load basic definition", () => { 79 | const lib = Library.load(indent ` 80 | EESchema-LIBRARY Version 2.3 81 | # 82 | # CONN_01X01 83 | # 84 | DEF CONN_01X01 P 0 40 Y N 1 F N 85 | F0 "P" 0 100 50 H V C CNN 86 | F1 "CONN_01X01" 100 0 50 V V C CNN 87 | F2 "" 0 0 50 H V C CNN 88 | F3 "" 0 0 50 H V C CNN 89 | $FPLIST 90 | Pin_Header_Straight_1X01 91 | Pin_Header_Angled_1X01 92 | Socket_Strip_Straight_1X01 93 | Socket_Strip_Angled_1X01 94 | $ENDFPLIST 95 | DRAW 96 | S -50 5 10 -5 0 1 0 N 97 | S -50 50 50 -50 0 1 0 N 98 | X P1 1 -200 0 150 R 50 50 1 1 P 99 | P 2 0 1 0 -50 70 -50 110 N 100 | A 0 -150 128 1287 513 0 1 20 N -80 -50 80 -50 101 | C -100 0 35 0 1 0 N 102 | T 0 -75 -250 50 0 0 0 B Normal 0 C C 103 | ENDDRAW 104 | ENDDEF 105 | # 106 | #End Library 107 | `); 108 | assert(lib.components.length === 1); 109 | assert(lib.findByName('CONN_01X01') instanceof LibComponent); 110 | 111 | const c = lib.findByName('CONN_01X01'); 112 | if (!c) throw "component is not found"; 113 | assert(c.name === 'CONN_01X01'); 114 | assert(c.reference === 'P'); 115 | assert(c.textOffset === 40); 116 | assert(c.drawPinname === false); 117 | assert(c.drawPinnumber === true); 118 | assert(c.unitCount === 1); 119 | assert(c.unitsLocked === false); 120 | assert(c.optionFlag === 'N'); 121 | 122 | assert(c.field.reference === 'P'); 123 | assert(c.field.pos.x === 0); 124 | assert(c.field.pos.y === 100); 125 | assert(c.field.textSize === 50); 126 | assert(c.field.textOrientation === TextAngle.HORIZ); 127 | assert(c.field.visibility === true); 128 | assert(c.field.hjustify === TextHjustify.CENTER); 129 | assert(c.field.vjustify === TextVjustify.CENTER); 130 | assert(c.field.italic === false); 131 | assert(c.field.bold === false); 132 | 133 | assert(c.fields[0].name === 'CONN_01X01'); 134 | assert(c.fields[0].pos.x === 100); 135 | assert(c.fields[0].pos.y === 0); 136 | assert(c.fields[0].textSize === 50); 137 | assert(c.fields[0].textOrientation === TextAngle.VERT); 138 | assert(c.fields[0].visibility === true); 139 | assert(c.fields[0].hjustify === TextHjustify.CENTER); 140 | assert(c.fields[0].vjustify === TextVjustify.CENTER); 141 | assert(c.fields[0].italic === false); 142 | assert(c.fields[0].bold === false); 143 | 144 | assert(c.fplist.length === 4); 145 | assert(c.draw.objects.length === 7); 146 | 147 | // S -50 5 10 -5 0 1 0 N 148 | assert(c.draw.objects[0] instanceof DrawSquare); 149 | assert((c.draw.objects[0] as DrawSquare).start.x === -50); 150 | assert((c.draw.objects[0] as DrawSquare).start.y === 5); 151 | assert((c.draw.objects[0] as DrawSquare).end.x === 10); 152 | assert((c.draw.objects[0] as DrawSquare).end.y === -5); 153 | assert((c.draw.objects[0] as DrawSquare).unit === 0); 154 | assert((c.draw.objects[0] as DrawSquare).convert === 1); 155 | assert((c.draw.objects[0] as DrawSquare).lineWidth === 0); 156 | assert((c.draw.objects[0] as DrawSquare).fill === Fill.NO_FILL); 157 | 158 | // S -50 50 50 -50 0 1 0 N 159 | assert(c.draw.objects[1] instanceof DrawSquare); 160 | assert((c.draw.objects[1] as DrawSquare).start.x === -50); 161 | assert((c.draw.objects[1] as DrawSquare).start.y === 50); 162 | assert((c.draw.objects[1] as DrawSquare).end.x === 50); 163 | assert((c.draw.objects[1] as DrawSquare).end.y === -50); 164 | assert((c.draw.objects[1] as DrawSquare).unit === 0); 165 | assert((c.draw.objects[1] as DrawSquare).convert === 1); 166 | assert((c.draw.objects[1] as DrawSquare).lineWidth === 0); 167 | assert((c.draw.objects[1] as DrawSquare).fill === Fill.NO_FILL); 168 | 169 | // X P1 1 -200 0 150 R 50 50 1 1 P 170 | assert(c.draw.objects[2] instanceof DrawPin); 171 | assert((c.draw.objects[2] as DrawPin).name === "P1"); 172 | assert((c.draw.objects[2] as DrawPin).num === "1"); 173 | assert((c.draw.objects[2] as DrawPin).pos.x === -200); 174 | assert((c.draw.objects[2] as DrawPin).pos.x === -200); 175 | assert((c.draw.objects[2] as DrawPin).length === 150); 176 | assert((c.draw.objects[2] as DrawPin).orientation === PinOrientation.RIGHT); 177 | assert((c.draw.objects[2] as DrawPin).nameTextSize === 50); 178 | assert((c.draw.objects[2] as DrawPin).numTextSize === 50); 179 | assert((c.draw.objects[2] as DrawPin).unit === 1); 180 | assert((c.draw.objects[2] as DrawPin).convert === 1); 181 | assert((c.draw.objects[2] as DrawPin).pinType === PinType.PASSIVE); 182 | assert.deepEqual((c.draw.objects[2] as DrawPin).attributes, []); 183 | assert((c.draw.objects[2] as DrawPin).visibility === true); 184 | 185 | // P 2 0 1 0 -50 70 -50 110 N 186 | assert(c.draw.objects[3] instanceof DrawPolyline); 187 | assert((c.draw.objects[3] as DrawPolyline).pointCount === 2); 188 | assert((c.draw.objects[3] as DrawPolyline).unit === 0); 189 | assert((c.draw.objects[3] as DrawPolyline).convert === 1); 190 | assert((c.draw.objects[3] as DrawPolyline).lineWidth === 0); 191 | assert.deepEqual((c.draw.objects[3] as DrawPolyline).points, [{ x: -50, y: 70 }, {x: -50, y: 110 }]); 192 | assert((c.draw.objects[3] as DrawPolyline).fill === Fill.NO_FILL); 193 | 194 | // A 0 -150 128 1287 513 0 1 20 N -80 -50 80 -50 195 | assert(c.draw.objects[4] instanceof DrawArc); 196 | assert((c.draw.objects[4] as DrawArc).pos.x === 0); 197 | assert((c.draw.objects[4] as DrawArc).pos.y === -150); 198 | assert((c.draw.objects[4] as DrawArc).radius === 128); 199 | assert((c.draw.objects[4] as DrawArc).startAngle === 1287); 200 | assert((c.draw.objects[4] as DrawArc).endAngle === 513); 201 | assert((c.draw.objects[4] as DrawArc).unit === 0); 202 | assert((c.draw.objects[4] as DrawArc).convert === 1); 203 | assert((c.draw.objects[4] as DrawArc).lineWidth === 20); 204 | assert((c.draw.objects[4] as DrawArc).fill === Fill.NO_FILL); 205 | assert((c.draw.objects[4] as DrawArc).start.x === -80); 206 | assert((c.draw.objects[4] as DrawArc).start.y === -50); 207 | assert((c.draw.objects[4] as DrawArc).end.x === 80); 208 | assert((c.draw.objects[4] as DrawArc).end.y === -50); 209 | 210 | // C -100 0 35 0 1 0 N 211 | assert(c.draw.objects[5] instanceof DrawCircle); 212 | assert((c.draw.objects[5] as DrawCircle).pos.x === -100); 213 | assert((c.draw.objects[5] as DrawCircle).pos.y === 0); 214 | assert((c.draw.objects[5] as DrawCircle).radius === 35); 215 | assert((c.draw.objects[5] as DrawCircle).unit === 0); 216 | assert((c.draw.objects[5] as DrawCircle).convert === 1); 217 | assert((c.draw.objects[5] as DrawCircle).lineWidth === 0); 218 | assert((c.draw.objects[5] as DrawCircle).fill === Fill.NO_FILL); 219 | 220 | // T 0 -75 -250 50 0 0 0 B Normal 0 C C 221 | assert(c.draw.objects[6] instanceof DrawText); 222 | assert((c.draw.objects[6] as DrawText).angle === 0); 223 | assert((c.draw.objects[6] as DrawText).pos.x === -75); 224 | assert((c.draw.objects[6] as DrawText).pos.y === -250); 225 | assert((c.draw.objects[6] as DrawText).textSize === 50); 226 | assert((c.draw.objects[6] as DrawText).textType === 0); 227 | assert((c.draw.objects[6] as DrawText).unit === 0); 228 | assert((c.draw.objects[6] as DrawText).convert === 0); 229 | assert((c.draw.objects[6] as DrawText).text === "B"); 230 | assert((c.draw.objects[6] as DrawText).italic === false); 231 | assert((c.draw.objects[6] as DrawText).bold === false); 232 | assert((c.draw.objects[6] as DrawText).hjustify === TextHjustify.CENTER); 233 | assert((c.draw.objects[6] as DrawText).vjustify === TextVjustify.CENTER); 234 | }); 235 | 236 | it("can treat Pin (X) correctly", () => { 237 | const lib = Library.load(indent ` 238 | EESchema-LIBRARY Version 2.3 239 | DEF TEST T 0 40 Y N 1 F N 240 | F0 "T" 0 100 50 H V C CNN 241 | F1 "TEST" 100 0 50 V V C CNN 242 | F2 "" 0 0 50 H V C CNN 243 | F3 "" 0 0 50 H V C CNN 244 | DRAW 245 | X P1 1 -200 0 150 R 50 50 1 1 P N 246 | ENDDRAW 247 | ENDDEF 248 | # 249 | #End Library 250 | `); 251 | assert(lib.components.length === 1); 252 | assert(lib.findByName('TEST') instanceof LibComponent); 253 | 254 | const c = lib.findByName('TEST'); 255 | if (!c) throw "component is not found"; 256 | // X P1 1 -200 0 150 R 50 50 1 1 P N 257 | assert(c.draw.objects[0] instanceof DrawPin); 258 | assert((c.draw.objects[0] as DrawPin).name === "P1"); 259 | assert((c.draw.objects[0] as DrawPin).num === "1"); 260 | assert((c.draw.objects[0] as DrawPin).pos.x === -200); 261 | assert((c.draw.objects[0] as DrawPin).pos.x === -200); 262 | assert((c.draw.objects[0] as DrawPin).length === 150); 263 | assert((c.draw.objects[0] as DrawPin).orientation === PinOrientation.RIGHT); 264 | assert((c.draw.objects[0] as DrawPin).nameTextSize === 50); 265 | assert((c.draw.objects[0] as DrawPin).numTextSize === 50); 266 | assert((c.draw.objects[0] as DrawPin).unit === 1); 267 | assert((c.draw.objects[0] as DrawPin).convert === 1); 268 | assert((c.draw.objects[0] as DrawPin).pinType === PinType.PASSIVE); 269 | assert.deepEqual((c.draw.objects[0] as DrawPin).attributes, ["N"]); 270 | assert((c.draw.objects[0] as DrawPin).visibility === false); 271 | }); 272 | 273 | it("can treat Text (T) correctly", () => { 274 | const lib = Library.load(indent ` 275 | EESchema-LIBRARY Version 2.3 276 | DEF TEST T 0 40 Y N 1 F N 277 | F0 "T" 0 100 50 H V C CNN 278 | F1 "TEST" 100 0 50 V V C CNN 279 | F2 "" 0 0 50 H V C CNN 280 | F3 "" 0 0 50 H V C CNN 281 | DRAW 282 | T 900 -75 -250 50 0 2 3 Foo~Bar Italic 1 R B 283 | T 900 -75 -250 50 0 2 3 "Foo''Bar''" Italic 1 R B 284 | T 900 -75 -250 50 0 2 3 "Foo~Bar''" Italic 1 R B 285 | ENDDRAW 286 | ENDDEF 287 | # 288 | #End Library 289 | `); 290 | assert(lib.components.length === 1); 291 | assert(lib.findByName('TEST') instanceof LibComponent); 292 | 293 | const c = lib.findByName('TEST'); 294 | if (!c) throw "component is not found"; 295 | assert(c.draw.objects[0] instanceof DrawText); 296 | assert((c.draw.objects[0] as DrawText).angle === 900); 297 | assert((c.draw.objects[0] as DrawText).pos.x === -75); 298 | assert((c.draw.objects[0] as DrawText).pos.y === -250); 299 | assert((c.draw.objects[0] as DrawText).textSize === 50); 300 | assert((c.draw.objects[0] as DrawText).textType === 0); 301 | assert((c.draw.objects[0] as DrawText).unit === 2); 302 | assert((c.draw.objects[0] as DrawText).convert === 3); 303 | assert((c.draw.objects[0] as DrawText).text === "Foo Bar"); 304 | assert((c.draw.objects[0] as DrawText).italic === true); 305 | assert((c.draw.objects[0] as DrawText).bold === true); 306 | assert((c.draw.objects[0] as DrawText).hjustify === TextHjustify.RIGHT); 307 | assert((c.draw.objects[0] as DrawText).vjustify === TextVjustify.BOTTOM); 308 | 309 | assert((c.draw.objects[1] as DrawText).text === 'Foo"Bar"'); 310 | assert((c.draw.objects[2] as DrawText).text === 'Foo~Bar"'); 311 | }); 312 | 313 | it("can treat Polyline (P) correctly", () => { 314 | const lib = Library.load(indent ` 315 | EESchema-LIBRARY Version 2.3 316 | DEF TEST T 0 40 Y N 1 F N 317 | F0 "T" 0 100 50 H V C CNN 318 | F1 "TEST" 100 0 50 V V C CNN 319 | F2 "" 0 0 50 H V C CNN 320 | F3 "" 0 0 50 H V C CNN 321 | DRAW 322 | P 2 0 1 0 -50 70 -50 110 F 323 | P 2 2 3 4 -50 70 -50 110 324 | ENDDRAW 325 | ENDDEF 326 | # 327 | #End Library 328 | `); 329 | assert(lib.components.length === 1); 330 | assert(lib.findByName('TEST') instanceof LibComponent); 331 | 332 | const c = lib.findByName('TEST'); 333 | if (!c) throw "component is not found"; 334 | assert(c.draw.objects[0] instanceof DrawPolyline); 335 | assert((c.draw.objects[0] as DrawPolyline).pointCount === 2); 336 | assert((c.draw.objects[0] as DrawPolyline).unit === 0); 337 | assert((c.draw.objects[0] as DrawPolyline).convert === 1); 338 | assert((c.draw.objects[0] as DrawPolyline).lineWidth === 0); 339 | assert.deepEqual((c.draw.objects[0] as DrawPolyline).points, [{x: -50, y: 70}, {x:-50, y:110}]); 340 | assert((c.draw.objects[0] as DrawPolyline).fill === Fill.FILLED_SHAPE); 341 | 342 | assert(c.draw.objects[1] instanceof DrawPolyline); 343 | assert((c.draw.objects[1] as DrawPolyline).pointCount === 2); 344 | assert((c.draw.objects[1] as DrawPolyline).unit === 2); 345 | assert((c.draw.objects[1] as DrawPolyline).convert === 3); 346 | assert((c.draw.objects[1] as DrawPolyline).lineWidth === 4); 347 | assert.deepEqual((c.draw.objects[1] as DrawPolyline).points, [{x: -50, y: 70}, {x:-50, y:110}]); 348 | assert((c.draw.objects[1] as DrawPolyline).fill === Fill.NO_FILL); 349 | }); 350 | 351 | it("can treat field correctly", () => { 352 | const lib = Library.load(indent ` 353 | EESchema-LIBRARY Version 2.3 354 | DEF Battery BT 0 0 N Y 1 F N 355 | F0 "BT" 100 50 50 H V L CNN 356 | F1 "Battery" 100 -50 50 H V L CNN 357 | F2 "" 0 40 50 V V C CNN 358 | F3 "" 0 40 50 V V C CNN 359 | DRAW 360 | S -90 -7 90 -17 0 1 0 F 361 | S -90 50 90 40 0 1 0 F 362 | S -62 -30 58 -50 0 1 0 F 363 | S -62 27 58 7 0 1 0 F 364 | P 2 0 1 10 20 95 60 95 N 365 | P 2 0 1 10 40 115 40 75 N 366 | X ~ 1 0 150 100 D 50 50 1 1 P 367 | X ~ 2 0 -150 100 U 50 50 1 1 P 368 | ENDDRAW 369 | ENDDEF 370 | # 371 | #End Library 372 | `); 373 | assert(lib.components.length === 1); 374 | assert(lib.findByName('Battery') instanceof LibComponent); 375 | 376 | const c = lib.findByName('Battery'); 377 | if (!c) throw "component is not found"; 378 | assert(c.field.reference === 'BT'); 379 | assert(c.field.pos.x === 100); 380 | assert(c.field.pos.y === 50); 381 | assert(c.field.textSize === 50); 382 | assert(c.field.textOrientation === 0); 383 | assert(c.field.visibility === true); 384 | assert(c.field.hjustify === TextHjustify.LEFT); 385 | assert(c.field.vjustify === TextVjustify.CENTER); 386 | assert(c.field.italic === false); 387 | assert(c.field.bold === false); 388 | }); 389 | }); 390 | -------------------------------------------------------------------------------- /dist/src/kicad_lib.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"kicad_lib.js","sourceRoot":"","sources":["../../src/kicad_lib.ts"],"names":[],"mappings":"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"} --------------------------------------------------------------------------------