- various performance enhancements

- fixing apinames.c, adding support for Watcom and Borland compilers
- adding generation of exported symbols list to the build system, including the Unix one !!

sorry Werner, I have no time to document this in ChangeLog at the moment
This commit is contained in:
David Turner 2005-10-28 16:14:14 +00:00
parent 69d45172b6
commit 9fbd2ab884
31 changed files with 683 additions and 567 deletions

View File

@ -155,12 +155,14 @@ SubInclude FT2_TOP $(FT2_SRC_DIR) tools ;
rule GenExportSymbols
{
local headers = [ Glob $(2) : *.h ] ;
local apinames = apinames$(SUFEXE) ;
local headers = [ Glob $(2) : *.h ] ;
APINAMES on $(1) = apinames$(SUFEXE) ;
Depends $(1) : $(headers) ;
Depends $(1) : $(apinames) $(headers) ;
GenExportSymbols1 $(1) : $(headers) ;
Clean clean : $(1) ;
}
actions GenExportSymbols1 bind APINAMES

View File

@ -55,6 +55,9 @@ L := /Fl
#
T := /Fo
# Target executable flag
#
TE := /Fe
# C flags
#

View File

@ -19,6 +19,10 @@ BUILD_DIR := $(TOP_DIR)/builds/dos
PLATFORM := dos
# The executable file extension (for tools). NOTE: WE INCLUDE THE DOT HERE !!
#
E := .exe
# The directory where all object files are placed.
#
# This lets you build the library in your own directory with something like

View File

