Browse Source

Text: port AbstractFont away from STL, adapt to Utility::Unicode changes.

All std::string arguments are now a StringView, what returned a
std::pair is now a Pair. STL compatibility headers are included on
deprecated builds to ease porting, as usual.

The only *really* breaking changes are in the internals, where an
ArrayView<const char32_t> is used instead of std::u32string, which is in
line with the change done in Utility::Unicode::utf32();  and a Triple is
returned instead of a std::tuple. Behaviorally nothing changed except
that fillGlyphCache() now asserts if the input string contains invalid
UTF-8 (which is also in line with the cahnge done in Utility::Unicode).
pull/168/head
Vladimír Vondruš 3 years ago
parent
commit
47a1295ab8
  1. 6
      doc/changelog.dox
  2. 2
      doc/snippets/MagnumText.cpp
  3. 33
      src/Magnum/Text/AbstractFont.cpp
  4. 30
      src/Magnum/Text/AbstractFont.h
  5. 4
      src/Magnum/Text/AbstractFontConverter.cpp
  6. 18
      src/Magnum/Text/Renderer.cpp
  7. 2
      src/Magnum/Text/Test/AbstractFontConverterTest.cpp
  8. 116
      src/Magnum/Text/Test/AbstractFontTest.cpp
  9. 32
      src/Magnum/Text/Test/AbstractLayouterTest.cpp
  10. 24
      src/Magnum/Text/Test/RendererGLTest.cpp
  11. 41
      src/MagnumPlugins/MagnumFont/MagnumFont.cpp
  12. 6
      src/MagnumPlugins/MagnumFont/MagnumFont.h
  13. 26
      src/MagnumPlugins/MagnumFont/Test/MagnumFontTest.cpp
  14. 6
      src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp

6
doc/changelog.dox

@ -1482,6 +1482,12 @@ See also:
@ref std::pair
- All @ref Math APIs that took or returned @ref std::pair now use
@relativeref{Corrade,Containers::Pair} instead
- @ref Text::AbstractFont public APIs now take
@ref Containers::StringView instead of @ref std::string and return
@ref Containers::Pair instead of @ref std::pair. Additionally, the
internal implementation relies on @ref Containers::ArrayView "Containers::ArrayView<const char32_t>"
instead of @ref std::u32string and @ref Containers::Triple instead of
@ref std::tuple, but that shouldn't affect end-user code in any way.
To handle most backwards compatibility, @ref Corrade/Containers/StringStl.h
and/or @ref Corrade/Containers/PairStl.h is included in affected headers
for implicit conversions from/to a @ref std::string and/or @ref std::pair,

2
doc/snippets/MagnumText.cpp

