star-cpr

Clip 2D meshes with 2D polygons
git clone git://git.meso-star.fr/star-cpr.git
Log | Files | Refs | README | LICENSE

commit 658e729e85c490811ffbba960863893a88a114a5
parent cca195062af7ee688e59beac4cff8bd72ae2b262
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Tue, 21 Feb 2023 11:16:01 +0100

Decrease memory footprint

Diffstat:
Msrc/scpr_c.h | 33+++++++++++++++++++++++----------
Msrc/scpr_intersector.c | 132+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/scpr_mesh.c | 68++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/scpr_polygon.c | 15++++++++++++++-
4 files changed, 164 insertions(+), 84 deletions(-)

diff --git a/src/scpr_c.h b/src/scpr_c.h @@ -23,7 +23,6 @@ #include <rsys/ref_count.h> #include <rsys/double2.h> #include <rsys/dynamic_array.h> -#include <rsys/dynamic_array_size_t.h> #include <rsys/hash_table.h> #include <math.h> @@ -31,6 +30,10 @@ #undef PI #include <clipper2/clipper.h> +#define DARRAY_NAME uint32 +#define DARRAY_DATA uint32_t +#include <rsys/dynamic_array.h> + #define DARRAY_NAME int64 #define DARRAY_DATA int64_t #include <rsys/dynamic_array.h> @@ -59,7 +62,7 @@ vertex_eq(const struct vertex* a, const struct vertex* b) /* Define the vertex to index hash table */ #define HTABLE_NAME vertex -#define HTABLE_DATA size_t +#define HTABLE_DATA uint32_t #define HTABLE_KEY struct vertex #define HTABLE_KEY_FUNCTOR_EQ vertex_eq #include <rsys/hash_table.h> @@ -85,15 +88,14 @@ struct scpr_polygon { struct scpr_mesh { struct darray_int64 coords; - struct darray_size_t indices; + struct darray_uint32 indices; ref_T ref; struct scpr_device* device; }; struct intersector_segment { - scpr_polygon* polygon; - size_t component, rank; + uint32_t component, first_vertex; }; #define DARRAY_NAME segments #define DARRAY_DATA struct intersector_segment @@ -103,7 +105,7 @@ struct intersector_segment { * darray. * The count is the number of ends of the segment at some range_point. */ #define HTABLE_NAME segment_idx -#define HTABLE_KEY size_t +#define HTABLE_KEY uint32_t #define HTABLE_DATA char #include <rsys/hash_table.h> @@ -150,7 +152,7 @@ range_point_copy_and_release /* An htable to link a pointer to a range_point to an 1D coordinate */ #define HTABLE_NAME range_point_idx #define HTABLE_KEY int64_t -#define HTABLE_DATA size_t +#define HTABLE_DATA uint32_t #include <rsys/hash_table.h> enum segment_interaction { @@ -178,7 +180,7 @@ struct intersector_dimension { /* An htable to store overlapping information */ struct intersector_segment_pair { - size_t rank1, rank2; + uint32_t rank1, rank2; }; static INLINE char pair_eq @@ -197,7 +199,7 @@ pair_eq /* An htable to keep track of registered components */ struct intersector_component { scpr_polygon* polygon; - size_t component; + uint32_t component; }; static FINLINE void component_init(struct mem_allocator* alloc, struct intersector_component* key) @@ -249,6 +251,15 @@ component_copy_and_release #define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE component_copy_and_release #include <rsys/hash_table.h> +#define DARRAY_NAME components +#define DARRAY_DATA struct intersector_component +#define DARRAY_FUNCTOR_INIT component_init +#define DARRAY_FUNCTOR_EQ component_eq +#define DARRAY_FUNCTOR_COPY component_copy +#define DARRAY_FUNCTOR_RELEASE component_release +#define DARRAY_FUNCTOR_COPY_AND_RELEASE component_copy_and_release +#include <rsys/dynamic_array.h> + /* A set of segments from different polygons spatially sorted to help find * (self-)intersections. */ struct scpr_intersector { @@ -261,8 +272,10 @@ struct scpr_intersector { * They are all the candidates for actual intersection plus some others that * are just close, but are without interaction. */ struct htable_interacting_segments interacting_segments; - /* All the registererd components */ + /* All the registererd components (an htable to check for unicity and a darray + * to store the components with indexing capability) */ struct htable_registered_components registererd_components; + struct darray_components components; ref_T ref; }; diff --git a/src/scpr_intersector.c b/src/scpr_intersector.c @@ -73,6 +73,7 @@ intersector_release(ref_T* ref) SCPR(device_ref_put(intersector->device)); htable_interacting_segments_release(&intersector->interacting_segments); htable_registered_components_release(&intersector->registererd_components); + darray_components_release(&intersector->components); MEM_RM(allocator, intersector); } @@ -82,10 +83,10 @@ register_point (struct scpr_intersector* intersector, const int dim_idx, const int64_t coord, - const size_t seg_idx) + const uint32_t seg_idx) { - size_t* pidx; - size_t rp_idx; + uint32_t* pidx; + uint32_t rp_idx; struct intersector_dimension* dim; struct intersector_range_point* sorted; res_T res = RES_OK; @@ -99,7 +100,7 @@ register_point size_t count = darray_range_points_size_get(&dim->sorted); ERR(darray_range_points_resize(&dim->sorted, 1+count)); sorted = darray_range_points_data_get(&dim->sorted); - rp_idx = count; + rp_idx = (uint32_t)count; sorted[rp_idx].coord = coord; /* Register this segment at this range point */ ERR(htable_segment_idx_set(&sorted[rp_idx].segments, &seg_idx, &one)); @@ -154,14 +155,14 @@ sort_points static void init_segment_pair (struct intersector_segment_pair* pair, - const size_t seg_idx1, - const size_t seg_idx2) + const uint32_t seg_idx1, + const uint32_t seg_idx2) { ASSERT(pair); pair->rank1 = seg_idx1; pair->rank2 = seg_idx2; if(pair->rank1 > pair->rank2) { - SWAP(ptrdiff_t, pair->rank1, pair->rank2); + SWAP(uint32_t, pair->rank1, pair->rank2); } } @@ -176,8 +177,8 @@ segments_bbox_interacts_1_core static int segments_bbox_interacts_1 - (size_t seg_idx1, - size_t seg_idx2, + (uint32_t seg_idx1, + uint32_t seg_idx2, enum segment_interaction inter, struct scpr_intersector* intersector) { @@ -185,22 +186,30 @@ segments_bbox_interacts_1 Clipper2Lib::Point64 *v11, * v12, *v21, *v22; int64_t lower1, upper1, lower2, upper2; size_t count, r11, r12, r21, r22; + const struct intersector_component* components; + struct scpr_polygon *polygon1, *polygon2; + uint32_t comp_idx1, comp_idx2; segments = darray_segments_cdata_get(&intersector->segments); seg1 = segments + seg_idx1; seg2 = segments + seg_idx2; + components = darray_components_cdata_get(&intersector->components); + comp_idx1 = components[seg1->component].component; + comp_idx2 = components[seg2->component].component; + polygon1 = components[seg1->component].polygon; + polygon2 = components[seg2->component].polygon; /* Get vertices */ - r11 = seg1->rank; - SCPR(polygon_get_vertices_count(seg1->polygon, seg1->component, &count)); + r11 = seg1->first_vertex; + SCPR(polygon_get_vertices_count(polygon1, comp_idx1, &count)); r12 = (r11 + 1) % count; - r21 = seg2->rank; - SCPR(polygon_get_vertices_count(seg2->polygon, seg2->component, &count)); + r21 = seg2->first_vertex; + SCPR(polygon_get_vertices_count(polygon2, comp_idx2, &count)); r22 = (r21 + 1) % count; - v11 = &seg1->polygon->paths[seg1->component][r11]; - v12 = &seg1->polygon->paths[seg1->component][r12]; - v21 = &seg2->polygon->paths[seg2->component][r21]; - v22 = &seg2->polygon->paths[seg2->component][r22]; + v11 = &polygon1->paths[comp_idx1][r11]; + v12 = &polygon1->paths[comp_idx1][r12]; + v21 = &polygon2->paths[comp_idx2][r21]; + v22 = &polygon2->paths[comp_idx2][r22]; if(inter & SOMETHING_X) { lower1 = MMIN(v11->x, v12->x); upper1 = MMAX(v11->x, v12->x); @@ -218,8 +227,8 @@ segments_bbox_interacts_1 /* Register interaction of 2 segments along 1 dimension */ static res_T register_segment_interaction - (const size_t seg_idx1, - const size_t seg_idx2, + (const uint32_t seg_idx1, + const uint32_t seg_idx2, const int allow_pair_creation, const enum segment_interaction inter, struct scpr_intersector* intersector) @@ -259,7 +268,7 @@ error: * open_segments along 1 dimension */ static res_T register_segment_interactions - (const size_t seg_idx, + (const uint32_t seg_idx, struct htable_segment_idx* open_segments, const int allow_pair_creation, const enum segment_interaction inter, @@ -274,7 +283,7 @@ register_segment_interactions htable_segment_idx_end(open_segments, &end); /* Loop on segments using this point */ while(!htable_segment_idx_iterator_eq(&it, &end)) { - size_t seg2_idx = *htable_segment_idx_iterator_key_get(&it); + uint32_t seg2_idx = *htable_segment_idx_iterator_key_get(&it); ERR(register_segment_interaction(seg_idx, seg2_idx, allow_pair_creation, inter, intersector)); htable_segment_idx_iterator_next(&it); @@ -299,7 +308,7 @@ register_interaction struct mem_allocator* allocator; struct intersector_dimension* dimension; char *begins = NULL, *ends = NULL; - size_t* seg_index = NULL; + uint32_t* seg_index = NULL; ASSERT(intersector); allocator = intersector->device->allocator; @@ -317,7 +326,7 @@ register_interaction scount = htable_segment_idx_size_get(&point->segments); begins = (char*)MEM_REALLOC(allocator, begins, scount * sizeof(*begins)); ends = (char*)MEM_REALLOC(allocator, ends, scount * sizeof(*ends)); - seg_index = (size_t*)MEM_REALLOC(allocator, seg_index, + seg_index = (uint32_t*)MEM_REALLOC(allocator, seg_index, scount * sizeof(*seg_index)); if(!begins || !ends || !seg_index) { res = RES_MEM_ERR; @@ -328,7 +337,7 @@ register_interaction htable_segment_idx_end(&point->segments, &end); while(!htable_segment_idx_iterator_eq(&it, &end)) { char c = *htable_segment_idx_iterator_data_get(&it); - size_t seg_idx = *htable_segment_idx_iterator_key_get(&it); + uint32_t seg_idx = *htable_segment_idx_iterator_key_get(&it); if(c == 2) { /* Both ends of the segment at this point */ ends[s] = begins[s] = 1; } else { @@ -474,26 +483,36 @@ check_two_segments_intersection (const struct intersector_segment* seg1, const struct intersector_segment* seg2, struct scpr_intersector_check_callbacks* callbacks, + struct scpr_intersector* intersector, void* data) { res_T res = RES_OK; size_t count, r11, r12, r21, r22; Clipper2Lib::Point64 *v11, * v12, *v21, *v22; int ccw1, ccw2, ccw3, ccw4, ovflw = 0; + const struct intersector_component* components; + struct scpr_polygon *polygon1, *polygon2; + uint32_t comp_idx1, comp_idx2; ASSERT(seg1 && seg2 && callbacks); + components = darray_components_cdata_get(&intersector->components); + comp_idx1 = components[seg1->component].component; + comp_idx2 = components[seg2->component].component; + polygon1 = components[seg1->component].polygon; + polygon2 = components[seg2->component].polygon; + /* Get vertices */ - r11 = seg1->rank; - ERR(scpr_polygon_get_vertices_count(seg1->polygon, seg1->component, &count)); + r11 = seg1->first_vertex; + ERR(scpr_polygon_get_vertices_count(polygon1, comp_idx1, &count)); r12 = (r11 + 1) % count; - r21 = seg2->rank; - ERR(scpr_polygon_get_vertices_count(seg2->polygon, seg2->component, &count)); + r21 = seg2->first_vertex; + ERR(scpr_polygon_get_vertices_count(polygon2, comp_idx2, &count)); r22 = (r21 + 1) % count; - v11 = &seg1->polygon->paths[seg1->component][r11]; - v12 = &seg1->polygon->paths[seg1->component][r12]; - v21 = &seg2->polygon->paths[seg2->component][r21]; - v22 = &seg2->polygon->paths[seg2->component][r22]; + v11 = &polygon1->paths[comp_idx1][r11]; + v12 = &polygon1->paths[comp_idx1][r12]; + v21 = &polygon2->paths[comp_idx2][r21]; + v22 = &polygon2->paths[comp_idx2][r22]; ASSERT(segments_bbox_interacts(v11, v12, v21, v22)); /* Test triangles orientation */ @@ -511,13 +530,13 @@ check_two_segments_intersection } else if(ccw1 == 0 && ccw2 == 0 && ccw3 == 0 && ccw4 == 0) { /* Colinear segments */ - callbacks->colinear_segments(seg1->polygon, seg1->component, seg1->rank, - seg2->polygon, seg2->component, seg2->rank, data); + callbacks->colinear_segments(polygon1, comp_idx1, seg1->first_vertex, + polygon2, comp_idx2, seg2->first_vertex, data); } else if(ccw1 * ccw2 < 0 && ccw3 * ccw4 < 0) { /* Basic segment intersection */ - callbacks->simple_intersection(seg1->polygon, seg1->component, seg1->rank, - seg2->polygon, seg2->component, seg2->rank, data); + callbacks->simple_intersection(polygon1, comp_idx1, seg1->first_vertex, + polygon2, comp_idx2, seg2->first_vertex, data); } exit: @@ -553,7 +572,7 @@ check_interacting_pairs = htable_interacting_segments_iterator_key_get(&it); const struct intersector_segment* seg1 = segments + pair->rank1; const struct intersector_segment* seg2 = segments + pair->rank2; - ERR(check_two_segments_intersection(seg1, seg2, callbacks, data)); + ERR(check_two_segments_intersection(seg1, seg2, callbacks, intersector, data)); } htable_interacting_segments_iterator_next(&it); } @@ -595,6 +614,7 @@ scpr_intersector_create init_dimension(allocator, intersector->dimensions + 1, OVERLAP_Y, CONTACT_Y); htable_interacting_segments_init(allocator, &intersector->interacting_segments); htable_registered_components_init(allocator, &intersector->registererd_components); + darray_components_init(allocator, &intersector->components); exit: if(out_intersector) *out_intersector = intersector; @@ -632,18 +652,20 @@ scpr_intersector_register_component const size_t icomponent) { res_T res = RES_OK; - size_t prev_count, new_count, i; + uint32_t i; + size_t new_count, prev_count, c; struct intersector_component comp; char *found, one = 1; - if(!intersector || !polygon || icomponent >= polygon->paths.size()) { + if(!intersector || !polygon || icomponent >= polygon->paths.size()) + { res = RES_BAD_ARG; goto error; } /* Check single registration */ comp.polygon = polygon; - comp.component = icomponent; + comp.component = (uint32_t)icomponent; found = htable_registered_components_find(&intersector->registererd_components, &comp); if(found) { @@ -652,21 +674,37 @@ scpr_intersector_register_component res = RES_BAD_ARG; goto error; } - htable_registered_components_set(&intersector->registererd_components, &comp, - &one); + c = htable_registered_components_size_get(&intersector->registererd_components); + if(c >= UINT32_MAX) { + logger_print(intersector->device->logger, LOG_ERROR, + "Too many components registered.\n"); + res = RES_BAD_ARG; + goto error; + } + ASSERT(c == darray_components_size_get(&intersector->components)); + ERR(htable_registered_components_set(&intersector->registererd_components, + &comp, &one)); + ERR(darray_components_push_back(&intersector->components, &comp)); prev_count = darray_segments_size_get(&intersector->segments); + ASSERT(prev_count <= UINT32_MAX); new_count = polygon->paths[icomponent].size(); - ERR(darray_segments_resize(&intersector->segments, prev_count + new_count)); + if(prev_count + new_count > UINT32_MAX) { + logger_print(intersector->device->logger, LOG_ERROR, + "Too many segments registered.\n"); + res = RES_BAD_ARG; + goto error; + } + ERR(darray_segments_resize(&intersector->segments, + (uint32_t)(prev_count + new_count))); for(i = 0; i < new_count; i++) { Clipper2Lib::Point64 *p0, *p1; - size_t seg_idx = prev_count + i; + uint32_t seg_idx = (uint32_t)(prev_count + i); struct intersector_segment* segment = darray_segments_data_get(&intersector->segments) + seg_idx; - segment->polygon = polygon; - segment->component = icomponent; - segment->rank = i; + segment->component = (uint32_t)c; + segment->first_vertex = i; p0 = &polygon->paths[icomponent][i]; p1 = &polygon->paths[icomponent][(i+1)%new_count]; ERR(register_point(intersector, 0, p0->x, seg_idx)); diff --git a/src/scpr_mesh.c b/src/scpr_mesh.c @@ -17,6 +17,7 @@ #include "scpr_c.h" #include <rsys/mem_allocator.h> +#include <rsys/logger.h> #include <polygon.h> #undef PI @@ -82,11 +83,11 @@ static res_T register_vertex (const int64_t pos[2], struct darray_int64* coords, - struct darray_size_t* indices, + struct darray_uint32* indices, struct htable_vertex* vertices) { struct vertex v; - size_t* pid, id; + uint32_t* pid, id; unsigned i; res_T res = RES_OK; ASSERT(pos && coords && indices && vertices); @@ -103,14 +104,15 @@ register_vertex } else { const size_t count = darray_int64_size_get(coords); + ASSERT(count <= UINT32_MAX); ERR(darray_int64_resize(coords, count+2/*#coords*/)); for(i = 0; i < 2; i++) darray_int64_data_get(coords)[count+i] = pos[i]; - id = count / 2; + id = (uint32_t)count / 2; ERR(htable_vertex_set(vertices, &v, &id)); } - ERR(darray_size_t_push_back(indices, &id)); + ERR(darray_uint32_push_back(indices, &id)); exit: return res; @@ -122,7 +124,7 @@ static FINLINE res_T register_triangle (int64_t tri[3][2], struct darray_int64* coords, /* Vertex buffer */ - struct darray_size_t* indices, /* Index buffer */ + struct darray_uint32* indices, /* Index buffer */ struct htable_vertex* vertices) /* Map a vertex to its index */ { size_t ivert; @@ -143,7 +145,7 @@ register_paths (struct scpr_device* dev, const Clipper2Lib::Paths64& paths, struct darray_int64* coords, /* Vertex buffer */ - struct darray_size_t* indices, /* Index buffer */ + struct darray_uint32* indices, /* Index buffer */ struct htable_vertex* vertices, /* Map a vertex to its index */ struct polygon* polygon) /* Used to triangulate the clipped polygons */ { @@ -237,7 +239,7 @@ mesh_release(ref_T* ref) allocator = mesh->device->allocator; SCPR(device_ref_put(mesh->device)); darray_int64_release(&mesh->coords); - darray_size_t_release(&mesh->indices); + darray_uint32_release(&mesh->indices); MEM_RM(allocator, mesh); } @@ -267,7 +269,7 @@ scpr_mesh_create mesh->device = dev; SCPR(device_ref_get(dev)); darray_int64_init(dev->allocator, &mesh->coords); - darray_size_t_init(dev->allocator, &mesh->indices); + darray_uint32_init(dev->allocator, &mesh->indices); exit: if(out_mesh) *out_mesh = mesh; @@ -307,8 +309,8 @@ scpr_mesh_setup_indexed_vertices void* data) { int64_t* pos = NULL; - size_t* ids = NULL; - size_t i; + uint32_t* ids = NULL; + size_t i, j; res_T res = RES_OK; if(!mesh || !ntris || !get_indices || !nverts || !get_position || !data) { @@ -316,8 +318,22 @@ scpr_mesh_setup_indexed_vertices goto error; } + if(ntris > UINT32_MAX) { + logger_print(mesh->device->logger, LOG_ERROR, + "Too many triangles.\n"); + res = RES_BAD_ARG; + goto error; + } + + if(nverts > UINT32_MAX) { + logger_print(mesh->device->logger, LOG_ERROR, + "Too many vertices.\n"); + res = RES_BAD_ARG; + goto error; + } + ERR(darray_int64_resize(&mesh->coords, nverts*2/*#coords per vertex*/)); - ERR(darray_size_t_resize(&mesh->indices, ntris*3/*#vertices per triangle*/)); + ERR(darray_uint32_resize(&mesh->indices, ntris*3/*#vertices per triangle*/)); /* Fetch mesh positions */ pos = darray_int64_data_get(&mesh->coords); @@ -328,15 +344,15 @@ scpr_mesh_setup_indexed_vertices } /* Fetch mesh indices */ - ids = darray_size_t_data_get(&mesh->indices); + ids = darray_uint32_data_get(&mesh->indices); FOR_EACH(i, 0, ntris) { - get_indices(i, ids + i*3, data); - if(ids[i*3+0] >= nverts - || ids[i*3+1] >= nverts - || ids[i*3+2] >= nverts) { + size_t tmp[3]; + get_indices(i, tmp, data); + if(tmp[0] >= nverts || tmp[1] >= nverts || tmp[2] >= nverts) { res = RES_BAD_ARG; goto error; } + for(j = 0; j < 3; j++) ids[i*3 + j] = (uint32_t)tmp[j]; } exit: @@ -344,7 +360,7 @@ exit: error: if(mesh) { darray_int64_clear(&mesh->coords); - darray_size_t_clear(&mesh->indices); + darray_uint32_clear(&mesh->indices); } goto exit; } @@ -362,8 +378,8 @@ res_T scpr_mesh_get_triangles_count(const struct scpr_mesh* mesh, size_t* ntris) { if(!mesh || !ntris) return RES_BAD_ARG; - ASSERT((darray_size_t_size_get(&mesh->indices)%3/*#vertices per triangle*/)==0); - *ntris = darray_size_t_size_get(&mesh->indices) / 3/*#vertices per triangle*/; + ASSERT((darray_uint32_size_get(&mesh->indices)%3/*#vertices per triangle*/)==0); + *ntris = darray_uint32_size_get(&mesh->indices) / 3/*#vertices per triangle*/; return RES_OK; } @@ -376,9 +392,9 @@ scpr_mesh_get_indices if(!mesh || !ids) return RES_BAD_ARG; SCPR(mesh_get_triangles_count(mesh, &ntris)); if(itri >= ntris) return RES_BAD_ARG; - ids[0] = darray_size_t_cdata_get(&mesh->indices)[i+0]; - ids[1] = darray_size_t_cdata_get(&mesh->indices)[i+1]; - ids[2] = darray_size_t_cdata_get(&mesh->indices)[i+2]; + ids[0] = darray_uint32_cdata_get(&mesh->indices)[i+0]; + ids[1] = darray_uint32_cdata_get(&mesh->indices)[i+1]; + ids[2] = darray_uint32_cdata_get(&mesh->indices)[i+2]; return RES_OK; } @@ -407,7 +423,7 @@ scpr_mesh_clip int64_t lower[2], upper[2]; struct polygon* polygon = NULL; /* Use to triangulate clipped polygons */ struct darray_int64 coords; /* Coordinates of the clipped mesh */ - struct darray_size_t indices; /* Indices of the clipped mesh */ + struct darray_uint32 indices; /* Indices of the clipped mesh */ struct htable_vertex vertices; /* Map a coordinate to its index */ Clipper2Lib::Clipper64 clipper; Clipper2Lib::Paths64 output; /* Contour of the clipped polgyon */ @@ -427,7 +443,7 @@ scpr_mesh_clip clip_type = scpr_operation_to_clip_type(op); darray_int64_init(allocator, &coords); - darray_size_t_init(allocator, &indices); + darray_uint32_init(allocator, &indices); htable_vertex_init(allocator, &vertices); if(aabb_is_degenerated(poly_desc->lower, poly_desc->upper)) goto exit; @@ -491,12 +507,12 @@ scpr_mesh_clip } ERR(darray_int64_copy_and_clear(&mesh->coords, &coords)); - ERR(darray_size_t_copy_and_clear(&mesh->indices, &indices)); + ERR(darray_uint32_copy_and_clear(&mesh->indices, &indices)); exit: if(polygon) POLYGON(ref_put(polygon)); darray_int64_release(&coords); - darray_size_t_release(&indices); + darray_uint32_release(&indices); htable_vertex_release(&vertices); return res; error: diff --git a/src/scpr_polygon.c b/src/scpr_polygon.c @@ -172,7 +172,7 @@ scpr_polygon_ref_put res_T scpr_polygon_setup_indexed_vertices (struct scpr_polygon* polygon, - const size_t ncomponents, /* #connex components */ + const size_t ncomponents, void (*get_nverts)(const size_t icomponent, size_t *nverts, void* ctx), void (*get_position) (const size_t icomponent, const size_t ivert, double pos[2], void* ctx), @@ -189,6 +189,13 @@ scpr_polygon_setup_indexed_vertices goto error; } + if(ncomponents > UINT32_MAX) { + logger_print(polygon->device->logger, LOG_ERROR, + "Too many components.\n"); + res = RES_BAD_ARG; + goto error; + } + dev = polygon->device; TRY(paths.resize(ncomponents)); @@ -197,6 +204,12 @@ scpr_polygon_setup_indexed_vertices /* Get count for connex component c */ get_nverts(c, &nverts, data); + if(nverts > UINT32_MAX) { + logger_print(polygon->device->logger, LOG_ERROR, + "Too many vertices for component %zu.\n", c); + res = RES_BAD_ARG; + goto error; + } TRY(paths[c].resize(nverts)); /* Fetch polygon positions for connex component c */