-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcreate-icon.js
More file actions
93 lines (82 loc) · 4.04 KB
/
create-icon.js
File metadata and controls
93 lines (82 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// DGMD tray icon — camera silhouette with {/} code lens
// macOS template: monochrome black + alpha
const fs = require('fs');
const zlib = require('zlib');
function createPNG(w, h, px) {
const sig = Buffer.from([137,80,78,71,13,10,26,10]);
const ihdr = Buffer.alloc(13);
ihdr.writeUInt32BE(w,0); ihdr.writeUInt32BE(h,4); ihdr[8]=8; ihdr[9]=6;
const raw = Buffer.alloc(h*(1+w*4));
for(let y=0;y<h;y++){raw[y*(1+w*4)]=0;for(let x=0;x<w;x++){const s=(y*w+x)*4,d=y*(1+w*4)+1+x*4;raw[d]=px[s];raw[d+1]=px[s+1];raw[d+2]=px[s+2];raw[d+3]=px[s+3];}}
return Buffer.concat([sig,chunk('IHDR',ihdr),chunk('IDAT',zlib.deflateSync(raw)),chunk('IEND',Buffer.alloc(0))]);
}
function chunk(t,d){const l=Buffer.alloc(4);l.writeUInt32BE(d.length);const tb=Buffer.from(t);const c=Buffer.alloc(4);c.writeUInt32BE(crc32(Buffer.concat([tb,d]))>>>0);return Buffer.concat([l,tb,d,c]);}
function crc32(b){let c=0xffffffff;for(let i=0;i<b.length;i++){c^=b[i];for(let j=0;j<8;j++)c=(c>>>1)^(c&1?0xedb88320:0);}return c^0xffffffff;}
function set(px, w, x, y, alpha) {
if (x < 0 || x >= w || y < 0 || y >= w) return;
const i = (Math.round(y) * w + Math.round(x)) * 4;
const a = Math.min(255, Math.max(px[i+3], Math.round(alpha)));
px[i] = 0; px[i+1] = 0; px[i+2] = 0; px[i+3] = a;
}
function drawCamera(size) {
const px = Buffer.alloc(size * size * 4);
const s = size;
const sc = s / 22; // scale factor (design at 22, render at size)
// Camera body: rounded rect
const bx1 = 2*sc, by1 = 6*sc, bx2 = 20*sc, by2 = 18*sc, br = 2.5*sc, bstroke = 1.4*sc;
// Viewfinder bump on top
const vx1 = 7*sc, vx2 = 15*sc, vy1 = 3.5*sc, vy2 = 6*sc, vr = 1.5*sc;
// Lens circle
const lcx = 11*sc, lcy = 12.5*sc, lr = 4*sc, lstroke = 1.3*sc;
for (let y = 0; y < s; y++) {
for (let x = 0; x < s; x++) {
let alpha = 0;
// --- Camera body (rounded rect stroke) ---
const dBody = sdfRoundedRect(x, y, bx1, by1, bx2, by2, br);
if (Math.abs(dBody) < bstroke / 2) {
const edge = bstroke / 2 - Math.abs(dBody);
alpha = Math.max(alpha, Math.min(255, edge * 255));
}
// --- Viewfinder bump (rounded rect stroke) ---
const dView = sdfRoundedRect(x, y, vx1, vy1, vx2, vy2, vr);
if (Math.abs(dView) < bstroke / 2) {
const edge = bstroke / 2 - Math.abs(dView);
alpha = Math.max(alpha, Math.min(255, edge * 255));
}
// Fill the overlap area between viewfinder and body to make it solid
if (dView < 0 && y >= vy1 && y <= by1 + bstroke) {
alpha = 0; // erase the body's top edge inside viewfinder
}
// Re-draw viewfinder outline cleanly
if (dView >= -bstroke/2 && dView < bstroke/2 && !(y > by1 - bstroke/2 && y < by1 + bstroke/2 && x > vx1 + vr && x < vx2 - vr)) {
// Don't draw the bottom of viewfinder where it merges with body top
if (y < by1 - bstroke/2 || x <= vx1 + vr || x >= vx2 - vr) {
const edge = bstroke / 2 - Math.abs(dView);
alpha = Math.max(alpha, Math.min(255, edge * 255));
}
}
// --- Lens (circle stroke) ---
const dLens = Math.sqrt((x - lcx) ** 2 + (y - lcy) ** 2) - lr;
if (Math.abs(dLens) < lstroke / 2) {
const edge = lstroke / 2 - Math.abs(dLens);
alpha = Math.max(alpha, Math.min(255, edge * 255));
}
if (alpha > 0) set(px, s, x, y, alpha);
}
}
return px;
}
// Signed distance to a rounded rectangle (negative = inside)
function sdfRoundedRect(px, py, x1, y1, x2, y2, r) {
const cx = (x1 + x2) / 2, cy = (y1 + y2) / 2;
const hw = (x2 - x1) / 2, hh = (y2 - y1) / 2;
const dx = Math.abs(px - cx) - hw + r;
const dy = Math.abs(py - cy) - hh + r;
const outside = Math.sqrt(Math.max(dx, 0) ** 2 + Math.max(dy, 0) ** 2) - r;
const inside = Math.min(Math.max(dx, dy), 0) - r;
// Negative inside, positive outside, ~0 at boundary
return outside > 0 ? outside : inside + r;
}
fs.writeFileSync('assets/iconTemplate.png', createPNG(22, 22, drawCamera(22)));
fs.writeFileSync('assets/iconTemplate@2x.png', createPNG(44, 44, drawCamera(44)));
console.log('✅ Camera tray icons created');