@ -142,6 +142,9 @@ FT_COMPILE = $(CC) $(ANSIFLAGS) $(FT_CFLAGS)
#
include $(TOP_DIR)/builds/modules.mk
# Includes the 'exports' rules file.
#
include $(TOP_DIR)/builds/exports.mk
# Initialize the list of objects.
#
@ -247,6 +250,8 @@ objects: $(OBJECTS_LIST)
library: $(PROJECT_LIBRARY)
dll: $(PROJECT_LIBRARY) exported_symbols
.c.$O:
$(FT_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
@ -283,7 +288,7 @@ distclean_project_std: clean_project_std
# working correctly on Win9x.
#
clean_project_dos:
-$(DELETE) $(subst /,\,$(OBJ)/*.$O $(CLEAN) $(NO_OUTPUT))
-$(DELETE) $(subst /,\,$(OBJ_DIR)/*.$O $(CLEAN) $(NO_OUTPUT))
distclean_project_dos: clean_project_dos
-$(DELETE) $(subst /,\,$(PROJECT_LIBRARY) $(DISTCLEAN) $(NO_OUTPUT))

View File

@ -18,6 +18,9 @@ SEP := $(strip \ )
BUILD_DIR := $(TOP_DIR)/builds/os2
PLATFORM := os2
# The executable file extension (for tools). NOTE: WE INCLUDE THE DOT HERE !!
#
E := .exe
# The directory where all object files are placed.
#

View File

@ -280,27 +280,27 @@
else
{
ssize_t total_read_count;
FT_ERROR(( "FT_Stream_Open:" ));
FT_ERROR(( " could not `mmap' file `%s'\n", filepathname ));
stream->base = (unsigned char*)ft_alloc( NULL, stream->size );
if ( !stream->base )
{
FT_ERROR(( "FT_Stream_Open:" ));
FT_ERROR(( " could not `alloc' memory\n" ));
goto Fail_Map;
}
total_read_count = 0;
do {
ssize_t read_count;
read_count = read( file,
stream->base + total_read_count,
read_count = read( file,
stream->base + total_read_count,
stream->size - total_read_count );
if ( ( read_count == -1 ) )

View File

@ -90,11 +90,16 @@ CC := $(LIBTOOL) --mode=compile $(CCraw)
LDFLAGS := @LDFLAGS@
# export symbols (XXX: HOW TO DEAL WITH CROSS COMPILATION ?)
#
EXPORTS_LIST := $(OBJ_DIR)/ftexport.sym
CCexe := $(CCraw) # used to compile "apinames" only
# Library linking
#
LINK_LIBRARY = $(LIBTOOL) --mode=link $(CCraw) -o $@ $(OBJECTS_LIST) \
-rpath $(libdir) -version-info $(version_info) \
$(LDFLAGS)
$(LDFLAGS) -export-symbols $(EXPORTS_LIST)
# EOF

View File

@ -51,5 +51,4 @@ LIB_DIR := $(OBJ_DIR)
NO_OUTPUT := 2> /dev/null
# EOF

View File

@ -12,6 +12,11 @@
# indicate that you have read the license and understand and accept it
# fully.
# default definitions of the export list
#
EXPORTS_LIST = $(OBJ_DIR)/freetype.def
EXPORTS_OPTIONS = /DEF:$(EXPORTS_LIST)
APINAMES_OPTIONS := -dfreetype.dll -wB
include $(TOP_DIR)/builds/win32/win32-def.mk
include $(TOP_DIR)/builds/compiler/bcc.mk

View File

@ -12,6 +12,11 @@
# indicate that you have read the license and understand and accept it
# fully.
# default definitions of the export list
#
EXPORTS_LIST = $(OBJ_DIR)/freetype.def
EXPORTS_OPTIONS = $(EXPORTS_LIST)
APINAMES_OPTIONS := -dfreetype.dll -w
# include Win32-specific definitions
include $(TOP_DIR)/builds/win32/win32-def.mk

View File

@ -12,6 +12,11 @@
# indicate that you have read the license and understand and accept it
# fully.
# default definitions of the export list
#
EXPORTS_LIST = $(OBJ_DIR)/freetype.def
EXPORTS_OPTIONS = /DEF:$(EXPORTS_LIST)
APINAMES_OPTIONS := -dfreetype.dll -w
include $(TOP_DIR)/builds/win32/win32-def.mk
include $(TOP_DIR)/builds/compiler/visualage.mk

View File

@ -12,6 +12,11 @@
# indicate that you have read the license and understand and accept it
# fully.
# default definitions of the export list
#
EXPORTS_LIST = $(OBJ_DIR)/freetype.def
EXPORTS_OPTIONS = /DEF:$(EXPORTS_LIST)
APINAMES_OPTIONS := -dfreetype.dll -w
include $(TOP_DIR)/builds/win32/win32-def.mk
include $(TOP_DIR)/builds/compiler/intelc.mk

View File

@ -12,6 +12,11 @@
# indicate that you have read the license and understand and accept it
# fully.
# default definitions of the export list
#
EXPORTS_LIST = $(OBJ_DIR)/freetype.def
EXPORTS_OPTIONS = $(EXPORTS_LIST)
APINAMES_OPTIONS := -dfreetype.dll -w
# include Win32-specific definitions
include $(TOP_DIR)/builds/win32/win32-def.mk

View File

@ -12,6 +12,11 @@
# indicate that you have read the license and understand and accept it
# fully.
# definitions of the export list
#
EXPORTS_LIST = $(OBJ_DIR)/freetype.def
EXPORTS_OPTIONS = /DEF:$(EXPORTS_LIST)
APINAMES_OPTIONS := -dfreetype.dll -w
include $(TOP_DIR)/builds/win32/win32-def.mk
include $(TOP_DIR)/builds/compiler/visualc.mk

View File

@ -12,6 +12,11 @@
# indicate that you have read the license and understand and accept it
# fully.
# redefine export symbol definitions
#
EXPORTS_LIST = $(OBJ_DIR)/watcom-ftexports.lbc
EXPORTS_OPTIONS = -\"export @$(EXPORTS_LIST)\"-
APINAMES_OPTIONS := -wW
include $(TOP_DIR)/builds/win32/win32-def.mk
include $(TOP_DIR)/builds/compiler/watcom.mk

View File

@ -18,6 +18,9 @@ SEP := $(strip \ )
BUILD_DIR := $(TOP_DIR)/builds/win32
PLATFORM := win32
# The executable file extension (for tools). NOTE: WE INCLUDE THE DOT HERE !!
#
E := .exe
# The directory where all object files are placed.
#

View File

@ -59,7 +59,7 @@ FT_BEGIN_HEADER
FT_Int arg1;
FT_Int arg2;
FT_Matrix transform;
} FT_SubGlyphRec;
@ -117,6 +117,22 @@ FT_BEGIN_HEADER
FT_UInt n_points,
FT_UInt n_contours );
#define FT_GLYPHLOADER_CHECK_P(_loader,_count) \
( (_count) == 0 || (int)((_loader)->base.outline.n_points + \
(_loader)->current.outline.n_points + \
(_count)) <= (int)(_loader)->max_points )
#define FT_GLYPHLOADER_CHECK_C(_loader,_count) \
( (_count) == 0 || (int)((_loader)->base.outline.n_contours + \
(_loader)->current.outline.n_contours + \
(_count)) <= (int)(_loader)->max_contours )
#define FT_GLYPHLOADER_CHECK_POINTS(_loader,_points,_contours) \
( ( FT_GLYPHLOADER_CHECK_P(_loader,_points) && \
FT_GLYPHLOADER_CHECK_C(_loader,_contours) ) \
? 0 \
: FT_GlyphLoader_CheckPoints( (_loader), (_points), (_contours) ) )
/* check that there is enough space to add `n_subs' sub-glyphs to */
/* a glyph loader */
FT_BASE( FT_Error )

View File

@ -265,11 +265,55 @@
#endif /* AF_DEBUG */
/* compute the direction value of a given vector */
FT_LOCAL_DEF( AF_Direction )
af_direction_compute( FT_Pos dx,
FT_Pos dy )
{
#if 1
AF_Direction dir = AF_DIR_NONE;
if ( dx < 0 )
{
if ( dy < 0 )
{
if ( -dx*12 < -dy )
dir = AF_DIR_DOWN;
else if ( -dy*12 < -dx )
dir = AF_DIR_LEFT;
}
else /* dy >= 0 */
{
if ( -dx*12 < dy )
dir = AF_DIR_UP;
else if ( dy*12 < -dx )
dir = AF_DIR_LEFT;
}
}
else /* dx >= 0 */
{
if ( dy < 0 )
{
if ( dx*12 < -dy )
dir = AF_DIR_DOWN;
else if ( -dy*12 < dx )
dir = AF_DIR_RIGHT;
}
else /* dy >= 0 */
{
if ( dx*12 < dy )
dir = AF_DIR_UP;
else if ( dy*12 < dx )
dir = AF_DIR_RIGHT;
}
}
return dir;
#else
AF_Direction dir;
FT_Pos ax = FT_ABS( dx );
FT_Pos ay = FT_ABS( dy );
@ -291,6 +335,7 @@
}
return dir;
#endif
}
@ -350,7 +395,8 @@
} while ( angle_in == angle_seg );
first = start;
diff_in = af_angle_diff( angle_in, angle_seg );
AF_ANGLE_DIFF( diff_in, angle_in, angle_seg );
/* now, process all segments in the contour */
do
@ -373,7 +419,7 @@
} while ( angle_out == angle_seg );
diff_out = af_angle_diff( angle_seg, angle_out );
AF_ANGLE_DIFF( diff_out, angle_seg, angle_out );
if ( ( diff_in ^ diff_out ) < 0 )
{
@ -657,7 +703,8 @@
angle_in = af_angle_atan( in_x, in_y );
angle_out = af_angle_atan( out_x, out_y );
delta = af_angle_diff( angle_in, angle_out );
AF_ANGLE_DIFF( delta, angle_in, angle_out );
if ( delta < 2 && delta > -2 )
goto Is_Weak_Point;

View File

@ -138,9 +138,9 @@
/* copy the outline points in the loader's current */
/* extra points which is used to keep original glyph coordinates */
error = FT_GlyphLoader_CheckPoints( gloader,
slot->outline.n_points + 4,
slot->outline.n_contours );
error = FT_GLYPHLOADER_CHECK_POINTS( gloader,
slot->outline.n_points + 4,
slot->outline.n_contours );
if ( error )
goto Exit;

View File

@ -133,6 +133,20 @@ FT_BEGIN_HEADER
af_angle_diff( AF_Angle angle1,
AF_Angle angle2 );
#define AF_ANGLE_DIFF(result,angle1,angle2) \
FT_BEGIN_STMNT \
AF_Angle _delta = (angle2) - (angle1); \
\
\
_delta %= AF_ANGLE_2PI; \
if ( _delta < 0 ) \
_delta += AF_ANGLE_2PI; \
\
if ( _delta > AF_ANGLE_PI ) \
_delta -= AF_ANGLE_2PI; \
\
result = _delta; \
FT_END_STMNT
/*************************************************************************/
/*************************************************************************/

View File

@ -394,6 +394,38 @@
FT_MulFix( FT_Long a,
FT_Long b )
{
#if 1
FT_Long sa, sb;
FT_ULong ua, ub;
if ( a == 0 || b == 0x10000L )
return a;
sa = (a >> (sizeof(a)*8 - 1)); a = (a^sa) - sa;
sb = (b >> (sizeof(b)*8 - 1)); b = (b^sb) - sb;
ua = (FT_ULong)a;
ub = (FT_ULong)b;
if ( ua <= 2048 && ub <= 1048576L )
{
ua = ( ua * ub + 0x8000 ) >> 16;
}
else
{
FT_ULong al = ua & 0xFFFF;
ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) +
( ( al * ( ub & 0xFFFF ) + 0x8000 ) >> 16 );
}
sa ^= sb,
ua = (FT_ULong)((ua ^ sa) - sa);
return (FT_Long)ua;
#else
FT_Long s;
FT_ULong ua, ub;
@ -421,6 +453,7 @@
}
return ( s < 0 ? -(FT_Long)ua : (FT_Long)ua );
#endif
}

