Browse Source

MagnumFont{,Converter}: actual proper tests.

Need some regression tests for the upcoming glyph cache rework as
otherwise it'll be too miserable. It now fills the glyph cache image
with some non-trivial data and compares to them, and checks the filled
glyphs for the created glyph cache too.

This also fixes a regression introduced when porting away from STL in
47a1295ab8, where UTF-8 layouting was
reporting extra glyphs at the end. Now UTF-8 support is properly tested
both in the MagnumFontConverter plugin and MagnumFont.
pull/168/head
Vladimír Vondruš 3 years ago
parent
commit
4ed4e44ee1
  1. 6
      src/MagnumPlugins/MagnumFont/MagnumFont.cpp
  2. 19
      src/MagnumPlugins/MagnumFont/Test/CMakeLists.txt
  3. 84
      src/MagnumPlugins/MagnumFont/Test/MagnumFontGLTest.cpp
  4. 104
      src/MagnumPlugins/MagnumFont/Test/MagnumFontTest.cpp
  5. 1
      src/MagnumPlugins/MagnumFont/Test/configure.h.cmake
  6. 10
      src/MagnumPlugins/MagnumFont/Test/font-empty.conf
  7. 19
      src/MagnumPlugins/MagnumFont/Test/font.conf
  8. BIN
      src/MagnumPlugins/MagnumFont/Test/font.tga
  9. 20
      src/MagnumPlugins/MagnumFontConverter/Test/CMakeLists.txt
  10. 186
      src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp
  11. 2
      src/MagnumPlugins/MagnumFontConverter/Test/configure.h.cmake
  12. 24
      src/MagnumPlugins/MagnumFontConverter/Test/font-empty-cache.conf
  13. BIN
      src/MagnumPlugins/MagnumFontConverter/Test/font-empty-cache.tga

6
src/MagnumPlugins/MagnumFont/MagnumFont.cpp

