diff --git a/Components/Overlay/include/OgreFont.h b/Components/Overlay/include/OgreFont.h index 127465cb944..b7f88da4a03 100644 --- a/Components/Overlay/include/OgreFont.h +++ b/Components/Overlay/include/OgreFont.h @@ -28,6 +28,7 @@ THE SOFTWARE #define _Font_H__ #include "OgreOverlayPrerequisites.h" +#include "OgrePrerequisites.h" #include "OgreResource.h" #include "OgreCommon.h" #include "OgreSharedPtr.h" @@ -44,6 +45,8 @@ namespace Ogre /** \addtogroup Overlays * @{ */ + class Font; + typedef SharedPtr FontPtr; /// decode UTF8 encoded bytestream to uint32 codepoints _OgreOverlayExport std::vector utftoc32(String str); @@ -124,12 +127,17 @@ namespace Ogre /// Range of code points to generate glyphs for (truetype only) CodePointRangeList mCodePointRangeList; + std::vector mMergeFonts; + /// Internal method for loading from ttf void createTextureFromFont(void); void loadImpl() override; void unloadImpl() override; size_t calculateSize(void) const override { return 0; } // permanent resource is in the texture + + friend class ImGuiOverlay; + DataStreamPtr _getTTFData(); public: /** Constructor. @@ -287,6 +295,16 @@ namespace Ogre { return mCodePointRangeList; } + + /** Add a font to merge with this one. + + This is useful when you want to use a font for most of the characters, but + fall back to another font for characters not present in the current font. e.g. icons. + */ + void addMergeFont(const FontPtr& font) { mMergeFonts.push_back(font); } + + const std::vector& getMergeFontList() const { return mMergeFonts; } + /** Gets the material generated for this font, as a weak reference. This will only be valid after the Font has been loaded. @@ -343,8 +361,6 @@ namespace Ogre */ void _setMaterial(const MaterialPtr& mat); }; - - typedef SharedPtr FontPtr; /** @} */ /** @} */ } diff --git a/Components/Overlay/src/OgreFont.cpp b/Components/Overlay/src/OgreFont.cpp index 97511dd34a7..30968796b22 100644 --- a/Components/Overlay/src/OgreFont.cpp +++ b/Components/Overlay/src/OgreFont.cpp @@ -328,14 +328,15 @@ namespace Ogre mTexture->load(); } //--------------------------------------------------------------------- + DataStreamPtr Font::_getTTFData() + { + // Locate ttf file, load it pre-buffered into memory by wrapping + // the original DataStream in a MemoryDataStream + return ResourceGroupManager::getSingleton().openResource(mSource, mGroup, this); + } void Font::loadResource(Resource* res) { - // Locate ttf file, load it pre-buffered into memory by wrapping the - // original DataStream in a MemoryDataStream - DataStreamPtr dataStreamPtr = - ResourceGroupManager::getSingleton().openResource( - mSource, mGroup, this); - MemoryDataStream ttfchunk(dataStreamPtr); + MemoryDataStream ttfchunk = _getTTFData(); // If codepoints not supplied, assume ASCII if (mCodePointRangeList.empty()) diff --git a/Components/Overlay/src/OgreImGuiOverlay.cpp b/Components/Overlay/src/OgreImGuiOverlay.cpp index dc9907a0f3c..0d4191b4cd0 100644 --- a/Components/Overlay/src/OgreImGuiOverlay.cpp +++ b/Components/Overlay/src/OgreImGuiOverlay.cpp @@ -123,9 +123,7 @@ ImFont* ImGuiOverlay::addFont(const String& name, const String& group) StringUtil::format("Font '%s' not found in group '%s'", name.c_str(), group.c_str())); OgreAssert(font->getType() == FT_TRUETYPE, "font must be of FT_TRUETYPE"); - DataStreamPtr dataStreamPtr = - ResourceGroupManager::getSingleton().openResource(font->getSource(), font->getGroup()); - MemoryDataStream ttfchunk(dataStreamPtr, false); // transfer ownership to imgui + MemoryDataStream ttfchunk(font->_getTTFData(), false); // transfer ownership to imgui // convert codepoint ranges for imgui CodePointRange cprange; @@ -149,8 +147,33 @@ ImFont* ImGuiOverlay::addFont(const String& name, const String& group) ImFontConfig cfg; strncpy(cfg.Name, name.c_str(), IM_ARRAYSIZE(cfg.Name) - 1); - return io.Fonts->AddFontFromMemoryTTF(ttfchunk.getPtr(), ttfchunk.size(), font->getTrueTypeSize() * vpScale, &cfg, - cprangePtr); + auto* ret = io.Fonts->AddFontFromMemoryTTF(ttfchunk.getPtr(), ttfchunk.size(), font->getTrueTypeSize() * vpScale, + &cfg, cprangePtr); + + cfg.MergeMode = true; + + for(const auto& mergeFont : font->getMergeFontList()) + { + MemoryDataStream mergeTtfchunk(mergeFont->_getTTFData(), false); // transfer ownership to imgui + + CodePointRange mergeCprange; + for (const auto& r : mergeFont->getCodePointRangeList()) + { + mergeCprange.push_back(r.first); + mergeCprange.push_back(r.second); + } + + OgreAssert(!mergeCprange.empty(), "merge font must have codepoint ranges"); + mergeCprange.push_back(0); // terminate + mCodePointRanges.push_back(mergeCprange); + cprangePtr = mCodePointRanges.back().data(); + + cfg.MergeMode = true; + ret = io.Fonts->AddFontFromMemoryTTF(mergeTtfchunk.getPtr(), mergeTtfchunk.size(), + mergeFont->getTrueTypeSize() * vpScale, &cfg, cprangePtr); + } + + return ret; } void ImGuiOverlay::ImGUIRenderable::createFontTexture() diff --git a/Components/Overlay/src/OgreOverlayTranslator.cpp b/Components/Overlay/src/OgreOverlayTranslator.cpp index 04401cee398..489e0f7a0e6 100644 --- a/Components/Overlay/src/OgreOverlayTranslator.cpp +++ b/Components/Overlay/src/OgreOverlayTranslator.cpp @@ -106,6 +106,31 @@ void FontTranslator::parseAttribute(ScriptCompiler* compiler, FontPtr& pFont, pFont->setAntialiasColour(flag); compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, prop->file, prop->line, attrib); } + else if(attrib == "merge_fonts") + { + if (prop->values.empty()) + { + compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line); + return; + } + + for (auto& v : prop->values) + { + if (!getString(v, &val)) + { + compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line); + return; + } + + auto mergeFont = FontManager::getSingleton().getByName(val, pFont->getGroup()); + if (!mergeFont) + { + compiler->addError(ScriptCompiler::CE_REFERENCETOANONEXISTINGOBJECT, prop->file, prop->line, val); + return; + } + pFont->addMergeFont(mergeFont); + } + } else if (attrib == "code_points") { if (prop->values.empty()) diff --git a/Docs/src/scripts.md b/Docs/src/scripts.md index e02795f459b..eb3c1f787e7 100644 --- a/Docs/src/scripts.md +++ b/Docs/src/scripts.md @@ -1299,4 +1299,6 @@ Here are the attributes you need to supply: @param code\_points nn-nn \[nn-nn\] .. This directive allows you to specify which unicode code points should be generated as glyphs into the font texture. If you don’t specify this, code points 32-126 will be generated by default which covers the ASCII glyphs. If you use this flag, you should specify a space-separated list of inclusive code point ranges of the form ’start-end’. Numbers must be decimal. +@param merge_font **name [name2]** @copydetails Ogre::Font::addMergeFont + You can also create new fonts at runtime by using the Ogre::FontManager if you wish.