Extra2D/Extra2D/include/extra2d/graphics/backends/opengl/gl_font_atlas.h

85 lines
2.6 KiB
C++

#pragma once
#include <extra2d/graphics/backends/opengl/gl_texture.h>
#include <extra2d/graphics/texture/font.h>
#include <stb/stb_truetype.h>
#include <stb/stb_rect_pack.h>
#include <unordered_map>
#include <vector>
namespace extra2d {
// ============================================================================
// OpenGL 字体图集实现 (使用 STB 库)
// 使用 stb_rect_pack 进行动态矩形打包,支持动态缓存字形
// ============================================================================
class GLFontAtlas : public FontAtlas {
public:
GLFontAtlas(const std::string& filepath, int fontSize, bool useSDF = false);
~GLFontAtlas() override;
// FontAtlas 接口实现
const Glyph* getGlyph(char32_t codepoint) const override;
Texture* getTexture() const override { return texture_.get(); }
int getFontSize() const override { return fontSize_; }
float getAscent() const override { return ascent_; }
float getDescent() const override { return descent_; }
float getLineGap() const override { return lineGap_; }
float getLineHeight() const override { return lineHeight_; }
bool isSDF() const override { return useSDF_; }
Vec2 measureText(const std::string& text) override;
private:
// 字形数据内部结构
struct GlyphData {
float width;
float height;
float bearingX;
float bearingY;
float advance;
float u0, v0, u1, v1;
};
// 图集配置 - 增大尺寸以支持更多字符
static constexpr int ATLAS_WIDTH = 1024;
static constexpr int ATLAS_HEIGHT = 1024;
static constexpr int PADDING = 2; // 字形之间的间距
bool useSDF_;
int fontSize_;
Ptr<GLTexture> texture_;
std::unordered_map<char32_t, GlyphData> glyphs_;
float lineHeight_;
float ascent_;
float descent_;
float lineGap_;
// 字体数据
std::vector<unsigned char> fontData_;
stbtt_fontinfo fontInfo_;
float scale_;
// stb_rect_pack 上下文 - 持久化以支持增量打包
mutable stbrp_context packContext_;
mutable std::vector<stbrp_node> packNodes_;
// 预分配缓冲区,避免每次动态分配
mutable std::vector<uint8_t> glyphBitmapCache_;
mutable std::vector<uint8_t> glyphRgbaCache_;
// 初始化字体
bool initFont(const std::string& filepath);
// 创建空白图集纹理
void createAtlas();
// 缓存字形到图集
void cacheGlyph(char32_t codepoint);
// 更新图集纹理区域
void updateAtlas(int x, int y, int width, int height,
const std::vector<uint8_t>& data);
};
} // namespace extra2d