View File

@ -195,7 +195,7 @@
FT_Error error = FT_Err_Ok;
FT_Outline* base = &loader->base.outline;
FT_Outline* current = &loader->current.outline;
FT_Bool adjust = 1;
FT_Bool adjust = 0;
FT_UInt new_max, old_max;

View File

@ -109,6 +109,46 @@
z = ( ( x >= 0 ) ? x : - x ) | ( (y >= 0) ? y : -y );
shift = 0;
#if 1
/* determine msb bit index in 'shift' */
if ( z >= (1L << 16 ) )
{
z >>= 16;
shift += 16;
}
if ( z >= (1L << 8) )
{
z >>= 8;
shift += 8;
}
if ( z >= (1L << 4) )
{
z >>= 4;
shift += 4;
}
if ( z >= (1L << 2) )
{
z >>= 2;
shift += 2;
}
if ( z >= 1 )
shift += 1;
if ( shift < 28 )
{
shift = 28-shift;
vec->x = x << shift;
vec->y = y << shift;
}
else if ( shift > 28 )
{
shift -= 28;
vec->x = x >> shift;
vec->y = y >> shift;
shift = -shift;
}
#else
if ( z < ( 1L << 27 ) )
{
do
@ -116,7 +156,6 @@
shift++;
z <<= 1;
} while ( z < ( 1L << 27 ) );
vec->x = x << shift;
vec->y = y << shift;
}
@ -132,6 +171,7 @@
vec->y = y >> shift;
shift = -shift;
}
#endif
return shift;
}

