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

1 month ago
#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);
// <20><>ÿһ<C3BF><D2BB>ʮ<EFBFBD><CAAE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽ<EFBFBD>
byteArray[i / 2] = std::stoi(hexString.substr(i, 2), nullptr, 16);
}
return byteArray;
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD>ļ<EFBFBD><C4BC>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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); // ȥ<><C8A5>ĩβ<C4A9><CEB2> null <20>ַ<EFBFBD>
return wideStr;
}
inline char *utf8_to_gbk(const char *utf8_str)
{
if (!utf8_str) return NULL;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>ij<EFBFBD><C4B3><EFBFBD>
size_t utf8_len = strlen(utf8_str) + 1; // +1 Ϊ null <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
size_t gbk_len = utf8_len * 2; // GBK <20><><EFBFBD>󳤶ȹ<F3B3A4B6><C8B9><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
char *gbk_str = (char *)malloc(gbk_len);
if (!gbk_str) return NULL;
char *in_buf = (char *)utf8_str;
char *out_buf = gbk_str;
// iconv <20><>ʼ<EFBFBD><CABC>
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;
// ת<><D7AA>
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; // ת<><D7AA>ʧ<EFBFBD><CAA7>
}
// <20><><EFBFBD><EFBFBD>ʵ<EFBFBD>ʳ<EFBFBD><CAB3>Ȳ<EFBFBD><C8B2><EFBFBD><EFBFBD><EFBFBD> null <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>ij<EFBFBD><C4B3><EFBFBD>
size_t gbk_len = strlen(gbk_str) + 1; // +1 Ϊ null <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
size_t utf8_len = gbk_len * 3; // UTF-8 <20><><EFBFBD>󳤶ȹ<F3B3A4B6><C8B9>㣬ÿ<E3A3AC><C3BF>GBK<42>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>ܱ<EFBFBD><DCB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>3<EFBFBD><33>UTF-8<>ַ<EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
char *utf8_str = (char *)malloc(utf8_len);
if (!utf8_str) return NULL;
char *in_buf = (char *)gbk_str;
char *out_buf = utf8_str;
// iconv <20><>ʼ<EFBFBD><CABC>
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;
// ת<><D7AA>
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; // ת<><D7AA>ʧ<EFBFBD><CAA7>
}
// <20><><EFBFBD><EFBFBD>ʵ<EFBFBD>ʳ<EFBFBD><CAB3>Ȳ<EFBFBD><C8B2><EFBFBD><EFBFBD><EFBFBD> null <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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;
}