diff --git a/src/Magnum/Text/AbstractGlyphCache.cpp b/src/Magnum/Text/AbstractGlyphCache.cpp index 865d29a2b..523a56863 100644 --- a/src/Magnum/Text/AbstractGlyphCache.cpp +++ b/src/Magnum/Text/AbstractGlyphCache.cpp @@ -25,6 +25,9 @@ #include "AbstractGlyphCache.h" +#include +#include /** @todo remove once std::vector is gone */ + #include "Magnum/Image.h" #include "Magnum/ImageView.h" #include "Magnum/PixelFormat.h" @@ -44,7 +47,38 @@ std::vector AbstractGlyphCache::reserve(const std::vector& s CORRADE_ASSERT((glyphs.size() == 1 && glyphs.at(0) == std::pair()), "Text::AbstractGlyphCache::reserve(): reserving space in non-empty cache is not yet implemented", {}); glyphs.reserve(glyphs.size() + sizes.size()); - return TextureTools::atlas(_size, sizes, _padding); + + /* Rotations are not yet supported */ + TextureTools::AtlasLandfill atlas{_size}; + atlas.setPadding(_padding) + .clearFlags(TextureTools::AtlasLandfillFlag::RotatePortrait| + TextureTools::AtlasLandfillFlag::RotateLandscape); + + /* Create the output array. Because the new atlas packer doesn't accept + zero sizes, change those to be (1, 1) instead. A new interface will + disallow them as well, but here we want to keep backwards + compatibility. */ + std::vector out(sizes.size()); + for(std::size_t i = 0; i != sizes.size(); ++i) + out[i].max() = Math::max(sizes[i], Vector2i{1}); + + /* The error message matches what the old TextureTools::atlas() did. Not + great, but that's the interface we should stay compatible with. */ + if(!atlas.add(Containers::stridedArrayView(out).slice(&Range2Di::max), + Containers::stridedArrayView(out).slice(&Range2Di::min))) + { + Error{} << "Text::AbstractGlyphCache::reserve(): requested atlas size" + << _size << "is too small to fit" << sizes.size() + << "textures. Generated atlas will be empty."; + return {}; + } + + /* Update the ranges max values to match the new offsets, undo the zero + sizes being (1, 1) */ + for(std::size_t i = 0; i != sizes.size(); ++i) + out[i].max() = out[i].min() + sizes[i]; + + return out; } void AbstractGlyphCache::insert(const UnsignedInt glyph, const Vector2i& position, const Range2Di& rectangle) { diff --git a/src/Magnum/Text/Test/AbstractGlyphCacheTest.cpp b/src/Magnum/Text/Test/AbstractGlyphCacheTest.cpp index 2f2187445..b3c7007f1 100644 --- a/src/Magnum/Text/Test/AbstractGlyphCacheTest.cpp +++ b/src/Magnum/Text/Test/AbstractGlyphCacheTest.cpp @@ -116,20 +116,31 @@ void AbstractGlyphCacheTest::access() { } void AbstractGlyphCacheTest::reserve() { - DummyGlyphCache cache{{29, 20}, {1, 2}}; - - std::vector out = cache.reserve({{5, 3}, {12, 6}, {10, 5}}); + DummyGlyphCache cache{{24, 20}, {1, 2}}; + + /* Padding should get applied to all */ + std::vector out = cache.reserve({ + {5, 3}, + /* Landscape glyphs shouldn't get rotated */ + {12, 6}, + {10, 5}, + /* Zero-sized glyphs should get preserved */ + {0, 1}, + {3, 0}, + }); CORRADE_COMPARE_AS(Containers::arrayView(out), Containers::arrayView({ - Range2Di::fromSize({1, 2}, {5, 3}), - Range2Di::fromSize({15, 2}, {12, 6}), - Range2Di::fromSize({1, 12}, {10, 5}), + Range2Di::fromSize({6, 12}, {5, 3}), + Range2Di::fromSize({1, 2}, {12, 6}), + Range2Di::fromSize({13, 12}, {10, 5}), + Range2Di::fromSize({1, 17}, {0, 1}), + Range2Di::fromSize({1, 12}, {3, 0}), }), TestSuite::Compare::Container); } void AbstractGlyphCacheTest::reserveIncremental() { CORRADE_SKIP_IF_NO_ASSERT(); - DummyGlyphCache cache{{25, 12}}; + DummyGlyphCache cache{{24, 20}, {1, 2}}; /* insert() is what triggers the assert, not reserve() alone */ cache.insert(0, {3, 5}, {{10, 10}, {23, 45}}); @@ -141,12 +152,12 @@ void AbstractGlyphCacheTest::reserveIncremental() { } void AbstractGlyphCacheTest::reserveTooSmall() { - DummyGlyphCache cache{{20, 12}}; + DummyGlyphCache cache{{24, 18}, {1, 2}}; std::ostringstream out; Error redirectError{&out}; CORRADE_VERIFY(cache.reserve({{5, 3}, {12, 6}, {10, 5}}).empty()); - CORRADE_COMPARE(out.str(), "TextureTools::atlas(): requested atlas size Vector(20, 12) is too small to fit 3 Vector(12, 6) textures. Generated atlas will be empty.\n"); + CORRADE_COMPARE(out.str(), "Text::AbstractGlyphCache::reserve(): requested atlas size Vector(24, 18) is too small to fit 3 textures. Generated atlas will be empty.\n"); } void AbstractGlyphCacheTest::setImage() {