@ -27,6 +27,7 @@
#include <sstream>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/GrowableArray.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/StridedArrayView.h>
@ -185,11 +186,12 @@ Containers::Pointer<AbstractGlyphCache> MagnumFont::doCreateGlyphCache() {
Containers::Pointer<AbstractLayouter> MagnumFont::doLayout(const AbstractGlyphCache& cache, const Float size, const Containers::StringView text) {
/* Get glyph codes from characters */
Containers::Array<UnsignedInt> glyphs{NoInit, text.size()};
Containers::Array<UnsignedInt> glyphs;
arrayReserve(glyphs, text.size());
for(std::size_t i = 0; i != text.size(); ) {
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;
arrayAppend(glyphs, it == _opened->glyphId.end() ? 0 : it->second);
i = codepointNext.second();
}

19
src/MagnumPlugins/MagnumFont/Test/CMakeLists.txt

@ -36,6 +36,9 @@ endif()
if(NOT MAGNUM_MAGNUMFONT_BUILD_STATIC)
set(MAGNUMFONT_PLUGIN_FILENAME $<TARGET_FILE:MagnumFont>)
set(TGAIMPORTER_PLUGIN_FILENAME $<TARGET_FILE:TgaImporter>)
if(MAGNUM_WITH_ANYIMAGEIMPORTER)
set(ANYIMAGEIMPORTER_PLUGIN_FILENAME $<TARGET_FILE:AnyImageImporter>)
endif()
endif()
# First replace ${} variables, then $<> generator expressions
@ -63,16 +66,28 @@ endif()
if(MAGNUM_BUILD_GL_TESTS)
corrade_add_test(MagnumFontGLTest MagnumFontGLTest.cpp
LIBRARIES MagnumText MagnumTrade MagnumOpenGLTester
LIBRARIES
MagnumDebugTools
MagnumText
MagnumTrade
MagnumOpenGLTester
FILES
font.conf
font-empty.conf
font.tga)
target_include_directories(MagnumFontGLTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>)
if(MAGNUM_MAGNUMFONT_BUILD_STATIC)
target_link_libraries(MagnumFontGLTest PRIVATE MagnumFont TgaImporter)
target_link_libraries(MagnumFontGLTest PRIVATE
MagnumFont) # TgaImporter should get linked transitively
if(MAGNUM_WITH_ANYIMAGEIMPORTER)
target_link_libraries(MagnumFontGLTest PRIVATE AnyImageImporter)
endif()
else()
# So the plugins get properly built when building the test
add_dependencies(MagnumFontGLTest MagnumFont TgaImporter)
if(MAGNUM_WITH_ANYIMAGEIMPORTER)
add_dependencies(MagnumFontGLTest AnyImageImporter)
endif()
endif()
if((CORRADE_BUILD_STATIC OR MAGNUM_BUILD_STATIC) AND NOT MAGNUM_MAGNUMFONT_BUILD_STATIC)
# CMake < 3.4 does this implicitly, but 3.4+ not anymore (see CMP0065).

84
src/MagnumPlugins/MagnumFont/Test/MagnumFontGLTest.cpp

@ -28,6 +28,13 @@
#include <Corrade/Containers/StringStl.h> /** @todo remove once AbstractFont is <string>-free */
#include <Corrade/Utility/Path.h>
#include "Magnum/Image.h"
#include "Magnum/ImageView.h"
#include "Magnum/PixelFormat.h"
#include "Magnum/DebugTools/CompareImage.h"
#ifdef MAGNUM_TARGET_GLES
#include "Magnum/DebugTools/TextureImage.h"
#endif
#include "Magnum/GL/OpenGLTester.h"
#include "Magnum/Text/AbstractFont.h"
#include "Magnum/Text/GlyphCache.h"
@ -41,6 +48,7 @@ struct MagnumFontGLTest: GL::OpenGLTester {
explicit MagnumFontGLTest();
void createGlyphCache();
void createGlyphCacheNoGlyphs();
/* Explicitly forbid system-wide plugin dependencies */
PluginManager::Manager<Trade::AbstractImporter> _importerManager{"nonexistent"};
@ -48,15 +56,20 @@ struct MagnumFontGLTest: GL::OpenGLTester {
};
MagnumFontGLTest::MagnumFontGLTest() {
addTests({&MagnumFontGLTest::createGlyphCache});
addTests({&MagnumFontGLTest::createGlyphCache,
&MagnumFontGLTest::createGlyphCacheNoGlyphs});
/* Load the plugins directly from the build tree. Otherwise they're static
and already loaded. */
/* Load the plugins directly from the build tree. Otherwise they're either
static and already loaded or not present in the build tree. */
_fontManager.registerExternalManager(_importerManager);
#if defined(TGAIMPORTER_PLUGIN_FILENAME) && defined(MAGNUMFONT_PLUGIN_FILENAME)
CORRADE_INTERNAL_ASSERT_OUTPUT(_importerManager.load(TGAIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
CORRADE_INTERNAL_ASSERT_OUTPUT(_fontManager.load(MAGNUMFONT_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
/* Optional plugins that don't have to be here */
#ifdef ANYIMAGEIMPORTER_PLUGIN_FILENAME
CORRADE_INTERNAL_ASSERT_OUTPUT(_importerManager.load(ANYIMAGEIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
}
void MagnumFontGLTest::createGlyphCache() {
@ -64,14 +77,71 @@ void MagnumFontGLTest::createGlyphCache() {
CORRADE_VERIFY(font->openFile(Utility::Path::join(MAGNUMFONT_TEST_DIR, "font.conf"), 0.0f));
/* Just testing that nothing crashes, asserts or errors */
Containers::Pointer<AbstractGlyphCache> cache = font->createGlyphCache();
CORRADE_VERIFY(cache);
MAGNUM_VERIFY_NO_GL_ERROR();
/* Verify glyph contents */
CORRADE_COMPARE(cache->glyphCount(), 4);
CORRADE_COMPARE((*cache)[0], std::make_pair(
Vector2i{-16, -8},
Range2Di{{0, 0}, {32, 16}}));
CORRADE_COMPARE((*cache)[font->glyphId(U'W')], std::make_pair(
Vector2i{9, 26},
Range2Di{{0, 4}, {40, 64}}));
CORRADE_COMPARE((*cache)[font->glyphId(U'e')], std::make_pair(
Vector2i{9, 4},
Range2Di{{20, 0}, {128, 48}}));
/* ě has deliberately the same glyph data as e */
UnsignedInt eId = font->glyphId(
/* MSVC (but not clang-cl) doesn't support UTF-8 in char32_t literals
but it does it regular strings. Still a problem in MSVC 2022, what a
trash fire, can't you just give up on those codepage insanities
already, ffs?! */
#if defined(CORRADE_TARGET_MSVC) && !defined(CORRADE_TARGET_CLANG)
U'\u011B'
#else
U'ě'
#endif
);
CORRADE_COMPARE((*cache)[eId], std::make_pair(
Vector2i{9, 4},
Range2Di{{20, 0}, {128, 48}}));
if(!(_importerManager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
!(_importerManager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found, not testing glyph cache contents");
/* Verify the actual texture. It should be the image file verbatim. On GLES
we cannot really verify that the size matches, but at least
something. */
#ifndef MAGNUM_TARGET_GLES
Image2D image = static_cast<GlyphCache&>(*cache).texture().image(0, {PixelFormat::R8Unorm});
#else
Image2D image = DebugTools::textureSubImage(static_cast<GlyphCache&>(*cache).texture(), 0, {{}, {8, 4}}, {PixelFormat::R8Unorm});
#endif
CORRADE_COMPARE_WITH(image,
Utility::Path::join(MAGNUMFONT_TEST_DIR, "font.tga"),
DebugTools::CompareImageToFile{_importerManager});
}
void MagnumFontGLTest::createGlyphCacheNoGlyphs() {
Containers::Pointer<AbstractFont> font = _fontManager.instantiate("MagnumFont");
CORRADE_VERIFY(font->openFile(Utility::Path::join(MAGNUMFONT_TEST_DIR, "font-empty.conf"), 0.0f));
Containers::Pointer<AbstractGlyphCache> cache = font->createGlyphCache();
CORRADE_VERIFY(cache);
CORRADE_COMPARE(cache->glyphCount(), 3);
MAGNUM_VERIFY_NO_GL_ERROR();
/* There's just the empty glyph added by the cache itself, nothing else */
CORRADE_COMPARE(cache->glyphCount(), 1);
CORRADE_COMPARE((*cache)[0], std::make_pair(
Vector2i{0, 0},
Range2Di{{0, 0}, {0, 0}}));
/** @todo properly test contents */
/* Not testing the image as there's no special codepath taken for it if
there are no glyphs */
}
}}}}

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

@ -47,6 +47,7 @@ struct MagnumFontTest: TestSuite::Tester {
void nonexistent();
void properties();
void layout();
void layoutNoGlyphsInCache();
void fileCallbackImage();
void fileCallbackImageNotFound();
@ -56,10 +57,22 @@ struct MagnumFontTest: TestSuite::Tester {
PluginManager::Manager<AbstractFont> _fontManager{"nonexistent"};
};
const struct {
const char* name;
const char* string;
} LayoutData[]{
{"", "Wave"},
{"UTF-8", "Wavě"},
};
MagnumFontTest::MagnumFontTest() {
addTests({&MagnumFontTest::nonexistent,
&MagnumFontTest::properties,
&MagnumFontTest::layout,
&MagnumFontTest::properties});
addInstancedTests({&MagnumFontTest::layout},
Containers::arraySize(LayoutData));
addTests({&MagnumFontTest::layoutNoGlyphsInCache,
&MagnumFontTest::fileCallbackImage,
&MagnumFontTest::fileCallbackImageNotFound});
@ -93,18 +106,39 @@ void MagnumFontTest::properties() {
CORRADE_COMPARE(font->ascent(), 25.0f);
CORRADE_COMPARE(font->descent(), -10.0f);
CORRADE_COMPARE(font->lineHeight(), 39.7333f);
CORRADE_COMPARE(font->glyphCount(), 3);
CORRADE_COMPARE(font->glyphSize(font->glyphId(U'W')), (Vector2{16.0f, 120.0f}));
CORRADE_COMPARE(font->glyphCount(), 4);
CORRADE_COMPARE(font->glyphId(U'W'), 2);
CORRADE_COMPARE(font->glyphId(U'e'), 1);
UnsignedInt eId = font->glyphId(
/* MSVC (but not clang-cl) doesn't support UTF-8 in char32_t literals
but it does it regular strings. Still a problem in MSVC 2022, what a
trash fire, can't you just give up on those codepage insanities
already, ffs?! */
#if defined(CORRADE_TARGET_MSVC) && !defined(CORRADE_TARGET_CLANG)
U'\u011B'
#else
U'ě'
#endif
);
CORRADE_COMPARE(eId, 3);
CORRADE_COMPARE(font->glyphSize(font->glyphId(U'W')), (Vector2{8.0f, 44.0f}));
CORRADE_COMPARE(font->glyphAdvance(font->glyphId(U'W')), (Vector2{23.0f, 0.0f}));
}
void MagnumFontTest::layout() {
auto&& data = LayoutData[testCaseInstanceId()];
setTestCaseDescription(data.name);
Containers::Pointer<AbstractFont> font = _fontManager.instantiate("MagnumFont");
CORRADE_VERIFY(font->openFile(Utility::Path::join(MAGNUMFONT_TEST_DIR, "font.conf"), 0.0f));
/* Fill the cache with some fake glyphs */
struct DummyGlyphCache: AbstractGlyphCache {
/* Fill the cache with some fake glyphs. Usually fillGlyphCache() would
happen here, but that requires creating a GL GlyphCache, which would
make it impossible to test w/o a GL context */
/** @todo clean up this mess, it's also getting increasingly out of sync
with the actual glyph cache data in the font */
struct: AbstractGlyphCache {
using AbstractGlyphCache::AbstractGlyphCache;
GlyphCacheFeatures doFeatures() const override { return {}; }
@ -112,8 +146,20 @@ void MagnumFontTest::layout() {
} cache{Vector2i{256}};
cache.insert(font->glyphId(U'W'), {25, 34}, {{0, 8}, {16, 128}});
cache.insert(font->glyphId(U'e'), {25, 12}, {{16, 4}, {64, 32}});
auto layouter = font->layout(cache, 0.5f, "Wave");
/* ě has deliberately the same glyph data as e */
cache.insert(font->glyphId(
/* MSVC (but not clang-cl) doesn't support UTF-8 in char32_t literals
but it does it regular strings. Still a problem in MSVC 2022, what a
trash fire, can't you just give up on those codepage insanities
already, ffs?! */
#if defined(CORRADE_TARGET_MSVC) && !defined(CORRADE_TARGET_CLANG)
U'\u011B'
#else
U'ě'
#endif
), {25, 12}, {{16, 4}, {64, 32}});
auto layouter = font->layout(cache, 0.5f, data.string);
CORRADE_VERIFY(layouter);
CORRADE_COMPARE(layouter->glyphCount(), 4);
@ -136,13 +182,53 @@ void MagnumFontTest::layout() {
Containers::pair(Range2D{}, Range2D{}));
CORRADE_COMPARE(cursorPosition, Vector2(0.25f, 0.0f));
/* 'e' */
/* 'e' or 'ě' */
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));
}
void MagnumFontTest::layoutNoGlyphsInCache() {
Containers::Pointer<AbstractFont> font = _fontManager.instantiate("MagnumFont");
CORRADE_VERIFY(font->openFile(Utility::Path::join(MAGNUMFONT_TEST_DIR, "font.conf"), 0.0f));
/* Tests the case where createGlyphCache() was accidentally not called */
struct: AbstractGlyphCache {
using AbstractGlyphCache::AbstractGlyphCache;
GlyphCacheFeatures doFeatures() const override { return {}; }
void doSetImage(const Vector2i&, const ImageView2D&) override {}
} cache{Vector2i{256}};
auto layouter = font->layout(cache, 0.5f, "Wave");
CORRADE_VERIFY(layouter);
CORRADE_COMPARE(layouter->glyphCount(), 4);
Range2D rectangle;
Vector2 cursorPosition;
/* Compared to layout(), only the cursor position gets updated, everything
else falls back to the invalid glyph */
CORRADE_COMPARE(layouter->renderGlyph(0, cursorPosition = {}, rectangle),
Containers::pair(Range2D{}, Range2D{}));
CORRADE_COMPARE(cursorPosition, Vector2(0.71875f, 0.0f));
CORRADE_COMPARE(layouter->renderGlyph(1, cursorPosition = {}, rectangle),
Containers::pair(Range2D{}, Range2D{}));
CORRADE_COMPARE(cursorPosition, Vector2(0.25f, 0.0f));
CORRADE_COMPARE(layouter->renderGlyph(2, cursorPosition = {}, rectangle),
Containers::pair(Range2D{}, Range2D{}));
CORRADE_COMPARE(cursorPosition, Vector2(0.25f, 0.0f));
CORRADE_COMPARE(layouter->renderGlyph(3, cursorPosition = {}, rectangle),
Containers::pair(Range2D{}, Range2D{}));
CORRADE_COMPARE(cursorPosition, Vector2(0.375f, 0.0f));
}
void MagnumFontTest::fileCallbackImage() {
Containers::Pointer<AbstractFont> font = _fontManager.instantiate("MagnumFont");
CORRADE_VERIFY(font->features() & FontFeature::FileCallback);

1
src/MagnumPlugins/MagnumFont/Test/configure.h.cmake

@ -24,5 +24,6 @@
*/
#cmakedefine MAGNUMFONT_PLUGIN_FILENAME "${MAGNUMFONT_PLUGIN_FILENAME}"
#cmakedefine ANYIMAGEIMPORTER_PLUGIN_FILENAME "${ANYIMAGEIMPORTER_PLUGIN_FILENAME}"
#cmakedefine TGAIMPORTER_PLUGIN_FILENAME "${TGAIMPORTER_PLUGIN_FILENAME}"
#define MAGNUMFONT_TEST_DIR "${MAGNUMFONT_TEST_DIR}"

10
src/MagnumPlugins/MagnumFont/Test/font-empty.conf

@ -0,0 +1,10 @@
# Copy of font.conf with all [char] and [glyph] sections removed. Deliberately
# referencing the same image.
version=1
image=font.tga
originalImageSize=128 64
padding=16 8
fontSize=16
ascent=25
descent=-10
lineHeight=39.7333

19
src/MagnumPlugins/MagnumFont/Test/font.conf

@ -1,7 +1,7 @@
version=1
image=font.tga
originalImageSize=1536 1536
padding=24 24
originalImageSize=128 64
padding=16 8
fontSize=16
ascent=25
descent=-10
@ -18,15 +18,22 @@ glyph=1
[char]
unicode=76
glyph=0
[char]
unicode=11B
glyph=3
[glyph]
advance=8 0
position=24 24
rectangle=24 24 -24 -24
position=0 0
rectangle=16 8 16 8
[glyph]
advance=12 0
position=25 12
rectangle=16 4 64 32
rectangle=36 8 112 40
[glyph]
advance=23 0
position=25 34
rectangle=0 8 16 128
rectangle=16 12 24 56
[glyph]
advance=12 0
position=25 12
rectangle=36 8 112 40

BIN
src/MagnumPlugins/MagnumFont/Test/font.tga

Binary file not shown.

20
src/MagnumPlugins/MagnumFontConverter/Test/CMakeLists.txt

@ -28,9 +28,11 @@
set(CMAKE_FOLDER "MagnumPlugins/MagnumFontConverter/Test")
if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID)
set(MAGNUMFONTCONVERTER_TEST_DIR ".")
set(MAGNUMFONTCONVERTER_TEST_WRITE_DIR "write")
set(MAGNUMFONT_TEST_DIR ".")
else()
set(MAGNUMFONTCONVERTER_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(MAGNUMFONTCONVERTER_TEST_WRITE_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(MAGNUMFONT_TEST_DIR ${PROJECT_SOURCE_DIR}/src/MagnumPlugins/MagnumFont/Test)
endif()
@ -38,6 +40,9 @@ endif()
if(NOT MAGNUM_MAGNUMFONTCONVERTER_BUILD_STATIC)
set(MAGNUMFONTCONVERTER_PLUGIN_FILENAME $<TARGET_FILE:MagnumFontConverter>)
set(TGAIMAGECONVERTER_PLUGIN_FILENAME $<TARGET_FILE:TgaImageConverter>)
if(MAGNUM_WITH_ANYIMAGEIMPORTER)
set(ANYIMAGEIMPORTER_PLUGIN_FILENAME $<TARGET_FILE:AnyImageImporter>)
endif()
if(MAGNUM_WITH_TGAIMPORTER)
set(TGAIMPORTER_PLUGIN_FILENAME $<TARGET_FILE:TgaImporter>)
endif()
@ -50,20 +55,31 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/configure.h
INPUT ${CMAKE_CURRENT_BINARY_DIR}/configure.h.in)
corrade_add_test(MagnumFontConverterTest MagnumFontConverterTest.cpp
LIBRARIES MagnumText MagnumTrade
LIBRARIES
MagnumDebugTools
MagnumText
MagnumTrade
FILES
../../MagnumFont/Test/font.conf
../../MagnumFont/Test/font.tga)
../../MagnumFont/Test/font.tga
font-empty-cache.conf
font-empty-cache.tga)
target_include_directories(MagnumFontConverterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>)
if(MAGNUM_MAGNUMFONTCONVERTER_BUILD_STATIC)
target_link_libraries(MagnumFontConverterTest PRIVATE
MagnumFontConverter) # TgaImageConverter should get linked transitively
if(MAGNUM_WITH_ANYIMAGEIMPORTER)
target_link_libraries(MagnumFontConverterTest PRIVATE AnyImageImporter)
endif()
if(MAGNUM_WITH_TGAIMPORTER)
target_link_libraries(MagnumFontConverterTest PRIVATE TgaImporter)
endif()
else()
# So the plugins get properly built when building the test
add_dependencies(MagnumFontConverterTest MagnumFontConverter)
if(MAGNUM_WITH_ANYIMAGEIMPORTER)
add_dependencies(MagnumFontConverterTest AnyImageImporter)
endif()
if(MAGNUM_WITH_TGAIMPORTER)
add_dependencies(MagnumFontConverterTest TgaImporter)
endif()

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

@ -25,6 +25,7 @@
#include <sstream>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Containers/StringStl.h> /** @todo remove once AbstractFont is <string>-free */
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/File.h>
@ -32,7 +33,9 @@
#include <Corrade/Utility/Path.h>
#include "Magnum/Image.h"
#include "Magnum/ImageView.h"
#include "Magnum/PixelFormat.h"
#include "Magnum/DebugTools/CompareImage.h"
#include "Magnum/Text/AbstractGlyphCache.h"
#include "Magnum/Text/AbstractFont.h"
#include "Magnum/Text/AbstractFontConverter.h"
@ -48,6 +51,7 @@ struct MagnumFontConverterTest: TestSuite::Tester {
explicit MagnumFontConverterTest();
void exportFont();
void exportFontEmptyCache();
void exportFontNoGlyphCacheImageDownload();
/* Explicitly forbid system-wide plugin dependencies */
@ -58,16 +62,20 @@ struct MagnumFontConverterTest: TestSuite::Tester {
MagnumFontConverterTest::MagnumFontConverterTest() {
addTests({&MagnumFontConverterTest::exportFont,
&MagnumFontConverterTest::exportFontEmptyCache,
&MagnumFontConverterTest::exportFontNoGlyphCacheImageDownload});
/* Load the plugins directly from the build tree. Otherwise they are static
and already loaded. */
/* Load the plugins directly from the build tree. Otherwise they're either
static and already loaded or not present in the build tree. */
_fontConverterManager.registerExternalManager(_imageConverterManager);
#if defined(TGAIMAGECONVERTER_PLUGIN_FILENAME) && defined(MAGNUMFONTCONVERTER_PLUGIN_FILENAME)
CORRADE_INTERNAL_ASSERT_OUTPUT(_imageConverterManager.load(TGAIMAGECONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
CORRADE_INTERNAL_ASSERT_OUTPUT(_fontConverterManager.load(MAGNUMFONTCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
/* Optional plugins that don't have to be here */
#ifdef ANYIMAGEIMPORTER_PLUGIN_FILENAME
CORRADE_INTERNAL_ASSERT_OUTPUT(_importerManager.load(ANYIMAGEIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
#ifdef TGAIMPORTER_PLUGIN_FILENAME
CORRADE_INTERNAL_ASSERT_OUTPUT(_importerManager.load(TGAIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
@ -76,6 +84,53 @@ MagnumFontConverterTest::MagnumFontConverterTest() {
CORRADE_INTERNAL_ASSERT_OUTPUT(Utility::Path::make(MAGNUMFONTCONVERTER_TEST_WRITE_DIR));
}
class MyFont: public Text::AbstractFont {
private:
void doClose() override { _opened = false; }
bool doIsOpened() const override { return _opened; }
Properties doOpenFile(Containers::StringView, Float) override {
_opened = true;
return {16.0f, 25.0f, -10.0f, 39.7333f, 4};
}
FontFeatures doFeatures() const override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }
UnsignedInt doGlyphId(const char32_t character) override {
switch(character) {
case U'W': return 2;
case U'e': return 1;
/* MSVC (but not clang-cl) doesn't support UTF-8 in char32_t
literals but it does it regular strings. Still a problem in
MSVC 2022, what a trash fire, can't you just give up on
those codepage insanities already, ffs?! */
#if defined(CORRADE_TARGET_MSVC) && !defined(CORRADE_TARGET_CLANG)
case U'\u011B':
#else
case U'ě':
#endif
return 3;
}
return 0;
}
Vector2 doGlyphSize(UnsignedInt) override { return {}; }
Vector2 doGlyphAdvance(const UnsignedInt glyph) override {
switch(glyph) {
case 0: return {8, 0};
case 1:
case 3: /* e and ě have the same advance */
return {12, 0};
case 2: return {23, 0};
}
CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
bool _opened = false;
};
void MagnumFontConverterTest::exportFont() {
Containers::String confFilename = Utility::Path::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.conf");
Containers::String tgaFilename = Utility::Path::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font.tga");
@ -85,83 +140,102 @@ void MagnumFontConverterTest::exportFont() {
if(Utility::Path::exists(tgaFilename))
CORRADE_VERIFY(Utility::Path::remove(tgaFilename));
/* Fake font with fake cache */
class FakeFont: public Text::AbstractFont {
public:
explicit FakeFont(): _opened(false) {}
private:
void doClose() override { _opened = false; }
bool doIsOpened() const override { return _opened; }
Properties doOpenFile(Containers::StringView, Float) override {
_opened = true;
return {16.0f, 25.0f, -10.0f, 39.7333f, 3};
}
FontFeatures doFeatures() const override { return {}; }
Containers::Pointer<AbstractLayouter> doLayout(const AbstractGlyphCache&, Float, Containers::StringView) override { return nullptr; }
MyFont font;
font.openFile({}, {});
UnsignedInt doGlyphId(const char32_t character) override {
switch(character) {
case 'W': return 2;
case 'e': return 1;
}
struct: AbstractGlyphCache {
using AbstractGlyphCache::AbstractGlyphCache;
return 0;
}
GlyphCacheFeatures doFeatures() const override { return GlyphCacheFeature::ImageDownload; }
void doSetImage(const Vector2i&, const ImageView2D&) override {}
Image2D doImage() override {
return Image2D{PixelFormat::R8Unorm, {8, 4}, Containers::Array<char>{InPlaceInit, {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v'
}}};
}
} cache{{128, 64}, {16, 8}};
/* Override the not found glyph to be in bounds as well */
cache.insert(0, {}, {{16, 8}, {16, 8}});
cache.insert(font.glyphId(U'W'), {25, 34}, {{16, 12}, {24, 56}});
cache.insert(font.glyphId(U'e'), {25, 12}, {{36, 8}, {112, 40}});
/* ě has deliberately the same glyph data as e */
cache.insert(font.glyphId(
/* MSVC (but not clang-cl) doesn't support UTF-8 in char32_t literals
but it does it regular strings. Still a problem in MSVC 2022, what a
trash fire, can't you just give up on those codepage insanities
already, ffs?! */
#if defined(CORRADE_TARGET_MSVC) && !defined(CORRADE_TARGET_CLANG)
U'\u011B'
#else
U'ě'
#endif
), {25, 12}, {{36, 8}, {112, 40}});
Vector2 doGlyphSize(UnsignedInt) override { return {}; }
/* Convert the file */
Containers::Pointer<AbstractFontConverter> converter = _fontConverterManager.instantiate("MagnumFontConverter");
CORRADE_VERIFY(converter->exportFontToFile(font, cache, Utility::Path::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font"), "Waveě"));
Vector2 doGlyphAdvance(const UnsignedInt glyph) override {
switch(glyph) {
case 0: return {8, 0};
case 1: return {12, 0};
case 2: return {23, 0};
}
/* Verify font parameters */
CORRADE_COMPARE_AS(confFilename,
Utility::Path::join(MAGNUMFONT_TEST_DIR, "font.conf"),
TestSuite::Compare::File);
CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
if(!(_importerManager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
!(_importerManager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found, not testing glyph cache contents");
bool _opened;
} font;
/* Verify font image */
CORRADE_COMPARE_WITH(tgaFilename,
Utility::Path::join(MAGNUMFONT_TEST_DIR, "font.tga"),
DebugTools::CompareImageFile{_importerManager});
}
void MagnumFontConverterTest::exportFontEmptyCache() {
Containers::String confFilename = Utility::Path::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font-empty-cache.conf");
Containers::String tgaFilename = Utility::Path::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font-empty-cache.tga");
/* Remove previously created files */
if(Utility::Path::exists(confFilename))
CORRADE_VERIFY(Utility::Path::remove(confFilename));
if(Utility::Path::exists(tgaFilename))
CORRADE_VERIFY(Utility::Path::remove(tgaFilename));
MyFont font;
font.openFile({}, {});
/* Create fake cache */
struct MyCache: AbstractGlyphCache {
explicit MyCache(): AbstractGlyphCache{Vector2i{1536}, Vector2i{24}} {}
struct: AbstractGlyphCache {
using AbstractGlyphCache::AbstractGlyphCache;
GlyphCacheFeatures doFeatures() const override { return GlyphCacheFeature::ImageDownload; }
void doSetImage(const Vector2i&, const ImageView2D&) override {}
Image2D doImage() override {
return Image2D{PixelFormat::R8Unorm, Vector2i{256}, Containers::Array<char>{ValueInit, 256*256}};
return Image2D{PixelFormat::R8Unorm, {8, 4}, Containers::Array<char>{ValueInit, 8*4}};
}
} cache;
cache.insert(font.glyphId(U'W'), {25, 34}, {{0, 8}, {16, 128}});
cache.insert(font.glyphId(U'e'), {25, 12}, {{16, 4}, {64, 32}});
} cache{{8, 4}};
/* Convert the file */
Containers::Pointer<AbstractFontConverter> converter = _fontConverterManager.instantiate("MagnumFontConverter");
CORRADE_VERIFY(converter->exportFontToFile(font, cache, Utility::Path::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font"), "Wave"));
CORRADE_VERIFY(converter->exportFontToFile(font, cache, Utility::Path::join(MAGNUMFONTCONVERTER_TEST_WRITE_DIR, "font-empty-cache"), "Wave"));
/* Verify font parameters */
CORRADE_COMPARE_AS(confFilename,
Utility::Path::join(MAGNUMFONT_TEST_DIR, "font.conf"),
Utility::Path::join(MAGNUMFONTCONVERTER_TEST_DIR, "font-empty-cache.conf"),
TestSuite::Compare::File);
if(!(_importerManager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
CORRADE_SKIP("TgaImporter plugin not enabled, not testing glyph cache contents");
/* Verify font image, no need to test image contents, as the image is
garbage anyway */
Containers::Pointer<Trade::AbstractImporter> importer = _importerManager.instantiate("TgaImporter");
CORRADE_VERIFY(importer->openFile(tgaFilename));
Containers::Optional<Trade::ImageData2D> image = importer->image2D(0);
CORRADE_VERIFY(image);
CORRADE_COMPARE(image->size(), Vector2i(256));
CORRADE_COMPARE(image->format(), PixelFormat::R8Unorm);
if(!(_importerManager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
!(_importerManager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found, not testing glyph cache contents");
/* Verify font image */
CORRADE_COMPARE_WITH(tgaFilename,
Utility::Path::join(MAGNUMFONTCONVERTER_TEST_DIR, "font-empty-cache.tga"),
DebugTools::CompareImageFile{_importerManager});
}
void MagnumFontConverterTest::exportFontNoGlyphCacheImageDownload() {
struct MyFont: AbstractFont {
struct: AbstractFont {
/* Supports neither file nor data opening */
FontFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return false; }
@ -175,7 +249,7 @@ void MagnumFontConverterTest::exportFontNoGlyphCacheImageDownload() {
}
} font;
struct DummyGlyphCache: AbstractGlyphCache {
struct: AbstractGlyphCache {
using AbstractGlyphCache::AbstractGlyphCache;
GlyphCacheFeatures doFeatures() const override { return {}; }

2
src/MagnumPlugins/MagnumFontConverter/Test/configure.h.cmake

@ -25,6 +25,8 @@
#cmakedefine MAGNUMFONTCONVERTER_PLUGIN_FILENAME "${MAGNUMFONTCONVERTER_PLUGIN_FILENAME}"
#cmakedefine TGAIMAGECONVERTER_PLUGIN_FILENAME "${TGAIMAGECONVERTER_PLUGIN_FILENAME}"
#cmakedefine ANYIMAGEIMPORTER_PLUGIN_FILENAME "${ANYIMAGEIMPORTER_PLUGIN_FILENAME}"
#cmakedefine TGAIMPORTER_PLUGIN_FILENAME "${TGAIMPORTER_PLUGIN_FILENAME}"
#define MAGNUMFONTCONVERTER_TEST_DIR "${MAGNUMFONTCONVERTER_TEST_DIR}"
#define MAGNUMFONTCONVERTER_TEST_WRITE_DIR "${MAGNUMFONTCONVERTER_TEST_WRITE_DIR}"
#define MAGNUMFONT_TEST_DIR "${MAGNUMFONT_TEST_DIR}"

24
src/MagnumPlugins/MagnumFontConverter/Test/font-empty-cache.conf

@ -0,0 +1,24 @@
version=1
image=font-empty-cache.tga
originalImageSize=8 4
padding=0 0
fontSize=16
ascent=25
descent=-10
lineHeight=39.7333
[char]
unicode=57
glyph=0
[char]
unicode=61
glyph=0
[char]
unicode=65
glyph=0
[char]
unicode=76
glyph=0
[glyph]
advance=8 0
position=0 0
rectangle=0 0 0 0

BIN
src/MagnumPlugins/MagnumFontConverter/Test/font-empty-cache.tga

Binary file not shown.
Loading…
Cancel
Save