You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
5.8 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#pragma once
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
#include "iconv.h"
#include "uemf.h"
#include <stdarg.h>
#define SAFEPRINTF_SUCCESS 0
#define SAFEPRINTF_ERROR -1
static const char * HexStringToByteArray(string hexString)
{
size_t length = hexString.length();
char * byteArray = new char[length / 2];
for (int i = 0; i < length; i += 2)
{
//byteArray[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
// 将每一对十六进制字符转换成一个字节
byteArray[i / 2] = std::stoi(hexString.substr(i, 2), nullptr, 16);
}
return byteArray;
}
// 读取出文件中的所有内容
static std::vector<BYTE> ReadFullFileData(CFile &fr)
{
ULONGLONG fileSize = fr.GetLength();
std::vector<BYTE> buffer(fileSize);
ULONGLONG left = fileSize;
ULONGLONG nread = 0;
BYTE* ptr = buffer.data();
while (left > 0)
{
UINT n = static_cast<UINT>(min(UINT_MAX, left));
if (fr.Read(ptr, n) != n)
{
return {};
}
left -= n;
ptr += n;
}
return buffer;
}
//string->wstring
static std::wstring UTF8ToWide(const char* utf8Str) {
if (!utf8Str) return L"";
int wideLen = MultiByteToWideChar(CP_ACP, 0, utf8Str, -1, nullptr, 0);
if (wideLen <= 0) return L"";
std::wstring wideStr(wideLen, 0);
MultiByteToWideChar(CP_UTF8, 0, utf8Str, -1, &wideStr[0], wideLen);
wideStr.resize(wideLen - 1); // 去除末尾的 null 字符
return wideStr;
}
inline char *utf8_to_gbk(const char *utf8_str)
{
if (!utf8_str) return NULL;
// 计算输入字符串的长度
size_t utf8_len = strlen(utf8_str) + 1; // +1 为 null 结束符
size_t gbk_len = utf8_len * 2; // GBK 最大长度估算
// 分配输出缓冲区
char *gbk_str = (char *)malloc(gbk_len);
if (!gbk_str) return NULL;
char *in_buf = (char *)utf8_str;
char *out_buf = gbk_str;
// iconv 初始化
iconv_t conv = iconv_open("GBK", "UTF-8");
if (conv == (iconv_t)-1)
{
free(gbk_str);
return NULL;
}
size_t in_bytes_left = utf8_len;
size_t out_bytes_left = gbk_len;
// 转换
size_t result = iconv(conv, &in_buf, &in_bytes_left, &out_buf, &out_bytes_left);
iconv_close(conv);
if (result == (size_t)-1)
{
free(gbk_str);
return NULL; // 转换失败
}
// 计算实际长度并添加 null 结束符
size_t out_len = gbk_len - out_bytes_left;
gbk_str[out_len] = '\0';
return gbk_str;
}
inline char *gbk_to_utf8(const char *gbk_str)
{
if (!gbk_str) return NULL;
// 计算输入字符串的长度
size_t gbk_len = strlen(gbk_str) + 1; // +1 为 null 结束符
size_t utf8_len = gbk_len * 3; // UTF-8 最大长度估算每个GBK字符可能变成最多3个UTF-8字符
// 分配输出缓冲区
char *utf8_str = (char *)malloc(utf8_len);
if (!utf8_str) return NULL;
char *in_buf = (char *)gbk_str;
char *out_buf = utf8_str;
// iconv 初始化
iconv_t conv = iconv_open("UTF-8", "GBK");
if (conv == (iconv_t)-1)
{
free(utf8_str);
return NULL;
}
size_t in_bytes_left = gbk_len;
size_t out_bytes_left = utf8_len;
// 转换
size_t result = iconv(conv, &in_buf, &in_bytes_left, &out_buf, &out_bytes_left);
iconv_close(conv);
if (result == (size_t)-1)
{
free(utf8_str);
return NULL; // 转换失败
}
// 计算实际长度并添加 null 结束符
size_t out_len = utf8_len - out_bytes_left;
utf8_str[out_len] = '\0';
return utf8_str;
}
/**
\brief Find a (sub)string in a caseinvariant manner, used for locating "Narrow" in font name
\return Returns -1 if no match, else returns the position (numbered from 0) of the first character of the match.
\param string Text to search
\param sub Text to find
*/
inline int TR_findcasesub(const char *string, const char *sub)
{
int i, j;
int match = 0;
for (i = 0; string[i]; i++)
{
for (match = 1, j = 0; sub[j] && string[i + j]; j++)
{
if (toupper(sub[j]) != toupper(string[i + j]))
{
match = 0;
break;
}
}
if (match && !sub[j])
{
break; /* matched over the entire substring */
}
}
return((match ? i : -1));
}
inline void U_swap4(void *ul, unsigned int count)
{
uint8_t ctmp;
uint8_t *cl = (uint8_t *)ul;
for (; count; count--, cl += 4)
{
ctmp = *(cl + 0);
*(cl + 0) = *(cl + 3);
*(cl + 3) = ctmp;
ctmp = *(cl + 1);
*(cl + 1) = *(cl + 2);
*(cl + 2) = ctmp;
}
}
/* Useful composition macros */
constexpr double SP_COLOR_U_TO_F(uint32_t v)
{
return v / 255.0;
}
constexpr uint32_t SP_COLOR_F_TO_U(double v)
{
return (unsigned int)(v * 255. + .5);
}
constexpr uint32_t SP_RGBA32_R_U(uint32_t v)
{
return (v >> 24) & 0xff;
}
constexpr uint32_t SP_RGBA32_G_U(uint32_t v)
{
return (v >> 16) & 0xff;
}
constexpr uint32_t SP_RGBA32_B_U(uint32_t v)
{
return (v >> 8) & 0xff;
}
constexpr uint32_t SP_RGBA32_A_U(uint32_t v)
{
return v & 0xff;
}
constexpr double SP_RGBA32_R_F(uint32_t v)
{
return SP_COLOR_U_TO_F(SP_RGBA32_R_U(v));
}
constexpr double SP_RGBA32_G_F(uint32_t v)
{
return SP_COLOR_U_TO_F(SP_RGBA32_G_U(v));
}
constexpr double SP_RGBA32_B_F(uint32_t v)
{
return SP_COLOR_U_TO_F(SP_RGBA32_B_U(v));
}
constexpr double SP_RGBA32_A_F(uint32_t v)
{
return SP_COLOR_U_TO_F(SP_RGBA32_A_U(v));
}
constexpr uint32_t SP_RGBA32_U_COMPOSE(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
{
return ((b & 0xff) << 24) | ((g & 0xff) << 16) | ((r & 0xff) << 8) | (a & 0xff);
}
constexpr uint32_t SP_RGBA32_F_COMPOSE(double r, double g, double b, double a)
{
return SP_RGBA32_U_COMPOSE(SP_COLOR_F_TO_U(r), SP_COLOR_F_TO_U(g), SP_COLOR_F_TO_U(b), SP_COLOR_F_TO_U(a));
}
constexpr uint32_t SP_RGBA32_C_COMPOSE(uint32_t c, double o)
{
return SP_RGBA32_U_COMPOSE(SP_RGBA32_R_U(c), SP_RGBA32_G_U(c), SP_RGBA32_B_U(c), SP_COLOR_F_TO_U(o));
}
constexpr uint32_t U_RGB_COMPOSE(U_COLORREF c)
{
return SP_RGBA32_U_COMPOSE(U_RGBAGetR(c), U_RGBAGetG(c), U_RGBAGetB(c), 0xff);
}
constexpr uint32_t U_RGBA_COMPOSE(U_COLORREF c)
{
return SP_RGBA32_U_COMPOSE(U_RGBAGetR(c), U_RGBAGetG(c), U_RGBAGetB(c), U_RGBAGetA(c));
}
template<size_t N>
int safeprintf(char(&buf)[N], const char* fmt, ...) {
va_list args;
va_start(args, fmt);
auto len = vsnprintf(buf, N, fmt, args);
va_end(args);
return len;
}