Browse Source

TextureTools: check that atlasArrayPowerOfTwo() sizes are in bounds.

What, such an essential check was missing there?
pull/168/head
Vladimír Vondruš 3 years ago
parent
commit
958e5edbc2
  1. 4
      src/Magnum/TextureTools/Atlas.cpp
  2. 5
      src/Magnum/TextureTools/Atlas.h
  3. 23
      src/Magnum/TextureTools/Test/AtlasTest.cpp

4
src/Magnum/TextureTools/Atlas.cpp

@ -80,8 +80,8 @@ Containers::Pair<Int, Containers::Array<Vector3i>> atlasArrayPowerOfTwo(const Ve
Containers::Array<Vector3i> sortedSizes{NoInit, sizes.size()}; Containers::Array<Vector3i> sortedSizes{NoInit, sizes.size()};
for(std::size_t i = 0; i != sizes.size(); ++i) { for(std::size_t i = 0; i != sizes.size(); ++i) {
const Vector2i size = sizes[i]; const Vector2i size = sizes[i];
CORRADE_ASSERT(size.product() && size.x() == size.y() && (size & (size - Vector2i{1})).isZero(), CORRADE_ASSERT(size.product() && size.x() == size.y() && (size & (size - Vector2i{1})).isZero() && size <= layerSize,
"TextureTools::atlasArrayPowerOfTwo(): expected size" << i << "to be a non-zero power-of-two square, got" << Debug::packed << size, {}); "TextureTools::atlasArrayPowerOfTwo(): expected size" << i << "to be a non-zero power-of-two square not larger than" << Debug::packed << layerSize << "but got" << Debug::packed << size, {});
sortedSizes[i].xy() = size; sortedSizes[i].xy() = size;
sortedSizes[i].z() = i; sortedSizes[i].z() = i;

5
src/Magnum/TextureTools/Atlas.h

@ -60,8 +60,9 @@ std::vector<Range2Di> MAGNUM_TEXTURETOOLS_EXPORT atlas(const Vector2i& atlasSize
coordinate being the layer index coordinate being the layer index
@m_since_latest @m_since_latest
Both @p layerSize and all items in @p sizes are expected to be non-zero, square The @p layerSize is expected to be non-zero, square and power-of-two. All items
and power-of-two. With such constraints the packing is optimal with no wasted in @p sizes are expected to be non-zero, square, power-of-two and not larger
than @p layerSize. With such constraints the packing is optimal with no wasted
space in all but the last layer. Setting @p layerSize to the size of the space in all but the last layer. Setting @p layerSize to the size of the
largest texture in the set will lead to the least wasted space in the last largest texture in the set will lead to the least wasted space in the last
layer. layer.

23
src/Magnum/TextureTools/Test/AtlasTest.cpp

@ -70,14 +70,25 @@ const struct {
{0, 2, 7, 13, 11, 3, 4, 5, 8, 14, 1, 9, 6, 12, 10}}, {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 struct {
const char* name; const char* name;
Vector2i size; Vector2i size;
const char* message; const char* message;
} ArrayPowerOfTwoWrongSizeData[]{ } ArrayPowerOfTwoWrongSizeData[]{
{"larger than size", {512, 512}, "{512, 512}"},
{"non-power-of-two", {128, 127}, "{128, 127}"}, {"non-power-of-two", {128, 127}, "{128, 127}"},
{"non-square", {128, 256}, "{128, 256}"}, {"non-square", {128, 256}, "{128, 256}"},
{"zero", {1024, 0}, "{1024, 0}"} {"zero", {1024, 0}, "{1024, 0}"},
}; };
AtlasTest::AtlasTest() { AtlasTest::AtlasTest() {
@ -95,8 +106,10 @@ AtlasTest::AtlasTest() {
addTests({&AtlasTest::arrayPowerOfTwoMoreLayers}); addTests({&AtlasTest::arrayPowerOfTwoMoreLayers});
addInstancedTests({&AtlasTest::arrayPowerOfTwoWrongLayerSize, addInstancedTests({&AtlasTest::arrayPowerOfTwoWrongLayerSize},
&AtlasTest::arrayPowerOfTwoWrongSize}, Containers::arraySize(ArrayPowerOfTwoWrongLayerSizeData));
addInstancedTests({&AtlasTest::arrayPowerOfTwoWrongSize},
Containers::arraySize(ArrayPowerOfTwoWrongSizeData)); Containers::arraySize(ArrayPowerOfTwoWrongSizeData));
} }
@ -274,7 +287,7 @@ void AtlasTest::arrayPowerOfTwoMoreLayers() {
} }
void AtlasTest::arrayPowerOfTwoWrongLayerSize() { void AtlasTest::arrayPowerOfTwoWrongLayerSize() {
auto&& data = ArrayPowerOfTwoWrongSizeData[testCaseInstanceId()]; auto&& data = ArrayPowerOfTwoWrongLayerSizeData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
CORRADE_SKIP_IF_NO_ASSERT(); CORRADE_SKIP_IF_NO_ASSERT();
@ -298,7 +311,7 @@ void AtlasTest::arrayPowerOfTwoWrongSize() {
{128, 128}, {128, 128},
data.size data.size
}); });
CORRADE_COMPARE(out.str(), Utility::formatString("TextureTools::atlasArrayPowerOfTwo(): expected size 2 to be a non-zero power-of-two square, got {}\n", data.message)); 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));
} }
}}}} }}}}

Loading…
Cancel
Save