From 596bcfd34086d30c39093d0287e95781857fa575 Mon Sep 17 00:00:00 2001 From: Anuj Verma Date: Wed, 19 Aug 2020 12:56:58 +0530 Subject: [PATCH] [sdf] Added function to generate SDF. * src/sdf/ftsdf.c (sdf_generate): Added function to generate SDF. This one doesn't use any optimization, it simply check all grid point against all contours. --- src/sdf/ftsdf.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/src/sdf/ftsdf.c b/src/sdf/ftsdf.c index 1b2eefbad..6d2552dcf 100644 --- a/src/sdf/ftsdf.c +++ b/src/sdf/ftsdf.c @@ -2647,6 +2647,158 @@ return error; } + /************************************************************************** + * + * @Function: + * sdf_generate + * + * @Description: + * This is the main function that is responsible for generating + * signed distance fields. The function will not align or compute + * the size of the `bitmap', therefore setup the `bitmap' properly + * and transform the `shape' appropriately before calling this + * function. + * Currently we check all the pixels against all the contours and + * all the edges. + * + * @Input: + * internal_params :: + * Internal parameters and properties required by the rasterizer. + * See `SDF_Params' for the actual parameters. + * + * shape :: + * A complete shape which is used to generate SDF. + * + * spread :: + * Maximum distances to be allowed inthe output bitmap. + * + * @Return + * bitmap :: + * The output bitmap which will contain the SDF information. + * + * FT_Error :: + * FreeType error, 0 means success. + * + */ + static FT_Error + sdf_generate( const SDF_Params internal_params, + const SDF_Shape* shape, + FT_UInt spread, + const FT_Bitmap* bitmap ) + { + FT_Error error = FT_Err_Ok; + FT_UInt width = 0; + FT_UInt rows = 0; + FT_UInt x = 0; /* used to loop in x direction i.e. width */ + FT_UInt y = 0; /* used to loop in y direction i.e. rows */ + FT_UInt sp_sq = 0; /* `spread' * `spread' int 16.16 fixed */ + + FT_Short* buffer; + + if ( !shape || !bitmap ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + if ( spread < MIN_SPREAD || spread > MAX_SPREAD ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + width = bitmap->width; + rows = bitmap->rows; + buffer = (FT_Short*)bitmap->buffer; + + if ( USE_SQUARED_DISTANCES ) + sp_sq = FT_INT_16D16( spread * spread ); + else + sp_sq = FT_INT_16D16( spread ); + + if ( width == 0 || rows == 0 ) + { + FT_TRACE0(( "[sdf] sdf_generate:\n" + " Cannot render glyph with width/height == 0\n" + " (width, height provided [%d, %d])", width, rows )); + error = FT_THROW( Cannot_Render_Glyph ); + goto Exit; + } + + /* loop through all the rows */ + for ( y = 0; y < rows; y++ ) + { + /* loop through all the pixels of a row */ + for ( x = 0; x < width; x++ ) + { + /* `grid_point' is the current pixel position */ + /* our task is to find the shortest distance */ + /* from this point to the entire shape. */ + FT_26D6_Vec grid_point = zero_vector; + SDF_Signed_Distance min_dist = max_sdf; + SDF_Contour* contour_list; + FT_UInt index; + FT_Short value; + + + grid_point.x = FT_INT_26D6( x ); + grid_point.y = FT_INT_26D6( y ); + + /* This `grid_point' is at the corner, but we */ + /* use the center of the pixel. */ + grid_point.x += FT_INT_26D6( 1 ) / 2; + grid_point.y += FT_INT_26D6( 1 ) / 2; + + contour_list = shape->contours; + + /* iterate through all the contours manually */ + while ( contour_list ) { + SDF_Signed_Distance current_dist = max_sdf; + + + FT_CALL( sdf_contour_get_min_distance( + contour_list, + grid_point, ¤t_dist ) ); + + if ( current_dist.distance < min_dist.distance ) + min_dist = current_dist; + + contour_list = contour_list->next; + } + + /* [OPTIMIZATION]: if (min_dist > sp_sq) then simply clamp */ + /* the value to spread to avoid square_root */ + + /* clamp the values to spread */ + if ( min_dist.distance > sp_sq ) + min_dist.distance = sp_sq; + + /* square_root the values and fit in a 6.10 fixed point */ + if ( USE_SQUARED_DISTANCES ) + min_dist.distance = square_root( min_dist.distance ); + + if ( internal_params.orientation == FT_ORIENTATION_FILL_LEFT ) + min_dist.sign = -min_dist.sign; + if ( internal_params.flip_sign ) + min_dist.sign = -min_dist.sign; + + min_dist.distance /= 64; /* convert from 16.16 to 22.10 */ + value = min_dist.distance & 0x0000FFFF; /* truncate to 6.10 */ + value *= min_dist.sign; + + if ( internal_params.flip_y ) + index = y * width + x; + else + index = ( rows - y - 1 ) * width + x; + + buffer[index] = value; + } + } + + Exit: + return error; + } + #endif /* END */