├── 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 |
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 |
71 |
{{ status }}
72 |
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 |
94 |
{{ status }}
95 |
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 |
99 |
{{ status }}
100 |
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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"}
--------------------------------------------------------------------------------