diff --git a/src/Text/AbstractFontConverter.cpp b/src/Text/AbstractFontConverter.cpp index ebd8cca31..94c626c31 100644 --- a/src/Text/AbstractFontConverter.cpp +++ b/src/Text/AbstractFontConverter.cpp @@ -22,13 +22,14 @@ DEALINGS IN THE SOFTWARE. */ +#include "AbstractFontConverter.h" + +#include #include #include #include #include -#include "AbstractFontConverter.h" - namespace Magnum { namespace Text { AbstractFontConverter::AbstractFontConverter() = default; @@ -39,7 +40,7 @@ std::vector>> AbstractFo CORRADE_ASSERT(features() >= (Feature::ExportFont|Feature::ConvertData), "Text::AbstractFontConverter::exportFontToData(): feature not supported", {}); - return doExportFontToData(font, cache, filename, Utility::Unicode::utf32(characters)); + return doExportFontToData(font, cache, filename, uniqueUnicode(characters)); } std::vector>> AbstractFontConverter::doExportFontToData(AbstractFont* const font, GlyphCache* const cache, const std::string& filename, const std::u32string& characters) const { @@ -57,7 +58,7 @@ Containers::Array AbstractFontConverter::exportFontToSingleData(A CORRADE_ASSERT(!(features() & Feature::MultiFile), "Text::AbstractFontConverter::exportFontToSingleData(): the format is not single-file", nullptr); - return doExportFontToSingleData(font, cache, Utility::Unicode::utf32(characters)); + return doExportFontToSingleData(font, cache, uniqueUnicode(characters)); } Containers::Array AbstractFontConverter::doExportFontToSingleData(AbstractFont*, GlyphCache*, const std::u32string&) const { @@ -69,7 +70,7 @@ bool AbstractFontConverter::exportFontToFile(AbstractFont* const font, GlyphCach CORRADE_ASSERT(features() & Feature::ExportFont, "Text::AbstractFontConverter::exportFontToFile(): feature not supported", false); - return doExportFontToFile(font, cache, filename, Utility::Unicode::utf32(characters)); + return doExportFontToFile(font, cache, filename, uniqueUnicode(characters)); } bool AbstractFontConverter::doExportFontToFile(AbstractFont* const font, GlyphCache* const cache, const std::string& filename, const std::u32string& characters) const { @@ -213,4 +214,15 @@ GlyphCache* AbstractFontConverter::doImportGlyphCacheFromFile(const std::string& return doImportGlyphCacheFromSingleData(data); } +std::u32string AbstractFontConverter::uniqueUnicode(const std::string& characters) { + /* Convert UTF-8 to UTF-32 */ + std::u32string result = Utility::Unicode::utf32(characters); + + /* Remove duplicate glyphs */ + std::sort(result.begin(), result.end()); + result.erase(std::unique(result.begin(), result.end()), result.end()); + + return std::move(result); +} + }} diff --git a/src/Text/AbstractFontConverter.h b/src/Text/AbstractFontConverter.h index 97ff78d08..c4508a7c0 100644 --- a/src/Text/AbstractFontConverter.h +++ b/src/Text/AbstractFontConverter.h @@ -44,7 +44,8 @@ Provides functionality for converting arbitrary font to different format. @section AbstractFontConverter-subclassing Subclassing Plugin implements doFeatures() and one or more of `exportTo*()` / `importFrom*()` -functions based on what features are supported. +functions based on what features are supported. Characters passed to font +exporting functions are converted to list of unique UTF-32 characters. You don't need to do most of the redundant sanity checks, these things are checked by the implementation: @@ -304,6 +305,9 @@ class MAGNUM_TEXT_EXPORT AbstractFontConverter: public PluginManager::AbstractPl * with its contents. */ virtual GlyphCache* doImportGlyphCacheFromFile(const std::string& filename) const; + + private: + MAGNUM_TEXT_LOCAL static std::u32string uniqueUnicode(const std::string& characters); }; CORRADE_ENUMSET_OPERATORS(AbstractFontConverter::Features) diff --git a/src/Text/Test/AbstractFontConverterTest.cpp b/src/Text/Test/AbstractFontConverterTest.cpp index b5c9cf380..e27626cac 100644 --- a/src/Text/Test/AbstractFontConverterTest.cpp +++ b/src/Text/Test/AbstractFontConverterTest.cpp @@ -37,6 +37,8 @@ class AbstractFontConverterTest: public TestSuite::Tester { public: explicit AbstractFontConverterTest(); + void convertGlyphs(); + void exportFontToSingleData(); void exportFontToFile(); @@ -48,7 +50,9 @@ class AbstractFontConverterTest: public TestSuite::Tester { }; AbstractFontConverterTest::AbstractFontConverterTest() { - addTests({&AbstractFontConverterTest::exportFontToSingleData, + addTests({&AbstractFontConverterTest::convertGlyphs, + + &AbstractFontConverterTest::exportFontToSingleData, &AbstractFontConverterTest::exportFontToFile, &AbstractFontConverterTest::exportGlyphCacheToSingleData, @@ -58,6 +62,29 @@ AbstractFontConverterTest::AbstractFontConverterTest() { &AbstractFontConverterTest::importGlyphCacheFromFile}); } +void AbstractFontConverterTest::convertGlyphs() { + class GlyphExporter: public AbstractFontConverter { + public: + GlyphExporter(std::u32string& characters): characters(characters) {} + + private: + Features doFeatures() const override { return Feature::ConvertData|Feature::ExportFont; } + + Containers::Array doExportFontToSingleData(AbstractFont*, GlyphCache*, const std::u32string& characters) const override { + this->characters = characters; + return {}; + } + + std::u32string& characters; + }; + + std::u32string characters; + GlyphExporter exporter(characters); + exporter.exportFontToSingleData(nullptr, nullptr, "abC01a0 "); + CORRADE_COMPARE(characters, (std::u32string{ + U' ', U'0', U'1', U'C', U'a', U'b'})); +} + void AbstractFontConverterTest::exportFontToSingleData() { class SingleDataExporter: public Text::AbstractFontConverter { private: