From 229d54f088a9ea61a9f3e1e9aee7a55297023299 Mon Sep 17 00:00:00 2001 From: tobid7 Date: Wed, 5 Mar 2025 12:06:40 +0100 Subject: [PATCH] # 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 --- CMakeLists.txt | 3 +- README.md | 6 +-- include/pd.hpp | 1 + include/pd/image/img_edit.hpp | 64 ++++++++++++++++++++++++++++++ include/pd/lithium/font.hpp | 2 +- include/pd/ui7/container/image.hpp | 4 +- source/image/img_edit.cpp | 39 ++++++++++++++++++ source/lithium/font.cpp | 63 ++++++++++++++++++----------- source/ui7/container/image.cpp | 2 +- 9 files changed, 154 insertions(+), 30 deletions(-) create mode 100644 include/pd/image/img_edit.hpp create mode 100644 source/image/img_edit.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9686864..380b969 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,7 @@ execute_process( ) # Set Project -project(palladium LANGUAGES C CXX VERSION 0.2.5) +project(palladium LANGUAGES C CXX VERSION 0.2.6) option(PD_BUILD_TESTS "Sets if TestApp and TestBench get build" OFF) @@ -80,6 +80,7 @@ source/core/timetrace.cpp) ## Image Source Code set(IMAGE_SRC +source/image/img_edit.cpp source/image/img_blur.cpp source/image/img_convert.cpp) diff --git a/README.md b/README.md index ce008b8..8691003 100644 --- a/README.md +++ b/README.md @@ -29,14 +29,14 @@ make install |---|---|---|---| | pd-core | 0.2.4 | multi | none | | pd-external | 0.1.0 | multi | none | -| pd-image | 0.2.4 | multi | pd-core | +| pd-image | 0.2.6 | multi | pd-core | | pd-drivers | 0.2.4 | multi | pd-core | | pd-lib3ds | 0.2.4 | 3ds | pd-core, pd-drivers | | pd-net | 0.2.4 | 3ds | pd-core, pd-lib3ds | -| pd-lithium | 0.2.4 | 3ds | pd-core, pd-image pd-lib3ds, citro3d | +| pd-lithium | 0.2.6 | 3ds | pd-core, pd-image pd-lib3ds, citro3d | | pd-sound | 0.2.4 | 3ds | pd-core, mpg123 | | pd-overlays | 0.2.4 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium, pd-ui7 | -| pd-ui7 | 0.2.4 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium | +| pd-ui7 | 0.2.6 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium | | pd-app | 0.2.4 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium | ## Credits diff --git a/include/pd.hpp b/include/pd.hpp index b7dd137..1406c42 100644 --- a/include/pd.hpp +++ b/include/pd.hpp @@ -40,6 +40,7 @@ SOFTWARE. // Image #include #include +#include // Drivers #include // Overlays diff --git a/include/pd/image/img_edit.hpp b/include/pd/image/img_edit.hpp new file mode 100644 index 0000000..8edaa9b --- /dev/null +++ b/include/pd/image/img_edit.hpp @@ -0,0 +1,64 @@ +#pragma once + +/* +MIT License + +Copyright (c) 2024 - 2025 tobid7 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include + +namespace PD { +class ImgEdit { + public: + ImgEdit() = default; + ImgEdit(const std::string& path) { this->Load(path); } + ImgEdit(const std::vector& buf) { this->Load(buf); } + ImgEdit(const std::vector& buf, int w, int h, int fmt = 4) { + this->Copy(buf, w, h, fmt); + } + ~ImgEdit() = default; + + void Load(const std::string& path); + void Load(const std::vector& buf); + void Copy(const std::vector& buf, int w, int h, int fmt = 4); + + std::vector& GetBuffer() { return buffer; } + std::vector GetBuffer() const { return buffer; } + + int Width() const { return w; } + int Height() const { return h; } + + u8& operator[](int idx) { return buffer[idx]; } + u8 operator[](int idx) const { return buffer[idx]; } + + // Probably these make th eabove ones useless + + operator std::vector&() { return buffer; } + operator std::vector() const { return buffer; } + + private: + std::vector buffer; + int w = 0; + int h = 0; + int fmt = 0; +}; +} // namespace PD \ No newline at end of file diff --git a/include/pd/lithium/font.hpp b/include/pd/lithium/font.hpp index e74f391..da1bd25 100644 --- a/include/pd/lithium/font.hpp +++ b/include/pd/lithium/font.hpp @@ -148,7 +148,7 @@ class Font : public SmartCtor { */ void LoadTTF(const std::string& path, int px_height = 32); /** - * Load 3DS System FOnt + * Load 3DS System Font */ void LoadSystemFont(); /** diff --git a/include/pd/ui7/container/image.hpp b/include/pd/ui7/container/image.hpp index e989478..6991719 100644 --- a/include/pd/ui7/container/image.hpp +++ b/include/pd/ui7/container/image.hpp @@ -43,6 +43,7 @@ class Image : public Container { this->screen = lr->CurrentScreen(); this->img = img; this->SetPos(pos); + this->newsize = size; if (size.x() != 0 || size.y() != 0) { this->SetSize(size); } else { @@ -58,7 +59,8 @@ class Image : public Container { void Draw() override; private: - Texture::Ref img; ///< Texture reference to the Image + Texture::Ref img; ///< Texture reference to the Image + vec2 newsize = 0.f; ///< New Size }; } // namespace UI7 } // namespace PD \ No newline at end of file diff --git a/source/image/img_edit.cpp b/source/image/img_edit.cpp new file mode 100644 index 0000000..6c7de54 --- /dev/null +++ b/source/image/img_edit.cpp @@ -0,0 +1,39 @@ +/* +MIT License + +Copyright (c) 2024 - 2025 tobid7 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include + +#include +#include +#include + +namespace PD { +void ImgEdit::Load(const std::string& path) { + u8* buf = stbi_load(path.c_str(), &w, &h, &fmt, 4); + buffer.assign(buf, buf + (w * h * 4)); + stbi_image_free(buf); +} +void ImgEdit::Load(const std::vector& buf) {} +void ImgEdit::Copy(const std::vector& buf, int w, int h, int fmt) {} +} // namespace PD \ No newline at end of file diff --git a/source/lithium/font.cpp b/source/lithium/font.cpp index 8cb08a3..0929af2 100644 --- a/source/lithium/font.cpp +++ b/source/lithium/font.cpp @@ -24,6 +24,7 @@ SOFTWARE. #include <3ds.h> #include +#include #include #include #include @@ -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(buffer), len); + unsigned char *buffer = new unsigned char[len]; + loader.read(reinterpret_cast(buffer), len); loader.close(); stbtt_InitFont(&inf, buffer, 0); - std::vector font_tex(quad * quad); + std::vector 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(ascent * scale); - std::map buf_cache; + std::map 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(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(off.x() / (float)quad); - uvs[1] = static_cast(1.f - (off.y() / (float)quad)); - uvs[2] = static_cast((float)(off.x() + w) / (float)quad); - uvs[3] = static_cast(1.f - (float)(off.y() + h) / (float)quad); + uvs[0] = static_cast(off.x() / (float)texszs); + uvs[1] = static_cast(1.f - (off.y() / (float)texszs)); + uvs[2] = static_cast((float)(off.x() + w) / (float)texszs); + uvs[3] = static_cast(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 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 \ No newline at end of file +} // namespace PD diff --git a/source/ui7/container/image.cpp b/source/ui7/container/image.cpp index d807e2c..9157592 100644 --- a/source/ui7/container/image.cpp +++ b/source/ui7/container/image.cpp @@ -29,7 +29,7 @@ void Image::Draw() { Assert(ren.get() && list.get(), "Did you run Container::Init correctly?"); Assert(img.get(), "Image is nullptr!"); ren->OnScreen(screen); - list->AddImage(FinalPos(), img); + list->AddImage(FinalPos(), img, newsize); } } // namespace UI7 } // namespace PD \ No newline at end of file