Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion Include/tesselator.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ void tessSetOption( TESStesselator *tess, int option, int value );
// vertexSize - defines the number of coordinates in tesselation result vertex, must be 2 or 3.
// normal - defines the normal of the input contours, of null the normal is calculated automatically.
// Returns:
// 1 if succeed, 0 if failed.
// 1 if succeed, 0 if failed (tessGetStatus can be used after to get a more
// specific failure status)
int tessTesselate( TESStesselator *tess, int windingRule, int elementType, int polySize, int vertexSize, const TESSreal* normal );

// tessGetVertexCount() - Returns number of vertices in the tesselated output.
Expand All @@ -243,6 +244,18 @@ int tessGetElementCount( TESStesselator *tess );
// tessGetElements() - Returns pointer to the first element.
const TESSindex* tessGetElements( TESStesselator *tess );

typedef enum TESSstatus {
TESS_STATUS_OK,
TESS_STATUS_OUT_OF_MEMORY,
TESS_STATUS_INVALID_INPUT
} TESSstatus;

// Return the success or failure status. If tessTesselate fails (or will fail,
// e.g. after invalid data is passed to tessAddContour), this can indicate
// more specifically why. It can also be checked after tessAddContour to
// see whether to bail out early.
TESSstatus tessGetStatus( TESStesselator *tess );

#ifdef __cplusplus
};
#endif
Expand Down
39 changes: 21 additions & 18 deletions Source/tess.c
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ TESStesselator* tessNewTess( TESSalloc* alloc )
// Initialize to begin polygon.
tess->mesh = NULL;

tess->outOfMemory = 0;
tess->status = TESS_STATUS_OK;
tess->vertexIndexCounter = 0;

tess->vertices = 0;
Expand Down Expand Up @@ -716,7 +716,7 @@ void OutputPolymesh( TESStesselator *tess, TESSmesh *mesh, int elementType, int
{
if (!tessMeshMergeConvexFaces( mesh, polySize ))
{
tess->outOfMemory = 1;
tess->status = TESS_STATUS_OUT_OF_MEMORY;
return;
}
}
Expand Down Expand Up @@ -759,7 +759,7 @@ void OutputPolymesh( TESStesselator *tess, TESSmesh *mesh, int elementType, int
sizeof(TESSindex) * maxFaceCount * polySize );
if (!tess->elements)
{
tess->outOfMemory = 1;
tess->status = TESS_STATUS_OUT_OF_MEMORY;
return;
}

Expand All @@ -768,15 +768,15 @@ void OutputPolymesh( TESStesselator *tess, TESSmesh *mesh, int elementType, int
sizeof(TESSreal) * tess->vertexCount * vertexSize );
if (!tess->vertices)
{
tess->outOfMemory = 1;
tess->status = TESS_STATUS_OUT_OF_MEMORY;
return;
}

tess->vertexIndices = (TESSindex*)tess->alloc.memalloc( tess->alloc.userData,
sizeof(TESSindex) * tess->vertexCount );
if (!tess->vertexIndices)
{
tess->outOfMemory = 1;
tess->status = TESS_STATUS_OUT_OF_MEMORY;
return;
}

Expand Down Expand Up @@ -867,23 +867,23 @@ void OutputContours( TESStesselator *tess, TESSmesh *mesh, int vertexSize )
sizeof(TESSindex) * tess->elementCount * 2 );
if (!tess->elements)
{
tess->outOfMemory = 1;
tess->status = TESS_STATUS_OUT_OF_MEMORY;
return;
}

tess->vertices = (TESSreal*)tess->alloc.memalloc( tess->alloc.userData,
sizeof(TESSreal) * tess->vertexCount * vertexSize );
if (!tess->vertices)
{
tess->outOfMemory = 1;
tess->status = TESS_STATUS_OUT_OF_MEMORY;
return;
}

tess->vertexIndices = (TESSindex*)tess->alloc.memalloc( tess->alloc.userData,
sizeof(TESSindex) * tess->vertexCount );
if (!tess->vertexIndices)
{
tess->outOfMemory = 1;
tess->status = TESS_STATUS_OUT_OF_MEMORY;
return;
}

