mirror of
https://github.com/zhenyan121/SporeBG-Conid.git
synced 2026-04-10 06:14:08 +08:00
Improved fontmanager and textrenderer class with automatic cache cleanup
This commit is contained in:
@@ -1,44 +1,68 @@
|
||||
|
||||
#include "FontManager.h"
|
||||
#include <stdexcept>
|
||||
FontManager::FontManager() {
|
||||
|
||||
FontManager::FontManager() {
|
||||
// 构造函数:初始化字体管理器
|
||||
// m_fonts 映射表会在默认构造时初始化为空
|
||||
}
|
||||
|
||||
FontManager::~FontManager() {
|
||||
// 析构函数:清理所有加载的字体资源
|
||||
for (auto& pair : m_fonts) {
|
||||
// 关闭并释放每个字体资源
|
||||
TTF_CloseFont(pair.second);
|
||||
}
|
||||
|
||||
// 清空字体缓存表
|
||||
m_fonts.clear();
|
||||
|
||||
|
||||
}
|
||||
|
||||
TTF_Font* FontManager::loadFont(const std::string& fontID, int ptSize) {
|
||||
// 构造字体文件的完整路径
|
||||
std::string path = "assets/fonts/" + fontID;
|
||||
std::string key = fontID + std::to_string(ptSize);
|
||||
// 计算该字体在缓存中的唯一哈希键
|
||||
size_t key = makeHash(fontID, ptSize);
|
||||
|
||||
// 检查字体是否已经被加载过
|
||||
auto it = m_fonts.find(key);
|
||||
// 检查字体是否已经加载
|
||||
if (it != m_fonts.end()) {
|
||||
// 字体已缓存,直接返回缓存的字体指针
|
||||
return it->second;
|
||||
}
|
||||
|
||||
TTF_Font* font = TTF_OpenFont(path.c_str(), ptSize);
|
||||
|
||||
// 从文件中加载字体
|
||||
TTF_Font* font = TTF_OpenFont(path.c_str(), ptSize);
|
||||
if (!font) {
|
||||
throw std::runtime_error("无法加载字体: " + key);
|
||||
// 字体加载失败,抛出异常
|
||||
throw std::runtime_error("无法加载字体: " + fontID);
|
||||
}
|
||||
|
||||
// 将新加载的字体存入缓存
|
||||
m_fonts[key] = font;
|
||||
return font;
|
||||
}
|
||||
|
||||
TTF_Font* FontManager::getFont(const std::string& key, int ptSize) {
|
||||
TTF_Font* FontManager::getFont(const std::string& fontID, int ptSize) {
|
||||
// 计算该字体的哈希键
|
||||
size_t key = makeHash(fontID, ptSize);
|
||||
|
||||
// 从字体缓存中查找该键对应的字体
|
||||
auto it = m_fonts.find(key);
|
||||
if (it != m_fonts.end()) {
|
||||
// 字体已缓存,直接返回缓存的字体指针
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return loadFont(key, ptSize);;
|
||||
// 如果缓存中未找到,自动调用loadFont加载字体
|
||||
return loadFont(fontID, ptSize);
|
||||
}
|
||||
|
||||
size_t FontManager::makeHash(const std::string& fontID, int ptSize) {
|
||||
// 分别计算字体名称和大小的哈希值
|
||||
size_t h1 = std::hash<std::string>{}(fontID);
|
||||
size_t h2 = std::hash<int>{}(ptSize);
|
||||
|
||||
|
||||
// 组合两个哈希值:使用XOR运算和位左移组合两个独立的哈希值
|
||||
// 这样可以确保不同的fontID或ptSize组合都会产生不同的哈希值
|
||||
return h1 ^ (h2 << 1);
|
||||
}
|
||||
|
||||
@@ -1,26 +1,67 @@
|
||||
/**
|
||||
* @file FontManager.h
|
||||
* @brief 字体加载和管理的实现,使用SDL的ttf库扩展
|
||||
* @author zhenyan121
|
||||
* @date 2025-12-12
|
||||
*/
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3_ttf/SDL_ttf.h>
|
||||
|
||||
/**
|
||||
* @class FontManager
|
||||
* @brief 字体管理的类
|
||||
*
|
||||
* 用于加载字体,缓存字体
|
||||
* 提供接口,用与获取字体缓存
|
||||
*/
|
||||
class FontManager {
|
||||
public:
|
||||
FontManager();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
* 清理已经加载的字体资源
|
||||
*/
|
||||
~FontManager();
|
||||
|
||||
// 加载字体(路径 + 字号)
|
||||
// ptSize 为字号
|
||||
/**
|
||||
* @brief 加载字体
|
||||
* 从字体文件中加载字体并将其缓存。不同大小的字体将被独立存储。
|
||||
* @param fontID 字体文件名称的引用,不包含路径前缀
|
||||
* @param ptSize 字体的磅值大小,不同的大小会产生不同的缓存键
|
||||
* @return 返回加载字体的指针,失败时抛出std::runtime_error异常
|
||||
* @note 该函数会自动检查字体是否已缓存,如已缓存则直接返回缓存的字体
|
||||
* @throw std::runtime_error 当字体文件无法打开时抛出异常
|
||||
*/
|
||||
TTF_Font* loadFont(const std::string& fontID, int ptSize);
|
||||
|
||||
// 获取已加载的字体
|
||||
TTF_Font* getFont(const std::string& key, int ptSize);
|
||||
/**
|
||||
* @brief 获取字体
|
||||
* 获取指定字体的指针。如果字体未被加载过,将自动调用loadFont进行加载。
|
||||
* @param fontID 字体文件名称的引用,不包含路径前缀
|
||||
* @param ptSize 字体的磅值大小
|
||||
* @return 返回获取到的字体指针,保证非空;失败时会抛出异常
|
||||
* @note 该函数是获取字体的推荐方式,具有自动加载功能
|
||||
* @throw std::runtime_error 当字体加载失败时抛出异常
|
||||
*/
|
||||
TTF_Font* getFont(const std::string& fontID, int ptSize);
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
// 用哈希表存储字体
|
||||
std::unordered_map<std::string, TTF_Font*> m_fonts;
|
||||
|
||||
std::unordered_map<size_t, TTF_Font*> m_fonts; ///< 字体缓存表,使用哈希值作为键存储TTF_Font指针
|
||||
|
||||
/**
|
||||
* @brief 计算组合哈希值
|
||||
* 根据字体名称和大小计算唯一的哈希键用于缓存。采用黄金比例乘法混合算法。
|
||||
* @param fontID 字体文件名称的引用
|
||||
* @param ptSize 字体的磅值大小
|
||||
* @return 返回计算得到的哈希值,作为m_fonts字典的键
|
||||
* @note 内部实现使用XOR运算和位移组合两个独立的哈希值
|
||||
*/
|
||||
size_t makeHash(const std::string& fontID, int ptSize);
|
||||
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "TextRenderer.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
TextRenderer::TextRenderer(SDL_Renderer* renderer, FontManager* fontManager) :
|
||||
m_fontManager(fontManager),
|
||||
m_renderer(renderer)
|
||||
@@ -8,73 +9,105 @@ TextRenderer::TextRenderer(SDL_Renderer* renderer, FontManager* fontManager) :
|
||||
}
|
||||
|
||||
TextRenderer::~TextRenderer() {
|
||||
for (auto& pair : m_cache) {
|
||||
|
||||
SDL_DestroyTexture(pair.second.texture);
|
||||
|
||||
}
|
||||
m_cache.clear();
|
||||
clearCache();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TextRenderer::renderText(const std::string& text, TextStyle style, int x, int y) {
|
||||
auto key = style.hash();
|
||||
std::pair<int, int> TextRenderer::getTextSize(const std::string& text, TextStyle style) {
|
||||
auto key = makeHash(text, style);
|
||||
auto it = m_cache.find(key);
|
||||
|
||||
// 查找缓存
|
||||
if (it != m_cache.end()) {
|
||||
// 更新最后访问时间
|
||||
it->second.lastAccessTime = std::time(nullptr);
|
||||
return {it->second.width, it->second.height};
|
||||
}
|
||||
|
||||
// 创建并缓存纹理
|
||||
CachedText cached = createAndCacheTexture(text, style);
|
||||
if (!cached.texture) {
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
return {cached.width, cached.height};
|
||||
}
|
||||
|
||||
void TextRenderer::renderText(const std::string& text, TextStyle style, int x, int y) {
|
||||
auto key = makeHash(text, style);
|
||||
auto it = m_cache.find(key);
|
||||
|
||||
// 查找缓存
|
||||
if (it != m_cache.end()) {
|
||||
// 更新最后访问时间
|
||||
it->second.lastAccessTime = std::time(nullptr);
|
||||
|
||||
// 使用缓存的纹理, SDL_FRect为浮点数矩形
|
||||
SDL_FRect dest = { static_cast<float>(x), static_cast<float>(y),
|
||||
static_cast<float>(it->second.width),
|
||||
static_cast<float>(it->second.height) };
|
||||
SDL_FRect dest = { static_cast<float>(x), static_cast<float>(y),
|
||||
static_cast<float>(it->second.width),
|
||||
static_cast<float>(it->second.height) };
|
||||
|
||||
// 绘制材质 NULL 的含义:绘制整个纹理(从 (0,0) 到纹理的完整宽高) &dest 目标区域
|
||||
SDL_RenderTexture(m_renderer, it->second.texture, NULL, &dest);
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建新的纹理
|
||||
TTF_Font* font = m_fontManager->getFont(style.fontID, style.fontSize);
|
||||
if (!font) {
|
||||
SDL_Log("错误:字体未找到 %s\n", style.fontID.c_str());
|
||||
// 绘制材质 NULL 的含义:绘制整个纹理(从 (0,0) 到纹理的完整宽高) &dest 目标区域
|
||||
SDL_RenderTexture(m_renderer, it->second.texture, NULL, &dest);
|
||||
return;
|
||||
}
|
||||
// 创建文字表面
|
||||
SDL_Surface* surface = TTF_RenderText_Solid(font, text.c_str(),text.length(), style.color);
|
||||
if (!surface) {
|
||||
printf("错误:无法创建文字表面\n");
|
||||
return;
|
||||
}
|
||||
// 创建纹理
|
||||
SDL_Texture* texture = SDL_CreateTextureFromSurface(m_renderer, surface);
|
||||
if (!texture) {
|
||||
SDL_Log("错误:无法创建纹理\n");
|
||||
SDL_DestroySurface(surface);
|
||||
return;
|
||||
}
|
||||
// 保存到缓存
|
||||
CachedText cached;
|
||||
cached.texture = texture;
|
||||
cached.width = surface->w;
|
||||
cached.height = surface->h;
|
||||
m_cache[key] = cached;
|
||||
|
||||
// 创建并缓存纹理
|
||||
CachedText cached = createAndCacheTexture(text, style);
|
||||
if (!cached.texture) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 渲染
|
||||
SDL_FRect dest = { static_cast<float>(x), static_cast<float>(y),
|
||||
static_cast<float>(surface->w),
|
||||
static_cast<float>(surface->h) };
|
||||
SDL_RenderTexture(m_renderer, texture, NULL, &dest);
|
||||
|
||||
// 清理表面
|
||||
SDL_DestroySurface(surface);
|
||||
|
||||
|
||||
static_cast<float>(cached.width),
|
||||
static_cast<float>(cached.height) };
|
||||
SDL_RenderTexture(m_renderer, cached.texture, NULL, &dest);
|
||||
}
|
||||
|
||||
SDL_Texture* TextRenderer::createTextTexture(const std::string& text, const std::string& fontID, SDL_Color color) {
|
||||
return nullptr;
|
||||
TextRenderer::CachedText TextRenderer::createAndCacheTexture(const std::string& text, TextStyle style) {
|
||||
CachedText result = {nullptr, 0, 0, std::time(nullptr)};
|
||||
|
||||
// 获取字体
|
||||
TTF_Font* font = m_fontManager->getFont(style.fontID, style.fontSize);
|
||||
if (!font) {
|
||||
SDL_Log("错误:字体未找到 %s\n", style.fontID.c_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
// 创建文字表面
|
||||
SDL_Surface* surface = TTF_RenderText_Solid(font, text.c_str(),text.length(), style.color);
|
||||
if (!surface) {
|
||||
SDL_Log("错误:无法创建文字表面 '%s'\n", text.c_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
// 创建纹理
|
||||
SDL_Texture* texture = SDL_CreateTextureFromSurface(m_renderer, surface);
|
||||
int width = surface->w;
|
||||
int height = surface->h;
|
||||
SDL_DestroySurface(surface); // 立即释放表面
|
||||
|
||||
if (!texture) {
|
||||
SDL_Log("错误:无法创建纹理\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 保存结果
|
||||
result.texture = texture;
|
||||
result.width = width;
|
||||
result.height = height;
|
||||
result.lastAccessTime = std::time(nullptr);
|
||||
|
||||
// 保存到缓存
|
||||
auto key = makeHash(text, style);
|
||||
m_cache[key] = result;
|
||||
|
||||
// 检查是否需要清理缓存
|
||||
if (m_cache.size() > MAX_CACHE_SIZE) {
|
||||
autoCleanCache();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,3 +118,68 @@ std::string makeCacheKey(const std::string& text, const std::string& fontID, SDL
|
||||
std::to_string(color.b) + "-" +
|
||||
std::to_string(color.a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t TextRenderer::makeHash(const std::string& text, TextStyle style) const {
|
||||
// 使用组合哈希技术
|
||||
|
||||
size_t h1 = std::hash<std::string>{}(style.fontID);
|
||||
size_t h2 = std::hash<std::string>{}(text);
|
||||
size_t h3 = std::hash<int>{}(style.fontSize);
|
||||
size_t h4 = std::hash<Uint8>{}(style.color.r);
|
||||
size_t h5 = std::hash<Uint8>{}(style.color.g);
|
||||
size_t h6 = std::hash<Uint8>{}(style.color.b);
|
||||
size_t h7 = std::hash<Uint8>{}(style.color.a);
|
||||
|
||||
// 组合哈希(使用黄金比例乘法混合)
|
||||
return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3) ^ (h5 << 4) ^ (h6 << 5) ^ (h7 << 6);
|
||||
}
|
||||
|
||||
|
||||
void TextRenderer::clearCache() {
|
||||
for (auto& pair : m_cache) {
|
||||
SDL_DestroyTexture(pair.second.texture);
|
||||
}
|
||||
m_cache.clear();
|
||||
SDL_Log("文本缓存已清空\n");
|
||||
}
|
||||
|
||||
|
||||
void TextRenderer::autoCleanCache() {
|
||||
// 如果缓存没有超过最大限制,则不进行清理
|
||||
if (m_cache.size() <= MAX_CACHE_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 收集所有缓存项,按最后访问时间排序
|
||||
std::vector<std::pair<size_t, time_t>> cacheItems;
|
||||
cacheItems.reserve(m_cache.size());
|
||||
|
||||
for (const auto& pair : m_cache) {
|
||||
cacheItems.emplace_back(pair.first, pair.second.lastAccessTime);
|
||||
}
|
||||
|
||||
// 按最后访问时间从早到晚排序(最旧的在前)
|
||||
std::sort(cacheItems.begin(), cacheItems.end(),
|
||||
[](const auto& a, const auto& b) {
|
||||
return a.second < b.second;
|
||||
});
|
||||
|
||||
// 计算需要删除的数量
|
||||
size_t itemsToRemove = m_cache.size() - MIN_CACHE_SIZE;
|
||||
|
||||
SDL_Log("缓存清理:删除 %zu / %zu 条目(当前缓存大小:%zu)\n",
|
||||
itemsToRemove, m_cache.size(), m_cache.size());
|
||||
|
||||
// 删除最旧的缓存项
|
||||
for (size_t i = 0; i < itemsToRemove && i < cacheItems.size(); ++i) {
|
||||
auto it = m_cache.find(cacheItems[i].first);
|
||||
if (it != m_cache.end()) {
|
||||
SDL_DestroyTexture(it->second.texture);
|
||||
m_cache.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Log("缓存清理完成,当前缓存大小:%zu\n", m_cache.size());
|
||||
}
|
||||
@@ -1,44 +1,167 @@
|
||||
/**
|
||||
* @file TextRenderer.h
|
||||
* @brief 文本渲染器类,用于将带有特定样式的文本渲染到屏幕上
|
||||
* @details 该类使用 SDL3 TTF 库进行文字渲染,并实现了纹理缓存机制以提高性能。
|
||||
* 支持获取文本尺寸和渲染文本到指定位置。
|
||||
* @author zhenyan121
|
||||
* @date 2025-12-12
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <list>
|
||||
#include <ctime>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3_ttf/SDL_ttf.h>
|
||||
#include "Textstyle.h"
|
||||
#include "FontManager.h"
|
||||
|
||||
/**
|
||||
* @class TextRenderer
|
||||
* @brief 文本渲染器
|
||||
* @details 负责管理文本渲染的生命周期,包括:
|
||||
* - 文本纹理的创建和缓存
|
||||
* - 文本尺寸的计算
|
||||
* - 文本到指定屏幕位置的渲染
|
||||
*
|
||||
* 使用哈希缓存机制存储已渲染的文本纹理,避免重复创建相同的纹理。
|
||||
*/
|
||||
class TextRenderer {
|
||||
private:
|
||||
SDL_Renderer* m_renderer;
|
||||
FontManager* m_fontManager;
|
||||
|
||||
// 缓存文字纹理
|
||||
|
||||
|
||||
struct CachedText {
|
||||
SDL_Texture* texture;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
std::unordered_map<size_t, CachedText> m_cache;
|
||||
// 创建材质
|
||||
SDL_Texture* createTextTexture(const std::string& text, const std::string& fontID, SDL_Color color);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param renderer SDL 渲染器指针,用于创建纹理和执行渲染操作。不可为 nullptr
|
||||
* @param fontManager 字体管理器指针,用于获取指定字体 ID 和大小的字体对象。不可为 nullptr
|
||||
* @details 初始化文本渲染器,设置必要的 SDL 渲染器和字体管理器引用
|
||||
*/
|
||||
TextRenderer(SDL_Renderer* renderer, FontManager* fontManager);
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
* @details 自动释放所有缓存中的 SDL 纹理资源,防止内存泄漏
|
||||
*/
|
||||
~TextRenderer();
|
||||
|
||||
/**
|
||||
* @brief 获取文本渲染后的尺寸
|
||||
* @param text 要计算尺寸的文本内容。支持任意 UTF-8 字符串
|
||||
* @param style 文本样式,包含字体 ID、大小、颜色等信息
|
||||
* @return 返回一个 pair,first 为宽度(像素),second 为高度(像素);
|
||||
* 如果渲染失败,返回 {0, 0}
|
||||
* @details 该函数会检查缓存,如果文本纹理已存在则直接返回其尺寸;
|
||||
* 否则创建新的纹理并缓存,然后返回尺寸。
|
||||
* 这样可以避免重复渲染相同的文本。
|
||||
* @note 返回的尺寸是矩形的宽和高
|
||||
*/
|
||||
std::pair<int, int> getTextSize(const std::string& text, TextStyle style);
|
||||
|
||||
//渲染文本
|
||||
|
||||
/**
|
||||
* @brief 将文本渲染到指定位置
|
||||
* @param text 要渲染的文本内容。支持任意 UTF-8 字符串
|
||||
* @param style 文本样式,包含字体 ID、大小、颜色等信息
|
||||
* @param x 文本左上角的 X 坐标(像素)
|
||||
* @param y 文本左上角的 Y 坐标(像素)
|
||||
* @details 该函数会检查缓存,如果文本纹理已存在则直接使用;
|
||||
* 否则创建新的纹理、缓存并渲染。
|
||||
* 使用浮点数坐标进行渲染,支持亚像素精度。
|
||||
* @note (x, y) 为文本左上角的顶点坐标
|
||||
*/
|
||||
void renderText(const std::string& text, TextStyle style, int x, int y);
|
||||
|
||||
};
|
||||
/**
|
||||
* @brief 为文本和样式生成哈希值
|
||||
* @param text 文本内容
|
||||
* @param style 文本样式
|
||||
* @return 返回组合哈希值,用于缓存键的生成
|
||||
* @details 利用文本内容、字体 ID、字体大小和颜色信息生成唯一的哈希值,
|
||||
* 用于在缓存中快速查找已渲染的文本纹理
|
||||
* @see m_cache
|
||||
*/
|
||||
size_t makeHash(const std::string& text, TextStyle style) const;
|
||||
|
||||
/**
|
||||
* @brief 手动清理所有缓存
|
||||
* @details 释放所有缓存中的纹理资源,完全清空缓存表
|
||||
* @note 清理后任何文本都需要重新渲染
|
||||
*/
|
||||
void clearCache();
|
||||
|
||||
private:
|
||||
/** @brief SDL 渲染器指针,用于创建纹理和执行 2D 渲染操作 */
|
||||
SDL_Renderer* m_renderer;
|
||||
|
||||
/** @brief 字体管理器指针,用于管理和获取字体资源 */
|
||||
FontManager* m_fontManager;
|
||||
|
||||
/**
|
||||
* @struct CachedText
|
||||
* @brief 缓存的文本纹理信息
|
||||
* @details 存储已渲染文本的纹理及其尺寸信息,用于快速重用
|
||||
*/
|
||||
struct CachedText {
|
||||
/** @brief 文本渲染后生成的 SDL 纹理指针 */
|
||||
SDL_Texture* texture;
|
||||
|
||||
/** @brief 文本纹理的宽度(像素) */
|
||||
int width;
|
||||
|
||||
/** @brief 文本纹理的高度(像素) */
|
||||
int height;
|
||||
|
||||
/** @brief 该缓存项的最后访问时间戳(秒) */
|
||||
time_t lastAccessTime;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 文本纹理缓存容器
|
||||
* @details 使用无序哈希表存储已渲染的文本纹理。
|
||||
* 键是由文本内容、字体信息等生成的哈希值(通过 makeHash 生成);
|
||||
* 值是对应的 CachedText 结构体,包含纹理指针和尺寸信息。
|
||||
*
|
||||
* 缓存机制的优势:
|
||||
* - 避免重复渲染相同的文本
|
||||
* - 提高渲染性能
|
||||
* - 加速尺寸查询
|
||||
* @see CachedText, makeHash()
|
||||
*/
|
||||
std::unordered_map<size_t, CachedText> m_cache;
|
||||
|
||||
/** @brief 最大缓存条目数,超过此数量会触发自动清理 */
|
||||
static constexpr size_t MAX_CACHE_SIZE = 256;
|
||||
|
||||
/** @brief 缓存清理时保留的最少条目数(清理时会保留最常用的条目) */
|
||||
static constexpr size_t MIN_CACHE_SIZE = 128;
|
||||
|
||||
/** @brief 自动清理缓存(当缓存超过最大限制时调用) */
|
||||
void autoCleanCache();
|
||||
|
||||
/**
|
||||
* @brief 创建文本纹理(暂未使用)
|
||||
* @param text 文本内容
|
||||
* @param fontID 字体 ID
|
||||
* @param color 文本颜色
|
||||
* @return 返回创建的纹理指针,创建失败时返回 nullptr
|
||||
* @deprecated 该函数已被 createAndCacheTexture() 取代
|
||||
*/
|
||||
//SDL_Texture* createTextTexture(const std::string& text, const std::string& fontID, SDL_Color color);
|
||||
|
||||
/**
|
||||
* @brief 创建并缓存文本纹理
|
||||
* @param text 文本内容
|
||||
* @param style 文本样式
|
||||
* @return 返回 CachedText 结构体,包含创建的纹理和尺寸信息;
|
||||
* 创建失败时返回空结构体(texture 为 nullptr)
|
||||
* @details 该函数执行以下步骤:
|
||||
* 1. 从字体管理器获取指定字体
|
||||
* 2. 使用 TTF 库将文本渲染为表面(Surface)
|
||||
* 3. 将表面转换为 SDL 纹理
|
||||
* 4. 立即释放表面以节省内存
|
||||
* 5. 将纹理和尺寸信息存储到缓存中
|
||||
* 6. 返回结果
|
||||
* @see CachedText, m_cache
|
||||
*/
|
||||
CachedText createAndCacheTexture(const std::string& text, TextStyle style);
|
||||
|
||||
};
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
* 用于统一管理文本外观
|
||||
*/
|
||||
struct TextStyle {
|
||||
std::string fontID; ///< 字体标识符(在FontManager中注册的ID)
|
||||
int fontSize = 16; ///< 字体大小(像素)
|
||||
SDL_Color color = {255, 255, 255, 255}; ///< 文本颜色(RGBA)
|
||||
std::string fontID = "SourceHanSansSC-Regular.otf"; ///< 字体标识符(在FontManager中注册的ID)
|
||||
int fontSize = 24; ///< 字体大小(像素)
|
||||
SDL_Color color = {0, 0, 0, 255}; ///< 文本颜色(RGBA)
|
||||
|
||||
/**
|
||||
* @brief 比较两个样式是否相等(用于缓存查找)
|
||||
@@ -27,21 +27,4 @@ struct TextStyle {
|
||||
color.b == other.color.b &&
|
||||
color.a == other.color.a;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 计算样式的哈希值(用于unordered_map)
|
||||
* @return size_t 哈希值
|
||||
*/
|
||||
size_t hash() const {
|
||||
// 使用组合哈希技术
|
||||
size_t h1 = std::hash<std::string>{}(fontID);
|
||||
size_t h2 = std::hash<int>{}(fontSize);
|
||||
size_t h3 = std::hash<Uint8>{}(color.r);
|
||||
size_t h4 = std::hash<Uint8>{}(color.g);
|
||||
size_t h5 = std::hash<Uint8>{}(color.b);
|
||||
size_t h6 = std::hash<Uint8>{}(color.a);
|
||||
|
||||
// 组合哈希(使用黄金比例乘法混合)
|
||||
return h1 ^ (h2 << 1) ^ (h3 << 2) ^ (h4 << 3) ^ (h5 << 4) ^ (h6 << 5);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user