diff --git a/[GSoC]ChangeLog b/[GSoC]ChangeLog index f3c597cd5..cc028a86b 100644 --- a/[GSoC]ChangeLog +++ b/[GSoC]ChangeLog @@ -1,3 +1,20 @@ +2020-06-20 Anuj Verma + + [sdf] Implemented a few functions required by a renderer + module. + + * src/sdf/ftsdf.c (sdf_TRaster_): Added new structure to hold + the memory allocator `FT_Memory'. + + * src/sdf/ftsdf.c (ft_sdf_raster): Implemented a few essential + functions required by `FT_Raster'. + + * src/sdf/ftsdfrend.c (ft_sdf_renderer_class): Implemented a few + essential functions required by `FT_Renderer'. + + * src/sdf/ftsdfrend.c (ft_sdf_render): Added functionality to + compute shift and padding before rendering the outline. + 2020-06-19 Anuj Verma * include/freetype/ftimage.h (FT_Render_Mode_): Added new @@ -27,7 +44,7 @@ * src/sdf/rules.mk, src/sdf/module.mk: Added files required to build the `sdf' module using the default build system. - * CMakeLists.txt (`BASE_SRCS'): Add `src/sdf/sdf.c' to the variable. + * CMakeLists.txt (BASE_SRCS): Add `src/sdf/sdf.c' to the variable. * include/freetype/config/ftmodule.h: Added `sdf' module declaration so that the module can be compiled when not compiling diff --git a/src/sdf/ftsdf.c b/src/sdf/ftsdf.c index b4b5c487a..30eb18492 100644 --- a/src/sdf/ftsdf.c +++ b/src/sdf/ftsdf.c @@ -5,15 +5,37 @@ #include "ftsdferrs.h" + /************************************************************************** + * + * structures and enums + * + */ + + typedef struct sdf_TRaster_ + { + FT_Memory memory; /* used internally to allocate memory */ + } sdf_TRaster; + + /************************************************************************** + * + * interface functions + * + */ + static int sdf_raster_new( FT_Memory memory, FT_Raster* araster) { - FT_Error error = FT_THROW( Unimplemented_Feature ); + FT_Error error = FT_Err_Ok; + sdf_TRaster* raster = NULL; - FT_UNUSED( memory ); - FT_UNUSED( araster ); + *araster = 0; + if ( !FT_ALLOC( raster, sizeof( sdf_TRaster ) ) ) + { + raster->memory = memory; + *araster = (FT_Raster)raster; + } return error; } @@ -23,6 +45,7 @@ unsigned char* pool_base, unsigned long pool_size ) { + /* no use of this function */ FT_UNUSED( raster ); FT_UNUSED( pool_base ); FT_UNUSED( pool_size ); @@ -33,6 +56,8 @@ unsigned long mode, void* args ) { + /* Currently there is no use for this function but later */ + /* it will be used to modify the `spread' parameter. */ FT_UNUSED( raster ); FT_UNUSED( mode ); FT_UNUSED( args ); @@ -55,7 +80,10 @@ static void sdf_raster_done( FT_Raster raster ) { - FT_UNUSED( raster ); + FT_Memory memory = (FT_Memory)((sdf_TRaster*)raster)->memory; + + + FT_FREE( raster ); } FT_DEFINE_RASTER_FUNCS( diff --git a/src/sdf/ftsdfrend.c b/src/sdf/ftsdfrend.c index 626416947..62268df12 100644 --- a/src/sdf/ftsdfrend.c +++ b/src/sdf/ftsdfrend.c @@ -1,69 +1,171 @@ #include #include +#include #include "ftsdfrend.h" #include "ftsdf.h" #include "ftsdferrs.h" + /* generate signed distance field from a glyph's slot image */ static FT_Error ft_sdf_render( FT_Renderer render, FT_GlyphSlot slot, FT_Render_Mode mode, const FT_Vector* origin ) { - FT_Error error = FT_THROW( Unimplemented_Feature ); + FT_Error error = FT_Err_Ok; + FT_Outline* outline = &slot->outline; + FT_Bitmap* bitmap = &slot->bitmap; + FT_Memory memory = render->root.memory; + FT_Pos x_shift = 0; + FT_Pos y_shift = 0; + + /* use hardcoded padding for now */ + FT_UInt x_pad = 10; + FT_UInt y_pad = 10; + FT_Raster_Params params; - FT_UNUSED( render ); - FT_UNUSED( slot ); - FT_UNUSED( mode ); - FT_UNUSED( origin ); + /* check if slot format is correct before rendering */ + if ( slot->format != render->glyph_format ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + + /* check if render mode is correct */ + if ( mode != FT_RENDER_MODE_SDF ) + { + FT_ERROR(( "ft_sdf_render: sdf module only" + "render when using `FT_RENDER_MODE_SDF'" )); + error = FT_THROW( Cannot_Render_Glyph ); + goto Exit; + } + + /* deallocate the previously allocated bitmap */ + if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + { + FT_FREE( bitmap->buffer ); + slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; + } + + /* preset the bitmap using the glyph's outline; */ + /* the sdf bitmap is similar to a antialiased bitmap */ + /* with a slighty bigger size and different pixel mode */ + if ( ft_glyphslot_preset_bitmap( slot, FT_RENDER_MODE_NORMAL, origin ) ) + { + error = FT_THROW( Raster_Overflow ); + goto Exit; + } + + if ( !bitmap->rows || !bitmap->pitch ) + goto Exit; + + /* apply the padding */ + bitmap->rows += y_pad; + bitmap->width += x_pad; + + /* ignore the pitch, pixel mode and set custom */ + bitmap->pixel_mode = FT_PIXEL_MODE_GRAY16; + bitmap->pitch = bitmap->width * 2; + bitmap->num_grays = 65536; + + /* allocate new buffer */ + if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) ) + goto Exit; + + slot->internal->flags |= FT_GLYPH_OWN_BITMAP; + + x_shift = 64 * -( slot->bitmap_left + x_pad ); + y_shift = 64 * -( slot->bitmap_top + y_pad ); + y_shift += 64 * (FT_Int)bitmap->rows; + + if ( origin ) + { + x_shift += origin->x; + y_shift += origin->y; + } + + /* translate outline to render it into the bitmap */ + if ( x_shift || y_shift ) + FT_Outline_Translate( outline, x_shift, y_shift ); + + /* set up parameters */ + params.target = bitmap; + params.source = outline; + params.flags = 0; + + /* render the outline */ + error = render->raster_render( render->raster, ¶ms ); + + Exit: + if ( !error ) + { + /* the glyph is successfully rendered to a bitmap */ + slot->format = FT_GLYPH_FORMAT_BITMAP; + } + else if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + { + FT_FREE( bitmap->buffer ); + slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; + } + + if ( x_shift || y_shift ) + FT_Outline_Translate( outline, -x_shift, -y_shift ); return error; } + /* transform the glyph using matrix and/or delta */ static FT_Error ft_sdf_transform( FT_Renderer render, FT_GlyphSlot slot, const FT_Matrix* matrix, const FT_Vector* delta ) { - FT_Error error = FT_THROW( Unimplemented_Feature ); + FT_Error error = FT_Err_Ok; - FT_UNUSED( render ); - FT_UNUSED( slot ); - FT_UNUSED( matrix ); - FT_UNUSED( delta ); + if ( slot->format != render->glyph_format ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + if ( matrix ) + FT_Outline_Transform( &slot->outline, matrix ); + + if ( delta ) + FT_Outline_Translate( &slot->outline, delta->x, delta->y ); + + Exit: return error; } + /* returns the control box of glyph's outline */ static void ft_sdf_get_cbox( FT_Renderer render, FT_GlyphSlot slot, FT_BBox* cbox ) { - FT_UNUSED( render ); - FT_UNUSED( slot ); - FT_UNUSED( cbox ); + FT_ZERO( cbox ); + + if ( slot->format == render->glyph_format ) + FT_Outline_Get_CBox( &slot->outline, cbox ); } + /* set render specific modes or attributes */ static FT_Error ft_sdf_set_mode( FT_Renderer render, FT_ULong mode_tag, FT_Pointer data ) { - FT_Error error = FT_THROW( Unimplemented_Feature ); - - - FT_UNUSED( render ); - FT_UNUSED( mode_tag ); - FT_UNUSED( data ); - - return error; + /* pass it to the rasterizer */ + return render->clazz->raster_class->raster_set_mode( render->raster, + mode_tag, + data ); } FT_DEFINE_RENDERER(