diff --git a/doc/changelog.dox b/doc/changelog.dox index c8481ef81..cc2eaebb5 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -809,6 +809,9 @@ See also: missing before, and @ref Text::Alignment::TopCenterIntegral, which is also needed in order to prevent aligning pixel-perfect fonts to fractional positions. +- Added a @ref Text::GlyphCache::GlyphCache(NoCreateT) and + @ref Text::DistanceFieldGlyphCache::DistanceFieldGlyphCache(NoCreateT) + constructor allowing to construct the object without a GL context present @subsubsection changelog-latest-changes-texturetools TextureTools library diff --git a/src/Magnum/Text/AbstractGlyphCache.cpp b/src/Magnum/Text/AbstractGlyphCache.cpp index e41f32fb6..d6c71d15f 100644 --- a/src/Magnum/Text/AbstractGlyphCache.cpp +++ b/src/Magnum/Text/AbstractGlyphCache.cpp @@ -144,6 +144,8 @@ AbstractGlyphCache::AbstractGlyphCache(const Vector2i& size, const Vector2i& pad AbstractGlyphCache::AbstractGlyphCache(const Vector2i& size): AbstractGlyphCache{PixelFormat::R8Unorm, size, {}} {} #endif +AbstractGlyphCache::AbstractGlyphCache(NoCreateT) noexcept {} + AbstractGlyphCache::AbstractGlyphCache(AbstractGlyphCache&&) noexcept = default; AbstractGlyphCache::~AbstractGlyphCache() = default; diff --git a/src/Magnum/Text/AbstractGlyphCache.h b/src/Magnum/Text/AbstractGlyphCache.h index fad6fda06..b04fcc0c2 100644 --- a/src/Magnum/Text/AbstractGlyphCache.h +++ b/src/Magnum/Text/AbstractGlyphCache.h @@ -317,6 +317,20 @@ class MAGNUM_TEXT_EXPORT AbstractGlyphCache { #endif #endif + /** + * @brief Construct without creating the internal state + * @m_since_latest + * + * The constructed instance is equivalent to moved-from state, i.e. no + * APIs can be safely called on the object. Useful in cases where you + * will overwrite the instance later anyway. Move another object over + * it to make it useful. + * + * Note that this is a low-level and a potentially dangerous API, see + * the documentation of @ref NoCreate for alternatives. + */ + explicit AbstractGlyphCache(NoCreateT) noexcept; + /** @brief Copying is not allowed */ AbstractGlyphCache(const AbstractGlyphCache&) = delete; diff --git a/src/Magnum/Text/DistanceFieldGlyphCache.cpp b/src/Magnum/Text/DistanceFieldGlyphCache.cpp index 02d0fa516..9819232ea 100644 --- a/src/Magnum/Text/DistanceFieldGlyphCache.cpp +++ b/src/Magnum/Text/DistanceFieldGlyphCache.cpp @@ -69,6 +69,8 @@ DistanceFieldGlyphCache::DistanceFieldGlyphCache(const Vector2i& sourceSize, con #endif } +DistanceFieldGlyphCache::DistanceFieldGlyphCache(NoCreateT) noexcept: GlyphCache{NoCreate}, _distanceField{NoCreate} {} + GlyphCacheFeatures DistanceFieldGlyphCache::doFeatures() const { return GlyphCacheFeature::ImageProcessing #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Text/DistanceFieldGlyphCache.h b/src/Magnum/Text/DistanceFieldGlyphCache.h index 9c39291ad..be98165d2 100644 --- a/src/Magnum/Text/DistanceFieldGlyphCache.h +++ b/src/Magnum/Text/DistanceFieldGlyphCache.h @@ -100,6 +100,22 @@ class MAGNUM_TEXT_EXPORT DistanceFieldGlyphCache: public GlyphCache { */ explicit DistanceFieldGlyphCache(const Vector2i& sourceSize, const Vector2i& size, UnsignedInt radius); + /** + * @brief Construct without creating the internal state and the OpenGL texture object + * @m_since_latest + * + * The constructed instance is equivalent to moved-from state, i.e. no + * APIs can be safely called on the object. Useful in cases where you + * will overwrite the instance later anyway. Move another object over + * it to make it useful. + * + * This function can be safely used for constructing (and later + * destructing) objects even without any OpenGL context being active. + * However note that this is a low-level and a potentially dangerous + * API, see the documentation of @ref NoCreate for alternatives. + */ + explicit DistanceFieldGlyphCache(NoCreateT) noexcept; + /** * @brief Distance field texture size * diff --git a/src/Magnum/Text/GlyphCache.cpp b/src/Magnum/Text/GlyphCache.cpp index 22ad1ee51..b9bbb00d9 100644 --- a/src/Magnum/Text/GlyphCache.cpp +++ b/src/Magnum/Text/GlyphCache.cpp @@ -63,6 +63,8 @@ GlyphCache::GlyphCache(const Vector2i& originalSize, const Vector2i& size, const #endif } +GlyphCache::GlyphCache(NoCreateT) noexcept: AbstractGlyphCache{NoCreate}, _texture{NoCreate} {} + GlyphCacheFeatures GlyphCache::doFeatures() const { return {}; } void GlyphCache::doSetImage(const Vector2i& offset, const ImageView2D& image) { diff --git a/src/Magnum/Text/GlyphCache.h b/src/Magnum/Text/GlyphCache.h index 9b0f8cf8f..44ac251d2 100644 --- a/src/Magnum/Text/GlyphCache.h +++ b/src/Magnum/Text/GlyphCache.h @@ -107,6 +107,22 @@ class MAGNUM_TEXT_EXPORT GlyphCache: public AbstractGlyphCache { */ explicit GlyphCache(const Vector2i& size, const Vector2i& padding = {}); + /** + * @brief Construct without creating the internal state and the OpenGL texture object + * @m_since_latest + * + * The constructed instance is equivalent to moved-from state, i.e. no + * APIs can be safely called on the object. Useful in cases where you + * will overwrite the instance later anyway. Move another object over + * it to make it useful. + * + * This function can be safely used for constructing (and later + * destructing) objects even without any OpenGL context being active. + * However note that this is a low-level and a potentially dangerous + * API, see the documentation of @ref NoCreate for alternatives. + */ + explicit GlyphCache(NoCreateT) noexcept; + /** @brief Cache texture */ GL::Texture2D& texture() { return _texture; } diff --git a/src/Magnum/Text/Test/AbstractGlyphCacheTest.cpp b/src/Magnum/Text/Test/AbstractGlyphCacheTest.cpp index 3986bc5dd..acabfa023 100644 --- a/src/Magnum/Text/Test/AbstractGlyphCacheTest.cpp +++ b/src/Magnum/Text/Test/AbstractGlyphCacheTest.cpp @@ -66,6 +66,7 @@ struct AbstractGlyphCacheTest: TestSuite::Tester { #endif void constructImageRowPadding(); void constructZeroSize(); + void constructNoCreate(); void constructCopy(); void constructMove(); @@ -162,6 +163,7 @@ AbstractGlyphCacheTest::AbstractGlyphCacheTest() { #endif &AbstractGlyphCacheTest::constructImageRowPadding, &AbstractGlyphCacheTest::constructZeroSize, + &AbstractGlyphCacheTest::constructNoCreate, &AbstractGlyphCacheTest::constructCopy, &AbstractGlyphCacheTest::constructMove, @@ -446,6 +448,16 @@ void AbstractGlyphCacheTest::constructZeroSize() { "Text::AbstractGlyphCache: expected non-zero size, got {0, 2, 1}\n"); } +void AbstractGlyphCacheTest::constructNoCreate() { + DummyGlyphCache cache{NoCreate}; + + /* Shouldn't crash */ + CORRADE_VERIFY(true); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::value); +} + void AbstractGlyphCacheTest::constructCopy() { CORRADE_VERIFY(!std::is_copy_constructible{}); CORRADE_VERIFY(!std::is_copy_assignable{}); diff --git a/src/Magnum/Text/Test/CMakeLists.txt b/src/Magnum/Text/Test/CMakeLists.txt index 94983e43e..c3c98b6ad 100644 --- a/src/Magnum/Text/Test/CMakeLists.txt +++ b/src/Magnum/Text/Test/CMakeLists.txt @@ -83,40 +83,45 @@ corrade_add_test(TextFeatureTest FeatureTest.cpp LIBRARIES MagnumTextTestLib) corrade_add_test(TextRendererTest RendererTest.cpp LIBRARIES MagnumTextTestLib) corrade_add_test(TextScriptTest ScriptTest.cpp LIBRARIES MagnumTextTestLib) -if(MAGNUM_TARGET_GL AND MAGNUM_BUILD_GL_TESTS) - corrade_add_test(TextDistanceFieldGlyphCacheGLTest DistanceFieldGlyphCacheGLTest.cpp - LIBRARIES - MagnumTextTestLib - MagnumOpenGLTester - MagnumDebugTools - FILES - ${PROJECT_SOURCE_DIR}/src/Magnum/TextureTools/Test/DistanceFieldGLTestFiles/input.tga - ${PROJECT_SOURCE_DIR}/src/Magnum/TextureTools/Test/DistanceFieldGLTestFiles/output.tga) - target_include_directories(TextDistanceFieldGlyphCacheGLTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/$) - if(MAGNUM_BUILD_PLUGINS_STATIC) - if(MAGNUM_WITH_ANYIMAGEIMPORTER) - target_link_libraries(TextDistanceFieldGlyphCacheGLTest PRIVATE AnyImageImporter) - endif() - if(MAGNUM_WITH_TGAIMPORTER) - target_link_libraries(TextDistanceFieldGlyphCacheGLTest PRIVATE TgaImporter) - endif() - else() - # So the plugins get properly built when building the test - if(MAGNUM_WITH_ANYIMAGEIMPORTER) - add_dependencies(TextDistanceFieldGlyphCacheGLTest AnyImageImporter) - endif() - if(MAGNUM_WITH_TGAIMPORTER) - add_dependencies(TextDistanceFieldGlyphCacheGLTest TgaImporter) +if(MAGNUM_TARGET_GL) + corrade_add_test(TextGlyphCacheTest GlyphCacheTest.cpp LIBRARIES MagnumText) + corrade_add_test(TextDistanceFieldGlyphCacheTest DistanceFieldGlyphCacheTest.cpp LIBRARIES MagnumText) + + if(MAGNUM_BUILD_GL_TESTS) + corrade_add_test(TextDistanceFieldGlyphCacheGLTest DistanceFieldGlyphCacheGLTest.cpp + LIBRARIES + MagnumTextTestLib + MagnumOpenGLTester + MagnumDebugTools + FILES + ${PROJECT_SOURCE_DIR}/src/Magnum/TextureTools/Test/DistanceFieldGLTestFiles/input.tga + ${PROJECT_SOURCE_DIR}/src/Magnum/TextureTools/Test/DistanceFieldGLTestFiles/output.tga) + target_include_directories(TextDistanceFieldGlyphCacheGLTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/$) + if(MAGNUM_BUILD_PLUGINS_STATIC) + if(MAGNUM_WITH_ANYIMAGEIMPORTER) + target_link_libraries(TextDistanceFieldGlyphCacheGLTest PRIVATE AnyImageImporter) + endif() + if(MAGNUM_WITH_TGAIMPORTER) + target_link_libraries(TextDistanceFieldGlyphCacheGLTest PRIVATE TgaImporter) + endif() + else() + # So the plugins get properly built when building the test + if(MAGNUM_WITH_ANYIMAGEIMPORTER) + add_dependencies(TextDistanceFieldGlyphCacheGLTest AnyImageImporter) + endif() + if(MAGNUM_WITH_TGAIMPORTER) + add_dependencies(TextDistanceFieldGlyphCacheGLTest TgaImporter) + endif() endif() - endif() - corrade_add_test(TextGlyphCacheGLTest GlyphCacheGLTest.cpp - LIBRARIES - MagnumText - MagnumOpenGLTester - MagnumDebugTools) - corrade_add_test(TextRendererGLTest RendererGLTest.cpp - LIBRARIES - MagnumTextTestLib - MagnumOpenGLTester) + corrade_add_test(TextGlyphCacheGLTest GlyphCacheGLTest.cpp + LIBRARIES + MagnumText + MagnumOpenGLTester + MagnumDebugTools) + corrade_add_test(TextRendererGLTest RendererGLTest.cpp + LIBRARIES + MagnumTextTestLib + MagnumOpenGLTester) + endif() endif() diff --git a/src/Magnum/Text/Test/DistanceFieldGlyphCacheTest.cpp b/src/Magnum/Text/Test/DistanceFieldGlyphCacheTest.cpp new file mode 100644 index 000000000..6950398c0 --- /dev/null +++ b/src/Magnum/Text/Test/DistanceFieldGlyphCacheTest.cpp @@ -0,0 +1,54 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022, 2023 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 "Magnum/Text/DistanceFieldGlyphCache.h" + +namespace Magnum { namespace Text { namespace Test { namespace { + +struct DistanceFieldGlyphCacheTest: TestSuite::Tester { + explicit DistanceFieldGlyphCacheTest(); + + void constructNoCreate(); +}; + +DistanceFieldGlyphCacheTest::DistanceFieldGlyphCacheTest() { + addTests({&DistanceFieldGlyphCacheTest::constructNoCreate}); +} + +void DistanceFieldGlyphCacheTest::constructNoCreate() { + DistanceFieldGlyphCache cache{NoCreate}; + + /* Shouldn't crash or try to acces GL */ + CORRADE_VERIFY(true); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::value); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Text::Test::DistanceFieldGlyphCacheTest) diff --git a/src/Magnum/Text/Test/GlyphCacheTest.cpp b/src/Magnum/Text/Test/GlyphCacheTest.cpp new file mode 100644 index 000000000..1ad75ecd4 --- /dev/null +++ b/src/Magnum/Text/Test/GlyphCacheTest.cpp @@ -0,0 +1,54 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022, 2023 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 "Magnum/Text/GlyphCache.h" + +namespace Magnum { namespace Text { namespace Test { namespace { + +struct GlyphCacheTest: TestSuite::Tester { + explicit GlyphCacheTest(); + + void constructNoCreate(); +}; + +GlyphCacheTest::GlyphCacheTest() { + addTests({&GlyphCacheTest::constructNoCreate}); +} + +void GlyphCacheTest::constructNoCreate() { + GlyphCache cache{NoCreate}; + + /* Shouldn't crash or try to acces GL */ + CORRADE_VERIFY(true); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::value); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Text::Test::GlyphCacheTest)