View File

@ -403,7 +403,7 @@
check_points( CFF_Builder* builder,
FT_Int count )
{
return FT_GlyphLoader_CheckPoints( builder->loader, count, 0 );
return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
}
@ -465,7 +465,7 @@
return CFF_Err_Ok;
}
error = FT_GlyphLoader_CheckPoints( builder->loader, 0, 1 );
error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
if ( !error )
{
if ( outline->n_contours > 0 )

View File

@ -133,7 +133,7 @@
/* check that we have begun a new path */
FT_ASSERT( glyph->path_begun != 0 );
error = FT_GlyphLoader_CheckPoints( loader, 1, 0 );
error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 0 );
if ( !error )
{
FT_UInt n = outline->n_points;
@ -163,7 +163,7 @@
/* check that we have begun a new path */
FT_ASSERT( glyph->path_begun != 0 );
error = FT_GlyphLoader_CheckPoints( loader, 3, 0 );
error = FT_GLYPHLOADER_CHECK_POINTS( loader, 3, 0 );
if ( !error )
{
FT_Vector* vec = outline->points + outline->n_points;
@ -199,7 +199,7 @@
glyph->path_begun = 1;
/* check that there is space for a new contour and a new point */
error = FT_GlyphLoader_CheckPoints( loader, 1, 1 );
error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 1 );
if ( !error )
/* add new start point */
error = pfr_glyph_line_to( glyph, to );

View File

@ -609,148 +609,6 @@
}
#ifndef FT_OPTIMIZE_MEMORY
/*
* The kerning data embedded in a PFR font are (charcode,charcode)
* pairs; we need to translate them to (gindex,gindex) and sort
* the resulting array.
*/
static FT_UInt
pfr_get_gindex( PFR_Char chars,
FT_UInt count,
FT_UInt charcode )
{
FT_UInt min = 0;
FT_UInt max = count;
while ( min < max )
{
FT_UInt mid = ( min + max ) >> 1;
PFR_Char c = chars + mid;
if ( c->char_code == charcode )
return mid + 1;
if ( c->char_code < charcode )
min = mid + 1;
else
max = mid;
}
return 0;
}
FT_CALLBACK_DEF( int )
pfr_compare_kern_pairs( const void* pair1,
const void* pair2 )
{
FT_UInt32 p1 = PFR_KERN_PAIR_INDEX( (PFR_KernPair)pair1 );
FT_UInt32 p2 = PFR_KERN_PAIR_INDEX( (PFR_KernPair)pair2 );
if ( p1 < p2 )
return -1;
if ( p1 > p2 )
return 1;
return 0;
}
static FT_Error
pfr_sort_kerning_pairs( FT_Stream stream,
PFR_PhyFont phy_font )
{
FT_Error error;
FT_Memory memory = stream->memory;
PFR_KernPair pairs;
PFR_KernItem item;
PFR_Char chars = phy_font->chars;
FT_UInt num_chars = phy_font->num_chars;
FT_UInt count;
/* create kerning pairs array */
if ( FT_NEW_ARRAY( phy_font->kern_pairs, phy_font->num_kern_pairs ) )
goto Exit;
/*
* load all kerning items into the array,
* converting character codes into glyph indices
*/
pairs = phy_font->kern_pairs;
item = phy_font->kern_items;
count = 0;
for ( ; item; item = item->next )
{
FT_UInt limit = count + item->pair_count;
FT_Byte* p;
if ( limit > phy_font->num_kern_pairs )
{
error = PFR_Err_Invalid_Table;
goto Exit;
}
if ( FT_STREAM_SEEK( item->offset ) ||
FT_FRAME_ENTER( item->pair_count * item->pair_size ) )
goto Exit;
p = stream->cursor;
for ( ; count < limit; count++ )
{
PFR_KernPair pair = pairs + count;
FT_UInt char1, char2;
FT_Int kerning;
if ( item->flags & PFR_KERN_2BYTE_CHAR )
{
char1 = FT_NEXT_USHORT( p );
char2 = FT_NEXT_USHORT( p );
}
else
{
char1 = FT_NEXT_BYTE( p );
char2 = FT_NEXT_BYTE( p );
}
if ( item->flags & PFR_KERN_2BYTE_ADJ )
kerning = item->base_adj + FT_NEXT_SHORT( p );
else
kerning = item->base_adj + FT_NEXT_BYTE( p );
pair->glyph1 = pfr_get_gindex( chars, num_chars, char1 );
pair->glyph2 = pfr_get_gindex( chars, num_chars, char2 );
pair->kerning = kerning;
}
FT_FRAME_EXIT();
}
/* sort the resulting array */
ft_qsort( pairs, count,
sizeof ( PFR_KernPairRec ),
pfr_compare_kern_pairs );
Exit:
if ( error )
{
/* disable kerning data in case of error
*/
phy_font->num_kern_pairs = 0;
}
return error;
}
#endif /* !FT_OPTIMIZE_MEMORY */
static const PFR_ExtraItemRec pfr_phy_font_extra_items[] =
{
@ -829,10 +687,6 @@
FT_FREE( phy_font->blue_values );
phy_font->num_blue_values = 0;
#ifndef FT_OPTIMIZE_MEMORY
FT_FREE( phy_font->kern_pairs );
#endif
{
PFR_KernItem item, next;
@ -1071,11 +925,6 @@
phy_font->bct_offset = FT_STREAM_POS();
phy_font->cursor = NULL;
#ifndef FT_OPTIMIZE_MEMORY
/* now sort kerning pairs */
error = pfr_sort_kerning_pairs( stream, phy_font );
#endif
Exit:
return error;

View File

@ -422,8 +422,6 @@
/*************************************************************************/
/*************************************************************************/
#ifdef FT_OPTIMIZE_MEMORY
FT_LOCAL_DEF( FT_Error )
pfr_face_get_kerning( FT_Face pfrface, /* PFR_Face */
FT_UInt glyph1,
@ -546,51 +544,4 @@
return error;
}
#else /* !FT_OPTIMIZE_MEMORY */
FT_LOCAL_DEF( FT_Error )
pfr_face_get_kerning( FT_Face pfrface, /* PFR_Face */
FT_UInt glyph1,
FT_UInt glyph2,
FT_Vector* kerning )
{
PFR_Face face = (PFR_Face)pfrface;
FT_Error error = PFR_Err_Ok;
PFR_PhyFont phy_font = &face->phy_font;
PFR_KernPair pairs = phy_font->kern_pairs;
FT_UInt32 idx = PFR_KERN_INDEX( glyph1, glyph2 );
FT_UInt min, max;
kerning->x = 0;
kerning->y = 0;
min = 0;
max = phy_font->num_kern_pairs;
while ( min < max )
{
FT_UInt mid = ( min + max ) >> 1;
PFR_KernPair pair = pairs + mid;
FT_UInt32 pidx = PFR_KERN_PAIR_INDEX( pair );
if ( pidx == idx )
{
kerning->x = pair->kerning;
break;
}
if ( pidx < idx )
min = mid + 1;
else
max = mid;
}
return error;
}
#endif /* !FT_OPTIMIZE_MEMORY */
/* END */

View File

@ -217,14 +217,6 @@ FT_BEGIN_HEADER
( (FT_UInt32)p[-2] << 16 ) | p[-1] )
typedef struct PFR_KernPairRec_
{
FT_UInt glyph1;
FT_UInt glyph2;
FT_Int kerning;
} PFR_KernPairRec, *PFR_KernPair;
/************************************************************************/
typedef struct PFR_PhyFontRec_
@ -266,9 +258,6 @@ FT_BEGIN_HEADER
FT_UInt num_kern_pairs;
PFR_KernItem kern_items;
PFR_KernItem* kern_items_tail;
#ifndef FT_OPTIMIZE_MEMORY
PFR_KernPair kern_pairs;
#endif
/* not part of the spec, but used during load */
FT_UInt32 bct_offset;

View File

@ -1623,7 +1623,7 @@
t1_builder_check_points( T1_Builder builder,
FT_Int count )
{
return FT_GlyphLoader_CheckPoints( builder->loader, count, 0 );
return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
}
@ -1689,7 +1689,7 @@
return PSaux_Err_Ok;
}
error = FT_GlyphLoader_CheckPoints( builder->loader, 0, 1 );
error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
if ( !error )
{
if ( outline->n_contours > 0 )

View File

@ -1,323 +1,441 @@
/*
* This little program is used to parse the FreeType headers and
* find the declaration of all public API. This is easy, because
* they all look like the following:
*
* FT_EXPORT( return_type )
* function_name( function arguments );
*
* You must pass the list of header files as arguments. Wildcards are
* accepted if you are using GCC for compilation (and probably by
* other compilers too).
*
* Author: David Turner, 2005
*
* This code is explicitly placed into the public domain.
*
*/
#include <stdio.h>
#include <stdlib.h>
#define PROGRAM_NAME "apinames"
#define PROGRAM_VERSION "0.1"
#define LINEBUFF_SIZE 1024
static void
panic( const char* message )
{
fprintf( stderr, "PANIC: %s\n", message );
exit(2);
}
typedef struct
{
char* name;
unsigned int hash;
} NameRec, *Name;
static Name the_names;
static int num_names;
static int max_names;
static void
names_add( const char* name,
const char* end )
{
int nn, len, h;
Name nm;
if ( end <= name )
return;
/* compute hash value */
len = (int)(end - name);
h = 0;
for ( nn = 0; nn < len; nn++ )
h = h*33 + name[nn];
/* check for an pre-existing name */
for ( nn = 0; nn < num_names; nn++ )
{
nm = the_names + nn;
if ( nm->hash == h &&
memcmp( name, nm->name, len ) == 0 &&
nm->name[len] == 0 )
return;
}
/* add new name */
if ( num_names >= max_names )
{
max_names += (max_names >> 1) + 4;
the_names = realloc( the_names, sizeof(the_names[0])*max_names );
if ( the_names == NULL )
panic( "not enough memory" );
}
nm = &the_names[num_names++];
nm->hash = h;
nm->name = malloc( len+1 );
if ( nm->name == NULL )
panic( "not enough memory" );
memcpy( nm->name, name, len );
nm->name[len] = 0;
}
static int
name_compare( const void* name1,
const void* name2 )
{
Name n1 = (Name)name1;
Name n2 = (Name)name2;
return strcmp( n1->name, n2->name );
}
static void
names_sort( void )
{
qsort( the_names, (size_t)num_names, sizeof(the_names[0]), name_compare );
}
static void
names_dump( FILE* out )
{
int nn;
for ( nn = 0; nn < num_names; nn++ )
fprintf( out, "%s\n", the_names[nn].name );
}
static void
names_dump_windef( FILE* out )
{
int nn;
/* note that we assume that __cdecl was used when compiling the
* DLL object files.
*/
fprintf( out, "DESCRIPTION FreeType 2 DLL\n" );
fprintf( out, "EXPORTS\n" );
for ( nn = 0; nn < num_names; nn++ )
fprintf( out, " %s\n", the_names[nn].name );
}
/* states of the line parser */
typedef enum
{
STATE_START = 0, /* waiting for FT_EXPORT keyword and return type */
STATE_TYPE, /* type was read, waiting for function name */
} State;
static int
read_header_file( FILE* file, int verbose )
{
static char buff[ LINEBUFF_SIZE+1 ];
State state = STATE_START;
while ( !feof( file ) )
{
char* p;
if ( !fgets( buff, LINEBUFF_SIZE, file ) )
break;
p = buff;
while ( *p && (*p == ' ' || *p == '\\') ) /* skip leading whitespace */
p++;
if ( *p == '\n' || *p == '\r' ) /* skip empty lines */
continue;
switch ( state )
{
case STATE_START:
{
if ( memcmp( p, "FT_EXPORT(", 10 ) != 0 )
break;
p += 10;
for (;;)
{
if ( *p == 0 || *p == '\n' || *p == '\r' )
goto NextLine;
if ( *p == ')' )
{
p++;
break;
}
p++;
}
state = STATE_TYPE;
/* sometimes, the name is just after the FT_EXPORT(...), so
* skip whitespace, and fall-through if we find an alphanumeric
* character
*/
while ( *p == ' ' || *p == '\t' )
p++;
if ( !isalpha(*p) )
break;
}
/* fall-through */
case STATE_TYPE:
{
char* name = p;
size_t func_len;
while ( isalpha(*p) || *p == '_' )
p++;
if ( p > name )
{
if ( verbose )
fprintf( stderr, ">>> %.*s\n", p-name, name );
names_add( name, p );
}
state = STATE_START;
}
break;
default:
;
}
NextLine:
;
}
return 0;
}
static void
usage( void )
{
fprintf( stderr,
"%s %s: extract FreeType API names from header files\n\n"
"this program is used to extract the list of public FreeType API\n"
"functions. It receives the list of header files as argument and\n"
"generates a sorted list of unique identifiers\n\n"
"usage: %s header1 [options] [header2 ...]\n\n"
"options: - : parse the content of stdin, ignore arguments\n"
" -v : verbose mode\n",
" -w : output windows .DEF file\n"
,
PROGRAM_NAME,
PROGRAM_VERSION,
PROGRAM_NAME
);
exit(1);
}
int main( int argc, const char* const* argv )
{
int from_stdin = 0;
int verbose = 0;
int do_win_def = 0;
if ( argc < 2 )
usage();
/* '-' used as a single argument means read source file from stdin */
while ( argc > 1 && argv[1][0] == '-' )
{
switch ( argv[1][1] )
{
case 'v':
verbose = 1;
break;
case 'w':
do_win_def = 1;
break;
case 0:
from_stdin = 1;
break;
default:
usage();
}
argc--;
argv++;
}
if ( from_stdin )
{
read_header_file( stdin, verbose );
}
else
{
for ( --argc, argv++; argc > 0; argc--, argv++ )
{
FILE* file = fopen( argv[0], "rb" );
if ( file == NULL )
fprintf( stderr, "unable to open '%s'\n", argv[0] );
else
{
if ( verbose )
fprintf( stderr, "opening '%s'\n", argv[0] );
read_header_file( file, verbose );
fclose( file );
}
}
}
if ( num_names == 0 )
panic( "could not find exported functions !!\n" );
names_sort();
if ( do_win_def )
names_dump_windef( stdout );
else
names_dump( stdout );
return 0;
}
/*
* This little program is used to parse the FreeType headers and
* find the declaration of all public API. This is easy, because
* they all look like the following:
*
* FT_EXPORT( return_type )
* function_name( function arguments );
*
* You must pass the list of header files as arguments. Wildcards are
* accepted if you are using GCC for compilation (and probably by
* other compilers too).
*
* Author: David Turner, 2005
*
* This code is explicitly placed into the public domain.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PROGRAM_NAME "apinames"
#define PROGRAM_VERSION "0.1"
#define LINEBUFF_SIZE 1024
typedef enum
{
OUTPUT_LIST = 0, /* output the list of names, one per line */
OUTPUT_WINDOWS_DEF, /* output a Windows .DEF file for Visual C++ or Mingw */
OUTPUT_BORLAND_DEF, /* output a Windows .DEF file for Borland C++ */
OUTPUT_WATCOM_LBC /* output a Watcom Linker Command File */
} OutputFormat;
static void
panic( const char* message )
{
fprintf( stderr, "PANIC: %s\n", message );
exit(2);
}
typedef struct
{
char* name;
unsigned int hash;
} NameRec, *Name;
static Name the_names;
static int num_names;
static int max_names;
static void
names_add( const char* name,
const char* end )
{
int nn, len, h;
Name nm;
if ( end <= name )
return;
/* compute hash value */
len = (int)(end - name);
h = 0;
for ( nn = 0; nn < len; nn++ )
h = h*33 + name[nn];
/* check for an pre-existing name */
for ( nn = 0; nn < num_names; nn++ )
{
nm = the_names + nn;
if ( nm->hash == h &&
memcmp( name, nm->name, len ) == 0 &&
nm->name[len] == 0 )
return;
}
/* add new name */
if ( num_names >= max_names )
{
max_names += (max_names >> 1) + 4;
the_names = realloc( the_names, sizeof(the_names[0])*max_names );
if ( the_names == NULL )
panic( "not enough memory" );
}
nm = &the_names[num_names++];
nm->hash = h;
nm->name = malloc( len+1 );
if ( nm->name == NULL )
panic( "not enough memory" );
memcpy( nm->name, name, len );
nm->name[len] = 0;
}
static int
name_compare( const void* name1,
const void* name2 )
{
Name n1 = (Name)name1;
Name n2 = (Name)name2;
return strcmp( n1->name, n2->name );
}
static void
names_sort( void )
{
qsort( the_names, (size_t)num_names, sizeof(the_names[0]), name_compare );
}
static void
names_dump( FILE* out,
OutputFormat format,
const char* dll_name )
{
int nn;
switch ( format )
{
case OUTPUT_WINDOWS_DEF:
if ( dll_name )
fprintf( out, "LIBRARY %s\n", dll_name );
fprintf( out, "DESCRIPTION FreeType 2 DLL\n" );
fprintf( out, "EXPORTS\n" );
for ( nn = 0; nn < num_names; nn++ )
fprintf( out, " %s\n", the_names[nn].name );
break;
case OUTPUT_BORLAND_DEF:
if ( dll_name )
fprintf( out, "LIBRARY %s\n", dll_name );
fprintf( out, "DESCRIPTION FreeType 2 DLL\n" );
fprintf( out, "EXPORTS\n" );
for ( nn = 0; nn < num_names; nn++ )
fprintf( out, " _%s\n", the_names[nn].name );
break;
case OUTPUT_WATCOM_LBC:
{
/* we must omit the .dll suffix from the library name */
char temp[512];
char* dot;
if ( dll_name == NULL )
{
fprintf( stderr,
"you must provide a DLL name with the -d option !!\n" );
exit(4);
}
dot = strchr( dll_name, '.' );
if ( dot != NULL )
{
int len = (dot - dll_name);
if ( len > sizeof(temp)-1 )
len = sizeof(temp)-1;
memcpy( temp, dll_name, len );
temp[len] = 0;
dll_name = (const char*)temp;
}
for ( nn = 0; nn < num_names; nn++ )
fprintf( out, "++_%s.%s.%s\n", the_names[nn].name, dll_name,
the_names[nn].name );
}
break;
default: /* LIST */
for ( nn = 0; nn < num_names; nn++ )
fprintf( out, "%s\n", the_names[nn].name );
}
}
/* states of the line parser */
typedef enum
{
STATE_START = 0, /* waiting for FT_EXPORT keyword and return type */
STATE_TYPE, /* type was read, waiting for function name */
} State;
static int
read_header_file( FILE* file, int verbose )
{
static char buff[ LINEBUFF_SIZE+1 ];
State state = STATE_START;
while ( !feof( file ) )
{
char* p;
if ( !fgets( buff, LINEBUFF_SIZE, file ) )
break;
p = buff;
while ( *p && (*p == ' ' || *p == '\\') ) /* skip leading whitespace */
p++;
if ( *p == '\n' || *p == '\r' ) /* skip empty lines */
continue;
switch ( state )
{
case STATE_START:
{
if ( memcmp( p, "FT_EXPORT(", 10 ) != 0 )
break;
p += 10;
for (;;)
{
if ( *p == 0 || *p == '\n' || *p == '\r' )
goto NextLine;
if ( *p == ')' )
{
p++;
break;
}
p++;
}
state = STATE_TYPE;
/* sometimes, the name is just after the FT_EXPORT(...), so
* skip whitespace, and fall-through if we find an alphanumeric
* character
*/
while ( *p == ' ' || *p == '\t' )
p++;
if ( !isalpha(*p) )
break;
}
/* fall-through */
case STATE_TYPE:
{
char* name = p;
size_t func_len;
while ( isalnum(*p) || *p == '_' )
p++;
if ( p > name )
{
if ( verbose )
fprintf( stderr, ">>> %.*s\n", p-name, name );
names_add( name, p );
}
state = STATE_START;
}
break;
default:
;
}
NextLine:
;
}
return 0;
}
static void
usage( void )
{
fprintf( stderr,
"%s %s: extract FreeType API names from header files\n\n"
"this program is used to extract the list of public FreeType API\n"
"functions. It receives the list of header files as argument and\n"
"generates a sorted list of unique identifiers\n\n"
"usage: %s header1 [options] [header2 ...]\n\n"
"options: - : parse the content of stdin, ignore arguments\n"
" -v : verbose mode, output sent to standard error\n",
" -oFILE : write output to FILE instead of standard output\n"
" -dNAME : indicate DLL file name, 'freetype.dll' by default\n"
" -w : output .DEF file for Visual C++ and Mingw\n"
" -wB : output .DEF file for Borland C++\n"
" -wW : output Watcom Linker Response File\n"
"\n"
,
PROGRAM_NAME,
PROGRAM_VERSION,
PROGRAM_NAME
);
exit(1);
}
int main( int argc, const char* const* argv )
{
int from_stdin = 0;
int verbose = 0;
OutputFormat format = OUTPUT_LIST; /* the default */
FILE* out = stdout;
const char* library_name = NULL;
if ( argc < 2 )
usage();
/* '-' used as a single argument means read source file from stdin */
while ( argc > 1 && argv[1][0] == '-' )
{
const char* arg = argv[1];
switch ( arg[1] )
{
case 'v':
verbose = 1;
break;
case 'o':
if ( arg[2] == 0 )
{
if ( argc < 2 )
usage();
arg = argv[2];
argv++;
argc--;
}
else
arg += 2;
out = fopen( arg, "wt" );
if ( out == NULL )
{
fprintf( stderr, "could not open '%s' for writing\n", argv[2] );
exit(3);
}
break;
case 'd':
if ( arg[2] == 0 )
{
if ( argc < 2 )
usage();
arg = argv[2];
argv++;
argc--;
}
else
arg += 2;
library_name = arg;
break;
case 'w':
format = OUTPUT_WINDOWS_DEF;
switch ( arg[2] )
{
case 'B':
format = OUTPUT_BORLAND_DEF;
break;
case 'W':
format = OUTPUT_WATCOM_LBC;
break;
case 0:
break;
default:
usage();
}
break;
case 0:
from_stdin = 1;
break;
default:
usage();
}
argc--;
argv++;
}
if ( from_stdin )
{
read_header_file( stdin, verbose );
}
else
{
for ( --argc, argv++; argc > 0; argc--, argv++ )
{
FILE* file = fopen( argv[0], "rb" );
if ( file == NULL )
fprintf( stderr, "unable to open '%s'\n", argv[0] );
else
{
if ( verbose )
fprintf( stderr, "opening '%s'\n", argv[0] );
read_header_file( file, verbose );
fclose( file );
}
}
}
if ( num_names == 0 )
panic( "could not find exported functions !!\n" );
names_sort();
names_dump( out, format, library_name );
if ( out != stdout )
fclose( out );
return 0;
}

View File

@ -420,7 +420,7 @@
/* check that we can add the contours to the glyph */
error = FT_GlyphLoader_CheckPoints( gloader, 0, n_contours );
error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
if ( error )
goto Fail;
@ -441,7 +441,7 @@
n_points = cont[-1] + 1;
/* note that we will add four phantom points later */
error = FT_GlyphLoader_CheckPoints( gloader, n_points + 4, 0 );
error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
if ( error )
goto Fail;
@ -1106,9 +1106,9 @@
outline = &loader->gloader->base.outline;
/* make room for phantom points */
error = FT_GlyphLoader_CheckPoints( loader->gloader,
outline->n_points + 4,
0 );
error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
outline->n_points + 4,
0 );
if ( error )
return error;