From 9bc1b9b3b1411d05e71a3e834b27529d0f7885b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 21 Oct 2023 11:40:36 +0200 Subject: [PATCH] Text: separate glyph ID and offset/advance retrieval in AbstractShaper. In basically all cases it's two independent operations so forcing them to be done together doesn't really bring any potential efficiency advantages. On the other hand, splitting them allows allows the caller to better make use of available memory, as the new renderGlyphQuadsInto() allows the input and output arrays to be aliased. Bumping AbstractFont plugin interface versions as this is a breaking change. --- doc/snippets/MagnumText.cpp | 32 +++++---- src/Magnum/Text/AbstractFont.cpp | 8 ++- src/Magnum/Text/AbstractFont.h | 2 +- src/Magnum/Text/AbstractShaper.cpp | 17 +++-- src/Magnum/Text/AbstractShaper.h | 61 +++++++++++------ src/Magnum/Text/Direction.h | 16 ++--- src/Magnum/Text/Renderer.cpp | 8 ++- src/Magnum/Text/Test/AbstractFontTest.cpp | 10 ++- src/Magnum/Text/Test/AbstractShaperTest.cpp | 67 ++++++++++++------- src/Magnum/Text/Test/RendererGLTest.cpp | 7 +- src/Magnum/Text/Test/RendererTest.cpp | 13 +++- src/MagnumPlugins/MagnumFont/MagnumFont.cpp | 7 +- .../MagnumFont/Test/MagnumFontTest.cpp | 12 ++-- 13 files changed, 169 insertions(+), 91 deletions(-) diff --git a/doc/snippets/MagnumText.cpp b/doc/snippets/MagnumText.cpp index db6670024..1b0c28ac7 100644 --- a/doc/snippets/MagnumText.cpp +++ b/doc/snippets/MagnumText.cpp @@ -278,9 +278,11 @@ struct GlyphInfo { Vector2 advance; }; Containers::Array glyphs{NoInit, shaper->glyphCount()}; -shaper->glyphsInto(stridedArrayView(glyphs).slice(&GlyphInfo::id), - stridedArrayView(glyphs).slice(&GlyphInfo::offset), - stridedArrayView(glyphs).slice(&GlyphInfo::advance)); +shaper->glyphIdsInto( + stridedArrayView(glyphs).slice(&GlyphInfo::id)); +shaper->glyphOffsetsAdvancesInto( + stridedArrayView(glyphs).slice(&GlyphInfo::offset), + stridedArrayView(glyphs).slice(&GlyphInfo::advance)); /* [AbstractShaper-shape] */ } @@ -313,25 +315,31 @@ Containers::Array glyphs; shaper->shape("Hello, world!", 0, 7); Containers::StridedArrayView1D glyphs1 = arrayAppend(glyphs, NoInit, shaper->glyphCount()); -shaper->glyphsInto(glyphs1.slice(&GlyphInfo::id), - glyphs1.slice(&GlyphInfo::offset), - glyphs1.slice(&GlyphInfo::advance)); +shaper->glyphIdsInto( + glyphs1.slice(&GlyphInfo::id)); +shaper->glyphOffsetsAdvancesInto( + glyphs1.slice(&GlyphInfo::offset), + glyphs1.slice(&GlyphInfo::advance)); /* Append "world" shaped with a bold font */ boldShaper->shape("Hello, world!", 7, 12); Containers::StridedArrayView1D glyphs2 = arrayAppend(glyphs, NoInit, boldShaper->glyphCount()); -boldShaper->glyphsInto(glyphs2.slice(&GlyphInfo::id), - glyphs2.slice(&GlyphInfo::offset), - glyphs2.slice(&GlyphInfo::advance)); +shaper->glyphIdsInto( + glyphs2.slice(&GlyphInfo::id)); +shaper->glyphOffsetsAdvancesInto( + glyphs2.slice(&GlyphInfo::offset), + glyphs2.slice(&GlyphInfo::advance)); /* Finally shape "!" shaped with a regular font again */ shaper->shape("Hello, world!", 12, 13); Containers::StridedArrayView1D glyphs3 = arrayAppend(glyphs, NoInit, shaper->glyphCount()); -shaper->glyphsInto(glyphs3.slice(&GlyphInfo::id), - glyphs3.slice(&GlyphInfo::offset), - glyphs3.slice(&GlyphInfo::advance)); +shaper->glyphIdsInto( + glyphs3.slice(&GlyphInfo::id)); +shaper->glyphOffsetsAdvancesInto( + glyphs3.slice(&GlyphInfo::offset), + glyphs3.slice(&GlyphInfo::advance)); /* [AbstractShaper-shape-multiple] */ } diff --git a/src/Magnum/Text/AbstractFont.cpp b/src/Magnum/Text/AbstractFont.cpp index 39cf0b29e..e2916effc 100644 --- a/src/Magnum/Text/AbstractFont.cpp +++ b/src/Magnum/Text/AbstractFont.cpp @@ -346,9 +346,11 @@ Containers::Pointer AbstractFont::layout(const AbstractGlyphCa Vector2 advance; }; Containers::Array glyphs{NoInit, shaper->glyphCount()}; - shaper->glyphsInto(stridedArrayView(glyphs).slice(&Glyph::id), - stridedArrayView(glyphs).slice(&Glyph::offset), - stridedArrayView(glyphs).slice(&Glyph::advance)); + shaper->glyphIdsInto( + stridedArrayView(glyphs).slice(&Glyph::id)); + shaper->glyphOffsetsAdvancesInto( + stridedArrayView(glyphs).slice(&Glyph::offset), + stridedArrayView(glyphs).slice(&Glyph::advance)); /* Create the data to return from AbstractLayouter::renderGlyph(). Most of this used to be copypasted in various *Layouter::doRenderGlyph() diff --git a/src/Magnum/Text/AbstractFont.h b/src/Magnum/Text/AbstractFont.h index 1dd179da3..cc3e53e86 100644 --- a/src/Magnum/Text/AbstractFont.h +++ b/src/Magnum/Text/AbstractFont.h @@ -772,7 +772,7 @@ updated interface string. */ /* Silly indentation to make the string appear in pluginInterface() docs */ #define MAGNUM_TEXT_ABSTRACTFONT_PLUGIN_INTERFACE /* [interface] */ \ -"cz.mosra.magnum.Text.AbstractFont/0.3.4" +"cz.mosra.magnum.Text.AbstractFont/0.3.5" /* [interface] */ #ifndef DOXYGEN_GENERATING_OUTPUT diff --git a/src/Magnum/Text/AbstractShaper.cpp b/src/Magnum/Text/AbstractShaper.cpp index d08739987..9c11276a2 100644 --- a/src/Magnum/Text/AbstractShaper.cpp +++ b/src/Magnum/Text/AbstractShaper.cpp @@ -115,13 +115,22 @@ ShapeDirection AbstractShaper::doDirection() const { return ShapeDirection::Unspecified; } -void AbstractShaper::glyphsInto(const Containers::StridedArrayView1D& ids, const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const { - CORRADE_ASSERT(ids.size() == _glyphCount && offsets.size() == _glyphCount && advances.size() == _glyphCount, - "Text::AbstractShaper::glyphsInto(): expected the ids, offsets and advanced views to have a size of" << _glyphCount << "but got" << ids.size() << Debug::nospace << "," << offsets.size() << "and" << advances.size(), ); +void AbstractShaper::glyphIdsInto(const Containers::StridedArrayView1D& ids) const { + CORRADE_ASSERT(ids.size() == _glyphCount, + "Text::AbstractShaper::glyphIdsInto(): expected the ids view to have a size of" << _glyphCount << "but got" << ids.size(), ); /* Call into the implementation only if there's actually anything shaped, otherwise it might not yet have everything properly set up */ if(_glyphCount) - doGlyphsInto(ids, offsets, advances); + doGlyphIdsInto(ids); +} + +void AbstractShaper::glyphOffsetsAdvancesInto(const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const { + CORRADE_ASSERT(offsets.size() == _glyphCount && advances.size() == _glyphCount, + "Text::AbstractShaper::glyphOffsetsAdvancesInto(): expected the offsets and advanced views to have a size of" << _glyphCount << "but got" << offsets.size() << "and" << advances.size(), ); + /* Call into the implementation only if there's actually anything shaped, + otherwise it might not yet have everything properly set up */ + if(_glyphCount) + doGlyphOffsetsAdvancesInto(offsets, advances); } }} diff --git a/src/Magnum/Text/AbstractShaper.h b/src/Magnum/Text/AbstractShaper.h index e0e974b49..4f179fbe7 100644 --- a/src/Magnum/Text/AbstractShaper.h +++ b/src/Magnum/Text/AbstractShaper.h @@ -123,10 +123,11 @@ instance has to stay in scope for at least as long as the @ref AbstractShaper is alive. A text is shaped by calling @ref shape(), retrieving the shaped glyph count -with @ref glyphCount() and then getting the glyph data with @ref glyphsInto(). -Glyph IDs can be then queried in (or inserted into) an @ref AbstractGlyphCache, -and the rendered glyphs positioned at @p offsets with the cursor moving by -@p advances is what makes up the final shaped text. +with @ref glyphCount() and then getting the glyph data with @ref glyphIdsInto() +and @ref glyphOffsetsAdvancesInto(). Glyph IDs can be then queried in (or +inserted into) an @ref AbstractGlyphCache, and the rendered glyphs positioned +at @p offsets with the cursor moving by @p advances is what makes up the final +shaped text. @snippet MagnumText.cpp AbstractShaper-shape @@ -198,12 +199,12 @@ per-font, per-script or per-language instances. @section Text-AbstractShaper-subclassing Subclassing The @ref AbstractFont plugin is meant to create a local @ref AbstractShaper -subclass. It implements at least @ref doShape() and @ref doGlyphsInto(), and -potentially also (a subset of) @ref doSetScript(), @ref doScript(), -@ref doSetLanguage(),@ref doLanguage(), @ref doSetDirection() and -@ref doDirection(). The public API does most sanity checks on its own, see -documentation of particular `do*()` functions for more information about the -guarantees. +subclass. It implements at least @ref doShape(), @ref doGlyphIdsInto() and +@ref doGlyphOffsetsAdvancesInto(), and potentially also (a subset of) +@ref doSetScript(), @ref doScript(), @ref doSetLanguage(),@ref doLanguage(), +@ref doSetDirection() and @ref doDirection(). The public API does most sanity +checks on its own, see documentation of particular `do*()` functions for more +information about the guarantees. */ class MAGNUM_TEXT_EXPORT AbstractShaper { public: @@ -397,15 +398,24 @@ class MAGNUM_TEXT_EXPORT AbstractShaper { ShapeDirection direction() const; /** - * @brief Retrieve glyph information + * @brief Retrieve glyph IDs * @param[out] ids Where to put glyph IDs + * + * The @p ids view is expected to have a size of @ref glyphCount(). + * After calling this function, the @p ids are commonly looked up in or + * inserted into an @ref AbstractGlyphCache. Offsets and advances + * corresponding to the IDs can be retrieved with + * @ref glyphOffsetsAdvancesInto(). + */ + void glyphIdsInto(const Containers::StridedArrayView1D& ids) const; + + /** + * @brief Retrieve glyph offsets and advances * @param[out] offsets Where to put glyph offsets * @param[out] advances Where to put glyph advances * - * The @p ids, @p offsets and @p advances views are all expected to - * have a size of @ref glyphCount(). After calling this function, the - * @p ids are commonly looked up in or inserted into an - * @ref AbstractGlyphCache, @p offsets specify where to put the glyph + * The @p offsets and @p advances views are all expected to have a size + * of @ref glyphCount(). The @p offsets specify where to put the glyph * relative to current cursor (which is then further offset for the * particular glyph rectangle returned from the glyph cache) and * @p advances specify in which direction to move the cursor for the @@ -414,10 +424,11 @@ class MAGNUM_TEXT_EXPORT AbstractShaper { * @relativeref{ShapeDirection,RightToLeft} Y components of @p advances * are @cpp 0.0f @ce, for @relativeref{ShapeDirection,TopToBottom} or * @relativeref{ShapeDirection,BottomToTop} X components of @p advances - * are @cpp 0.0f @ce. + * are @cpp 0.0f @ce. Glyph IDs corresponding to the offsets and + * advances can be retrieved with @ref glyphIdsInto(). * @see @ref direction() */ - void glyphsInto(const Containers::StridedArrayView1D& ids, const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const; + void glyphOffsetsAdvancesInto(const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const; private: /** @@ -473,13 +484,21 @@ class MAGNUM_TEXT_EXPORT AbstractShaper { virtual ShapeDirection doDirection() const; /** - * @brief Implemenation for @ref glyphsInto() + * @brief Implemenation for @ref glyphIdsInto() + * + * The @p ids are guaranteed to have a size of @ref glyphCount(). + * Called only if @ref glyphCount() is not @cpp 0 @ce. + */ + virtual void doGlyphIdsInto(const Containers::StridedArrayView1D& ids) const = 0; + + /** + * @brief Implemenation for @ref glyphOffsetsAdvancesInto() * - * The @p ids, @p offsets and @p advances are guaranteed to have a size - * of @ref glyphCount(). Called only if @ref glyphCount() is not + * The @p offsets and @p advances are guaranteed to have a size of + * @ref glyphCount(). Called only if @ref glyphCount() is not * @cpp 0 @ce. */ - virtual void doGlyphsInto(const Containers::StridedArrayView1D& ids, const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const = 0; + virtual void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const = 0; Containers::Reference _font; UnsignedInt _glyphCount; diff --git a/src/Magnum/Text/Direction.h b/src/Magnum/Text/Direction.h index 24cc5333b..78f238a24 100644 --- a/src/Magnum/Text/Direction.h +++ b/src/Magnum/Text/Direction.h @@ -56,29 +56,29 @@ enum class ShapeDirection: UnsignedByte { /** * Left to right. When returned from @ref AbstractShaper::direction(), - * the @p advances filled by @ref AbstractShaper::glyphsInto() have their Y - * components @cpp 0.0f @ce. + * the @p advances filled by @ref AbstractShaper::glyphOffsetsAdvancesInto() + * have their Y components @cpp 0.0f @ce. */ LeftToRight = 1, /** * Right to left. When returned from @ref AbstractShaper::direction(), - * the @p advances filled by @ref AbstractShaper::glyphsInto() have their Y - * components @cpp 0.0f @ce. + * the @p advances filled by @ref AbstractShaper::glyphOffsetsAdvancesInto() + * have their Y components @cpp 0.0f @ce. */ RightToLeft, /** * Top to bottom. When returned from @ref AbstractShaper::direction(), - * the @p advances filled by @ref AbstractShaper::glyphsInto() have their X - * components @cpp 0.0f @ce. + * the @p advances filled by @ref AbstractShaper::glyphOffsetsAdvancesInto() + * have their X components @cpp 0.0f @ce. */ TopToBottom, /** * Bottom to top. When returned from @ref AbstractShaper::direction(), - * the @p advances filled by @ref AbstractShaper::glyphsInto() have their X - * components @cpp 0.0f @ce. + * the @p advances filled by @ref AbstractShaper::glyphOffsetsAdvancesInto() + * have their X components @cpp 0.0f @ce. */ BottomToTop }; diff --git a/src/Magnum/Text/Renderer.cpp b/src/Magnum/Text/Renderer.cpp index 391fcac8a..fbae60dc9 100644 --- a/src/Magnum/Text/Renderer.cpp +++ b/src/Magnum/Text/Renderer.cpp @@ -316,9 +316,11 @@ std::tuple, Range2D> renderVerticesInternal(AbstractFont& fo /* Shape the line, get the results */ shaper->shape(line); const Containers::StridedArrayView1D lineGlyphs = glyphs.prefix(shaper->glyphCount()); - shaper->glyphsInto(lineGlyphs.slice(&Glyph::id), - lineGlyphs.slice(&Glyph::offset), - lineGlyphs.slice(&Glyph::advance)); + shaper->glyphIdsInto( + lineGlyphs.slice(&Glyph::id)); + shaper->glyphOffsetsAdvancesInto( + lineGlyphs.slice(&Glyph::offset), + lineGlyphs.slice(&Glyph::advance)); /* Verify that we don't reallocate anything. The only problem might arise when the layouter decides to compose one character from more diff --git a/src/Magnum/Text/Test/AbstractFontTest.cpp b/src/Magnum/Text/Test/AbstractFontTest.cpp index 6cf7f219c..a01e216b7 100644 --- a/src/Magnum/Text/Test/AbstractFontTest.cpp +++ b/src/Magnum/Text/Test/AbstractFontTest.cpp @@ -1123,7 +1123,8 @@ void AbstractFontTest::createShaper() { return 37; } - void doGlyphsInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} + void doGlyphIdsInto(const Containers::StridedArrayView1D&) const override {} + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} }; struct MyFont: AbstractFont { @@ -1190,8 +1191,10 @@ void AbstractFontTest::layout() { return 3; } - void doGlyphsInto(const Containers::StridedArrayView1D& ids, const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const override { + void doGlyphIdsInto(const Containers::StridedArrayView1D& ids) const override { Utility::copy({3, 7, 3}, ids); + } + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const override { Utility::copy({{0.5f, 1.0f}, {1.0f, 0.5f}, {2.0f, 2.0f}}, offsets); @@ -1342,11 +1345,12 @@ void AbstractFontTest::layoutGlyphOutOfRange() { return 3; } - void doGlyphsInto(const Containers::StridedArrayView1D& ids, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override { + void doGlyphIdsInto(const Containers::StridedArrayView1D& ids) const override { /* Clear the IDs as otherwise it'd result in OOB calls into the glyph cache */ for(UnsignedInt& i: ids) i = 0; } + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} }; struct MyFont: AbstractFont { diff --git a/src/Magnum/Text/Test/AbstractShaperTest.cpp b/src/Magnum/Text/Test/AbstractShaperTest.cpp index f699c53f2..f2890e89d 100644 --- a/src/Magnum/Text/Test/AbstractShaperTest.cpp +++ b/src/Magnum/Text/Test/AbstractShaperTest.cpp @@ -182,7 +182,8 @@ struct DummyShaper: AbstractShaper { using AbstractShaper::AbstractShaper; UnsignedInt doShape(Containers::StringView, UnsignedInt, UnsignedInt, Containers::ArrayView) override { return {}; } - void doGlyphsInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} + void doGlyphIdsInto(const Containers::StridedArrayView1D&) const override {} + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} }; void AbstractShaperTest::construct() { @@ -229,7 +230,8 @@ void AbstractShaperTest::setScript() { } UnsignedInt doShape(Containers::StringView, UnsignedInt, UnsignedInt, Containers::ArrayView) override { return {}; } - void doGlyphsInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} + void doGlyphIdsInto(const Containers::StridedArrayView1D&) const override {} + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} bool called = false; } shaper{FakeFont}; @@ -254,7 +256,8 @@ void AbstractShaperTest::setLanguage() { } UnsignedInt doShape(Containers::StringView, UnsignedInt, UnsignedInt, Containers::ArrayView) override { return {}; } - void doGlyphsInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} + void doGlyphIdsInto(const Containers::StridedArrayView1D&) const override {} + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} bool called = false; } shaper{FakeFont}; @@ -278,8 +281,8 @@ void AbstractShaperTest::setDirection() { return true; } - UnsignedInt doShape(Containers::StringView, UnsignedInt, UnsignedInt, Containers::ArrayView) override { return {}; } - void doGlyphsInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} + UnsignedInt doShape(Containers::StringView, UnsignedInt, UnsignedInt, Containers::ArrayView) override { return {}; } void doGlyphIdsInto(const Containers::StridedArrayView1D&) const override {} + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} bool called = false; } shaper{FakeFont}; @@ -326,14 +329,17 @@ void AbstractShaperTest::shape() { return ShapeDirection::BottomToTop; } - void doGlyphsInto(const Containers::StridedArrayView1D& ids, const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const override { + void doGlyphIdsInto(const Containers::StridedArrayView1D& ids) const override { CORRADE_COMPARE(ids.size(), 24); CORRADE_COMPARE(ids[0], 1337); + ids[1] = 666; + } + + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const override { CORRADE_COMPARE(offsets.size(), 24); CORRADE_COMPARE(offsets[0], (Vector2{13.0f, 37.0f})); CORRADE_COMPARE(advances.size(), 24); CORRADE_COMPARE(advances[0], (Vector2{42.0f, 69.0f})); - ids[1] = 666; offsets[1] = {-4.0f, -5.0f}; advances[1] = {12.0f, 23.0f}; } @@ -366,7 +372,8 @@ void AbstractShaperTest::shape() { ids[0] = 1337; offsets[0] = {13.0f, 37.0f}; advances[0] = {42.0f, 69.0f}; - shaper.glyphsInto(ids, offsets, advances); + shaper.glyphIdsInto(ids); + shaper.glyphOffsetsAdvancesInto(offsets, advances); CORRADE_COMPARE(ids[1], 666); CORRADE_COMPARE(offsets[1], (Vector2{-4.0f, -5.0f})); CORRADE_COMPARE(advances[1], (Vector2{12.0f, 23.0f})); @@ -385,7 +392,8 @@ void AbstractShaperTest::shapeNoFeatures() { return 24; } - void doGlyphsInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} + void doGlyphIdsInto(const Containers::StridedArrayView1D&) const override {} + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} bool shapeCalled = false; } shaper{FakeFont}; @@ -419,7 +427,8 @@ void AbstractShaperTest::shapeNoBeginEnd() { return 24; } - void doGlyphsInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} + void doGlyphIdsInto(const Containers::StridedArrayView1D&) const override {} + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} bool shapeCalled = false; } shaper{FakeFont}; @@ -449,7 +458,8 @@ void AbstractShaperTest::shapeNoBeginEndFeatures() { return 24; } - void doGlyphsInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} + void doGlyphIdsInto(const Containers::StridedArrayView1D&) const override {} + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} bool shapeCalled = false; } shaper{FakeFont}; @@ -470,7 +480,8 @@ void AbstractShaperTest::shapeScriptLanguageDirectionNotImplemented() { return 24; } - void doGlyphsInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} + void doGlyphIdsInto(const Containers::StridedArrayView1D&) const override {} + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} } shaper{FakeFont}; /* Initially it won't call into any of the implementations */ @@ -507,7 +518,8 @@ void AbstractShaperTest::shapeZeroGlyphs() { return ShapeDirection::BottomToTop; } - void doGlyphsInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} + void doGlyphIdsInto(const Containers::StridedArrayView1D&) const override {} + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} } shaper{FakeFont}; CORRADE_COMPARE(shaper.shape("some text", 3, 8), 0); @@ -533,7 +545,8 @@ void AbstractShaperTest::shapeBeginEndOutOfRange() { return 5; } - void doGlyphsInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} + void doGlyphIdsInto(const Containers::StridedArrayView1D&) const override {} + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override {} } shaper{FakeFont}; /* Capture correct function name */ @@ -585,7 +598,10 @@ void AbstractShaperTest::glyphsIntoEmpty() { return 0; } - void doGlyphsInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override { + void doGlyphIdsInto(const Containers::StridedArrayView1D&) const override { + CORRADE_FAIL("This shouldn't be called"); + } + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override { CORRADE_FAIL("This shouldn't be called"); } } shaper{FakeFont}; @@ -594,7 +610,8 @@ void AbstractShaperTest::glyphsIntoEmpty() { CORRADE_VERIFY(true); /* This should not assert but also not call anywhere */ - shaper.glyphsInto(nullptr, nullptr, nullptr); + shaper.glyphIdsInto(nullptr); + shaper.glyphOffsetsAdvancesInto(nullptr, nullptr); } void AbstractShaperTest::glyphsIntoInvalidViewSizes() { @@ -607,14 +624,16 @@ void AbstractShaperTest::glyphsIntoInvalidViewSizes() { return 5; } - void doGlyphsInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override { + void doGlyphIdsInto(const Containers::StridedArrayView1D&) const override { + CORRADE_FAIL("This shouldn't be called"); + } + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D&, const Containers::StridedArrayView1D&) const override { CORRADE_FAIL("This shouldn't be called"); } } shaper{FakeFont}; CORRADE_COMPARE(shaper.shape("yey"), 5); - UnsignedInt ids[5]; UnsignedInt idsWrong[6]; Vector2 offsets[5]; Vector2 offsetsWrong[6]; @@ -623,13 +642,13 @@ void AbstractShaperTest::glyphsIntoInvalidViewSizes() { std::ostringstream out; Error redirectError{&out}; - shaper.glyphsInto(idsWrong, offsets, advances); - shaper.glyphsInto(ids, offsetsWrong, advances); - shaper.glyphsInto(ids, offsets, advancesWrong); + shaper.glyphIdsInto(idsWrong); + shaper.glyphOffsetsAdvancesInto(offsetsWrong, advances); + shaper.glyphOffsetsAdvancesInto(offsets, advancesWrong); CORRADE_COMPARE(out.str(), - "Text::AbstractShaper::glyphsInto(): expected the ids, offsets and advanced views to have a size of 5 but got 6, 5 and 5\n" - "Text::AbstractShaper::glyphsInto(): expected the ids, offsets and advanced views to have a size of 5 but got 5, 6 and 5\n" - "Text::AbstractShaper::glyphsInto(): expected the ids, offsets and advanced views to have a size of 5 but got 5, 5 and 6\n"); + "Text::AbstractShaper::glyphIdsInto(): expected the ids view to have a size of 5 but got 6\n" + "Text::AbstractShaper::glyphOffsetsAdvancesInto(): expected the offsets and advanced views to have a size of 5 but got 6 and 5\n" + "Text::AbstractShaper::glyphOffsetsAdvancesInto(): expected the offsets and advanced views to have a size of 5 but got 5 and 6\n"); } }}}} diff --git a/src/Magnum/Text/Test/RendererGLTest.cpp b/src/Magnum/Text/Test/RendererGLTest.cpp index f9342cae8..9b416c626 100644 --- a/src/Magnum/Text/Test/RendererGLTest.cpp +++ b/src/Magnum/Text/Test/RendererGLTest.cpp @@ -61,7 +61,7 @@ struct TestShaper: AbstractShaper { return text.size(); } - void doGlyphsInto(const Containers::StridedArrayView1D& ids, const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const override { + void doGlyphIdsInto(const Containers::StridedArrayView1D& ids) const override { for(UnsignedInt i = 0; i != ids.size(); ++i) { /* It just rotates between the three glyphs */ if(i % 3 == 0) @@ -70,7 +70,10 @@ struct TestShaper: AbstractShaper { ids[i] = 7; else ids[i] = 9; - + } + } + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const override { + for(UnsignedInt i = 0; i != offsets.size(); ++i) { /* Offset Y and advance X is getting larger with every glyph, advance Y is flipping its sign with every glyph */ offsets[i] = Vector2::yAxis(i + 1); diff --git a/src/Magnum/Text/Test/RendererTest.cpp b/src/Magnum/Text/Test/RendererTest.cpp index 7f992e06c..80544c490 100644 --- a/src/Magnum/Text/Test/RendererTest.cpp +++ b/src/Magnum/Text/Test/RendererTest.cpp @@ -297,7 +297,7 @@ struct TestShaper: AbstractShaper { return text.size(); } - void doGlyphsInto(const Containers::StridedArrayView1D& ids, const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const override { + void doGlyphIdsInto(const Containers::StridedArrayView1D& ids) const override { for(UnsignedInt i = 0; i != ids.size(); ++i) { /* It just rotates between the three glyphs */ if(i % 3 == 0) @@ -306,7 +306,10 @@ struct TestShaper: AbstractShaper { ids[i] = 7; else ids[i] = 9; - + } + } + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const override { + for(UnsignedInt i = 0; i != offsets.size(); ++i) { /* Offset Y and advance X is getting larger with every glyph, advance Y is flipping its sign with every glyph */ offsets[i] = Vector2::yAxis(i + 1); @@ -961,9 +964,13 @@ void RendererTest::multiline() { return text.size(); } - void doGlyphsInto(const Containers::StridedArrayView1D& ids, const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const override { + void doGlyphIdsInto(const Containers::StridedArrayView1D& ids) const override { for(UnsignedInt i = 0; i != ids.size(); ++i) { ids[i] = 0; + } + } + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const override { + for(UnsignedInt i = 0; i != offsets.size(); ++i) { offsets[i] = {}; advances[i] = Vector2::xAxis(4.0f); } diff --git a/src/MagnumPlugins/MagnumFont/MagnumFont.cpp b/src/MagnumPlugins/MagnumFont/MagnumFont.cpp index 93913b5b8..f0cef2b2b 100644 --- a/src/MagnumPlugins/MagnumFont/MagnumFont.cpp +++ b/src/MagnumPlugins/MagnumFont/MagnumFont.cpp @@ -208,10 +208,11 @@ Containers::Pointer MagnumFont::doCreateShaper() { return _glyphs.size(); } - void doGlyphsInto(const Containers::StridedArrayView1D& ids, const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const override { - const Data& fontData = *static_cast(font())._opened; - + void doGlyphIdsInto(const Containers::StridedArrayView1D& ids) const override { Utility::copy(_glyphs, ids); + } + void doGlyphOffsetsAdvancesInto(const Containers::StridedArrayView1D& offsets, const Containers::StridedArrayView1D& advances) const override { + const Data& fontData = *static_cast(font())._opened; for(std::size_t i = 0; i != _glyphs.size(); ++i) { /* There's no glyph offsets in addition to advances */ offsets[i] = {}; diff --git a/src/MagnumPlugins/MagnumFont/Test/MagnumFontTest.cpp b/src/MagnumPlugins/MagnumFont/Test/MagnumFontTest.cpp index b1440fce0..e3aad0ef7 100644 --- a/src/MagnumPlugins/MagnumFont/Test/MagnumFontTest.cpp +++ b/src/MagnumPlugins/MagnumFont/Test/MagnumFontTest.cpp @@ -152,7 +152,8 @@ void MagnumFontTest::shape() { UnsignedInt ids[4]; Vector2 offsets[4]; Vector2 advances[4]; - shaper->glyphsInto(ids, offsets, advances); + shaper->glyphIdsInto(ids); + shaper->glyphOffsetsAdvancesInto(offsets, advances); CORRADE_COMPARE_AS(Containers::arrayView(ids), Containers::arrayView({ 2u, /* 'W' */ 0u, /* 'a' (not found) */ @@ -197,7 +198,8 @@ void MagnumFontTest::shaperReuse() { UnsignedInt ids[2]; Vector2 offsets[2]; Vector2 advances[2]; - shaper->glyphsInto(ids, offsets, advances); + shaper->glyphIdsInto(ids); + shaper->glyphOffsetsAdvancesInto(offsets, advances); CORRADE_COMPARE_AS(Containers::arrayView(ids), Containers::arrayView({ 2u, /* 'W' */ 1u /* 'e' */ @@ -216,7 +218,8 @@ void MagnumFontTest::shaperReuse() { UnsignedInt ids[4]; Vector2 offsets[4]; Vector2 advances[4]; - shaper->glyphsInto(ids, offsets, advances); + shaper->glyphIdsInto(ids); + shaper->glyphOffsetsAdvancesInto(offsets, advances); CORRADE_COMPARE_AS(Containers::arrayView(ids), Containers::arrayView({ 2u, /* 'W' */ 0u, /* 'a' (not found) */ @@ -239,7 +242,8 @@ void MagnumFontTest::shaperReuse() { UnsignedInt ids[1]; Vector2 offsets[1]; Vector2 advances[1]; - shaper->glyphsInto(ids, offsets, advances); + shaper->glyphIdsInto(ids); + shaper->glyphOffsetsAdvancesInto(offsets, advances); CORRADE_COMPARE_AS(Containers::arrayView(ids), Containers::arrayView({ 0u, }), TestSuite::Compare::Container);