forked from minhngoc25a/freetype2
[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.
This commit is contained in:
parent
75182d8ad1
commit
596bcfd340
152
src/sdf/ftsdf.c
152
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 */
|
||||
|
|
Loading…
Reference in New Issue