# 0.2.6-1

- Fix TTF FOnt loader to support any size between 8 and 64
- Fix UI7 Image Custom SIze support
- Add new Syste mfor Image buffer modification to image lib
This commit is contained in:
2025-03-05 12:06:40 +01:00
parent c9e14ad08f
commit 229d54f088
9 changed files with 154 additions and 30 deletions

View File

@ -24,6 +24,7 @@ SOFTWARE.
#include <3ds.h>
#include <pd/external/stb_truetype.h>
#include <pd/core/bit_util.hpp>
#include <pd/core/io.hpp>
#include <pd/core/strings.hpp>
#include <pd/core/sys.hpp>
@ -31,30 +32,34 @@ SOFTWARE.
namespace PD {
namespace LI {
void Font::LoadTTF(const std::string& path, int height) {
sysfont = false;
void Font::LoadTTF(const std::string &path, int height) {
sysfont = false; // Not using System Font
TT::Scope st("LI_LoadTTF_" + path);
pixel_height = height;
int quad = height * 16;
pixel_height = height; // Set internel pixel height
// Use NextPow2 to be able to use sizes between for example 16 and 32
// before it only was possible to use 8, 16, 32, 64 as size
int texszs = BitUtil::GetPow2(height * 16);
// Load stbtt
stbtt_fontinfo inf;
std::ifstream loader(path, std::ios::binary);
if (!loader.is_open()) return;
loader.seekg(0, std::ios::end);
size_t len = loader.tellg();
loader.seekg(0, std::ios::beg);
unsigned char* buffer = new unsigned char[len];
loader.read(reinterpret_cast<char*>(buffer), len);
unsigned char *buffer = new unsigned char[len];
loader.read(reinterpret_cast<char *>(buffer), len);
loader.close();
stbtt_InitFont(&inf, buffer, 0);
std::vector<unsigned char> font_tex(quad * quad);
std::vector<unsigned char> font_tex(texszs * texszs); // Create font Texture
float scale = stbtt_ScaleForPixelHeight(&inf, pixel_height);
int ascent, descent, lineGap;
stbtt_GetFontVMetrics(&inf, &ascent, &descent, &lineGap);
int baseline = static_cast<int>(ascent * scale);
std::map<u32, int> buf_cache;
std::map<u32, int> buf_cache; // Cache to not render same codepoint tex twice
/// Load Codepoints
auto tex = Texture::New();
vec2 off;
for (u32 ii = 0x0000; ii < 0xFFFF; ii++) {
@ -68,11 +73,13 @@ void Font::LoadTTF(const std::string& path, int height) {
Codepoint c;
int w = 0, h = 0, xo = 0, yo = 0;
unsigned char* bitmap =
unsigned char *bitmap =
stbtt_GetCodepointBitmap(&inf, scale, scale, i, &w, &h, &xo, &yo);
int x0, y0, x1, y1;
stbtt_GetCodepointBitmapBox(&inf, i, scale, scale, &x0, &y0, &x1, &y1);
// Check if Codepoint exists as hash and if it is use its already written
// data
u32 hashed_map = IO::HashMemory(std::vector<u8>(bitmap, bitmap + (w * h)));
if (buf_cache.find(hashed_map) != buf_cache.end()) {
c = GetCodepoint(buf_cache[hashed_map]);
@ -84,25 +91,27 @@ void Font::LoadTTF(const std::string& path, int height) {
buf_cache[hashed_map] = i;
}
if (off[0] + w > quad) {
if (off[0] + w > texszs) {
off[1] += pixel_height;
off[0] = 0;
}
// Set UV Data
vec4 uvs;
uvs[0] = static_cast<float>(off.x() / (float)quad);
uvs[1] = static_cast<float>(1.f - (off.y() / (float)quad));
uvs[2] = static_cast<float>((float)(off.x() + w) / (float)quad);
uvs[3] = static_cast<float>(1.f - (float)(off.y() + h) / (float)quad);
uvs[0] = static_cast<float>(off.x() / (float)texszs);
uvs[1] = static_cast<float>(1.f - (off.y() / (float)texszs));
uvs[2] = static_cast<float>((float)(off.x() + w) / (float)texszs);
uvs[3] = static_cast<float>(1.f - (float)(off.y() + h) / (float)texszs);
c.uv(uvs);
c.tex(tex);
c.size(vec2(w, h));
c.off(baseline + yo);
// Render glyph
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
int map_pos = ((off[1] + y) * quad + (off[0] + x));
int map_pos = ((off[1] + y) * texszs + (off[0] + x));
font_tex[map_pos] = bitmap[x + y * w];
}
}
@ -112,19 +121,21 @@ void Font::LoadTTF(const std::string& path, int height) {
// Small Patch to avoid some possible artifacts
off[0] += w + 1;
if (off[0] + w > quad) {
if (off[0] + w > texszs) {
off[1] += pixel_height;
if (off[1] + pixel_height > quad) {
if (off[1] + pixel_height > texszs) {
break;
}
off[0] = 0;
}
}
tex->LoadPixels(font_tex, quad, quad, Texture::A8, Texture::LINEAR);
// Load the Texture and append to list
tex->LoadPixels(font_tex, texszs, texszs, Texture::A8, Texture::LINEAR);
textures.push_back(tex);
}
Font::Codepoint& Font::GetCodepoint(u32 cp) {
Font::Codepoint &Font::GetCodepoint(u32 cp) {
// Check if codepoijt exist or return a static invalid one
auto res = cpmap.find(cp);
if (res == cpmap.end()) {
static Codepoint invalid;
@ -134,16 +145,19 @@ Font::Codepoint& Font::GetCodepoint(u32 cp) {
}
void Font::LoadSystemFont() {
TT::Scope st("LI_SystemFont");
sysfont = true;
fontEnsureMapped();
TT::Scope st("LI_SystemFont"); // Trace loading time
sysfont = true; // Set as System Font
fontEnsureMapped(); // Call this to be sure the font is mapped
// Get some const references for system font loading
const auto fnt = fontGetSystemFont();
const auto fnt_info = fontGetInfo(fnt);
const auto glyph_info = fontGetGlyphInfo(fnt);
// Resize the Texture list by the num of sysfont textures
this->textures.resize(glyph_info->nSheets + 1);
/// Modify the Pixel Height by 1.1f to fit the
/// Size og ttf font Rendering
pixel_height = glyph_info->cellHeight * 1.1f;
// Load the Textures and make sure they don't auto unload
for (size_t i = 0; i < glyph_info->nSheets; i++) {
auto stex = Texture::New();
auto tx = new C3D_Tex;
@ -162,6 +176,7 @@ void Font::LoadSystemFont() {
textures[i] = stex;
}
std::vector<unsigned int> charSet;
// Write the Charset into a vector
for (auto cmap = fnt_info->cmap; cmap; cmap = cmap->next) {
if (cmap->mappingMethod == CMAP_TYPE_DIRECT) {
if (cmap->codeEnd >= cmap->codeBegin) {
@ -194,9 +209,11 @@ void Font::LoadSystemFont() {
}
}
// Sort the charset and make sure all values are unique
std::sort(charSet.begin(), charSet.end());
charSet.erase(std::unique(charSet.begin(), charSet.end()));
// Setup the Codepoint map by the charset
for (auto cp : charSet) {
int gidx = fontGlyphIndexFromCodePoint(fnt, cp);
if (gidx >= 0xFFFF) continue;
@ -219,4 +236,4 @@ void Font::LoadSystemFont() {
}
}
} // namespace LI
} // namespace PD
} // namespace PD