diff --git a/src/Magnum/Text/AbstractFontConverter.cpp b/src/Magnum/Text/AbstractFontConverter.cpp index 1f9f78aa3..5819a43f5 100644 --- a/src/Magnum/Text/AbstractFontConverter.cpp +++ b/src/Magnum/Text/AbstractFontConverter.cpp @@ -104,7 +104,14 @@ std::vector>> AbstractFontConvert CORRADE_ASSERT(features() >= (FontConverterFeature::ExportFont|FontConverterFeature::ConvertData), "Text::AbstractFontConverter::exportFontToData(): feature not supported", {}); - return doExportFontToData(font, cache, filename, uniqueUnicode(characters)); + std::vector>> out = doExportFontToData(font, cache, filename, uniqueUnicode(characters)); + #ifndef CORRADE_NO_ASSERT + for(const auto& i: out) + CORRADE_ASSERT(!i.second.deleter(), + "Text::AbstractFontConverter::exportFontToData(): implementation is not allowed to use a custom Array deleter", {}); + #endif + + return out; } std::vector>> AbstractFontConverter::doExportFontToData(AbstractFont& font, AbstractGlyphCache& cache, const std::string& filename, const std::u32string& characters) const { @@ -123,7 +130,10 @@ Containers::Array AbstractFontConverter::exportFontToSingleData(AbstractFo CORRADE_ASSERT(!(features() & FontConverterFeature::MultiFile), "Text::AbstractFontConverter::exportFontToSingleData(): the format is not single-file", nullptr); - return doExportFontToSingleData(font, cache, uniqueUnicode(characters)); + Containers::Array out = doExportFontToSingleData(font, cache, uniqueUnicode(characters)); + CORRADE_ASSERT(!out.deleter(), + "Text::AbstractFontConverter::exportFontToSingleData(): implementation is not allowed to use a custom Array deleter", {}); + return out; } Containers::Array AbstractFontConverter::doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string&) const { @@ -157,7 +167,14 @@ std::vector>> AbstractFontConvert CORRADE_ASSERT(features() >= (FontConverterFeature::ExportGlyphCache|FontConverterFeature::ConvertData), "Text::AbstractFontConverter::exportGlyphCacheToData(): feature not supported", {}); - return doExportGlyphCacheToData(cache, filename); + std::vector>> out = doExportGlyphCacheToData(cache, filename); + #ifndef CORRADE_NO_ASSERT + for(const auto& i: out) + CORRADE_ASSERT(!i.second.deleter(), + "Text::AbstractFontConverter::exportGlyphCacheToData(): implementation is not allowed to use a custom Array deleter", {}); + #endif + + return out; } std::vector>> AbstractFontConverter::doExportGlyphCacheToData(AbstractGlyphCache& cache, const std::string& filename) const { @@ -176,7 +193,10 @@ Containers::Array AbstractFontConverter::exportGlyphCacheToSingleData(Abst CORRADE_ASSERT(!(features() & FontConverterFeature::MultiFile), "Text::AbstractFontConverter::exportGlyphCacheToSingleData(): the format is not single-file", nullptr); - return doExportGlyphCacheToSingleData(cache); + Containers::Array out = doExportGlyphCacheToSingleData(cache); + CORRADE_ASSERT(!out.deleter(), + "Text::AbstractFontConverter::exportGlyphCacheToSingleData(): implementation is not allowed to use a custom Array deleter", {}); + return out; } Containers::Array AbstractFontConverter::doExportGlyphCacheToSingleData(AbstractGlyphCache&) const { diff --git a/src/Magnum/Text/Test/AbstractFontConverterTest.cpp b/src/Magnum/Text/Test/AbstractFontConverterTest.cpp index ca80ca065..10ec5b46e 100644 --- a/src/Magnum/Text/Test/AbstractFontConverterTest.cpp +++ b/src/Magnum/Text/Test/AbstractFontConverterTest.cpp @@ -51,9 +51,11 @@ struct AbstractFontConverterTest: TestSuite::Tester { void exportFontToSingleData(); void exportFontToSingleDataNotImplemented(); + void exportFontToSingleDataCustomDeleter(); void exportFontToSingleDataNotSingleFile(); void exportFontToData(); void exportFontToDataNotImplemented(); + void exportFontToDataCustomDeleter(); void exportFontToDataThroughSingleData(); void exportFontToDataThroughSingleDataFailed(); void exportFontToFile(); @@ -64,9 +66,11 @@ struct AbstractFontConverterTest: TestSuite::Tester { void exportGlyphCacheToSingleData(); void exportGlyphCacheToSingleDataNotImplemented(); + void exportGlyphCacheToSingleDataCustomDeleter(); void exportGlyphCacheToSingleDataNotSingleFile(); void exportGlyphCacheToData(); void exportGlyphCacheToDataNotImplemented(); + void exportGlyphCacheToDataCustomDeleter(); void exportGlyphCacheToDataThroughSingleData(); void exportGlyphCacheToDataThroughSingleDataFailed(); void exportGlyphCacheToFile(); @@ -100,9 +104,11 @@ AbstractFontConverterTest::AbstractFontConverterTest() { &AbstractFontConverterTest::exportFontToSingleData, &AbstractFontConverterTest::exportFontToSingleDataNotImplemented, + &AbstractFontConverterTest::exportFontToSingleDataCustomDeleter, &AbstractFontConverterTest::exportFontToSingleDataNotSingleFile, &AbstractFontConverterTest::exportFontToData, &AbstractFontConverterTest::exportFontToDataNotImplemented, + &AbstractFontConverterTest::exportFontToDataCustomDeleter, &AbstractFontConverterTest::exportFontToDataThroughSingleData, &AbstractFontConverterTest::exportFontToDataThroughSingleDataFailed, &AbstractFontConverterTest::exportFontToFile, @@ -113,9 +119,11 @@ AbstractFontConverterTest::AbstractFontConverterTest() { &AbstractFontConverterTest::exportGlyphCacheToSingleData, &AbstractFontConverterTest::exportGlyphCacheToSingleDataNotImplemented, + &AbstractFontConverterTest::exportGlyphCacheToSingleDataCustomDeleter, &AbstractFontConverterTest::exportGlyphCacheToSingleDataNotSingleFile, &AbstractFontConverterTest::exportGlyphCacheToData, &AbstractFontConverterTest::exportGlyphCacheToDataNotImplemented, + &AbstractFontConverterTest::exportGlyphCacheToDataCustomDeleter, &AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleData, &AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleDataFailed, &AbstractFontConverterTest::exportGlyphCacheToFile, @@ -248,6 +256,25 @@ void AbstractFontConverterTest::exportFontToSingleDataNotImplemented() { CORRADE_COMPARE(out.str(), "Text::AbstractFontConverter::exportFontToSingleData(): feature advertised but not implemented\n"); } +void AbstractFontConverterTest::exportFontToSingleDataCustomDeleter() { + CORRADE_SKIP_IF_NO_ASSERT(); + + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; + } + + Containers::Array doExportFontToSingleData(AbstractFont&, AbstractGlyphCache&, const std::u32string&) const override { + return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.exportFontToSingleData(dummyFont, dummyGlyphCache, {}); + CORRADE_COMPARE(out.str(), "Text::AbstractFontConverter::exportFontToSingleData(): implementation is not allowed to use a custom Array deleter\n"); +} + void AbstractFontConverterTest::exportFontToSingleDataNotSingleFile() { CORRADE_SKIP_IF_NO_ASSERT(); @@ -307,6 +334,28 @@ void AbstractFontConverterTest::exportFontToDataNotImplemented() { CORRADE_COMPARE(out.str(), "Text::AbstractFontConverter::exportFontToData(): feature advertised but not implemented\n"); } +void AbstractFontConverterTest::exportFontToDataCustomDeleter() { + CORRADE_SKIP_IF_NO_ASSERT(); + + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportFont; + } + std::vector>> doExportFontToData(AbstractFont&, AbstractGlyphCache&, const std::string&, const std::u32string&) const override { + /* First is alright, second not */ + std::vector>> out; + out.emplace_back("", nullptr); + out.emplace_back("", Containers::Array{nullptr, 0, [](char*, std::size_t) {}}); + return out; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.exportFontToData(dummyFont, dummyGlyphCache, "font.out", {}); + CORRADE_COMPARE(out.str(), "Text::AbstractFontConverter::exportFontToData(): implementation is not allowed to use a custom Array deleter\n"); +} + void AbstractFontConverterTest::exportFontToDataThroughSingleData() { struct: AbstractFontConverter { FontConverterFeatures doFeatures() const override { @@ -493,6 +542,25 @@ void AbstractFontConverterTest::exportGlyphCacheToSingleDataNotImplemented() { CORRADE_COMPARE(out.str(), "Text::AbstractFontConverter::exportGlyphCacheToSingleData(): feature advertised but not implemented\n"); } +void AbstractFontConverterTest::exportGlyphCacheToSingleDataCustomDeleter() { + CORRADE_SKIP_IF_NO_ASSERT(); + + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache; + } + + Containers::Array doExportGlyphCacheToSingleData(AbstractGlyphCache&) const override { + return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.exportGlyphCacheToSingleData(dummyGlyphCache); + CORRADE_COMPARE(out.str(), "Text::AbstractFontConverter::exportGlyphCacheToSingleData(): implementation is not allowed to use a custom Array deleter\n"); +} + void AbstractFontConverterTest::exportGlyphCacheToSingleDataNotSingleFile() { CORRADE_SKIP_IF_NO_ASSERT(); @@ -551,6 +619,28 @@ void AbstractFontConverterTest::exportGlyphCacheToDataNotImplemented() { CORRADE_COMPARE(out.str(), "Text::AbstractFontConverter::exportGlyphCacheToData(): feature advertised but not implemented\n"); } +void AbstractFontConverterTest::exportGlyphCacheToDataCustomDeleter() { + CORRADE_SKIP_IF_NO_ASSERT(); + + struct: AbstractFontConverter { + FontConverterFeatures doFeatures() const override { + return FontConverterFeature::ConvertData|FontConverterFeature::ExportGlyphCache; + } + std::vector>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string&) const override { + /* First is alright, second not */ + std::vector>> out; + out.emplace_back("", nullptr); + out.emplace_back("", Containers::Array{nullptr, 0, [](char*, std::size_t) {}}); + return out; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.exportGlyphCacheToData(dummyGlyphCache, "cache.out"); + CORRADE_COMPARE(out.str(), "Text::AbstractFontConverter::exportGlyphCacheToData(): implementation is not allowed to use a custom Array deleter\n"); +} + void AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleData() { struct: AbstractFontConverter { FontConverterFeatures doFeatures() const override {