font2bitmap 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +14 -17
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
`)} // '${
|
|
2
|
+
import R from"node:fs";import{Command as P}from"commander";var v={name:"font2bitmap",version:"1.1.2",description:"Utility to convert font files to bitmap format",main:"dist/cli.js",type:"module",keywords:["bitmap","OLED","font","ssd1306"],author:"Pavel Koltyshev <pkoltyshev@gmail.com>",license:"MIT",repository:"pkolt/font2bitmap",bugs:{url:"https://github.com/pkolt/font2bitmap/issues",email:"pkoltyshev@gmail.com"},files:["README.md","LICENSE.md","dist/cli.js"],bin:{font2bitmap:"dist/cli.js"},engines:{node:">= 24"},scripts:{dev:"node ./src/cli.ts",build:"rimraf dist && esbuild ./src/cli.ts --bundle --minify --platform=node --format=esm --packages=external --outfile=./dist/cli.js",types:"tsc --noEmit",format:"prettier --check src","format-fix":"prettier --write src",lint:"eslint","lint-fix":"eslint --fix",knip:"knip",test:"node --test",coverage:"node --test --experimental-test-coverage",check:"npm run types && npm run format && npm run test && npm run lint && npm run knip",prepare:'if [ "$NODE_ENV" != "production" ]; then git config core.hooksPath .git-hooks; fi',"pre-commit":"npm run check",release:"release-it"},devDependencies:{"@eslint/js":"^9.39.2","@types/node":"^25.0.3",esbuild:"^0.27.2",eslint:"^9.39.2",jiti:"^2.6.1",knip:"^5.78.0",prettier:"^3.7.4","release-it":"^19.2.2",rimraf:"^6.1.3",typescript:"^5.9.3","typescript-eslint":"^8.50.1"},dependencies:{canvas:"^3.2.0",commander:"^14.0.2"}};import{createCanvas as k,registerFont as j}from"canvas";var _="Font Family",E="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",F="0123456789",I="\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041A\u041B\u041C\u041D\u041E\u041F\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042A\u042B\u042C\u042D\u042E\u042F\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043A\u043B\u043C\u043D\u043E\u043F\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044A\u044B\u044C\u044D\u044E\u044F",T=`.,!?"'-=/\\[]{}();:&*+@~`;function D(t,e,o){e.fillStyle="#fff",e.fillRect(0,0,e.canvas.width,e.canvas.height),e.fillStyle="#000",e.fillText(t,0,o/2);let p=e.getImageData(0,0,e.canvas.width,o),{data:n}=p,r=e.canvas.width,i=-1;for(let f=0;f<o;f++)for(let c=0;c<e.canvas.width;c++){let d=n[(f*e.canvas.width+c)*4];d!==void 0&&d<255&&(c<r&&(r=c),c>i&&(i=c))}if(r>i)return{char:t,width:0,symbol:{char:t,width:0,bitmap:new Uint8Array(0)}};let a=i-r+1,l=Math.ceil(a/8),h=new Uint8Array(l*o);if(a>0)for(let f=0;f<o;f++)for(let c=0;c<a;c++){let d=n[(f*e.canvas.width+(r+c))*4];if(d!==void 0&&d<128){let y=f*l+Math.floor(c/8),x=c%8,s=h[y];s!==void 0&&(h[y]=s|1<<x)}}return{char:t,width:a,symbol:{char:t,width:a,bitmap:h}}}function L(t){if(t.length===0)return[];let e=[...t].sort((r,i)=>r.char.charCodeAt(0)-i.char.charCodeAt(0)),o=e[0];if(!o)return[];let p=[],n={start:o.char.charCodeAt(0),end:o.char.charCodeAt(0),symbols:[o.symbol]};for(let r=1;r<e.length;r++){let i=e[r];if(!i)continue;let a=i.char.charCodeAt(0);a===n.end+1?(n.end=a,n.symbols.push(i.symbol)):(p.push(n),n={start:a,end:a,symbols:[i.symbol]})}return p.push(n),p}function O(t){j(t.fontPath,{family:_});let{height:e}=t,o=k(e*2,e).getContext("2d");o.font=`${e}px "${_}"`,o.textBaseline="middle",o.textAlign="left",o.textDrawingMode="glyph";let p=M(t.subsets,t.symbols),n={name:t.fontName,width:0,height:0,letterSpacing:t.letterSpacing,wordSpacing:t.wordSpacing,subsets:[]};if(p.length===0)return n;let r=p.map(l=>D(l,o,e)),i=r.map(({char:l,symbol:h})=>({char:l,symbol:h})),a=Math.max(0,...r.map(l=>l.width));return n.width=a,n.height=e,n.subsets=L(i),n}function M(t,e){let o={ascii:Array.from({length:95},(n,r)=>String.fromCharCode(32+r)).join(""),latin:E,digits:F,cyrillic:I,punctuation:T},p=new Set(e);return t.forEach(n=>{o[n].split("").forEach(r=>p.add(r))}),Array.from(p)}function N(t){let e=t.name,o=t.subsets.map(n=>{let r=0,i=[],a=[],l=[],h=(s,S,w=16,C=16)=>{if(s.length===0)return"";let g=Array.from(s).map(b=>`0x${b.toString(16).padStart(2,"0")}`),u=[];for(let b=0;b<g.length;b+=w)u.push(" ".repeat(C)+g.slice(b,b+w).join(", "));let $=u.pop();return $&&u.push(`${$},`),`${u.join(`,
|
|
3
|
+
`)} // '${S}'`},f=n.symbols.some(s=>s.width!==t.width);for(let s of n.symbols)i.push(r),r+=s.bitmap.length,a.push(s.width),l.push(h(s.bitmap,s.char,16,16));let c=(s,S=16,w=16)=>{if(s.length===0)return"{}";let C=s.map(u=>`0x${u.toString(16).padStart(2,"0")}`),g=[];for(let u=0;u<C.length;u+=S)g.push(" ".repeat(w)+C.slice(u,u+S).join(", "));return`{
|
|
4
4
|
${g.join(`,
|
|
5
5
|
`)}
|
|
6
|
-
}`},
|
|
7
|
-
${
|
|
6
|
+
}`},d=`{
|
|
7
|
+
${l.filter(s=>s!=="").join(`,
|
|
8
8
|
`)}
|
|
9
|
-
}`,
|
|
10
|
-
.start = ${
|
|
11
|
-
.end = ${
|
|
12
|
-
.symbols_count = ${
|
|
13
|
-
.symbols = (uint8_t[])${
|
|
14
|
-
.offsets = (uint32_t[]) ${
|
|
15
|
-
.widths = ${
|
|
9
|
+
}`,y=`{ ${i.join(", ")} }`,x=f?`(uint8_t[]) ${c(a,20,16)}`:"NULL";return` {
|
|
10
|
+
.start = ${n.start},
|
|
11
|
+
.end = ${n.end},
|
|
12
|
+
.symbols_count = ${n.symbols.length},
|
|
13
|
+
.symbols = (uint8_t[])${d},
|
|
14
|
+
.offsets = (uint32_t[]) ${y},
|
|
15
|
+
.widths = ${x}
|
|
16
16
|
}`}).join(`,
|
|
17
|
-
`);return`#
|
|
18
|
-
#define ${n}
|
|
17
|
+
`);return`#pragma once
|
|
19
18
|
|
|
20
19
|
#include <stdint.h>
|
|
21
20
|
#include "font.h"
|
|
@@ -27,9 +26,7 @@ const font_t ${e} = {
|
|
|
27
26
|
.word_spacing = ${t.wordSpacing},
|
|
28
27
|
.subsets_count = ${t.subsets.length},
|
|
29
28
|
.subsets = (const font_subset_t[]) {
|
|
30
|
-
${
|
|
29
|
+
${o}
|
|
31
30
|
}
|
|
32
31
|
};
|
|
33
|
-
|
|
34
|
-
#endif // ${n}
|
|
35
|
-
`}var x=new P;x.name("font2bitmap").version(_.version).description(_.description);x.requiredOption("--fontPath <path>","Path to the font file (e.g., RobotoMono-Medium.ttf)").requiredOption("--fontName <name>","Name of the font (e.g., RobotoMono)").requiredOption("--height <height>","Height of the font in pixels",t=>parseInt(t,10)).requiredOption("--output <path>","Output file path").option("--format <format>","Output format","pico").option("--subsets <subset1,subset2>","Comma-separated list of character subsets",t=>t.split(","),["ascii"]).option("--letter-spacing <spacing>","Letter spacing",t=>parseInt(t,10),1).option("--word-spacing <spacing>","Word spacing",t=>parseInt(t,10),6).option("--symbols <value>","A string of additional characters to include","");x.parse(process.argv);var p=x.opts();try{if(!U.existsSync(p.fontPath))throw new Error(`Error: Font file not found at ${p.fontPath}`);let t={fontPath:p.fontPath,fontName:p.fontName,height:p.height,subsets:p.subsets,symbols:p.symbols?Array.from(p.symbols):[],letterSpacing:p.letterSpacing,wordSpacing:p.wordSpacing},e=N(t);if(p.format==="pico"){let n=R(e);U.writeFileSync(p.output,n),console.log(`Output successfully written to ${p.output}`)}else throw new Error(`Error: Unsupported format "${p.format}"`)}catch(t){t instanceof Error?console.error(t.message):console.error(t),process.exit(1)}
|
|
32
|
+
`}var A=new P;A.name("font2bitmap").version(v.version).description(v.description);A.requiredOption("--fontPath <path>","Path to the font file (e.g., RobotoMono-Medium.ttf)").requiredOption("--fontName <name>","Name of the font (e.g., RobotoMono)").requiredOption("--height <height>","Height of the font in pixels",t=>parseInt(t,10)).requiredOption("--output <path>","Output file path").option("--format <format>","Output format","pico").option("--subsets <subset1,subset2>","Comma-separated list of character subsets",t=>t.split(","),["ascii"]).option("--letter-spacing <spacing>","Letter spacing",t=>parseInt(t,10),1).option("--word-spacing <spacing>","Word spacing",t=>parseInt(t,10),6).option("--symbols <value>","A string of additional characters to include","");A.parse(process.argv);var m=A.opts();try{if(!R.existsSync(m.fontPath))throw new Error(`Error: Font file not found at ${m.fontPath}`);let t={fontPath:m.fontPath,fontName:m.fontName,height:m.height,subsets:m.subsets,symbols:m.symbols?Array.from(m.symbols):[],letterSpacing:m.letterSpacing,wordSpacing:m.wordSpacing},e=O(t);if(m.format==="pico"){let o=N(e);R.writeFileSync(m.output,o),console.log(`Output successfully written to ${m.output}`)}else throw new Error(`Error: Unsupported format "${m.format}"`)}catch(t){t instanceof Error?console.error(t.message):console.error(t),process.exit(1)}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "font2bitmap",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Utility to convert font files to bitmap format",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"type": "module",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"dev": "node ./src/cli.ts",
|
|
33
|
-
"build": "esbuild ./src/cli.ts --bundle --minify --platform=node --format=esm --packages=external --outfile=./dist/cli.js",
|
|
33
|
+
"build": "rimraf dist && esbuild ./src/cli.ts --bundle --minify --platform=node --format=esm --packages=external --outfile=./dist/cli.js",
|
|
34
34
|
"types": "tsc --noEmit",
|
|
35
35
|
"format": "prettier --check src",
|
|
36
36
|
"format-fix": "prettier --write src",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"knip": "^5.78.0",
|
|
54
54
|
"prettier": "^3.7.4",
|
|
55
55
|
"release-it": "^19.2.2",
|
|
56
|
+
"rimraf": "^6.1.3",
|
|
56
57
|
"typescript": "^5.9.3",
|
|
57
58
|
"typescript-eslint": "^8.50.1"
|
|
58
59
|
},
|