[sdf] Add function to generate SDF.
* src/sdf/ftsdf.c (sdf_generate): New function, currently disabled. This is a proof-of-concept implementation: It doesn't use any optimization, it simply checks all grid points against all contours.
This commit is contained in:
parent
0d52f4ae0a
commit
986d3108ac
|
@ -1,3 +1,11 @@
|
|||
2020-08-19 Anuj Verma <anujv@iitbhilai.ac.in>
|
||||
|
||||
[sdf] Add function to generate SDF.
|
||||
|
||||
* src/sdf/ftsdf.c (sdf_generate): New function, currently disabled.
|
||||
This is a proof-of-concept implementation: It doesn't use any
|
||||
optimization, it simply checks all grid points against all contours.
|
||||
|
||||
2020-08-19 Anuj Verma <anujv@iitbhilai.ac.in>
|
||||
|
||||
[sdf] Add functions to get shortest distance from any edge/contour.
|
||||
|
|
162
src/sdf/ftsdf.c
162
src/sdf/ftsdf.c
|
@ -2887,6 +2887,166 @@
|
|||
return error;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @Function:
|
||||
* sdf_generate
|
||||
*
|
||||
* @Description:
|
||||
* This is the main function that is responsible for generating signed
|
||||
* distance fields. The function does not align or compute the size of
|
||||
* `bitmap`; therefore the calling application must set up `bitmap`
|
||||
* properly and transform the `shape' appropriately in advance.
|
||||
*
|
||||
* Currently we check all pixels against all contours and all edges.
|
||||
*
|
||||
* @Input:
|
||||
* internal_params ::
|
||||
* Internal parameters and properties required by the rasterizer. See
|
||||
* @SDF_Params for more.
|
||||
*
|
||||
* shape ::
|
||||
* A complete shape which is used to generate SDF.
|
||||
*
|
||||
* spread ::
|
||||
* Maximum distances to be allowed in the output bitmap.
|
||||
*
|
||||
* @Output:
|
||||
* bitmap ::
|
||||
* The output bitmap which will contain the SDF information.
|
||||
*
|
||||
* @Return:
|
||||
* 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`] as a 16.16 fixed value */
|
||||
|
||||
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_generate:"
|
||||
" Cannot render glyph with width/height == 0\n" ));
|
||||
FT_TRACE0(( " "
|
||||
" (width, height provided [%d, %d])\n",
|
||||
width, rows ));
|
||||
|
||||
error = FT_THROW( Cannot_Render_Glyph );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* loop over all rows */
|
||||
for ( y = 0; y < rows; y++ )
|
||||
{
|
||||
/* loop over all 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 over all 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 /* 0 */
|
||||
|
||||
/* END */
|
||||
|
|
Loading…
Reference in New Issue