/*
This file is part of Magnum .
Copyright © 2010 , 2011 , 2012 , 2013 , 2014 , 2015 , 2016 , 2017 , 2018 , 2019 ,
2020 , 2021 , 2022 , 2023 Vladimír Vondruš < mosra @ centrum . cz >
Permission is hereby granted , free of charge , to any person obtaining a
copy of this software and associated documentation files ( the " Software " ) ,
to deal in the Software without restriction , including without limitation
the rights to use , copy , modify , merge , publish , distribute , sublicense ,
and / or sell copies of the Software , and to permit persons to whom the
Software is furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE .
*/
# include <sstream>
# include <vector>
# include <Corrade/Containers/Array.h>
# include <Corrade/Containers/StridedBitArrayView.h>
# include <Corrade/Containers/Pair.h>
# include <Corrade/Containers/StridedArrayView.h>
# include <Corrade/Containers/StringStl.h> /** @todo remove 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/DebugStl.h>
# include <Corrade/Utility/FormatStl.h>
# include "Magnum/Math/Range.h"
# include "Magnum/TextureTools/Atlas.h"
namespace Magnum { namespace TextureTools { namespace Test { namespace {
struct AtlasTest : TestSuite : : Tester {
explicit AtlasTest ( ) ;
void debugLandfillFlag ( ) ;
void debugLandfillFlags ( ) ;
void landfillFullFit ( ) ;
void landfill ( ) ;
void landfillIncremental ( ) ;
void landfillNoFit ( ) ;
void landfillCopy ( ) ;
void landfillMove ( ) ;
void landfillArrayFullFit ( ) ;
void landfillArray ( ) ;
void landfillArrayIncremental ( ) ;
void landfillArrayNoFit ( ) ;
void landfillArrayCopy ( ) ;
void landfillArrayMove ( ) ;
void landfillInvalidSize ( ) ;
void landfillSetFlagsInvalid ( ) ;
void landfillAddMissingRotations ( ) ;
void landfillAddInvalidViewSizes ( ) ;
void landfillAddTooLargeElement ( ) ;
void basic ( ) ;
void padding ( ) ;
void empty ( ) ;
void tooSmall ( ) ;
void arrayPowerOfTwoEmpty ( ) ;
void arrayPowerOfTwoSingleElement ( ) ;
void arrayPowerOfTwoAllSameElements ( ) ;
void arrayPowerOfTwoOneLayer ( ) ;
void arrayPowerOfTwoMoreLayers ( ) ;
void arrayPowerOfTwoInvalidViewSizes ( ) ;
void arrayPowerOfTwoWrongLayerSize ( ) ;
void arrayPowerOfTwoWrongSize ( ) ;
# ifdef MAGNUM_BUILD_DEPRECATED
void arrayPowerOfTwoDeprecated ( ) ;
# endif
} ;
const Vector2i LandfillSizes [ ] {
{ 3 , 6 } , /* 0 */
{ 2 , 5 } , /* 1 */
{ 4 , 2 } , /* 2 */
{ 3 , 3 } , /* 3 */
{ 2 , 3 } , /* 4 */
{ 3 , 3 } , /* 5 */
{ 2 , 2 } , /* 6 */
{ 2 , 1 } , /* 7 */
{ 2 , 2 } , /* 8 */
{ 2 , 2 } , /* 9 */
{ 2 , 1 } , /* a */
{ 1 , 2 } , /* b */
{ 1 , 1 } , /* c */
} ;
const struct {
const char * name ;
AtlasLandfillFlags flags ;
Vector2i size ;
Vector2i filledSize ;
Containers : : Pair < Vector2i , bool > offsetsFlips [ Containers : : arraySize ( LandfillSizes ) ] ;
} LandfillData [ ] {
/* In all of these, rectangles with the same size should keep their order.
5 after 3 , 9 after 8 after 6 ( and b after a after 7 if they ' re rotated
to the same orientation ) */
{ " no rotation, no width sorting " , { } , { 11 , 12 } , { 11 , 10 } , {
/* 99b
99 b77
8866 aac
88662222
000 2222555
00011 555
00011 555
0001133344
0001133344
0001133344 */
{ { 0 , 0 } , false } , /* 0 */
{ { 3 , 0 } , false } , /* 1 */
{ { 4 , 5 } , false } , /* 2 */
{ { 5 , 0 } , false } , /* 3 */
{ { 8 , 0 } , false } , /* 4 */
{ { 8 , 3 } , false } , /* 5 */
{ { 2 , 6 } , false } , /* 6 */
{ { 3 , 8 } , false } , /* 7 */
{ { 0 , 6 } , false } , /* 8 */
{ { 0 , 8 } , false } , /* 9 */
{ { 5 , 7 } , false } , /* a */
{ { 2 , 8 } , false } , /* b */
{ { 7 , 7 } , false } } } , /* c */
/* No rotation with width sorting omitted, not interesting */
{ " portrait, no width sorting " , AtlasLandfillFlag : : RotatePortrait , { 11 , 12 } , { 11 , 10 } , {
/* 99a
99 ab
88 bc
88766555
00076655544
00011 55544
0001122 44
0001122333
0001122333
0001122333 */
{ { 0 , 0 } , false } , /* 0 */
{ { 3 , 0 } , false } , /* 1 */
{ { 5 , 0 } , true } , /* 2 */
{ { 7 , 0 } , false } , /* 3 */
{ { 9 , 3 } , false } , /* 4 */
{ { 6 , 4 } , false } , /* 5 */
{ { 4 , 5 } , false } , /* 6 */
{ { 3 , 5 } , true } , /* 7 */
{ { 1 , 6 } , false } , /* 8 */
{ { 0 , 8 } , false } , /* 9 */
{ { 2 , 8 } , true } , /* a */
{ { 3 , 7 } , false } , /* b */
{ { 4 , 7 } , false } } } , /* c */
{ " portrait, widest first " , AtlasLandfillFlag : : RotatePortrait | AtlasLandfillFlag : : WidestFirst , { 11 , 12 } , { 11 , 10 } , {
/* 7ab
7 abc
9988
99886644
000 6644555
00011 44555
0001122 555
0001122333
0001122333
0001122333 */
{ { 0 , 0 } , false } , /* 0 */
{ { 3 , 0 } , false } , /* 1 */
{ { 5 , 0 } , true } , /* 2 */
{ { 7 , 0 } , false } , /* 3 */
{ { 6 , 4 } , false } , /* 4 */
{ { 8 , 3 } , false } , /* 5 */
{ { 4 , 5 } , false } , /* 6 */
{ { 0 , 8 } , true } , /* 7 */
{ { 2 , 6 } , false } , /* 8 */
{ { 0 , 6 } , false } , /* 9 */
{ { 1 , 8 } , true } , /* a */
{ { 2 , 8 } , false } , /* b */
{ { 3 , 8 } , false } } } , /* c */
{ " portrait, widest first, unbounded height " , AtlasLandfillFlag : : RotatePortrait | AtlasLandfillFlag : : WidestFirst , { 11 , 0 } , { 11 , 10 } , {
/* Should have the same result as above
7 ab
7 abc
9988
99886644
000 6644555
00011 44555
0001122 555
0001122333
0001122333
0001122333 */
{ { 0 , 0 } , false } , /* 0 */
{ { 3 , 0 } , false } , /* 1 */
{ { 5 , 0 } , true } , /* 2 */
{ { 7 , 0 } , false } , /* 3 */
{ { 6 , 4 } , false } , /* 4 */
{ { 8 , 3 } , false } , /* 5 */
{ { 4 , 5 } , false } , /* 6 */
{ { 0 , 8 } , true } , /* 7 */
{ { 2 , 6 } , false } , /* 8 */
{ { 0 , 6 } , false } , /* 9 */
{ { 1 , 8 } , true } , /* a */
{ { 2 , 8 } , false } , /* b */
{ { 3 , 8 } , false } } } , /* c */
{ " portrait, narrowest first " , AtlasLandfillFlag : : RotatePortrait | AtlasLandfillFlag : : NarrowestFirst , { 11 , 12 } , { 11 , 10 } , {
/* 8899
8899
66 b c
66 ba7555
000 a7555333
00011555333
0001122 333
000112244
000112244
000112244 */
{ { 0 , 0 } , false } , /* 0 */
{ { 3 , 0 } , false } , /* 1 */
{ { 5 , 0 } , true } , /* 2 */
{ { 8 , 3 } , false } , /* 3 */
{ { 7 , 0 } , false } , /* 4 */
{ { 5 , 4 } , false } , /* 5 */
{ { 0 , 6 } , false } , /* 6 */
{ { 4 , 5 } , true } , /* 7 */
{ { 0 , 8 } , false } , /* 8 */
{ { 2 , 8 } , false } , /* 9 */
{ { 3 , 5 } , true } , /* a */
{ { 2 , 6 } , false } , /* b */
{ { 4 , 7 } , false } } } , /* c */
{ " landscape, no width sorting " , AtlasLandfillFlag : : RotateLandscape , { 11 , 12 } , { 11 , 10 } , {
/* 99
7799
cbbaa6688
22224446688
2222444 555
11111555
11111555
000000333
000000333
000000333 */
{ { 0 , 0 } , true } , /* 0 */
{ { 3 , 3 } , true } , /* 1 */
{ { 0 , 5 } , false } , /* 2 */
{ { 6 , 0 } , false } , /* 3 */
{ { 4 , 5 } , true } , /* 4 */
{ { 8 , 3 } , false } , /* 5 */
{ { 7 , 6 } , false } , /* 6 */
{ { 7 , 8 } , false } , /* 7 */
{ { 9 , 6 } , false } , /* 8 */
{ { 9 , 8 } , false } , /* 9 */
{ { 5 , 7 } , false } , /* a */
{ { 3 , 7 } , true } , /* b */
{ { 2 , 7 } , false } } } , /* c */
{ " landscape, widest first " , AtlasLandfillFlag : : RotateLandscape | AtlasLandfillFlag : : WidestFirst , { 11 , 12 } , { 11 , 10 } , {
/* No change compared to "no width sorting" in this case
99
7799
cbbaa6688
22224446688
2222444 555
11111555
11111555
000000333
000000333
000000333 */
{ { 0 , 0 } , true } , /* 0 */
{ { 3 , 3 } , true } , /* 1 */
{ { 0 , 5 } , false } , /* 2 */
{ { 6 , 0 } , false } , /* 3 */
{ { 4 , 5 } , true } , /* 4 */
{ { 8 , 3 } , false } , /* 5 */
{ { 7 , 6 } , false } , /* 6 */
{ { 7 , 8 } , false } , /* 7 */
{ { 9 , 6 } , false } , /* 8 */
{ { 9 , 8 } , false } , /* 9 */
{ { 5 , 7 } , false } , /* a */
{ { 3 , 7 } , true } , /* b */
{ { 2 , 7 } , false } } } , /* c */
{ " landscape, narrowest first " , AtlasLandfillFlag : : RotateLandscape | AtlasLandfillFlag : : NarrowestFirst , { 11 , 12 } , { 11 , 10 } , {
/* 11111
bb c11111
aa772222
994442222
99444000000
8866000000
8866000000
333555
333555
333555 */
{ { 5 , 3 } , true } , /* 0 */
{ { 6 , 8 } , true } , /* 1 */
{ { 5 , 6 } , false } , /* 2 */
{ { 0 , 0 } , false } , /* 3 */
{ { 2 , 5 } , true } , /* 4 */
{ { 3 , 0 } , false } , /* 5 */
{ { 3 , 3 } , false } , /* 6 */
{ { 3 , 7 } , false } , /* 7 */
{ { 1 , 3 } , false } , /* 8 */
{ { 0 , 5 } , false } , /* 9 */
{ { 1 , 7 } , false } , /* a */
{ { 0 , 8 } , true } , /* b */
{ { 5 , 8 } , false } } } , /* c */
} ;
const Vector2i LandfillArraySizes [ ] {
{ 3 , 6 } , /* 0 */
{ 2 , 5 } , /* 1 */
{ 4 , 2 } , /* 2 */
{ 3 , 3 } , /* 3 */
{ 3 , 3 } , /* 4 */
{ 2 , 2 } , /* 5 */
{ 2 , 2 } , /* 6 */
{ 2 , 1 } , /* 7 */
{ 2 , 2 } , /* 8 */
{ 2 , 2 } , /* 9 */
} ;
const struct {
const char * name ;
AtlasLandfillFlags flags ;
Vector3i size ;
Vector3i filledSize ;
Containers : : Pair < Vector3i , bool > offsetsFlips [ Containers : : arraySize ( LandfillArraySizes ) ] ;
} LandfillArrayData [ ] {
/* Various sorting aspects are tested in landfill() already, this just
checks the array - specific behaviors and the rotation - less overload */
{ " no rotation " , { } , { 11 , 6 , 3 } , { 11 , 6 , 2 } , {
/* 000
00011552222
00011552222
00011333444
00011333444 668899
00011333444 66889977 */
{ { 0 , 0 , 0 } , false } , /* 0 */
{ { 3 , 0 , 0 } , false } , /* 1 */
{ { 7 , 3 , 0 } , false } , /* 2 */
{ { 5 , 0 , 0 } , false } , /* 3 */
{ { 8 , 0 , 0 } , false } , /* 4 */
{ { 5 , 3 , 0 } , false } , /* 5 */
{ { 0 , 0 , 1 } , false } , /* 6 */
{ { 6 , 0 , 1 } , false } , /* 7 */
{ { 2 , 0 , 1 } , false } , /* 8 */
{ { 4 , 0 , 1 } , false } } } , /* 9 */
{ " portrait, widest first " , AtlasLandfillFlag : : RotatePortrait | AtlasLandfillFlag : : WidestFirst , { 11 , 6 , 3 } , { 11 , 6 , 2 } , {
/* 000 55444
00011 55444
0001122 444
0001122333
0001122333 6688997
0001122333 6688997 */
{ { 0 , 0 , 0 } , false } , /* 0 */
{ { 3 , 0 , 0 } , false } , /* 1 */
{ { 5 , 0 , 0 } , true } , /* 2 */
{ { 7 , 0 , 0 } , false } , /* 3 */
{ { 8 , 3 , 0 } , false } , /* 4 */
{ { 6 , 4 , 0 } , false } , /* 5 */
{ { 0 , 0 , 1 } , false } , /* 6 */
{ { 6 , 0 , 1 } , true } , /* 7 */
{ { 2 , 0 , 1 } , false } , /* 8 */
{ { 4 , 0 , 1 } , false } } } , /* 9 */
{ " portrait, widest first, unbounded " , AtlasLandfillFlag : : RotatePortrait | AtlasLandfillFlag : : WidestFirst , { 11 , 6 , 3 } , { 11 , 6 , 2 } , {
/* Should have the same result as above
000 55444
00011 55444
0001122 444
0001122333
0001122333 6688997
0001122333 6688997 */
{ { 0 , 0 , 0 } , false } , /* 0 */
{ { 3 , 0 , 0 } , false } , /* 1 */
{ { 5 , 0 , 0 } , true } , /* 2 */
{ { 7 , 0 , 0 } , false } , /* 3 */
{ { 8 , 3 , 0 } , false } , /* 4 */
{ { 6 , 4 , 0 } , false } , /* 5 */
{ { 0 , 0 , 1 } , false } , /* 6 */
{ { 6 , 0 , 1 } , true } , /* 7 */
{ { 2 , 0 , 1 } , false } , /* 8 */
{ { 4 , 0 , 1 } , false } } } , /* 9 */
} ;
/* Could make order[15] and then Containers::arraySize(), but then it won't
work on MSVC2015 and cause overly complicated code elsewhere */
constexpr std : : size_t ArrayPowerOfTwoOneLayerImageCount = 15 ;
const struct {
const char * name ;
std : : size_t order [ ArrayPowerOfTwoOneLayerImageCount ] ;
} ArrayPowerOfTwoOneLayerData [ ] {
{ " sorted " ,
{ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 } } ,
{ " " ,
/* Because there are duplicate sizes, the shuffling needs to preserve
the original order of duplicates to match the output */
{ 0 , 2 , 7 , 13 , 11 , 3 , 4 , 5 , 8 , 14 , 1 , 9 , 6 , 12 , 10 } } ,
} ;
const struct {
const char * name ;
Vector2i size ;
const char * message ;
} ArrayPowerOfTwoWrongLayerSizeData [ ] {
{ " non-power-of-two " , { 128 , 127 } , " {128, 127} " } ,
{ " non-square " , { 128 , 256 } , " {128, 256} " } ,
{ " zero " , { 1024 , 0 } , " {1024, 0} " } ,
} ;
const struct {
const char * name ;
Vector2i size ;
const char * message ;
} ArrayPowerOfTwoWrongSizeData [ ] {
{ " larger than size " , { 512 , 512 } , " {512, 512} " } ,
{ " non-power-of-two " , { 128 , 127 } , " {128, 127} " } ,
{ " non-square " , { 128 , 256 } , " {128, 256} " } ,
{ " zero " , { 1024 , 0 } , " {1024, 0} " } ,
} ;
AtlasTest : : AtlasTest ( ) {
addTests ( { & AtlasTest : : debugLandfillFlag ,
& AtlasTest : : debugLandfillFlags ,
& AtlasTest : : landfillFullFit } ) ;
addInstancedTests ( { & AtlasTest : : landfill } ,
Containers : : arraySize ( LandfillData ) ) ;
addTests ( { & AtlasTest : : landfillIncremental ,
& AtlasTest : : landfillNoFit ,
& AtlasTest : : landfillCopy ,
& AtlasTest : : landfillMove ,
& AtlasTest : : landfillArrayFullFit } ) ;
addInstancedTests ( { & AtlasTest : : landfillArray } ,
Containers : : arraySize ( LandfillArrayData ) ) ;
addTests ( { & AtlasTest : : landfillArrayIncremental ,
& AtlasTest : : landfillArrayNoFit ,
& AtlasTest : : landfillArrayCopy ,
& AtlasTest : : landfillArrayMove ,
& AtlasTest : : landfillInvalidSize ,
& AtlasTest : : landfillSetFlagsInvalid ,
& AtlasTest : : landfillAddMissingRotations ,
& AtlasTest : : landfillAddInvalidViewSizes ,
& AtlasTest : : landfillAddTooLargeElement ,
& AtlasTest : : basic ,
& AtlasTest : : padding ,
& AtlasTest : : empty ,
& AtlasTest : : tooSmall ,
& AtlasTest : : arrayPowerOfTwoEmpty ,
& AtlasTest : : arrayPowerOfTwoSingleElement ,
& AtlasTest : : arrayPowerOfTwoAllSameElements } ) ;
addInstancedTests ( { & AtlasTest : : arrayPowerOfTwoOneLayer } ,
Containers : : arraySize ( ArrayPowerOfTwoOneLayerData ) ) ;
addTests ( { & AtlasTest : : arrayPowerOfTwoMoreLayers ,
& AtlasTest : : arrayPowerOfTwoInvalidViewSizes } ) ;
addInstancedTests ( { & AtlasTest : : arrayPowerOfTwoWrongLayerSize } ,
Containers : : arraySize ( ArrayPowerOfTwoWrongLayerSizeData ) ) ;
addInstancedTests ( { & AtlasTest : : arrayPowerOfTwoWrongSize } ,
Containers : : arraySize ( ArrayPowerOfTwoWrongSizeData ) ) ;
# ifdef MAGNUM_BUILD_DEPRECATED
addTests ( { & AtlasTest : : arrayPowerOfTwoDeprecated } ) ;
# endif
}
void AtlasTest : : debugLandfillFlag ( ) {
std : : ostringstream out ;
Debug { & out } < < AtlasLandfillFlag : : RotatePortrait < < AtlasLandfillFlag ( 0xcafedead ) ;
CORRADE_COMPARE ( out . str ( ) , " TextureTools::AtlasLandfillFlag::RotatePortrait TextureTools::AtlasLandfillFlag(0xcafedead) \n " ) ;
}
void AtlasTest : : debugLandfillFlags ( ) {
std : : ostringstream out ;
Debug { & out } < < ( AtlasLandfillFlag : : RotateLandscape | AtlasLandfillFlag : : NarrowestFirst | AtlasLandfillFlag ( 0xdead0000 ) ) < < AtlasLandfillFlags { } ;
CORRADE_COMPARE ( out . str ( ) , " TextureTools::AtlasLandfillFlag::RotateLandscape|TextureTools::AtlasLandfillFlag::NarrowestFirst|TextureTools::AtlasLandfillFlag(0xdead0000) TextureTools::AtlasLandfillFlags{} \n " ) ;
}
void AtlasTest : : landfillFullFit ( ) {
/* Trivial case to verify there are no off-by-one errors that would prevent
a tight fit */
AtlasLandfill atlas { { 4 , 6 } } ;
CORRADE_COMPARE ( atlas . size ( ) , ( Vector2i { 4 , 6 } ) ) ;
CORRADE_COMPARE ( atlas . filledSize ( ) , ( Vector2i { 4 , 0 } ) ) ;
CORRADE_COMPARE ( atlas . flags ( ) , AtlasLandfillFlag : : RotatePortrait | AtlasLandfillFlag : : WidestFirst ) ;
Vector2i offsets [ 4 ] ;
UnsignedByte rotationData [ 1 ] ;
Containers : : MutableBitArrayView rotations { rotationData , 0 , 4 } ;
/* Testing the init list overload here as all others test the view */
CORRADE_VERIFY ( atlas . add ( {
{ 2 , 4 } , /* 0 */
{ 2 , 3 } , /* 1 */
{ 2 , 3 } , /* 2 */
{ 2 , 2 } , /* 3 */
} , offsets , rotations ) ) ;
CORRADE_COMPARE ( atlas . filledSize ( ) , ( Vector2i { 4 , 6 } ) ) ;
CORRADE_COMPARE_AS ( rotations , Containers : : stridedArrayView ( {
false , false , false , false
} ) . sliceBit ( 0 ) , TestSuite : : Compare : : Container ) ;
/* 3322
3322
0022
0011
0011
0011 */
CORRADE_COMPARE_AS ( Containers : : arrayView ( offsets ) , Containers : : arrayView < Vector2i > ( {
{ 0 , 0 } , /* 0 */
{ 2 , 0 } , /* 1 */
{ 2 , 3 } , /* 2 */
{ 0 , 4 } , /* 3 */
} ) , TestSuite : : Compare : : Container ) ;
}
void AtlasTest : : landfill ( ) {
auto & & data = LandfillData [ testCaseInstanceId ( ) ] ;
setTestCaseDescription ( data . name ) ;
AtlasLandfill atlas { data . size } ;
/* For unbounded sizes it should return 0 again */
CORRADE_COMPARE ( atlas . size ( ) , data . size ) ;
Vector2i offsets [ Containers : : arraySize ( LandfillSizes ) ] ;
/* In case rotations aren't enabled, this isn't zero-initialized by
add ( ) */
UnsignedByte rotationData [ 2 ] { } ;
Containers : : MutableBitArrayView rotations { rotationData , 0 , Containers : : arraySize ( LandfillSizes ) } ;
atlas . setFlags ( data . flags ) ;
/* Test the rotations-less overload if no rotations are enabled */
if ( ! ( data . flags & ( AtlasLandfillFlag : : RotatePortrait | AtlasLandfillFlag : : RotateLandscape ) ) )
CORRADE_VERIFY ( atlas . add ( LandfillSizes , offsets ) ) ;
else
CORRADE_VERIFY ( atlas . add ( LandfillSizes , offsets , rotations ) ) ;
CORRADE_COMPARE ( atlas . filledSize ( ) , data . filledSize ) ;
CORRADE_COMPARE_AS ( rotations ,
Containers : : stridedArrayView ( data . offsetsFlips )
. slice ( & Containers : : Pair < Vector2i , bool > : : second )
. sliceBit ( 0 ) ,
TestSuite : : Compare : : Container ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( offsets ) ,
Containers : : stridedArrayView ( data . offsetsFlips )
. slice ( & Containers : : Pair < Vector2i , bool > : : first ) ,
TestSuite : : Compare : : Container ) ;
}
void AtlasTest : : landfillIncremental ( ) {
/* Same as landfill(portrait, widest first) (which is the default flags)
but with the data split into three parts ( 0 to 4 , 5 to 8 , 9 to c ) , and
shuffled to verify the sort works as it should */
Vector2i sizeData [ ] {
{ 4 , 2 } , /* 0, rotated */
{ 3 , 6 } , /* 1 */
{ 3 , 3 } , /* 2 */
{ 5 , 2 } , /* 3, rotated */
{ 3 , 3 } , /* 4 */
{ 2 , 2 } , /* 5 */
{ 2 , 2 } , /* 6 */
{ 2 , 2 } , /* 7 */
{ 3 , 2 } , /* 8, rotated */
{ 1 , 1 } , /* 9 */
{ 1 , 2 } , /* a */
{ 2 , 1 } , /* b, rotated */
{ 1 , 2 } , /* c */
} ;
auto sizes = Containers : : arrayView ( sizeData ) ;
Vector2i offsetData [ Containers : : arraySize ( sizeData ) ] ;
auto offsets = Containers : : arrayView ( offsetData ) ;
UnsignedByte rotationData [ 2 ] ;
Containers : : MutableBitArrayView rotations { rotationData , 0 , Containers : : arraySize ( sizeData ) } ;
AtlasLandfill atlas { { 11 , 10 } } ;
CORRADE_COMPARE ( atlas . filledSize ( ) , ( Vector2i { 11 , 0 } ) ) ;
CORRADE_VERIFY ( atlas . add (
sizes . prefix ( 5 ) ,
offsets . prefix ( 5 ) ,
rotations . prefix ( 5 ) ) ) ;
CORRADE_COMPARE ( atlas . filledSize ( ) , ( Vector2i { 11 , 6 } ) ) ;
CORRADE_VERIFY ( atlas . add (
sizes . slice ( 5 , 9 ) ,
offsets . slice ( 5 , 9 ) ,
rotations . slice ( 5 , 9 ) ) ) ;
CORRADE_COMPARE ( atlas . filledSize ( ) , ( Vector2i { 11 , 8 } ) ) ;
CORRADE_VERIFY ( atlas . add (
sizes . exceptPrefix ( 9 ) ,
offsets . exceptPrefix ( 9 ) ,
rotations . exceptPrefix ( 9 ) ) ) ;
CORRADE_COMPARE ( atlas . filledSize ( ) , ( Vector2i { 11 , 10 } ) ) ;
CORRADE_COMPARE_AS ( rotations , Containers : : stridedArrayView ( {
true , false , false , true , false , false , false , false , true , false ,
false , true , false
} ) . sliceBit ( 0 ) , TestSuite : : Compare : : Container ) ;
/* abc
abc9
7766
77665588
111 5588444
11133 88444
1113300 444
1113300222
1113300222
1113300222 */
CORRADE_COMPARE_AS ( offsets , Containers : : arrayView < Vector2i > ( {
{ 5 , 0 } , /* 0 */
{ 0 , 0 } , /* 1 */
{ 7 , 0 } , /* 2 */
{ 3 , 0 } , /* 3 */
{ 8 , 3 } , /* 4 */
{ 4 , 5 } , /* 5 */
{ 2 , 6 } , /* 6 */
{ 0 , 6 } , /* 7 */
{ 6 , 4 } , /* 8 */
{ 3 , 8 } , /* 9 */
{ 0 , 8 } , /* a */
{ 1 , 8 } , /* b */
{ 2 , 8 } , /* c */
} ) , TestSuite : : Compare : : Container ) ;
}
void AtlasTest : : landfillNoFit ( ) {
/* Same as landfill(portrait, widest first) (which is the default flags)
which fits into { 11 , 10 } but limiting height to 9 */
AtlasLandfill atlas { { 11 , 9 } } ;
Vector2i offsets [ Containers : : arraySize ( LandfillSizes ) ] ;
UnsignedByte rotationData [ 2 ] ;
Containers : : MutableBitArrayView rotations { rotationData , 0 , Containers : : arraySize ( LandfillSizes ) } ;
CORRADE_VERIFY ( ! atlas . add ( LandfillSizes , offsets , rotations ) ) ;
}
void AtlasTest : : landfillCopy ( ) {
CORRADE_VERIFY ( ! std : : is_copy_constructible < AtlasLandfill > { } ) ;
CORRADE_VERIFY ( ! std : : is_copy_assignable < AtlasLandfill > { } ) ;
}
void AtlasTest : : landfillMove ( ) {
AtlasLandfill a { { 16 , 24 } } ;
Vector2i offsets [ 2 ] ;
UnsignedByte rotations [ 1 ] ;
CORRADE_VERIFY ( a . add ( { { 15 , 17 } , { 2 , 3 } } , offsets , Containers : : MutableBitArrayView { rotations , 0 , 2 } ) ) ;
AtlasLandfill b = Utility : : move ( a ) ;
CORRADE_COMPARE ( b . size ( ) , ( Vector2i { 16 , 24 } ) ) ;
CORRADE_COMPARE ( b . filledSize ( ) , ( Vector2i { 16 , 20 } ) ) ;
AtlasLandfill c { { 16 , 12 } } ;
c = Utility : : move ( b ) ;
CORRADE_COMPARE ( c . size ( ) , ( Vector2i { 16 , 24 } ) ) ;
CORRADE_COMPARE ( c . filledSize ( ) , ( Vector2i { 16 , 20 } ) ) ;
CORRADE_VERIFY ( std : : is_nothrow_move_constructible < AtlasLandfill > : : value ) ;
CORRADE_VERIFY ( std : : is_nothrow_move_assignable < AtlasLandfill > : : value ) ;
}
void AtlasTest : : landfillArrayFullFit ( ) {
/* Trivial case to verify there are no off-by-one errors that would prevent
a tight fit */
AtlasLandfillArray atlas { { 4 , 5 , 2 } } ;
CORRADE_COMPARE ( atlas . size ( ) , ( Vector3i { 4 , 5 , 2 } ) ) ;
CORRADE_COMPARE ( atlas . filledSize ( ) , ( Vector3i { 4 , 5 , 0 } ) ) ;
CORRADE_COMPARE ( atlas . flags ( ) , AtlasLandfillFlag : : RotatePortrait | AtlasLandfillFlag : : WidestFirst ) ;
Vector3i offsets [ 6 ] ;
UnsignedByte rotationData [ 1 ] ;
Containers : : MutableBitArrayView rotations { rotationData , 0 , 6 } ;
/* Testing the init list overload as all others test the view */
CORRADE_VERIFY ( atlas . add ( {
{ 3 , 5 } , /* 0 */
{ 1 , 5 } , /* 1 */
{ 3 , 3 } , /* 2 */
{ 1 , 3 } , /* 3 */
{ 2 , 2 } , /* 4 */
{ 2 , 2 } , /* 5 */
} , offsets , rotations ) ) ;
CORRADE_COMPARE ( atlas . filledSize ( ) , ( Vector3i { 4 , 5 , 2 } ) ) ;
CORRADE_COMPARE_AS ( rotations , Containers : : stridedArrayView ( {
false , false , false , false , false , false
} ) . sliceBit ( 0 ) , TestSuite : : Compare : : Container ) ;
/* 0001 5544
0001 5544
0001 2223
0001 2223
0001 2223 */
CORRADE_COMPARE_AS ( Containers : : arrayView ( offsets ) , Containers : : arrayView < Vector3i > ( {
{ 0 , 0 , 0 } , /* 0 */
{ 3 , 0 , 0 } , /* 1 */
{ 0 , 0 , 1 } , /* 2 */
{ 3 , 0 , 1 } , /* 3 */
{ 2 , 3 , 1 } , /* 4 */
{ 0 , 3 , 1 } , /* 5 */
} ) , TestSuite : : Compare : : Container ) ;
}
void AtlasTest : : landfillArray ( ) {
auto & & data = LandfillArrayData [ testCaseInstanceId ( ) ] ;
setTestCaseDescription ( data . name ) ;
AtlasLandfillArray atlas { data . size } ;
/* For unbounded sizes it should return 0 again */
CORRADE_COMPARE ( atlas . size ( ) , data . size ) ;
Vector3i offsets [ Containers : : arraySize ( LandfillArraySizes ) ] ;
/* In case rotations aren't enabled, this isn't zero-initialized by
add ( ) */
UnsignedByte rotationData [ 2 ] { } ;
Containers : : MutableBitArrayView rotations { rotationData , 0 , Containers : : arraySize ( LandfillArraySizes ) } ;
atlas . setFlags ( data . flags ) ;
/* Test the rotations-less overload if no rotations are enabled */
if ( ! ( data . flags & ( AtlasLandfillFlag : : RotatePortrait | AtlasLandfillFlag : : RotateLandscape ) ) )
CORRADE_VERIFY ( atlas . add ( LandfillArraySizes , offsets ) ) ;
else
CORRADE_VERIFY ( atlas . add ( LandfillArraySizes , offsets , rotations ) ) ;
CORRADE_COMPARE ( atlas . filledSize ( ) , data . filledSize ) ;
CORRADE_COMPARE_AS ( rotations ,
Containers : : stridedArrayView ( data . offsetsFlips )
. slice ( & Containers : : Pair < Vector3i , bool > : : second )
. sliceBit ( 0 ) ,
TestSuite : : Compare : : Container ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( offsets ) ,
Containers : : stridedArrayView ( data . offsetsFlips )
. slice ( & Containers : : Pair < Vector3i , bool > : : first ) ,
TestSuite : : Compare : : Container ) ;
}
void AtlasTest : : landfillArrayIncremental ( ) {
/* 000 55444
00011 55444
0001122 444
0001122333
0001122333 6688997
0001122333 6688997 */
Vector2i sizeData [ ] {
{ 4 , 2 } , /* 0, rotated */
{ 3 , 6 } , /* 1 */
{ 3 , 3 } , /* 2 */
{ 5 , 2 } , /* 3, rotated */
{ 2 , 2 } , /* 4 */
{ 2 , 2 } , /* 5 */
{ 3 , 3 } , /* 6 */
{ 2 , 2 } , /* 7 */
{ 2 , 1 } , /* 8, rotated */
{ 2 , 2 } , /* 9 */
} ;
auto sizes = Containers : : arrayView ( sizeData ) ;
Vector3i offsetData [ Containers : : arraySize ( sizeData ) ] ;
auto offsets = Containers : : arrayView ( offsetData ) ;
UnsignedByte rotationData [ 2 ] ;
Containers : : MutableBitArrayView rotations { rotationData , 0 , Containers : : arraySize ( sizeData ) } ;
AtlasLandfillArray atlas { { 11 , 6 , 2 } } ;
CORRADE_COMPARE ( atlas . filledSize ( ) , ( Vector3i { 11 , 6 , 0 } ) ) ;
CORRADE_VERIFY ( atlas . add (
sizes . prefix ( 4 ) ,
offsets . prefix ( 4 ) ,
rotations . prefix ( 4 ) ) ) ;
CORRADE_COMPARE ( atlas . filledSize ( ) , ( Vector3i { 11 , 6 , 1 } ) ) ;
CORRADE_VERIFY ( atlas . add (
sizes . slice ( 4 , 7 ) ,
offsets . slice ( 4 , 7 ) ,
rotations . slice ( 4 , 7 ) ) ) ;
CORRADE_COMPARE ( atlas . filledSize ( ) , ( Vector3i { 11 , 6 , 2 } ) ) ;
CORRADE_VERIFY ( atlas . add (
sizes . exceptPrefix ( 7 ) ,
offsets . exceptPrefix ( 7 ) ,
rotations . exceptPrefix ( 7 ) ) ) ;
CORRADE_COMPARE ( atlas . filledSize ( ) , ( Vector3i { 11 , 6 , 2 } ) ) ;
CORRADE_COMPARE_AS ( rotations , Containers : : stridedArrayView ( {
true , false , false , true , false , false , false , false , true , false
} ) . sliceBit ( 0 ) , TestSuite : : Compare : : Container ) ;
/* 111 44666
11133 44666
1113300 666
1113300222
1113300222 5577998
1113300222 5577998 */
CORRADE_COMPARE_AS ( offsets , Containers : : arrayView < Vector3i > ( {
{ 5 , 0 , 0 } , /* 0 */
{ 0 , 0 , 0 } , /* 1 */
{ 7 , 0 , 0 } , /* 2 */
{ 3 , 0 , 0 } , /* 3 */
{ 6 , 4 , 0 } , /* 4 */
{ 0 , 0 , 1 } , /* 5 */
{ 8 , 3 , 0 } , /* 6 */
{ 2 , 0 , 1 } , /* 7 */
{ 6 , 0 , 1 } , /* 8 */
{ 4 , 0 , 1 } , /* 9 */
} ) , TestSuite : : Compare : : Container ) ;
}
void AtlasTest : : landfillArrayNoFit ( ) {
/* Same as landfillArray(portrait, widest first) (which is the default
flags ) which fits into { 11 , 6 , 2 } but limiting depth to 1 */
AtlasLandfillArray atlas { { 11 , 6 , 1 } } ;
Vector3i offsets [ Containers : : arraySize ( LandfillArraySizes ) ] ;
UnsignedByte rotationData [ 2 ] ;
Containers : : MutableBitArrayView rotations { rotationData , 0 , Containers : : arraySize ( LandfillArraySizes ) } ;
CORRADE_VERIFY ( ! atlas . add ( LandfillArraySizes , offsets , rotations ) ) ;
}
void AtlasTest : : landfillArrayCopy ( ) {
CORRADE_VERIFY ( ! std : : is_copy_constructible < AtlasLandfillArray > { } ) ;
CORRADE_VERIFY ( ! std : : is_copy_assignable < AtlasLandfillArray > { } ) ;
}
void AtlasTest : : landfillArrayMove ( ) {
AtlasLandfillArray a { { 16 , 24 , 8 } } ;
Vector3i offsets [ 2 ] ;
UnsignedByte rotations [ 1 ] ;
CORRADE_VERIFY ( a . add ( { { 12 , 17 } , { 5 , 12 } } , offsets , Containers : : MutableBitArrayView { rotations , 0 , 2 } ) ) ;
AtlasLandfillArray b = Utility : : move ( a ) ;
CORRADE_COMPARE ( b . size ( ) , ( Vector3i { 16 , 24 , 8 } ) ) ;
CORRADE_COMPARE ( b . filledSize ( ) , ( Vector3i { 16 , 24 , 2 } ) ) ;
AtlasLandfillArray c { { 16 , 12 , 1 } } ;
c = Utility : : move ( b ) ;
CORRADE_COMPARE ( c . size ( ) , ( Vector3i { 16 , 24 , 8 } ) ) ;
CORRADE_COMPARE ( c . filledSize ( ) , ( Vector3i { 16 , 24 , 2 } ) ) ;
CORRADE_VERIFY ( std : : is_nothrow_move_constructible < AtlasLandfillArray > : : value ) ;
CORRADE_VERIFY ( std : : is_nothrow_move_assignable < AtlasLandfillArray > : : value ) ;
}
void AtlasTest : : landfillInvalidSize ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
/* These are fine */
AtlasLandfill { { 16 , 0 } } ;
AtlasLandfill { { 65536 , 16 } } ;
AtlasLandfillArray { { 16 , 16 , 0 } } ;
AtlasLandfillArray { { 65536 , 16 , 16 } } ;
std : : ostringstream out ;
Error redirectError { & out } ;
AtlasLandfill { { 0 , 16 } } ;
AtlasLandfill { { 65537 , 16 } } ;
AtlasLandfillArray { { 0 , 16 , 16 } } ;
AtlasLandfillArray { { 16 , 0 , 16 } } ;
AtlasLandfillArray { { 65537 , 16 , 16 } } ;
CORRADE_COMPARE_AS ( out . str ( ) ,
" TextureTools::AtlasLandfill: expected non-zero width, got {0, 16} \n "
" TextureTools::AtlasLandfill: expected width to fit into 16 bits, got {65537, 16} \n "
" TextureTools::AtlasLandfillArray: expected non-zero width and height, got {0, 16, 16} \n "
" TextureTools::AtlasLandfillArray: expected non-zero width and height, got {16, 0, 16} \n "
" TextureTools::AtlasLandfillArray: expected width to fit into 16 bits, got {65537, 16, 16} \n " ,
TestSuite : : Compare : : String ) ;
}
void AtlasTest : : landfillSetFlagsInvalid ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
AtlasLandfill atlas { { 16 , 16 } } ;
AtlasLandfillArray array { { 16 , 16 , 1 } } ;
std : : ostringstream out ;
Error redirectError { & out } ;
atlas . setFlags ( AtlasLandfillFlag : : RotatePortrait | AtlasLandfillFlag : : RotateLandscape ) ;
array . setFlags ( AtlasLandfillFlag : : RotatePortrait | AtlasLandfillFlag : : RotateLandscape ) ;
atlas . setFlags ( AtlasLandfillFlag : : WidestFirst | AtlasLandfillFlag : : NarrowestFirst ) ;
array . setFlags ( AtlasLandfillFlag : : WidestFirst | AtlasLandfillFlag : : NarrowestFirst ) ;
CORRADE_COMPARE_AS ( out . str ( ) ,
" TextureTools::AtlasLandfill::setFlags(): only one of RotatePortrait and RotateLandscape can be set \n "
" TextureTools::AtlasLandfillArray::setFlags(): only one of RotatePortrait and RotateLandscape can be set \n "
" TextureTools::AtlasLandfill::setFlags(): only one of WidestFirst and NarrowestFirst can be set \n "
" TextureTools::AtlasLandfillArray::setFlags(): only one of WidestFirst and NarrowestFirst can be set \n " ,
TestSuite : : Compare : : String ) ;
}
void AtlasTest : : landfillAddMissingRotations ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
AtlasLandfill atlasPortrait { { 16 , 23 } } ;
AtlasLandfill atlasLandscape { { 16 , 23 } } ;
AtlasLandfillArray arrayPortrait { { 16 , 23 , 2 } } ;
AtlasLandfillArray arrayLandscape { { 16 , 23 , 2 } } ;
atlasPortrait . setFlags ( AtlasLandfillFlag : : RotatePortrait ) ;
arrayPortrait . setFlags ( AtlasLandfillFlag : : RotatePortrait ) ;
atlasLandscape . setFlags ( AtlasLandfillFlag : : RotateLandscape ) ;
arrayLandscape . setFlags ( AtlasLandfillFlag : : RotateLandscape ) ;
Vector2i sizes [ 2 ] ;
Vector2i offsets [ 2 ] ;
Vector3i offsets3 [ 2 ] ;
std : : ostringstream out ;
Error redirectError { & out } ;
atlasPortrait . add ( sizes , offsets ) ;
arrayPortrait . add ( sizes , offsets3 ) ;
/* "Testing" the rotation-less init list variants too */
atlasLandscape . add ( { { } , { } } , offsets ) ;
arrayLandscape . add ( { { } , { } } , offsets3 ) ;
CORRADE_COMPARE ( out . str ( ) ,
" TextureTools::AtlasLandfill::add(): TextureTools::AtlasLandfillFlag::RotatePortrait set, expected a rotations view \n "
" TextureTools::AtlasLandfillArray::add(): TextureTools::AtlasLandfillFlag::RotatePortrait set, expected a rotations view \n "
" TextureTools::AtlasLandfill::add(): TextureTools::AtlasLandfillFlag::RotateLandscape set, expected a rotations view \n "
" TextureTools::AtlasLandfillArray::add(): TextureTools::AtlasLandfillFlag::RotateLandscape set, expected a rotations view \n " ) ;
}
void AtlasTest : : landfillAddInvalidViewSizes ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
AtlasLandfill atlas { { 16 , 23 } } ;
Vector2i sizes [ 2 ] ;
Vector2i offsets [ 2 ] ;
Vector2i offsetsInvalid [ 3 ] ;
UnsignedByte rotationsData [ 1 ] ;
Containers : : MutableBitArrayView rotations { rotationsData , 0 , 2 } ;
Containers : : MutableBitArrayView rotationsInvalid { rotationsData , 0 , 3 } ;
std : : ostringstream out ;
Error redirectError { & out } ;
atlas . add ( sizes , offsetsInvalid , rotations ) ;
atlas . add ( sizes , offsets , rotationsInvalid ) ;
CORRADE_COMPARE ( out . str ( ) ,
" TextureTools::AtlasLandfill::add(): expected sizes and offsets views to have the same size, got 2 and 3 \n "
" TextureTools::AtlasLandfill::add(): expected sizes and rotations views to have the same size, got 2 and 3 \n " ) ;
}
void AtlasTest : : landfillAddTooLargeElement ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
/* The atlas makes the sizes portrait first, the array landscape instead */
AtlasLandfill atlas { { 16 , 23 } } ;
AtlasLandfill atlas2 { { 16 , 13 } } ;
AtlasLandfillArray array { { 23 , 16 , 3 } } ;
AtlasLandfillArray array2 { { 13 , 16 , 3 } } ;
array . setFlags ( AtlasLandfillFlag : : RotateLandscape ) ;
array2 . setFlags ( AtlasLandfillFlag : : RotateLandscape ) ;
Vector2i offsets [ 2 ] ;
Vector3i offsets3 [ 2 ] ;
UnsignedByte rotationsData [ 1 ] ;
Containers : : MutableBitArrayView rotations { rotationsData , 0 , 2 } ;
std : : ostringstream out ;
Error redirectError { & out } ;
atlas . add ( { { 16 , 23 } , { 0 , 23 } } , offsets , rotations ) ;
array . add ( { { 23 , 16 } , { 23 , 0 } } , offsets3 , rotations ) ;
atlas . add ( { { 16 , 23 } , { 17 , 23 } } , offsets , rotations ) ;
array . add ( { { 23 , 16 } , { 23 , 17 } } , offsets3 , rotations ) ;
/* Sizes that fit but don't after a flip */
atlas2 . add ( { { 13 , 13 } , { 15 , 13 } } , offsets , rotations ) ;
array2 . add ( { { 13 , 13 } , { 13 , 15 } } , offsets3 , rotations ) ;
CORRADE_COMPARE_AS ( out . str ( ) ,
" TextureTools::AtlasLandfill::add(): expected size 1 to be non-zero and not larger than {16, 23} but got {0, 23} \n "
" TextureTools::AtlasLandfillArray::add(): expected size 1 to be non-zero and not larger than {23, 16} but got {23, 0} \n "
" TextureTools::AtlasLandfill::add(): expected size 1 to be non-zero and not larger than {16, 23} but got {17, 23} \n "
" TextureTools::AtlasLandfillArray::add(): expected size 1 to be non-zero and not larger than {23, 16} but got {23, 17} \n "
" TextureTools::AtlasLandfill::add(): expected size 1 to be non-zero and not larger than {16, 13} but got {13, 15} \n "
" TextureTools::AtlasLandfillArray::add(): expected size 1 to be non-zero and not larger than {13, 16} but got {15, 13} \n " ,
TestSuite : : Compare : : String ) ;
}
void AtlasTest : : basic ( ) {
std : : vector < Range2Di > atlas = TextureTools : : atlas ( { 64 , 64 } , {
{ 12 , 18 } ,
{ 32 , 15 } ,
{ 23 , 25 }
} ) ;
CORRADE_COMPARE ( atlas . size ( ) , 3 ) ;
CORRADE_COMPARE ( atlas , ( std : : vector < Range2Di > {
Range2Di : : fromSize ( { 0 , 0 } , { 12 , 18 } ) ,
Range2Di : : fromSize ( { 32 , 0 } , { 32 , 15 } ) ,
Range2Di : : fromSize ( { 0 , 25 } , { 23 , 25 } ) } ) ) ;
}
void AtlasTest : : padding ( ) {
std : : vector < Range2Di > atlas = TextureTools : : atlas ( { 64 , 64 } , {
{ 8 , 16 } ,
{ 28 , 13 } ,
{ 19 , 23 }
} , { 2 , 1 } ) ;
CORRADE_COMPARE ( atlas . size ( ) , 3 ) ;
CORRADE_COMPARE ( atlas , ( std : : vector < Range2Di > {
Range2Di : : fromSize ( { 2 , 1 } , { 8 , 16 } ) ,
Range2Di : : fromSize ( { 34 , 1 } , { 28 , 13 } ) ,
Range2Di : : fromSize ( { 2 , 26 } , { 19 , 23 } ) } ) ) ;
}
void AtlasTest : : empty ( ) {
std : : vector < Range2Di > atlas = TextureTools : : atlas ( { } , { } ) ;
CORRADE_VERIFY ( atlas . empty ( ) ) ;
}
void AtlasTest : : tooSmall ( ) {
std : : ostringstream o ;
Error redirectError { & o } ;
std : : vector < Range2Di > atlas = TextureTools : : atlas ( { 64 , 32 } , {
{ 8 , 16 } ,
{ 21 , 13 } ,
{ 19 , 29 }
} , { 2 , 1 } ) ;
CORRADE_VERIFY ( atlas . empty ( ) ) ;
CORRADE_COMPARE ( o . str ( ) , " TextureTools::atlas(): requested atlas size Vector(64, 32) is too small to fit 3 Vector(25, 31) textures. Generated atlas will be empty. \n " ) ;
}
void AtlasTest : : arrayPowerOfTwoEmpty ( ) {
Containers : : ArrayView < Vector3i > offsets ;
CORRADE_COMPARE ( atlasArrayPowerOfTwo ( { 128 , 128 } , { } , offsets ) , 0 ) ;
}
void AtlasTest : : arrayPowerOfTwoSingleElement ( ) {
Vector3i offsets [ 1 ] ;
CORRADE_COMPARE ( atlasArrayPowerOfTwo ( { 128 , 128 } , { { 128 , 128 } } , offsets ) , 1 ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( offsets ) , Containers : : arrayView < Vector3i > ( {
{ 0 , 0 , 0 }
} ) , TestSuite : : Compare : : Container ) ;
}
void AtlasTest : : arrayPowerOfTwoAllSameElements ( ) {
Vector3i offsets [ 4 ] ;
CORRADE_COMPARE ( atlasArrayPowerOfTwo ( { 128 , 128 } , {
{ 64 , 64 } ,
{ 64 , 64 } ,
{ 64 , 64 } ,
{ 64 , 64 } ,
} , offsets ) , 1 ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( offsets ) , Containers : : arrayView < Vector3i > ( {
{ 0 , 0 , 0 } ,
{ 64 , 0 , 0 } ,
{ 0 , 64 , 0 } ,
{ 64 , 64 , 0 }
} ) , TestSuite : : Compare : : Container ) ;
}
void AtlasTest : : arrayPowerOfTwoOneLayer ( ) {
auto & & data = ArrayPowerOfTwoOneLayerData [ testCaseInstanceId ( ) ] ;
setTestCaseDescription ( data . name ) ;
const Vector2i inputSorted [ ArrayPowerOfTwoOneLayerImageCount ] {
{ 1024 , 1024 } , /* 0 */
{ 1024 , 1024 } , /* 1 */
{ 512 , 512 } , /* 2 */
{ 512 , 512 } , /* 3 */
{ 512 , 512 } , /* 4 */
{ 512 , 512 } , /* 5 */
{ 512 , 512 } , /* 6 */
{ 256 , 256 } , /* 7 */
{ 256 , 256 } , /* 8 */
{ 256 , 256 } , /* 9 */
{ 256 , 256 } , /* 10 */
{ 128 , 128 } , /* 11 */
{ 128 , 128 } , /* 12 */
{ 32 , 32 } , /* 13 */
{ 32 , 32 } /* 14 */
} ;
const Vector3i expectedSorted [ ArrayPowerOfTwoOneLayerImageCount ] {
{ 0 , 0 , 0 } ,
{ 1024 , 0 , 0 } ,
{ 0 , 1024 , 0 } ,
{ 512 , 1024 , 0 } ,
{ 0 , 1536 , 0 } ,
{ 512 , 1536 , 0 } ,
{ 1024 , 1024 , 0 } ,
{ 1536 , 1024 , 0 } ,
{ 1792 , 1024 , 0 } ,
{ 1536 , 1280 , 0 } ,
{ 1792 , 1280 , 0 } ,
{ 1024 , 1536 , 0 } ,
{ 1152 , 1536 , 0 } ,
{ 1024 , 1664 , 0 } ,
{ 1056 , 1664 , 0 }
} ;
Vector2i input [ ArrayPowerOfTwoOneLayerImageCount ] ;
Vector3i expected [ ArrayPowerOfTwoOneLayerImageCount ] ;
for ( std : : size_t i = 0 ; i ! = ArrayPowerOfTwoOneLayerImageCount ; + + i ) {
input [ i ] = inputSorted [ data . order [ i ] ] ;
expected [ i ] = expectedSorted [ data . order [ i ] ] ;
}
Vector3i offsets [ ArrayPowerOfTwoOneLayerImageCount ] ;
CORRADE_COMPARE ( atlasArrayPowerOfTwo ( { 2048 , 2048 } , input , offsets ) , 1 ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( offsets ) ,
Containers : : arrayView ( expected ) ,
TestSuite : : Compare : : Container ) ;
}
void AtlasTest : : arrayPowerOfTwoMoreLayers ( ) {
Vector3i offsets [ 11 ] ;
CORRADE_COMPARE ( atlasArrayPowerOfTwo ( { 2048 , 2048 } , {
{ 2048 , 2048 } ,
{ 1024 , 1024 } ,
{ 1024 , 1024 } ,
{ 1024 , 1024 } ,
{ 512 , 512 } ,
{ 512 , 512 } ,
{ 512 , 512 } ,
{ 512 , 512 } ,
{ 512 , 512 } ,
{ 256 , 256 } ,
{ 256 , 256 }
} , offsets ) , 3 ) ;
CORRADE_COMPARE_AS ( Containers : : arrayView ( offsets ) , Containers : : arrayView < Vector3i > ( {
{ 0 , 0 , 0 } ,
{ 0 , 0 , 1 } ,
{ 1024 , 0 , 1 } ,
{ 0 , 1024 , 1 } ,
{ 1024 , 1024 , 1 } ,
{ 1536 , 1024 , 1 } ,
{ 1024 , 1536 , 1 } ,
{ 1536 , 1536 , 1 } ,
{ 0 , 0 , 2 } ,
{ 512 , 0 , 2 } ,
{ 768 , 0 , 2 }
} ) , TestSuite : : Compare : : Container ) ;
}
void AtlasTest : : arrayPowerOfTwoInvalidViewSizes ( ) {
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
Vector2i sizes [ 2 ] ;
Vector3i offsetsInvalid [ 3 ] ;
std : : ostringstream out ;
Error redirectError { & out } ;
atlasArrayPowerOfTwo ( { } , sizes , offsetsInvalid ) ;
CORRADE_COMPARE ( out . str ( ) ,
" TextureTools::atlasArrayPowerOfTwo(): expected sizes and offsets views to have the same size, got 2 and 3 \n " ) ;
}
void AtlasTest : : arrayPowerOfTwoWrongLayerSize ( ) {
auto & & data = ArrayPowerOfTwoWrongLayerSizeData [ testCaseInstanceId ( ) ] ;
setTestCaseDescription ( data . name ) ;
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
std : : ostringstream out ;
Error redirectError { & out } ;
atlasArrayPowerOfTwo ( data . size , { } , { } ) ;
CORRADE_COMPARE ( out . str ( ) , Utility : : formatString ( " TextureTools::atlasArrayPowerOfTwo(): expected layer size to be a non-zero power-of-two square, got {} \n " , data . message ) ) ;
}
void AtlasTest : : arrayPowerOfTwoWrongSize ( ) {
auto & & data = ArrayPowerOfTwoWrongSizeData [ testCaseInstanceId ( ) ] ;
setTestCaseDescription ( data . name ) ;
CORRADE_SKIP_IF_NO_ASSERT ( ) ;
Vector3i offsets [ 3 ] ;
std : : ostringstream out ;
Error redirectError { & out } ;
atlasArrayPowerOfTwo ( { 256 , 256 } , {
{ 64 , 64 } ,
{ 128 , 128 } ,
data . size
} , offsets ) ;
CORRADE_COMPARE ( out . str ( ) , Utility : : formatString ( " TextureTools::atlasArrayPowerOfTwo(): expected size 2 to be a non-zero power-of-two square not larger than {{256, 256}} but got {} \n " , data . message ) ) ;
}
# ifdef MAGNUM_BUILD_DEPRECATED
void AtlasTest : : arrayPowerOfTwoDeprecated ( ) {
/* Same as arrayPowerOfTwoAllSameElements(), but with the deprecated API */
CORRADE_IGNORE_DEPRECATED_PUSH
Containers : : Pair < Int , Containers : : Array < Vector3i > > out = atlasArrayPowerOfTwo ( { 128 , 128 } , {
{ 64 , 64 } ,
{ 64 , 64 } ,
{ 64 , 64 } ,
{ 64 , 64 } ,
} ) ;
CORRADE_IGNORE_DEPRECATED_POP
CORRADE_COMPARE ( out . first ( ) , 1 ) ;
CORRADE_COMPARE_AS ( out . second ( ) , Containers : : arrayView < Vector3i > ( {
{ 0 , 0 , 0 } ,
{ 64 , 0 , 0 } ,
{ 0 , 64 , 0 } ,
{ 64 , 64 , 0 }
} ) , TestSuite : : Compare : : Container ) ;
}
# endif
} } } }
CORRADE_TEST_MAIN ( Magnum : : TextureTools : : Test : : AtlasTest )