diff --git a/doc/changelog.dox b/doc/changelog.dox index 1ad3f4f0c..24069f89d 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -767,6 +767,7 @@ See also: @subsubsection changelog-latest-changes-text Text library +- Added @ref Text::AbstractFont::glyphCount() - Added @ref Text::Renderer::fontSize() @subsubsection changelog-latest-changes-trade Trade library diff --git a/src/Magnum/Text/AbstractFont.cpp b/src/Magnum/Text/AbstractFont.cpp index be01f267f..ebfea333d 100644 --- a/src/Magnum/Text/AbstractFont.cpp +++ b/src/Magnum/Text/AbstractFont.cpp @@ -114,6 +114,7 @@ bool AbstractFont::openData(Containers::ArrayView data, const Float _ascent = properties.ascent; _descent = properties.descent; _lineHeight = properties.lineHeight; + _glyphCount = properties.glyphCount; return true; } @@ -166,6 +167,7 @@ bool AbstractFont::openFile(const Containers::StringView filename, const Float s _ascent = properties.ascent; _descent = properties.descent; _lineHeight = properties.lineHeight; + _glyphCount = properties.glyphCount; return true; } @@ -237,6 +239,11 @@ Float AbstractFont::lineHeight() const { return _lineHeight; } +UnsignedInt AbstractFont::glyphCount() const { + CORRADE_ASSERT(isOpened(), "Text::AbstractFont::glyphCount(): no font opened", 0); + return _glyphCount; +} + UnsignedInt AbstractFont::glyphId(const char32_t character) { CORRADE_ASSERT(isOpened(), "Text::AbstractFont::glyphId(): no font opened", 0); @@ -245,6 +252,7 @@ UnsignedInt AbstractFont::glyphId(const char32_t character) { Vector2 AbstractFont::glyphAdvance(const UnsignedInt glyph) { CORRADE_ASSERT(isOpened(), "Text::AbstractFont::glyphAdvance(): no font opened", {}); + CORRADE_ASSERT(glyph < _glyphCount, "Text::AbstractFont::glyphAdvance(): index" << glyph << "out of range for" << _glyphCount << "glyphs", {}); return doGlyphAdvance(glyph); } diff --git a/src/Magnum/Text/AbstractFont.h b/src/Magnum/Text/AbstractFont.h index 9fe354c55..0e5089155 100644 --- a/src/Magnum/Text/AbstractFont.h +++ b/src/Magnum/Text/AbstractFont.h @@ -435,6 +435,18 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { */ Float lineHeight() const; + /** + * @brief Total count of glyphs in the font + * @m_since_latest + * + * Expects that a font is opened. + * @note This function is meant to be used only for font observations + * and conversions. In performance-critical code the + * @ref fillGlyphCache() and @ref layout() functions should be + * used instead. + */ + UnsignedInt glyphCount() const; + /** * @brief Glyph ID for given character * @@ -451,7 +463,8 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { * * Distance the cursor for the next glyph that follows @p glyph. * Doesn't consider kerning or any other advanced shaping features. - * Expects that a font is opened. + * Expects that a font is opened and @p glyph is less than + * @ref glyphCount(). * @note This function is meant to be used only for font observations * and conversions. In performance-critical code the @ref layout() * function should be used instead. @@ -503,8 +516,8 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { struct Properties { #if defined(CORRADE_TARGET_GCC) && !defined(CORRADE_TARGET_CLANG) && __GNUC__ < 5 /* Otherwise GCC 4.8 loudly complains about missing initializers */ - constexpr /*implicit*/ Properties() noexcept: size{}, ascent{}, descent{}, lineHeight{} {} - constexpr /*implicit*/ Properties(Float size, Float ascent, Float descent, Float lineHeight) noexcept: size{size}, ascent{ascent}, descent{descent}, lineHeight{lineHeight} {} + constexpr /*implicit*/ Properties() noexcept: size{}, ascent{}, descent{}, lineHeight{}, glyphCount{} {} + constexpr /*implicit*/ Properties(Float size, Float ascent, Float descent, Float lineHeight, UnsignedInt glyphCount) noexcept: size{size}, ascent{ascent}, descent{descent}, lineHeight{lineHeight}, glyphCount{glyphCount} {} #endif /** @@ -530,6 +543,13 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { * @see @ref lineHeight() */ Float lineHeight; + + /** + * Total count of glyphs in the font + * @see @ref glyphCount() + * @m_since_latest + */ + UnsignedInt glyphCount; }; protected: @@ -617,6 +637,7 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { } _fileCallbackTemplate{nullptr, nullptr}; Float _size{}, _ascent{}, _descent{}, _lineHeight{}; + UnsignedInt _glyphCount{}; }; /** @@ -702,7 +723,7 @@ updated interface string. */ /* Silly indentation to make the string appear in pluginInterface() docs */ #define MAGNUM_TEXT_ABSTRACTFONT_PLUGIN_INTERFACE /* [interface] */ \ -"cz.mosra.magnum.Text.AbstractFont/0.3.1" +"cz.mosra.magnum.Text.AbstractFont/0.3.2" /* [interface] */ #ifndef DOXYGEN_GENERATING_OUTPUT diff --git a/src/Magnum/Text/Test/AbstractFontTest.cpp b/src/Magnum/Text/Test/AbstractFontTest.cpp index 0c69334c9..1517b3538 100644 --- a/src/Magnum/Text/Test/AbstractFontTest.cpp +++ b/src/Magnum/Text/Test/AbstractFontTest.cpp @@ -77,6 +77,7 @@ struct AbstractFontTest: TestSuite::Tester { void glyphAdvance(); void glyphAdvanceNoFont(); + void glyphAdvanceOutOfRange(); void layout(); void layoutNoFont(); @@ -130,6 +131,7 @@ AbstractFontTest::AbstractFontTest() { &AbstractFontTest::glyphAdvance, &AbstractFontTest::glyphAdvanceNoFont, + &AbstractFontTest::glyphAdvanceOutOfRange, &AbstractFontTest::layout, &AbstractFontTest::layoutNoFont, @@ -181,7 +183,7 @@ void AbstractFontTest::openData() { Properties doOpenData(const Containers::ArrayView data, Float size) override { _opened = (data.size() == 1 && data[0] == '\xa5'); - return {size, 1.0f, 2.0f, 3.0f}; + return {size, 1.0f, 2.0f, 3.0f, 15}; } UnsignedInt doGlyphId(char32_t) override { return {}; } @@ -201,6 +203,7 @@ void AbstractFontTest::openData() { CORRADE_COMPARE(font.ascent(), 1.0f); CORRADE_COMPARE(font.descent(), 2.0f); CORRADE_COMPARE(font.lineHeight(), 3.0f); + CORRADE_COMPARE(font.glyphCount(), 15); } void AbstractFontTest::openFileAsData() { @@ -211,7 +214,7 @@ void AbstractFontTest::openFileAsData() { Properties doOpenData(const Containers::ArrayView data, Float size) override { _opened = (data.size() == 1 && data[0] == '\xa5'); - return {size, 1.0f, 2.0f, 3.0f}; + return {size, 1.0f, 2.0f, 3.0f, 15}; } UnsignedInt doGlyphId(char32_t) override { return {}; } @@ -231,6 +234,7 @@ void AbstractFontTest::openFileAsData() { CORRADE_COMPARE(font.ascent(), 1.0f); CORRADE_COMPARE(font.descent(), 2.0f); CORRADE_COMPARE(font.lineHeight(), 3.0f); + CORRADE_COMPARE(font.glyphCount(), 15); } void AbstractFontTest::openFileAsDataNotFound() { @@ -512,7 +516,7 @@ void AbstractFontTest::setFileCallbackOpenFileDirectly() { Properties doOpenFile(Containers::StringView filename, Float size) override { /* Called because FileCallback is supported */ _opened = filename == "file.dat" && fileCallback() && fileCallbackUserData(); - return {size, 1.0f, 2.0f, 3.0f}; + return {size, 1.0f, 2.0f, 3.0f, 15}; } Properties doOpenData(Containers::ArrayView, Float) override { @@ -544,6 +548,7 @@ void AbstractFontTest::setFileCallbackOpenFileDirectly() { CORRADE_COMPARE(font.ascent(), 1.0f); CORRADE_COMPARE(font.descent(), 2.0f); CORRADE_COMPARE(font.lineHeight(), 3.0f); + CORRADE_COMPARE(font.glyphCount(), 15); } void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementation() { @@ -559,7 +564,7 @@ void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementation() { Properties doOpenData(Containers::ArrayView data, Float size) override { _opened = (data.size() == 1 && data[0] == '\xb0'); - return {size, 1.0f, 2.0f, 3.0f}; + return {size, 1.0f, 2.0f, 3.0f, 15}; } UnsignedInt doGlyphId(char32_t) override { return {}; } @@ -602,6 +607,7 @@ void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementation() { CORRADE_COMPARE(font.ascent(), 1.0f); CORRADE_COMPARE(font.descent(), 2.0f); CORRADE_COMPARE(font.lineHeight(), 3.0f); + CORRADE_COMPARE(font.glyphCount(), 15); } void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementationFailed() { @@ -649,7 +655,7 @@ void AbstractFontTest::setFileCallbackOpenFileAsData() { Properties doOpenData(Containers::ArrayView data, Float size) override { _opened = (data.size() == 1 && data[0] == '\xb0'); - return {size, 1.0f, 2.0f, 3.0f}; + return {size, 1.0f, 2.0f, 3.0f, 15}; } UnsignedInt doGlyphId(char32_t) override { return {}; } @@ -693,6 +699,7 @@ void AbstractFontTest::setFileCallbackOpenFileAsData() { CORRADE_COMPARE(font.ascent(), 1.0f); CORRADE_COMPARE(font.descent(), 2.0f); CORRADE_COMPARE(font.lineHeight(), 3.0f); + CORRADE_COMPARE(font.glyphCount(), 15); } void AbstractFontTest::setFileCallbackOpenFileAsDataFailed() { @@ -735,7 +742,7 @@ void AbstractFontTest::properties() { Properties doOpenData(const Containers::ArrayView, Float size) override { _opened = true; - return {size, 1.0f, 2.0f, 3.0f}; + return {size, 1.0f, 2.0f, 3.0f, 15}; } UnsignedInt doGlyphId(char32_t) override { return {}; } @@ -752,6 +759,7 @@ void AbstractFontTest::properties() { CORRADE_COMPARE(font.ascent(), 1.0f); CORRADE_COMPARE(font.descent(), 2.0f); CORRADE_COMPARE(font.lineHeight(), 3.0f); + CORRADE_COMPARE(font.glyphCount(), 15); } void AbstractFontTest::propertiesNoFont() { @@ -775,11 +783,13 @@ void AbstractFontTest::propertiesNoFont() { font.ascent(); font.descent(); font.lineHeight(); + font.glyphCount(); CORRADE_COMPARE(out.str(), "Text::AbstractFont::size(): no font opened\n" "Text::AbstractFont::ascent(): no font opened\n" "Text::AbstractFont::descent(): no font opened\n" - "Text::AbstractFont::lineHeight(): no font opened\n"); + "Text::AbstractFont::lineHeight(): no font opened\n" + "Text::AbstractFont::glyphCount(): no font opened\n"); } void AbstractFontTest::glyphId() { @@ -821,17 +831,25 @@ void AbstractFontTest::glyphIdNoFont() { void AbstractFontTest::glyphAdvance() { struct MyFont: AbstractFont { - FontFeatures doFeatures() const override { return {}; } - bool doIsOpened() const override { return true; } + FontFeatures doFeatures() const override { return FontFeature::OpenData; } + bool doIsOpened() const override { return _opened; } void doClose() override {} + Properties doOpenData(Containers::ArrayView, Float) override { + _opened = true; + return {0.0f, 0.0f, 0.0f, 0.0f, 98}; + } UnsignedInt doGlyphId(char32_t) override { return {}; } Vector2 doGlyphAdvance(UnsignedInt a) override { return {a*10.0f, -Float(a)/10.0f}; } Containers::Pointer doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; } + + bool _opened = false; } font; + /* Have to explicitly open in order to make glyphCount() non-zero */ + CORRADE_VERIFY(font.openData(nullptr, 0.0f)); CORRADE_COMPARE(font.glyphAdvance(97), (Vector2{970.0f, -9.7f})); } @@ -856,6 +874,37 @@ void AbstractFontTest::glyphAdvanceNoFont() { CORRADE_COMPARE(out.str(), "Text::AbstractFont::glyphAdvance(): no font opened\n"); } +void AbstractFontTest::glyphAdvanceOutOfRange() { + CORRADE_SKIP_IF_NO_ASSERT(); + + struct MyFont: AbstractFont { + FontFeatures doFeatures() const override { return FontFeature::OpenData; } + bool doIsOpened() const override { return _opened; } + void doClose() override {} + + Properties doOpenData(Containers::ArrayView, Float) override { + _opened = true; + return {0.0f, 0.0f, 0.0f, 0.0f, 3}; + } + UnsignedInt doGlyphId(char32_t) override { return {}; } + Vector2 doGlyphAdvance(UnsignedInt) override { return {}; } + Containers::Pointer doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { + return nullptr; + } + + bool _opened = false; + } font; + + /* Have to explicitly open in order to make glyphCount() non-zero */ + CORRADE_VERIFY(font.openData(nullptr, 0.0f)); + + std::ostringstream out; + Error redirectError{&out}; + font.glyphAdvance(3); + CORRADE_COMPARE(out.str(), + "Text::AbstractFont::glyphAdvance(): index 3 out of range for 3 glyphs\n"); +} + struct DummyGlyphCache: AbstractGlyphCache { using AbstractGlyphCache::AbstractGlyphCache; diff --git a/src/Magnum/Text/Test/RendererGLTest.cpp b/src/Magnum/Text/Test/RendererGLTest.cpp index 702d4afba..9834f0461 100644 --- a/src/Magnum/Text/Test/RendererGLTest.cpp +++ b/src/Magnum/Text/Test/RendererGLTest.cpp @@ -350,7 +350,7 @@ void RendererGLTest::multiline() { Properties doOpenFile(Containers::StringView, Float) override { _opened = true; - return {0.5f, 0.45f, -0.25f, 0.75f}; + return {0.5f, 0.45f, -0.25f, 0.75f, 1}; } UnsignedInt doGlyphId(char32_t) override { return 0; } diff --git a/src/MagnumPlugins/MagnumFont/MagnumFont.cpp b/src/MagnumPlugins/MagnumFont/MagnumFont.cpp index 61bf7387d..403165a6a 100644 --- a/src/MagnumPlugins/MagnumFont/MagnumFont.cpp +++ b/src/MagnumPlugins/MagnumFont/MagnumFont.cpp @@ -134,7 +134,8 @@ auto MagnumFont::doOpenData(const Containers::ArrayView data, const return {_opened->conf.value("fontSize"), _opened->conf.value("ascent"), _opened->conf.value("descent"), - _opened->conf.value("lineHeight")}; + _opened->conf.value("lineHeight"), + UnsignedInt(glyphs.size())}; } auto MagnumFont::doOpenFile(const Containers::StringView filename, const Float size) -> Properties { @@ -150,7 +151,7 @@ UnsignedInt MagnumFont::doGlyphId(const char32_t character) { } Vector2 MagnumFont::doGlyphAdvance(const UnsignedInt glyph) { - return glyph < _opened->glyphAdvance.size() ? _opened->glyphAdvance[glyph] : Vector2(); + return _opened->glyphAdvance[glyph]; } Containers::Pointer MagnumFont::doCreateGlyphCache() { diff --git a/src/MagnumPlugins/MagnumFont/Test/MagnumFontTest.cpp b/src/MagnumPlugins/MagnumFont/Test/MagnumFontTest.cpp index fe77b87d6..08ed71920 100644 --- a/src/MagnumPlugins/MagnumFont/Test/MagnumFontTest.cpp +++ b/src/MagnumPlugins/MagnumFont/Test/MagnumFontTest.cpp @@ -93,7 +93,8 @@ void MagnumFontTest::properties() { CORRADE_COMPARE(font->ascent(), 25.0f); CORRADE_COMPARE(font->descent(), -10.0f); CORRADE_COMPARE(font->lineHeight(), 39.7333f); - CORRADE_COMPARE(font->glyphAdvance(font->glyphId(U'W')), Vector2(23.0f, 0.0f)); + CORRADE_COMPARE(font->glyphCount(), 3); + CORRADE_COMPARE(font->glyphAdvance(font->glyphId(U'W')), (Vector2{23.0f, 0.0f})); } void MagnumFontTest::layout() { diff --git a/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp b/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp index 37ca2ca34..bd33d4e61 100644 --- a/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp +++ b/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp @@ -95,7 +95,7 @@ void MagnumFontConverterTest::exportFont() { bool doIsOpened() const override { return _opened; } Properties doOpenFile(Containers::StringView, Float) override { _opened = true; - return {16.0f, 25.0f, -10.0f, 39.7333f}; + return {16.0f, 25.0f, -10.0f, 39.7333f, 3}; } FontFeatures doFeatures() const override { return {}; } Containers::Pointer doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }