Browse Source

Text: add AbstractFont::openMemory().

Basically the same logic as with Trade::AbstractImporter::openMemory(),
the doOpenData() signature is (yet again) changed to accept a pair of a
r-value Array reference and a DataFlags describing whether the memory is
owned or not. Compared to Trade, I don't anticipate any in-place
mutation of open fonts, so there's no DataFlags::Mutable.

There's also no DataFlags::Global because data of the opened font aren't
exposed further anywhere (so far at least, but I can imagine SVG data
eventually possibly passed through to importers, which then could be a
use case for this flag).

This is the final breaking change to the AbstractFont doOpenData() API.
Adapting of all other code to these changes will be done in a subsequent
commit, so right now a non-deprecated build still fails.
pull/482/merge
Vladimír Vondruš 1 week ago
parent
commit
2401a2243d
  1. 30
      doc/snippets/Text.cpp
  2. 59
      src/Magnum/Text/AbstractFont.cpp
  3. 132
      src/Magnum/Text/AbstractFont.h
  4. 152
      src/Magnum/Text/Test/AbstractFontTest.cpp

30
doc/snippets/Text.cpp

@ -216,6 +216,36 @@ font->setFileCallback([](const std::string& filename,
/* [AbstractFont-setFileCallback-template] */ /* [AbstractFont-setFileCallback-template] */
} }
{
struct: Text::AbstractFont {
Text::FontFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return false; }
void doClose() override {}
Properties doProperties() override { return {}; }
void doGlyphIdsInto(const Containers::StridedArrayView1D<const char32_t>&, const Containers::StridedArrayView1D<UnsignedInt>&) override {}
Vector2 doGlyphSize(UnsignedInt) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<Text::AbstractShaper> doCreateShaper() override { return {}; }
Containers::Array<char> _in;
/* [AbstractFont-doOpenData-ownership] */
void doOpenData(Containers::Array<char>&& data, Text::DataFlags dataFlags,
Float size, UnsignedInt fontId) override
{
/* Take over the existing array or copy the data if we can't */
if(dataFlags & (Text::DataFlag::Owned|Text::DataFlag::ExternallyOwned))
_in = std::move(data);
else
_in = Containers::Array<char>{InPlaceInit, data};
DOXYGEN_ELLIPSIS(static_cast<void>(size); static_cast<void>(fontId);)
}
/* [AbstractFont-doOpenData-ownership] */
} font;
}
{ {
/* -Wnonnull in GCC 11+ "helpfully" says "this is null" if I don't initialize /* -Wnonnull in GCC 11+ "helpfully" says "this is null" if I don't initialize
the font pointer. I don't care, I just want you to check compilation errors, the font pointer. I don't care, I just want you to check compilation errors,

59
src/Magnum/Text/AbstractFont.cpp

@ -94,6 +94,28 @@ Debug& operator<<(Debug& debug, const FontFeatures value) {
}); });
} }
Debug& operator<<(Debug& debug, const DataFlag value) {
debug << "Text::DataFlag" << Debug::nospace;
switch(value) {
/* LCOV_EXCL_START */
#define _c(v) case DataFlag::v: return debug << "::" #v;
_c(Owned)
_c(ExternallyOwned)
#undef _c
/* LCOV_EXCL_STOP */
}
return debug << "(" << Debug::nospace << Debug::hex << UnsignedByte(value) << Debug::nospace << ")";
}
Debug& operator<<(Debug& debug, const DataFlags value) {
return Containers::enumSetDebugOutput(debug, value, "Text::DataFlags{}", {
DataFlag::Owned,
DataFlag::ExternallyOwned
});
}
Containers::StringView AbstractFont::pluginInterface() { Containers::StringView AbstractFont::pluginInterface() {
return MAGNUM_TEXT_ABSTRACTFONT_PLUGIN_INTERFACE ""_s; return MAGNUM_TEXT_ABSTRACTFONT_PLUGIN_INTERFACE ""_s;
} }
@ -181,7 +203,7 @@ bool AbstractFont::openData(const Containers::ArrayView<const void> data, const
the check doesn't be done on the plugin side) because for some file the check doesn't be done on the plugin side) because for some file
formats it could be valid (MagnumFont in particular). */ formats it could be valid (MagnumFont in particular). */
close(); close();
doOpenData(Containers::arrayCast<const char>(data), size, fontId); doOpenData(Containers::Array<char>{const_cast<char*>(static_cast<const char*>(data.data())), data.size(), [](char*, std::size_t) {}}, {}, size, fontId);
/* If opening succeeded, cache reported font properties. If not, the values /* If opening succeeded, cache reported font properties. If not, the values
were reset to default-constructed values by close(). (OTOH, on were reset to default-constructed values by close(). (OTOH, on
@ -203,7 +225,7 @@ bool AbstractFont::openData(const Containers::ArrayView<const void> data, const
return false; return false;
} }
void AbstractFont::doOpenData(const Containers::ArrayView<const char> data, const Float size, const UnsignedInt fontId) { void AbstractFont::doOpenData(Containers::Array<char>&& data, DataFlags, const Float size, const UnsignedInt fontId) {
#ifndef MAGNUM_BUILD_DEPRECATED #ifndef MAGNUM_BUILD_DEPRECATED
CORRADE_ASSERT_UNREACHABLE("Text::AbstractFont::openData(): feature advertised but not implemented", ); CORRADE_ASSERT_UNREACHABLE("Text::AbstractFont::openData(): feature advertised but not implemented", );
static_cast<void>(data); static_cast<void>(data);
@ -238,6 +260,31 @@ auto AbstractFont::doOpenData(Containers::ArrayView<const char>, Float) -> Prope
} }
#endif #endif
bool AbstractFont::openMemory(Containers::ArrayView<const void> memory, const Float size, const UnsignedInt fontId) {
CORRADE_ASSERT(features() & FontFeature::OpenData,
"Text::AbstractFont::openData(): feature not supported", false);
/* We accept empty data here (instead of checking for them and failing so
the check doesn't be done on the plugin side) because for some file
formats it could be valid (MagnumFont in particular). */
close();
doOpenData(Containers::Array<char>{const_cast<char*>(static_cast<const char*>(memory.data())), memory.size(), [](char*, std::size_t) {}}, DataFlag::ExternallyOwned, size, fontId);
/* If opening succeeded, cache reported font properties. Same logic as in
openData() */
if(isOpened()) {
const Properties properties = doProperties();
_size = properties.size;
_ascent = properties.ascent;
_descent = properties.descent;
_lineHeight = properties.lineHeight;
_glyphCount = properties.glyphCount;
return true;
}
return false;
}
Containers::Optional<UnsignedInt> AbstractFont::fileFontCount(const Containers::StringView filename) { Containers::Optional<UnsignedInt> AbstractFont::fileFontCount(const Containers::StringView filename) {
/* The logic here is mirroring what's in openFile(), just with delegating /* The logic here is mirroring what's in openFile(), just with delegating
to different APIs. Comments are kept whole, just referring to different to different APIs. Comments are kept whole, just referring to different
@ -368,7 +415,7 @@ bool AbstractFont::openFile(const Containers::StringView filename, const Float s
return isOpened(); return isOpened();
} }
doOpenData(*data, size, fontId); doOpenData(Containers::Array<char>{const_cast<char*>(data->data()), data->size(), [](char*, std::size_t) {}}, {}, size, fontId);
_fileCallback(filename, InputFileCallbackPolicy::Close, _fileCallbackUserData); _fileCallback(filename, InputFileCallbackPolicy::Close, _fileCallbackUserData);
/* Shouldn't get here, the assert is fired already in setFileCallback() */ /* Shouldn't get here, the assert is fired already in setFileCallback() */
@ -420,18 +467,18 @@ void AbstractFont::doOpenFile(const Containers::StringView filename, const Float
return; return;
} }
doOpenData(*data, size, fontId); doOpenData(Containers::Array<char>{const_cast<char*>(data->data()), data->size(), [](char*, std::size_t) {}}, {}, size, fontId);
_fileCallback(filename, InputFileCallbackPolicy::Close, _fileCallbackUserData); _fileCallback(filename, InputFileCallbackPolicy::Close, _fileCallbackUserData);
/* Otherwise open the file directly */ /* Otherwise open the file directly */
} else { } else {
const Containers::Optional<Containers::Array<char>> data = Utility::Path::read(filename); Containers::Optional<Containers::Array<char>> data = Utility::Path::read(filename);
if(!data) { if(!data) {
Error() << "Text::AbstractFont::openFile(): cannot open file" << filename; Error() << "Text::AbstractFont::openFile(): cannot open file" << filename;
return; return;
} }
doOpenData(*data, size, fontId); doOpenData(*Utility::move(data), DataFlag::Owned, size, fontId);
} }
} }

132
src/Magnum/Text/AbstractFont.h

@ -28,7 +28,7 @@
*/ */
/** @file /** @file
* @brief Class @ref Magnum::Text::AbstractFont, enum @ref Magnum::Text::FontFeature, enum set @ref Magnum::Text::FontFeatures * @brief Class @ref Magnum::Text::AbstractFont, enum @ref Magnum::Text::FontFeature, @ref Magnum::Text::DataFlag, enum set @ref Magnum::Text::FontFeatures, @ref Magnum::Text::DataFlags
*/ */
#include <initializer_list> #include <initializer_list>
@ -103,6 +103,55 @@ MAGNUM_TEXT_EXPORT Debug& operator<<(Debug& debug, FontFeature value);
/** @debugoperatorenum{FontFeatures} */ /** @debugoperatorenum{FontFeatures} */
MAGNUM_TEXT_EXPORT Debug& operator<<(Debug& debug, FontFeatures value); MAGNUM_TEXT_EXPORT Debug& operator<<(Debug& debug, FontFeatures value);
/**
@brief Data flag
@m_since_latest
@see @ref DataFlags, @ref AbstractFont::doOpenData(), @ref Trade::DataFlag
*/
enum class DataFlag: UnsignedByte {
/**
* Data is owned by the instance, meaning it stays in scope for as long as
* the instance. If neither @ref DataFlag::Owned nor
* @ref DataFlag::ExternallyOwned is set, the data is considered to be just
* a temporary allocation and no assumptions about its lifetime can be
* made.
*/
Owned = 1 << 0,
/**
* Data has an owner external to the instance, for example a memory-mapped
* file or a constant memory. In general the data lifetime exceeds lifetime
* of the instance wrapping it. If neither @ref DataFlag::Owned nor
* @ref DataFlag::ExternallyOwned is set, the data is considered to be just
* a temporary allocation and no assumptions about its lifetime can be
* made.
*/
ExternallyOwned = 1 << 1
};
/**
@debugoperatorenum{DataFlag}
@m_since_latest
*/
MAGNUM_TEXT_EXPORT Debug& operator<<(Debug& debug, DataFlag value);
/**
@brief Data flags
@m_since_latest
@see @ref AbstractFont::doOpenData(), @ref Trade::DataFlag
*/
typedef Containers::EnumSet<DataFlag> DataFlags;
CORRADE_ENUMSET_OPERATORS(DataFlags)
/**
@debugoperatorenum{DataFlags}
@m_since_latest
*/
MAGNUM_TEXT_EXPORT Debug& operator<<(Debug& debug, DataFlags value);
/** /**
@brief Base for font plugins @brief Base for font plugins
@ -189,10 +238,10 @@ all glyphs in the font:
@section Text-AbstractFont-usage-callbacks Loading data from memory, using file callbacks @section Text-AbstractFont-usage-callbacks Loading data from memory, using file callbacks
Besides loading data directly from the filesystem using @ref openFile() like Besides loading data directly from the filesystem using @ref openFile() like
shown above, it's possible to use @ref openData() to load fonts from memory shown above, it's possible to use @ref openData() / @ref openMemory() to load
(for example from @relativeref{Corrade,Utility::Resource}). Note that the fonts from memory (for example from @relativeref{Corrade,Utility::Resource}).
particular font implementation has to support @ref FontFeature::OpenData for Note that the particular font implementation has to support
this method to work: @ref FontFeature::OpenData for this method to work:
@snippet Text.cpp AbstractFont-usage-data @snippet Text.cpp AbstractFont-usage-data
@ -461,10 +510,14 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
* @param size Size to open the font in, in points * @param size Size to open the font in, in points
* @param fontId Font index * @param fontId Font index
* *
* Closes previous file, if it was opened, and tries to open given * Closes previous file, if it was opened, and tries to open given raw
* raw data. Available only if @ref FontFeature::OpenData is supported. * data. Available only if @ref FontFeature::OpenData is supported. On
* On failure prints a message to @relativeref{Magnum,Error} and * failure prints a message to @relativeref{Magnum,Error} and returns
* returns @cpp false @ce. * @cpp false @ce.
*
* The @p data is not expected to be alive after the function exits.
* Using @ref openMemory() instead as can avoid unnecessary copies in
* exchange for stricter requirements on @p data lifetime.
* *
* The function will fail if @p fontId is larger than the count of * The function will fail if @p fontId is larger than the count of
* fonts in given file. The total font count can be queried using * fonts in given file. The total font count can be queried using
@ -477,6 +530,35 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
*/ */
bool openData(Containers::ArrayView<const void> data, Float size, UnsignedInt fontId = 0); bool openData(Containers::ArrayView<const void> data, Float size, UnsignedInt fontId = 0);
/**
* @brief Open a non-temporary memory
* @param memory Resident memory containing font data
* @param size Size to open the font in, in points
* @param fontId Font index
* @m_since_latest
*
* Closes previous file, if it was opened, and tries to open given raw
* data. Available only if @ref FontFeature::OpenData is supported. On
* failure prints a message to @relativeref{Magnum,Error} and returns
* @cpp false @ce.
*
* Unlike @ref openData(), this function expects @p memory to stay in
* scope until the font is destructed, @ref close() is called or
* another file is opened. This allows the implementation to directly
* operate on the provided memory, without having to allocate a local
* copy to extend its lifetime.
*
* The function will fail if @p fontId is larger than the count of
* fonts in given file. The total font count can be queried using
* @ref dataFontCount(), but as font rasterization libraries commonly
* require picking a concrete font index in order to open a file at
* all and don't allow changing it afterwards, it's faster to directly
* attempt to open a concrete index without checking it against
* @ref dataFontCount() first, and handle a potential failure.
* @see @ref features(), @ref openFile()
*/
bool openMemory(Containers::ArrayView<const void> memory, Float size, UnsignedInt fontId = 0);
/** /**
* @brief Open a file * @brief Open a file
* @param filename Font file * @param filename Font file
@ -864,18 +946,44 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
virtual Containers::Optional<UnsignedInt> doDataFontCount(Containers::ArrayView<const char> data); virtual Containers::Optional<UnsignedInt> doDataFontCount(Containers::ArrayView<const char> data);
/** /**
* @brief Implementation for @ref openData() * @brief Implementation for @ref openData() and @ref openMemory()
* @m_since_latest * @m_since_latest
* *
* If the operation was successful, @ref doIsOpened() should return * If the operation was successful, @ref doIsOpened() should return
* @cpp true @ce after calling this function, @cpp false @ce otherwise. * @cpp true @ce after calling this function, @cpp false @ce otherwise.
*
* The @p data is mutable or owned depending on the value of
* @p dataFlags. This can be used for example to avoid allocating a
* local copy in order to preserve its lifetime. The following cases
* are possible:
*
* - If @p dataFlags is empty, @p data is a @cpp const @ce
* non-owning view. This happens when the function is called from
* @ref openData(). You have to assume the data go out of scope
* after the function exists, so if the font needs to access the
* data after, it has to allocate a local copy.
* - If @p dataFlags is @ref DataFlag::Owned, @p data is an owned
* (mutable) memory. This happens when the implementation is
* called from the default @ref doOpenFile() implementation --- it
* reads a file into a newly allocated array and passes it to this
* function. You can take ownership of the @p data instance
* instead of allocating a local copy.
* - If @p dataFlags is @ref DataFlag::ExternallyOwned, it can be
* assumed that @p data will stay in scope until @ref doClose() is
* called or the font is destructed. This happens when the
* function is called from @ref openMemory().
*
* Example workflow in a plugin that needs to preserve access to the
* input data but wants to avoid allocating a copy if possible:
*
* @snippet Text.cpp AbstractFont-doOpenData-ownership
*/ */
virtual void doOpenData(Containers::ArrayView<const char> data, Float size, UnsignedInt fontId); virtual void doOpenData(Containers::Array<char>&& data, DataFlags dataFlags, Float size, UnsignedInt fontId);
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @brief Implementation for @ref openData() * @brief Implementation for @ref openData()
* @m_deprecated_since_latest Implement @ref doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) * @m_deprecated_since_latest Implement @ref doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt)
* and @ref doProperties() instead. * and @ref doProperties() instead.
* *
* If @ref doIsOpened() returns @cpp true @ce after calling this * If @ref doIsOpened() returns @cpp true @ce after calling this

152
src/Magnum/Text/Test/AbstractFontTest.cpp

@ -26,7 +26,7 @@
*/ */
#include <string> /** @todo remove once file callbacks are std::string-free */ #include <string> /** @todo remove once file callbacks are std::string-free */
#include <Corrade/Containers/ArrayView.h> #include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Optional.h> #include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StridedArrayView.h> #include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Containers/String.h> #include <Corrade/Containers/String.h>
@ -60,6 +60,8 @@ struct AbstractFontTest: TestSuite::Tester {
void debugFeaturePacked(); void debugFeaturePacked();
void debugFeatures(); void debugFeatures();
void debugFeaturesPacked(); void debugFeaturesPacked();
void debugDataFlag();
void debugDataFlags();
void construct(); void construct();
@ -77,12 +79,14 @@ struct AbstractFontTest: TestSuite::Tester {
void fontCountInvalid(); void fontCountInvalid();
void dataFontCountNotSupported(); void dataFontCountNotSupported();
void openData(); void openDataMemory();
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
void openDataDeprecated(); void openDataDeprecated();
void openDataDeprecatedNonZeroFontId(); void openDataDeprecatedNonZeroFontId();
/* No deprecated variants of openMemory(), as the behavior is the same as
with openData() there */
#endif #endif
void openDataFailed(); void openDataMemoryFailed();
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
void openDataFailedDeprecated(); void openDataFailedDeprecated();
#endif #endif
@ -198,10 +202,26 @@ struct AbstractFontTest: TestSuite::Tester {
const struct { const struct {
const char* name; const char* name;
bool openMemory;
bool openedBefore; bool openedBefore;
DataFlags expectedFlags;
/** @todo remove this once the deprecated APIs are gone */ /** @todo remove this once the deprecated APIs are gone */
UnsignedInt fontId; UnsignedInt fontId;
} OpenDataFileData[]{ } OpenDataMemoryData[]{
{"open data", false, false, {}, 0},
{"open data, opened before", false, true, {}, 0},
{"open data, non-zero font ID", false, false, {}, 1},
{"open memory", true, false, DataFlag::ExternallyOwned, 0},
{"open memory, opened before", true, true, DataFlag::ExternallyOwned, 0},
{"open memory, non-zero font ID", true, false, DataFlag::ExternallyOwned, 1}
};
const struct {
const char* name;
bool openedBefore;
/** @todo remove this once the deprecated APIs are gone */
UnsignedInt fontId;
} OpenFileData[]{
{"", false, 0}, {"", false, 0},
{"opened before", true, 0}, {"opened before", true, 0},
{"non-zero font ID", false, 1} {"non-zero font ID", false, 1}
@ -242,6 +262,8 @@ AbstractFontTest::AbstractFontTest() {
&AbstractFontTest::debugFeaturePacked, &AbstractFontTest::debugFeaturePacked,
&AbstractFontTest::debugFeatures, &AbstractFontTest::debugFeatures,
&AbstractFontTest::debugFeaturesPacked, &AbstractFontTest::debugFeaturesPacked,
&AbstractFontTest::debugDataFlag,
&AbstractFontTest::debugDataFlags,
&AbstractFontTest::construct}); &AbstractFontTest::construct});
@ -266,23 +288,23 @@ AbstractFontTest::AbstractFontTest() {
&AbstractFontTest::fontCountInvalid, &AbstractFontTest::fontCountInvalid,
&AbstractFontTest::dataFontCountNotSupported}); &AbstractFontTest::dataFontCountNotSupported});
addInstancedTests({&AbstractFontTest::openData}, addInstancedTests({&AbstractFontTest::openDataMemory},
Containers::arraySize(OpenDataFileData)); Containers::arraySize(OpenDataMemoryData));
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
addTests({&AbstractFontTest::openDataDeprecated, addTests({&AbstractFontTest::openDataDeprecated,
&AbstractFontTest::openDataDeprecatedNonZeroFontId}); &AbstractFontTest::openDataDeprecatedNonZeroFontId});
#endif #endif
addInstancedTests({&AbstractFontTest::openDataFailed}, addInstancedTests({&AbstractFontTest::openDataMemoryFailed},
Containers::arraySize(OpenData)); Containers::arraySize(OpenDataMemoryData));
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
addTests({&AbstractFontTest::openDataFailedDeprecated}); addTests({&AbstractFontTest::openDataFailedDeprecated});
#endif #endif
addInstancedTests({&AbstractFontTest::openFile}, addInstancedTests({&AbstractFontTest::openFile},
Containers::arraySize(OpenDataFileData)); Containers::arraySize(OpenFileData));
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
addTests({&AbstractFontTest::openFileDeprecated, addTests({&AbstractFontTest::openFileDeprecated,
@ -452,6 +474,18 @@ void AbstractFontTest::debugFeaturesPacked() {
CORRADE_COMPARE(out, "OpenData|PreparedGlyphCache {} Text::FontFeature::FileCallback\n"); CORRADE_COMPARE(out, "OpenData|PreparedGlyphCache {} Text::FontFeature::FileCallback\n");
} }
void AbstractFontTest::debugDataFlag() {
Containers::String out;
Debug{&out} << DataFlag::ExternallyOwned << DataFlag(0xf0);
CORRADE_COMPARE(out, "Text::DataFlag::ExternallyOwned Text::DataFlag(0xf0)\n");
}
void AbstractFontTest::debugDataFlags() {
Containers::String out;
Debug{&out} << (DataFlag::Owned|DataFlag(0xa0)) << DataFlags{};
CORRADE_COMPARE(out, "Text::DataFlag::Owned|Text::DataFlag(0xa0) Text::DataFlags{}\n");
}
void AbstractFontTest::construct() { void AbstractFontTest::construct() {
struct: AbstractFont { struct: AbstractFont {
FontFeatures doFeatures() const override { return {}; } FontFeatures doFeatures() const override { return {}; }
@ -493,7 +527,7 @@ void AbstractFontTest::dataFontCount() {
return 37; return 37;
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -535,7 +569,7 @@ void AbstractFontTest::dataFontCountFailed() {
return {}; return {};
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -713,7 +747,7 @@ void AbstractFontTest::fileFontCountAsData() {
return 37; return 37;
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -754,7 +788,7 @@ void AbstractFontTest::fileFontCountAsDataNotFound() {
return {}; return {};
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -803,7 +837,7 @@ void AbstractFontTest::fileFontCountAsDataFailed() {
return {}; return {};
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -910,8 +944,8 @@ void AbstractFontTest::dataFontCountNotSupported() {
CORRADE_COMPARE(out, "Text::AbstractFont::dataFontCount(): feature not supported\n"); CORRADE_COMPARE(out, "Text::AbstractFont::dataFontCount(): feature not supported\n");
} }
void AbstractFontTest::openData() { void AbstractFontTest::openDataMemory() {
auto&& data = OpenDataFileData[testCaseInstanceId()]; auto&& data = OpenDataMemoryData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
struct: AbstractFont { struct: AbstractFont {
@ -922,11 +956,14 @@ void AbstractFontTest::openData() {
opened = false; opened = false;
} }
void doOpenData(Containers::ArrayView<const char> data, Float size, UnsignedInt fontId) override { void doOpenData(Containers::Array<char>&& data, DataFlags dataFlags, Float size, UnsignedInt fontId) override {
CORRADE_VERIFY(!opened); CORRADE_VERIFY(!opened);
CORRADE_COMPARE_AS(data, CORRADE_COMPARE_AS(data,
Containers::arrayView({'\xa5'}), Containers::arrayView({'\xa5'}),
TestSuite::Compare::Container); TestSuite::Compare::Container);
CORRADE_COMPARE(dataFlags, expectedFlags);
/* The array should have a custom no-op deleter */
CORRADE_VERIFY(data.deleter());
CORRADE_COMPARE(size, 13.0f); CORRADE_COMPARE(size, 13.0f);
CORRADE_COMPARE(fontId, expectedFontId); CORRADE_COMPARE(fontId, expectedFontId);
opened = true; opened = true;
@ -941,9 +978,11 @@ void AbstractFontTest::openData() {
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; } Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractShaper> doCreateShaper() override { return {}; } Containers::Pointer<AbstractShaper> doCreateShaper() override { return {}; }
DataFlags expectedFlags;
UnsignedInt expectedFontId; UnsignedInt expectedFontId;
bool opened; bool opened;
} font; } font;
font.expectedFlags = data.expectedFlags;
font.expectedFontId = data.fontId; font.expectedFontId = data.fontId;
font.opened = data.openedBefore; font.opened = data.openedBefore;
CORRADE_COMPARE(font.isOpened(), data.openedBefore); CORRADE_COMPARE(font.isOpened(), data.openedBefore);
@ -953,6 +992,9 @@ void AbstractFontTest::openData() {
doOpenData() overload */ doOpenData() overload */
/** @todo remove the instanced font ID once the deprecated APIs are gone, /** @todo remove the instanced font ID once the deprecated APIs are gone,
supply a constant instead */ supply a constant instead */
if(data.openMemory)
CORRADE_VERIFY(font.openMemory(a5, 13.0f, data.fontId));
else
CORRADE_VERIFY(font.openData(a5, 13.0f, data.fontId)); CORRADE_VERIFY(font.openData(a5, 13.0f, data.fontId));
CORRADE_VERIFY(font.isOpened()); CORRADE_VERIFY(font.isOpened());
CORRADE_COMPARE(font.size(), 31.0f); CORRADE_COMPARE(font.size(), 31.0f);
@ -1042,8 +1084,8 @@ void AbstractFontTest::openDataDeprecatedNonZeroFontId() {
} }
#endif #endif
void AbstractFontTest::openDataFailed() { void AbstractFontTest::openDataMemoryFailed() {
auto&& data = OpenData[testCaseInstanceId()]; auto&& data = OpenDataMemoryData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
struct: AbstractFont { struct: AbstractFont {
@ -1051,7 +1093,7 @@ void AbstractFontTest::openDataFailed() {
bool doIsOpened() const override { return false; } bool doIsOpened() const override { return false; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
called = true; called = true;
} }
@ -1074,6 +1116,9 @@ void AbstractFontTest::openDataFailed() {
overload for font 0 */ overload for font 0 */
/** @todo remove the instanced font ID once the deprecated APIs are gone, /** @todo remove the instanced font ID once the deprecated APIs are gone,
supply a constant instead */ supply a constant instead */
if(data.openMemory)
CORRADE_VERIFY(!font.openMemory(nullptr, 1.0f, data.fontId));
else
CORRADE_VERIFY(!font.openData(nullptr, 1.0f, data.fontId)); CORRADE_VERIFY(!font.openData(nullptr, 1.0f, data.fontId));
CORRADE_VERIFY(!font.isOpened()); CORRADE_VERIFY(!font.isOpened());
CORRADE_VERIFY(font.called); CORRADE_VERIFY(font.called);
@ -1114,7 +1159,7 @@ void AbstractFontTest::openDataFailedDeprecated() {
#endif #endif
void AbstractFontTest::openFile() { void AbstractFontTest::openFile() {
auto&& data = OpenDataFileData[testCaseInstanceId()]; auto&& data = OpenFileData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
struct: AbstractFont { struct: AbstractFont {
@ -1317,10 +1362,13 @@ void AbstractFontTest::openFileAsData() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char> data, Float size, UnsignedInt fontId) override { void doOpenData(Containers::Array<char>&& data, DataFlags dataFlags, Float size, UnsignedInt fontId) override {
CORRADE_COMPARE_AS(data, CORRADE_COMPARE_AS(data,
Containers::arrayView({'\xa5'}), Containers::arrayView({'\xa5'}),
TestSuite::Compare::Container); TestSuite::Compare::Container);
CORRADE_COMPARE(dataFlags, DataFlag::Owned);
/* I.e., we can take over the array, it's not just a view */
CORRADE_VERIFY(!data.deleter());
CORRADE_COMPARE(size, 13.0f); CORRADE_COMPARE(size, 13.0f);
CORRADE_COMPARE(fontId, expectedFontId); CORRADE_COMPARE(fontId, expectedFontId);
_opened = true; _opened = true;
@ -1365,7 +1413,7 @@ void AbstractFontTest::openFileAsDataNotFound() {
bool doIsOpened() const override { return false; } bool doIsOpened() const override { return false; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
CORRADE_FAIL("This should not be called"); CORRADE_FAIL("This should not be called");
} }
@ -1476,7 +1524,7 @@ void AbstractFontTest::openFileAsDataFailed() {
bool doIsOpened() const override { return false; } bool doIsOpened() const override { return false; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
called = true; called = true;
} }
@ -1663,7 +1711,7 @@ void AbstractFontTest::propertiesNotImplemented() {
void doOpenFile(Containers::StringView, Float, UnsignedInt) override { void doOpenFile(Containers::StringView, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -1902,7 +1950,7 @@ void AbstractFontTest::setFileCallbackOpenFileDirectly() {
_opened = true; _opened = true;
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
CORRADE_FAIL("This should not be called"); CORRADE_FAIL("This should not be called");
} }
@ -1964,7 +2012,7 @@ void AbstractFontTest::setFileCallbackOpenFileDirectlyDeprecated() {
return {size, 1.0f, 2.0f, 3.0f, 15}; return {size, 1.0f, 2.0f, 3.0f, 15};
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
CORRADE_FAIL("This should not be called"); CORRADE_FAIL("This should not be called");
} }
Properties doOpenData(Containers::ArrayView<const char>, Float) override { Properties doOpenData(Containers::ArrayView<const char>, Float) override {
@ -2077,7 +2125,7 @@ void AbstractFontTest::setFileCallbackOpenFileDirectlyFailed() {
openCalled = true; openCalled = true;
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
CORRADE_FAIL("This should not be called"); CORRADE_FAIL("This should not be called");
} }
@ -2132,7 +2180,7 @@ void AbstractFontTest::setFileCallbackOpenFileDirectlyFailedDeprecated() {
return {}; return {};
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
CORRADE_FAIL("This should not be called"); CORRADE_FAIL("This should not be called");
} }
Properties doOpenData(Containers::ArrayView<const char>, Float) override { Properties doOpenData(Containers::ArrayView<const char>, Float) override {
@ -2197,10 +2245,13 @@ void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementation() {
AbstractFont::doOpenFile(filename, size, fontId); AbstractFont::doOpenFile(filename, size, fontId);
} }
void doOpenData(Containers::ArrayView<const char> data, Float size, UnsignedInt fontId) override { void doOpenData(Containers::Array<char>&& data, DataFlags dataFlags, Float size, UnsignedInt fontId) override {
CORRADE_COMPARE_AS(data, CORRADE_COMPARE_AS(data,
Containers::arrayView({'\xb0'}), Containers::arrayView({'\xb0'}),
TestSuite::Compare::Container); TestSuite::Compare::Container);
CORRADE_COMPARE(dataFlags, DataFlags{});
/* The array should have a custom no-op deleter */
CORRADE_VERIFY(data.deleter());
CORRADE_COMPARE(size, 42.0f); CORRADE_COMPARE(size, 42.0f);
CORRADE_COMPARE(fontId, expectedFontId); CORRADE_COMPARE(fontId, expectedFontId);
_opened = true; _opened = true;
@ -2368,7 +2419,7 @@ void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementationNotFound(
AbstractFont::doOpenFile(filename, size, fontId); AbstractFont::doOpenFile(filename, size, fontId);
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
CORRADE_FAIL("This should not be called"); CORRADE_FAIL("This should not be called");
} }
@ -2439,7 +2490,7 @@ void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementationFailed()
AbstractFont::doOpenFile(filename, size, fontId); AbstractFont::doOpenFile(filename, size, fontId);
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
openDataCalled = true; openDataCalled = true;
} }
@ -2593,10 +2644,13 @@ void AbstractFontTest::setFileCallbackOpenFileAsData() {
CORRADE_FAIL("This should not be called"); CORRADE_FAIL("This should not be called");
} }
void doOpenData(Containers::ArrayView<const char> data, Float size, UnsignedInt fontId) override { void doOpenData(Containers::Array<char>&& data, DataFlags dataFlags, Float size, UnsignedInt fontId) override {
CORRADE_COMPARE_AS(data, CORRADE_COMPARE_AS(data,
Containers::arrayView({'\xb0'}), Containers::arrayView({'\xb0'}),
TestSuite::Compare::Container); TestSuite::Compare::Container);
CORRADE_COMPARE(dataFlags, DataFlags{});
/* The array should have a custom no-op deleter */
CORRADE_VERIFY(data.deleter());
CORRADE_COMPARE(size, 13.0f); CORRADE_COMPARE(size, 13.0f);
CORRADE_COMPARE(fontId, expectedFontId); CORRADE_COMPARE(fontId, expectedFontId);
_opened = true; _opened = true;
@ -2810,7 +2864,7 @@ void AbstractFontTest::setFileCallbackOpenFileAsDataNotFound() {
CORRADE_FAIL("This should not be called"); CORRADE_FAIL("This should not be called");
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
CORRADE_FAIL("This should not be called"); CORRADE_FAIL("This should not be called");
} }
@ -2873,7 +2927,7 @@ void AbstractFontTest::setFileCallbackOpenFileAsDataFailed() {
CORRADE_FAIL("This should not be called"); CORRADE_FAIL("This should not be called");
} }
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
openCalled = true; openCalled = true;
} }
@ -3000,7 +3054,7 @@ void AbstractFontTest::properties() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -3062,7 +3116,7 @@ void AbstractFontTest::glyphId() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -3156,7 +3210,7 @@ void AbstractFontTest::glyphIdOutOfRange() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -3197,7 +3251,7 @@ void AbstractFontTest::glyphName() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -3235,7 +3289,7 @@ void AbstractFontTest::glyphNameNotImplemented() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -3293,7 +3347,7 @@ void AbstractFontTest::glyphNameOutOfRange() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -3329,7 +3383,7 @@ void AbstractFontTest::glyphSizeAdvance() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -3382,7 +3436,7 @@ void AbstractFontTest::glyphSizeAdvanceOutOfRange() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -3424,7 +3478,7 @@ void AbstractFontTest::fillGlyphCache() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -3479,7 +3533,7 @@ void AbstractFontTest::fillGlyphCacheOutOfRange() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -3519,7 +3573,7 @@ void AbstractFontTest::fillGlyphCacheNotUnique() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -3555,7 +3609,7 @@ void AbstractFontTest::fillGlyphCacheFromString() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -3626,7 +3680,7 @@ void AbstractFontTest::fillGlyphCacheFailed() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }
@ -3704,7 +3758,7 @@ void AbstractFontTest::fillGlyphCacheNotImplemented() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override {} void doClose() override {}
void doOpenData(Containers::ArrayView<const char>, Float, UnsignedInt) override { void doOpenData(Containers::Array<char>&&, DataFlags, Float, UnsignedInt) override {
_opened = true; _opened = true;
} }

Loading…
Cancel
Save