Browse Source

Text: use the new landfill packer in AbstractGlyphCache.

Not yet the full extent of it including rotations and incremental
packing, as the existing interface is too awful, also patching over
zero-sized glyphs that the new packer doesn't like. Another round of
deprecations needs to happen first.
pull/168/head
Vladimír Vondruš 3 years ago
parent
commit
2692ff216c
  1. 36
      src/Magnum/Text/AbstractGlyphCache.cpp
  2. 29
      src/Magnum/Text/Test/AbstractGlyphCacheTest.cpp

36
src/Magnum/Text/AbstractGlyphCache.cpp

@ -25,6 +25,9 @@
#include "AbstractGlyphCache.h" #include "AbstractGlyphCache.h"
#include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Containers/ArrayViewStl.h> /** @todo remove once std::vector is gone */
#include "Magnum/Image.h" #include "Magnum/Image.h"
#include "Magnum/ImageView.h" #include "Magnum/ImageView.h"
#include "Magnum/PixelFormat.h" #include "Magnum/PixelFormat.h"
@ -44,7 +47,38 @@ std::vector<Range2Di> AbstractGlyphCache::reserve(const std::vector<Vector2i>& s
CORRADE_ASSERT((glyphs.size() == 1 && glyphs.at(0) == std::pair<Vector2i, Range2Di>()), CORRADE_ASSERT((glyphs.size() == 1 && glyphs.at(0) == std::pair<Vector2i, Range2Di>()),
"Text::AbstractGlyphCache::reserve(): reserving space in non-empty cache is not yet implemented", {}); "Text::AbstractGlyphCache::reserve(): reserving space in non-empty cache is not yet implemented", {});
glyphs.reserve(glyphs.size() + sizes.size()); 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<Range2Di> 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) { void AbstractGlyphCache::insert(const UnsignedInt glyph, const Vector2i& position, const Range2Di& rectangle) {

29
src/Magnum/Text/Test/AbstractGlyphCacheTest.cpp

@ -116,20 +116,31 @@ void AbstractGlyphCacheTest::access() {
} }
void AbstractGlyphCacheTest::reserve() { void AbstractGlyphCacheTest::reserve() {
DummyGlyphCache cache{{29, 20}, {1, 2}}; DummyGlyphCache cache{{24, 20}, {1, 2}};
std::vector<Range2Di> out = cache.reserve({{5, 3}, {12, 6}, {10, 5}}); /* Padding should get applied to all */
std::vector<Range2Di> 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>({ CORRADE_COMPARE_AS(Containers::arrayView(out), Containers::arrayView<Range2Di>({
Range2Di::fromSize({1, 2}, {5, 3}), Range2Di::fromSize({6, 12}, {5, 3}),
Range2Di::fromSize({15, 2}, {12, 6}), Range2Di::fromSize({1, 2}, {12, 6}),
Range2Di::fromSize({1, 12}, {10, 5}), Range2Di::fromSize({13, 12}, {10, 5}),
Range2Di::fromSize({1, 17}, {0, 1}),
Range2Di::fromSize({1, 12}, {3, 0}),
}), TestSuite::Compare::Container); }), TestSuite::Compare::Container);
} }
void AbstractGlyphCacheTest::reserveIncremental() { void AbstractGlyphCacheTest::reserveIncremental() {
CORRADE_SKIP_IF_NO_ASSERT(); CORRADE_SKIP_IF_NO_ASSERT();
DummyGlyphCache cache{{25, 12}}; DummyGlyphCache cache{{24, 20}, {1, 2}};
/* insert() is what triggers the assert, not reserve() alone */ /* insert() is what triggers the assert, not reserve() alone */
cache.insert(0, {3, 5}, {{10, 10}, {23, 45}}); cache.insert(0, {3, 5}, {{10, 10}, {23, 45}});
@ -141,12 +152,12 @@ void AbstractGlyphCacheTest::reserveIncremental() {
} }
void AbstractGlyphCacheTest::reserveTooSmall() { void AbstractGlyphCacheTest::reserveTooSmall() {
DummyGlyphCache cache{{20, 12}}; DummyGlyphCache cache{{24, 18}, {1, 2}};
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
CORRADE_VERIFY(cache.reserve({{5, 3}, {12, 6}, {10, 5}}).empty()); 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() { void AbstractGlyphCacheTest::setImage() {

Loading…
Cancel
Save