修改为filesystem作为路径参数类型

This commit is contained in:
Nanako 2025-04-01 17:57:17 +08:00
parent 7206c04a71
commit 4036ee2ded
11 changed files with 151 additions and 24 deletions

View File

@ -16,7 +16,7 @@ int main(int argc, char* argv[]) {
manager.add_font(L"C:/Windows/Fonts/seguiemj.ttf");
const auto& text_block = std::make_shared<mtext_block>();
text_block->set_text(U"Hello, World! 你好,世界!🥶😅😎");
text_block->set_text(U"Hello, World! 你好,世界!🥶");
const auto& text_block2 = std::make_shared<mtext_block>();
text_block2->set_text(U"Hello, World!");

View File

@ -3,6 +3,7 @@
#include <string>
#include <cstddef>
#include <memory>
#include <filesystem>
class mapped_file {
public:
@ -12,7 +13,7 @@ public:
mapped_file(const mapped_file&) = delete;
mapped_file& operator=(const mapped_file&) = delete;
virtual bool map_file(const std::wstring& filename) = 0;
virtual bool map_file(const std::filesystem::path& filename) = 0;
virtual void unmap() = 0;
[[nodiscard]] virtual const void* get_data() const = 0;

View File

@ -18,7 +18,7 @@ public:
mapped_file_unix(mapped_file_unix&& other) noexcept;
mapped_file_unix& operator=(mapped_file_unix&& other) noexcept;
bool map_file(const std::wstring& filename);
bool map_file(const std::filesystem::path& filename);
void unmap();
[[nodiscard]] const void* get_data() const { return data; }
@ -61,7 +61,7 @@ mapped_file_unix& mapped_file_unix::operator=(mapped_file_unix&& other) noexcept
return *this;
}
bool mapped_file_unix::map_file(const std::wstring& filename) {
bool mapped_file_unix::map_file(const std::filesystem::path& filename) {
cleanup();
std::string utf8_filename(filename.begin(), filename.end());

View File

@ -17,7 +17,7 @@ public:
mapped_file_win(mapped_file_win&& other) noexcept;
mapped_file_win& operator=(mapped_file_win&& other) noexcept;
bool map_file(const std::wstring& filename) override;
bool map_file(const std::filesystem::path& filename) override;
void unmap() override;
[[nodiscard]] const void* get_data() const override { return data_; }
@ -68,7 +68,7 @@ mapped_file_win& mapped_file_win::operator=(mapped_file_win&& other) noexcept {
return *this;
}
bool mapped_file_win::map_file(const std::wstring& filename) {
bool mapped_file_win::map_file(const std::filesystem::path& filename) {
cleanup();
file_handle_ = CreateFileW(

View File

@ -12,7 +12,7 @@ font_face_t::font_face_t() {
// 延迟初始化渲染器,直到加载字体
}
bool font_face_t::load_from_file(const std::wstring& font_path) {
bool font_face_t::load_from_file(const std::filesystem::path& font_path) {
// 读取字体文件数据
if (!load_font_data(font_path)) {
return false;
@ -260,7 +260,7 @@ void font_face_t::init_renderers() {
#endif
}
bool font_face_t::load_font_data(const std::wstring& font_path) {
bool font_face_t::load_font_data(const std::filesystem::path& font_path) {
// 创建内存映射文件
font_data_ = mapped_file::create();
if (!font_data_ || !font_data_->map_file(font_path)) {

View File

@ -9,6 +9,7 @@
#include "stb_truetype.h"
#include "misc/mapped_file/mapped_file.h"
#include "font_renderer/font_renderer.h"
#include <filesystem>
/**
* @class font_face_t
@ -43,7 +44,7 @@ public:
* @param font_path
* @return
*/
bool load_from_file(const std::wstring& font_path);
bool load_from_file(const std::filesystem::path& font_path);
//--------------------------------------------------------------------------
// 字体度量信息
@ -227,7 +228,7 @@ private:
* @param font_path
* @return
*/
bool load_font_data(const std::wstring& font_path);
bool load_font_data(const std::filesystem::path& font_path);
/**
* @brief

View File

@ -1,5 +1,7 @@
#include "colr_renderer.h"
#include <fstream>
#include "font/font_utils.h"
#include "font/stb_truetype.h"
@ -8,6 +10,125 @@ bool colr_renderer_t::supports_font(const uint8_t* font_data, int font_offset) c
font::find_table_offset(font_data, font_offset, "CPAL") != 0;
}
void save_bitmap(const std::string& filename, const color_emoji_bitmap_t& bitmap) {
// 检查输入有效性
if (bitmap.width <= 0 || bitmap.height <= 0 || bitmap.data.empty()) {
throw std::invalid_argument("Invalid bitmap data");
}
if (bitmap.data.size() < static_cast<size_t>(bitmap.width * bitmap.height * 4)) {
throw std::invalid_argument("Bitmap data size doesn't match dimensions");
}
#pragma pack(push, 1)
// BMP文件头结构
struct BITMAPFILEHEADER {
uint16_t bfType; // 文件类型,必须是"BM"0x4D42
uint32_t bfSize; // 文件大小
uint16_t bfReserved1; // 保留必须为0
uint16_t bfReserved2; // 保留必须为0
uint32_t bfOffBits; // 从文件开始到像素数据的偏移量
};
// BMP V4信息头结构**支持Alpha通道**
struct BITMAPV4HEADER {
uint32_t biSize; // 信息头大小
int32_t biWidth; // 图像宽度
int32_t biHeight; // 图像高度
uint16_t biPlanes; // 颜色平面数必须为1
uint16_t biBitCount; // 每个像素的位数
uint32_t biCompression; // 压缩方式
uint32_t biSizeImage; // 图像大小
int32_t biXPelsPerMeter; // 水平分辨率
int32_t biYPelsPerMeter; // 垂直分辨率
uint32_t biClrUsed; // 使用的颜色索引数
uint32_t biClrImportant; // 重要的颜色索引数
uint32_t bV4RedMask; // 红色掩码
uint32_t bV4GreenMask; // 绿色掩码
uint32_t bV4BlueMask; // 蓝色掩码
uint32_t bV4AlphaMask; // Alpha掩码
uint32_t bV4CSType; // 颜色空间类型
uint8_t bV4Endpoints[36]; // 端点
uint32_t bV4GammaRed; // 红色Gamma
uint32_t bV4GammaGreen; // 绿色Gamma
uint32_t bV4GammaBlue; // 蓝色Gamma
};
#pragma pack(pop)
// 常量定义
const uint32_t BI_BITFIELDS = 3; // 位域压缩
const uint16_t BMP_SIGNATURE = 0x4D42; // "BM"
// 计算文件大小
int rowSize = ((bitmap.width * 32 + 31) / 32) * 4; // 每行字节数必须是4的倍数
int dataSize = rowSize * bitmap.height;
int fileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPV4HEADER) + dataSize;
// 准备文件头
BITMAPFILEHEADER fileHeader = {0};
fileHeader.bfType = BMP_SIGNATURE;
fileHeader.bfSize = fileSize;
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPV4HEADER);
// 准备信息头
BITMAPV4HEADER infoHeader = {0};
infoHeader.biSize = sizeof(BITMAPV4HEADER);
infoHeader.biWidth = bitmap.width;
infoHeader.biHeight = bitmap.height; // **正值表示图像从下到上存储**
infoHeader.biPlanes = 1;
infoHeader.biBitCount = 32; // 32位每像素BGRA
infoHeader.biCompression = BI_BITFIELDS;
infoHeader.biSizeImage = dataSize;
infoHeader.biXPelsPerMeter = 0;
infoHeader.biYPelsPerMeter = 0;
infoHeader.biClrUsed = 0;
infoHeader.biClrImportant = 0;
infoHeader.bV4RedMask = 0x00FF0000; // R在第3字节
infoHeader.bV4GreenMask = 0x0000FF00; // G在第2字节
infoHeader.bV4BlueMask = 0x000000FF; // B在第1字节
infoHeader.bV4AlphaMask = 0xFF000000; // A在第4字节
infoHeader.bV4CSType = 0; // LCS_CALIBRATED_RGB
// 打开文件
std::ofstream file(filename, std::ios::binary);
if (!file) {
throw std::runtime_error("Failed to open file for writing: " + filename);
}
// 写入文件头
file.write(reinterpret_cast<const char*>(&fileHeader), sizeof(fileHeader));
// 写入信息头
file.write(reinterpret_cast<const char*>(&infoHeader), sizeof(infoHeader));
// 转换并写入像素数据
// **BMP存储顺序是从下到上从左到右且是BGRA而不是RGBA**
std::vector<uint8_t> bmpData(dataSize, 0); // 初始化为0
for (int y = 0; y < bitmap.height; y++) {
for (int x = 0; x < bitmap.width; x++) {
// 计算源数据和目标数据的索引
size_t srcIndex = (y * bitmap.width + x) * 4; // RGBA
size_t destIndex = ((bitmap.height - 1 - y) * rowSize) + (x * 4); // BGRA, 从下到上
// RGBA -> BGRA
bmpData[destIndex + 0] = bitmap.data[srcIndex + 2]; // B <- R
bmpData[destIndex + 1] = bitmap.data[srcIndex + 1]; // G <- G
bmpData[destIndex + 2] = bitmap.data[srcIndex + 0]; // R <- B
bmpData[destIndex + 3] = bitmap.data[srcIndex + 3]; // A <- A
}
}
// 写入像素数据
file.write(reinterpret_cast<const char*>(bmpData.data()), dataSize);
if (!file.good()) {
throw std::runtime_error("Error occurred while writing to file: " + filename);
}
}
std::optional<color_emoji_bitmap_t> colr_renderer_t::render_emoji(
const stbtt_fontinfo& font_info,
const uint8_t* font_data,
@ -160,6 +281,10 @@ std::optional<color_emoji_bitmap_t> colr_renderer_t::render_emoji(
layer_width, layer_height, layer_width,
scale, scale, layer_glyph_id);
// 测试保存BMP
save_bitmap(std::to_string(i) + ".bmp", bitmap);
// 计算图层在最终位图中的位置
const int offset_x = layer_x0 - x0;
const int offset_y = layer_y0 - y0;
@ -189,9 +314,9 @@ std::optional<color_emoji_bitmap_t> colr_renderer_t::render_emoji(
// 对于细节图层(如眼睛),增强其影响
float enhanced_alpha = src_alpha;
if (palette_entry_index > 0 && src_alpha > 0) { // 非底色图层且有透明度
enhanced_alpha = std::min(src_alpha * 1.2f, 1.0f); // 稍微增强
}
// if (palette_entry_index > 0 && src_alpha > 0) { // 非底色图层且有透明度
// enhanced_alpha = std::min(src_alpha * 1.2f, 1.0f); // 稍微增强
// }
const float dst_alpha = bitmap.data[dst_idx + 3] / 255.0f;
const float out_alpha = enhanced_alpha + dst_alpha * (1.0f - enhanced_alpha);

View File

@ -1,5 +1,7 @@
#include "font_system.h"
#include "emoji_detector.h"
void font_manager::destroy() {
fonts_.clear();
emoji_font_ids_.clear();
@ -8,7 +10,7 @@ void font_manager::destroy() {
next_font_id_ = 0;
}
int font_manager::add_font(const std::wstring& in_font_path, const std::string& in_font_type) {
int font_manager::add_font(const std::filesystem::path& in_font_path, const std::string& in_font_type) {
auto font = std::make_shared<font_face_t>();
if (!font->load_from_file(in_font_path)) {
return -1;

View File

@ -5,12 +5,10 @@
#include <unordered_map>
#include <optional>
#include "emoji_detector.h"
#include "font_face.h"
#include "atlas/bitmap_glyph_atlas.h"
#include "atlas/color_emoji_atlas.h"
#include "atlas/font_atlas.h"
#include "atlas/font_atlas_manager.h"
#include <filesystem>
/**
* @class font_manager
@ -48,7 +46,7 @@ public:
* @param in_font_type (regular, bold, italic, emoji等)
* @return ID-1
*/
int add_font(const std::wstring& in_font_path, const std::string& in_font_type = "regular");
int add_font(const std::filesystem::path& in_font_path, const std::string& in_font_type = "regular");
/**
* @brief

View File

@ -142,10 +142,10 @@ struct text_layout_t {
atlas_region_t region; // 纹理图集区域
};
std::vector<glyph_position_t> glyphs; // 所有字形位置
Eigen::Vector2f total_size; // 文本总尺寸
float ascent; // 上升高度
float baseline = 0.0f; // 基线位置
std::vector<glyph_position_t> glyphs; // 所有字形位置
Eigen::Vector2f total_size; // 文本总尺寸
float ascent; // 上升高度
float baseline; // 基线位置
};
/**

View File

@ -42,8 +42,8 @@ private:
void update_layout();
std::u32string text_;
text_layout_t layout_;
float font_size_ = 24.0f * 1.5f;
text_layout_t layout_{};
float font_size_ = 15.0f;
float line_spacing_ = 1.2f;
float max_width_ = 0.0f;
std::shared_ptr<font_face_t> font_;