diff --git a/ChangeLog b/ChangeLog index fb56e4f59..cde05d7a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,20 @@ * include/freetype/internal/ftmemory.h: adding FT_ARRAY_ZERO, as a convenience macro. + * include/freetype/config/ftoption.h, include/freetype/internal/ttypes.h, + src/truetype/ttpload.c, src/truetype/ttpload.h, src/truetype/ttgload.c: + added the temporary configuration FT_OPTIMIZE_MEMORY to control various + optimizations used to reduce the heap footprint of memory-mapped TrueType + files. + + * src/truetype/ttpload.c (tt_face_load_loca, tt_face_get_location, + tt_face_done_loca): when FT_OPTIMIZE_MEMORY is set, the locations table + is read directly from memory-mapped streams, instead of being decoded + into the heap. + + * src/truetype/ttpload.c: only load the CVT and fpgm tables when the + bytecode interpreter is compiled in. + 2005-02-20 Werner Lemberg diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h index 1d9efe4c5..c3d06c412 100644 --- a/include/freetype/config/ftoption.h +++ b/include/freetype/config/ftoption.h @@ -568,6 +568,8 @@ FT_BEGIN_HEADER #endif /* FT_CONFIG_OPTION_CHESTER_HINTS */ +#define FT_OPTIMIZE_MEMORY + FT_END_HEADER diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h index 4a3aab1aa..183beb8b9 100644 --- a/include/freetype/internal/tttypes.h +++ b/include/freetype/internal/tttypes.h @@ -361,6 +361,7 @@ FT_BEGIN_HEADER } TT_HdmxRec, *TT_Hdmx; + /*************************************************************************/ /* */ /* */ @@ -1263,9 +1264,14 @@ FT_BEGIN_HEADER /* */ /***********************************************************************/ +#ifdef FT_OPTIMIZE_MEMORY + FT_UInt num_locations; + FT_Byte* glyph_locations; +#else /* the glyph locations */ FT_UShort num_locations; FT_Long* glyph_locations; +#endif /* the font program, if any */ FT_ULong font_program_size; @@ -1297,7 +1303,7 @@ FT_BEGIN_HEADER FT_Bool doblend; GX_Blend blend; #endif - + /***********************************************************************/ /* */ /* Other tables or fields. This is used by derivative formats like */ diff --git a/src/autohint/ahglyph.c b/src/autohint/ahglyph.c index 5bf198830..7db7bb9bf 100644 --- a/src/autohint/ahglyph.c +++ b/src/autohint/ahglyph.c @@ -304,12 +304,15 @@ if ( FT_RENEW_ARRAY( outline->points, max, news ) || - FT_RENEW_ARRAY( outline->horz_edges, max * 2, news * 2 ) || - FT_RENEW_ARRAY( outline->horz_segments, max * 2, news * 2 ) ) + FT_RENEW_ARRAY( outline->horz_edges, max * 2, news * 2 ) ) + goto Exit; + + outline->vert_edges = outline->horz_edges + news; + + if ( FT_RENEW_ARRAY( outline->horz_segments, max * 2, news * 2 ) ) goto Exit; /* readjust some pointers */ - outline->vert_edges = outline->horz_edges + news; outline->vert_segments = outline->horz_segments + news; outline->max_points = news; } diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c index 145ac98aa..036a7d2ed 100644 --- a/src/truetype/ttgload.c +++ b/src/truetype/ttgload.c @@ -1019,13 +1019,7 @@ #endif /* FT_CONFIG_OPTION_INCREMENTAL */ - { - offset = face->glyph_locations[glyph_index]; - count = 0; - - if ( glyph_index < (FT_UInt)face->num_locations - 1 ) - count = (FT_UInt)( face->glyph_locations[glyph_index + 1] - offset ); - } + offset = tt_face_get_location( face, glyph_index, &count ); if ( count == 0 ) { diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c index b606ace6d..095292d65 100644 --- a/src/truetype/ttobjs.c +++ b/src/truetype/ttobjs.c @@ -218,8 +218,11 @@ if ( !face->root.internal->incremental_interface ) error = tt_face_load_loca( face, stream ); if ( !error ) - error = tt_face_load_cvt( face, stream ) || - tt_face_load_fpgm( face, stream ); + { + error = tt_face_load_cvt( face, stream ); + if ( !error ) + error = tt_face_load_fpgm( face, stream ); + } #else @@ -290,8 +293,7 @@ sfnt->done_face( face ); /* freeing the locations table */ - FT_FREE( face->glyph_locations ); - face->num_locations = 0; + tt_face_done_loca( face ); /* freeing the CVT */ FT_FREE( face->cvt ); diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c index 9cae477c5..cc2eb61d4 100644 --- a/src/truetype/ttpload.c +++ b/src/truetype/ttpload.c @@ -58,6 +58,118 @@ /* */ /* FreeType error code. 0 means success. */ /* */ +#ifdef FT_OPTIMIZE_MEMORY + + FT_LOCAL_DEF( FT_Error ) + tt_face_load_loca( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_ULong table_len; + + + FT_TRACE2(( "Locations " )); + error = face->goto_table( face, TTAG_loca, stream, &table_len ); + if ( error ) + { + error = TT_Err_Locations_Missing; + goto Exit; + } + + if ( face->header.Index_To_Loc_Format != 0 ) + { + if ( table_len >= 040000 ) + { + FT_TRACE2(( "table too large !!\n" )); + error = TT_Err_Invalid_Table; + goto Exit; + } + face->num_locations = (FT_UInt)(table_len >> 2); + } + else + { + if ( table_len >= 0x20000 ) + { + FT_TRACE2(( "table too large !!\n" )); + error = TT_Err_Invalid_Table; + goto Exit; + } + face->num_locations = (FT_UInt)(table_len >> 1); + } + + + /* extract the frame. We don't need to decompress it since + * we'll be able to parse it directly + */ + if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) ) + goto Exit; + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + + + FT_LOCAL_DEF( FT_ULong ) + tt_face_get_location( TT_Face face, + FT_UInt gindex, + FT_UInt *asize ) + { + FT_ULong pos1, pos2; + FT_Byte* p; + FT_Byte* p_limit; + + pos1 = pos2 = 0; + if ( gindex < face->num_locations ) + { + if ( face->header.Index_To_Loc_Format != 0 ) + { + p = face->glyph_locations + gindex*4; + p_limit = face->glyph_locations + face->num_locations*4; + + pos1 = FT_NEXT_ULONG(p); + pos2 = pos1; + + if ( p+4 <= p_limit ) + pos2 = FT_NEXT_ULONG(p); + } + else + { + p = face->glyph_locations + gindex*2; + p_limit = face->glyph_locations + face->num_locations*2; + + pos1 = FT_NEXT_USHORT(p); + pos2 = pos1; + + if ( p+2 <= p_limit ) + pos2 = FT_NEXT_USHORT(p); + + pos1 <<= 1; + pos2 <<= 1; + } + } + + *asize = (FT_UInt)(pos2 - pos1); + + return pos1; + } + + + FT_LOCAL_DEF( void ) + tt_face_done_loca( TT_Face face ) + { + FT_Stream stream = face->root.stream; + + FT_FRAME_RELEASE( face->glyph_locations ); + face->num_locations = 0; + } + + + +#else /* !FT_OPTIMIZE_MEMORY */ + FT_LOCAL_DEF( FT_Error ) tt_face_load_loca( TT_Face face, FT_Stream stream ) @@ -130,6 +242,39 @@ } + FT_LOCAL_DEF( FT_ULong ) + tt_face_get_location( TT_Face face, + FT_UInt gindex, + FT_UInt *asize ) + { + FT_ULong offset; + FT_UInt count; + + offset = face->glyph_locations[gindex]; + count = 0; + + if ( gindex < (FT_UInt)face->num_locations - 1 ) + count = (FT_UInt)( face->glyph_locations[gindex + 1] - offset ); + + *asize = count; + return offset; + } + + + FT_LOCAL_DEF( void ) + tt_face_done_loca( TT_Face face ) + { + FT_Memory memory = face->root.memory; + + FT_FREE( face->glyph_locations ); + face->num_locations = 0; + } + + + +#endif /* !FT_OPTIMIZE_MEMORY */ + + /*************************************************************************/ /* */ /* */ @@ -151,6 +296,8 @@ tt_face_load_cvt( TT_Face face, FT_Stream stream ) { +#ifdef FT_CONFIG_OPTION_BYTECODE_INTERPRETER + FT_Error error; FT_Memory memory = stream->memory; FT_ULong table_len; @@ -197,6 +344,12 @@ Exit: return error; + +#else /* !BYTECODE_INTERPRETER */ + FT_UNUSED(face); + FT_UNUSED(stream); + return 0; +#endif } @@ -221,6 +374,8 @@ tt_face_load_fpgm( TT_Face face, FT_Stream stream ) { +#ifdef FT_CONFIG_OPTION_BYTECODE_INTERPRETER + FT_Error error; FT_ULong table_len; @@ -267,6 +422,12 @@ Exit: return error; + +#else /* !BYTECODE_INTERPRETER */ + FT_UNUSED(face); + FT_UNUSED(stream); + return 0; +#endif } diff --git a/src/truetype/ttpload.h b/src/truetype/ttpload.h index 3f8cd64ff..1d14aecac 100644 --- a/src/truetype/ttpload.h +++ b/src/truetype/ttpload.h @@ -31,6 +31,14 @@ FT_BEGIN_HEADER tt_face_load_loca( TT_Face face, FT_Stream stream ); + FT_LOCAL( FT_ULong ) + tt_face_get_location( TT_Face face, + FT_UInt gindex, + FT_UInt *asize ); + + FT_LOCAL( void ) + tt_face_done_loca( TT_Face face ); + FT_LOCAL( FT_Error ) tt_face_load_cvt( TT_Face face, FT_Stream stream );