diff --git a/src/Magnum/Text/AbstractFont.cpp b/src/Magnum/Text/AbstractFont.cpp index 19e1893c8..d0cc4fd44 100644 --- a/src/Magnum/Text/AbstractFont.cpp +++ b/src/Magnum/Text/AbstractFont.cpp @@ -45,12 +45,16 @@ bool AbstractFont::openData(const std::vector AbstractFont::doOpenData(const std::vector>>& data, const Float size) { +auto AbstractFont::doOpenData(const std::vector>>& data, const Float size) -> Metrics { CORRADE_ASSERT(!(features() & Feature::MultiFile), "Text::AbstractFont::openData(): feature advertised but not implemented", {}); CORRADE_ASSERT(data.size() == 1, @@ -67,24 +71,32 @@ bool AbstractFont::openSingleData(const Containers::ArrayView data, "Text::AbstractFont::openSingleData(): the format is not single-file", false); close(); - std::tie(_size, _lineHeight) = doOpenSingleData(data, size); - CORRADE_INTERNAL_ASSERT(isOpened() || (_size == 0.0f && _lineHeight == 0.0f)); + const Metrics metrics = doOpenSingleData(data, size); + _size = metrics.size; + _ascent = metrics.ascent; + _descent = metrics.descent; + _lineHeight = metrics.lineHeight; + CORRADE_INTERNAL_ASSERT(isOpened() || (!_size && !_ascent && !_descent && !_lineHeight)); return isOpened(); } -std::pair AbstractFont::doOpenSingleData(Containers::ArrayView, Float) { +auto AbstractFont::doOpenSingleData(Containers::ArrayView, Float) -> Metrics { CORRADE_ASSERT(false, "Text::AbstractFont::openSingleData(): feature advertised but not implemented", {}); return {}; } bool AbstractFont::openFile(const std::string& filename, const Float size) { close(); - std::tie(_size, _lineHeight) = doOpenFile(filename, size); - CORRADE_INTERNAL_ASSERT(isOpened() || (_size == 0.0f && _lineHeight == 0.0f)); + const Metrics metrics = doOpenFile(filename, size); + _size = metrics.size; + _ascent = metrics.ascent; + _descent = metrics.descent; + _lineHeight = metrics.lineHeight; + CORRADE_INTERNAL_ASSERT(isOpened() || (!_size && !_ascent && !_descent && !_lineHeight)); return isOpened(); } -std::pair AbstractFont::doOpenFile(const std::string& filename, const Float size) { +auto AbstractFont::doOpenFile(const std::string& filename, const Float size) -> Metrics { CORRADE_ASSERT(features() & Feature::OpenData && !(features() & Feature::MultiFile), "Text::AbstractFont::openFile(): not implemented", {}); diff --git a/src/Magnum/Text/AbstractFont.h b/src/Magnum/Text/AbstractFont.h index 55ad1487d..3af3f3ddc 100644 --- a/src/Magnum/Text/AbstractFont.h +++ b/src/Magnum/Text/AbstractFont.h @@ -72,10 +72,10 @@ checked by the implementation: - All `do*()` implementations working on opened file are called only if there is any file opened. -Plugin interface string is `"cz.mosra.magnum.Text.AbstractFont/0.2.3"`. +Plugin interface string is `"cz.mosra.magnum.Text.AbstractFont/0.2.4"`. */ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { - CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFont/0.2.3") + CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFont/0.2.4") public: /** @@ -158,16 +158,33 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { /** * @brief Font size * - * Returns scale in which @ref lineHeight() and @ref glyphAdvance() is - * returned. + * Returns scale in which @ref lineHeight(), @ref ascent(), + * @ref descent() and @ref glyphAdvance() is returned. */ Float size() const { return _size; } + /** + * @brief Font ascent + * + * Distance from baseline to top, scaled to font size. Positive value. + * @see @ref size(), @ref descent(), @ref lineHeight() + */ + Float ascent() const { return _ascent; } + + /** + * @brief Font descent + * + * Distance from baseline to bottom, scalled to font size. Negative + * value. + * @see @ref size(), @ref ascent(), @ref lineHeight() + */ + Float descent() const { return _descent; } + /** * @brief Line height * * Returns line height scaled to font size. - * @see @ref size() + * @see @ref size(), @ref ascent(), @ref descent() */ Float lineHeight() const { return _lineHeight; } @@ -225,6 +242,38 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { */ std::unique_ptr layout(const GlyphCache& cache, Float size, const std::string& text); + protected: + /** + * @brief Font metrics + * + * @see @ref doOpenFile(), @ref doOpenData(), @ref doOpenSingleData() + */ + struct Metrics { + /** + * Font size + * @see @ref size() + */ + Float size; + + /** + * Font ascent + * @see @ref ascent() + */ + Float ascent; + + /** + * Font descent + * @see @ref descent() + */ + Float descent; + + /** + * Line height + * @see @ref lineHeight() + */ + Float lineHeight; + }; + #ifdef DOXYGEN_GENERATING_OUTPUT protected: #else @@ -239,29 +288,29 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { /** * @brief Implementation for @ref openData() * - * Return size and line height of opened font on successful opening, - * zeros otherwise. If the plugin doesn't have @ref Feature::MultiFile, + * Return metrics of opened font on successful opening, zeros + * otherwise. If the plugin doesn't have @ref Feature::MultiFile, * default implementation calls @ref doOpenSingleData(). */ - virtual std::pair doOpenData(const std::vector>>& data, Float size); + virtual Metrics doOpenData(const std::vector>>& data, Float size); /** * @brief Implementation for @ref openSingleData() * - * Return size and line height of opened font on successful opening, - * zeros otherwise. + * Return metrics of opened font on successful opening, zeros + * otherwise. */ - virtual std::pair doOpenSingleData(Containers::ArrayView data, Float size); + virtual Metrics doOpenSingleData(Containers::ArrayView data, Float size); /** * @brief Implementation for @ref openFile() * - * Return size and line height of opened font on successful opening, - * zeros otherwise. If @ref Feature::OpenData is supported and the - * plugin doesn't have @ref Feature::MultiFile, default implementation - * opens the file and calls @ref doOpenSingleData() with its contents. + * Return metrics of opened font on successful opening, zeros + * otherwise. If @ref Feature::OpenData is supported and the plugin + * doesn't have @ref Feature::MultiFile, default implementation opens + * the file and calls @ref doOpenSingleData() with its contents. */ - virtual std::pair doOpenFile(const std::string& filename, Float size); + virtual Metrics doOpenFile(const std::string& filename, Float size); /** @brief Implementation for @ref close() */ virtual void doClose() = 0; @@ -289,7 +338,7 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { #ifdef DOXYGEN_GENERATING_OUTPUT private: #endif - Float _size, _lineHeight; + Float _size, _ascent, _descent, _lineHeight; }; CORRADE_ENUMSET_OPERATORS(AbstractFont::Features) diff --git a/src/Magnum/Text/AbstractFontConverter.h b/src/Magnum/Text/AbstractFontConverter.h index 912aa7fca..22c4c264c 100644 --- a/src/Magnum/Text/AbstractFontConverter.h +++ b/src/Magnum/Text/AbstractFontConverter.h @@ -68,10 +68,10 @@ checked by the implementation: - Function `doImport*FromData()` is called only if there is at least one data array passed. -Plugin interface string is `"cz.mosra.magnum.Text.AbstractFontConverter/0.1.1"`. +Plugin interface string is `"cz.mosra.magnum.Text.AbstractFontConverter/0.1.2"`. */ class MAGNUM_TEXT_EXPORT AbstractFontConverter: public PluginManager::AbstractPlugin { - CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFontConverter/0.1.1") + CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFontConverter/0.1.2") public: /** diff --git a/src/Magnum/Text/Test/AbstractFontTest.cpp b/src/Magnum/Text/Test/AbstractFontTest.cpp index 8601212b2..fbda4f7ce 100644 --- a/src/Magnum/Text/Test/AbstractFontTest.cpp +++ b/src/Magnum/Text/Test/AbstractFontTest.cpp @@ -56,7 +56,7 @@ class SingleDataFont: public Text::AbstractFont { bool doIsOpened() const override { return opened; } void doClose() override {} - std::pair doOpenSingleData(const Containers::ArrayView data, Float) override { + Metrics doOpenSingleData(const Containers::ArrayView data, Float) override { opened = (data.size() == 1 && data[0] == '\xa5'); return {}; } diff --git a/src/Magnum/Text/Test/RendererGLTest.cpp b/src/Magnum/Text/Test/RendererGLTest.cpp index 73dac9db4..51afbc7e7 100644 --- a/src/Magnum/Text/Test/RendererGLTest.cpp +++ b/src/Magnum/Text/Test/RendererGLTest.cpp @@ -344,9 +344,9 @@ void RendererGLTest::multiline() { bool doIsOpened() const override { return _opened; } void doClose() override { _opened = false; } - std::pair doOpenFile(const std::string&, Float) override { + Metrics doOpenFile(const std::string&, Float) override { _opened = true; - return {0.5f, 0.75f}; + return {0.5f, 0.45f, -0.25f, 0.75f}; } UnsignedInt doGlyphId(char32_t) override { return 0; } @@ -370,6 +370,8 @@ void RendererGLTest::multiline() { /* We're rendering text at 2.0f size and the font is scaled to 0.3f, so the line advance should be 0.75f*2.0f/0.5f = 3.0f */ CORRADE_COMPARE(font.size(), 0.5f); + CORRADE_COMPARE(font.ascent(), 0.45f); + CORRADE_COMPARE(font.descent(), -0.25f); CORRADE_COMPARE(font.lineHeight(), 0.75f); /* Bounds */ diff --git a/src/MagnumPlugins/MagnumFont/MagnumFont.cpp b/src/MagnumPlugins/MagnumFont/MagnumFont.cpp index b9e1648fe..6f1bb04e1 100644 --- a/src/MagnumPlugins/MagnumFont/MagnumFont.cpp +++ b/src/MagnumPlugins/MagnumFont/MagnumFont.cpp @@ -68,7 +68,7 @@ auto MagnumFont::doFeatures() const -> Features { return Feature::OpenData|Featu bool MagnumFont::doIsOpened() const { return _opened; } -std::pair MagnumFont::doOpenData(const std::vector>>& data, const Float) { +auto MagnumFont::doOpenData(const std::vector>>& data, const Float) -> Metrics { /* We need just the configuration file and image file */ if(data.size() != 2) { Error() << "Text::MagnumFont::openData(): wanted two files, got" << data.size(); @@ -112,7 +112,7 @@ std::pair MagnumFont::doOpenData(const std::vector MagnumFont::doOpenFile(const std::string& filename, Float) { +auto MagnumFont::doOpenFile(const std::string& filename, Float) -> Metrics { /* Open the configuration file */ Utility::Configuration conf(filename, Utility::Configuration::Flag::ReadOnly|Utility::Configuration::Flag::SkipComments); if(!conf.isValid() || conf.isEmpty()) { @@ -143,7 +143,7 @@ std::pair MagnumFont::doOpenFile(const std::string& filename, Floa return openInternal(std::move(conf), std::move(*image)); } -std::pair MagnumFont::openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image) { +auto MagnumFont::openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image) -> Metrics { /* Everything okay, save the data internally */ _opened = new Data{std::move(conf), std::move(image), std::unordered_map{}, {}}; @@ -161,7 +161,10 @@ std::pair MagnumFont::openInternal(Utility::Configuration&& conf, _opened->glyphId.emplace(c->value("unicode"), glyphId); } - return {_opened->conf.value("fontSize"), _opened->conf.value("lineHeight")}; + return {_opened->conf.value("fontSize"), + _opened->conf.value("ascent"), + _opened->conf.value("descent"), + _opened->conf.value("lineHeight")}; } void MagnumFont::doClose() { diff --git a/src/MagnumPlugins/MagnumFont/MagnumFont.h b/src/MagnumPlugins/MagnumFont/MagnumFont.h index ee46d9389..0496e64a3 100644 --- a/src/MagnumPlugins/MagnumFont/MagnumFont.h +++ b/src/MagnumPlugins/MagnumFont/MagnumFont.h @@ -120,9 +120,9 @@ class MagnumFont: public AbstractFont { bool doIsOpened() const override; - std::pair doOpenData(const std::vector>>& data, Float) override; + Metrics doOpenData(const std::vector>>& data, Float) override; - std::pair doOpenFile(const std::string& filename, Float) override; + Metrics doOpenFile(const std::string& filename, Float) override; void doClose() override; @@ -134,7 +134,7 @@ class MagnumFont: public AbstractFont { std::unique_ptr doLayout(const GlyphCache& cache, Float size, const std::string& text) override; - std::pair openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image); + Metrics openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image); Data* _opened; }; diff --git a/src/MagnumPlugins/MagnumFont/Test/MagnumFontGLTest.cpp b/src/MagnumPlugins/MagnumFont/Test/MagnumFontGLTest.cpp index 3e6183d99..36226d297 100644 --- a/src/MagnumPlugins/MagnumFont/Test/MagnumFontGLTest.cpp +++ b/src/MagnumPlugins/MagnumFont/Test/MagnumFontGLTest.cpp @@ -52,6 +52,8 @@ void MagnumFontGLTest::properties() { MagnumFont font; CORRADE_VERIFY(font.openFile(Utility::Directory::join(MAGNUMFONT_TEST_DIR, "font.conf"), 0.0f)); CORRADE_COMPARE(font.size(), 16.0f); + 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)); } diff --git a/src/MagnumPlugins/MagnumFont/Test/font.conf b/src/MagnumPlugins/MagnumFont/Test/font.conf index 7cf2c7b9b..b305ba032 100644 --- a/src/MagnumPlugins/MagnumFont/Test/font.conf +++ b/src/MagnumPlugins/MagnumFont/Test/font.conf @@ -3,6 +3,8 @@ image=font.tga originalImageSize=1536 1536 padding=24 24 fontSize=16 +ascent=25 +descent=-10 lineHeight=39.7333 [char] unicode=57 diff --git a/src/MagnumPlugins/MagnumFont/pluginRegistration.cpp b/src/MagnumPlugins/MagnumFont/pluginRegistration.cpp index 34c1b92c6..b7c2ccc55 100644 --- a/src/MagnumPlugins/MagnumFont/pluginRegistration.cpp +++ b/src/MagnumPlugins/MagnumFont/pluginRegistration.cpp @@ -26,4 +26,4 @@ #include "MagnumPlugins/MagnumFont/MagnumFont.h" CORRADE_PLUGIN_REGISTER(MagnumFont, Magnum::Text::MagnumFont, - "cz.mosra.magnum.Text.AbstractFont/0.2.3") + "cz.mosra.magnum.Text.AbstractFont/0.2.4") diff --git a/src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.cpp b/src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.cpp index 8ec23908f..ff56e2fe5 100644 --- a/src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.cpp +++ b/src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.cpp @@ -53,6 +53,8 @@ std::vector>> MagnumFontConverter configuration.setValue("originalImageSize", cache.textureSize()); configuration.setValue("padding", cache.padding()); configuration.setValue("fontSize", font.size()); + configuration.setValue("ascent", font.ascent()); + configuration.setValue("descent", font.descent()); configuration.setValue("lineHeight", font.lineHeight()); /* Compress glyph IDs so the glyphs are in consecutive array, glyph 0 diff --git a/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterGLTest.cpp b/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterGLTest.cpp index d98c69f32..6c34c61aa 100644 --- a/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterGLTest.cpp +++ b/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterGLTest.cpp @@ -65,9 +65,9 @@ void MagnumFontConverterGLTest::exportFont() { private: void doClose() { _opened = false; } bool doIsOpened() const { return _opened; } - std::pair doOpenFile(const std::string&, Float) { + Metrics doOpenFile(const std::string&, Float) { _opened = true; - return {16.0f, 39.7333f}; + return {16.0f, 25.0f, -10.0f, 39.7333f}; } Features doFeatures() const { return {}; } std::unique_ptr doLayout(const GlyphCache&, Float, const std::string&) { return nullptr; } diff --git a/src/MagnumPlugins/MagnumFontConverter/pluginRegistration.cpp b/src/MagnumPlugins/MagnumFontConverter/pluginRegistration.cpp index b45853467..dfdca3e24 100644 --- a/src/MagnumPlugins/MagnumFontConverter/pluginRegistration.cpp +++ b/src/MagnumPlugins/MagnumFontConverter/pluginRegistration.cpp @@ -26,4 +26,4 @@ #include "MagnumPlugins/MagnumFontConverter/MagnumFontConverter.h" CORRADE_PLUGIN_REGISTER(MagnumFontConverter, Magnum::Text::MagnumFontConverter, - "cz.mosra.magnum.Text.AbstractFontConverter/0.1.1") + "cz.mosra.magnum.Text.AbstractFontConverter/0.1.2")