From 929ff6996c020b7cda3c8d928cf3f2de4b063708 Mon Sep 17 00:00:00 2001 From: David Turner Date: Mon, 13 Apr 2009 00:20:03 +0200 Subject: [PATCH] Introduce FT_PicDataRec in include/freetype/internal/ftpic.h Modify a few users to use it. --- include/freetype/internal/ftpic.h | 91 +++++++++++++++++++++++++++++-- src/base/basepic.c | 62 +++++++++------------ src/base/basepic.h | 2 +- src/base/ftinit.c | 37 +++++++------ src/base/ftobjs.c | 2 +- src/base/ftpic.c | 68 ++++++++++++++++++++++- src/truetype/ttpic.c | 60 +++++++++----------- 7 files changed, 225 insertions(+), 97 deletions(-) diff --git a/include/freetype/internal/ftpic.h b/include/freetype/internal/ftpic.h index 8c441d6b6..f887a0f67 100644 --- a/include/freetype/internal/ftpic.h +++ b/include/freetype/internal/ftpic.h @@ -31,6 +31,51 @@ FT_BEGIN_HEADER #ifdef FT_CONFIG_OPTION_PIC + /* A FT_PicDataRec object models a heap-allocated structure + * used to hold data that, in non-PIC builds of the engine, + * would be constant and contain pointers. + * + * The FT_PicDataRec contains book-keeping information about + * the structure, whose exact fields depend on which module + * is defining/using it. The structure itself can be + * accessed as the 'data' field of a FT_PicDataRec object. + */ + typedef struct FT_PicDataRec_* FT_PicData; + + /* A FT_PicTableRec object contains the FT_PicDataRec of all + * PIC structures needed by the library at runtime. + */ + typedef struct FT_PicTableRec_* FT_PicTable; + + /* A special callback function call to finalize the structure + * backed by a FT_PicDataRec object. It is called by + * ft_pic_table_done_data and its first parameter is the 'data' + * field of the corresponding FT_PicDataRec. Note that the + * PIC structure itself is allocated by ft_pic_table_init_data + * and freed by ft_pic_table_done_data. + */ + typedef void (*FT_PicDataDoneFunc)( void* data, FT_PicTable pic ); + + /* A special initialization function called by ft_pic_table_init_data + * to initialize a freshly allocated PIC structure. + */ + typedef FT_Error (*FT_PicDataInitFunc)( void* data, FT_PicTable pic ); + + /* The FT_PicDataRec itself holds a pointer to heap-allocated + * PIC data, a reference count and an optional finalizer function. + * + * One should call ft_pic_table_init_data() to register a new + * heap-allocated PIC structure, which address will be placed + * into the 'data' field. + */ + typedef struct FT_PicDataRec_ + { + void* data; + FT_Int ref_count; + FT_PicDataDoneFunc done; + + } FT_PicDataRec; + /* When FT_CONFIG_OPTION_PIC is defined, the FT_PicTable * is used to hold all constant structures that normally * contain pointers in the normal build of FreeType. @@ -41,10 +86,20 @@ FT_BEGIN_HEADER */ typedef struct FT_PicTableRec_ { - /* pic containers for base */ - void* base; + FT_Library library; + FT_Memory memory; + +/* this macro is used to define the list of FT_PicDataRec + * stored in the PIC table. Add new entries here. + */ +#define FT_PIC_ENTRY_LIST \ + _FT_PICDATA( base ) \ + +/* now define the entries in the PIC table itself */ +#define _FT_PICDATA(name) FT_PicDataRec name [1]; + FT_PIC_ENTRY_LIST +#undef _FT_PICDATA - /* pic containers for modules */ void* autofit; void* cff; void* pshinter; @@ -54,13 +109,39 @@ FT_BEGIN_HEADER void* smooth; void* truetype; - } FT_PicTableRec, *FT_PicTable; + } FT_PicTableRec; + +#define FT_LIBRARY_GET_PIC_DATA(library_,name_) \ + library_->pic_table.name_->data + + /* allocate and initialize a PIC structure in the heap. + * This should be called at module initialization time + * before the PIC data can be used. + * + * if the structure already exists, this simply increments + * its reference count. + */ + FT_BASE( FT_Error ) + ft_pic_table_init_data( FT_PicTable table, + FT_PicData data, + FT_UInt data_size, + FT_PicDataInitFunc data_init, + FT_PicDataDoneFunc data_done ); + + /* finalize and free a given PIC structure. This really + * decrements the reference count and performs destruction + * if it reaches 0. + * + * this should be called a module exit time. + */ + FT_BASE( void ) + ft_pic_table_done_data( FT_PicTable table, + FT_PicData data ); /* Initialize the PIC table's base */ FT_BASE( FT_Error ) ft_library_pic_init( FT_Library library ); - /* Destroy the contents of the PIC table. */ FT_BASE( void ) ft_library_pic_done( FT_Library library ); diff --git a/src/base/basepic.c b/src/base/basepic.c index b0d6a18cb..280dc7012 100644 --- a/src/base/basepic.c +++ b/src/base/basepic.c @@ -31,21 +31,32 @@ FT_Error ft_create_default_module_classes(FT_Library); void ft_destroy_default_module_classes(FT_Library); - void - ft_base_pic_free( FT_Library library ) + static void + pic_base_done( void* base, FT_PicTable pic ) { - FT_PicTable pic_table = &library->pic_table; - FT_Memory memory = library->memory; + FT_UNUSED(base); + /* Destroy default module classes (in case FT_Add_Default_Modules was used) */ + ft_destroy_default_module_classes( pic->library ); + } - if ( pic_table->base ) - { - /* Destroy default module classes (in case FT_Add_Default_Modules was used) */ - ft_destroy_default_module_classes( library ); + static FT_Error + pic_base_init( void* data, FT_PicTable pic ) + { + BasePIC* base = (BasePIC*)data; + FT_Error error; - FT_FREE( pic_table->base ); - pic_table->base = NULL; - } + /* initialize default modules list and pointers */ + error = ft_create_default_module_classes( pic->library ); + if ( error ) + goto Exit; + + /* initialize pointer table - this is how the module usually expects this data */ + ft_pic_init_ft_outline_glyph_class(&base->ft_outline_glyph_class); + ft_pic_init_ft_bitmap_glyph_class(&base->ft_bitmap_glyph_class); + + Exit: + return error; } @@ -53,33 +64,14 @@ ft_base_pic_init( FT_Library library ) { FT_PicTable pic_table = &library->pic_table; - FT_Error error = FT_Err_Ok; - FT_Memory memory = library->memory; - BasePIC* container; - /* allocate pointer, clear and set global container pointer */ - if ( FT_NEW ( container ) ) - return error; - - pic_table->base = container; - - /* initialize default modules list and pointers */ - error = ft_create_default_module_classes( library ); - if ( error ) - goto Exit; - - /* initialize pointer table - this is how the module usually expects this data */ - ft_pic_init_ft_outline_glyph_class(&container->ft_outline_glyph_class); - ft_pic_init_ft_bitmap_glyph_class(&container->ft_bitmap_glyph_class); - -Exit: - if(error) - ft_base_pic_free(library); - - return error; + return ft_pic_table_init_data( pic_table, + pic_table->base, + sizeof(BasePIC), + pic_base_init, + pic_base_done ); } - #endif /* FT_CONFIG_OPTION_PIC */ diff --git a/src/base/basepic.h b/src/base/basepic.h index e9eb68cff..11936ea7d 100644 --- a/src/base/basepic.h +++ b/src/base/basepic.h @@ -43,7 +43,7 @@ FT_BEGIN_HEADER #define GET_PIC(lib) ((BasePIC*)((lib)->pic_table.base)) #define FT_OUTLINE_GLYPH_CLASS_GET (&GET_PIC(library)->ft_outline_glyph_class) #define FT_BITMAP_GLYPH_CLASS_GET (&GET_PIC(library)->ft_bitmap_glyph_class) -#define FT_DEFAULT_MODULES_GET (GET_PIC(library)->default_module_classes) +#define FT_DEFAULT_MODULES_GET (const FT_Module_Class* const*)(GET_PIC(library)->default_module_classes) void ft_base_pic_free( FT_Library library ); diff --git a/src/base/ftinit.c b/src/base/ftinit.c index 9ed6c4274..ba830b218 100644 --- a/src/base/ftinit.c +++ b/src/base/ftinit.c @@ -115,7 +115,7 @@ FT_Module_Class** classes; FT_Memory memory; FT_UInt i; - BasePIC* pic_table = library->pic_table.base; + BasePIC* pic_table = FT_LIBRARY_GET_PIC_DATA(library, base); if ( !pic_table->default_module_classes ) return; @@ -130,13 +130,6 @@ pic_table->default_module_classes = 0; } - /* initialize all module classes and the pointer table */ -#undef FT_USE_MODULE -#define FT_USE_MODULE( type, x ) \ - error = ft_library_pic_alloc_##x(library, &clazz); \ - if (error) goto Exit; \ - classes[i++] = clazz; - FT_BASE_DEF( FT_Error ) ft_create_default_module_classes( FT_Library library ) { @@ -145,27 +138,35 @@ FT_Module_Class** classes; FT_Module_Class* clazz; FT_UInt i; - BasePIC* pic_table = library->pic_table.base; + BasePIC* pic_table = FT_LIBRARY_GET_PIC_DATA(library, base); memory = library->memory; pic_table->default_module_classes = 0; - if ( FT_ALLOC(classes, sizeof(FT_Module_Class*) * (FT_NUM_MODULE_CLASSES + 1) ) ) + if ( FT_NEW_ARRAY(classes, FT_NUM_MODULE_CLASSES + 1 ) ) return error; - /* initialize all pointers to 0, especially the last one */ - for (i = 0; i < FT_NUM_MODULE_CLASSES; i++) - classes[i] = 0; - classes[FT_NUM_MODULE_CLASSES] = 0; i = 0; + /* initialize all module classes and the pointer table */ +#undef FT_USE_MODULE +#define FT_USE_MODULE( type, x ) \ + error = ft_library_pic_alloc_##x(library, &clazz); \ + if (error) \ + goto Exit; \ + \ + classes[i++] = clazz; + #include FT_CONFIG_MODULES_H +#undef FT_USE_MODULE -Exit: - if (error) ft_destroy_default_module_classes( library ); - else pic_table->default_module_classes = classes; +Exit: + if (error) + ft_destroy_default_module_classes( library ); + else + pic_table->default_module_classes = classes; - return error; + return error; } diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index cdbc40de8..04f5b0153 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -4144,7 +4144,7 @@ Fail: #ifdef FT_CONFIG_OPTION_PIC - ft_library_done_pic( library ); + ft_library_pic_done( library ); #endif FT_FREE( library ); return error; diff --git a/src/base/ftpic.c b/src/base/ftpic.c index ba07ae5f4..095bbf67a 100644 --- a/src/base/ftpic.c +++ b/src/base/ftpic.c @@ -25,13 +25,75 @@ /* documentation is in ftpic.h */ + FT_BASE_DEF( FT_Error ) + ft_pic_table_init_data( FT_PicTable pic, + FT_PicData data, + FT_UInt data_size, + FT_PicDataInitFunc data_init, + FT_PicDataDoneFunc data_done ) + { + void* pic_data = data->data; + FT_Error error = 0; + FT_Memory memory = pic->memory; + + /* if the PIC structure already exist, just increment its + * reference count + */ + if (pic_data != NULL) + { + data->ref_count += 1; + return 0; + } + + if ( FT_ALLOC( pic_data, data_size ) ) + goto Exit; + + error = data_init( pic_data, pic ); + if (error) + { + if (data_done) + data_done( pic_data, pic ); + + FT_FREE( pic_data ); + goto Exit; + } + + data->data = pic_data; + data->ref_count = 1; + data->done = data_done; + + Exit: + return error; + } + + + FT_BASE_DEF( void ) + ft_pic_table_done_data( FT_PicTable pic, + FT_PicData data ) + { + FT_Memory memory = pic->memory; + + if ( --data->ref_count != 0 ) + return; + + if (data->done) + data->done( data->data, pic ); + + FT_FREE(data->data); + data->done = NULL; + } + + FT_BASE_DEF( FT_Error ) ft_library_pic_init( FT_Library library ) { - FT_PicTable pic_table = &library->pic_table; - FT_Error error = FT_Err_Ok; + FT_PicTable pic = &library->pic_table; + FT_Error error = FT_Err_Ok; - FT_ZERO(pic_table); + FT_ZERO(pic); + + pic->library = library; + pic->memory = library->memory; error = ft_base_pic_init( library ); if(error) diff --git a/src/truetype/ttpic.c b/src/truetype/ttpic.c index 6cc210e83..09ba3f473 100644 --- a/src/truetype/ttpic.c +++ b/src/truetype/ttpic.c @@ -29,57 +29,49 @@ void ft_pic_init_tt_service_gx_multi_masters(FT_Service_MultiMastersRec*); void ft_pic_init_tt_service_truetype_glyf(FT_Service_TTGlyfRec*); - void - tt_driver_class_pic_free( FT_Library library ) + static void + pic_tt_driver_done( void* data, FT_PicTable pic ) { - FT_PicTable pic_table = &library->pic_table; - FT_Memory memory = library->memory; + TTModulePIC* container = (TTModulePIC*) data; - if ( pic_table->truetype ) + if (container->tt_services) { - TTModulePIC* container = (TTModulePIC*)pic_table->truetype; - - if(container->tt_services) - { - ft_library_pic_free_tt_services(library, container->tt_services); - container->tt_services = NULL; - } - FT_FREE( container ); - pic_table->truetype = NULL; + ft_library_pic_free_tt_services(pic->library, container->tt_services); + container->tt_services = NULL; } } - - FT_Error - tt_driver_class_pic_init( FT_Library library ) + static FT_Error + pic_tt_driver_init( void* data, FT_PicTable pic ) { - FT_PicTable pic_table = &library->pic_table; - FT_Error error = FT_Err_Ok; - FT_Memory memory = library->memory; - TTModulePIC* container; + TTModulePIC* container = (TTModulePIC*) data; + FT_Error error; - /* allocate pointer, clear and set global container pointer */ - if ( FT_NEW ( container ) ) - return error; - - pic_table->truetype = container; - - /* initialize pointer table - this is how the module usually expects this data */ - error = ft_library_pic_alloc_tt_services(library, &container->tt_services); - if(error) + error = ft_library_pic_alloc_tt_services(pic->library, &container->tt_services); + if (error) goto Exit; + #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT ft_pic_init_tt_service_gx_multi_masters(&container->tt_service_gx_multi_masters); #endif ft_pic_init_tt_service_truetype_glyf(&container->tt_service_truetype_glyf); -Exit: - if(error) - tt_driver_class_pic_free(library); - + Exit: return error; } + FT_Error + tt_driver_class_pic_init( FT_Library library ) + { + FT_PicTable pic_table = &library->pic_table; + + return ft_pic_table_init_data( pic_table, + pic_table->truetype, + sizeof(TTModulePIC), + pic_tt_driver_init, + pic_tt_driver_done ); + } + #endif /* FT_CONFIG_OPTION_PIC */