From 52e1dc6eda4c1e944b48239a5de8316b52bb9afe Mon Sep 17 00:00:00 2001 From: locpham Date: Sun, 9 Aug 2026 02:59:11 +0000 Subject: [PATCH] =?UTF-8?q?FEAT:=20icon=20exe=20=3D=20favicon=20cua=20app?= =?UTF-8?q?=20=E2=80=94=20favicon.svg=20->=20PNG=20->=20ICO=20(6=20sizes?= =?UTF-8?q?=2016-128)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - engine.spec: icon='src-tauri/icons/favicon.ico' (cung nguon voi icon hien thi trong app, truoc day dung icon.ico mac dinh khac favicon) - tools/gen_favicon_ico.js: script tai sinh ICO tu app/templates/favicon.svg (resvg-js WASM, khong can libcairo) - Verify: ICO 6 sizes (16/24/32/48/64/128), 571 mau, binary chay OK --- engine.spec | 4 ++- src-tauri/icons/favicon.ico | Bin 0 -> 32892 bytes tools/gen_favicon_ico.js | 55 ++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src-tauri/icons/favicon.ico create mode 100644 tools/gen_favicon_ico.js diff --git a/engine.spec b/engine.spec index fbce929..aff2a8d 100644 --- a/engine.spec +++ b/engine.spec @@ -124,5 +124,7 @@ exe = EXE( upx_exclude=[], runtime_tmpdir=None, console=False, # True khi debug (xem log truc tiep), False cho production - icon='src-tauri/icons/icon.ico', + # Icon exe = favicon cua app (app/templates/favicon.svg -> render PNG -> ICO, + # sinh boi tools/gen_favicon_ico.py). Cung nguon voi icon hien thi trong app. + icon='src-tauri/icons/favicon.ico', ) diff --git a/src-tauri/icons/favicon.ico b/src-tauri/icons/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f7e1874525dfbde89aafb14c9aa551b18ebc4f26 GIT binary patch literal 32892 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 literal 0 HcmV?d00001 diff --git a/tools/gen_favicon_ico.js b/tools/gen_favicon_ico.js new file mode 100644 index 0000000..616926e --- /dev/null +++ b/tools/gen_favicon_ico.js @@ -0,0 +1,55 @@ +// Sinh src-tauri/icons/favicon.ico tu app/templates/favicon.svg (icon exe). +// Dung: node tools/gen_favicon_ico.js +// (Can @resvg/resvg-js — npm install @resvg/resvg-js trong thu muc lam viec, +// hoac chay trong thu muc da cai. Output: src-tauri/icons/favicon.ico.) +// ICO chua cac size 16/24/32/48/64/128 — Windows dung cho exe icon. +const fs = require('fs'); +const path = require('path'); + +const ROOT = path.resolve(__dirname, '..'); +const SVG = path.join(ROOT, 'app', 'templates', 'favicon.svg'); +const OUT = path.join(ROOT, 'src-tauri', 'icons', 'favicon.ico'); + +let Resvg; +try { + ({ Resvg } = require('@resvg/resvg-js')); +} catch (e) { + console.error('Thieu @resvg/resvg-js. Chay: npm install @resvg/resvg-js'); + process.exit(1); +} + +const svg = fs.readFileSync(SVG, 'utf8'); +const SIZES = [16, 24, 32, 48, 64, 128]; + +function buildIco(images) { + const header = Buffer.alloc(6); + header.writeUInt16LE(0, 0); + header.writeUInt16LE(1, 2); + header.writeUInt16LE(images.length, 4); + const entries = []; + const datas = []; + let offset = 6 + 16 * images.length; + for (const { size, data } of images) { + const entry = Buffer.alloc(16); + const dim = size >= 256 ? 0 : size; + entry.writeUInt8(dim, 0); + entry.writeUInt8(dim, 1); + entry.writeUInt8(0, 2); + entry.writeUInt8(0, 3); + entry.writeUInt16LE(1, 4); + entry.writeUInt16LE(32, 6); + entry.writeUInt32LE(data.length, 8); + entry.writeUInt32LE(offset, 12); + entries.push(entry); + datas.push(data); + offset += data.length; + } + return Buffer.concat([header, ...entries, ...datas]); +} + +const pngs = SIZES.map(s => ({ + size: s, + data: new Resvg(svg, { fitTo: { mode: 'width', value: s }, background: 'rgba(0,0,0,0)' }).render().asPng(), +})); +fs.writeFileSync(OUT, buildIco(pngs)); +console.log('favicon.ico ->', OUT, fs.statSync(OUT).size, 'bytes');