[sdf] Add function to copy source bitmap to distance map.

* src/sdf/ftbsdf.c (bsdf_init_distance_map): New function.
This commit is contained in:
Anuj Verma 2020-08-20 21:09:23 -07:00 committed by Werner Lemberg
parent 0f644f38e9
commit 6b9a8044be
2 changed files with 207 additions and 0 deletions

View File

@ -1,3 +1,9 @@
2020-08-20 Anuj Verma <anujv@iitbhilai.ac.in>
[sdf] Add function to copy source bitmap to distance map.
* src/sdf/ftbsdf.c (bsdf_init_distance_map): New function.
2020-08-20 Anuj Verma <anujv@iitbhilai.ac.in>
[sdf] Add functions to compute pixel edge distances.

View File

@ -494,4 +494,205 @@
return error;
}
/**************************************************************************
*
* @Function:
* bsdf_init_distance_map
*
* @Description:
* Initialize the distance map according to the '8-point sequential
* Euclidean distance mapping' (8SED) algorithm. Basically it copies
* the `source` bitmap alpha values to the `distance_map->alpha`
* parameter of `worker`.
*
* @Input:
* source ::
* Source bitmap to copy the data from.
*
* @Output:
* worker ::
* Target distance map to copy the data to.
*
* @Return:
* FreeType error, 0 means success.
*
*/
static FT_Error
bsdf_init_distance_map( const FT_Bitmap* source,
BSDF_Worker* worker )
{
FT_Error error = FT_Err_Ok;
FT_Int x_diff, y_diff;
FT_Int t_i, t_j, s_i, s_j;
FT_Byte* s;
ED* t;
/* again check the parameters (probably unnecessary) */
if ( !source || !worker )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
/* Because of the way we convert a bitmap to SDF, */
/* i.e., aligning the source to the center of the */
/* target, the target's width and rows must be */
/* checked before copying. */
if ( worker->width < (FT_Int)source->width ||
worker->rows < (FT_Int)source->rows )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
/* check pixel mode */
if ( source->pixel_mode == FT_PIXEL_MODE_NONE )
{
FT_ERROR(( "bsdf_copy_source_to_target:"
" Invalid pixel mode of source bitmap" ));
error = FT_THROW( Invalid_Argument );
goto Exit;
}
#ifdef FT_DEBUG_LEVEL_TRACE
if ( source->pixel_mode == FT_PIXEL_MODE_MONO )
{
FT_TRACE0(( "bsdf_copy_source_to_target:"
" The `bsdf' renderer can convert monochrome\n" ));
FT_TRACE0(( " "
" bitmaps to SDF but the results are not perfect\n" ));
FT_TRACE0(( " "
" because there is no way to approximate actual\n" ));
FT_TRACE0(( " "
" outlines from monochrome bitmaps. Consider\n" ));
FT_TRACE0(( " "
" using an anti-aliased bitmap instead.\n" ));
}
#endif
/* Calculate the width and row differences */
/* between target and source. */
x_diff = worker->width - source->width;
y_diff = worker->rows - source->rows;
x_diff /= 2;
y_diff /= 2;
t = (ED*)worker->distance_map;
s = source->buffer;
/* For now we only support pixel mode `FT_PIXEL_MODE_MONO` */
/* and `FT_PIXEL_MODE_GRAY`. More will be added later. */
/* */
/* [NOTE]: We can also use @FT_Bitmap_Convert to convert */
/* bitmap to 8bpp. To avoid extra allocation and */
/* since the target bitmap can be 16bpp we manually */
/* convert the source bitmap to the desired bpp. */
switch ( source->pixel_mode )
{
case FT_PIXEL_MODE_MONO:
{
FT_Int t_width = worker->width;
FT_Int t_rows = worker->rows;
FT_Int s_width = source->width;
FT_Int s_rows = source->rows;
for ( t_j = 0; t_j < t_rows; t_j++ )
{
for ( t_i = 0; t_i < t_width; t_i++ )
{
FT_Int t_index = t_j * t_width + t_i;
FT_Int s_index;
FT_Int div, mod;
FT_Byte pixel, byte;
t[t_index] = zero_ed;
s_i = t_i - x_diff;
s_j = t_j - y_diff;
/* Assign 0 to padding similar to */
/* the source bitmap. */
if ( s_i < 0 || s_i >= s_width ||
s_j < 0 || s_j >= s_rows )
continue;
if ( worker->params.flip_y )
s_index = ( s_rows - s_j - 1 ) * source->pitch;
else
s_index = s_j * source->pitch;
div = s_index + s_i / 8;
mod = 7 - s_i % 8;
pixel = s[div];
byte = 1 << mod;
t[t_index].alpha = pixel & byte ? 255 : 0;
pixel = 0;
}
}
}
break;
case FT_PIXEL_MODE_GRAY:
{
FT_Int t_width = worker->width;
FT_Int t_rows = worker->rows;
FT_Int s_width = source->width;
FT_Int s_rows = source->rows;
/* loop over all pixels and assign pixel values from source */
for ( t_j = 0; t_j < t_rows; t_j++ )
{
for ( t_i = 0; t_i < t_width; t_i++ )
{
FT_Int t_index = t_j * t_width + t_i;
FT_Int s_index;
t[t_index] = zero_ed;
s_i = t_i - x_diff;
s_j = t_j - y_diff;
/* Assign 0 to padding similar to */
/* the source bitmap. */
if ( s_i < 0 || s_i >= s_width ||
s_j < 0 || s_j >= s_rows )
continue;
if ( worker->params.flip_y )
s_index = ( s_rows - s_j - 1 ) * s_width + s_i;
else
s_index = s_j * s_width + s_i;
/* simply copy the alpha values */
t[t_index].alpha = s[s_index];
}
}
}
break;
default:
FT_ERROR(( "bsdf_copy_source_to_target:"
" unsopported pixel mode of source bitmap\n" ));
error = FT_THROW( Unimplemented_Feature );
break;
}
Exit:
return error;
}
/* END */