2024-02-05 22:25:30 -08:00
|
|
|
#include "ehs/io/FontAtlas.h"
|
|
|
|
#include "ehs/io/File.h"
|
|
|
|
#include "ehs/Serializer.h"
|
|
|
|
|
|
|
|
namespace ehs
|
|
|
|
{
|
|
|
|
FontAtlas::~FontAtlas()
|
|
|
|
{
|
|
|
|
delete[] atlas;
|
|
|
|
}
|
|
|
|
|
|
|
|
FontAtlas::FontAtlas()
|
|
|
|
: hashId(0), glyphScale(0), size(0), atlas(nullptr)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
FontAtlas::FontAtlas(const Str_8& filePath)
|
|
|
|
{
|
|
|
|
File fontFile(filePath, Mode::READ, Disposition::OPEN);
|
|
|
|
|
|
|
|
hashId = fontFile.GetName().Hash_64();
|
|
|
|
id = fontFile.GetName();
|
|
|
|
|
|
|
|
Serializer<UInt_64> fData = fontFile.ReadSerializer_64(Endianness::LE, fontFile.Size());
|
|
|
|
fontFile.Release();
|
|
|
|
|
|
|
|
Version ver = fData.ReadVersion();
|
|
|
|
if (ver != Version(1, 0, 0))
|
|
|
|
{
|
|
|
|
EHS_LOG_INT("Error", 2, "The Event Horizon Font file, \"" + filePath + "\", must be version 1.0.0, but was version " +
|
|
|
|
Str_8::FromNum(ver.major) + "." + Str_8::FromNum(ver.minor) + "." +
|
|
|
|
Str_8::FromNum(ver.patch) + ".");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
glyphScale = fData.Read<UInt_64>();
|
|
|
|
|
|
|
|
glyphs.Resize(fData.Read<UInt_64>());
|
|
|
|
for (UInt_64 i = 0; i < glyphs.Size(); ++i)
|
|
|
|
glyphs[i] = Glyph(fData);
|
|
|
|
|
|
|
|
resolution = fData.ReadVec2<UInt_64>();
|
2024-02-19 22:58:59 -08:00
|
|
|
atlas = new Byte[resolution.x * resolution.y];
|
|
|
|
size = 0;
|
2024-02-05 22:25:30 -08:00
|
|
|
fData.ReadArray(atlas, &size);
|
|
|
|
}
|
|
|
|
|
|
|
|
FontAtlas::FontAtlas(FontAtlas&& fa) noexcept
|
|
|
|
: BaseObj(std::move(fa)), hashId(fa.hashId), id((Str_8&&)fa.id), glyphScale(fa.glyphScale),
|
|
|
|
glyphs((Array<Glyph>&&)fa.glyphs), resolution(fa.resolution), size(fa.size), atlas(fa.atlas)
|
|
|
|
{
|
|
|
|
fa.hashId = 0;
|
|
|
|
fa.glyphScale = 0;
|
|
|
|
fa.resolution = {};
|
|
|
|
fa.size = 0;
|
|
|
|
fa.atlas = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
FontAtlas::FontAtlas(const FontAtlas& fa)
|
|
|
|
: BaseObj(fa), hashId(fa.hashId), id(fa.id), glyphScale(fa.glyphScale), glyphs(fa.glyphs),
|
|
|
|
resolution(fa.resolution), size(fa.size), atlas(new Byte[fa.size])
|
|
|
|
{
|
|
|
|
Util::Copy(atlas, fa.atlas, fa.size);
|
|
|
|
}
|
|
|
|
|
|
|
|
FontAtlas& FontAtlas::operator=(FontAtlas&& fa) noexcept
|
|
|
|
{
|
|
|
|
if (this == &fa)
|
|
|
|
return *this;
|
|
|
|
|
|
|
|
BaseObj::operator=(std::move(fa));
|
|
|
|
|
|
|
|
hashId = fa.hashId;
|
|
|
|
id = (Str_8&&)fa.id;
|
|
|
|
glyphScale = fa.glyphScale;
|
|
|
|
glyphs = (Array<Glyph>&&)fa.glyphs;
|
|
|
|
resolution = fa.resolution;
|
|
|
|
size = fa.size;
|
|
|
|
delete[] atlas;
|
|
|
|
atlas = fa.atlas;
|
|
|
|
|
|
|
|
fa.hashId = 0;
|
|
|
|
fa.glyphScale = 0;
|
|
|
|
fa.resolution = {};
|
|
|
|
fa.size = 0;
|
|
|
|
fa.atlas = nullptr;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
FontAtlas& FontAtlas::operator=(const FontAtlas& fa)
|
|
|
|
{
|
|
|
|
if (this == &fa)
|
|
|
|
return *this;
|
|
|
|
|
|
|
|
BaseObj::operator=(fa);
|
|
|
|
|
|
|
|
hashId = fa.hashId;
|
|
|
|
id = fa.id;
|
|
|
|
glyphScale = fa.glyphScale;
|
|
|
|
glyphs = fa.glyphs;
|
|
|
|
resolution = {};
|
|
|
|
size = fa.size;
|
|
|
|
delete[] atlas;
|
|
|
|
atlas = new Byte[fa.size];
|
|
|
|
|
|
|
|
Util::Copy(atlas, fa.atlas, fa.size);
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
FontAtlas::operator Byte *() const
|
|
|
|
{
|
|
|
|
return atlas;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FontAtlas::Release()
|
|
|
|
{
|
|
|
|
hashId = 0;
|
|
|
|
id = {};
|
|
|
|
glyphScale = 0;
|
|
|
|
glyphs.Clear();
|
|
|
|
resolution = {0, 0};
|
|
|
|
size = 0;
|
|
|
|
delete[] atlas;
|
|
|
|
atlas = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
UInt_64 FontAtlas::GetHashId() const
|
|
|
|
{
|
|
|
|
return hashId;
|
|
|
|
}
|
|
|
|
|
|
|
|
Str_8 FontAtlas::GetId() const
|
|
|
|
{
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
UInt_64 FontAtlas::GetGlyphScale() const
|
|
|
|
{
|
|
|
|
return glyphScale;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Array<Glyph>& FontAtlas::GetGlyphs() const
|
|
|
|
{
|
|
|
|
return glyphs;
|
|
|
|
}
|
|
|
|
|
|
|
|
Glyph FontAtlas::GetGlyph(const Char_32 code) const
|
|
|
|
{
|
|
|
|
for (UInt_32 i = 0; i < glyphs.Size(); ++i)
|
|
|
|
if (glyphs[i].GetCode() == code)
|
|
|
|
return glyphs[i];
|
|
|
|
|
|
|
|
return glyphs[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
Vec2_u64 FontAtlas::GetResolution() const
|
|
|
|
{
|
|
|
|
return resolution;
|
|
|
|
}
|
|
|
|
|
|
|
|
UInt_64 FontAtlas::GetSize() const
|
|
|
|
{
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FontAtlas::IsValid() const
|
|
|
|
{
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vec2_f FontAtlas::CalculateSize(const Str_8& text) const
|
|
|
|
{
|
|
|
|
Vec2_f result;
|
|
|
|
|
|
|
|
for (UInt_64 i = 0; i < text.Size(); ++i)
|
|
|
|
{
|
|
|
|
Glyph glyph = GetGlyph(text[i]);
|
|
|
|
|
|
|
|
result.x += (float)glyph.GetAdvance().x;
|
|
|
|
|
|
|
|
if ((float)glyph.GetScale().y > result.y)
|
|
|
|
result.y = (float)glyph.GetScale().y;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
float FontAtlas::CalculateWidth(const Str_8 &text) const
|
|
|
|
{
|
|
|
|
float result = 0.0f;
|
|
|
|
|
|
|
|
for (UInt_64 i = 0; i < text.Size(); ++i)
|
|
|
|
{
|
|
|
|
Glyph glyph = GetGlyph(text[i]);
|
|
|
|
|
|
|
|
result += (float)glyph.GetAdvance().x;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
float FontAtlas::CalculateHeight(const Str_8& text) const
|
|
|
|
{
|
|
|
|
float result = 0.0f;
|
|
|
|
|
|
|
|
for (UInt_64 i = 0; i < text.Size(); ++i)
|
|
|
|
{
|
|
|
|
Glyph glyph = GetGlyph(text[i]);
|
|
|
|
|
|
|
|
if ((float)glyph.GetScale().y > result)
|
|
|
|
result = (float)glyph.GetScale().y;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
UInt_64 FontAtlas::CalculateIndexAtPoint(const Str_8& text, const Vec2_f& point) const
|
|
|
|
{
|
|
|
|
float result = 0.0f;
|
|
|
|
|
|
|
|
for (UInt_64 i = 0; i < text.Size(); ++i)
|
|
|
|
{
|
|
|
|
Glyph glyph = GetGlyph(text[i]);
|
|
|
|
|
|
|
|
float temp = result + (float)glyph.GetAdvance().x;
|
|
|
|
if (point.x > temp)
|
|
|
|
result += (float)glyph.GetAdvance().x;
|
|
|
|
else if (point.x <= temp)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return text.Size();
|
|
|
|
}
|
|
|
|
|
|
|
|
Mesh FontAtlas::Generate(const Anchor anchor, const Str_8& text) const
|
|
|
|
{
|
|
|
|
Vec2_f pos;
|
|
|
|
|
|
|
|
switch (anchor)
|
|
|
|
{
|
|
|
|
case Anchor::BOTTOM_CENTER:
|
|
|
|
{
|
|
|
|
pos.x -= CalculateWidth(text) * 0.5f;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Anchor::TOP_LEFT:
|
|
|
|
{
|
|
|
|
pos.x -= CalculateWidth(text);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Anchor::TOP_CENTER:
|
|
|
|
{
|
|
|
|
pos.x -= CalculateWidth(text) * 0.5f;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Anchor::CENTER_RIGHT:
|
|
|
|
{
|
|
|
|
pos.y -= CalculateHeight(text);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Anchor::CENTER:
|
|
|
|
{
|
|
|
|
Vec4_f size = CalculateSize(text);
|
|
|
|
pos.x -= size.x * 0.5f;
|
|
|
|
pos.y -= size.y;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Array<Vertex_f> verts(text.Size() * 4);
|
|
|
|
Array<UInt_32> indices(text.Size() * 6);
|
|
|
|
|
|
|
|
for (UInt_64 i = 0; i < text.Size(); ++i)
|
|
|
|
{
|
|
|
|
Glyph glyph = GetGlyph(text[i]);
|
|
|
|
Vec2_f scale = glyph.GetScale();
|
|
|
|
|
|
|
|
float x = pos.x + (float)glyph.GetBearing().x;
|
|
|
|
float y = pos.y + (float)(GetGlyphScale() - glyph.GetBearing().y);
|
|
|
|
|
|
|
|
UInt_32 vertsI = i * 4;
|
|
|
|
|
|
|
|
verts[vertsI] = Vertex_f({x, y, 1.0f}, {}, glyph.GetUV().GetPos());
|
|
|
|
verts[vertsI + 1] = Vertex_f({x, y + scale.y, 1.0f}, {}, Vec2_f(glyph.GetUV().x, glyph.GetUV().h));
|
|
|
|
verts[vertsI + 2] = Vertex_f({x + scale.x, y, 1.0f}, {}, Vec2_f(glyph.GetUV().w, glyph.GetUV().y));
|
|
|
|
verts[vertsI + 3] = Vertex_f({x + scale.x, y + scale.y, 1.0f}, {}, glyph.GetUV().GetScale());
|
|
|
|
|
|
|
|
UInt_32 indicesI = i * 6;
|
|
|
|
|
|
|
|
indices[indicesI] = vertsI;
|
|
|
|
indices[indicesI + 1] = vertsI + 1;
|
|
|
|
indices[indicesI + 2] = vertsI + 2;
|
|
|
|
indices[indicesI + 3] = vertsI + 3;
|
|
|
|
indices[indicesI + 4] = vertsI + 2;
|
|
|
|
indices[indicesI + 5] = vertsI + 1;
|
|
|
|
|
|
|
|
pos.x += (float)glyph.GetAdvance().x;
|
|
|
|
}
|
|
|
|
|
|
|
|
return {id, (Array<Vertex_f>&&)verts, (Array<UInt_32>&&)indices};
|
|
|
|
}
|
|
|
|
}
|