diff --git a/example/romfs/ComicNeue.png b/example/romfs/ComicNeue.png new file mode 100644 index 0000000..ba44237 Binary files /dev/null and b/example/romfs/ComicNeue.png differ diff --git a/example/source/main.cpp b/example/source/main.cpp index f5f8ab0..a0a5a28 100755 --- a/example/source/main.cpp +++ b/example/source/main.cpp @@ -11,8 +11,11 @@ class Example : public Amy::App { Top = C3D::CreateScreen(GFX_TOP); Mgr = new Amy::AssetMgr(); Iron::Init(); + auto fnt = Iron::Font::New(); + fnt->LoadBMF("romfs:/ComicNeue.png"); Mgr->AutoLoad("icon", "romfs:/icon.png"); - Mgr->AutoLoad("font", "romfs:/ComicNeue.ttf"); + Mgr->Add("font", fnt); + // Mgr->AutoLoad("font", "romfs:/ComicNeue.ttf"); dl = new Iron::Drawlist(); dl->SetFont(Mgr->Get("font")); } diff --git a/include/amethyst/iron.hpp b/include/amethyst/iron.hpp index 7de445c..8715a65 100644 --- a/include/amethyst/iron.hpp +++ b/include/amethyst/iron.hpp @@ -105,6 +105,7 @@ class Iron { public: Drawlist() { DrawSolid(); } ~Drawlist() { pData.clear(); } + AMY_SHARED(Drawlist) // required due to memory management Drawlist(const Drawlist&) = delete; @@ -122,7 +123,9 @@ class Iron { void DrawSolid(); void DrawTex(Texture::Ref tex) { pTex = tex; } void SetFont(Font::Ref fnt) { pCurrentFont = fnt; } - + void SetFontScale(float v) { pFontScale = v; } + float GetFontScale() { return pFontScale; } + void DefaultFontScale() { pFontScale = 0.7; } /** Draw Api */ void DrawRect(const fvec2& pos, const fvec2& size, ui color, int thickness = 1); diff --git a/include/amethyst/texture.hpp b/include/amethyst/texture.hpp index 2511bbc..804e85d 100755 --- a/include/amethyst/texture.hpp +++ b/include/amethyst/texture.hpp @@ -29,6 +29,8 @@ class Texture : public Asset { // Dont set as loaded as only the root tex can be loaded } void Unload(); + void Unloadable(bool v) { pLoaded = v; } + bool Unloadable() { return pLoaded; } int W() const { return pSize.x; } int& W() { return pSize.x; } diff --git a/source/iron/font.cpp b/source/iron/font.cpp index 51fac60..8bb8d59 100644 --- a/source/iron/font.cpp +++ b/source/iron/font.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #if AMY_STB_TT == 1 #define STB_TRUETYPE_IMPLEMENTATION @@ -8,14 +9,52 @@ #include namespace Amy { -void Iron::Font::LoadBMF(ksr path) {} +// Dont read this code please ... tnaks +void Iron::Font::LoadBMF(ksr path) { + Image img(path); + if (img.Width() != img.Height() || img.Bpp() != 4) { + throw std::runtime_error( + "[Amy] Font: BMF is not in rgba or not 1x1 dimensioned!"); + } + auto base = Amy::Texture::New(); + base->Load(img.GetBuffer(), img.Width(), img.Height(), img.Bpp()); + base->Unloadable(false); + PxHeight = img.Height() / 16; + for (int i = 0; i < img.Height(); i += PxHeight) { + for (int j = 0; j < img.Width(); j += PxHeight) { + int maxw = 0; + Amy::Texture::Ref tex = Amy::Texture::New(); + for (int y = i; y < i + PxHeight; y++) { + for (int x = j; x < j + PxHeight; x++) { + if (img.GetBuffer()[((y * img.Width() + x) * 4) + 3] != 0) { + maxw = std::max(maxw, x - j); + } + } + } + maxw++; + tex->Load(base->Ptr(), base->Size(), base->Uv()); + Codepoint cp; + cp.Cp = (i / PxHeight) * 16 + (j / PxHeight); + cp.Offset = 0.f; + cp.Size = fvec2(maxw, PxHeight); + cp.Tex = tex; + cp.Uv = fvec4(float(j) / float(img.Width()), + 1.f - float(i) / float(img.Height()), + float(j + maxw) / float(img.Width()), + 1.f - float(i + PxHeight) / float(img.Height())); + cp.Valid = maxw != 0; + pCodeMap[(i / PxHeight) * 16 + (j / PxHeight)] = cp; + Textures.push_back(tex); + } + } +} void Iron::Font::LoadTTF(ksr path, int size) { auto data = Amy::Utils::LoadFile2Mem(path); LoadTTF(data, size); } -void Iron::Font::LoadTTF(const vec &data, int size) { +void Iron::Font::LoadTTF(const vec& data, int size) { /** * Some additional Info: * Removed the stbtt get bitmapbox as we dont need to place @@ -54,7 +93,7 @@ void Iron::Font::LoadTTF(const vec &data, int size) { if (stbtt_IsGlyphEmpty(&inf, gi)) continue; int w = 0, h = 0, xo = 0, yo = 0; - unsigned char *bitmap = + unsigned char* bitmap = stbtt_GetCodepointBitmap(&inf, scale, scale, ii, &w, &h, &xo, &yo); if (!bitmap || w <= 0 || h <= 0) { if (bitmap) free(bitmap); @@ -130,13 +169,13 @@ void Iron::Font::LoadTTF(const vec &data, int size) { } } -void Iron::Font::pMakeAtlas(bool final, vec &font_tex, int texszs, +void Iron::Font::pMakeAtlas(bool final, vec& font_tex, int texszs, Texture::Ref tex) { tex->Load(font_tex, texszs, texszs); Textures.push_back(tex); } -Iron::Font::Codepoint &Iron::Font::GetCodepoint(ui cp) { +Iron::Font::Codepoint& Iron::Font::GetCodepoint(ui cp) { // Check if codepoijt exist or return a static invalid one auto res = pCodeMap.find(cp); if (res == pCodeMap.end()) { @@ -157,7 +196,7 @@ fvec2 Iron::Font::GetTextBounds(ksr text, float scale) { float cfs = (PxFactor * scale) / (float)PxHeight; float lh = (float)PxHeight * cfs; size_t index = 0; - for (auto &it : wtext) { + for (auto& it : wtext) { if (it == L'\0') { break; } @@ -192,9 +231,9 @@ fvec2 Iron::Font::GetTextBounds(ksr text, float scale) { return res; } -void Iron::Font::CmdTextEx(vec &cmds, const fvec2 &pos, ui color, - float scale, const std::string &text, - AmyTextFlags flags, const fvec2 &box) { +void Iron::Font::CmdTextEx(vec& cmds, const fvec2& pos, ui color, + float scale, const std::string& text, + AmyTextFlags flags, const fvec2& box) { fvec2 off; float cfs = (PxFactor * scale) / (float)PxHeight; float lh = (float)PxHeight * cfs; @@ -218,7 +257,7 @@ void Iron::Font::CmdTextEx(vec &cmds, const fvec2 &pos, ui color, lines.push_back(tmp); } - for (auto &it : lines) { + for (auto& it : lines) { /*if (flags & AmyTextFlags_Short) { fvec2 tmp_dim; it = ShortText(it, box.x() - pos.x(), tmp_dim); @@ -228,7 +267,7 @@ void Iron::Font::CmdTextEx(vec &cmds, const fvec2 &pos, ui color, auto cmd = Command::New(); auto Tex = GetCodepoint(wline[0]).Tex; cmd->Tex = Tex; - for (auto &jt : wline) { + for (auto& jt : wline) { auto cp = GetCodepoint(jt); if ((!cp.Valid && jt != L' ' && jt != L'\n' && jt != L'\t') && jt != L'\r') {