新增mapped_file,同时字体加载使用内存映射来避免加载整个字体到内存中
This commit is contained in:
parent
e6a7254598
commit
6ea4ee9a78
177
src/core/misc/mapped_file.cpp
Normal file
177
src/core/misc/mapped_file.cpp
Normal 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
|
76
src/core/misc/mapped_file.h
Normal file
76
src/core/misc/mapped_file.h
Normal 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
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user