- 在 .gitignore 中添加 node_modules 目录 - 在 Msvc.php 中添加 compileResourceFile 方法用于编译 .rc 资源文件 - 新增 package.json 配置文件及 svg-to-ico.js 转换脚本 - 在 project.yml 中添加 Windows 资源文件配置示例 - 添加 swoole-logo.svg 图标文件 - 在 Translator.php 中集成资源文件生成功能 - 实现资源文件编译和链接到最终可执行文件的流程 - 更新版本号从 1049 到 1051pull/1/head
parent
c79573a9fe
commit
b17b4acbac
10 changed files with 381 additions and 7 deletions
@ -1,6 +1,19 @@ |
|||||||
name: win32-hello |
name: win32-hello |
||||||
version: 0.0.1 |
version: 0.0.1 |
||||||
mode: bin |
mode: bin |
||||||
|
|
||||||
|
# Windows 资源文件配置示例 |
||||||
|
# resource: |
||||||
|
# icon: icon.ico |
||||||
|
# version-info: |
||||||
|
# file-version: 0.0.1.0 |
||||||
|
# product-version: 0.0.1.0 |
||||||
|
# company-name: "My Company" |
||||||
|
# file-description: "Win32 Hello World Application" |
||||||
|
# legal-copyright: "Copyright (C) 2026 My Company" |
||||||
|
# product-name: "Win32 Hello" |
||||||
|
# original-filename: "win32-hello.exe" |
||||||
|
|
||||||
sources: |
sources: |
||||||
- hello-win.php |
- hello-win.php |
||||||
- ./cpp-src |
- ./cpp-src |
||||||
|
|||||||
@ -0,0 +1,25 @@ |
|||||||
|
{ |
||||||
|
"name": "compiler", |
||||||
|
"version": "1.0.0", |
||||||
|
"description": "- 需要 PHP-8.2 以上版本 - 需要 GCC-9 以上版本,支持 C++17 标准 - 需要 CMake-3.24 以上版本", |
||||||
|
"main": "index.js", |
||||||
|
"directories": { |
||||||
|
"doc": "docs", |
||||||
|
"example": "examples", |
||||||
|
"test": "tests" |
||||||
|
}, |
||||||
|
"scripts": { |
||||||
|
"test": "echo \"Error: no test specified\" && exit 1" |
||||||
|
}, |
||||||
|
"repository": { |
||||||
|
"type": "git", |
||||||
|
"url": "git@git.code-galaxy.net:aot/compiler.git" |
||||||
|
}, |
||||||
|
"keywords": [], |
||||||
|
"author": "", |
||||||
|
"license": "ISC", |
||||||
|
"type": "commonjs", |
||||||
|
"dependencies": { |
||||||
|
"sharp": "^0.34.5" |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,147 @@ |
|||||||
|
/** |
||||||
|
* SVG → ICO 转换脚本 (Node.js) |
||||||
|
*
|
||||||
|
* 使用 sharp 库将 SVG 渲染为多尺寸 PNG,再合并为 ICO |
||||||
|
*
|
||||||
|
* 用法: node svg-to-ico.js <input.svg> [output.ico] |
||||||
|
*/ |
||||||
|
|
||||||
|
const sharp = require('sharp'); |
||||||
|
const fs = require('fs'); |
||||||
|
const path = require('path'); |
||||||
|
|
||||||
|
const sizes = [16, 32, 48, 64, 128, 256]; |
||||||
|
|
||||||
|
async function main() { |
||||||
|
const args = process.argv.slice(2); |
||||||
|
if (args.length < 1) { |
||||||
|
console.log('用法: node svg-to-ico.js <input.svg> [output.ico]'); |
||||||
|
process.exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
const inputSvg = path.resolve(args[0]); |
||||||
|
const outputIco = args.length >= 2
|
||||||
|
? path.resolve(args[1])
|
||||||
|
: path.join(path.dirname(inputSvg), path.basename(inputSvg, '.svg') + '.ico'); |
||||||
|
|
||||||
|
if (!fs.existsSync(inputSvg)) { |
||||||
|
console.log(`错误: SVG 文件不存在: ${inputSvg}`); |
||||||
|
process.exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
console.log('=== SVG → ICO 转换工具 ===\n'); |
||||||
|
console.log(`输入: ${inputSvg}`); |
||||||
|
console.log(`输出: ${outputIco}\n`); |
||||||
|
|
||||||
|
const svgBuffer = fs.readFileSync(inputSvg); |
||||||
|
|
||||||
|
// 步骤1: 渲染 SVG 为多个尺寸的 PNG
|
||||||
|
const pngBuffers = {}; |
||||||
|
for (const size of sizes) { |
||||||
|
console.log(`[1/2] 渲染 SVG → PNG (${size}x${size})...`); |
||||||
|
try { |
||||||
|
const pngBuffer = await sharp(svgBuffer, { density: 300 }) |
||||||
|
.resize(size, size, { fit: 'contain', background: { r: 255, g: 255, b: 255, alpha: 1 } }) |
||||||
|
.png() |
||||||
|
.toBuffer(); |
||||||
|
pngBuffers[size] = pngBuffer; |
||||||
|
console.log(` 完成: ${size}x${size} (${pngBuffer.length} bytes)`); |
||||||
|
} catch (err) { |
||||||
|
console.log(` 警告: ${size}x${size} PNG 生成失败: ${err.message},跳过`); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const validSizes = Object.keys(pngBuffers).map(Number).sort((a, b) => a - b); |
||||||
|
if (validSizes.length === 0) { |
||||||
|
console.log('\n错误: 所有尺寸的 PNG 都生成失败'); |
||||||
|
process.exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
// 步骤2: 合并为 ICO
|
||||||
|
console.log('\n[2/2] 合并 PNG → ICO...'); |
||||||
|
const icoBuffer = createIcoFromPngs(pngBuffers, validSizes); |
||||||
|
fs.writeFileSync(outputIco, icoBuffer); |
||||||
|
|
||||||
|
console.log(`\n成功! ICO 文件已生成: ${outputIco}`); |
||||||
|
console.log(`包含尺寸: ${validSizes.join(', ')}`); |
||||||
|
console.log(`文件大小: ${icoBuffer.length} bytes`); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 将多个 PNG buffer 合并为 ICO 格式的 Buffer |
||||||
|
*/ |
||||||
|
function createIcoFromPngs(pngBuffers, sizes) { |
||||||
|
const imageCount = sizes.length; |
||||||
|
|
||||||
|
// 计算各部分大小
|
||||||
|
const headerSize = 6; // ICO 头部
|
||||||
|
const dirEntrySize = 16; // 每个目录条目
|
||||||
|
const dirSize = dirEntrySize * imageCount; |
||||||
|
|
||||||
|
let dataOffset = headerSize + dirSize; |
||||||
|
|
||||||
|
// 构建目录条目
|
||||||
|
const dirEntries = []; |
||||||
|
for (const size of sizes) { |
||||||
|
const pngData = pngBuffers[size]; |
||||||
|
const dataSize = pngData.length; |
||||||
|
|
||||||
|
// Width/Height: 0 表示 256
|
||||||
|
const w = size >= 256 ? 0 : size; |
||||||
|
const h = size >= 256 ? 0 : size; |
||||||
|
|
||||||
|
dirEntries.push({ |
||||||
|
width: w, |
||||||
|
height: h, |
||||||
|
colorCount: 0, |
||||||
|
reserved: 0, |
||||||
|
planes: 1, |
||||||
|
bitCount: 32, |
||||||
|
dataSize: dataSize, |
||||||
|
offset: dataOffset |
||||||
|
}); |
||||||
|
|
||||||
|
dataOffset += dataSize; |
||||||
|
} |
||||||
|
|
||||||
|
// 计算总大小
|
||||||
|
let totalSize = headerSize + dirSize; |
||||||
|
for (const size of sizes) { |
||||||
|
totalSize += pngBuffers[size].length; |
||||||
|
} |
||||||
|
|
||||||
|
// 构建 ICO 二进制数据
|
||||||
|
const buffer = Buffer.alloc(totalSize); |
||||||
|
let pos = 0; |
||||||
|
|
||||||
|
// ICO 头部 (6 bytes)
|
||||||
|
buffer.writeUInt16LE(0, pos); pos += 2; // Reserved
|
||||||
|
buffer.writeUInt16LE(1, pos); pos += 2; // Type: 1 = ICO
|
||||||
|
buffer.writeUInt16LE(imageCount, pos); pos += 2; // Image count
|
||||||
|
|
||||||
|
// 目录条目
|
||||||
|
for (const entry of dirEntries) { |
||||||
|
buffer.writeUInt8(entry.width, pos); pos += 1; |
||||||
|
buffer.writeUInt8(entry.height, pos); pos += 1; |
||||||
|
buffer.writeUInt8(entry.colorCount, pos); pos += 1; |
||||||
|
buffer.writeUInt8(entry.reserved, pos); pos += 1; |
||||||
|
buffer.writeUInt16LE(entry.planes, pos); pos += 2; |
||||||
|
buffer.writeUInt16LE(entry.bitCount, pos); pos += 2; |
||||||
|
buffer.writeUInt32LE(entry.dataSize, pos); pos += 4; |
||||||
|
buffer.writeUInt32LE(entry.offset, pos); pos += 4; |
||||||
|
} |
||||||
|
|
||||||
|
// 图像数据
|
||||||
|
for (const size of sizes) { |
||||||
|
const pngData = pngBuffers[size]; |
||||||
|
pngData.copy(buffer, pos); |
||||||
|
pos += pngData.length; |
||||||
|
} |
||||||
|
|
||||||
|
return buffer; |
||||||
|
} |
||||||
|
|
||||||
|
main().catch(err => { |
||||||
|
console.error('错误:', err); |
||||||
|
process.exit(1); |
||||||
|
}); |
||||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
@ -1 +1 @@ |
|||||||
1049 |
1051 |
||||||
Loading…
Reference in new issue