Expand Down Expand Up @@ -934,7 +934,7 @@ void tessAddContour( TESStesselator *tess, int size, const void* vertices,
if ( tess->mesh == NULL )
tess->mesh = tessMeshNewMesh( &tess->alloc );
if ( tess->mesh == NULL ) {
tess->outOfMemory = 1;
tess->status = TESS_STATUS_OUT_OF_MEMORY;
return;
}

Expand All @@ -951,27 +951,26 @@ void tessAddContour( TESStesselator *tess, int size, const void* vertices,
if (!IsValidCoord(coords[0]) ||
!IsValidCoord(coords[1]) ||
(size > 2 && !IsValidCoord(coords[2]))) {
// "Out of memory" isn't quite right, but give up and bail out
tess->outOfMemory = 1;
tess->status = TESS_STATUS_INVALID_INPUT;
return;
}
if( e == NULL ) {
/* Make a self-loop (one vertex, one edge). */
e = tessMeshMakeEdge( tess->mesh );
if ( e == NULL ) {
tess->outOfMemory = 1;
tess->status = TESS_STATUS_OUT_OF_MEMORY;
return;
}
if ( !tessMeshSplice( tess->mesh, e, e->Sym ) ) {
tess->outOfMemory = 1;
tess->status = TESS_STATUS_OUT_OF_MEMORY;
return;
}
} else {
/* Create a new vertex and edge which immediately follow e
* in the ordering around the left face.
*/
if ( tessMeshSplitEdge( tess->mesh, e ) == NULL ) {
tess->outOfMemory = 1;
tess->status = TESS_STATUS_OUT_OF_MEMORY;
return;
}
e = e->Lnext;
Expand Down Expand Up @@ -1051,7 +1050,7 @@ int tessTesselate( TESStesselator *tess, int windingRule, int elementType,
return 0;
}

if (tess->outOfMemory || !tess->mesh)
if (tess->status != TESS_STATUS_OK || !tess->mesh)
{
return 0;
}
Expand Down Expand Up @@ -1099,9 +1098,7 @@ int tessTesselate( TESStesselator *tess, int windingRule, int elementType,
tessMeshDeleteMesh( &tess->alloc, mesh );
tess->mesh = NULL;

if (tess->outOfMemory)
return 0;
return 1;
return tess->status == TESS_STATUS_OK;
}

int tessGetVertexCount( TESStesselator *tess )
Expand All @@ -1128,3 +1125,9 @@ const int* tessGetElements( TESStesselator *tess )
{
return tess->elements;
}

TESSstatus tessGetStatus( TESStesselator *tess )
{
return tess->status;
}

4 changes: 1 addition & 3 deletions Source/tess.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,12 @@
extern "C" {
#endif

//typedef struct TESStesselator TESStesselator;

struct TESStesselator {

/*** state needed for collecting the input data ***/
TESSmesh *mesh; /* stores the input contours, and eventually
the tessellation itself */
int outOfMemory;
TESSstatus status;

/*** state needed for projecting onto the sweep plane ***/

Expand Down
16 changes: 16 additions & 0 deletions Tests/libtess2_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,22 @@ TEST_F(Libtess2Test, UnitQuad) {
EXPECT_EQ(tessGetElementCount(tess), 2);
}

TEST_F(Libtess2Test, GetStatusInvalidInput) {
AddPolyline(tess, {{-2e+37f, 0.f}, {0, 5}, {1e37f, -5}});
EXPECT_EQ(tessTesselate(tess, TESS_WINDING_POSITIVE, TESS_POLYGONS,
kNumTriangleVertices, kComponentCount, nullptr),
0);
EXPECT_EQ(tessGetStatus(tess), TESS_STATUS_INVALID_INPUT);
}

TEST_F(Libtess2Test, GetStatusOk) {
AddPolyline(tess, {{0, 0}, {0, 1}, {1, 1}, {1, 0}});
EXPECT_NE(tessTesselate(tess, TESS_WINDING_POSITIVE, TESS_POLYGONS,
kNumTriangleVertices, kComponentCount, nullptr),
0);
EXPECT_EQ(tessGetStatus(tess), TESS_STATUS_OK);
}

TEST_F(Libtess2Test, FloatOverflowQuad) {
constexpr float kFloatMin = std::numeric_limits<float>::min();
constexpr float kFloatMax = std::numeric_limits<float>::max();
Expand Down