@ -27,14 +27,18 @@
# include <Corrade/Containers/Array.h>
# include <Corrade/Containers/StridedArrayView.h>
# include <Corrade/Containers/StringView.h>
# include <Corrade/Containers/StringStl.h> /** @todo drop once Debug is stream-free */
# include <Corrade/TestSuite/Tester.h>
# include <Corrade/TestSuite/Compare/Container.h>
# include <Corrade/TestSuite/Compare/String.h>
# include <Corrade/Utility/Algorithms.h>
# include <Corrade/Utility/DebugStl.h> /** @todo drop once Debug is stream-free */
# include "Magnum/PixelFormat.h"
# include "Magnum/Text/AbstractFont.h"
# include "Magnum/Text/AbstractGlyphCache.h"
# include "Magnum/Text/AbstractShaper.h"
# include "Magnum/Text/Direction.h"
# include "Magnum/Text/Renderer.h"
namespace Magnum { namespace Text { namespace Test { namespace {
@ -42,6 +46,30 @@ namespace Magnum { namespace Text { namespace Test { namespace {
struct RendererTest : TestSuite : : Tester {
explicit RendererTest ( ) ;
void lineGlyphPositions ( ) ;
void lineGlyphPositionsAliasedViews ( ) ;
void lineGlyphPositionsInvalidViewSizes ( ) ;
void lineGlyphPositionsInvalidDirection ( ) ;
void lineGlyphPositionsNoFontOpened ( ) ;
void lineGlyphQuads ( ) ;
void lineGlyphQuadsAliasedViews ( ) ;
void lineGlyphQuadsInvalidViewSizes ( ) ;
void lineGlyphQuadsNoFontOpened ( ) ;
void lineGlyphQuadsFontNotFoundInCache ( ) ;
void lineGlyphQuads2D ( ) ;
void lineGlyphQuads2DArrayGlyphCache ( ) ;
void alignLine ( ) ;
void alignLineInvalidDirection ( ) ;
void alignBlock ( ) ;
void alignBlockInvalidDirection ( ) ;
template < class T > void glyphQuadIndices ( ) ;
void glyphQuadIndicesTypeTooSmall ( ) ;
void renderData ( ) ;
void multiline ( ) ;
@ -52,6 +80,37 @@ struct RendererTest: TestSuite::Tester {
# endif
} ;
const struct {
const char * name ;
Alignment alignment ;
Float offset ;
} AlignLineData [ ] {
/* The vertical alignment and GlyphBounds has no effect here */
/* Left is the default (0) value, thus should result in no shift */
{ " left " , Alignment : : BottomLeft , - 10.0f } ,
{ " right " , Alignment : : LineRightGlyphBounds , - 13.5f } ,
/* Integral should be handled only for Center */
{ " right, integral " , Alignment : : MiddleRightGlyphBoundsIntegral , - 13.5f } ,
{ " center " , Alignment : : TopCenter , - 11.75f } ,
{ " center, integral " , Alignment : : TopCenterIntegral , - 12.0f } ,
} ;
const struct {
const char * name ;
Alignment alignment ;
Float offset ;
} AlignBlockData [ ] {
/* The horizontal alignment and GlyphBounds has no effect here */
/* Line is the default (0) value, thus should result in no shift */
{ " line " , Alignment : : LineCenterGlyphBounds , 0.0f } ,
{ " bottom " , Alignment : : BottomRight , - 9.5f } ,
{ " top " , Alignment : : TopLeftGlyphBounds , - 19.5f } ,
/* Integral should be handled only for Middle */
{ " top, integral " , Alignment : : TopCenterGlyphBoundsIntegral , - 19.5f } ,
{ " middle " , Alignment : : MiddleLeft , - 14.5f } ,
{ " middle, integral " , Alignment : : MiddleLeftIntegral , - 15.0f }
} ;
const struct {
TestSuite : : TestCaseDescriptionSourceLocation name ;
Alignment alignment ;
@ -189,6 +248,36 @@ const struct {
} ;
RendererTest : : RendererTest ( ) {
addTests ( { & RendererTest : : lineGlyphPositions ,
& RendererTest : : lineGlyphPositionsAliasedViews ,
& RendererTest : : lineGlyphPositionsInvalidViewSizes ,
& RendererTest : : lineGlyphPositionsInvalidDirection ,
& RendererTest : : lineGlyphPositionsNoFontOpened ,
& RendererTest : : lineGlyphQuads ,
& RendererTest : : lineGlyphQuadsAliasedViews ,
& RendererTest : : lineGlyphQuadsInvalidViewSizes ,
& RendererTest : : lineGlyphQuadsNoFontOpened ,
& RendererTest : : lineGlyphQuadsFontNotFoundInCache ,
& RendererTest : : lineGlyphQuads2D ,
& RendererTest : : lineGlyphQuads2DArrayGlyphCache } ) ;
addInstancedTests ( { & RendererTest : : alignLine } ,
Containers : : arraySize ( AlignLineData ) ) ;
addTests ( { & RendererTest : : alignLineInvalidDirection } ) ;
addInstancedTests ( { & RendererTest : : alignBlock } ,
Containers : : arraySize ( AlignBlockData ) ) ;
addTests ( { & RendererTest : : alignBlockInvalidDirection ,
& RendererTest : : glyphQuadIndices < UnsignedInt > ,
& RendererTest : : glyphQuadIndices < UnsignedShort > ,
& RendererTest : : glyphQuadIndices < UnsignedByte > ,
& RendererTest : : glyphQuadIndicesTypeTooSmall } ) ;
addInstancedTests ( { & RendererTest : : renderData } ,
Containers : : arraySize ( RenderDataData ) ) ;
@ -271,6 +360,494 @@ DummyGlyphCache testGlyphCache(AbstractFont& font) {
return cache ;
}
DummyGlyphCache testGlyphCacheArray ( AbstractFont & font ) {
DummyGlyphCache cache { PixelFormat : : R8Unorm , { 20 , 20 , 3 } } ;
/* Add one more font to verify the right one gets picked */
cache . addFont ( 96 ) ;
UnsignedInt fontId = cache . addFont ( font . glyphCount ( ) , & font ) ;
/* Three glyphs, covering bottom, top left and top right of the cache */
cache . addGlyph ( fontId , 3 , { 5 , 10 } , 2 , { { } , { 20 , 10 } } ) ;
cache . addGlyph ( fontId , 7 , { 10 , 5 } , 0 , { { 0 , 10 } , { 10 , 20 } } ) ;
cache . addGlyph ( fontId , 9 , { 5 , 5 } , 1 , { { 10 , 10 } , { 20 , 20 } } ) ;
return cache ;
}
void RendererTest : : lineGlyphPositions ( ) {
TestFont font ;
font . openFile ( { } , 2.5f ) ;
Vector2 glyphOffsets [ ] {
{ 0.2f , - 0.4f } ,
{ 0.4f , 0.8f } ,
{ - 0.2f , 0.4f } ,
} ;
Vector2 glyphAdvances [ ] {
{ 1.0f , 0.0f } ,
{ 2.0f , 0.2f } ,
{ 3.0f , - 0.2f }
} ;
Vector2 cursor { 100.0f , 200.0f } ;
/* The font is opened at 2.5, rendering at 1.25, so everything will be
scaled by 0.5 */
Vector2 glyphPositions [ 3 ] ;
Range2D rectangle = renderLineGlyphPositionsInto ( font , 1.25f , LayoutDirection : : HorizontalTopToBottom , glyphOffsets , glyphAdvances , cursor , glyphPositions ) ;
/* The rectangle contains the cursor range and descent to ascent */
CORRADE_COMPARE ( rectangle , ( Range2D { { 100.0f , 198.75f } , { 103.0f , 202.25 } } ) ) ;
CORRADE_COMPARE ( cursor , ( Vector2 { 103.0f , 200.0f } ) ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( glyphPositions ) , Containers : : arrayView < Vector2 > ( {
{ 100.1f , 199.8f } ,
{ 100.7f , 200.4f } ,
{ 101.4f , 200.3f }
} ) , TestSuite : : Compare : : Container ) ;
}
void RendererTest : : lineGlyphPositionsAliasedViews ( ) {
/* Like lineGlyphPositions(), but with the input data stored in the output
array . The internals should be written in a way that doesn ' t overwrite
the input before it ' s read . */
TestFont font ;
font . openFile ( { } , 2.5f ) ;
Vector2 glyphOffsetsPositions [ ] {
{ 0.2f , - 0.4f } ,
{ 0.4f , 0.8f } ,
{ - 0.2f , 0.4f } ,
} ;
Vector2 glyphAdvances [ ] {
{ 1.0f , 0.0f } ,
{ 2.0f , 0.2f } ,
{ 3.0f , - 0.2f }
} ;
Vector2 cursor { 100.0f , 200.0f } ;
Range2D rectangle = renderLineGlyphPositionsInto ( font , 1.25f , LayoutDirection : : HorizontalTopToBottom , glyphOffsetsPositions , glyphAdvances , cursor , glyphOffsetsPositions ) ;
CORRADE_COMPARE ( rectangle , ( Range2D { { 100.0f , 198.75f } , { 103.0f , 202.25 } } ) ) ;
CORRADE_COMPARE ( cursor , ( Vector2 { 103.0f , 200.0f } ) ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( glyphOffsetsPositions ) , Containers : : arrayView < Vector2 > ( {
{ 100.1f , 199.8f } ,
{ 100.7f , 200.4f } ,
{ 101.4f , 200.3f }
} ) , TestSuite : : Compare : : Container ) ;
}
void RendererTest : : lineGlyphPositionsInvalidViewSizes ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
TestFont font ;
Vector2 data [ 5 ] ;
Vector2 dataInvalid [ 4 ] ;
Vector2 cursor ;
std : : ostringstream out ;
Error redirectError { & out } ;
renderLineGlyphPositionsInto ( font , 10.0f , LayoutDirection : : HorizontalTopToBottom , data , data , cursor , dataInvalid ) ;
renderLineGlyphPositionsInto ( font , 10.0f , LayoutDirection : : HorizontalTopToBottom , data , dataInvalid , cursor , data ) ;
renderLineGlyphPositionsInto ( font , 10.0f , LayoutDirection : : HorizontalTopToBottom , dataInvalid , data , cursor , data ) ;
CORRADE_COMPARE ( out . str ( ) ,
" Text::renderLineGlyphPositionsInto(): expected glyphOffsets, glyphAdvances and output views to have the same size, got 5, 5 and 4 \n "
" Text::renderLineGlyphPositionsInto(): expected glyphOffsets, glyphAdvances and output views to have the same size, got 5, 4 and 5 \n "
" Text::renderLineGlyphPositionsInto(): expected glyphOffsets, glyphAdvances and output views to have the same size, got 4, 5 and 5 \n " ) ;
}
void RendererTest : : lineGlyphPositionsInvalidDirection ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
TestFont font ;
Vector2 cursor ;
std : : ostringstream out ;
Error redirectError { & out } ;
renderLineGlyphPositionsInto ( font , 10.0f , LayoutDirection : : VerticalLeftToRight , { } , { } , cursor , { } ) ;
CORRADE_COMPARE ( out . str ( ) , " Text::renderLineGlyphPositionsInto(): only Text::LayoutDirection::HorizontalTopToBottom is supported right now, got Text::LayoutDirection::VerticalLeftToRight \n " ) ;
}
void RendererTest : : lineGlyphPositionsNoFontOpened ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
TestFont font ;
Vector2 cursor ;
std : : ostringstream out ;
Error redirectError { & out } ;
renderLineGlyphPositionsInto ( font , 10.0f , LayoutDirection : : HorizontalTopToBottom , { } , { } , cursor , { } ) ;
CORRADE_COMPARE ( out . str ( ) , " Text::renderLineGlyphPositionsInto(): no font opened \n " ) ;
}
void RendererTest : : lineGlyphQuads ( ) {
TestFont font ;
font . openFile ( { } , 2.5f ) ;
DummyGlyphCache cache = testGlyphCacheArray ( font ) ;
Vector2 glyphPositions [ ] {
{ 100.0f , 200.0f } ,
{ 103.0f , 202.0f } ,
{ 107.0f , 196.0f }
} ;
UnsignedInt glyphIds [ ] {
3 , 7 , 9
} ;
Vector2 positions [ 3 * 4 ] ;
Vector3 textureCoordinates [ 3 * 4 ] ;
/* The font is opened at 2.5, rendering at 1.25, so everything will be
scaled by 0.5 */
Range2D rectangle = renderGlyphQuadsInto ( font , 1.25f , cache , glyphPositions , glyphIds , positions , textureCoordinates ) ;
CORRADE_COMPARE ( rectangle , ( Range2D { { 102.5f , 198.5f } , { 114.5f , 210.0f } } ) ) ;
/* 2---3
| |
0 - - - 1 */
CORRADE_COMPARE_AS ( Containers : : arrayView ( positions ) , Containers : : arrayView < Vector2 > ( {
{ 102.5f , 205.0f } , /* Offset {5, 10}, size {20, 10}, scaled by 0.5 */
{ 112.5f , 205.0f } ,
{ 102.5f , 210.0f } ,
{ 112.5f , 210.0f } ,
{ 108.0f , 204.5f } , /* Offset {10, 5}, size {10, 10}, scaled by 0.5 */
{ 113.0f , 204.5f } ,
{ 108.0f , 209.5f } ,
{ 113.0f , 209.5f } ,
{ 109.5f , 198.5f } , /* Offset {5, 5}, size {10, 10}, scaled by 0.5 */
{ 114.5f , 198.5f } ,
{ 109.5f , 203.5f } ,
{ 114.5f , 203.5f } ,
} ) , TestSuite : : Compare : : Container ) ;
/* First glyph is bottom, second top left, third top right; layer is
different for each .
+ - + - +
| b | c |
2 - - - 3
| a |
0 - - - 1 */
CORRADE_COMPARE_AS ( Containers : : arrayView ( textureCoordinates ) , Containers : : arrayView < Vector3 > ( {
{ 0.0f , 0.0f , 2.0f } ,
{ 1.0f , 0.0f , 2.0f } ,
{ 0.0f , 0.5f , 2.0f } ,
{ 1.0f , 0.5f , 2.0f } ,
{ 0.0f , 0.5f , 0.0f } ,
{ 0.5f , 0.5f , 0.0f } ,
{ 0.0f , 1.0f , 0.0f } ,
{ 0.5f , 1.0f , 0.0f } ,
{ 0.5f , 0.5f , 1.0f } ,
{ 1.0f , 0.5f , 1.0f } ,
{ 0.5f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f } ,
} ) , TestSuite : : Compare : : Container ) ;
}
void RendererTest : : lineGlyphQuadsAliasedViews ( ) {
/* Like lineGlyphPositions(), but with the input data stored in the output
array . The internals should be written in a way that doesn ' t overwrite
the input before it ' s read . */
TestFont font ;
font . openFile ( { } , 2.5f ) ;
DummyGlyphCache cache = testGlyphCacheArray ( font ) ;
Vector2 positions [ 3 * 4 ] ;
Vector3 textureCoordinates [ 3 * 4 ] ;
Containers : : StridedArrayView1D < Vector2 > glyphPositions = Containers : : stridedArrayView ( positions ) . every ( 4 ) ;
Utility : : copy ( {
{ 100.0f , 200.0f } ,
{ 103.0f , 202.0f } ,
{ 107.0f , 196.0f }
} , glyphPositions ) ;
Containers : : StridedArrayView1D < UnsignedInt > glyphIds = Containers : : arrayCast < UnsignedInt > ( Containers : : stridedArrayView ( textureCoordinates ) . every ( 4 ) ) ;
Utility : : copy ( {
3 , 7 , 9
} , glyphIds ) ;
Range2D rectangle = renderGlyphQuadsInto ( font , 1.25f , cache , glyphPositions , glyphIds , positions , textureCoordinates ) ;
CORRADE_COMPARE ( rectangle , ( Range2D { { 102.5f , 198.5f } , { 114.5f , 210.0f } } ) ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( positions ) , Containers : : arrayView < Vector2 > ( {
{ 102.5f , 205.0f } ,
{ 112.5f , 205.0f } ,
{ 102.5f , 210.0f } ,
{ 112.5f , 210.0f } ,
{ 108.0f , 204.5f } ,
{ 113.0f , 204.5f } ,
{ 108.0f , 209.5f } ,
{ 113.0f , 209.5f } ,
{ 109.5f , 198.5f } ,
{ 114.5f , 198.5f } ,
{ 109.5f , 203.5f } ,
{ 114.5f , 203.5f } ,
} ) , TestSuite : : Compare : : Container ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( textureCoordinates ) , Containers : : arrayView < Vector3 > ( {
{ 0.0f , 0.0f , 2.0f } ,
{ 1.0f , 0.0f , 2.0f } ,
{ 0.0f , 0.5f , 2.0f } ,
{ 1.0f , 0.5f , 2.0f } ,
{ 0.0f , 0.5f , 0.0f } ,
{ 0.5f , 0.5f , 0.0f } ,
{ 0.0f , 1.0f , 0.0f } ,
{ 0.5f , 1.0f , 0.0f } ,
{ 0.5f , 0.5f , 1.0f } ,
{ 1.0f , 0.5f , 1.0f } ,
{ 0.5f , 1.0f , 1.0f } ,
{ 1.0f , 1.0f , 1.0f } ,
} ) , TestSuite : : Compare : : Container ) ;
}
void RendererTest : : lineGlyphQuadsInvalidViewSizes ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
TestFont font ;
DummyGlyphCache cache { PixelFormat : : R8Unorm , { 20 , 20 } } ;
Vector2 glyphPositions [ 4 ] ;
Vector2 glyphPositionsInvalid [ 5 ] ;
UnsignedInt glyphIds [ 4 ] ;
UnsignedInt glyphIdsInvalid [ 3 ] ;
Vector2 positions [ 16 ] ;
Vector2 positionsInvalid [ 15 ] ;
Vector3 textureCoordinates [ 16 ] ;
Vector3 textureCoordinatesInvalid [ 17 ] ;
std : : ostringstream out ;
Error redirectError { & out } ;
renderGlyphQuadsInto ( font , 10.0f , cache , glyphPositions , glyphIdsInvalid , positions , textureCoordinates ) ;
renderGlyphQuadsInto ( font , 10.0f , cache , glyphPositionsInvalid , glyphIds , positions , textureCoordinates ) ;
renderGlyphQuadsInto ( font , 10.0f , cache , glyphPositions , glyphIds , positions , textureCoordinatesInvalid ) ;
renderGlyphQuadsInto ( font , 10.0f , cache , glyphPositions , glyphIds , positionsInvalid , textureCoordinates ) ;
CORRADE_COMPARE_AS ( out . str ( ) ,
" Text::renderGlyphQuadsInto(): expected glyphIds and glyphPositions views to have the same size, got 3 and 4 \n "
" Text::renderGlyphQuadsInto(): expected glyphIds and glyphPositions views to have the same size, got 4 and 5 \n "
" Text::renderGlyphQuadsInto(): expected vertexPositions and vertexTextureCoordinates views to have 16 elements, got 16 and 17 \n "
" Text::renderGlyphQuadsInto(): expected vertexPositions and vertexTextureCoordinates views to have 16 elements, got 15 and 16 \n " ,
TestSuite : : Compare : : String ) ;
}
void RendererTest : : lineGlyphQuadsNoFontOpened ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
TestFont font ;
DummyGlyphCache cache { PixelFormat : : R8Unorm , { 20 , 20 } } ;
std : : ostringstream out ;
Error redirectError { & out } ;
renderGlyphQuadsInto ( font , 10.0f , cache , nullptr , nullptr , nullptr , Containers : : StridedArrayView1D < Vector3 > { } ) ;
CORRADE_COMPARE ( out . str ( ) , " Text::renderGlyphQuadsInto(): no font opened \n " ) ;
}
void RendererTest : : lineGlyphQuadsFontNotFoundInCache ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
TestFont font ;
font . openFile ( { } , 0.5f ) ;
DummyGlyphCache cache { PixelFormat : : R8Unorm , { 20 , 20 } } ;
cache . addFont ( 56 ) ;
cache . addFont ( 13 ) ;
std : : ostringstream out ;
Error redirectError { & out } ;
renderGlyphQuadsInto ( font , 10.0f , cache , nullptr , nullptr , nullptr , Containers : : StridedArrayView1D < Vector3 > { } ) ;
CORRADE_COMPARE ( out . str ( ) , " Text::renderGlyphQuadsInto(): font not found among 2 fonts in passed glyph cache \n " ) ;
}
void RendererTest : : lineGlyphQuads2D ( ) {
/* Like lineGlyphPositions(), but with just a 2D glyph cache and using the
three - component overload . */
TestFont font ;
font . openFile ( { } , 2.5f ) ;
DummyGlyphCache cache = testGlyphCache ( font ) ;
Vector2 glyphPositions [ ] {
{ 100.0f , 200.0f } ,
{ 103.0f , 202.0f } ,
{ 107.0f , 196.0f }
} ;
UnsignedInt glyphIds [ ] {
3 , 7 , 9
} ;
Vector2 positions [ 3 * 4 ] ;
Vector2 textureCoordinates [ 3 * 4 ] ;
Range2D rectangle = renderGlyphQuadsInto ( font , 1.25f , cache , glyphPositions , glyphIds , positions , textureCoordinates ) ;
CORRADE_COMPARE ( rectangle , ( Range2D { { 102.5f , 198.5f } , { 114.5f , 210.0f } } ) ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( positions ) , Containers : : arrayView < Vector2 > ( {
{ 102.5f , 205.0f } ,
{ 112.5f , 205.0f } ,
{ 102.5f , 210.0f } ,
{ 112.5f , 210.0f } ,
{ 108.0f , 204.5f } ,
{ 113.0f , 204.5f } ,
{ 108.0f , 209.5f } ,
{ 113.0f , 209.5f } ,
{ 109.5f , 198.5f } ,
{ 114.5f , 198.5f } ,
{ 109.5f , 203.5f } ,
{ 114.5f , 203.5f } ,
} ) , TestSuite : : Compare : : Container ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( textureCoordinates ) , Containers : : arrayView < Vector2 > ( {
{ 0.0f , 0.0f } ,
{ 1.0f , 0.0f } ,
{ 0.0f , 0.5f } ,
{ 1.0f , 0.5f } ,
{ 0.0f , 0.5f } ,
{ 0.5f , 0.5f } ,
{ 0.0f , 1.0f } ,
{ 0.5f , 1.0f } ,
{ 0.5f , 0.5f } ,
{ 1.0f , 0.5f } ,
{ 0.5f , 1.0f } ,
{ 1.0f , 1.0f } ,
} ) , TestSuite : : Compare : : Container ) ;
}
void RendererTest : : lineGlyphQuads2DArrayGlyphCache ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
TestFont font ;
struct : AbstractGlyphCache {
using AbstractGlyphCache : : AbstractGlyphCache ;
GlyphCacheFeatures doFeatures ( ) const override { return { } ; }
} cache { PixelFormat : : R8Unorm , { 20 , 20 , 2 } } ;
std : : ostringstream out ;
Error redirectError { & out } ;
renderGlyphQuadsInto ( font , 10.0f , cache , nullptr , nullptr , nullptr , Containers : : StridedArrayView1D < Vector2 > { } ) ;
CORRADE_COMPARE ( out . str ( ) , " Text::renderGlyphQuadsInto(): can't use this overload with an array glyph cache \n " ) ;
}
void RendererTest : : alignLine ( ) {
auto & & data = AlignLineData [ testCaseInstanceId ( ) ] ;
setTestCaseDescription ( data . name ) ;
Range2D rectangle { { 10.0f , 200.0f } , { 13.5f , - 960.0f } } ;
/* The positions aren't taken into account, so they can be arbitrary */
Vector2 positions [ ] {
{ 100.0f , 200.0f } ,
{ 300.0f , - 60.0f } ,
{ - 10.0f , 100.0f } ,
} ;
Range2D alignedRectangle = alignRenderedLine ( rectangle , LayoutDirection : : HorizontalTopToBottom , data . alignment , positions ) ;
CORRADE_COMPARE ( alignedRectangle , rectangle . translated ( { data . offset , 0.0f } ) ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( positions ) , Containers : : arrayView < Vector2 > ( {
{ 100.0f + data . offset , 200.0f } ,
{ 300.0f + data . offset , - 60.0f } ,
{ - 10.0f + data . offset , 100.0f }
} ) , TestSuite : : Compare : : Container ) ;
}
void RendererTest : : alignLineInvalidDirection ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
std : : ostringstream out ;
Error redirectError { & out } ;
alignRenderedLine ( { } , LayoutDirection : : VerticalRightToLeft , Alignment : : LineLeft , nullptr ) ;
CORRADE_COMPARE ( out . str ( ) , " Text::alignRenderedLine(): only Text::LayoutDirection::HorizontalTopToBottom is supported right now, got Text::LayoutDirection::VerticalRightToLeft \n " ) ;
}
void RendererTest : : alignBlock ( ) {
auto & & data = AlignBlockData [ testCaseInstanceId ( ) ] ;
setTestCaseDescription ( data . name ) ;
Range2D rectangle { { 100.0f , 9.5f } , { - 70.0f , 19.5f } } ;
/* The positions aren't taken into account, so they can be arbitrary */
Vector2 positions [ ] {
{ 100.0f , 200.0f } ,
{ - 10.0f , 100.0f } ,
{ 300.0f , - 60.0f } ,
} ;
Range2D alignedRectangle = alignRenderedBlock ( rectangle , LayoutDirection : : HorizontalTopToBottom , data . alignment , positions ) ;
CORRADE_COMPARE ( alignedRectangle , rectangle . translated ( { 0.0f , data . offset } ) ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( positions ) , Containers : : arrayView < Vector2 > ( {
{ 100.0f , 200.0f + data . offset } ,
{ - 10.0f , 100.0f + data . offset } ,
{ 300.0f , - 60.0f + data . offset } ,
} ) , TestSuite : : Compare : : Container ) ;
}
void RendererTest : : alignBlockInvalidDirection ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
std : : ostringstream out ;
Error redirectError { & out } ;
alignRenderedBlock ( { } , LayoutDirection : : VerticalRightToLeft , Alignment : : LineLeft , nullptr ) ;
CORRADE_COMPARE ( out . str ( ) , " Text::alignRenderedBlock(): only Text::LayoutDirection::HorizontalTopToBottom is supported right now, got Text::LayoutDirection::VerticalRightToLeft \n " ) ;
}
template < class T > void RendererTest : : glyphQuadIndices ( ) {
setTestCaseTemplateName ( Math : : TypeTraits < T > : : name ( ) ) ;
/* 2---3 2 3---5
| | | \ \ |
| | | \ \ |
| | | \ \ |
0 - - - 1 0 - - - 1 4 */
T indices [ 3 * 6 ] ;
renderGlyphQuadIndicesInto ( 60 , indices ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( indices ) , Containers : : arrayView < T > ( {
240 , 241 , 242 , 242 , 241 , 243 ,
244 , 245 , 246 , 246 , 245 , 247 ,
248 , 249 , 250 , 250 , 249 , 251
} ) , TestSuite : : Compare : : Container ) ;
}
void RendererTest : : glyphQuadIndicesTypeTooSmall ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
/* This should be fine */
UnsignedByte indices8 [ 18 ] ;
UnsignedShort indices16 [ 18 ] ;
UnsignedInt indices32 [ 18 ] ;
renderGlyphQuadIndicesInto ( 256 / 4 - 3 , indices8 ) ;
renderGlyphQuadIndicesInto ( 65536 / 4 - 3 , indices16 ) ;
renderGlyphQuadIndicesInto ( 4294967296u / 4 - 3 , indices32 ) ;
CORRADE_COMPARE ( indices8 [ 17 ] , 255 ) ;
CORRADE_COMPARE ( indices16 [ 17 ] , 65535 ) ;
CORRADE_COMPARE ( indices32 [ 17 ] , 4294967295 ) ;
/* Empty view also */
renderGlyphQuadIndicesInto ( 256 / 4 , Containers : : ArrayView < UnsignedByte > { } ) ;
renderGlyphQuadIndicesInto ( 65536 / 4 , Containers : : ArrayView < UnsignedShort > { } ) ;
renderGlyphQuadIndicesInto ( 4294967296u / 4 , Containers : : ArrayView < UnsignedInt > { } ) ;
std : : ostringstream out ;
Error redirectError { & out } ;
renderGlyphQuadIndicesInto ( 256 / 4 - 3 + 1 , indices8 ) ;
renderGlyphQuadIndicesInto ( 65536 / 4 - 3 + 1 , indices16 ) ;
renderGlyphQuadIndicesInto ( 4294967296u / 4 - 3 + 1 , indices32 ) ;
/* Should assert even if there's actually no indices to write */
renderGlyphQuadIndicesInto ( 256 / 4 + 1 , Containers : : ArrayView < UnsignedByte > { } ) ;
renderGlyphQuadIndicesInto ( 65536 / 4 + 1 , Containers : : ArrayView < UnsignedShort > { } ) ;
renderGlyphQuadIndicesInto ( 4294967296u / 4 + 1 , Containers : : ArrayView < UnsignedInt > { } ) ;
CORRADE_COMPARE ( out . str ( ) ,
" Text::renderGlyphQuadIndicesInto(): max index value of 259 cannot fit into a 8-bit type \n "
" Text::renderGlyphQuadIndicesInto(): max index value of 65539 cannot fit into a 16-bit type \n "
" Text::renderGlyphQuadIndicesInto(): max index value of 4294967299 cannot fit into a 32-bit type \n "
" Text::renderGlyphQuadIndicesInto(): max index value of 259 cannot fit into a 8-bit type \n "
" Text::renderGlyphQuadIndicesInto(): max index value of 65539 cannot fit into a 16-bit type \n "
" Text::renderGlyphQuadIndicesInto(): max index value of 4294967299 cannot fit into a 32-bit type \n " ) ;
}
void RendererTest : : renderData ( ) {
auto & & data = RenderDataData [ testCaseInstanceId ( ) ] ;
setTestCaseDescription ( data . name ) ;
@ -301,32 +878,32 @@ void RendererTest::renderData() {
+ - +
+ - + | c |
0 - - - 2 | b | + - +
2 - - - 3 | b | + - +
| a | + - +
1 - - - 3 */
0 - - - 1 */
CORRADE_COMPARE_AS ( positions , ( std : : vector < Vector2 > {
/* Cursor is {0, 0}. Offset from the cache is {5, 10}, offset from the
renderer is { 0 , 1 } , size is { 20 , 10 } ; all scaled by 0.5 */
Vector2 { 2.5f , 10.5f } + data . offset ,
Vector2 { 2.5f , 5.5f } + data . offset ,
Vector2 { 12.5f , 10.5f } + data . offset ,
Vector2 { 12.5f , 5.5f } + data . offset ,
Vector2 { 2.5f , 10.5f } + data . offset ,
Vector2 { 12.5f , 10.5f } + data . offset ,
/* Advance was {1, 0.5}, cursor is {1, 0.5}. Offset from the cache is
{ 10 , 5 } , offset from the renderer is { 0 , 2 } , size is { 10 , 10 } ; all
scaled by 0.5 */
Vector2 { 5.5f , 8.75f } + data . offset ,
Vector2 { 5.5f , 3.75f } + data . offset ,
Vector2 { 10.5f , 8.75f } + data . offset ,
Vector2 { 10.5f , 3.75f } + data . offset ,
Vector2 { 5.5f , 8.75f } + data . offset ,
Vector2 { 10.5f , 8.75f } + data . offset ,
/* Advance was {2, -0.5}, cursor is {3, 0}. Offset from the cache is
{ 5 , 5 } , offset from the renderer is { 0 , 3 } , size is { 10 , 10 } ; all
scaled by 0.5 */
Vector2 { 4.0f , 9.0f } + data . offset ,
Vector2 { 4.0f , 4.0f } + data . offset ,
Vector2 { 9.0f , 4.0f } + data . offset ,
Vector2 { 4.0f , 9.0f } + data . offset ,
Vector2 { 9.0f , 9.0f } + data . offset ,
Vector2 { 9.0f , 4.0f } + data . offset
} ) , TestSuite : : Compare : : Container ) ;
/* Bounds. Different depending on whether or not GlyphBounds alignment is
@ -340,36 +917,36 @@ void RendererTest::renderData() {
right .
+ - + - +
| b | c |
0 - - - 2
2 - - - 3
| a |
1 - - - 3 */
0 - - - 1 */
CORRADE_COMPARE_AS ( textureCoordinates , ( std : : vector < Vector2 > {
{ 0.0f , 0.5f } ,
{ 0.0f , 0.0f } ,
{ 1.0f , 0.5f } ,
{ 1.0f , 0.0f } ,
{ 0.0f , 0.5f } ,
{ 1.0f , 0.5f } ,
{ 0.0f , 1.0f } ,
{ 0.0f , 0.5f } ,
{ 0.5f , 1.0f } ,
{ 0.5f , 0.5f } ,
{ 0.0f , 1.0f } ,
{ 0.5f , 1.0f } ,
{ 0.5f , 0.5f } ,
{ 1.0f , 0.5f } ,
{ 0.5f , 1.0f } ,
{ 1.0f , 1.0f } ,
{ 1.0f , 0.5f }
} ) , TestSuite : : Compare : : Container ) ;
/* Indices
0 - - - 2 0 - - - 2 5
| | | / / |
| | | / / |
| | | / / |
1 - - - 3 1 3 - - - 4 */
2 - - - 3 2 3 - - - 5
| | | \ \ |
| | | \ \ |
| | | \ \ |
0 - - - 1 0 - - - 1 4 */
CORRADE_COMPARE_AS ( indices , ( std : : vector < UnsignedInt > {
0 , 1 , 2 , 1 , 3 , 2 ,
4 , 5 , 6 , 5 , 7 , 6 ,
8 , 9 , 10 , 9 , 11 , 10
0 , 1 , 2 , 2 , 1 , 3 ,
4 , 5 , 6 , 6 , 5 , 7 ,
8 , 9 , 10 , 10 , 9 , 11 ,
} ) , TestSuite : : Compare : : Container ) ;
}
@ -449,70 +1026,70 @@ void RendererTest::multiline() {
[ g ] [ h ] [ i ] */
CORRADE_COMPARE_AS ( positions , ( std : : vector < Vector2 > {
Vector2 { 0.0f , 1.0f } + data . offset0 , /* a */
Vector2 { 0.0f , 0.0f } + data . offset0 ,
Vector2 { 1.0f , 1.0f } + data . offset0 ,
Vector2 { 0.0f , 0.0f } + data . offset0 , /* a */
Vector2 { 1.0f , 0.0f } + data . offset0 ,
Vector2 { 0.0f , 1.0f } + data . offset0 ,
Vector2 { 1.0f , 1.0f } + data . offset0 ,
Vector2 { 2.0f , 1.0f } + data . offset0 , /* b */
Vector2 { 2.0f , 0.0f } + data . offset0 ,
Vector2 { 3.0f , 1.0f } + data . offset0 ,
Vector2 { 2.0f , 0.0f } + data . offset0 , /* b */
Vector2 { 3.0f , 0.0f } + data . offset0 ,
Vector2 { 2.0f , 1.0f } + data . offset0 ,
Vector2 { 3.0f , 1.0f } + data . offset0 ,
Vector2 { 4.0f , 1.0f } + data . offset0 , /* c */
Vector2 { 4.0f , 0.0f } + data . offset0 ,
Vector2 { 5.0f , 1.0f } + data . offset0 ,
Vector2 { 4.0f , 0.0f } + data . offset0 , /* c */
Vector2 { 5.0f , 0.0f } + data . offset0 ,
Vector2 { 4.0f , 1.0f } + data . offset0 ,
Vector2 { 5.0f , 1.0f } + data . offset0 ,
Vector2 { 6.0f , 1.0f } + data . offset0 , /* d */
Vector2 { 6.0f , 0.0f } + data . offset0 ,
Vector2 { 7.0f , 1.0f } + data . offset0 ,
Vector2 { 6.0f , 0.0f } + data . offset0 , /* d */
Vector2 { 7.0f , 0.0f } + data . offset0 ,
Vector2 { 6.0f , 1.0f } + data . offset0 ,
Vector2 { 7.0f , 1.0f } + data . offset0 ,
Vector2 { 0.0f , 1.0f } + data . offset1 , /* e */
Vector2 { 0.0f , 0.0f } + data . offset1 ,
Vector2 { 1.0f , 1.0f } + data . offset1 ,
Vector2 { 0.0f , 0.0f } + data . offset1 , /* e */
Vector2 { 1.0f , 0.0f } + data . offset1 ,
Vector2 { 0.0f , 1.0f } + data . offset1 ,
Vector2 { 1.0f , 1.0f } + data . offset1 ,
Vector2 { 2.0f , 1.0f } + data . offset1 , /* f */
Vector2 { 2.0f , 0.0f } + data . offset1 ,
Vector2 { 3.0f , 1.0f } + data . offset1 ,
Vector2 { 2.0f , 0.0f } + data . offset1 , /* f */
Vector2 { 3.0f , 0.0f } + data . offset1 ,
Vector2 { 2.0f , 1.0f } + data . offset1 ,
Vector2 { 3.0f , 1.0f } + data . offset1 ,
/* Two linebreaks here */
Vector2 { 0.0f , 1.0f } + data . offset2 , /* g */
Vector2 { 0.0f , 0.0f } + data . offset2 ,
Vector2 { 1.0f , 1.0f } + data . offset2 ,
Vector2 { 0.0f , 0.0f } + data . offset2 , /* g */
Vector2 { 1.0f , 0.0f } + data . offset2 ,
Vector2 { 0.0f , 1.0f } + data . offset2 ,
Vector2 { 1.0f , 1.0f } + data . offset2 ,
Vector2 { 2.0f , 1.0f } + data . offset2 , /* h */
Vector2 { 2.0f , 0.0f } + data . offset2 ,
Vector2 { 3.0f , 1.0f } + data . offset2 ,
Vector2 { 2.0f , 0.0f } + data . offset2 , /* h */
Vector2 { 3.0f , 0.0f } + data . offset2 ,
Vector2 { 2.0f , 1.0f } + data . offset2 ,
Vector2 { 3.0f , 1.0f } + data . offset2 ,
Vector2 { 4.0f , 1.0f } + data . offset2 , /* i */
Vector2 { 4.0f , 0.0f } + data . offset2 ,
Vector2 { 5.0f , 1.0f } + data . offset2 ,
Vector2 { 4.0f , 0.0f } + data . offset2 , /* i */
Vector2 { 5.0f , 0.0f } + data . offset2 ,
Vector2 { 4.0f , 1.0f } + data . offset2 ,
Vector2 { 5.0f , 1.0f } + data . offset2 ,
} ) , TestSuite : : Compare : : Container ) ;
/* Indices
0 - - - 2 0 - - - 2 5
| | | / / |
| | | / / |
| | | / / |
1 - - - 3 1 3 - - - 4 */
2 - - - 3 2 3 - - - 5
| | | \ \ |
| | | \ \ |
| | | \ \ |
0 - - - 1 0 - - - 1 4 */
CORRADE_COMPARE_AS ( indices , ( std : : vector < UnsignedInt > {
0 , 1 , 2 , 1 , 3 , 2 ,
4 , 5 , 6 , 5 , 7 , 6 ,
8 , 9 , 10 , 9 , 11 , 10 ,
12 , 13 , 14 , 13 , 15 , 14 ,
16 , 17 , 18 , 17 , 19 , 18 ,
20 , 21 , 22 , 21 , 23 , 22 ,
24 , 25 , 26 , 25 , 27 , 26 ,
28 , 29 , 30 , 29 , 31 , 30 ,
32 , 33 , 34 , 33 , 35 , 34
0 , 1 , 2 , 2 , 1 , 3 ,
4 , 5 , 6 , 6 , 5 , 7 ,
8 , 9 , 10 , 10 , 9 , 11 ,
12 , 13 , 14 , 14 , 1 3 , 15 ,
16 , 17 , 18 , 18 , 1 7 , 19 ,
20 , 21 , 22 , 22 , 2 1 , 23 ,
24 , 25 , 26 , 26 , 2 5 , 27 ,
28 , 29 , 30 , 30 , 29 , 31 ,
32 , 33 , 34 , 34 , 3 3 , 35 ,
} ) , TestSuite : : Compare : : Container ) ;
}