@logomarks/core 0.1.2 → 0.1.4
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/CHANGELOG.md +12 -0
- package/package.json +1 -1
- package/src/similar/signature.js +4 -2
- package/src/skill/bundle.js +26 -9
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ All notable changes to `@logomarks/core` are documented here.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.1.4] — 2026-11-06
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- The generated `fit.mjs` fits several files each in place. Given exactly two files it used to take the second as the output and write the first one's fit into it, so the second mark was lost. A file's fit now goes to another file only with `-o out.svg`, or when the second path doesn't exist yet (`in.svg out.svg`, as before). `--help` prints the usage (it used to crash), and an unknown option, a missing path or `-o` with several inputs exits 2 with the reason.
|
|
13
|
+
|
|
14
|
+
## [0.1.3] — 2026-11-06
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- `letterSignatures()` counts a pixel as ink only above half coverage (8-bit alpha 128 and up, as `holecheck.mjs` did): with Float32 coverage, an alpha of 127 rounded past `127 / 255` and counted, which moved letter scores by about a hundredth and could reorder near matches.
|
|
19
|
+
|
|
8
20
|
## [0.1.2] — 2026-11-06
|
|
9
21
|
|
|
10
22
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logomarks/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Geometry, SVG reading, fitting, analysis and similarity for logomarks on a 512 grid: the kit the Logomarks set is drawn with (shapes, real booleans, strokes, tracks, iso solids, badges, letter skeletons), one SVG path parser, the 448 fit, speck and shape-tag analysis, outline signatures, and the industry-symbol parts.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
package/src/similar/signature.js
CHANGED
|
@@ -96,7 +96,8 @@ function cropped(a, R, N) {
|
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
98
|
* A mark's letter signatures from its coverage at LETTER.render: its holes (null when it has none) and its ink, each
|
|
99
|
-
* cropped to its box at LETTER.size.
|
|
99
|
+
* cropped to its box at LETTER.size. A pixel is ink when it is more than half covered (8-bit alpha 128 and up, as
|
|
100
|
+
* holecheck read it), whether the coverage is a Float32Array or a Float64Array.
|
|
100
101
|
*
|
|
101
102
|
* @param {Float32Array} alpha Coverage 0–1, `render` × `render`.
|
|
102
103
|
* @param {number} [R] Its side (128).
|
|
@@ -105,7 +106,8 @@ function cropped(a, R, N) {
|
|
|
105
106
|
*/
|
|
106
107
|
export function letterSignatures(alpha, R = LETTER.render, N = LETTER.size) {
|
|
107
108
|
const ink = new Uint8Array(R * R);
|
|
108
|
-
|
|
109
|
+
// > 0.5, not > 127 / 255: an alpha of 127 stored as Float32 rounds up past the double 127 / 255 and would count as ink
|
|
110
|
+
for (let i = 0; i < ink.length; i++) ink[i] = alpha[i] > 0.5 ? 1 : 0;
|
|
109
111
|
const holes = cropped(holesOf(ink, R), R, N);
|
|
110
112
|
return { holes: holes.some((v) => v > 0) ? holes : null, ink: cropped(ink, R, N) };
|
|
111
113
|
}
|
package/src/skill/bundle.js
CHANGED
|
@@ -41,8 +41,8 @@ const FIT_HEADER = `#!/usr/bin/env node
|
|
|
41
41
|
// {{url}} · CC0 · no dependencies
|
|
42
42
|
//
|
|
43
43
|
// node fit.mjs mark.svg fit in place
|
|
44
|
-
// node fit.mjs in.svg out.svg
|
|
45
|
-
// node fit.mjs marks/
|
|
44
|
+
// node fit.mjs in.svg -o out.svg fit to another file (in.svg out.svg too, while out.svg doesn't exist)
|
|
45
|
+
// node fit.mjs a.svg b.svg marks/ fit each file, and every .svg in a folder, in place
|
|
46
46
|
// node fit.mjs --check mark.svg marks/ only report; exits 1 if anything is off
|
|
47
47
|
//
|
|
48
48
|
// Reads <path d> (with fill-rule), <circle>, <ellipse>, <rect> and <polygon>; nested
|
|
@@ -58,16 +58,33 @@ import path from 'node:path';
|
|
|
58
58
|
const FIT_MAIN = `
|
|
59
59
|
// ---------- command line ----------
|
|
60
60
|
|
|
61
|
+
const USAGE = \`Usage: node fit.mjs [--check] <file.svg | folder>... [-o out.svg]
|
|
62
|
+
Fits each file in place (a folder: every .svg in it). -o writes one file's fit to another file;
|
|
63
|
+
so does a second path that doesn't exist yet (in.svg out.svg). --check only reports.\`;
|
|
64
|
+
|
|
65
|
+
/** Stops with a message and the usage. */
|
|
66
|
+
const fail = (msg) => { console.error(\`fit.mjs: \${msg}\\n\${USAGE}\`); process.exit(2); };
|
|
67
|
+
|
|
61
68
|
const args = process.argv.slice(2);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
if (args.some((a) => a === '--help' || a === '-h')) { console.log(USAGE); process.exit(0); }
|
|
70
|
+
const checking = args.includes('--check');
|
|
71
|
+
let out = null;
|
|
72
|
+
const paths = [];
|
|
73
|
+
for (let i = 0; i < args.length; i++) {
|
|
74
|
+
if (args[i] === '--check') continue;
|
|
75
|
+
if (args[i] === '-o' || args[i] === '--out') { out = args[++i] ?? fail(\`\${args[i - 1]} needs a file\`); continue; }
|
|
76
|
+
if (args[i].startsWith('-')) fail(\`unknown option \${args[i]}\`);
|
|
77
|
+
paths.push(args[i]);
|
|
78
|
+
}
|
|
79
|
+
if (!paths.length) fail('no file or folder given');
|
|
80
|
+
for (const p of paths) if (!fs.existsSync(p)) {
|
|
81
|
+
// in.svg out.svg: the second path names the file to write, as -o does
|
|
82
|
+
if (!checking && !out && paths.length === 2 && p === paths[1] && p.endsWith('.svg')) out = paths.pop();
|
|
83
|
+
else fail(\`\${p} doesn't exist\`);
|
|
67
84
|
}
|
|
85
|
+
if (out && (checking || paths.length !== 1 || fs.statSync(paths[0]).isDirectory())) fail('-o takes one .svg file to fit, without --check');
|
|
68
86
|
const files = [];
|
|
69
|
-
|
|
70
|
-
for (const a of args) {
|
|
87
|
+
for (const a of paths) {
|
|
71
88
|
if (fs.statSync(a).isDirectory()) for (const f of fs.readdirSync(a)) { if (f.endsWith('.svg')) files.push(path.join(a, f)); }
|
|
72
89
|
else files.push(a);
|
|
73
90
|
}
|