From e76e88771c0ac16aa028a48b32499f9ac3630dff Mon Sep 17 00:00:00 2001 From: jingkaimori Date: Thu, 19 Sep 2024 00:10:06 +0800 Subject: [PATCH] feat: add text tile modifier fix stability and format --- games/devtest/mods/testnodes/textures.lua | 17 ++++ src/client/imagesource.cpp | 97 +++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/games/devtest/mods/testnodes/textures.lua b/games/devtest/mods/testnodes/textures.lua index 0d4194753..4aeb25048 100644 --- a/games/devtest/mods/testnodes/textures.lua +++ b/games/devtest/mods/testnodes/textures.lua @@ -367,3 +367,20 @@ core.register_node("testnodes:tga_type10_32bpp_tb", { use_texture_alpha = "blend", groups = { dig_immediate = 2 }, }) + +minetest.register_node("testnodes:glyph_font", { + description = S("Combine Test Node"), + tiles = {{ + name = "testnodes_generated_mb.png".. + "^[text:regular font::::white".. + "^[text:large font(16pt):16::0,32:white".. + "^[text:larger font(32pt):32::0,64:white".. + "^[text:bold font(20pt):20:bold:0,96:white".. + "^[text:italic font(20pt):20:italic:0,128:white".. + "^[text:monospace font(20pt):20:mono:0,160:white".. + "^[text:red monospace font(20pt):20:mono:0,192:red", + align_style = "world", + scale = 8, + }}, + groups = { dig_immediate = 2 }, +}) diff --git a/src/client/imagesource.cpp b/src/client/imagesource.cpp index e2538c372..82201c214 100644 --- a/src/client/imagesource.cpp +++ b/src/client/imagesource.cpp @@ -14,6 +14,8 @@ #include "util/base64.h" #include "util/numeric.h" #include "util/strfnd.h" +#include "client/fontengine.h" +#include "irrlicht_changes/CGUITTFont.h" //////////////////////////////// @@ -1762,6 +1764,101 @@ bool ImageSource::generateImagePart(std::string_view part_of_name, apply_brightness_contrast(baseimg, v2u32(0, 0), baseimg->getDimension(), brightness, contrast); } + /* + [text:string:size:mono,bold,italic:x,y:color + Render a character at given position + size and font is optional, but colon should be kept + */ + else if (str_starts_with(part_of_name, "[text:")) { + Strfnd sf(part_of_name); + sf.next(":"); + std::string textdef = sf.next(":"); + core::stringw textdefW = utf8_to_stringw(textdef); + + unsigned int fontSize = FONT_SIZE_UNSPECIFIED; + std::string sizeStr = sf.next(":"); + if (is_number(sizeStr)) + { + fontSize = mystoi(sizeStr,0,200); + } + + FontMode mode = FM_Standard; + bool bold = false, italic = false; + std::string fontStyle = sf.next(":"); + std::vector styleWords = str_split(fontStyle, ','); + for(auto word : styleWords){ + if (word == "mono") + { + mode = FM_Mono; + }else if (word == "bold") + { + bold = true; + }else if(word == "italic"){ + italic = true; + } + } + FontSpec spec(fontSize, mode, bold, italic); + + core::position2di pos(0,0); + std::string positionStr = sf.next(":"); + std::vector positionStrs = str_split(positionStr, ','); + if (positionStrs.size() >= 2) + { + if (is_number(positionStrs[0])) { + pos.X = mystoi(positionStrs[0]); + } + if (is_number(positionStrs[1])) { + pos.Y = mystoi(positionStrs[1]); + } + } + + video::SColor color(0xff,0xff,0xff,0xff); + std::string colorStr = sf.next(""); + if (!parseColorString(colorStr,color,false)){ + return false; + }; + + irr::gui::CGUITTFont *font = + static_cast(g_fontengine->getFont(spec)); + core::dimension2d sizeText = font->getDimension(textdefW.c_str()); + + video::ECOLOR_FORMAT colorFormat = video::ECF_A8R8G8B8; + core::dimension2d size =sizeText; + if (baseimg) + { + colorFormat = baseimg->getColorFormat(); + size =baseimg->getDimension(); + } + std::string textureName("text_renderer__"); + textureName.append(part_of_name); + + auto texture = + driver->addRenderTargetTexture(size, textureName, colorFormat); + if (driver->setRenderTarget(texture, video::ECBF_ALL, video::SColor(0,0,0,0))) { + if (baseimg) { + auto baseTexture = driver->addTexture("text_renderer_base__", baseimg); + driver->draw2DImage(baseTexture, core::vector2di(0,0)); + driver->removeTexture(baseTexture); + } + font->draw(textdefW, core::recti(pos, sizeText), color); + driver->setRenderTarget(NULL); + void* lockedData = texture->lock(); + if (lockedData) { + if (baseimg) { + baseimg->drop(); + } + baseimg = driver->createImageFromData(colorFormat, size, lockedData, false); + texture->unlock(); + } else { + errorstream << "no data inside texture, internal error" << std::endl; + } + } else { + errorstream << "fails to set render target, " + "can this driver renders to target:" << + driver->queryFeature(video::EVDF_RENDER_TO_TARGET) << std::endl; + } + driver->removeTexture(texture); + } else { errorstream << "generateImagePart(): Invalid "