Load Fonts in A8 format, Fix Freeze with BMF
This commit is contained in:
@@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED true)
|
|||||||
|
|
||||||
option(AMY_GOD_DEV "Turn this on if you think you are god" OFF)
|
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
|
# THis option should be disabled if you use STB_IMAGE in you main project
|
||||||
set(AMY_BUILD_STB_IMAGE CACHE BOOL 0)
|
set(AMY_BUILD_STB_IMAGE 0)
|
||||||
set(AMY_BUILD_STB_TRUETYPE 1)
|
set(AMY_BUILD_STB_TRUETYPE 1)
|
||||||
set(AMY_WITH_MPG123 "Include MP3 Support" CACHE BOOL 1)
|
set(AMY_WITH_MPG123 "Include MP3 Support" CACHE BOOL 1)
|
||||||
|
|
||||||
|
|||||||
@@ -11,18 +11,18 @@ class Example : public Amy::App {
|
|||||||
Top = C3D::CreateScreen(GFX_TOP);
|
Top = C3D::CreateScreen(GFX_TOP);
|
||||||
Mgr = new Amy::AssetMgr();
|
Mgr = new Amy::AssetMgr();
|
||||||
Iron::Init();
|
Iron::Init();
|
||||||
|
Mgr->AutoLoad("icon", "romfs:/icon.png");
|
||||||
auto fnt = Iron::Font::New();
|
auto fnt = Iron::Font::New();
|
||||||
fnt->LoadBMF("romfs:/ComicNeue.png");
|
fnt->LoadBMF("romfs:/ComicNeue.png");
|
||||||
Mgr->AutoLoad("icon", "romfs:/icon.png");
|
|
||||||
Mgr->Add("font", fnt);
|
Mgr->Add("font", fnt);
|
||||||
// Mgr->AutoLoad("font", "romfs:/ComicNeue.ttf");
|
// Mgr->AutoLoad("font", "romfs:/ComicNeue.ttf");
|
||||||
dl = new Iron::Drawlist();
|
dl = Iron::Drawlist::New();
|
||||||
dl->SetFont(Mgr->Get<Iron::Font>("font"));
|
dl->SetFont(Mgr->Get<Iron::Font>("font"));
|
||||||
}
|
}
|
||||||
|
|
||||||
~Example() {
|
~Example() {
|
||||||
|
dl.reset();
|
||||||
delete Top;
|
delete Top;
|
||||||
delete dl;
|
|
||||||
delete Mgr;
|
delete Mgr;
|
||||||
Iron::Exit();
|
Iron::Exit();
|
||||||
C3D::Deinit();
|
C3D::Deinit();
|
||||||
@@ -59,7 +59,7 @@ class Example : public Amy::App {
|
|||||||
|
|
||||||
Iron::NewFrame();
|
Iron::NewFrame();
|
||||||
Iron::DrawOn(Top);
|
Iron::DrawOn(Top);
|
||||||
Iron::Draw(*dl);
|
Iron::Draw(dl->Data());
|
||||||
dl->Clear();
|
dl->Clear();
|
||||||
C3D::EndFrame();
|
C3D::EndFrame();
|
||||||
Amy::GTrace::End("Main");
|
Amy::GTrace::End("Main");
|
||||||
@@ -67,7 +67,7 @@ class Example : public Amy::App {
|
|||||||
|
|
||||||
C3D::Screen* Top;
|
C3D::Screen* Top;
|
||||||
Amy::AssetMgr* Mgr;
|
Amy::AssetMgr* Mgr;
|
||||||
Iron::Drawlist* dl;
|
Iron::Drawlist::Ref dl = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class Iron {
|
|||||||
struct Codepoint {
|
struct Codepoint {
|
||||||
ui Cp = 0;
|
ui Cp = 0;
|
||||||
fvec4 Uv;
|
fvec4 Uv;
|
||||||
Texture::Ref Tex;
|
Texture::Ref Tex = nullptr;
|
||||||
fvec2 Size;
|
fvec2 Size;
|
||||||
float Offset = 0; // Unused??
|
float Offset = 0; // Unused??
|
||||||
bool Valid = true;
|
bool Valid = true;
|
||||||
@@ -213,7 +213,7 @@ class Iron {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static void pSetupShader();
|
static void pSetupShader();
|
||||||
static void pFragConfig();
|
static void pFragConfig(GPU_TEXCOLOR clr);
|
||||||
static void pInitSolidTex();
|
static void pInitSolidTex();
|
||||||
static bool pCheckSize(size_t idx, size_t vtx);
|
static bool pCheckSize(size_t idx, size_t vtx);
|
||||||
|
|
||||||
|
|||||||
@@ -69,15 +69,14 @@ void C3D::Shader::Load(const std::vector<uc>& data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void C3D::Shader::Compile(const std::string& code) {
|
void C3D::Shader::Compile(const std::string& code) {
|
||||||
auto ret = Pica::AssembleCode(code.c_str());
|
Load(Pica::AssembleCode(code.c_str()));
|
||||||
Load(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void C3D::Shader::Use() {
|
void C3D::Shader::Use() {
|
||||||
// C3D_BindProgram(&pProgram);
|
|
||||||
// code works perfectly without C3D_BindProgram
|
// code works perfectly without C3D_BindProgram
|
||||||
// but nor withour shaderProgramUse ...
|
// but nor without shaderProgramUse ...
|
||||||
shaderProgramUse(&pProgram);
|
shaderProgramUse(&pProgram);
|
||||||
|
C3D_BindProgram(&pProgram);
|
||||||
C3D_SetAttrInfo(&pInfo);
|
C3D_SetAttrInfo(&pInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,17 @@ int Image::GetBppOfFmt(const Image::Format& fmt) {
|
|||||||
void Image::Convert(Image& img, const Format& dst) {
|
void Image::Convert(Image& img, const Format& dst) {
|
||||||
if (img.pFmt == dst) {
|
if (img.pFmt == dst) {
|
||||||
return;
|
return;
|
||||||
|
} else if (img.pFmt == RGBA && dst == A8) {
|
||||||
|
std::vector<uc> cpy = img.pBuffer;
|
||||||
|
img.pBuffer.resize(img.pW * img.pH);
|
||||||
|
for (int y = 0; y < img.pH; y++) {
|
||||||
|
for (int x = 0; x < img.pW; x++) {
|
||||||
|
int src = (y * img.pW + x) * 4;
|
||||||
|
int dst = (y * img.pW + x);
|
||||||
|
img.pBuffer[dst] = cpy[src + 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
img.pFmt = A8;
|
||||||
} else if (img.pFmt == RGB && dst == BGR) {
|
} else if (img.pFmt == RGB && dst == BGR) {
|
||||||
Utils::Image::ReverseBuf(img.pBuffer, img.pW, img.pH, 3);
|
Utils::Image::ReverseBuf(img.pBuffer, img.pW, img.pH, 3);
|
||||||
img.pFmt = BGR;
|
img.pFmt = BGR;
|
||||||
|
|||||||
@@ -12,12 +12,14 @@ namespace Amy {
|
|||||||
// Dont read this code please ... tnaks
|
// Dont read this code please ... tnaks
|
||||||
void Iron::Font::LoadBMF(ksr path) {
|
void Iron::Font::LoadBMF(ksr path) {
|
||||||
Image img(path);
|
Image img(path);
|
||||||
if (img.Width() != img.Height() || img.Bpp() != 4) {
|
img.Convert(Image::A8);
|
||||||
|
if (img.Width() != img.Height() || img.Bpp() != 1 || img.Width() <= 0 ||
|
||||||
|
img.Height() <= 0) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"[Amy] Font: BMF is not in rgba or not 1x1 dimensioned!");
|
"[Amy] Font: BMF is not in rgba or not 1x1 dimensioned!");
|
||||||
}
|
}
|
||||||
auto base = Amy::Texture::New();
|
auto base = Amy::Texture::New();
|
||||||
base->Load(img.GetBuffer(), img.Width(), img.Height(), img.Bpp());
|
base->Load(img.GetBuffer(), img.Width(), img.Height(), img.Bpp(), img.Fmt());
|
||||||
base->Unloadable(false);
|
base->Unloadable(false);
|
||||||
PxHeight = img.Height() / 16;
|
PxHeight = img.Height() / 16;
|
||||||
for (int i = 0; i < img.Height(); i += PxHeight) {
|
for (int i = 0; i < img.Height(); i += PxHeight) {
|
||||||
@@ -26,26 +28,27 @@ void Iron::Font::LoadBMF(ksr path) {
|
|||||||
Amy::Texture::Ref tex = Amy::Texture::New();
|
Amy::Texture::Ref tex = Amy::Texture::New();
|
||||||
for (int y = i; y < i + PxHeight; y++) {
|
for (int y = i; y < i + PxHeight; y++) {
|
||||||
for (int x = j; x < j + PxHeight; x++) {
|
for (int x = j; x < j + PxHeight; x++) {
|
||||||
if (img.GetBuffer()[((y * img.Width() + x) * 4) + 3] != 0) {
|
if (img.GetBuffer()[y * img.Width() + x] != 0) {
|
||||||
maxw = std::max(maxw, x - j);
|
maxw = std::max(maxw, x - j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maxw++;
|
|
||||||
tex->Load(base->Ptr(), base->Size(), base->Uv());
|
|
||||||
Codepoint cp;
|
Codepoint cp;
|
||||||
|
cp.Valid = maxw != 0;
|
||||||
cp.Cp = (i / PxHeight) * 16 + (j / PxHeight);
|
cp.Cp = (i / PxHeight) * 16 + (j / PxHeight);
|
||||||
cp.Offset = 0.f;
|
cp.Offset = 0.f;
|
||||||
cp.Size = fvec2(maxw, PxHeight);
|
if (cp.Valid) {
|
||||||
|
tex->Load(base->Ptr(), base->Size(), base->Uv());
|
||||||
|
cp.Size = fvec2(maxw + 1, PxHeight);
|
||||||
cp.Tex = tex;
|
cp.Tex = tex;
|
||||||
cp.Uv = fvec4(float(j) / float(img.Width()),
|
cp.Uv = fvec4(float(j) / float(img.Width()),
|
||||||
1.f - float(i) / float(img.Height()),
|
1.f - float(i) / float(img.Height()),
|
||||||
float(j + maxw) / float(img.Width()),
|
float(j + maxw + 1) / float(img.Width()),
|
||||||
1.f - float(i + PxHeight) / float(img.Height()));
|
1.f - float(i + PxHeight) / float(img.Height()));
|
||||||
cp.Valid = maxw != 0;
|
|
||||||
pCodeMap[(i / PxHeight) * 16 + (j / PxHeight)] = cp;
|
|
||||||
Textures.push_back(tex);
|
Textures.push_back(tex);
|
||||||
}
|
}
|
||||||
|
pCodeMap[(i / PxHeight) * 16 + (j / PxHeight)] = cp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +84,7 @@ void Iron::Font::LoadTTF(const vec<uc>& data, int size) {
|
|||||||
// Cache to not render same codepoint tex twice
|
// Cache to not render same codepoint tex twice
|
||||||
std::map<u32, int> buf_cache;
|
std::map<u32, int> buf_cache;
|
||||||
|
|
||||||
std::vector<u8> font_tex(texszs * texszs * 4, 0);
|
std::vector<u8> font_tex(texszs * texszs, 0);
|
||||||
auto tex = Texture::New();
|
auto tex = Texture::New();
|
||||||
fvec2 off;
|
fvec2 off;
|
||||||
|
|
||||||
@@ -147,12 +150,8 @@ void Iron::Font::LoadTTF(const vec<uc>& data, int size) {
|
|||||||
for (int y = 0; y < h; ++y) {
|
for (int y = 0; y < h; ++y) {
|
||||||
for (int x = 0; x < w; ++x) {
|
for (int x = 0; x < w; ++x) {
|
||||||
int map_pos = ((static_cast<int>(off.y) + y) * texszs +
|
int map_pos = ((static_cast<int>(off.y) + y) * texszs +
|
||||||
(static_cast<int>(off.x) + x)) *
|
(static_cast<int>(off.x) + x));
|
||||||
4;
|
font_tex[map_pos] = bitmap[x + y * w];
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +170,7 @@ void Iron::Font::LoadTTF(const vec<uc>& data, int size) {
|
|||||||
|
|
||||||
void Iron::Font::pMakeAtlas(bool final, vec<uc>& font_tex, int texszs,
|
void Iron::Font::pMakeAtlas(bool final, vec<uc>& font_tex, int texszs,
|
||||||
Texture::Ref tex) {
|
Texture::Ref tex) {
|
||||||
tex->Load(font_tex, texszs, texszs);
|
tex->Load(font_tex, texszs, texszs, 1, Amy::Image::A8);
|
||||||
Textures.push_back(tex);
|
Textures.push_back(tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,14 +80,14 @@ void Iron::DrawOn(C3D::Screen* screen) {
|
|||||||
void Iron::Draw(const std::vector<Iron::Command::Ref>& data) {
|
void Iron::Draw(const std::vector<Iron::Command::Ref>& data) {
|
||||||
// disable depthtest cause we have no z buffer
|
// disable depthtest cause we have no z buffer
|
||||||
C3D::DepthTest(false);
|
C3D::DepthTest(false);
|
||||||
pFragConfig();
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while (i < data.size()) {
|
while (i < data.size()) {
|
||||||
Texture::Ref tex = data[i]->Tex;
|
Texture::Ref tex = data[i]->Tex;
|
||||||
if (!tex) {
|
if (!tex || !tex->Ptr()) {
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
pFragConfig(tex->Ptr()->fmt);
|
||||||
auto scissorOn = data[i]->ScissorOn;
|
auto scissorOn = data[i]->ScissorOn;
|
||||||
auto scissor = data[i]->ScissorRect;
|
auto scissor = data[i]->ScissorRect;
|
||||||
auto start = m_idx;
|
auto start = m_idx;
|
||||||
@@ -133,17 +133,30 @@ void Iron::pSetupShader() {
|
|||||||
uLocProj = m_shader->loc("projection");
|
uLocProj = m_shader->loc("projection");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Iron::pFragConfig() {
|
void Iron::pFragConfig(GPU_TEXCOLOR clr) {
|
||||||
C3D::Frag::Edit();
|
C3D::Frag::Edit();
|
||||||
|
switch (clr) {
|
||||||
|
case GPU_A4:
|
||||||
|
case GPU_A8:
|
||||||
|
case GPU_L4:
|
||||||
|
case GPU_L8:
|
||||||
|
C3D::Frag::Src(C3D_Alpha, GPU_TEXTURE0);
|
||||||
|
C3D::Frag::Func(C3D_RGB, GPU_REPLACE);
|
||||||
|
C3D::Frag::Func(C3D_Alpha, GPU_MODULATE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
C3D::Frag::Src(C3D_Both, GPU_TEXTURE0);
|
C3D::Frag::Src(C3D_Both, GPU_TEXTURE0);
|
||||||
C3D::Frag::Func(C3D_Both, GPU_MODULATE);
|
C3D::Frag::Func(C3D_Both, GPU_MODULATE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Iron::pInitSolidTex() {
|
void Iron::pInitSolidTex() {
|
||||||
// i know there is a lot of memory wasted :(
|
// i know there is a lot of memory wasted :(
|
||||||
std::vector<uc> pixels(16 * 16 * 4, 0xff);
|
std::vector<uc> pixels(16 * 16, 0xff);
|
||||||
m_solid = Texture::New();
|
m_solid = Texture::New();
|
||||||
m_solid->Load(pixels, 16, 16);
|
m_solid->Load(pixels, 16, 16, 1, Amy::Image::A8);
|
||||||
if (!m_solid->Ptr()) {
|
if (!m_solid->Ptr()) {
|
||||||
throw Error("white tex failed to load!");
|
throw Error("white tex failed to load!");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user