From 75182d8ad1134bf2527056aaafe902edae42f7c2 Mon Sep 17 00:00:00 2001 From: Anuj Verma Date: Wed, 19 Aug 2020 12:22:34 +0530 Subject: [PATCH] [sdf] Added functions to get shortest distance from any edge/contour. * src/sdf/ftsdf,c (sdf_edge_get_min_distance): Added function to get shortest distance from any arbitary edge. * src/sdf/ftsdf.c (sdf_contour_get_min_distance): Added function to get shortest distance from a contour. It basically returns the shortest distance from the nearest edge. --- src/sdf/ftsdf.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/src/sdf/ftsdf.c b/src/sdf/ftsdf.c index e38aa7401..1b2eefbad 100644 --- a/src/sdf/ftsdf.c +++ b/src/sdf/ftsdf.c @@ -2505,5 +2505,148 @@ return error; } + /************************************************************************** + * + * @Function: + * sdf_edge_get_min_distance + * + * @Description: + * This is a handy function which can be used to find shortest distance + * from a `point' to any type of `edge'. It checks the edge type and + * then calls the relevant `get_min_distance_' function. + * + * @Input: + * edge :: + * An edge to which the shortest distance is to be computed. + * + * point :: + * Point from which the shortest distance is to be computed. + * + * @Return: + * out :: + * Signed distance from the `point' to the `edge'. + * + * FT_Error :: + * FreeType error, 0 means success. + * + */ + static FT_Error + sdf_edge_get_min_distance( SDF_Edge* edge, + FT_26D6_Vec point, + SDF_Signed_Distance* out) + { + FT_Error error = FT_Err_Ok; + + + if ( !edge || !out ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + /* edge specific distance calculation */ + switch ( edge->edge_type ) { + case SDF_EDGE_LINE: + get_min_distance_line( edge, point, out ); + break; + case SDF_EDGE_CONIC: + get_min_distance_conic( edge, point, out ); + break; + case SDF_EDGE_CUBIC: + get_min_distance_cubic( edge, point, out ); + break; + default: + error = FT_THROW( Invalid_Argument ); + } + + Exit: + return error; + } + + /* `sdf_generate' is not used at the moment */ + #if 0 + + /************************************************************************** + * + * @Function: + * sdf_contour_get_min_distance + * + * @Description: + * This function iterate through all the edges that make up + * the contour and find the shortest distance from a point to + * this contour and assigns it to `out'. + * + * @Input: + * contour :: + * A contour to which the shortest distance is to be computed. + * + * point :: + * Point from which the shortest distance is to be computed. + * + * @Return: + * out :: + * Signed distance from the `point' to the `contour'. + * + * FT_Error :: + * FreeType error, 0 means success. + * + * @Note: + * The function does not return signed distance for each edge + * which make up the contour, it simply returns the shortest + * of all the edges. + * + */ + static FT_Error + sdf_contour_get_min_distance( SDF_Contour* contour, + FT_26D6_Vec point, + SDF_Signed_Distance* out) + { + FT_Error error = FT_Err_Ok; + SDF_Signed_Distance min_dist = max_sdf; + SDF_Edge* edge_list; + + + if ( !contour || !out ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + edge_list = contour->edges; + + /* iterate through all the edges manually */ + while ( edge_list ) { + SDF_Signed_Distance current_dist = max_sdf; + FT_16D16 diff; + + + FT_CALL( sdf_edge_get_min_distance( + edge_list, + point, ¤t_dist ) ); + + if ( current_dist.distance >= 0 ) + { + diff = current_dist.distance - min_dist.distance; + + + if ( FT_ABS(diff ) < CORNER_CHECK_EPSILON ) + min_dist = resolve_corner( min_dist, current_dist ); + else if ( diff < 0 ) + min_dist = current_dist; + } + else + { + FT_TRACE0(( "sdf_contour_get_min_distance: Overflowed.\n" )); + } + + edge_list = edge_list->next; + } + + *out = min_dist; + Exit: + return error; + } + + #endif /* END */