From 858c9787f05db70023203a24db64778d2287588b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 6 Nov 2013 14:17:46 +0100 Subject: [PATCH] Text: initial support for line height in AbstractFont. Got finally pissed with the requirement of setting AbstractFont::_size manually and took this as opportunity to rework the internal plugin API in a better way. Bumped the interface version, as this is binary incompatible. MagnumFont doesn't support lineHeight yet. --- src/Plugins/MagnumFont/MagnumFont.cpp | 33 ++++++++------- src/Plugins/MagnumFont/MagnumFont.h | 8 ++-- .../pluginRegistrationMagnumFont.cpp | 2 +- .../Test/MagnumFontConverterTest.cpp | 13 ++++-- src/Text/AbstractFont.cpp | 33 ++++++++------- src/Text/AbstractFont.h | 42 +++++++++++-------- src/Text/Test/AbstractFontTest.cpp | 3 +- 7 files changed, 78 insertions(+), 56 deletions(-) diff --git a/src/Plugins/MagnumFont/MagnumFont.cpp b/src/Plugins/MagnumFont/MagnumFont.cpp index 241b30bb3..4094e6bc6 100644 --- a/src/Plugins/MagnumFont/MagnumFont.cpp +++ b/src/Plugins/MagnumFont/MagnumFont.cpp @@ -67,11 +67,11 @@ auto MagnumFont::doFeatures() const -> Features { return Feature::OpenData|Featu bool MagnumFont::doIsOpened() const { return _opened; } -void MagnumFont::doOpenData(const std::vector>>& data, const Float) { +std::pair MagnumFont::doOpenData(const std::vector>>& data, const Float) { /* We need just the configuration file and image file */ if(data.size() != 2) { Error() << "Text::MagnumFont::openData(): wanted two files, got" << data.size(); - return; + return {}; } /* Open the configuration file */ @@ -79,51 +79,51 @@ void MagnumFont::doOpenData(const std::vector("version") != 1) { Error() << "Text::MagnumFont::openData(): unsupported file version, expected 1 but got" << conf.value("version"); - return; + return {}; } /* Check that we have also the image file */ if(conf.value("image") != data[1].first) { Error() << "Text::MagnumFont::openData(): expected file" << conf.value("image") << "but got" << data[1].first; - return; + return {}; } /* Open and load image file */ Trade::TgaImporter importer; if(!importer.openData(data[1].second)) { Error() << "Text::MagnumFont::openData(): cannot open image file"; - return; + return {}; } std::optional image = importer.image2D(0); if(!image) { Error() << "Text::MagnumFont::openData(): cannot load image file"; - return; + return {}; } - openInternal(std::move(conf), std::move(*image)); + return openInternal(std::move(conf), std::move(*image)); } -void MagnumFont::doOpenFile(const std::string& filename, Float) { +std::pair MagnumFont::doOpenFile(const std::string& filename, Float) { /* Open the configuration file */ Utility::Configuration conf(filename, Utility::Configuration::Flag::ReadOnly|Utility::Configuration::Flag::SkipComments); if(!conf.isValid() || conf.isEmpty()) { Error() << "Text::MagnumFont::openFile(): cannot open file" << filename << conf.isValid(); - return; + return {}; } /* Check version */ if(conf.value("version") != 1) { Error() << "Text::MagnumFont::openFile(): unsupported file version, expected 1 but got" << conf.value("version"); - return; + return {}; } /* Open and load image file */ @@ -131,21 +131,20 @@ void MagnumFont::doOpenFile(const std::string& filename, Float) { Trade::TgaImporter importer; if(!importer.openFile(imageFilename)) { Error() << "Text::MagnumFont::openFile(): cannot open image file" << imageFilename; - return; + return {}; } std::optional image = importer.image2D(0); if(!image) { Error() << "Text::MagnumFont::openFile(): cannot load image file"; - return; + return {}; } - openInternal(std::move(conf), std::move(*image)); + return openInternal(std::move(conf), std::move(*image)); } -void MagnumFont::openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image) { +std::pair MagnumFont::openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image) { /* Everything okay, save the data internally */ _opened = new Data{std::move(conf), std::move(image), {}, {}}; - _size = _opened->conf.value("fontSize"); /* Glyph advances */ const std::vector glyphs = _opened->conf.groups("glyph"); @@ -160,6 +159,8 @@ void MagnumFont::openInternal(Utility::Configuration&& conf, Trade::ImageData2D& CORRADE_INTERNAL_ASSERT(glyphId < _opened->glyphAdvance.size()); _opened->glyphId.emplace(c->value("unicode"), glyphId); } + + return {_opened->conf.value("fontSize"), 0}; } void MagnumFont::doClose() { diff --git a/src/Plugins/MagnumFont/MagnumFont.h b/src/Plugins/MagnumFont/MagnumFont.h index 3999bcc68..99fc3de5f 100644 --- a/src/Plugins/MagnumFont/MagnumFont.h +++ b/src/Plugins/MagnumFont/MagnumFont.h @@ -115,9 +115,9 @@ class MagnumFont: public AbstractFont { bool doIsOpened() const override; - void doOpenData(const std::vector>>& data, Float) override; + std::pair doOpenData(const std::vector>>& data, Float) override; - void doOpenFile(const std::string& filename, Float) override; + std::pair doOpenFile(const std::string& filename, Float) override; void doClose() override; @@ -129,9 +129,9 @@ class MagnumFont: public AbstractFont { std::unique_ptr doLayout(const GlyphCache& cache, Float size, const std::string& text) override; - Data* _opened; + std::pair openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image); - void openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image); + Data* _opened; }; }} diff --git a/src/Plugins/MagnumFont/pluginRegistrationMagnumFont.cpp b/src/Plugins/MagnumFont/pluginRegistrationMagnumFont.cpp index 3482fd6f6..9438143d0 100644 --- a/src/Plugins/MagnumFont/pluginRegistrationMagnumFont.cpp +++ b/src/Plugins/MagnumFont/pluginRegistrationMagnumFont.cpp @@ -25,4 +25,4 @@ #include "MagnumFont/MagnumFont.h" CORRADE_PLUGIN_REGISTER(MagnumFont, Magnum::Text::MagnumFont, - "cz.mosra.magnum.Text.AbstractFont/0.2.1") + "cz.mosra.magnum.Text.AbstractFont/0.2.2") diff --git a/src/Plugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp b/src/Plugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp index c0cb3d190..25e14c1d6 100644 --- a/src/Plugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp +++ b/src/Plugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp @@ -60,11 +60,15 @@ void MagnumFontConverterTest::exportFont() { /* Fake font with fake cache */ class FakeFont: public Text::AbstractFont { public: - explicit FakeFont() { _size = 16.0f; } + explicit FakeFont(): _opened(false) {} private: - void doClose() {} - bool doIsOpened() const { return true; } + void doClose() { _opened = false; } + bool doIsOpened() const { return _opened; } + std::pair doOpenFile(const std::string&, Float) { + _opened = true; + return {16.0f, 0}; + } Features doFeatures() const { return {}; } std::unique_ptr doLayout(const GlyphCache&, Float, const std::string&) { return nullptr; } @@ -86,7 +90,10 @@ void MagnumFontConverterTest::exportFont() { CORRADE_ASSERT_UNREACHABLE(); } + + bool _opened; } font; + font.openFile({}, {}); /* Create fake cache */ MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg); diff --git a/src/Text/AbstractFont.cpp b/src/Text/AbstractFont.cpp index f8699d421..a45c9ff43 100644 --- a/src/Text/AbstractFont.cpp +++ b/src/Text/AbstractFont.cpp @@ -34,7 +34,7 @@ namespace Magnum { namespace Text { AbstractFont::AbstractFont(): _size(0.0f) {} -AbstractFont::AbstractFont(PluginManager::AbstractManager* manager, std::string plugin): AbstractPlugin(manager, std::move(plugin)), _size(0.0f) {} +AbstractFont::AbstractFont(PluginManager::AbstractManager* manager, std::string plugin): AbstractPlugin(manager, std::move(plugin)), _size(0.0f), _lineHeight(0.0f) {} bool AbstractFont::openData(const std::vector>>& data, const Float size) { CORRADE_ASSERT(features() & Feature::OpenData, @@ -43,18 +43,19 @@ bool AbstractFont::openData(const std::vector>>& data, const Float size) { +std::pair AbstractFont::doOpenData(const std::vector>>& data, const Float size) { CORRADE_ASSERT(!(features() & Feature::MultiFile), - "Text::AbstractFont::openData(): feature advertised but not implemented", ); + "Text::AbstractFont::openData(): feature advertised but not implemented", {}); CORRADE_ASSERT(data.size() == 1, - "Text::AbstractFont::openData(): expected just one file for single-file format", ); + "Text::AbstractFont::openData(): expected just one file for single-file format", {}); close(); - doOpenSingleData(data[0].second, size); + return doOpenSingleData(data[0].second, size); } bool AbstractFont::openSingleData(const Containers::ArrayReference data, const Float size) { @@ -64,29 +65,31 @@ bool AbstractFont::openSingleData(const Containers::ArrayReference, Float) { - CORRADE_ASSERT(false, "Text::AbstractFont::openSingleData(): feature advertised but not implemented", ); +std::pair AbstractFont::doOpenSingleData(Containers::ArrayReference, Float) { + CORRADE_ASSERT(false, "Text::AbstractFont::openSingleData(): feature advertised but not implemented", {}); } bool AbstractFont::openFile(const std::string& filename, const Float size) { close(); - doOpenFile(filename, size); + std::tie(_size, _lineHeight) = doOpenFile(filename, size); + CORRADE_INTERNAL_ASSERT(isOpened() || (_size == 0.0f && _lineHeight == 0.0f)); return isOpened(); } -void AbstractFont::doOpenFile(const std::string& filename, const Float size) { +std::pair AbstractFont::doOpenFile(const std::string& filename, const Float size) { CORRADE_ASSERT(features() & Feature::OpenData && !(features() & Feature::MultiFile), - "Text::AbstractFont::openFile(): not implemented", ); + "Text::AbstractFont::openFile(): not implemented", {}); /* Open file */ std::ifstream in(filename.data(), std::ios::binary); if(!in.good()) { Error() << "Trade::AbstractFont::openFile(): cannot open file" << filename; - return; + return {}; } /* Create array to hold file contents */ @@ -98,12 +101,14 @@ void AbstractFont::doOpenFile(const std::string& filename, const Float size) { in.read(reinterpret_cast(data.begin()), data.size()); in.close(); - doOpenSingleData(data, size); + return doOpenSingleData(data, size); } void AbstractFont::close() { if(isOpened()) { doClose(); + _size = 0.0f; + _lineHeight = 0.0f; CORRADE_INTERNAL_ASSERT(!isOpened()); } } diff --git a/src/Text/AbstractFont.h b/src/Text/AbstractFont.h index 6e9fd9d38..57e04c753 100644 --- a/src/Text/AbstractFont.h +++ b/src/Text/AbstractFont.h @@ -67,7 +67,7 @@ checked by the implementation: there is any file opened. */ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { - CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFont/0.2.1") + CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFont/0.2.2") public: /** @@ -150,6 +150,9 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { /** @brief Font size */ Float size() const { return _size; } + /** @brief Line height */ + Float lineHeight() const { return _lineHeight; } + /** * @brief Glyph ID for given character * @@ -199,13 +202,6 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { */ std::unique_ptr layout(const GlyphCache& cache, Float size, const std::string& text); - #ifdef DOXYGEN_GENERATING_OUTPUT - private: - #else - protected: - #endif - Float _size; - #ifdef DOXYGEN_GENERATING_OUTPUT protected: #else @@ -220,22 +216,29 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { /** * @brief Implementation for @ref openData() * - * If the plugin doesn't have @ref Feature::MultiFile, default - * implementation calls @ref doOpenSingleData(). + * Return size and line height of opened font on successful opening, + * zeros otherwise. If the plugin doesn't have @ref Feature::MultiFile, + * default implementation calls @ref doOpenSingleData(). */ - virtual void doOpenData(const std::vector>>& data, Float size); + virtual std::pair doOpenData(const std::vector>>& data, Float size); - /** @brief Implementation for @ref openSingleData() */ - virtual void doOpenSingleData(Containers::ArrayReference data, Float size); + /** + * @brief Implementation for @ref openSingleData() + * + * Return size and line height of opened font on successful opening, + * zeros otherwise. + */ + virtual std::pair doOpenSingleData(Containers::ArrayReference data, Float size); /** * @brief Implementation for @ref openFile() * - * 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 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. */ - virtual void doOpenFile(const std::string& filename, Float size); + virtual std::pair doOpenFile(const std::string& filename, Float size); /** @brief Implementation for @ref close() */ virtual void doClose() = 0; @@ -266,6 +269,11 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { /** @brief Implementation for @ref layout() */ virtual std::unique_ptr doLayout(const GlyphCache& cache, Float size, const std::string& text) = 0; + + #ifdef DOXYGEN_GENERATING_OUTPUT + private: + #endif + Float _size, _lineHeight; }; CORRADE_ENUMSET_OPERATORS(AbstractFont::Features) diff --git a/src/Text/Test/AbstractFontTest.cpp b/src/Text/Test/AbstractFontTest.cpp index 7257816d9..afb577ecd 100644 --- a/src/Text/Test/AbstractFontTest.cpp +++ b/src/Text/Test/AbstractFontTest.cpp @@ -55,8 +55,9 @@ class SingleDataFont: public Text::AbstractFont { bool doIsOpened() const override { return opened; } void doClose() override {} - void doOpenSingleData(const Containers::ArrayReference data, Float) override { + std::pair doOpenSingleData(const Containers::ArrayReference data, Float) override { opened = (data.size() == 1 && data[0] == 0xa5); + return {}; } UnsignedInt doGlyphId(char32_t) override { return 0; }