mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-05 07:57:27 +02:00
Replace resource tools with python scripts
May fix pipeline failures on ghactions where makeico or toarray just exit with a non-zero status for no reason. Also makes it easier (possible, rather) to build TPT using a cross-compiling msvc toolchain on windows; you can't have two different msvc toolchains in PATH on windows because of course you can't. toarray had been python before, maybe I converted it to cpp to avoid pulling in python as a dependency, I'm not sure. With android vanilla development (hopefully) gaining traction soon, we'll be relying anyway on helper scripts I've written in python, so python will be a dependency sooner or later. Meson implicitly makes python a dependency, but there could be Meson implementations out there that don't rely on python, who knows.
This commit is contained in:
@@ -6,9 +6,6 @@ project(
|
||||
'c_std=c99',
|
||||
'cpp_std=c++17',
|
||||
'cpp_rtti=false',
|
||||
'build.c_std=c99', # used by to_array
|
||||
'build.cpp_std=c++17', # used by to_array
|
||||
'build.cpp_rtti=false', # used by to_array
|
||||
],
|
||||
meson_version: '>=0.64.0',
|
||||
)
|
||||
@@ -20,9 +17,9 @@ endif
|
||||
|
||||
fs = import('fs')
|
||||
to_array = generator(
|
||||
executable('toarray', sources: 'resources/ToArray.cpp', native: true),
|
||||
find_program('python'),
|
||||
output: [ '@PLAINNAME@.cpp', '@PLAINNAME@.h' ],
|
||||
arguments: [ '@OUTPUT0@', '@OUTPUT1@', '@INPUT@', '@EXTRA_ARGS@' ]
|
||||
arguments: [ join_paths(meson.current_source_dir(), 'resources/to-array.py'), '@OUTPUT0@', '@OUTPUT1@', '@INPUT@', '@EXTRA_ARGS@' ]
|
||||
)
|
||||
|
||||
render_icons_with_inkscape = get_option('render_icons_with_inkscape')
|
||||
|
@@ -1,137 +0,0 @@
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
static void writeU32LE(uint8_t *dest, uint32_t value)
|
||||
{
|
||||
dest[0] = uint8_t( value & 0xFF);
|
||||
dest[1] = uint8_t((value >> 8) & 0xFF);
|
||||
dest[2] = uint8_t((value >> 16) & 0xFF);
|
||||
dest[3] = uint8_t((value >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
static uint32_t readU32BE(const uint8_t *src)
|
||||
{
|
||||
return uint32_t(src[3]) |
|
||||
(uint32_t(src[2]) << 8) |
|
||||
(uint32_t(src[1]) << 16) |
|
||||
(uint32_t(src[0]) << 24);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 3)
|
||||
{
|
||||
std::cerr << "usage: " << argv[0] << " OUTPUT INPUT..." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
auto images = argc - 2;
|
||||
if (images > 255)
|
||||
{
|
||||
std::cerr << "too many images specified" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
std::string outputPath = argv[1];
|
||||
std::ofstream output(outputPath, std::ios::binary);
|
||||
auto outputFailure = [&outputPath](std::string action) {
|
||||
std::cerr << "failed to " << action << " " << outputPath << ": " << strerror(errno) << std::endl;
|
||||
exit(1);
|
||||
};
|
||||
if (!output)
|
||||
{
|
||||
outputFailure("open");
|
||||
}
|
||||
std::vector<char> header(6 + images * 16, 0);
|
||||
auto writeHeader = [&header, &output, &outputFailure]() {
|
||||
output.seekp(0, std::ios_base::beg);
|
||||
output.write(&header[0], header.size());
|
||||
if (!output)
|
||||
{
|
||||
outputFailure("write");
|
||||
}
|
||||
};
|
||||
writeHeader(); // make space for header
|
||||
auto *headerU8 = reinterpret_cast<uint8_t *>(&header[0]);
|
||||
headerU8[2] = 1;
|
||||
headerU8[4] = images;
|
||||
for (auto image = 0; image < images; ++image)
|
||||
{
|
||||
std::string inputPath = argv[2 + image];
|
||||
std::ifstream input(inputPath, std::ios::binary);
|
||||
auto inputFailure = [&inputPath](std::string action) {
|
||||
std::cerr << "failed to " << action << " " << inputPath << ": " << strerror(errno) << std::endl;
|
||||
exit(1);
|
||||
};
|
||||
auto imageFailure = [&inputPath](std::string failure) {
|
||||
std::cerr << "failed to process " << inputPath << ": " << failure << std::endl;
|
||||
exit(1);
|
||||
};
|
||||
if (!input)
|
||||
{
|
||||
inputFailure("open");
|
||||
}
|
||||
std::vector<char> buf;
|
||||
input.seekg(0, std::ios_base::end);
|
||||
buf.resize(input.tellg());
|
||||
input.seekg(0, std::ios_base::beg);
|
||||
input.read(&buf[0], buf.size());
|
||||
if (!input)
|
||||
{
|
||||
inputFailure("read");
|
||||
}
|
||||
auto *bufU8 = reinterpret_cast<uint8_t *>(&buf[0]);
|
||||
if (buf.size() < 0x21 ||
|
||||
readU32BE(&bufU8[0]) != UINT32_C(0x89504E47) ||
|
||||
readU32BE(&bufU8[4]) != UINT32_C(0x0D0A1A0A) ||
|
||||
bufU8[0x18] != 8 ||
|
||||
bufU8[0x19] != 6)
|
||||
{
|
||||
imageFailure("not a 32bpp RGBA PNG");
|
||||
}
|
||||
auto writeOffset = output.tellp();
|
||||
output.write(&buf[0], buf.size());
|
||||
if (!output)
|
||||
{
|
||||
outputFailure("write");
|
||||
}
|
||||
auto width = readU32BE(&bufU8[0x10]);
|
||||
auto height = readU32BE(&bufU8[0x14]);
|
||||
if (width == 256)
|
||||
{
|
||||
width = 0;
|
||||
}
|
||||
if (width > 255)
|
||||
{
|
||||
imageFailure("width exceeds U8 limit");
|
||||
}
|
||||
if (height == 256)
|
||||
{
|
||||
height = 0;
|
||||
}
|
||||
if (height > 255)
|
||||
{
|
||||
imageFailure("height exceeds U8 limit");
|
||||
}
|
||||
auto *entryU8 = headerU8 + 6 + image * 16;
|
||||
entryU8[0] = width;
|
||||
entryU8[1] = height;
|
||||
entryU8[4] = 1;
|
||||
entryU8[6] = 32;
|
||||
if (buf.size() > UINT32_MAX)
|
||||
{
|
||||
imageFailure("data size exceeds U32 limit");
|
||||
}
|
||||
writeU32LE(&entryU8[8], uint32_t(buf.size()));
|
||||
if (writeOffset > UINT32_MAX)
|
||||
{
|
||||
std::cerr << "output data size exceeds U32 limit" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
writeU32LE(&entryU8[12], uint32_t(writeOffset));
|
||||
}
|
||||
writeHeader(); // actually write it out
|
||||
return 0;
|
||||
}
|
@@ -1,52 +0,0 @@
|
||||
#include <fstream>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 5)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
auto *outputCppPath = argv[1];
|
||||
auto *outputHPath = argv[2];
|
||||
auto *inputAnyPath = argv[3];
|
||||
auto *symbolName = argv[4];
|
||||
std::ifstream inputAny(inputAnyPath, std::ios::binary);
|
||||
std::ofstream outputCpp(outputCppPath);
|
||||
if (!outputCpp)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
outputCpp << "#include \"" << outputHPath << "\"\nconst unsigned char " << symbolName << "[] = { ";
|
||||
auto dataLen = 0U;
|
||||
while (true)
|
||||
{
|
||||
char ch;
|
||||
inputAny.read(&ch, 1);
|
||||
if (inputAny.eof())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (!inputAny)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
outputCpp << (unsigned int)(unsigned char)(ch) << ", ";
|
||||
dataLen += 1;
|
||||
}
|
||||
outputCpp << " }; const unsigned int " << symbolName << "_size = " << dataLen << ";\n";
|
||||
if (!outputCpp)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
std::ofstream outputH(outputHPath);
|
||||
if (!outputH)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
outputH << "#pragma once\nextern const unsigned char " << symbolName << "[]; extern const unsigned int " << symbolName << "_size;\n";
|
||||
if (!outputH)
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
return 0;
|
||||
}
|
38
resources/make-ico.py
Normal file
38
resources/make-ico.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import struct
|
||||
import sys
|
||||
|
||||
(
|
||||
script,
|
||||
output_ico,
|
||||
*input_pngs,
|
||||
) = sys.argv
|
||||
|
||||
input_pngs_size = len(input_pngs)
|
||||
assert(input_pngs_size <= 255)
|
||||
|
||||
ico_header = b''
|
||||
ico_data = b''
|
||||
data_offset = 6 + 16 * input_pngs_size
|
||||
for input_png in input_pngs:
|
||||
with open(input_png, 'rb') as input_png_f:
|
||||
data = input_png_f.read()
|
||||
data_size = len(data)
|
||||
assert(data_size >= 0x21)
|
||||
magic, width, height, bit_depth, color_type = struct.unpack('>QxxxxxxxxLLBBxxxxxxx', data[0 : 0x21])
|
||||
assert(magic == 0x89504E470D0A1A0A)
|
||||
assert(width <= 256)
|
||||
assert(height <= 256)
|
||||
assert(bit_depth == 8)
|
||||
assert(color_type == 6)
|
||||
if width == 256:
|
||||
width = 0
|
||||
if height == 256:
|
||||
height = 0
|
||||
ico_header += struct.pack('<BBxxHHLL', width, height, 1, 32, data_size, data_offset)
|
||||
data_offset += data_size
|
||||
ico_data += data
|
||||
|
||||
with open(output_ico, 'wb') as output_ico_f:
|
||||
output_ico_f.write(struct.pack('<xxHH', 1, input_pngs_size))
|
||||
output_ico_f.write(ico_header)
|
||||
output_ico_f.write(ico_data)
|
@@ -42,7 +42,6 @@ if host_platform == 'windows'
|
||||
icon_cps_ico_path = ''
|
||||
winutf8_xml_path = ''
|
||||
if windows_icons
|
||||
make_ico = executable('makeico', sources: 'MakeIco.cpp', native: true)
|
||||
generated_win_icos = {}
|
||||
win_icos = {
|
||||
'icon_exe': [ 'icon_exe', 'icon_exe_48', 'icon_exe_32', 'icon_exe_16' ],
|
||||
@@ -50,7 +49,8 @@ if host_platform == 'windows'
|
||||
}
|
||||
foreach key, icons : win_icos
|
||||
command = [
|
||||
make_ico,
|
||||
find_program('python'),
|
||||
join_paths(meson.current_source_dir(), 'make-ico.py'),
|
||||
'@OUTPUT@',
|
||||
]
|
||||
foreach ikey : icons
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include "@RESOUCE_H@"
|
||||
#include <winuser.h>
|
||||
#include <winver.h>
|
||||
#include <ntdef.h>
|
||||
// #include <ntdef.h> // maybe not needed?
|
||||
|
||||
#define HAVE_ICONS @HAVE_ICONS@
|
||||
#define HAVE_UTF8CP @HAVE_UTF8CP@
|
||||
|
28
resources/to-array.py
Normal file
28
resources/to-array.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import sys
|
||||
|
||||
(
|
||||
script,
|
||||
output_cpp_path,
|
||||
output_h_path,
|
||||
input_path,
|
||||
symbol_name,
|
||||
) = sys.argv
|
||||
|
||||
with open(input_path, 'rb') as input_f:
|
||||
data = input_f.read()
|
||||
data_size = len(data)
|
||||
bytes_str = ', '.join([ str(ch) for ch in data ])
|
||||
|
||||
with open(output_cpp_path, 'w') as output_cpp_f:
|
||||
output_cpp_f.write(f'''
|
||||
#include "{output_h_path}"
|
||||
const unsigned char {symbol_name}[] = {{ {bytes_str} }};
|
||||
const unsigned int {symbol_name}_size = {data_size};
|
||||
''')
|
||||
|
||||
with open(output_h_path, 'w') as output_h_f:
|
||||
output_h_f.write(f'''
|
||||
#pragma once
|
||||
extern const unsigned char {symbol_name}[];
|
||||
extern const unsigned int {symbol_name}_size;
|
||||
''')
|
Reference in New Issue
Block a user