@ -59,7 +59,7 @@ struct MyFont: Text::AbstractFont {
void doClose() override {}
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<Text::AbstractLayouter> doLayout(const Text::AbstractGlyphCache&, Float, const std::string&) override { return {}; }
Containers::Pointer<Text::AbstractLayouter> doLayout(const Text::AbstractGlyphCache&, Float, Containers::StringView) override { return {}; }
};
struct MyFontConverter: Text::AbstractFontConverter {
explicit MyFontConverter(PluginManager::AbstractManager& manager, Containers::StringView plugin): Text::AbstractFontConverter{manager, plugin} {}

33
src/Magnum/Text/AbstractFont.cpp

@ -25,13 +25,15 @@
#include "AbstractFont.h"
#include <string> /** @todo remove once file callbacks are <string>-free */
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/EnumSet.hpp>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringStl.h> /** @todo remove once file callbacks are <string>-free */
#include <Corrade/Containers/Triple.h>
#include <Corrade/PluginManager/Manager.hpp>
#include <Corrade/Utility/DebugStl.h> /** @todo remove once AbstractFont is <string>-free */
#include <Corrade/Utility/Path.h>
#include <Corrade/Utility/Unicode.h>
@ -116,7 +118,7 @@ auto AbstractFont::doOpenData(Containers::ArrayView<const char>, Float) -> Metri
CORRADE_ASSERT_UNREACHABLE("Text::AbstractFont::openData(): feature advertised but not implemented", {});
}
bool AbstractFont::openFile(const std::string& filename, const Float size) {
bool AbstractFont::openFile(const Containers::StringView filename, const Float size) {
close();
Metrics metrics;
@ -158,7 +160,7 @@ bool AbstractFont::openFile(const std::string& filename, const Float size) {
return isOpened();
}
auto AbstractFont::doOpenFile(const std::string& filename, const Float size) -> Metrics {
auto AbstractFont::doOpenFile(const Containers::StringView filename, const Float size) -> Metrics {
CORRADE_ASSERT(features() & FontFeature::OpenData, "Text::AbstractFont::openFile(): not implemented", {});
Metrics metrics;
@ -229,16 +231,20 @@ Vector2 AbstractFont::glyphAdvance(const UnsignedInt glyph) {
return doGlyphAdvance(glyph);
}
void AbstractFont::fillGlyphCache(AbstractGlyphCache& cache, const std::string& characters) {
void AbstractFont::fillGlyphCache(AbstractGlyphCache& cache, const Containers::StringView characters) {
CORRADE_ASSERT(isOpened(),
"Text::AbstractFont::fillGlyphCache(): no font opened", );
CORRADE_ASSERT(!(features() & FontFeature::PreparedGlyphCache),
"Text::AbstractFont::fillGlyphCache(): feature not supported", );
doFillGlyphCache(cache, Utility::Unicode::utf32(characters));
const Containers::Optional<Containers::Array<char32_t>> utf32 = Utility::Unicode::utf32(characters);
CORRADE_ASSERT(utf32,
"Text::AbstractFont::fillGlyphCache(): not a valid UTF-8 string:" << characters, );
doFillGlyphCache(cache, *utf32);
}
void AbstractFont::doFillGlyphCache(AbstractGlyphCache&, const std::u32string&) {
void AbstractFont::doFillGlyphCache(AbstractGlyphCache&, Containers::ArrayView<const char32_t>) {
CORRADE_ASSERT_UNREACHABLE("Text::AbstractFont::fillGlyphCache(): feature advertised but not implemented", );
}
@ -255,7 +261,7 @@ Containers::Pointer<AbstractGlyphCache> AbstractFont::doCreateGlyphCache() {
CORRADE_ASSERT_UNREACHABLE("Text::AbstractFont::createGlyphCache(): feature advertised but not implemented", nullptr);
}
Containers::Pointer<AbstractLayouter> AbstractFont::layout(const AbstractGlyphCache& cache, const Float size, const std::string& text) {
Containers::Pointer<AbstractLayouter> AbstractFont::layout(const AbstractGlyphCache& cache, const Float size, const Containers::StringView text) {
CORRADE_ASSERT(isOpened(), "Text::AbstractFont::layout(): no font opened", nullptr);
return doLayout(cache, size, text);
@ -291,17 +297,14 @@ AbstractLayouter::AbstractLayouter(UnsignedInt glyphCount): _glyphCount(glyphCou
AbstractLayouter::~AbstractLayouter() = default;
std::pair<Range2D, Range2D> AbstractLayouter::renderGlyph(const UnsignedInt i, Vector2& cursorPosition, Range2D& rectangle) {
Containers::Pair<Range2D, Range2D> AbstractLayouter::renderGlyph(const UnsignedInt i, Vector2& cursorPosition, Range2D& rectangle) {
CORRADE_ASSERT(i < glyphCount(), "Text::AbstractLayouter::renderGlyph(): index" << i << "out of range for" << glyphCount() << "glyphs", {});
/* Render the glyph */
Range2D quadPosition, textureCoordinates;
Vector2 advance;
std::tie(quadPosition, textureCoordinates, advance) = doRenderGlyph(i);
const Containers::Triple<Range2D, Range2D, Vector2> quadPositionTextureCoordinatesAdvance = doRenderGlyph(i);
/* Move the quad to cursor */
quadPosition.bottomLeft() += cursorPosition;
quadPosition.topRight() += cursorPosition;
const Range2D quadPosition = quadPositionTextureCoordinatesAdvance.first().translated(cursorPosition);
/* Extend rectangle with current quad bounds. If zero size, replace it. */
if(!rectangle.size().isZero()) {
@ -310,10 +313,10 @@ std::pair<Range2D, Range2D> AbstractLayouter::renderGlyph(const UnsignedInt i, V
} else rectangle = quadPosition;
/* Advance cursor position to next character */
cursorPosition += advance;
cursorPosition += quadPositionTextureCoordinatesAdvance.third();
/* Return moved quad and unchanged texture coordinates */
return {quadPosition, textureCoordinates};
return {quadPosition, quadPositionTextureCoordinatesAdvance.second()};
}
}}

30
src/Magnum/Text/AbstractFont.h

@ -29,14 +29,20 @@
* @brief Class @ref Magnum::Text::AbstractFont, @ref Magnum::Text::AbstractLayouter, enum @ref Magnum::Text::FontFeature, enum set @ref Magnum::Text::FontFeatures
*/
#include <string>
#include <tuple>
#include <Corrade/PluginManager/AbstractPlugin.h>
#include <Corrade/Utility/StlForwardString.h> /** @todo remove once file callbacks are std::string-free */
#include "Magnum/Magnum.h"
#include "Magnum/Text/Text.h"
#include "Magnum/Text/visibility.h"
#ifdef MAGNUM_BUILD_DEPRECATED
/* For APIs that used to take or return a std::string */
#include <Corrade/Containers/StringStl.h>
/* renderGlyph() used to return a std::pair */
#include <Corrade/Containers/PairStl.h>
#endif
namespace Magnum { namespace Text {
/**
@ -372,7 +378,7 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
* memory view to @ref openData() instead. See @ref setFileCallback()
* for more information.
*/
bool openFile(const std::string& filename, Float size);
bool openFile(Containers::StringView filename, Float size);
/**
* @brief Close currently opened file
@ -461,9 +467,9 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
* Fills the cache with given characters. Fonts having
* @ref FontFeature::PreparedGlyphCache do not support partial glyph
* cache filling, use @ref createGlyphCache() instead. Expects that a
* font is opened.
* font is opened and @p characters is valid UTF-8.
*/
void fillGlyphCache(AbstractGlyphCache& cache, const std::string& characters);
void fillGlyphCache(AbstractGlyphCache& cache, Containers::StringView characters);
/**
* @brief Create glyph cache
@ -486,7 +492,7 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
* that a font is opened.
* @see @ref fillGlyphCache(), @ref createGlyphCache()
*/
Containers::Pointer<AbstractLayouter> layout(const AbstractGlyphCache& cache, Float size, const std::string& text);
Containers::Pointer<AbstractLayouter> layout(const AbstractGlyphCache& cache, Float size, Containers::StringView text);
protected:
/**
@ -543,7 +549,7 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
* supported --- instead, file is loaded though the callback and data
* passed through to @ref doOpenData().
*/
virtual Metrics doOpenFile(const std::string& filename, Float size);
virtual Metrics doOpenFile(Containers::StringView filename, Float size);
private:
/** @brief Implementation for @ref features() */
@ -586,13 +592,13 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
* The string is converted from UTF-8 to UTF-32, duplicate characters
* are *not* removed.
*/
virtual void doFillGlyphCache(AbstractGlyphCache& cache, const std::u32string& characters);
virtual void doFillGlyphCache(AbstractGlyphCache& cache, Containers::ArrayView<const char32_t> characters);
/** @brief Implementation for @ref createGlyphCache() */
virtual Containers::Pointer<AbstractGlyphCache> doCreateGlyphCache();
/** @brief Implementation for @ref layout() */
virtual Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache& cache, Float size, const std::string& text) = 0;
virtual Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache& cache, Float size, Containers::StringView text) = 0;
Containers::Optional<Containers::ArrayView<const char>>(*_fileCallback)(const std::string&, InputFileCallbackPolicy, void*){};
void* _fileCallbackUserData{};
@ -650,7 +656,7 @@ class MAGNUM_TEXT_EXPORT AbstractLayouter {
* updates @p rectangle with extended bounds. Expects that @p i is less
* than @ref glyphCount().
*/
std::pair<Range2D, Range2D> renderGlyph(UnsignedInt i, Vector2& cursorPosition, Range2D& rectangle);
Containers::Pair<Range2D, Range2D> renderGlyph(UnsignedInt i, Vector2& cursorPosition, Range2D& rectangle);
protected:
/**
@ -667,7 +673,7 @@ class MAGNUM_TEXT_EXPORT AbstractLayouter {
* Returns quad position (relative to current cursor position), texture
* coordinates and advance to the next glyph.
*/
virtual std::tuple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt i) = 0;
virtual Containers::Triple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt i) = 0;
UnsignedInt _glyphCount;
};
@ -690,7 +696,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"
"cz.mosra.magnum.Text.AbstractFont/0.3.1"
/* [interface] */
#ifndef DOXYGEN_GENERATING_OUTPUT

4
src/Magnum/Text/AbstractFontConverter.cpp

@ -58,7 +58,9 @@ namespace {
std::u32string uniqueUnicode(const std::string& characters)
{
/* Convert UTF-8 to UTF-32 */
std::u32string result = Utility::Unicode::utf32(characters);
Containers::Optional<Containers::Array<char32_t>> utf32 = Utility::Unicode::utf32(characters);
/** @todo result validity check */
std::u32string result{utf32->begin(), utf32->end()};
/* Remove duplicate glyphs */
std::sort(result.begin(), result.end());

18
src/Magnum/Text/Renderer.cpp

@ -26,7 +26,8 @@
#include "Renderer.h"
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Containers/ArrayViewStl.h> /** @todo remove once Renderer is STL-free */
#include <Corrade/Containers/StringStl.h> /** @todo remove once Renderer is STL-free */
#include "Magnum/Mesh.h"
#include "Magnum/GL/Context.h"
@ -111,8 +112,7 @@ std::tuple<std::vector<Vertex>, Range2D> renderVerticesInternal(AbstractFont& fo
/* Render all glyphs */
Vector2 cursorPosition(linePosition);
for(UnsignedInt i = 0; i != layouter->glyphCount(); ++i) {
Range2D quadPosition, textureCoordinates;
std::tie(quadPosition, textureCoordinates) = layouter->renderGlyph(i, cursorPosition, lineRectangle);
const Containers::Pair<Range2D, Range2D> quadPositionTextureCoordinates = layouter->renderGlyph(i, cursorPosition, lineRectangle);
/* 0---2
| |
@ -121,10 +121,14 @@ std::tuple<std::vector<Vertex>, Range2D> renderVerticesInternal(AbstractFont& fo
1---3 */
vertices.insert(vertices.end(), {
{quadPosition.topLeft(), textureCoordinates.topLeft()},
{quadPosition.bottomLeft(), textureCoordinates.bottomLeft()},
{quadPosition.topRight(), textureCoordinates.topRight()},
{quadPosition.bottomRight(), textureCoordinates.bottomRight()}
{quadPositionTextureCoordinates.first().topLeft(),
quadPositionTextureCoordinates.second().topLeft()},
{quadPositionTextureCoordinates.first().bottomLeft(),
quadPositionTextureCoordinates.second().bottomLeft()},
{quadPositionTextureCoordinates.first().topRight(),
quadPositionTextureCoordinates.second().topRight()},
{quadPositionTextureCoordinates.first().bottomRight(),
quadPositionTextureCoordinates.second().bottomRight()}
});
}

2
src/Magnum/Text/Test/AbstractFontConverterTest.cpp

@ -160,7 +160,7 @@ struct DummyFont: AbstractFont {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} dummyFont;

116
src/Magnum/Text/Test/AbstractFontTest.cpp

@ -26,10 +26,12 @@
#include <sstream>
#include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StringStl.h> /** @todo remove once AbstractFont is <string>-free */
#include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringStl.h> /** @todo remove once Debug is stream-free */
#include <Corrade/Containers/Triple.h>
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/String.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/DebugStl.h> /** @todo remove once Debug is stream-free */
#include <Corrade/Utility/Path.h>
#include "Magnum/FileCallback.h"
@ -83,6 +85,7 @@ struct AbstractFontTest: TestSuite::Tester {
void fillGlyphCacheNotSupported();
void fillGlyphCacheNotImplemented();
void fillGlyphCacheNoFont();
void fillGlyphCacheInvalidUtf8();
void createGlyphCache();
void createGlyphCacheNotSupported();
@ -135,6 +138,7 @@ AbstractFontTest::AbstractFontTest() {
&AbstractFontTest::fillGlyphCacheNotSupported,
&AbstractFontTest::fillGlyphCacheNotImplemented,
&AbstractFontTest::fillGlyphCacheNoFont,
&AbstractFontTest::fillGlyphCacheInvalidUtf8,
&AbstractFontTest::createGlyphCache,
&AbstractFontTest::createGlyphCacheNotSupported,
@ -147,6 +151,8 @@ AbstractFontTest::AbstractFontTest() {
&AbstractFontTest::debugFeaturesPacked});
}
using namespace Containers::Literals;
void AbstractFontTest::construct() {
struct: AbstractFont {
FontFeatures doFeatures() const override { return {}; }
@ -155,7 +161,7 @@ void AbstractFontTest::construct() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -180,7 +186,7 @@ void AbstractFontTest::openData() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
@ -210,7 +216,7 @@ void AbstractFontTest::openFileAsData() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
@ -235,7 +241,7 @@ void AbstractFontTest::openFileAsDataNotFound() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -260,7 +266,7 @@ void AbstractFontTest::openFileNotImplemented() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -282,7 +288,7 @@ void AbstractFontTest::openDataNotSupported() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -303,7 +309,7 @@ void AbstractFontTest::openDataNotImplemented() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -325,7 +331,7 @@ void AbstractFontTest::setFileCallback() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -351,7 +357,7 @@ void AbstractFontTest::setFileCallbackTemplate() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
@ -383,7 +389,7 @@ void AbstractFontTest::setFileCallbackTemplateNull() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
@ -408,7 +414,7 @@ void AbstractFontTest::setFileCallbackTemplateConst() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
@ -435,7 +441,7 @@ void AbstractFontTest::setFileCallbackFileOpened() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -457,7 +463,7 @@ void AbstractFontTest::setFileCallbackNotImplemented() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -482,7 +488,7 @@ void AbstractFontTest::setFileCallbackNotSupported() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -503,7 +509,7 @@ void AbstractFontTest::setFileCallbackOpenFileDirectly() {
bool doIsOpened() const override { return _opened; }
void doClose() override { _opened = false; }
Metrics doOpenFile(const std::string& filename, Float size) override {
Metrics doOpenFile(Containers::StringView filename, Float size) override {
/* Called because FileCallback is supported */
_opened = filename == "file.dat" && fileCallback() && fileCallbackUserData();
return {size, 1.0f, 2.0f, 3.0f};
@ -517,7 +523,7 @@ void AbstractFontTest::setFileCallbackOpenFileDirectly() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
@ -546,7 +552,7 @@ void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementation() {
bool doIsOpened() const override { return _opened; }
void doClose() override { _opened = false; }
Metrics doOpenFile(const std::string& filename, Float size) override {
Metrics doOpenFile(Containers::StringView filename, Float size) override {
openFileCalled = filename == "file.dat" && fileCallback() && fileCallbackUserData();
return AbstractFont::doOpenFile(filename, size);
}
@ -558,7 +564,7 @@ void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementation() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
@ -604,14 +610,14 @@ void AbstractFontTest::setFileCallbackOpenFileThroughBaseImplementationFailed()
bool doIsOpened() const override { return false; }
void doClose() override {}
Metrics doOpenFile(const std::string& filename, Float size) override {
Metrics doOpenFile(Containers::StringView filename, Float size) override {
openFileCalled = true;
return AbstractFont::doOpenFile(filename, size);
}
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
@ -636,7 +642,7 @@ void AbstractFontTest::setFileCallbackOpenFileAsData() {
bool doIsOpened() const override { return _opened; }
void doClose() override { _opened = false; }
Metrics doOpenFile(const std::string&, Float) override {
Metrics doOpenFile(Containers::StringView, Float) override {
openFileCalled = true;
return {};
}
@ -648,7 +654,7 @@ void AbstractFontTest::setFileCallbackOpenFileAsData() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
@ -695,14 +701,14 @@ void AbstractFontTest::setFileCallbackOpenFileAsDataFailed() {
bool doIsOpened() const override { return false; }
void doClose() override {}
Metrics doOpenFile(const std::string&, Float) override {
Metrics doOpenFile(Containers::StringView, Float) override {
openFileCalled = true;
return {};
}
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
@ -734,7 +740,7 @@ void AbstractFontTest::properties() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
@ -758,7 +764,7 @@ void AbstractFontTest::propertiesNoFont() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -784,7 +790,7 @@ void AbstractFontTest::glyphId() {
UnsignedInt doGlyphId(char32_t a) override { return a*10; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -802,7 +808,7 @@ void AbstractFontTest::glyphIdNoFont() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -821,7 +827,7 @@ void AbstractFontTest::glyphAdvance() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt a) override { return {a*10.0f, -Float(a)/10.0f}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -839,7 +845,7 @@ void AbstractFontTest::glyphAdvanceNoFont() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;
@ -860,7 +866,7 @@ struct DummyGlyphCache: AbstractGlyphCache {
void AbstractFontTest::layout() {
struct Layouter: AbstractLayouter {
explicit Layouter(UnsignedInt count): AbstractLayouter{count} {}
std::tuple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt) override { return {}; }
Containers::Triple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt) override { return {}; }
};
struct MyFont: AbstractFont {
@ -870,7 +876,7 @@ void AbstractFontTest::layout() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache& cache, Float size, const std::string& str) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache& cache, Float size, Containers::StringView str) override {
return Containers::pointer<Layouter>(UnsignedInt(cache.textureSize().x()*str.size()*size));
}
} font;
@ -890,7 +896,7 @@ void AbstractFontTest::layoutNoFont() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override { return nullptr; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }
} font;
std::ostringstream out;
@ -908,9 +914,9 @@ void AbstractFontTest::fillGlyphCache() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override { return nullptr; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }
void doFillGlyphCache(AbstractGlyphCache& cache, const std::u32string& characters) override {
void doFillGlyphCache(AbstractGlyphCache& cache, Containers::ArrayView<const char32_t> characters) override {
for(char a: characters) cache.insert(a*10, {a/2, a*2}, {});
}
} font;
@ -937,7 +943,7 @@ void AbstractFontTest::fillGlyphCacheNotSupported() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override { return nullptr; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }
} font;
std::ostringstream out;
@ -957,7 +963,7 @@ void AbstractFontTest::fillGlyphCacheNotImplemented() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override { return nullptr; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }
} font;
std::ostringstream out;
@ -977,7 +983,7 @@ void AbstractFontTest::fillGlyphCacheNoFont() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override { return nullptr; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }
} font;
std::ostringstream out;
@ -987,6 +993,26 @@ void AbstractFontTest::fillGlyphCacheNoFont() {
CORRADE_COMPARE(out.str(), "Text::AbstractFont::fillGlyphCache(): no font opened\n");
}
void AbstractFontTest::fillGlyphCacheInvalidUtf8() {
CORRADE_SKIP_IF_NO_ASSERT();
struct MyFont: AbstractFont {
FontFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; }
void doClose() override {}
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }
} font;
std::ostringstream out;
Error redirectError{&out};
DummyGlyphCache cache{{100, 100}};
font.fillGlyphCache(cache, "he\xffo");
CORRADE_COMPARE(out.str(), "Text::AbstractFont::fillGlyphCache(): not a valid UTF-8 string: he\xffo\n");
}
void AbstractFontTest::createGlyphCache() {
struct MyFont: AbstractFont {
FontFeatures doFeatures() const override { return FontFeature::PreparedGlyphCache; }
@ -995,11 +1021,11 @@ void AbstractFontTest::createGlyphCache() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override { return nullptr; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }
Containers::Pointer<AbstractGlyphCache> doCreateGlyphCache() override {
Containers::Pointer<AbstractGlyphCache> cache{new DummyGlyphCache{{100, 100}}};
for(char a: std::string{"helo"}) cache->insert(a*10, {a/2, a*2}, {});
for(char a: "helo"_s) cache->insert(a*10, {a/2, a*2}, {});
return cache;
}
} font;
@ -1023,7 +1049,7 @@ void AbstractFontTest::createGlyphCacheNotSupported() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override { return nullptr; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }
} font;
std::ostringstream out;
@ -1042,7 +1068,7 @@ void AbstractFontTest::createGlyphCacheNotImplemented() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override { return nullptr; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }
} font;
std::ostringstream out;
@ -1061,7 +1087,7 @@ void AbstractFontTest::createGlyphCacheNoFont() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override { return nullptr; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }
} font;
std::ostringstream out;

32
src/Magnum/Text/Test/AbstractLayouterTest.cpp

@ -24,6 +24,7 @@
*/
#include <sstream>
#include <Corrade/Containers/Triple.h>
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/Utility/DebugStl.h> /** @todo remove once Debug is stream-free */
@ -48,10 +49,10 @@ void AbstractLayouterTest::renderGlyph() {
struct Layouter: AbstractLayouter {
explicit Layouter(): AbstractLayouter{3} {}
std::tuple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt) override {
return std::make_tuple(Range2D({1.0f, 0.5f}, {1.1f, 1.0f}),
Range2D({0.3f, 1.1f}, {-0.5f, 0.7f}),
Vector2(2.0f, -1.0f));
Containers::Triple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt) override {
return {{{1.0f, 0.5f}, {1.1f, 1.0f}},
{{0.3f, 1.1f}, {-0.5f, 0.7f}},
{2.0f, -1.0f}};
}
};
@ -60,24 +61,21 @@ void AbstractLayouterTest::renderGlyph() {
Vector2 cursorPosition(1.0f, 2.0f);
Layouter l;
Range2D quadPosition;
Range2D textureCoords;
std::tie(quadPosition, textureCoords) = l.renderGlyph(0, cursorPosition, rectangle);
CORRADE_COMPARE(quadPosition, Range2D({2.0f, 2.5f}, {2.1f, 3.0f}));
CORRADE_COMPARE(textureCoords, Range2D({0.3f, 1.1f}, {-0.5f, 0.7f}));
CORRADE_COMPARE(l.renderGlyph(0, cursorPosition, rectangle),
Containers::pair(Range2D{{2.0f, 2.5f}, {2.1f, 3.0f}},
Range2D{{0.3f, 1.1f}, {-0.5f, 0.7f}}));
CORRADE_COMPARE(cursorPosition, Vector2(3.0f, 1.0f));
CORRADE_COMPARE(rectangle, Range2D({2.0f, 2.5f}, {2.1f, 3.0f}));
std::tie(quadPosition, textureCoords) = l.renderGlyph(1, cursorPosition, rectangle);
CORRADE_COMPARE(quadPosition, Range2D({4.0f, 1.5f}, {4.1f, 2.0f}));
CORRADE_COMPARE(textureCoords, Range2D({0.3f, 1.1f}, {-0.5f, 0.7f}));
CORRADE_COMPARE(l.renderGlyph(1, cursorPosition, rectangle),
Containers::pair(Range2D{{4.0f, 1.5f}, {4.1f, 2.0f}},
Range2D{{0.3f, 1.1f}, {-0.5f, 0.7f}}));
CORRADE_COMPARE(cursorPosition, Vector2(5.0f, 0.0f));
CORRADE_COMPARE(rectangle, Range2D({2.0f, 1.5f}, {4.1f, 3.0f}));
std::tie(quadPosition, textureCoords) = l.renderGlyph(2, cursorPosition, rectangle);
CORRADE_COMPARE(quadPosition, Range2D({6.0f, 0.5f}, {6.1f, 1.0f}));
CORRADE_COMPARE(textureCoords, Range2D({0.3f, 1.1f}, {-0.5f, 0.7f}));
CORRADE_COMPARE(l.renderGlyph(2, cursorPosition, rectangle),
Containers::pair(Range2D{{6.0f, 0.5f}, {6.1f, 1.0f}},
Range2D{{0.3f, 1.1f}, {-0.5f, 0.7f}}));
CORRADE_COMPARE(cursorPosition, Vector2(7.0f, -1.0f));
CORRADE_COMPARE(rectangle, Range2D({2.0f, 0.5f}, {6.1f, 3.0f}));
}
@ -88,7 +86,7 @@ void AbstractLayouterTest::renderGlyphOutOfRange() {
struct Layouter: AbstractLayouter {
explicit Layouter(): AbstractLayouter{3} {}
std::tuple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt) override { return {}; }
Containers::Triple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt) override { return {}; }
} layouter;
Range2D rectangle;

24
src/Magnum/Text/Test/RendererGLTest.cpp

@ -24,6 +24,8 @@
*/
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/StringView.h>
#include <Corrade/Containers/Triple.h>
#include <Corrade/TestSuite/Compare/Container.h>
#include "Magnum/GL/Context.h"
@ -59,12 +61,10 @@ class TestLayouter: public AbstractLayouter {
explicit TestLayouter(Float size, std::size_t glyphCount): AbstractLayouter(glyphCount), _size(size) {}
private:
std::tuple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt i) override {
return std::make_tuple(
Range2D({}, Vector2(3.0f, 2.0f)*((i+1)*_size)),
Range2D::fromSize({i*6.0f, 0.0f}, {6.0f, 10.0f}),
(Vector2::xAxis((i+1)*3.0f)+Vector2(1.0f, -1.0f))*_size
);
Containers::Triple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt i) override {
return {{{}, Vector2(3.0f, 2.0f)*((i+1)*_size)},
Range2D::fromSize({i*6.0f, 0.0f}, {6.0f, 10.0f}),
(Vector2::xAxis((i+1)*3.0f)+Vector2(1.0f, -1.0f))*_size};
}
Float _size;
@ -79,7 +79,7 @@ class TestFont: public AbstractFont {
UnsignedInt doGlyphId(char32_t) override { return 0; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, const Float size, const std::string& text) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float size, Containers::StringView text) override {
return Containers::Pointer<AbstractLayouter>(new TestLayouter(size, text.size()));
}
};
@ -331,8 +331,10 @@ void RendererGLTest::multiline() {
explicit Layouter(UnsignedInt glyphCount): AbstractLayouter(glyphCount) {}
private:
std::tuple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt) override {
return std::make_tuple(Range2D({}, Vector2(1.0f)), Range2D({}, Vector2(1.0f)), Vector2::xAxis(2.0f));
Containers::Triple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt) override {
return {{{}, Vector2(1.0f)},
Range2D({}, Vector2(1.0f)),
Vector2::xAxis(2.0f)};
}
};
@ -346,7 +348,7 @@ void RendererGLTest::multiline() {
bool doIsOpened() const override { return _opened; }
void doClose() override { _opened = false; }
Metrics doOpenFile(const std::string&, Float) override {
Metrics doOpenFile(Containers::StringView, Float) override {
_opened = true;
return {0.5f, 0.45f, -0.25f, 0.75f};
}
@ -354,7 +356,7 @@ void RendererGLTest::multiline() {
UnsignedInt doGlyphId(char32_t) override { return 0; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string& text) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView text) override {
return Containers::Pointer<AbstractLayouter>(new Layouter(text.size()));
}

41
src/MagnumPlugins/MagnumFont/MagnumFont.cpp

@ -26,10 +26,10 @@
#include "MagnumFont.h"
#include <sstream>
#include <Corrade/Containers/ArrayView.h>
#include <Corrade/Containers/GrowableArray.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/StringStl.h> /** @todo remove once AbstractFont is <string>-free */
#include <Corrade/Containers/Triple.h>
#include <Corrade/Utility/Configuration.h>
#include <Corrade/Utility/Path.h>
#include <Corrade/Utility/Unicode.h>
@ -52,27 +52,27 @@ struct MagnumFont::Data {
Containers::Optional<Trade::ImageData2D> image;
Containers::Optional<Containers::String> filePath;
std::unordered_map<char32_t, UnsignedInt> glyphId;
std::vector<Vector2> glyphAdvance;
Containers::Array<Vector2> glyphAdvance;
};
namespace {
class MagnumFontLayouter: public AbstractLayouter {
public:
explicit MagnumFontLayouter(const std::vector<Vector2>& glyphAdvance, const AbstractGlyphCache& cache, Float fontSize, Float textSize, std::vector<UnsignedInt>&& glyphs);
explicit MagnumFontLayouter(Containers::ArrayView<const Vector2> glyphAdvance, const AbstractGlyphCache& cache, Float fontSize, Float textSize, Containers::Array<UnsignedInt>&& glyphs);
private:
std::tuple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt i) override;
Containers::Triple<Range2D, Range2D, Vector2> doRenderGlyph(UnsignedInt i) override;
const std::vector<Vector2>& glyphAdvance;
const Containers::ArrayView<const Vector2> glyphAdvance;
const AbstractGlyphCache& cache;
const Float fontSize, textSize;
const std::vector<UnsignedInt> glyphs;
const Containers::Array<UnsignedInt> glyphs;
};
}
MagnumFont::MagnumFont(): _opened(nullptr) {}
MagnumFont::MagnumFont(PluginManager::AbstractManager& manager, const std::string& plugin): AbstractFont{manager, plugin}, _opened(nullptr) {}
MagnumFont::MagnumFont(PluginManager::AbstractManager& manager, const Containers::StringView& plugin): AbstractFont{manager, plugin}, _opened(nullptr) {}
MagnumFont::~MagnumFont() { close(); }
@ -119,9 +119,9 @@ auto MagnumFont::doOpenData(const Containers::ArrayView<const char> data, const
/* Glyph advances */
const std::vector<Utility::ConfigurationGroup*> glyphs = _opened->conf.groups("glyph");
_opened->glyphAdvance.reserve(glyphs.size());
arrayReserve(_opened->glyphAdvance, glyphs.size());
for(const Utility::ConfigurationGroup* const g: glyphs)
_opened->glyphAdvance.push_back(g->value<Vector2>("advance"));
arrayAppend(_opened->glyphAdvance, g->value<Vector2>("advance"));
/* Fill character->glyph map */
const std::vector<Utility::ConfigurationGroup*> chars = _opened->conf.groups("char");
@ -137,7 +137,7 @@ auto MagnumFont::doOpenData(const Containers::ArrayView<const char> data, const
_opened->conf.value<Float>("lineHeight")};
}
auto MagnumFont::doOpenFile(const std::string& filename, Float size) -> Metrics {
auto MagnumFont::doOpenFile(const Containers::StringView filename, const Float size) -> Metrics {
_opened.emplace();
_opened->filePath.emplace(Utility::Path::split(filename).first());
@ -170,15 +170,14 @@ Containers::Pointer<AbstractGlyphCache> MagnumFont::doCreateGlyphCache() {
return Containers::Pointer<AbstractGlyphCache>{Utility::move(cache)};
}
Containers::Pointer<AbstractLayouter> MagnumFont::doLayout(const AbstractGlyphCache& cache, Float size, const std::string& text) {
Containers::Pointer<AbstractLayouter> MagnumFont::doLayout(const AbstractGlyphCache& cache, const Float size, const Containers::StringView text) {
/* Get glyph codes from characters */
std::vector<UnsignedInt> glyphs;
glyphs.reserve(text.size());
Containers::Array<UnsignedInt> glyphs{NoInit, text.size()};
for(std::size_t i = 0; i != text.size(); ) {
UnsignedInt codepoint;
std::tie(codepoint, i) = Utility::Unicode::nextChar(text, i);
const auto it = _opened->glyphId.find(codepoint);
glyphs.push_back(it == _opened->glyphId.end() ? 0 : it->second);
const Containers::Pair<char32_t, std::size_t> codepointNext = Utility::Unicode::nextChar(text, i);
const auto it = _opened->glyphId.find(codepointNext.first());
glyphs[i] = it == _opened->glyphId.end() ? 0 : it->second;
i = codepointNext.second();
}
return Containers::pointer<MagnumFontLayouter>(_opened->glyphAdvance, cache, this->size(), size, Utility::move(glyphs));
@ -186,9 +185,9 @@ Containers::Pointer<AbstractLayouter> MagnumFont::doLayout(const AbstractGlyphCa
namespace {
MagnumFontLayouter::MagnumFontLayouter(const std::vector<Vector2>& glyphAdvance, const AbstractGlyphCache& cache, const Float fontSize, const Float textSize, std::vector<UnsignedInt>&& glyphs): AbstractLayouter(glyphs.size()), glyphAdvance(glyphAdvance), cache(cache), fontSize(fontSize), textSize(textSize), glyphs(Utility::move(glyphs)) {}
MagnumFontLayouter::MagnumFontLayouter(Containers::ArrayView<const Vector2> glyphAdvance, const AbstractGlyphCache& cache, const Float fontSize, const Float textSize, Containers::Array<UnsignedInt>&& glyphs): AbstractLayouter{UnsignedInt(glyphs.size())}, glyphAdvance{glyphAdvance}, cache(cache), fontSize{fontSize}, textSize{textSize}, glyphs{Utility::move(glyphs)} {}
std::tuple<Range2D, Range2D, Vector2> MagnumFontLayouter::doRenderGlyph(const UnsignedInt i) {
Containers::Triple<Range2D, Range2D, Vector2> MagnumFontLayouter::doRenderGlyph(const UnsignedInt i) {
/* Position of the texture in the resulting glyph, texture coordinates */
Vector2i position;
Range2Di rectangle;
@ -204,7 +203,7 @@ std::tuple<Range2D, Range2D, Vector2> MagnumFontLayouter::doRenderGlyph(const Un
/* Advance for given glyph, denormalized to requested text size */
const Vector2 advance = glyphAdvance[glyphs[i]]*(textSize/fontSize);
return std::make_tuple(quadRectangle, textureCoordinates, advance);
return {quadRectangle, textureCoordinates, advance};
}
}

6
src/MagnumPlugins/MagnumFont/MagnumFont.h

@ -165,7 +165,7 @@ class MAGNUM_MAGNUMFONT_EXPORT MagnumFont: public AbstractFont {
explicit MagnumFont();
/** @brief Plugin manager constructor */
explicit MagnumFont(PluginManager::AbstractManager& manager, const std::string& plugin);
explicit MagnumFont(PluginManager::AbstractManager& manager, const Containers::StringView& plugin);
~MagnumFont();
@ -173,13 +173,13 @@ class MAGNUM_MAGNUMFONT_EXPORT MagnumFont: public AbstractFont {
MAGNUM_MAGNUMFONT_LOCAL FontFeatures doFeatures() const override;
MAGNUM_MAGNUMFONT_LOCAL bool doIsOpened() const override;
MAGNUM_MAGNUMFONT_LOCAL Metrics doOpenData(Containers::ArrayView<const char> data, Float) override;
MAGNUM_MAGNUMFONT_LOCAL Metrics doOpenFile(const std::string& filename, Float) override;
MAGNUM_MAGNUMFONT_LOCAL Metrics doOpenFile(Containers::StringView filename, Float) override;
MAGNUM_MAGNUMFONT_LOCAL void doClose() override;
MAGNUM_MAGNUMFONT_LOCAL UnsignedInt doGlyphId(char32_t character) override;
MAGNUM_MAGNUMFONT_LOCAL Vector2 doGlyphAdvance(UnsignedInt glyph) override;
MAGNUM_MAGNUMFONT_LOCAL Containers::Pointer<AbstractGlyphCache> doCreateGlyphCache() override;
MAGNUM_MAGNUMFONT_LOCAL Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache& cache, Float size, const std::string& text) override;
MAGNUM_MAGNUMFONT_LOCAL Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache& cache, Float size, Containers::StringView text) override;
struct Data;
Containers::Pointer<Data> _opened;

26
src/MagnumPlugins/MagnumFont/Test/MagnumFontTest.cpp

@ -116,32 +116,28 @@ void MagnumFontTest::layout() {
CORRADE_COMPARE(layouter->glyphCount(), 4);
Range2D rectangle;
Range2D position;
Range2D textureCoordinates;
Vector2 cursorPosition;
/* 'W' */
Vector2 cursorPosition;
std::tie(position, textureCoordinates) = layouter->renderGlyph(0, cursorPosition = {}, rectangle);
CORRADE_COMPARE(position, Range2D({0.78125f, 1.0625f}, {1.28125f, 4.8125f}));
CORRADE_COMPARE(textureCoordinates, Range2D({0, 0.03125f}, {0.0625f, 0.5f}));
CORRADE_COMPARE(layouter->renderGlyph(0, cursorPosition = {}, rectangle),
Containers::pair(Range2D{{0.78125f, 1.0625f}, {1.28125f, 4.8125f}},
Range2D{{0, 0.03125f}, {0.0625f, 0.5f}}));
CORRADE_COMPARE(cursorPosition, Vector2(0.71875f, 0.0f));
/* 'a' (not found) */
std::tie(position, textureCoordinates) = layouter->renderGlyph(1, cursorPosition = {}, rectangle);
CORRADE_COMPARE(position, Range2D());
CORRADE_COMPARE(textureCoordinates, Range2D());
CORRADE_COMPARE(layouter->renderGlyph(1, cursorPosition = {}, rectangle),
Containers::pair(Range2D{}, Range2D{}));
CORRADE_COMPARE(cursorPosition, Vector2(0.25f, 0.0f));
/* 'v' (not found) */
std::tie(position, textureCoordinates) = layouter->renderGlyph(2, cursorPosition = {}, rectangle);
CORRADE_COMPARE(position, Range2D());
CORRADE_COMPARE(textureCoordinates, Range2D());
CORRADE_COMPARE(layouter->renderGlyph(2, cursorPosition = {}, rectangle),
Containers::pair(Range2D{}, Range2D{}));
CORRADE_COMPARE(cursorPosition, Vector2(0.25f, 0.0f));
/* 'e' */
std::tie(position, textureCoordinates) = layouter->renderGlyph(3, cursorPosition = {}, rectangle);
CORRADE_COMPARE(position, Range2D({0.78125f, 0.375f}, {2.28125f, 1.25f}));
CORRADE_COMPARE(textureCoordinates, Range2D({0.0625f, 0.015625f}, {0.25f, 0.125f}));
CORRADE_COMPARE(layouter->renderGlyph(3, cursorPosition = {}, rectangle),
Containers::pair(Range2D{{0.78125f, 0.375f}, {2.28125f, 1.25f}},
Range2D{{0.0625f, 0.015625f}, {0.25f, 0.125f}}));
CORRADE_COMPARE(cursorPosition, Vector2(0.375f, 0.0f));
}

6
src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp

@ -93,12 +93,12 @@ void MagnumFontConverterTest::exportFont() {
private:
void doClose() override { _opened = false; }
bool doIsOpened() const override { return _opened; }
Metrics doOpenFile(const std::string&, Float) override {
Metrics doOpenFile(Containers::StringView, Float) override {
_opened = true;
return {16.0f, 25.0f, -10.0f, 39.7333f};
}
FontFeatures doFeatures() const override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override { return nullptr; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }
UnsignedInt doGlyphId(const char32_t character) override {
switch(character) {
@ -167,7 +167,7 @@ void MagnumFontConverterTest::exportFontNoGlyphCacheImageDownload() {
UnsignedInt doGlyphId(char32_t) override { return {}; }
Vector2 doGlyphAdvance(UnsignedInt) override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, const std::string&) override {
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override {
return nullptr;
}
} font;

Loading…
Cancel
Save