@ -1,6 +1,18 @@
// we use `unique_ptr' and `decltype', defined since C++11
# if __cplusplus < 201103L
# error "a C++11 compiler is needed"
# endif
# include <assert.h>
# include <stdint.h>
# include <memory>
# include <vector>
using namespace std ;
# include <ft2build.h>
# include FT_FREETYPE_H
@ -16,60 +28,147 @@
# include FT_MODULE_H
# include FT_CFF_DRIVER_H
# include FT_TRUETYPE_DRIVER_H
# include FT_MULTIPLE_MASTERS_H
static FT_Library library ;
static int InitResult = FT_Init_FreeType ( & library ) ;
static int InitResult ;
struct FT_Global {
FT_Global ( ) {
InitResult = FT_Init_FreeType ( & library ) ;
}
~ FT_Global ( ) {
FT_Done_FreeType ( library ) ;
}
} ;
FT_Global global_ft ;
static void
setIntermediateAxis ( FT_Face face )
{
// only handle Multiple Masters and GX variation fonts
if ( ! ( face - > face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) )
return ;
// get variation data for current instance
FT_MM_Var * variations_ptr = nullptr ;
if ( FT_Get_MM_Var ( face , & variations_ptr ) )
return ;
unique_ptr < FT_MM_Var ,
decltype ( free ) * > variations ( variations_ptr , free ) ;
vector < FT_Fixed > coords ( variations - > num_axis ) ;
// select an arbitrary instance
for ( unsigned int i = 0 ; i < variations - > num_axis ; i + + )
coords [ i ] = ( variations - > axis [ i ] . minimum +
variations - > axis [ i ] . def ) / 2 ;
if ( FT_Set_Var_Design_Coordinates ( face ,
coords . size ( ) ,
coords . data ( ) ) )
return ;
}
extern " C " int
LLVMFuzzerTestOneInput ( const uint8_t * data ,
size_t size )
size_t size_ )
{
assert ( ! InitResult ) ;
if ( size < 1 )
if ( size_ < 1 )
return 0 ;
long size = ( long ) size_ ;
FT_Face face ;
FT_Int32 load_flags = FT_LOAD_DEFAULT ;
#if 0
FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL ;
# endif
// We use a conservative approach here, at the cost of calling
// `FT_New_Face' quite often. The idea is that the fuzzer should be
// able to try all faces and named instances of a font, expecting that
// some faces don't work for various reasons, e.g., a broken subfont, or
// an unsupported NFNT bitmap font in a Mac dfont resource that holds
// more than a single font.
if ( ! FT_New_Memory_Face ( library , data , size , 0 , & face ) )
// get number of faces
if ( FT_New_Memory_Face ( library , data , size , - 1 , & face ) )
return 0 ;
long num_faces = face - > num_faces ;
FT_Done_Face ( face ) ;
// loop over all faces
for ( long face_index = 0 ;
face_index < num_faces ;
face_index + + )
{
unsigned int first_index = 0 ;
// get number of instances
if ( FT_New_Memory_Face ( library ,
data ,
size ,
- ( face_index + 1 ) ,
& face ) )
continue ;
long num_instances = face - > style_flags > > 16 ;
FT_Done_Face ( face ) ;
for ( unsigned i = first_index ;
i < ( unsigned int ) face - > num_glyphs ;
i + + )
// load face with and without instances
for ( long instance_index = 0 ;
instance_index < num_instances + 1 ;
instance_index + + )
{
if ( FT_Load_Glyph ( face , i , load_flags ) )
if ( FT_New_Memory_Face ( library ,
data ,
size ,
( instance_index < < 16 ) + face_index ,
& face ) )
continue ;
// Rendering is the most expensive and the least interesting part.
//
// if ( FT_Render_Glyph( face->glyph, render_mode) )
// continue;
// FT_GlyphSlot_Embolden( face->glyph );
// set up 20pt at 72dpi as an arbitrary size
FT_Set_Char_Size ( face , 20 , 20 , 72 , 72 ) ;
#if 0
FT_Glyph glyph ;
// test MM interface only for a face without a selected instance
if ( instance_index = = 0 )
setIntermediateAxis ( face ) ;
// loop over all glyphs
for ( unsigned int glyph_index = 0 ;
glyph_index < ( unsigned int ) face - > num_glyphs ;
glyph_index + + )
{
if ( FT_Load_Glyph ( face , glyph_index , load_flags ) )
continue ;
if ( ! FT_Get_Glyph ( face - > glyph , & glyph ) )
FT_Done_Glyph ( glyph ) ;
// Rendering is the most expensive and the least interesting part.
//
// if ( FT_Render_Glyph( face->glyph, render_mode) )
// continue;
// FT_GlyphSlot_Embolden( face->glyph );
FT_Outline * outline = & face - > glyph - > outline ;
FT_Matrix rot30 = { 0xDDB4 , - 0x8000 , 0x8000 , 0xDDB4 } ;
#if 0
FT_Glyph glyph ;
if ( ! FT_Get_Glyph ( face - > glyph , & glyph ) )
FT_Done_Glyph ( glyph ) ;
FT_Outline_Transform ( outline , & rot30 ) ;
FT_Outline * outline = & face - > glyph - > outline ;
FT_Matrix rot30 = { 0xDDB4 , - 0x8000 , 0x8000 , 0xDDB4 } ;
FT_BBox bbox ;
FT_Outline_Transform ( outline , & rot30 ) ;
FT_Outline_Get_BBox ( outline , & bbox ) ;
FT_BBox bbox ;
FT_Outline_Get_BBox ( outline , & bbox ) ;
# endif
}
}
FT_Done_Face ( face ) ;
FT_Done_Face ( face ) ;
}
}
return 0 ;