2021SC@SDUSC
一、简述
这篇博客我们继续之前的内容,分析2D渲染的其他内容,上一章我们分析了一部分与字体相关的内容,这一篇我们继续分析余下内容。
二、分析
(一)、字体管理器FontManager
概述:字体管理和字符集管理实用程序服务。
具体结构如下:
class FLAXENGINE_API FontManager
{
public:
static float FontScale;
static FT_Library GetLibrary();
static FontTextureAtlas* GetAtlas(int32 index);
static bool AddNewEntry(Font* font, Char c, FontCharacterEntry& entry);
static void Invalidate(FontCharacterEntry& entry);
static void Flush();
static void EnsureAtlasCreated(int32 index);
static bool IsDirty();
static bool HasDataSyncWithGPU();
};
下面我们具体解释每个属性和函数的意义以及作用:
FontScale:全局字符字体比例因子。 用于在高 DPI 显示器上放大字符。
GetLibrary:获取 FreeType 库。返回库
GetAtlas:获取纹理图集。参数为图集索引
AddNewEntry:将给定字体中的字符添加到缓存中。"font"为其创建字符条目的字体。"c"要添加的字符"entry"创建的字符条目。返回值:如果不能向字体缓存添加新字符条目则为真,否则为假
Invalidate:使缓存的动态字体字符无效。 可用于在更改字体资产选项后重新加载字体字符。"entry"字体字符入口。
Flush:刷新所有字体图集。
EnsureAtlasCreated:确保已创建具有给定索引的图集
IsDirty:确定一个或多个字体图集是否脏。
HasDataSynWithGPU:确定所有地图集是否已与 GPU 内存同步并且数据是否是最新。true 如果所有地图集都已与 GPU 内存同步并且数据是最新的;
我们再看一下字体管理器的初始化方法:
Init()
{
ASSERT(Library == nullptr);
FontManager::FontScale = (float)Platform::GetDpi() / (float)DefaultDPI; // TODO: Adjust this at runtime
FreeTypeMemory.user = nullptr;
FreeTypeMemory.alloc = &FreeTypeAlloc;
FreeTypeMemory.realloc = &FreeTypeRealloc;
FreeTypeMemory.free = &FreeTypeFree;
const FT_Error error = FT_New_Library(&FreeTypeMemory, &Library);
if (error)
{
LOG_FT_ERROR(error);
return true;
}
FT_Add_Default_Modules(Library);
FT_Int major, minor, patch;
FT_Library_Version(Library, &major, &minor, &patch);
LOG(Info, "FreeType initialized, version: {0}.{1}.{2}", major, minor, patch);
return false;
}
首先断言库不为空,FontScale缩放 UI 字体以匹配显示器 DPI。
初始化FreeType。记录版本信息。
字体管理器FontManager中最复杂的部分是向其中添加条目,源代码在这里不再贴出,仅解释具体流程:
bool FontManager::AddNewEntry(Font* font, Char c, FontCharacterEntry& entry)
获取锁。设置加载标志。
获取字体中字形的索引。
加载字形。处理特殊效果。
将字形渲染到位图。
填写字符数据。
分配内存。
空字形结束。
光栅化后复制字形数据(逐行)。
标准化不使用 256 色的灰度图像。
如果使用临时位图,则释放。
查找字符纹理的图集,将字符添加到纹理,检查结果,如果没有添加空字符。
检查这个字符是否没有图集,创建新图集,初始图集,将字符添加到纹理。
填充图集相关数据。
(二)、字体纹理图集FontTextureAtlas
概述:包含缓存字体字形图集的纹理资源。
结构体struct Slot : RectPack<Slot>,继承自RectPack,RectPack使用填充将矩形打包到 2D 图集中的实现。 使用简单的空间划分。
一下枚举描述如何处理纹理图集填充:
enum PaddingStyle
{
NoPadding,
DilateBorder,
PadWithZero,
};
NoPadding:不填充地图集。
DilateBorder:将纹理扩大一个像素以填充图集。
PadWithZero:一个用零填充的像素统一填充边框。
接下来包括基本的Get、Set方法,以及一些功能函数;
void Setup(PixelFormat format, PaddingStyle paddingStyle);
void Init(uint32 width, uint32 height);
Slot* AddEntry(uint32 targetWidth, uint32 targetHeight, const Array<byte>& data);
bool Invalidate(uint32 x, uint32 y, uint32 width, uint32 height);
void CopyDataIntoSlot(const Slot* slot, const Array<byte>& data);
void Clear();
void Dispose();
void Flush();
void EnsureTextureCreated() const;
bool HasDataSyncWithGPU() const;
SetUp:创建后设置图集。"format"像素格式。"paddingStyle"填充样式。
Init:初始化图集。"width"宽度。"height"高度。
AddEntry:将新条目添加到地图集"targetWidth"条目的宽度。"targetHeight"条目的高度。"data"数据。返回新条目占用的atlas槽。
Invalidate:使来自地图集的缓存动态条目无效。"x"插槽位置(以图集像素为单位的 X 坐标)。"y"插槽位置(以图集像素为单位的 Y 坐标)。"width"槽宽度(以图集像素为单位的大小)。"height"槽高度(以图集像素为单位的大小)。返回如果槽已被释放则为真,否则为假。
CopyDataIntoSlot:将数据复制到插槽中。"slot">插槽。"data"数据。
Clear:清除此地图集条目数据(不更改大小/纹理等)。
Dispose:清除此地图集条目数据(不更改大小/纹理等)。处置整个地图集数据(纹理、节点等)。
Flush;将此图集数据刷新到 GPU
EnsureTextureCreated:确保已为该图集创建纹理。
HasDataSynWithGPU;确定图集是否有与 GPU 同步的数据。
这里也简单介绍一下AddEntry的流程:
FontTextureAtlas::Slot* FontTextureAtlas::AddEntry(uint32 targetWidth, uint32 targetHeight, const Array<byte>& data)
检查无效尺寸。
尝试为纹理找到插槽。
检查是否适合它,将数据复制到图集内存中,设置脏位。
返回结果。
以上就是本篇博客的全部内容,关于2D渲染的部分已基本分析结束 ,剩余的一点内容将在下一篇博客进行分析。