diff --git a/src/Magnum/Text/AbstractFontConverter.cpp b/src/Magnum/Text/AbstractFontConverter.cpp index ff7bc364c..72a02d4d6 100644 --- a/src/Magnum/Text/AbstractFontConverter.cpp +++ b/src/Magnum/Text/AbstractFontConverter.cpp @@ -239,7 +239,7 @@ Containers::Pointer AbstractFontConverter::doImportGlyphCach /* Open file */ if(!Utility::Directory::exists(filename)) { - Error() << "Trade::AbstractFontConverter::importGlyphCacheFromFile(): cannot open file" << filename; + Error() << "Text::AbstractFontConverter::importGlyphCacheFromFile(): cannot open file" << filename; return nullptr; } diff --git a/src/Magnum/Text/Test/AbstractFontConverterTest.cpp b/src/Magnum/Text/Test/AbstractFontConverterTest.cpp index 2aca0a3e4..d78fa781a 100644 --- a/src/Magnum/Text/Test/AbstractFontConverterTest.cpp +++ b/src/Magnum/Text/Test/AbstractFontConverterTest.cpp @@ -45,15 +45,29 @@ struct AbstractFontConverterTest: TestSuite::Tester { void convertGlyphs(); void exportFontToSingleData(); + void exportFontToData(); + void exportFontToDataThroughSingleData(); + void exportFontToDataThroughSingleDataFailed(); void exportFontToFile(); - void exportFontToFileFailed(); + void exportFontToFileThroughData(); + void exportFontToFileThroughDataFailed(); + void exportFontToFileThroughDataNotWritable(); void exportGlyphCacheToSingleData(); + void exportGlyphCacheToData(); + void exportGlyphCacheToDataThroughSingleData(); + void exportGlyphCacheToDataThroughSingleDataFailed(); void exportGlyphCacheToFile(); - void exportGlyphCacheToFileFailed(); + void exportGlyphCacheToFileThroughData(); + void exportGlyphCacheToFileThroughDataFailed(); + void exportGlyphCacheToFileThroughDataNotWritable(); void importGlyphCacheFromSingleData(); + void importGlyphCacheFromData(); + void importGlyphCacheFromDataAsSingleData(); void importGlyphCacheFromFile(); + void importGlyphCacheFromFileAsSingleData(); + void importGlyphCacheFromFileAsSingleDataNotFound(); void debugFeature(); void debugFeatures(); @@ -63,15 +77,29 @@ AbstractFontConverterTest::AbstractFontConverterTest() { addTests({&AbstractFontConverterTest::convertGlyphs, &AbstractFontConverterTest::exportFontToSingleData, + &AbstractFontConverterTest::exportFontToData, + &AbstractFontConverterTest::exportFontToDataThroughSingleData, + &AbstractFontConverterTest::exportFontToDataThroughSingleDataFailed, &AbstractFontConverterTest::exportFontToFile, - &AbstractFontConverterTest::exportFontToFileFailed, + &AbstractFontConverterTest::exportFontToFileThroughData, + &AbstractFontConverterTest::exportFontToFileThroughDataFailed, + &AbstractFontConverterTest::exportFontToFileThroughDataNotWritable, &AbstractFontConverterTest::exportGlyphCacheToSingleData, + &AbstractFontConverterTest::exportGlyphCacheToData, + &AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleData, + &AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleDataFailed, &AbstractFontConverterTest::exportGlyphCacheToFile, - &AbstractFontConverterTest::exportGlyphCacheToFileFailed, + &AbstractFontConverterTest::exportGlyphCacheToFileThroughData, + &AbstractFontConverterTest::exportGlyphCacheToFileThroughDataFailed, + &AbstractFontConverterTest::exportGlyphCacheToFileThroughDataNotWritable, &AbstractFontConverterTest::importGlyphCacheFromSingleData, + &AbstractFontConverterTest::importGlyphCacheFromData, + &AbstractFontConverterTest::importGlyphCacheFromDataAsSingleData, &AbstractFontConverterTest::importGlyphCacheFromFile, + &AbstractFontConverterTest::importGlyphCacheFromFileAsSingleData, + &AbstractFontConverterTest::importGlyphCacheFromFileAsSingleDataNotFound, &AbstractFontConverterTest::debugFeature, &AbstractFontConverterTest::debugFeatures}); @@ -100,99 +128,263 @@ struct DummyGlyphCache: AbstractGlyphCache { } dummyGlyphCache{{}}; void AbstractFontConverterTest::convertGlyphs() { - class GlyphExporter: public AbstractFontConverter { - public: - /* GCC 4.8 apparently can't handle {} here */ - GlyphExporter(std::u32string& characters): _characters(characters) {} + std::u32string characters; + struct GlyphConverter: AbstractFontConverter { + /* GCC 4.8 apparently can't handle {} here */ + GlyphConverter(std::u32string& characters): _characters(characters) {} - private: - FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; } + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; + } - Containers::Array doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string& characters) const override { - _characters = characters; - return nullptr; - } + Containers::Array doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string& characters) const override { + _characters = characters; + return nullptr; + } - std::u32string& _characters; - }; + private: std::u32string& _characters; + } converter{characters}; - std::u32string characters; - GlyphExporter exporter(characters); - exporter.exportFontToSingleData(dummyFont, dummyGlyphCache, "abC01a0 "); + converter.exportFontToSingleData(dummyFont, dummyGlyphCache, "abC01a0 "); CORRADE_COMPARE(characters, U" 01Cab"); } void AbstractFontConverterTest::exportFontToSingleData() { - class SingleDataExporter: public Text::AbstractFontConverter { - private: - FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; } + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; + } + + Containers::Array doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string& characters) const override { + return Containers::array({'\xee', char(characters.size())}); + } + } converter; + + Containers::Array out = converter.exportFontToSingleData(dummyFont, dummyGlyphCache, "euhh"); + CORRADE_COMPARE_AS(out, Containers::arrayView({'\xee', '\x03'}), + TestSuite::Compare::Container); +} + +void AbstractFontConverterTest::exportFontToData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; + } + + std::vector>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string& filename, const std::u32string& characters) const override { + /* Wow what a shit API */ + std::vector>> out; + out.emplace_back(filename, Containers::array({char(characters.size())})); + out.emplace_back(filename + ".dat", Containers::array({'\xee'})); + return out; + } + } converter; - Containers::Array doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string&) const override { - Containers::Array data(1); - data[0] = '\xee'; - return data; - } - }; + auto ret = converter.exportFontToData(dummyFont, dummyGlyphCache, "font.out", "eH"); + CORRADE_COMPARE(ret.size(), 2); + + CORRADE_COMPARE(ret[0].first, "font.out"); + CORRADE_COMPARE_AS(ret[0].second, Containers::arrayView({'\x02'}), + TestSuite::Compare::Container); + + CORRADE_COMPARE(ret[1].first, "font.out.dat"); + CORRADE_COMPARE_AS(ret[1].second, Containers::arrayView({'\xee'}), + TestSuite::Compare::Container); +} + +void AbstractFontConverterTest::exportFontToDataThroughSingleData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; + } + + Containers::Array doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string& characters) const override { + return Containers::array({'\xee', char(characters.size())}); + } + } converter; /* doExportFontToData() should call doExportFontToSingleData() */ - SingleDataExporter exporter; - auto ret = exporter.exportFontToData(dummyFont, dummyGlyphCache, "font.out", {}); + auto ret = converter.exportFontToData(dummyFont, dummyGlyphCache, "font.out", "ehh"); CORRADE_COMPARE(ret.size(), 1); CORRADE_COMPARE(ret[0].first, "font.out"); - CORRADE_COMPARE(ret[0].second.size(), 1); - CORRADE_COMPARE(ret[0].second[0], '\xee'); + CORRADE_COMPARE_AS(ret[0].second, Containers::arrayView({'\xee', '\x02'}), + TestSuite::Compare::Container); +} + +void AbstractFontConverterTest::exportFontToDataThroughSingleDataFailed() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; + } + + Containers::Array doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string&) const override { + return {}; + } + } converter; + + auto ret = converter.exportFontToData(dummyFont, dummyGlyphCache, "font.out", "ehh"); + CORRADE_VERIFY(ret.empty()); } void AbstractFontConverterTest::exportFontToFile() { - class DataExporter: public Text::AbstractFontConverter { - private: - FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile; } - - std::vector>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string& filename, const std::u32string&) const override { - /* Why the hell GCC 4.9 fails to do proper move so I need to - work around that this ugly way?! */ - std::vector>> ret; - ret.emplace_back(filename, Containers::Array{Containers::InPlaceInit, {'\xf0'}}); - ret.emplace_back(filename + ".data", Containers::Array{Containers::InPlaceInit, {'\xfe', '\xed'}}); - return ret; - } - }; - - /* Remove previous files */ - Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out")); - Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out.data")); + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile; + } + + bool doExportFontToFile(AbstractFont&, AbstractGlyphCache&, const std::string& filename, const std::u32string& characters) const override { + return + Utility::Directory::write(filename, Containers::arrayView({'\xf0'})) && + Utility::Directory::write(filename + ".dat", Containers::arrayView({'\xfe', char(characters.size())})); + } + } converter; + + const std::string filename = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"); + const std::string filename2 = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out.dat"); + + /* Remove previous files, if any */ + Utility::Directory::rm(filename); + Utility::Directory::rm(filename2); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename2)); + + CORRADE_VERIFY(converter.exportFontToFile(dummyFont, dummyGlyphCache, filename, "eh")); + CORRADE_COMPARE_AS(filename, "\xf0", + TestSuite::Compare::FileToString); + CORRADE_COMPARE_AS(filename2, + "\xfe\x02", TestSuite::Compare::FileToString); +} + +void AbstractFontConverterTest::exportFontToFileThroughData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile; + } + + std::vector>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string& filename, const std::u32string& characters) const override { + std::vector>> ret; + ret.emplace_back(filename, Containers::array({'\xf0'})); + ret.emplace_back(filename + ".dat", Containers::array({'\xfe', char(characters.size())})); + return ret; + } + } converter; + + const std::string filename = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"); + const std::string filename2 = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out.dat"); + + /* Remove previous files, if any */ + Utility::Directory::rm(filename); + Utility::Directory::rm(filename2); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename2)); /* doExportToFile() should call doExportToData() */ - DataExporter exporter; - bool exported = exporter.exportFontToFile(dummyFont, dummyGlyphCache, Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"), {}); - CORRADE_VERIFY(exported); - CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"), - "\xf0", TestSuite::Compare::FileToString); - CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out.data"), - "\xfe\xed", TestSuite::Compare::FileToString); + CORRADE_VERIFY(converter.exportFontToFile(dummyFont, dummyGlyphCache, filename, "awoo")); + CORRADE_COMPARE_AS(filename, "\xf0", + TestSuite::Compare::FileToString); + CORRADE_COMPARE_AS(filename2, "\xfe\x03", + TestSuite::Compare::FileToString); } -void AbstractFontConverterTest::exportFontToFileFailed() { +void AbstractFontConverterTest::exportFontToFileThroughDataFailed() { struct: AbstractFontConverter { - FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile; } + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile; + } std::vector>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string&, const std::u32string&) const override { return {}; } - } exporter; + } converter; + + const std::string filename = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "font.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* Function should fail, no file should get written and no error output + should be printed (the base implementation assumes the plugin does it) */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.exportFontToFile(dummyFont, dummyGlyphCache, filename, {})); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_COMPARE(out.str(), ""); +} - CORRADE_VERIFY(!exporter.exportFontToFile(dummyFont, dummyGlyphCache, "nonexistent.dat", {})); +void AbstractFontConverterTest::exportFontToFileThroughDataNotWritable() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont|FontConverterFeature::MultiFile; + } + + std::vector>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string& filename, const std::u32string&) const override { + std::vector>> ret; + ret.emplace_back(filename, Containers::array({'\xf0'})); + return ret; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.exportFontToFile(dummyFont, dummyGlyphCache, "/some/path/that/does/not/exist", {})); + CORRADE_COMPARE(out.str(), + "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" + "Text::AbstractFontConverter::exportFontToFile(): cannot write to file /some/path/that/does/not/exist\n"); } void AbstractFontConverterTest::exportGlyphCacheToSingleData() { - struct: Text::AbstractFontConverter { + struct: AbstractFontConverter { FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache; } Containers::Array doExportGlyphCacheToSingleData(AbstractGlyphCache&) const override { - return Containers::Array{Containers::InPlaceInit, {'\xee'}}; + return Containers::array({'\xee'}); } - } exporter; + } converter; + + Containers::Array out = converter.exportGlyphCacheToSingleData(dummyGlyphCache); + CORRADE_COMPARE_AS(out, + (Containers::Array{Containers::InPlaceInit, {'\xee'}}), + TestSuite::Compare::Container); +} + +void AbstractFontConverterTest::exportGlyphCacheToData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache; + } + + std::vector>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string& filename) const override { + std::vector>> ret; + ret.emplace_back(filename, Containers::array({'\xf0'})); + ret.emplace_back(filename + ".dat", Containers::array({'\xfe', '\xed'})); + return ret; + } + } converter; + + auto ret = converter.exportGlyphCacheToData(dummyGlyphCache, "cache.out"); + CORRADE_COMPARE(ret.size(), 2); + + CORRADE_COMPARE(ret[0].first, "cache.out"); + CORRADE_COMPARE_AS(ret[0].second, Containers::arrayView({'\xf0'}), + TestSuite::Compare::Container); + + CORRADE_COMPARE(ret[1].first, "cache.out.dat"); + CORRADE_COMPARE_AS(ret[1].second, Containers::arrayView({'\xfe', '\xed'}), + TestSuite::Compare::Container); +} + +void AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache; + } + + Containers::Array doExportGlyphCacheToSingleData(AbstractGlyphCache&) const override { + return Containers::array({'\xee'}); + } + } converter; /* doExportGlyphCacheToData() should call doExportGlyphCacheToSingleData() */ - auto ret = exporter.exportGlyphCacheToData(dummyGlyphCache, "font.out"); + auto ret = converter.exportGlyphCacheToData(dummyGlyphCache, "font.out"); CORRADE_COMPARE(ret.size(), 1); CORRADE_COMPARE(ret[0].first, "font.out"); CORRADE_COMPARE_AS(ret[0].second, @@ -200,72 +392,235 @@ void AbstractFontConverterTest::exportGlyphCacheToSingleData() { TestSuite::Compare::Container); } +void AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleDataFailed() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache; + } + + Containers::Array doExportGlyphCacheToSingleData(AbstractGlyphCache&) const override { + return {}; + } + } converter; + + auto ret = converter.exportGlyphCacheToData(dummyGlyphCache, "font.out"); + CORRADE_VERIFY(ret.empty()); +} + void AbstractFontConverterTest::exportGlyphCacheToFile() { - class DataExporter: public Text::AbstractFontConverter { - private: - FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache|FontConverterFeature::MultiFile; } - - std::vector>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string& filename) const override { - /* Why the hell GCC 4.9 fails to do proper move so I need to - work around that this ugly way?! */ - std::vector>> ret; - ret.emplace_back(filename, Containers::Array{Containers::InPlaceInit, {'\xf0'}}); - ret.emplace_back(filename + ".data", Containers::Array{Containers::InPlaceInit, {'\xfe', '\xed'}}); - return ret; - } - }; - - /* Remove previous files */ - Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out")); - Utility::Directory::rm(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out.data")); + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache|FontConverterFeature::MultiFile; + } + + bool doExportGlyphCacheToFile(AbstractGlyphCache&, const std::string& filename) const override { + return + Utility::Directory::write(filename, Containers::arrayView({'\xf0'})) && + Utility::Directory::write(filename + ".dat", Containers::arrayView({'\xfe', '\xed'})); + } + } converter; + + const std::string filename = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "cache.out"); + const std::string filename2 = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "cache.out.dat"); + + /* Remove previous files, if any */ + Utility::Directory::rm(filename); + Utility::Directory::rm(filename2); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename2)); + + CORRADE_VERIFY(converter.exportGlyphCacheToFile(dummyGlyphCache, filename)); + CORRADE_COMPARE_AS(filename, "\xf0", + TestSuite::Compare::FileToString); + CORRADE_COMPARE_AS(filename2, + "\xfe\xed", TestSuite::Compare::FileToString); +} + +void AbstractFontConverterTest::exportGlyphCacheToFileThroughData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache|FontConverterFeature::MultiFile; + } + + std::vector>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string& filename) const override { + std::vector>> ret; + ret.emplace_back(filename, Containers::Array{Containers::InPlaceInit, {'\xf0'}}); + ret.emplace_back(filename + ".dat", Containers::Array{Containers::InPlaceInit, {'\xfe', '\xed'}}); + return ret; + } + } converter; + + const std::string filename = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "cache.out"); + const std::string filename2 = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "cache.out.dat"); + + /* Remove previous files, if any */ + Utility::Directory::rm(filename); + Utility::Directory::rm(filename2); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename2)); /* doExportGlyphCacheToFile() should call doExportGlyphCacheToData() */ - DataExporter exporter; - bool exported = exporter.exportGlyphCacheToFile(dummyGlyphCache, Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out")); - CORRADE_VERIFY(exported); - CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out"), - "\xf0", TestSuite::Compare::FileToString); - CORRADE_COMPARE_AS(Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "glyphcache.out.data"), - "\xfe\xed", TestSuite::Compare::FileToString); + CORRADE_VERIFY(converter.exportGlyphCacheToFile(dummyGlyphCache, filename)); + CORRADE_COMPARE_AS(filename, "\xf0", + TestSuite::Compare::FileToString); + CORRADE_COMPARE_AS(filename2, + "\xfe\xed", TestSuite::Compare::FileToString); } -void AbstractFontConverterTest::exportGlyphCacheToFileFailed() { - struct: Text::AbstractFontConverter { +void AbstractFontConverterTest::exportGlyphCacheToFileThroughDataFailed() { + struct: AbstractFontConverter { FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache|FontConverterFeature::MultiFile; } std::vector>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string&) const override { return {}; } - } exporter; + } converter; - /* doExportGlyphCacheToFile() should call doExportGlyphCacheToData() */ - CORRADE_VERIFY(!exporter.exportGlyphCacheToFile(dummyGlyphCache, "nonexistent.dat")); + const std::string filename = Utility::Directory::join(TEXT_TEST_OUTPUT_DIR, "cache.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* Function should fail, no file should get written and no error output + should be printed (the base implementation assumes the plugin does it) */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.exportGlyphCacheToFile(dummyGlyphCache, filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_COMPARE(out.str(), ""); } -class SingleGlyphCacheDataImporter: public Text::AbstractFontConverter { - private: - FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ImportGlyphCache; } +void AbstractFontConverterTest::exportGlyphCacheToFileThroughDataNotWritable() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache|FontConverterFeature::MultiFile; } + + std::vector>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string& filename) const override { + std::vector>> ret; + ret.emplace_back(filename, Containers::array({'\xf0'})); + return ret; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.exportGlyphCacheToFile(dummyGlyphCache, "/some/path/that/does/not/exist")); + CORRADE_COMPARE(out.str(), + "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" + "Text::AbstractFontConverter::exportGlyphCacheToFile(): cannot write to file /some/path/that/does/not/exist\n"); +} + +void AbstractFontConverterTest::importGlyphCacheFromSingleData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ImportGlyphCache; + } Containers::Pointer doImportGlyphCacheFromSingleData(const Containers::ArrayView data) const override { if(data.size() == 1 && data[0] == '\xa5') return Containers::pointer(new DummyGlyphCache{{123, 345}}); return nullptr; } -}; + } converter; + + const char data[] = {'\xa5'}; + Containers::Pointer cache = converter.importGlyphCacheFromSingleData(data); + CORRADE_VERIFY(cache); + CORRADE_COMPARE(cache->textureSize(), (Vector2i{123, 345})); +} + +void AbstractFontConverterTest::importGlyphCacheFromData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ImportGlyphCache; + } + + Containers::Pointer doImportGlyphCacheFromData(const std::vector>>& data) const override { + if(data.size() == 2 && data[1].second.size() == 1 && data[1].second[0] == '\xa5') + return Containers::pointer(new DummyGlyphCache{{123, 345}}); + return nullptr; + } + } converter; + + const char data[] = {'\xa5'}; + Containers::Pointer cache = converter.importGlyphCacheFromData({{}, {{}, data}}); + CORRADE_VERIFY(cache); + CORRADE_COMPARE(cache->textureSize(), (Vector2i{123, 345})); +} + +void AbstractFontConverterTest::importGlyphCacheFromDataAsSingleData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ImportGlyphCache; + } + + Containers::Pointer doImportGlyphCacheFromSingleData(const Containers::ArrayView data) const override { + if(data.size() == 1 && data[0] == '\xa5') + return Containers::pointer(new DummyGlyphCache{{123, 345}}); + return nullptr; + } + } converter; -void AbstractFontConverterTest::importGlyphCacheFromSingleData() { - /* doImportFromData() should call doImportFromSingleData() */ - SingleGlyphCacheDataImporter importer; const char data[] = {'\xa5'}; - Containers::Pointer cache = importer.importGlyphCacheFromData({{{}, data}}); + Containers::Pointer cache = converter.importGlyphCacheFromData({{{}, data}}); + CORRADE_VERIFY(cache); CORRADE_COMPARE(cache->textureSize(), (Vector2i{123, 345})); } void AbstractFontConverterTest::importGlyphCacheFromFile() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ImportGlyphCache; + } + + Containers::Pointer doImportGlyphCacheFromFile(const std::string& filename) const override { + Containers::Array data = Utility::Directory::read(filename); + if(data.size() == 1 && data[0] == '\xa5') + return Containers::pointer(new DummyGlyphCache{{123, 345}}); + return nullptr; + } + } converter; + + Containers::Pointer cache = converter.importGlyphCacheFromFile(Utility::Directory::join(TEXT_TEST_DIR, "data.bin")); + CORRADE_VERIFY(cache); + CORRADE_COMPARE(cache->textureSize(), (Vector2i{123, 345})); +} + +void AbstractFontConverterTest::importGlyphCacheFromFileAsSingleData() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ImportGlyphCache; + } + + Containers::Pointer doImportGlyphCacheFromSingleData(const Containers::ArrayView data) const override { + if(data.size() == 1 && data[0] == '\xa5') + return Containers::pointer(new DummyGlyphCache{{123, 345}}); + return nullptr; + } + } converter; + /* doImportFromFile() should call doImportFromSingleData() */ - SingleGlyphCacheDataImporter importer; - Containers::Pointer cache = importer.importGlyphCacheFromFile(Utility::Directory::join(TEXT_TEST_DIR, "data.bin")); + Containers::Pointer cache = converter.importGlyphCacheFromFile(Utility::Directory::join(TEXT_TEST_DIR, "data.bin")); + CORRADE_VERIFY(cache); CORRADE_COMPARE(cache->textureSize(), (Vector2i{123, 345})); } +void AbstractFontConverterTest::importGlyphCacheFromFileAsSingleDataNotFound() { + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ImportGlyphCache; + } + + Containers::Pointer doImportGlyphCacheFromSingleData(const Containers::ArrayView) const override { + CORRADE_VERIFY(!"this shouldn't get reached"); + return {}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.importGlyphCacheFromFile("nonexistent.bin")); + CORRADE_COMPARE(out.str(), "Text::AbstractFontConverter::importGlyphCacheFromFile(): cannot open file nonexistent.bin\n"); +} + void AbstractFontConverterTest::debugFeature() { std::ostringstream out;