#pragma once #include #include #include #include #include #include #include #include // STB 矩形打包 #include namespace extra2d { /** * @brief 字符信息结构 */ struct GlyphInfo { Vec2 uv0; // 左下角 UV 坐标 Vec2 uv1; // 右上角 UV 坐标 Vec2 size; // 像素尺寸 Vec2 bearing; // 基线偏移(左下角相对原点的偏移) float advance; // 水平步进(到下一个字符的距离) uint32 pageIndex; // 所在图集页索引 bool valid = false; // 是否有效 }; /** * @brief 图集页结构 * * 使用 stb_rect_pack 进行矩形打包 */ struct AtlasPage { static constexpr uint32 DEFAULT_SIZE = 1024; // 默认图集尺寸 Ptr texture; // 纹理 stbrp_context packContext; // 打包上下文 std::vector packNodes; // 打包节点数组 std::vector pixelData; // CPU 端像素数据 uint32 width = DEFAULT_SIZE; // 图集宽度 uint32 height = DEFAULT_SIZE; // 图集高度 bool dirty = false; // 是否需要更新 GPU 纹理 /** * @brief 构造函数 */ AtlasPage(); /** * @brief 初始化图集页 * @param size 图集尺寸 * @return 是否初始化成功 */ bool init(uint32 size); /** * @brief 打包矩形到图集 * @param width 矩形宽度 * @param height 矩形高度 * @param outX 输出 X 坐标 * @param outY 输出 Y 坐标 * @return 是否打包成功 */ bool packRect(uint32 width, uint32 height, uint32& outX, uint32& outY); /** * @brief 写入像素数据到图集 * @param x 起始 X 坐标 * @param y 起始 Y 坐标 * @param width 宽度 * @param height 高度 * @param data 像素数据(单通道) */ void writePixels(uint32 x, uint32 y, uint32 width, uint32 height, const uint8* data); /** * @brief 更新 GPU 纹理 */ void updateTexture(); /** * @brief 清空图集 */ void clear(); }; /** * @brief 字体图集类 * * 管理动态字符图集,支持多页扩展 */ class FontAtlas : public Resource { public: FontAtlas(); ~FontAtlas() override; /** * @brief 获取资源类型 */ ResourceType getType() const override { return ResourceType::FontAtlas; } /** * @brief 初始化字体图集 * @param pageSize 图集页尺寸 * @return 是否初始化成功 */ bool init(uint32 pageSize = AtlasPage::DEFAULT_SIZE); /** * @brief 添加字符到图集 * @param codepoint Unicode 码点 * @param bitmap 字符位图数据(单通道) * @param width 位图宽度 * @param height 位图高度 * @param bearingX 水平基线偏移 * @param bearingY 垂直基线偏移 * @param advance 水平步进 * @return 是否添加成功 */ bool addGlyph(uint32 codepoint, const uint8* bitmap, uint32 width, uint32 height, float bearingX, float bearingY, float advance); /** * @brief 获取字符信息 * @param codepoint Unicode 码点 * @return 字符信息指针,如果不存在返回 nullptr */ const GlyphInfo* getGlyph(uint32 codepoint) const; /** * @brief 检查字符是否已缓存 * @param codepoint Unicode 码点 * @return 是否已缓存 */ bool hasGlyph(uint32 codepoint) const; /** * @brief 获取图集页数量 */ uint32 getPageCount() const { return static_cast(pages_.size()); } /** * @brief 获取指定页的纹理 * @param pageIndex 页索引 * @return 纹理指针 */ Texture* getPageTexture(uint32 pageIndex) const; /** * @brief 更新所有需要更新的图集页纹理 */ void updateTextures(); /** * @brief 清空所有图集 */ void clear(); /** * @brief 获取图集页尺寸 */ uint32 getPageSize() const { return pageSize_; } private: std::vector> pages_; // 图集页数组 std::unordered_map glyphs_; // 字符信息映射表 uint32 pageSize_ = AtlasPage::DEFAULT_SIZE; // 图集页尺寸 /** * @brief 获取或创建可用的图集页 * @return 图集页指针 */ AtlasPage* getOrCreatePage(); }; } // namespace extra2d