diff --git a/src/Plugins/MagnumFont/CMakeLists.txt b/src/Plugins/MagnumFont/CMakeLists.txt new file mode 100644 index 000000000..dc9025bc1 --- /dev/null +++ b/src/Plugins/MagnumFont/CMakeLists.txt @@ -0,0 +1,53 @@ +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +find_package(Magnum REQUIRED Text) + +set(MagnumFont_SOURCES + MagnumFont.cpp) + +set(MagnumFont_HEADERS + MagnumFont.h) + +add_library(MagnumFontObjects OBJECT ${MagnumFont_SOURCES}) +set_target_properties(MagnumFontObjects PROPERTIES COMPILE_FLAGS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}) + +corrade_add_plugin(MagnumFont ${MAGNUM_PLUGINS_FONT_INSTALL_DIR} + MagnumFont.conf + $ + pluginRegistrationMagnumFont.cpp) +target_link_libraries(MagnumFont + ${MAGNUM_LIBRARIES} + ${MAGNUM_TEXT_LIBRARIES}) + +install(FILES ${MagnumFont_HEADERS} DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/MagnumFont) + +if(BUILD_GL_TESTS) + add_library(MagnumFontTestLib $) + target_link_libraries(MagnumFontTestLib + ${MAGNUM_LIBRARIES} + ${MAGNUM_TEXT_LIBRARIES} + TgaImporterTestLib) + add_subdirectory(Test) +endif() diff --git a/src/Plugins/MagnumFont/MagnumFont.conf b/src/Plugins/MagnumFont/MagnumFont.conf new file mode 100644 index 000000000..6aae56c10 --- /dev/null +++ b/src/Plugins/MagnumFont/MagnumFont.conf @@ -0,0 +1 @@ +depends=TgaImporter diff --git a/src/Plugins/MagnumFont/MagnumFont.cpp b/src/Plugins/MagnumFont/MagnumFont.cpp new file mode 100644 index 000000000..b526a4fc3 --- /dev/null +++ b/src/Plugins/MagnumFont/MagnumFont.cpp @@ -0,0 +1,222 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "MagnumFont.h" + +#include +#include +#include +#include +#include +#include + +#include "TgaImporter/TgaImporter.h" + +namespace Magnum { namespace Text { + +struct MagnumFont::Data { + Utility::Configuration conf; + Trade::ImageData2D image; + std::unordered_map glyphId; + std::vector glyphAdvance; +}; + +namespace { + class MagnumFontLayouter: public AbstractLayouter { + public: + explicit MagnumFontLayouter(const std::unordered_map& glyphId, const std::vector& glyphAdvance, const GlyphCache* cache, Float fontSize, Float textSize, const std::string& text); + + std::tuple renderGlyph(UnsignedInt i) override; + + private: + const std::vector& glyphAdvance; + const GlyphCache* const cache; + const Float fontSize, textSize; + std::vector glyphs; + }; +} + +MagnumFont::MagnumFont(): _opened(nullptr) {} + +MagnumFont::MagnumFont(PluginManager::AbstractManager* const manager, std::string plugin): AbstractFont(manager, std::move(plugin)), _opened(nullptr) {} + +auto MagnumFont::doFeatures() const -> Features { return Feature::OpenData|Feature::MultiFile|Feature::PreparedGlyphCache; } + +bool MagnumFont::doIsOpened() const { return _opened; } + +void MagnumFont::doOpenData(const std::vector>>& data, const Float) { + /* We need just the configuration file and image file */ + if(data.size() != 2) { + Error() << "Magnum::Text::MagnumFont::openData(): wanted two files, got" << data.size(); + return; + } + + /* Open the configuration file */ + std::istringstream in({reinterpret_cast(data[0].second.begin()), data[0].second.size()}); + Utility::Configuration conf(in, Utility::Configuration::Flag::SkipComments); + if(!conf.isValid() || conf.isEmpty()) { + Error() << "Magnum::Text::MagnumFont::openData(): cannot open file" << data[0].first << conf.isValid(); + return; + } + + /* Check that we have also the image file */ + if(conf.value("image") != data[1].first) { + Error() << "Magnum::Text::MagnumFont::openData(): expected file" + << conf.value("image") << "but got" << data[1].first; + return; + } + + /* Open and load image file */ + Trade::TgaImporter importer; + if(!importer.openData(data[1].second)) { + Error() << "Magnum::Text::MagnumFont::openData(): cannot open image file"; + return; + } + Trade::ImageData2D* image = importer.image2D(0); + if(!image) { + Error() << "Magnum::Text::MagnumFont::openData(): cannot load image file"; + return; + } + + openInternal(std::move(conf), std::move(*image)); + delete image; +} + +void 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() << "Magnum::Text::MagnumFont::openFile(): cannot open file" << filename << conf.isValid(); + return; + } + + /* Open and load image file */ + const std::string imageFilename = Utility::Directory::join(Utility::Directory::path(filename), conf.value("image")); + Trade::TgaImporter importer; + if(!importer.openFile(imageFilename)) { + Error() << "Magnum::Text::MagnumFont::openFile(): cannot open image file" << imageFilename; + return; + } + Trade::ImageData2D* image = importer.image2D(0); + if(!image) { + Error() << "Magnum::Text::MagnumFont::openFile(): cannot load image file"; + return; + } + + openInternal(std::move(conf), std::move(*image)); + delete image; +} + +void 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"); + + /* Set glyph advance array to proper size */ + _opened->glyphAdvance.resize(_opened->conf.groupCount("glyph")); + + /* Fill character->glyph map */ + const std::vector chars = _opened->conf.groups("char"); + for(const Utility::ConfigurationGroup* const c: chars) { + const UnsignedInt glyphId = c->value("glyph"); + CORRADE_INTERNAL_ASSERT(glyphId < _opened->glyphAdvance.size()); + _opened->glyphId.emplace(c->value("unicode"), glyphId); + _opened->glyphAdvance[glyphId] = c->value("advance"); + } +} + +void MagnumFont::doClose() { + delete _opened; + _opened = nullptr; +} + +UnsignedInt MagnumFont::doGlyphId(const char32_t character) { + auto it = _opened->glyphId.find(character); + return it != _opened->glyphId.end() ? it->second : 0; +} + +Vector2 MagnumFont::doGlyphAdvance(const UnsignedInt glyph) { + return glyph < _opened->glyphAdvance.size() ? _opened->glyphAdvance[glyph] : Vector2(); +} + +GlyphCache* MagnumFont::doCreateGlyphCache() { + /* Set cache image */ + auto cache = new Text::DistanceFieldGlyphCache( + _opened->conf.value("originalImageSize"), + _opened->image.size(), + _opened->conf.value("padding").min()); + cache->setDistanceFieldImage({}, _opened->image); + + /* Fill glyph map */ + const std::vector glyphs = _opened->conf.groups("glyph"); + for(std::size_t i = 0; i != glyphs.size(); ++i) + cache->insert(i, glyphs[i]->value("position"), glyphs[i]->value("rectangle")); + + return cache; +} + +AbstractLayouter* MagnumFont::doLayout(const GlyphCache* cache, Float size, const std::string& text) { + return new MagnumFontLayouter(_opened->glyphId, _opened->glyphAdvance, cache, this->size(), size, text); +} + +namespace { + +MagnumFontLayouter::MagnumFontLayouter(const std::unordered_map& glyphId, const std::vector& glyphAdvance, const GlyphCache* cache, Float fontSize, Float textSize, const std::string& text): glyphAdvance(glyphAdvance), cache(cache), fontSize(fontSize), textSize(textSize) { + /* Get glyph codes from characters */ + glyphs.reserve(text.size()); + for(std::size_t i = 0; i != text.size(); ) { + UnsignedInt codepoint; + std::tie(codepoint, i) = Utility::Unicode::nextChar(text, i); + const auto it = glyphId.find(codepoint); + glyphs.push_back(it == glyphId.end() ? 0 : it->second); + } + _glyphCount = glyphs.size(); +} + +std::tuple MagnumFontLayouter::renderGlyph(UnsignedInt i) { + /* Position of the texture in the resulting glyph, texture coordinates */ + Vector2i position; + Rectanglei rectangle; + std::tie(position, rectangle) = (*cache)[glyphs[i]]; + + const Rectangle texturePosition = Rectangle::fromSize(Vector2(position)/fontSize, + Vector2(rectangle.size())/fontSize); + const Rectangle textureCoordinates(Vector2(rectangle.bottomLeft())/cache->textureSize(), + Vector2(rectangle.topRight())/cache->textureSize()); + + /* Absolute quad position, composed from cursor position, glyph offset + and texture position, denormalized to requested text size */ + Rectangle quadPosition = Rectangle::fromSize( + Vector2(texturePosition.left(), texturePosition.bottom())*textSize, + texturePosition.size()*textSize); + + /* Advance for given glyph, denormalized to requested text size */ + const Vector2 advance = glyphAdvance[glyphs[i]]*textSize/fontSize; + + return std::make_tuple(quadPosition, textureCoordinates, advance); +} + +} + +}} diff --git a/src/Plugins/MagnumFont/MagnumFont.h b/src/Plugins/MagnumFont/MagnumFont.h new file mode 100644 index 000000000..065b8f1e6 --- /dev/null +++ b/src/Plugins/MagnumFont/MagnumFont.h @@ -0,0 +1,130 @@ +#ifndef Magnum_Text_MagnumFont_h +#define Magnum_Text_MagnumFont_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class Magnum::Text::MagnumFont + */ + +#include +#include + +namespace Magnum { namespace Text { + +/** +@brief Simple bitmap font + +The font consists of two files, one text file containing character and glyph +info and one TGA file containing the glyphs in distance field format. The font +can be conveniently created from any other format using MagnumFontConverter. +The file syntax is as in following: + + # Font image filename + image=font.tga + + # Size of unscaled font image + originalImageSize=1536 1536 + + # Glyph padding + padding=9 + + # Font size + fontSize=128 + + # Character + [char] + + # UTF-32 codepoint ('a') + unicode=0061 + + # Glyph ID + glyph=1 + + # Advance to next character in pixels (i.e. on unscaled font image) + advance=45 0 + + # Another character + [char] + unicode=0062 + glyph=2 + advance=42 0 + + # ... + + # Glyph 0, a.k.a. "Not Found" glyph + [glyph] + + # Glyph texture position relative to baseline, in pixels + position=5 -1 + + # Glyph rectangle in font image, in pixels (left, bottom, right, top) + rectangle=0 0 42 25 + + # Glyph 1 + [glyph] + position=0 0 + rectangle=45 0 44 25 + + # ... + +@see Trade::TgaImporter +*/ +class MagnumFont: public AbstractFont { + public: + /** @brief Default constructor */ + explicit MagnumFont(); + + /** @brief Plugin manager constructor */ + explicit MagnumFont(PluginManager::AbstractManager* manager, std::string plugin); + + private: + class Data; + + Features doFeatures() const override; + + bool doIsOpened() const override; + + void doOpenData(const std::vector>>& data, Float) override; + + void doOpenFile(const std::string& filename, Float) override; + + void doClose() override; + + UnsignedInt doGlyphId(char32_t character) override; + + Vector2 doGlyphAdvance(UnsignedInt glyph) override; + + GlyphCache* doCreateGlyphCache() override; + + AbstractLayouter* doLayout(const GlyphCache* cache, Float size, const std::string& text) override; + + Data* _opened; + + void openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image); +}; + +}} + +#endif diff --git a/src/Plugins/MagnumFont/Test/CMakeLists.txt b/src/Plugins/MagnumFont/Test/CMakeLists.txt new file mode 100644 index 000000000..0cc473499 --- /dev/null +++ b/src/Plugins/MagnumFont/Test/CMakeLists.txt @@ -0,0 +1,30 @@ +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/magnumFontTestConfigure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/magnumFontTestConfigure.h) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +corrade_add_test(MagnumFontTest MagnumFontTest.cpp LIBRARIES MagnumFontTestLib ${GL_TEST_LIBRARIES}) diff --git a/src/Plugins/MagnumFont/Test/MagnumFontTest.cpp b/src/Plugins/MagnumFont/Test/MagnumFontTest.cpp new file mode 100644 index 000000000..638abc890 --- /dev/null +++ b/src/Plugins/MagnumFont/Test/MagnumFontTest.cpp @@ -0,0 +1,105 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include + +#include "MagnumFont/MagnumFont.h" + +#include "magnumFontTestConfigure.h" + +namespace Magnum { namespace Text { namespace Test { + +class MagnumFontTest: public Magnum::Test::AbstractOpenGLTester { + public: + explicit MagnumFontTest(); + + void properties(); + void layout(); + void createGlyphCache(); +}; + +MagnumFontTest::MagnumFontTest() { + addTests({&MagnumFontTest::properties, + &MagnumFontTest::layout, + &MagnumFontTest::createGlyphCache}); +} + +void MagnumFontTest::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.glyphAdvance(font.glyphId(U'W')), Vector2(23.0f, 0.0f)); +} + +void MagnumFontTest::layout() { + MagnumFont font; + CORRADE_VERIFY(font.openFile(Utility::Directory::join(MAGNUMFONT_TEST_DIR, "font.conf"), 0.0f)); + + /* Fill the cache with some fake glyphs */ + GlyphCache cache(Vector2i(256)); + cache.insert(font.glyphId(U'W'), {25, 34}, {{0, 8}, {16, 128}}); + cache.insert(font.glyphId(U'e'), {25, 12}, {{16, 4}, {64, 32}}); + + AbstractLayouter* layouter = font.layout(&cache, 0.5f, "Wave"); + CORRADE_VERIFY(layouter); + CORRADE_COMPARE(layouter->glyphCount(), 4); + + Rectangle position; + Rectangle textureCoordinates; + Vector2 advance; + + /* 'W' */ + std::tie(position, textureCoordinates, advance) = layouter->renderGlyph(0); + CORRADE_COMPARE(position, Rectangle({0.78125f, 1.0625f}, {1.28125f, 4.8125f})); + CORRADE_COMPARE(textureCoordinates, Rectangle({0, 0.03125f}, {0.0625f, 0.5f})); + CORRADE_COMPARE(advance, Vector2(0.71875f, 0.0f)); + + /* 'a' (not in cache) */ + std::tie(position, textureCoordinates, advance) = layouter->renderGlyph(1); + CORRADE_COMPARE(position, Rectangle()); + CORRADE_COMPARE(textureCoordinates, Rectangle()); + CORRADE_COMPARE(advance, Vector2(0.34375f, 0.0f)); + + /* 'v' (not in cache) */ + std::tie(position, textureCoordinates, advance) = layouter->renderGlyph(2); + CORRADE_COMPARE(position, Rectangle()); + CORRADE_COMPARE(textureCoordinates, Rectangle()); + CORRADE_COMPARE(advance, Vector2(0.34375f, 0.0f)); + + /* 'e' */ + std::tie(position, textureCoordinates, advance) = layouter->renderGlyph(3); + CORRADE_COMPARE(position, Rectangle({0.78125f, 0.375f}, {2.28125f, 1.25f})); + CORRADE_COMPARE(textureCoordinates, Rectangle({0.0625f, 0.015625f}, {0.25f, 0.125f})); + CORRADE_COMPARE(advance, Vector2(0.375f, 0.0f)); +} + +void MagnumFontTest::createGlyphCache() { + /** @todo */ +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Text::Test::MagnumFontTest) diff --git a/src/Plugins/MagnumFont/Test/font.conf b/src/Plugins/MagnumFont/Test/font.conf new file mode 100644 index 000000000..0a771d745 --- /dev/null +++ b/src/Plugins/MagnumFont/Test/font.conf @@ -0,0 +1,29 @@ +image=font.tga +originalImageSize=1536 1536 +padding=24 24 +fontSize=16 +[char] +unicode=57 +advance=23 0 +glyph=2 +[char] +unicode=61 +advance=11 0 +glyph=0 +[char] +unicode=65 +advance=12 0 +glyph=1 +[char] +unicode=76 +advance=11 0 +glyph=0 +[glyph] +position=0 0 +rectangle=0 0 0 0 +[glyph] +position=1 -12 +rectangle=-8 -20 88 56 +[glyph] +position=1 10 +rectangle=-24 -16 40 152 diff --git a/src/Plugins/MagnumFont/Test/font.tga b/src/Plugins/MagnumFont/Test/font.tga new file mode 100644 index 000000000..8389c0da6 Binary files /dev/null and b/src/Plugins/MagnumFont/Test/font.tga differ diff --git a/src/Plugins/MagnumFont/Test/magnumFontTestConfigure.h.cmake b/src/Plugins/MagnumFont/Test/magnumFontTestConfigure.h.cmake new file mode 100644 index 000000000..250b209d4 --- /dev/null +++ b/src/Plugins/MagnumFont/Test/magnumFontTestConfigure.h.cmake @@ -0,0 +1,25 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#define MAGNUMFONT_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}" diff --git a/src/Plugins/MagnumFont/pluginRegistrationMagnumFont.cpp b/src/Plugins/MagnumFont/pluginRegistrationMagnumFont.cpp new file mode 100644 index 000000000..3250c4f96 --- /dev/null +++ b/src/Plugins/MagnumFont/pluginRegistrationMagnumFont.cpp @@ -0,0 +1,28 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "MagnumFont/MagnumFont.h" + +CORRADE_PLUGIN_REGISTER(MagnumFont, Magnum::Text::MagnumFont, + "cz.mosra.magnum.Text.AbstractFont/0.2") diff --git a/src/Plugins/MagnumFontConverter/CMakeLists.txt b/src/Plugins/MagnumFontConverter/CMakeLists.txt new file mode 100644 index 000000000..9cc254f97 --- /dev/null +++ b/src/Plugins/MagnumFontConverter/CMakeLists.txt @@ -0,0 +1,52 @@ +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +find_package(Magnum REQUIRED Text) + +set(MagnumFontConverter_SOURCES + MagnumFontConverter.cpp) + +set(MagnumFontConverter_HEADERS + MagnumFontConverter.h) + +add_library(MagnumFontConverterObjects OBJECT ${MagnumFontConverter_SOURCES}) +set_target_properties(MagnumFontConverterObjects PROPERTIES COMPILE_FLAGS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}) + +corrade_add_plugin(MagnumFontConverter ${MAGNUM_PLUGINS_FONTCONVERTER_INSTALL_DIR} + MagnumFontConverter.conf + $ + pluginRegistrationMagnumFontConverter.cpp) +target_link_libraries(MagnumFontConverter + ${MAGNUM_LIBRARIES} + ${MAGNUM_TEXT_LIBRARIES}) + +install(FILES ${MagnumFontConverter_HEADERS} DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/MagnumFontConverter) + +if(BUILD_TESTS) + add_library(MagnumFontConverterTestLib $) + target_link_libraries(MagnumFontConverterTestLib + ${MAGNUM_LIBRARIES} + ${MAGNUM_TEXT_LIBRARIES}) + add_subdirectory(Test) +endif() diff --git a/src/Plugins/MagnumFontConverter/MagnumFontConverter.conf b/src/Plugins/MagnumFontConverter/MagnumFontConverter.conf new file mode 100644 index 000000000..977dc2119 --- /dev/null +++ b/src/Plugins/MagnumFontConverter/MagnumFontConverter.conf @@ -0,0 +1 @@ +depends=TgaImageConverter diff --git a/src/Plugins/MagnumFontConverter/MagnumFontConverter.cpp b/src/Plugins/MagnumFontConverter/MagnumFontConverter.cpp new file mode 100644 index 000000000..ab2d155ad --- /dev/null +++ b/src/Plugins/MagnumFontConverter/MagnumFontConverter.cpp @@ -0,0 +1,106 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "MagnumFontConverter.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Magnum { namespace Text { + +MagnumFontConverter::MagnumFontConverter() = default; + +MagnumFontConverter::MagnumFontConverter(PluginManager::AbstractManager* manager, std::string plugin): AbstractFontConverter(manager, std::move(plugin)) {} + +auto MagnumFontConverter::doFeatures() const -> Features { + return Feature::ExportFont|Feature::ConvertData|Feature::MultiFile; +} + +std::vector>> MagnumFontConverter::doExportFontToData(AbstractFont* font, GlyphCache* cache, const std::string& filename, const std::u32string& characters) const { + Utility::Configuration configuration; + + configuration.setValue("image", Utility::Directory::filename(filename) + ".tga"); + configuration.setValue("originalImageSize", cache->textureSize()); + configuration.setValue("padding", cache->padding()); + configuration.setValue("fontSize", font->size()); + + /* Compress glyph IDs so the glyphs are in consecutive array, glyph 0 + should stay at position 0 */ + std::unordered_map glyphIdMap; + glyphIdMap.reserve(cache->glyphCount()); + glyphIdMap.emplace(0, 0); + for(const std::pair>& glyph: *cache) + glyphIdMap.emplace(glyph.first, glyphIdMap.size()); + + /** @todo Save only glyphs contained in @p characters */ + + /* Inverse map from new glyph IDs to old ones */ + std::vector inverseGlyphIdMap(glyphIdMap.size()); + for(const std::pair& map: glyphIdMap) + inverseGlyphIdMap[map.second] = map.first; + + /* Save character properties, map glyph IDs to new ones */ + for(const char32_t c: characters) { + Utility::ConfigurationGroup* group = configuration.addGroup("char"); + const UnsignedInt glyphId = font->glyphId(c); + group->setValue("unicode", c); + group->setValue("advance", font->glyphAdvance(glyphId)); + + /* Map old glyph ID to new, if not found, map to glyph 0 */ + auto found = glyphIdMap.find(glyphId); + group->setValue("glyph", found == glyphIdMap.end() ? 0 : glyphIdMap.at(glyphId)); + } + + /* Save glyph properties in order which preserves their IDs */ + for(UnsignedInt oldGlyphId: inverseGlyphIdMap) { + std::pair glyph = (*cache)[oldGlyphId]; + Utility::ConfigurationGroup* group = configuration.addGroup("glyph"); + group->setValue("position", glyph.first); + group->setValue("rectangle", glyph.second); + } + + std::ostringstream confOut; + configuration.save(confOut); + std::string confStr = confOut.str(); + Containers::Array confData{confStr.size()}; + std::copy(confStr.begin(), confStr.end(), confData.begin()); + + /* Save cache image */ + Image2D image(ImageFormat::Red, ImageType::UnsignedByte); + cache->texture()->image(0, image); + auto tgaData = Trade::TgaImageConverter().exportToData(&image); + + std::vector>> out; + out.emplace_back(filename + ".conf", std::move(confData)); + out.emplace_back(filename + ".tga", std::move(tgaData)); + return std::move(out); +} + +}} diff --git a/src/Plugins/MagnumFontConverter/MagnumFontConverter.h b/src/Plugins/MagnumFontConverter/MagnumFontConverter.h new file mode 100644 index 000000000..a0e773397 --- /dev/null +++ b/src/Plugins/MagnumFontConverter/MagnumFontConverter.h @@ -0,0 +1,56 @@ +#ifndef Magnum_Text_MagnumFontConverter_h +#define Magnum_Text_MagnumFontConverter_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class Magnum::Text::MagnumFontConverter + */ + +#include + +namespace Magnum { namespace Text { + +/** +@brief Converter to MagnumFont + +Expects filename prefix, creates two files, `prefix.conf` and `prefix.tga`. See +MagnumFont for more information about the font. +*/ +class MagnumFontConverter: public Text::AbstractFontConverter { + public: + /** @brief Default constructor */ + explicit MagnumFontConverter(); + + /** @brief Plugin manager constructor */ + explicit MagnumFontConverter(PluginManager::AbstractManager* manager, std::string plugin); + + private: + Features doFeatures() const override; + std::vector>> doExportFontToData(AbstractFont* font, GlyphCache* cache, const std::string& filename, const std::u32string& characters) const override; +}; + +}} + +#endif diff --git a/src/Plugins/MagnumFontConverter/Test/CMakeLists.txt b/src/Plugins/MagnumFontConverter/Test/CMakeLists.txt new file mode 100644 index 000000000..7a41395ad --- /dev/null +++ b/src/Plugins/MagnumFontConverter/Test/CMakeLists.txt @@ -0,0 +1,37 @@ +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/magnumFontConverterTestConfigure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/magnumFontConverterTestConfigure.h) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../FreeTypeFont/Test/ + ${CMAKE_CURRENT_BINARY_DIR}/../../MagnumFont/Test/ + ${CMAKE_CURRENT_BINARY_DIR}) + +corrade_add_test(MagnumFontConverterTest MagnumFontConverterTest.cpp LIBRARIES + MagnumFontConverterTestLib + FreeTypeFontTestLib + TgaImageConverterTestLib + TgaImporterTestLib + ${GL_TEST_LIBRARIES}) diff --git a/src/Plugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp b/src/Plugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp new file mode 100644 index 000000000..a57311e09 --- /dev/null +++ b/src/Plugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp @@ -0,0 +1,99 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FreeTypeFont/FreeTypeFont.h" +#include "MagnumFontConverter/MagnumFontConverter.h" +#include "TgaImporter/TgaImporter.h" + +#include "freeTypeFontTestConfigure.h" +#include "magnumFontTestConfigure.h" +#include "magnumFontConverterTestConfigure.h" + +namespace Magnum { namespace Text { namespace Test { + +class MagnumFontConverterTest: public Magnum::Test::AbstractOpenGLTester { + public: + explicit MagnumFontConverterTest(); + + ~MagnumFontConverterTest(); + + void exportFont(); +}; + +MagnumFontConverterTest::MagnumFontConverterTest() { + addTests({&MagnumFontConverterTest::exportFont}); + + FreeTypeFont::initialize(); +} + +MagnumFontConverterTest::~MagnumFontConverterTest() { + FreeTypeFont::finalize(); +} + +void MagnumFontConverterTest::exportFont() { + /* Remove previously created files */ + Utility::Directory::rm(Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.conf")); + Utility::Directory::rm(Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.tga")); + + /* Open font */ + FreeTypeFont font; + CORRADE_VERIFY(font.openFile(Utility::Directory::join(FREETYPEFONT_TEST_DIR, "Oxygen.ttf"), 16.0f)); + + /* Create fake cache */ + MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg); + GlyphCache cache(TextureFormat::R8, Vector2i(1536), Vector2i(256), Vector2i(24)); + cache.insert(font.glyphId(U'W'), {25, 34}, {{0, 8}, {16, 128}}); + cache.insert(font.glyphId(U'e'), {25, 12}, {{16, 4}, {64, 32}}); + + /* Convert the file */ + MagnumFontConverter converter; + converter.exportFontToFile(&font, &cache, Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font"), "Wave"); + + /* Verify font parameters */ + /** @todo This might behave differently elsewhere due to unspecified order of glyphs in cache */ + CORRADE_COMPARE_AS(Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.conf"), + Utility::Directory::join(MAGNUMFONT_TEST_DIR, "font.conf"), + TestSuite::Compare::File); + + /* Verify font image, no need to test image contents, as the image is garbage anyway */ + Trade::TgaImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.tga"))); + Trade::ImageData2D* image = importer.image2D(0); + CORRADE_COMPARE(image->size(), Vector2i(256)); + CORRADE_COMPARE(image->format(), ImageFormat::Red); + CORRADE_COMPARE(image->type(), ImageType::UnsignedByte); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Text::Test::MagnumFontConverterTest) diff --git a/src/Plugins/MagnumFontConverter/Test/magnumFontConverterTestConfigure.h.cmake b/src/Plugins/MagnumFontConverter/Test/magnumFontConverterTestConfigure.h.cmake new file mode 100644 index 000000000..befd1c45b --- /dev/null +++ b/src/Plugins/MagnumFontConverter/Test/magnumFontConverterTestConfigure.h.cmake @@ -0,0 +1,25 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#define MAGNUMFONTCONVERTER_TEST_WRITE_DIR "${CMAKE_CURRENT_BINARY_DIR}" diff --git a/src/Plugins/MagnumFontConverter/pluginRegistrationMagnumFontConverter.cpp b/src/Plugins/MagnumFontConverter/pluginRegistrationMagnumFontConverter.cpp new file mode 100644 index 000000000..a0bbc18ce --- /dev/null +++ b/src/Plugins/MagnumFontConverter/pluginRegistrationMagnumFontConverter.cpp @@ -0,0 +1,28 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "MagnumFontConverter/MagnumFontConverter.h" + +CORRADE_PLUGIN_REGISTER(MagnumFontConverter, Magnum::Text::MagnumFontConverter, + "cz.mosra.magnum.Text.AbstractFontConverter/0.1")