新增mapped_file,同时字体加载使用内存映射来避免加载整个字体到内存中

This commit is contained in:
Nanako 2024-12-25 11:30:31 +08:00
parent e6a7254598
commit 6ea4ee9a78
4 changed files with 259 additions and 17 deletions

View File

@ -0,0 +1,177 @@
#include "mapped_file.h"
#include <stdexcept>
#ifdef _WIN32
mapped_file_win::mapped_file_win() : data(nullptr), size(0), file_handle(INVALID_HANDLE_VALUE), mapping_handle(nullptr) {}
mapped_file_win::~mapped_file_win() {
cleanup();
}
mapped_file_win::mapped_file_win(mapped_file_win&& other) noexcept
: data(other.data), size(other.size), file_handle(other.file_handle), mapping_handle(other.mapping_handle) {
other.data = nullptr;
other.size = 0;
other.file_handle = INVALID_HANDLE_VALUE;
other.mapping_handle = nullptr;
}
mapped_file_win& mapped_file_win::operator=(mapped_file_win&& other) noexcept {
if (this == &other)
return *this;
cleanup();
data = other.data;
size = other.size;
file_handle = other.file_handle;
mapping_handle = other.mapping_handle;
other.data = nullptr;
other.size = 0;
other.file_handle = INVALID_HANDLE_VALUE;
other.mapping_handle = nullptr;
return *this;
}
bool mapped_file_win::map_file(const std::wstring& filename) {
cleanup();
file_handle = CreateFileW(
filename.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr
);
if (file_handle == INVALID_HANDLE_VALUE) {
throw std::runtime_error("Failed to open file");
}
LARGE_INTEGER file_size;
if (!GetFileSizeEx(file_handle, &file_size)) {
cleanup();
throw std::runtime_error("Failed to get file size");
}
size = static_cast<size_t>(file_size.QuadPart);
mapping_handle = CreateFileMappingW(
file_handle,
nullptr,
PAGE_READONLY,
0,
0,
nullptr
);
if (mapping_handle == nullptr) {
cleanup();
throw std::runtime_error("Failed to create file mapping");
}
data = MapViewOfFile(
mapping_handle,
FILE_MAP_READ,
0,
0,
0
);
if (data == nullptr) {
cleanup();
throw std::runtime_error("Failed to map view of file");
}
return true;
}
void mapped_file_win::cleanup() {
if (data) {
UnmapViewOfFile(data);
data = nullptr;
}
if (mapping_handle) {
CloseHandle(mapping_handle);
mapping_handle = nullptr;
}
if (file_handle != INVALID_HANDLE_VALUE) {
CloseHandle(file_handle);
file_handle = INVALID_HANDLE_VALUE;
}
size = 0;
}
void mapped_file_win::unmap() {
cleanup();
}
#else
mapped_file_unix::mapped_file_unix() : data(nullptr), size(0), fd(-1) {}
mapped_file_unix::~mapped_file_unix() {
cleanup();
}
mapped_file_unix::mapped_file_unix(mapped_file_unix&& other) noexcept
: data(other.data), size(other.size), fd(other.fd) {
other.data = nullptr;
other.size = 0;
other.fd = -1;
}
mapped_file_unix& mapped_file_unix::operator=(mapped_file_unix&& other) noexcept {
if (this != &other) {
cleanup();
data = other.data;
size = other.size;
fd = other.fd;
other.data = nullptr;
other.size = 0;
other.fd = -1;
}
return *this;
}
bool mapped_file_unix::map_file(const std::wstring& filename) {
cleanup();
std::string utf8_filename(filename.begin(), filename.end());
fd = open(utf8_filename.c_str(), O_RDONLY);
if (fd == -1) {
throw std::runtime_error("Failed to open file");
}
struct stat sb;
if (fstat(fd, &sb) == -1) {
cleanup();
throw std::runtime_error("Failed to get file size");
}
size = static_cast<size_t>(sb.st_size);
data = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (data == MAP_FAILED) {
cleanup();
throw std::runtime_error("Failed to map file");
}
return true;
}
void mapped_file_unix::cleanup() {
if (data) {
munmap(data, size);
data = nullptr;
}
if (fd != -1) {
close(fd);
fd = -1;
}
size = 0;
}
void mapped_file_unix::unmap() {
cleanup();
}
#endif

View File

@ -0,0 +1,76 @@
#pragma once
#pragma once
#include <string>
#include <cstddef>
#ifdef _WIN32
#include <windows.h>
class mapped_file_win {
public:
mapped_file_win();
~mapped_file_win();
// 禁用拷贝
mapped_file_win(const mapped_file_win&) = delete;
mapped_file_win& operator=(const mapped_file_win&) = delete;
// 允许移动
mapped_file_win(mapped_file_win&& other) noexcept;
mapped_file_win& operator=(mapped_file_win&& other) noexcept;
bool map_file(const std::wstring& filename);
void unmap();
[[nodiscard]] const void* get_data() const { return data; }
[[nodiscard]] void* get_data() { return data; }
[[nodiscard]] size_t get_size() const { return size; }
[[nodiscard]] bool is_mapped() const { return data != nullptr; }
private:
void cleanup();
void* data;
size_t size;
HANDLE file_handle;
HANDLE mapping_handle;
};
using mapped_file = mapped_file_win;
#else
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
class mapped_file_unix {
public:
mapped_file_unix();
~mapped_file_unix();
// 禁用拷贝
mapped_file_unix(const mapped_file_unix&) = delete;
mapped_file_unix& operator=(const mapped_file_unix&) = delete;
// 允许移动
mapped_file_unix(mapped_file_unix&& other) noexcept;
mapped_file_unix& operator=(mapped_file_unix&& other) noexcept;
bool map_file(const std::wstring& filename);
void unmap();
[[nodiscard]] const void* get_data() const { return data; }
[[nodiscard]] void* get_data() { return data; }
[[nodiscard]] size_t get_size() const { return size; }
[[nodiscard]] bool is_mapped() const { return data != nullptr; }
private:
void cleanup();
void* data;
size_t size;
int fd;
};
using mapped_file = mapped_file_unix;
#endif

View File

@ -46,26 +46,12 @@ bool aorii_text::initialize(const wchar_t* in_font_path, const float in_font_pix
font = new stbtt_fontinfo();
font_pixel_size = in_font_pixel_size;
font_file.map_file(in_font_path);
// 加载字体文件
FILE* font_file = nullptr;
fopen_s(&font_file, font_path_a.c_str(), "rb");
if (!font_file) {
printf("Failed to open font file\n");
return false;
}
fseek(font_file, 0, SEEK_END);
const size_t font_size = ftell(font_file);
fseek(font_file, 0, SEEK_SET);
auto* font_buffer = static_cast<uint8_t*>(malloc(font_size));
fread(font_buffer, 1, font_size, font_file);
fclose(font_file);
auto font_buffer = (uint8_t*)font_file.get_data();
if (!stbtt_InitFont(font, font_buffer, stbtt_GetFontOffsetForIndex(font_buffer, 0))) {
spdlog::error("Failed to initialize font");
free(font_buffer);
font_file.unmap();
delete font;
font = nullptr;
return false;

View File

@ -5,6 +5,8 @@
#include <unordered_map>
#include "misc/mapped_file.h"
class renderer_texture_array;
struct stbtt_fontinfo;
@ -59,6 +61,7 @@ private:
bool create_new_texture_atlas();
character_info& add_character_to_atlas(int32_t glyph_index, const wchar_t ch);
stbtt_fontinfo* font;
mapped_file font_file;
renderer_texture_array* texture_array;
const uint32_t texture_size;