Implement Text Rendering

Added STB truetype
Switched AssetMgr to use Shared Ptr
This commit is contained in:
2025-12-07 23:20:15 +01:00
parent 28d2e291b3
commit 88e367a299
17 changed files with 5504 additions and 44 deletions

View File

@@ -7,7 +7,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED true)
option(AMY_GOD_DEV "Turn this on if you think you are god" OFF)
# THis option should be disabled if you use STB_IMAGE in you main project
set(AMY_BUILD_STB_IMAGE "Include STB Image code" CACHE BOOL 1)
set(AMY_BUILD_STB_IMAGE 1)
set(AMY_BUILD_STB_TRUETYPE 1)
set(AMY_WITH_MPG123 "Include MP3 Support" CACHE BOOL 1)
#add_subdirectory(vendor/libpicasso)
@@ -24,6 +25,7 @@ add_library(${PROJECT_NAME} STATIC
source/c3d.cpp
source/iron/iron.cpp
source/iron/drawlist.cpp
source/iron/font.cpp
source/maths/mat.cpp
)
target_include_directories(${PROJECT_NAME} PUBLIC
@@ -38,6 +40,7 @@ target_link_libraries(${PROJECT_NAME} PUBLIC m z ctru citro3d mpg123)
target_compile_definitions(${PROJECT_NAME} PUBLIC
AMY_3DS
AMY_STB_IMAGE=${AMY_BUILD_STB_IMAGE}
AMY_STB_TT=${AMY_BUILD_STB_TRUETYPE}
AMY_WITH_MPG123=${AMY_WITH_MPG123}
)
target_compile_options(${PROJECT_NAME} PUBLIC -Wno-psabi)
@@ -45,4 +48,4 @@ target_compile_options(${PROJECT_NAME} PUBLIC -Wno-psabi)
add_subdirectory(example)
install(TARGETS ${PROJECT_NAME})
install(DIRECTORY include DESTINATION .)
install(DIRECTORY include DESTINATION .)

View File

@@ -26,4 +26,4 @@ Coming Soon...
## Credits
- [tobid7](https://github.com/tobid7) Lead Developer, Stealing a lot of code of [Palladium](https://github.com/tobid7/palladium)
- [nothings](https://github.com/nothings) [stb_image](https://github.com/nothings/stb)
- [nothings](https://github.com/nothings) stb_image and stb_truetype from [here](https://github.com/nothings/stb)

BIN
example/romfs/ComicNeue.ttf Normal file

Binary file not shown.

View File

@@ -0,0 +1,93 @@
Copyright 2014 The Comic Neue Project Authors (https://github.com/crozynski/comicneue)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

View File

@@ -13,7 +13,11 @@ class Example : public Amy::App {
Mgr->AutoLoad("icon", "romfs:/icon.png");
Iron::Init();
dl = new Iron::Drawlist();
Fnt = Iron::Font::New();
Fnt->LoadTTF("romfs:/ComicNeue.ttf");
dl->SetFont(Fnt);
}
~Example() {
delete Top;
delete dl;
@@ -46,6 +50,7 @@ class Example : public Amy::App {
dl->DrawCircleFilled(Amy::fvec2(200, 120), 50, Amy::Color("#ffffff"), 40);
dl->DrawSolid();
dl->DrawRectFilled(0, 50, Amy::Color(0.f, 1.f, 0.f, 1.f));
dl->DrawText(Amy::fvec2(5, 50), "Hello World!", Amy::Color(255, 0, 255));
Iron::NewFrame();
Iron::DrawOn(Top);
@@ -57,6 +62,7 @@ class Example : public Amy::App {
C3D::Screen* Top;
Amy::AssetMgr* Mgr;
Iron::Drawlist* dl;
Iron::Font::Ref Fnt;
};
int main() {

View File

@@ -1,9 +1,12 @@
#pragma once
#include <amethyst/types.hpp>
namespace Amy {
class Asset {
public:
Asset() = default;
virtual ~Asset() = default;
AMY_SHARED(Asset);
};
} // namespace Amy

View File

@@ -3,6 +3,7 @@
#include <amethyst/id.hpp>
#include <amethyst/texture.hpp>
#include <amethyst/types.hpp>
#include <memory>
namespace Amy {
class AssetMgr {
@@ -12,7 +13,7 @@ class AssetMgr {
void AutoLoad(const ID& name, ksr path);
void Add(const ID& id, Asset* v) {
void Add(const ID& id, Asset::Ref v) {
if (pAssets.count(id)) {
throw std::runtime_error("[amy]: assets: " + id.GetName() +
" already exists!");
@@ -27,12 +28,12 @@ class AssetMgr {
}
template <typename T>
T* Get(const ID& id) {
std::shared_ptr<T> Get(const ID& id) {
auto r = pAssets.find(id);
if (r == pAssets.end()) {
throw std::runtime_error("[amy] assets: unable to find " + id.GetName());
}
if (auto v = dynamic_cast<T*>(r->second)) {
if (auto v = std::dynamic_pointer_cast<T>(r->second)) {
return v;
} else {
throw std::runtime_error(id.GetName() + " is not of type " +
@@ -46,14 +47,14 @@ class AssetMgr {
if (r == pAssets.end()) {
throw std::runtime_error("[amy] assets: unable to find " + id.GetName());
}
return dynamic_cast<T*>(r->second) != nullptr;
return std::dynamic_pointer_cast<T>(r->second) != nullptr;
}
template <typename T>
size_t Count() const {
size_t ret = 0;
for (auto& it : pAssets) {
if (dynamic_cast<T*>(it.second)) {
if (std::dynamic_pointer_cast<T>(it.second)) {
ret++;
}
}
@@ -61,6 +62,6 @@ class AssetMgr {
}
private:
std::map<ID, Asset*> pAssets;
std::map<ID, Asset::Ref> pAssets;
};
} // namespace Amy

View File

@@ -42,6 +42,7 @@ class C3D {
Shader(ksr path);
Shader() {}
~Shader();
AMY_SHARED(Shader);
void Load(ksr path);
void Load(kvr<uc> data);

View File

@@ -8,6 +8,17 @@
#include <amethyst/texture.hpp>
#include <amethyst/types.hpp>
using AmyTextFlags = Amy::ui;
enum AmyTextFlags_ {
AmyTextFlags_None = 0, ///< Do nothing
AmyTextFlags_AlignRight = 1 << 0, ///< Align Right of position
AmyTextFlags_AlignMid = 1 << 1, ///< Align in the middle of pos and box
AmyTextFlags_Shaddow = 1 << 2, ///< Draws the text twice to create shaddow
AmyTextFlags_Wrap = 1 << 3, ///< Wrap Text: May be runs better with TMS
AmyTextFlags_Short = 1 << 4, ///< Short Text: May be runs better with TMS
AmyTextFlags_Scroll = 1 << 5, ///< Not implemented [scoll text if to long]
};
namespace Amy {
class Iron {
public:
@@ -51,7 +62,7 @@ class Iron {
bool ScissorOn = false;
int Layer = 0;
int Index = 0;
Texture* Tex = nullptr;
Texture::Ref Tex = nullptr;
};
class Font {
@@ -59,7 +70,7 @@ class Iron {
struct Codepoint {
ui Cp = 0;
fvec4 Uv;
Texture* Tex;
Texture::Ref Tex;
fvec2 Size;
float Offset = 0; // Unused??
bool Valid = true;
@@ -80,12 +91,13 @@ class Iron {
fvec2 GetTextBounds(ksr text, float scale);
void CmdTextEx(vec<Command::Ref>& cmds, const fvec2& pos, ui color,
float scale, ksr text, ui flags = 0, const fvec2& box = 0);
void pMakeAtlas(bool final, vec<uc>& pixels, int size, Texture* tex);
float scale, ksr text, AmyTextFlags flags = 0,
const fvec2& box = 0);
void pMakeAtlas(bool final, vec<uc>& pixels, int size, Texture::Ref tex);
int PxHeight;
int PxFactor = 24;
vec<Texture*> Textures;
vec<Texture::Ref> Textures;
std::map<u32, Codepoint> pCodeMap;
};
@@ -108,7 +120,8 @@ class Iron {
void Clear();
void DrawSolid();
void DrawTex(Texture* tex) { pTex = tex; }
void DrawTex(Texture::Ref tex) { pTex = tex; }
void SetFont(Font::Ref fnt) { pCurrentFont = fnt; }
/** Draw Api */
void DrawRect(const fvec2& pos, const fvec2& size, ui color,
@@ -160,10 +173,11 @@ class Iron {
void clipCmd(Command* ptr);
std::vector<Command::Ref> pData;
std::vector<fvec2> pPath;
Texture* pTex = nullptr;
Texture::Ref pTex = nullptr;
std::stack<fvec4> ClipRects;
Font* pCurrentFont;
Font::Ref pCurrentFont;
int pLayer = 0;
float pFontScale = 0.7;
};
Iron() = default;
~Iron() = default;
@@ -173,7 +187,7 @@ class Iron {
static void NewFrame();
static void DrawOn(C3D::Screen* screen);
static void Draw(const std::vector<Command::Ref>& data);
static Texture* WhiteTex() { return m_solid; }
static Texture::Ref WhiteTex() { return m_solid; }
/** Static renderer utility funcs */
@@ -185,7 +199,7 @@ class Iron {
const fvec2& c, ui clr);
static void CmdConvexPolyFilled(Command* cmd,
const std::vector<fvec2>& points, ui clr,
Texture* tex);
Texture::Ref tex);
static bool InBox(const fvec2& pos, const fvec2& size, const fvec4& area);
static bool InBox(const fvec2& pos, const fvec4& area);
static bool InBox(const fvec2& a, const fvec2& b, const fvec2& c,
@@ -206,7 +220,7 @@ class Iron {
static C3D::Shader* m_shader;
static mat4 m_mtx;
static int m_idx, m_vtx;
static Texture* m_solid;
static Texture::Ref m_solid;
static ui VertexCount;
static ui IndexCount;
};

View File

@@ -12,10 +12,22 @@ class Texture : public Asset {
public:
Texture() = default;
Texture(ksr path);
Texture(C3D_Tex* tex, const ivec2& size, const Rect& uv) {
Load(tex, size, uv);
}
~Texture();
AMY_SHARED(Texture);
void Load(ksr path);
void Load(kvr<uc> pixels, int w, int h, int bpp = 4,
Image::Format fmt = Image::RGBA);
void Load(C3D_Tex* tex, const ivec2& size, const Rect& uv) {
Unload();
pTex = tex;
pSize = size;
pUv = uv;
// Dont set as loaded as only the root tex can be loaded
}
void Unload();
int W() const { return pSize.x; }
@@ -26,7 +38,7 @@ class Texture : public Asset {
ivec2& Size() { return pSize; }
Rect& Uv() { return pUv; }
C3D_Tex* Ptr() { return pLoaded ? pTex : nullptr; }
C3D_Tex* Ptr() { return pTex; }
void Bind(int reg = 0);

View File

@@ -16,6 +16,8 @@ bool IsSingleBitNum(ui v);
ull GetTimeNano();
ull GetTimeMicro();
ull GetTimeMilli();
void String2U16(us* res, ksr src, size_t max);
std::string U16toU8(us* in, size_t max);
/**
* FNV Hash functiom (32 Bit)
* https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function

View File

@@ -6,11 +6,11 @@ namespace Amy {
void AssetMgr::AutoLoad(const ID& id, ksr path) {
if (path.ends_with(".png") || path.ends_with(".jpg") ||
path.ends_with(".bmp")) {
Texture* tex = new Texture();
auto tex = Texture::New();
tex->Load(path);
Add(id, tex);
} else if (path.ends_with(".shbin")) {
C3D::Shader* shader = new C3D::Shader();
auto shader = C3D::Shader::New();
shader->Load(path);
Add(id, shader);
} else {

File diff suppressed because it is too large Load Diff

View File

@@ -243,30 +243,30 @@ void Iron::Drawlist::DrawConvexPolyFilled(const std::vector<fvec2>& points,
void Iron::Drawlist::DrawText(const fvec2& pos, const std::string& text,
ui color) {
/*if (!pCurrentFont) {
if (!pCurrentFont) {
return;
}
std::vector<Command::Ref> cmds;
pCurrentFont->CmdTextEx(cmds, pos, color, pFontScale, text);
for (size_t i = 0; i < cmds.size(); i++) {
cmds[i]->Index = pDrawlist.size();
cmds[i]->Layer = Layer;
AddCommand(std::move(cmds[i]));
}*/
cmds[i]->Index = pData.size();
cmds[i]->Layer = pLayer;
Push(std::move(cmds[i]));
}
}
void Iron::Drawlist::DrawTextEx(const fvec2& p, const std::string& text,
ui color, ui flags, const fvec2& box) {
/*if (!pCurrentFont) {
if (!pCurrentFont) {
return;
}
std::vector<Command::Ref> cmds;
pCurrentFont->CmdTextEx(cmds, p, color, pFontScale, text, flags, box);
for (size_t i = 0; i < cmds.size(); i++) {
cmds[i]->Index = pDrawlist.size();
cmds[i]->Layer = Layer;
AddCommand(std::move(cmds[i]));
}*/
cmds[i]->Index = pData.size();
cmds[i]->Layer = pLayer;
Push(std::move(cmds[i]));
}
}
void Iron::Drawlist::DrawLine(const fvec2& a, const fvec2& b, ui color, int t) {

View File

@@ -1,17 +1,142 @@
#include <amethyst/iron.hpp>
#include <amethyst/utils.hpp>
#include <filesystem>
#if AMY_STB_TT == 1
#define STB_TRUETYPE_IMPLEMENTATION
#endif
#include <stb_truetype.h>
namespace Amy {
void Iron::Font::LoadBMF(ksr path) {}
void Iron::Font::LoadTTF(ksr path, int size) {}
void Iron::Font::LoadTTF(ksr path, int size) {
auto data = Amy::Utils::LoadFile2Mem(path);
LoadTTF(data, size);
}
void Iron::Font::pMakeAtlas(bool final, vec<uc>& font_tex, int texszs,
Texture* tex) {
void Iron::Font::LoadTTF(const vec<uc> &data, int size) {
/**
* Some additional Info:
* Removed the stbtt get bitmapbox as we dont need to place
* the glyps nicely in the tex. next step would be using the free
* space on the y axis to get mor glyphs inside
*/
PxHeight = size;
int texszs = Amy::Utils::NextPow2(PxHeight * 16);
if (texszs > 1024) {
texszs = 1024; // Max size
}
stbtt_fontinfo inf;
if (!stbtt_InitFont(&inf, data.data(), 0)) {
return;
}
float scale = stbtt_ScaleForPixelHeight(&inf, PxHeight);
int ascent, descent, lineGap;
stbtt_GetFontVMetrics(&inf, &ascent, &descent, &lineGap);
int baseline = static_cast<int>(ascent * scale);
// Cache to not render same codepoint tex twice
std::map<u32, int> buf_cache;
std::vector<u8> font_tex(texszs * texszs * 4, 0);
auto tex = Texture::New();
fvec2 off;
bool empty = true;
for (u32 ii = 0x0000; ii <= 0xFFFF; ii++) {
int gi = stbtt_FindGlyphIndex(&inf, ii);
if (gi == 0) continue;
if (stbtt_IsGlyphEmpty(&inf, gi)) continue;
int w = 0, h = 0, xo = 0, yo = 0;
unsigned char *bitmap =
stbtt_GetCodepointBitmap(&inf, scale, scale, ii, &w, &h, &xo, &yo);
if (!bitmap || w <= 0 || h <= 0) {
if (bitmap) free(bitmap);
continue;
}
u32 hashed_map =
Utils::HashMemory(std::vector<u8>(bitmap, bitmap + (w * h)));
if (buf_cache.find(hashed_map) != buf_cache.end()) {
Codepoint c = GetCodepoint(buf_cache[hashed_map]);
c.Cp = ii;
pCodeMap[ii] = c;
free(bitmap);
continue;
} else {
buf_cache[hashed_map] = ii;
}
// Next row
if (off.x + w > texszs) {
off.y += PxHeight;
off.x = 0.0f;
}
// Bake cause we go out of the tex
if (off.y + PxHeight > texszs) {
pMakeAtlas(false, font_tex, texszs, tex);
tex = Texture::New();
off = 0;
std::fill(font_tex.begin(), font_tex.end(), 0);
empty = true;
}
// UVs & Codepoint
Codepoint c;
fvec4 uvs;
// cast the ints to floats and not the floats...
// dont know where my mind was when creating the code
uvs.x = off.x / static_cast<float>(texszs);
uvs.y = off.y / static_cast<float>(texszs);
uvs.z = (off.x + w) / static_cast<float>(texszs);
uvs.w = (off.y + h) / static_cast<float>(texszs);
// Flip (too lazy to place it into the seq at top)
uvs.y = 1.f - uvs.y;
uvs.w = 1.f - uvs.w;
c.Uv = uvs;
c.Tex = tex;
c.Size = fvec2(w, h);
c.Offset = baseline + yo;
c.Cp = ii;
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
int map_pos = ((static_cast<int>(off.y) + y) * texszs +
(static_cast<int>(off.x) + x)) *
4;
font_tex[map_pos + 0] = 255;
font_tex[map_pos + 1] = 255;
font_tex[map_pos + 2] = 255;
font_tex[map_pos + 3] = bitmap[x + y * w];
}
}
empty = false;
pCodeMap[ii] = c;
free(bitmap);
// offset by 1 (prevents visual glitches i had)
off.x += w + 1;
}
if (!empty) {
pMakeAtlas(true, font_tex, texszs, tex);
}
}
void Iron::Font::pMakeAtlas(bool final, vec<uc> &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()) {
@@ -21,4 +146,124 @@ Iron::Font::Codepoint& Iron::Font::GetCodepoint(ui cp) {
}
return res->second;
}
fvec2 Iron::Font::GetTextBounds(ksr text, float scale) {
// Use wstring for exemple for german äöü
auto wtext = std::filesystem::path(text).wstring();
// Create a temp position and offset as [0, 0]
fvec2 res;
float x = 0;
// Curent Font Scale
float cfs = (PxFactor * scale) / (float)PxHeight;
float lh = (float)PxHeight * cfs;
size_t index = 0;
for (auto &it : wtext) {
if (it == L'\0') {
break;
}
index++;
auto cp = GetCodepoint(it);
if (!cp.Valid && it != '\n' && it != '\t' && it != ' ') {
continue;
}
switch (it) {
case L'\n':
res.y += lh;
res.x = std::max(res.x, x);
x = 0.f;
break;
case L'\t':
x += 16 * cfs;
break;
case L' ':
x += 4 * cfs;
// Fall trough here to get the same result as in
// TextCommand if/else Section
default:
x += cp.Size.x * cfs;
if (index != wtext.size()) {
x += 2 * cfs;
}
break;
}
}
res.x = std::max(res.x, x);
res.y += lh;
return res;
}
void Iron::Font::CmdTextEx(vec<Command::Ref> &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;
fvec2 td;
fvec2 rpos = pos;
fvec2 rbox = box;
if (flags & (AmyTextFlags_AlignMid | AmyTextFlags_AlignRight)) {
td = GetTextBounds(text, scale);
}
if (flags & AmyTextFlags_AlignMid) {
rpos = rbox * 0.5 - td * 0.5 + pos;
}
if (flags & AmyTextFlags_AlignRight) {
rpos.x = rpos.x - td.x;
}
std::vector<std::string> lines;
std::istringstream iss(text);
std::string tmp;
while (std::getline(iss, tmp)) {
lines.push_back(tmp);
}
for (auto &it : lines) {
/*if (flags & AmyTextFlags_Short) {
fvec2 tmp_dim;
it = ShortText(it, box.x() - pos.x(), tmp_dim);
}*/
// Bitte nicht nachmachen... Also ernsthaft jz, bitte macht das nicht
auto wline = std::filesystem::path(it).wstring();
auto cmd = Command::New();
auto Tex = GetCodepoint(wline[0]).Tex;
cmd->Tex = Tex;
for (auto &jt : wline) {
auto cp = GetCodepoint(jt);
if ((!cp.Valid && jt != L' ' && jt != L'\n' && jt != L'\t') &&
jt != L'\r') {
continue;
}
if (Tex != cp.Tex) {
cmds.push_back(std::move(cmd));
cmd = Command::New();
Tex = cp.Tex;
cmd->Tex = Tex;
}
if (jt == L'\t') {
off.x += 16 * cfs;
} else {
if (jt != L' ') {
if (flags & AmyTextFlags_Shaddow) {
// Draw
Rect rec = Iron::PrimRect(
rpos + vec2(off.x + 1, off.y + (cp.Offset * cfs)) + 1,
cp.Size * cfs, 0.f);
Iron::CmdQuad(cmd.get(), rec, cp.Uv, 0xff111111);
}
// Draw
Rect rec = Iron::PrimRect(rpos + off + fvec2(0, (cp.Offset * cfs)),
cp.Size * cfs, 0.f);
Iron::CmdQuad(cmd.get(), rec, cp.Uv, color);
off.x += cp.Size.x * cfs + 2 * cfs;
} else {
off.x += 4 * cfs;
}
}
}
cmds.push_back(std::move(cmd));
off.y += lh;
off.x = 0;
}
}
} // namespace Amy

View File

@@ -51,7 +51,7 @@ int Iron::uLocProj = 0;
C3D::Shader* Iron::m_shader = nullptr;
mat4 Iron::m_mtx;
int Iron::m_idx = 0, Iron::m_vtx = 0;
Texture* Iron::m_solid = nullptr;
Texture::Ref Iron::m_solid = nullptr;
ui Iron::VertexCount = 0;
ui Iron::IndexCount = 0;
@@ -63,7 +63,7 @@ void Iron::Init() {
}
void Iron::Exit() {
delete m_solid;
m_solid.reset();
delete m_shader;
m_vbuf.clear();
m_ibuf.clear();
@@ -89,7 +89,7 @@ void Iron::Draw(const std::vector<Iron::Command::Ref>& data) {
pFragConfig();
size_t i = 0;
while (i < data.size()) {
Texture* tex = data[i]->Tex;
Texture::Ref tex = data[i]->Tex;
if (!tex) {
i++;
continue;
@@ -157,7 +157,7 @@ void Iron::pFragConfig() {
void Iron::pInitSolidTex() {
// i know there is a lot of memory wasted :(
std::vector<uc> pixels(16 * 16 * 4, 0xff);
m_solid = new Texture();
m_solid = Texture::New();
m_solid->Load(pixels, 16, 16);
if (!m_solid->Ptr()) {
throw Error("white tex failed to load!");
@@ -239,14 +239,15 @@ void Iron::CmdTriangle(Command* cmd, const fvec2& a, const fvec2& b,
}
void Iron::CmdConvexPolyFilled(Command* cmd, const std::vector<fvec2>& points,
ui color, Texture* tex) {
ui color, Texture::Ref tex) {
if (points.size() < 3 || tex == nullptr) {
#ifdef AMY_GOD_DEV
return;
#else
throw std::runtime_error("[amy] iron: trying to render convex poly with " +
std::to_string(points.size()) +
" points and Texture " + std::to_string((ui)tex));
" points and Texture " +
std::to_string((ui)tex.get()));
#endif
}
// Support for Custom Textures (UV calculation)

View File

@@ -70,7 +70,7 @@ ull GetTimeMilli() {
.count();
}
void String2U16(us* res, const std::string& src, size_t max) {
void String2U16(us* res, ksr src, size_t max) {
/// GOT FORCED TO REPLACE std::wstring_convert by some
/// manual work as it got removed in cxx20
/// TODO ///