Browse Source

Text: make DistanceFieldGlyphCache work with tight flush rectangles.

Such as is the case with fillGlyphCache(), which just maintains the
union of all glyph rectangles. Sorry for having that temporarily broken.

Also I don't really like the solution here, but was the best I could
come up with, after a bunch of failed attempts to try to do this
directly in the TextureTools::DistanceField.
pull/168/head
Vladimír Vondruš 3 years ago
parent
commit
202ac59f66
  1. 26
      src/Magnum/Text/DistanceFieldGlyphCache.cpp
  2. 21
      src/Magnum/Text/Test/DistanceFieldGlyphCacheGLTest.cpp

26
src/Magnum/Text/DistanceFieldGlyphCache.cpp

@ -100,8 +100,30 @@ void DistanceFieldGlyphCache::doSetImage(const Vector2i& offset, const ImageView
#endif
#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL))
{
input.setImage(0, GL::textureFormat(image.format()), image);
_distanceField(input, texture(), Range2Di::fromSize(offset*scale, image.size()*scale), image.size());
/* Create an image view that includes the distance field radius as
well, to be sure the edges are processed appropriately as well */
/** @todo this feels more like a hack than a real solution, any better
idea? Tried to make TextureTools::DistanceField pad the processing
area on its own, but eventually gave up as it would (a) made the
processing do more work than necessary in many cases, with no easy
way to opt out of that, (b) wasn't really working if the input
didn't have a black strip around the edge on platforms that don't
support border clamp, (c) required the input texture to have
certain wrapping mode set */
CORRADE_INTERNAL_ASSERT(image.storage().skip().xy() == offset);
const Vector2i paddedMin = Math::max(Vector2i{0},
image.storage().skip().xy() - padding());
const Vector2i paddedMax = Math::min(size().xy(),
image.size() + image.storage().skip().xy() + padding());
const ImageView2D paddedImage{
PixelStorage{image.storage()}
.setSkip({paddedMin, image.storage().skip().z()}),
image.format(),
paddedMax - paddedMin,
image.data()};
input.setImage(0, GL::textureFormat(paddedImage.format()), paddedImage);
_distanceField(input, texture(), Range2Di::fromSize(paddedMin*scale, paddedImage.size()*scale), paddedImage.size());
}
#endif
}

21
src/Magnum/Text/Test/DistanceFieldGlyphCacheGLTest.cpp

@ -70,14 +70,25 @@ struct DistanceFieldGlyphCacheGLTest: GL::OpenGLTester {
const struct {
const char* name;
Vector2i sourceSize, size, sourceOffset;
Range2Di flushRange;
Containers::Size2D offset;
} SetImageData[]{
{"",
{256, 256}, {64, 64},
{}, {}},
{256, 256}, {64, 64}, {},
{{}, {256, 256}},
{}},
{"upload with offset",
{512, 384}, {128, 96},
{256, 128}, {128/4, 256/4}},
{512, 384}, {128, 96}, {256, 128},
{{256, 128}, {512, 384}},
{128/4, 256/4}},
{"tight flush rectangle",
{256, 256}, {64, 64}, {},
/* The image is 256x256 with a black 48x48 border around. Even with the
border excluded from the flush rectangle, the doSetImage() should be
still called with a large enough padding to properly run the
distance field algorithm as if the whole image was processed. */
{{48, 48}, {208, 208}},
{}},
};
DistanceFieldGlyphCacheGLTest::DistanceFieldGlyphCacheGLTest() {
@ -158,7 +169,7 @@ void DistanceFieldGlyphCacheGLTest::setImage() {
std::size_t(data.sourceOffset.y()),
std::size_t(data.sourceOffset.x()),
0}, src.size()));
cache.flushImage(Range2Di::fromSize(data.sourceOffset, inputImage->size()));
cache.flushImage(data.flushRange);
MAGNUM_VERIFY_NO_GL_ERROR();
/* On GLES processedImage() isn't implemented as it'd mean creating a

Loading…
Cancel
Save