diff options
Diffstat (limited to 'src/base/ftobjs.c')
-rw-r--r-- | src/base/ftobjs.c | 308 |
1 files changed, 229 insertions, 79 deletions
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index f167b2f..89892df 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -4,7 +4,7 @@ /* */ /* The FreeType private base classes (body). */ /* */ -/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */ +/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -26,6 +26,7 @@ #include FT_INTERNAL_STREAM_H #include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */ #include FT_TRUETYPE_TABLES_H +#include FT_TRUETYPE_TAGS_H #include FT_TRUETYPE_IDS_H #include FT_OUTLINE_H @@ -36,13 +37,11 @@ #include FT_SERVICE_KERNING_H #include FT_SERVICE_TRUETYPE_ENGINE_H -#ifdef ANDROID_FONT_HACK -#include <unistd.h> -#include <fcntl.h> -#endif +#include "ftbase.h" #define GRID_FIT_METRICS + FT_BASE_DEF( FT_Pointer ) ft_service_list_lookup( FT_ServiceDesc service_descriptors, const char* service_id ) @@ -133,13 +132,14 @@ FT_Stream stream; + *astream = 0; + if ( !library ) return FT_Err_Invalid_Library_Handle; if ( !args ) return FT_Err_Invalid_Argument; - *astream = 0; memory = library->memory; if ( FT_NEW( stream ) ) @@ -201,6 +201,12 @@ } + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ #undef FT_COMPONENT #define FT_COMPONENT trace_objs @@ -249,7 +255,7 @@ FT_BASE_DEF( void ) ft_glyphslot_free_bitmap( FT_GlyphSlot slot ) { - if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) ) { FT_Memory memory = FT_FACE_MEMORY( slot->face ); @@ -547,7 +553,7 @@ FT_Driver driver; FT_GlyphSlot slot; FT_Library library; - FT_Bool autohint = 0; + FT_Bool autohint = FALSE; FT_Module hinter; @@ -577,38 +583,6 @@ load_flags &= ~FT_LOAD_RENDER; } -#ifdef ANDROID_FONT_HACK - else - { - static int hack_mode; - - if (hack_mode == 0) { - do { - int fd = open("/data/misc/font-hack", O_RDONLY); - char buff[2]; - int ret; - - hack_mode = 1; /*means light node by default */ - if (fd < 0) - break; - - ret = read(fd, buff, 1); - if (ret == 1) - hack_mode = 1 + (buff[0] - '0'); - - close(fd); - } while (0); - } - - switch (hack_mode) - { - case 1: - load_flags &= 0xfff0ffff; - load_flags |= FT_LOAD_TARGET_LIGHT; - break; - } - } -#endif /* * Determine whether we need to auto-hint or not. @@ -623,22 +597,22 @@ * * - Otherwise, auto-hint for LIGHT hinting mode. * - * - Exception: The font requires the unpatented - * bytecode interpreter to load properly. + * - Exception: The font is `tricky' and requires + * the native hinter to load properly. */ - autohint = 0; - if ( hinter && - ( load_flags & FT_LOAD_NO_HINTING ) == 0 && - ( load_flags & FT_LOAD_NO_AUTOHINT ) == 0 && - FT_DRIVER_IS_SCALABLE( driver ) && - FT_DRIVER_USES_OUTLINES( driver ) && - face->internal->transform_matrix.yy > 0 && - face->internal->transform_matrix.yx == 0 ) + if ( hinter && + !( load_flags & FT_LOAD_NO_HINTING ) && + !( load_flags & FT_LOAD_NO_AUTOHINT ) && + FT_DRIVER_IS_SCALABLE( driver ) && + FT_DRIVER_USES_OUTLINES( driver ) && + !FT_IS_TRICKY( face ) && + face->internal->transform_matrix.yy > 0 && + face->internal->transform_matrix.yx == 0 ) { - if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) != 0 || - !FT_DRIVER_HAS_HINTER( driver ) ) - autohint = 1; + if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT ) || + !FT_DRIVER_HAS_HINTER( driver ) ) + autohint = TRUE; else { FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); @@ -646,7 +620,7 @@ if ( mode == FT_RENDER_MODE_LIGHT || face->internal->ignore_unpatented_hinter ) - autohint = 1; + autohint = TRUE; } } @@ -729,7 +703,7 @@ /* compute the linear advance in 16.16 pixels */ if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 && - ( face->face_flags & FT_FACE_FLAG_SCALABLE ) ) + ( FT_IS_SCALABLE( face ) ) ) { FT_Size_Metrics* metrics = &face->size->metrics; @@ -1147,7 +1121,7 @@ /* there's a Mac-specific extended implementation of FT_New_Face() */ /* in src/base/ftmac.c */ -#ifndef FT_MACINTOSH +#if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON ) /* documentation is in freetype.h */ @@ -1170,7 +1144,7 @@ return FT_Open_Face( library, &args, face_index, aface ); } -#endif /* !FT_MACINTOSH */ +#endif /* defined( FT_MACINTOSH ) && !defined( DARWIN_NO_CARBON ) */ /* documentation is in freetype.h */ @@ -1197,7 +1171,7 @@ } -#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS ) +#ifdef FT_CONFIG_OPTION_MAC_FONTS /* The behavior here is very similar to that in base/ftmac.c, but it */ /* is designed to work on non-mac systems, so no mac specific calls. */ @@ -1226,9 +1200,9 @@ /* we don't really have access to it. */ - /* Finalizer for a memory stream; gets called by FT_Done_Face(). - It frees the memory it uses. */ - /* from ftmac.c */ + /* Finalizer for a memory stream; gets called by FT_Done_Face(). */ + /* It frees the memory it uses. */ + /* From ftmac.c. */ static void memory_stream_close( FT_Stream stream ) { @@ -1244,7 +1218,7 @@ /* Create a new memory stream from a buffer and a size. */ - /* from ftmac.c */ + /* From ftmac.c. */ static FT_Error new_memory_stream( FT_Library library, FT_Byte* base, @@ -1281,7 +1255,7 @@ /* Create a new FT_Face given a buffer and a driver name. */ /* from ftmac.c */ - static FT_Error + FT_LOCAL_DEF( FT_Error ) open_face_from_buffer( FT_Library library, FT_Byte* base, FT_ULong size, @@ -1314,20 +1288,161 @@ args.driver = FT_Get_Module( library, driver_name ); } +#ifdef FT_MACINTOSH + /* At this point, face_index has served its purpose; */ + /* whoever calls this function has already used it to */ + /* locate the correct font data. We should not propagate */ + /* this index to FT_Open_Face() (unless it is negative). */ + + if ( face_index > 0 ) + face_index = 0; +#endif + error = FT_Open_Face( library, &args, face_index, aface ); if ( error == FT_Err_Ok ) (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; else +#ifdef FT_MACINTOSH + FT_Stream_Free( stream, 0 ); +#else { FT_Stream_Close( stream ); FT_FREE( stream ); } +#endif return error; } + /* Look up `TYP1' or `CID ' table from sfnt table directory. */ + /* `offset' and `length' must exclude the binary header in tables. */ + + /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */ + /* format too. Here, since we can't expect that the TrueType font */ + /* driver is loaded unconditially, we must parse the font by */ + /* ourselves. We are only interested in the name of the table and */ + /* the offset. */ + + static FT_Error + ft_lookup_PS_in_sfnt_stream( FT_Stream stream, + FT_Long face_index, + FT_ULong* offset, + FT_ULong* length, + FT_Bool* is_sfnt_cid ) + { + FT_Error error; + FT_UShort numTables; + FT_Long pstable_index; + FT_ULong tag; + int i; + + + *offset = 0; + *length = 0; + *is_sfnt_cid = FALSE; + + /* TODO: support for sfnt-wrapped PS/CID in TTC format */ + + /* version check for 'typ1' (should be ignored?) */ + if ( FT_READ_ULONG( tag ) ) + return error; + if ( tag != TTAG_typ1 ) + return FT_Err_Unknown_File_Format; + + if ( FT_READ_USHORT( numTables ) ) + return error; + if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */ + return error; + + pstable_index = -1; + *is_sfnt_cid = FALSE; + + for ( i = 0; i < numTables; i++ ) + { + if ( FT_READ_ULONG( tag ) || FT_STREAM_SKIP( 4 ) || + FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) ) + return error; + + if ( tag == TTAG_CID ) + { + pstable_index++; + *offset += 22; + *length -= 22; + *is_sfnt_cid = TRUE; + if ( face_index < 0 ) + return FT_Err_Ok; + } + else if ( tag == TTAG_TYP1 ) + { + pstable_index++; + *offset += 24; + *length -= 24; + *is_sfnt_cid = FALSE; + if ( face_index < 0 ) + return FT_Err_Ok; + } + if ( face_index >= 0 && pstable_index == face_index ) + return FT_Err_Ok; + } + return FT_Err_Table_Missing; + } + + + FT_LOCAL_DEF( FT_Error ) + open_face_PS_from_sfnt_stream( FT_Library library, + FT_Stream stream, + FT_Long face_index, + FT_Int num_params, + FT_Parameter *params, + FT_Face *aface ) + { + FT_Error error; + FT_Memory memory = library->memory; + FT_ULong offset, length; + FT_Long pos; + FT_Bool is_sfnt_cid; + FT_Byte* sfnt_ps; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + + + pos = FT_Stream_Pos( stream ); + + error = ft_lookup_PS_in_sfnt_stream( stream, + face_index, + &offset, + &length, + &is_sfnt_cid ); + if ( error ) + goto Exit; + + if ( FT_Stream_Seek( stream, pos + offset ) ) + goto Exit; + + if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) ) + goto Exit; + + error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length ); + if ( error ) + goto Exit; + + error = open_face_from_buffer( library, + sfnt_ps, + length, + face_index < 0 ? face_index : 0, + is_sfnt_cid ? "cid" : "type1", + aface ); + Exit: + FT_Stream_Seek( stream, pos ); + return error; + } + + +#if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON ) + /* The resource header says we've got resource_cnt `POST' (type1) */ /* resources in this file. They all need to be coalesced into */ /* one lump which gets passed on to the type1 driver. */ @@ -1482,17 +1597,25 @@ if ( rlen == -1 ) return FT_Err_Cannot_Open_Resource; + error = open_face_PS_from_sfnt_stream( library, + stream, + face_index, + 0, NULL, + aface ); + if ( !error ) + goto Exit; + + /* rewind sfnt stream before open_face_PS_from_sfnt_stream() */ + if ( FT_Stream_Seek( stream, flag_offset + 4 ) ) + goto Exit; + if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) ) return error; error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen ); if ( error ) goto Exit; - is_cff = rlen > 4 && sfnt_data[0] == 'O' && - sfnt_data[1] == 'T' && - sfnt_data[2] == 'T' && - sfnt_data[3] == 'O'; - + is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 ); error = open_face_from_buffer( library, sfnt_data, rlen, @@ -1531,7 +1654,7 @@ error = FT_Raccess_Get_DataOffsets( library, stream, map_offset, rdara_pos, - FT_MAKE_TAG( 'P', 'O', 'S', 'T' ), + TTAG_POST, &data_offsets, &count ); if ( !error ) { @@ -1546,7 +1669,7 @@ error = FT_Raccess_Get_DataOffsets( library, stream, map_offset, rdara_pos, - FT_MAKE_TAG( 's', 'f', 'n', 't' ), + TTAG_sfnt, &data_offsets, &count ); if ( !error ) { @@ -1637,7 +1760,7 @@ FT_Error errors[FT_RACCESS_N_RULES]; FT_Open_Args args2; - FT_Stream stream2; + FT_Stream stream2 = 0; FT_Raccess_Guess( library, stream, @@ -1692,7 +1815,7 @@ } - /* Check for some macintosh formats. */ + /* Check for some macintosh formats without Carbon framework. */ /* Is this a macbinary file? If so look at the resource fork. */ /* Is this a mac dfont file? */ /* Is this an old style resource fork? (in data) */ @@ -1735,6 +1858,7 @@ face_index, aface, args ); return error; } +#endif #endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */ @@ -1750,7 +1874,7 @@ FT_Error error; FT_Driver driver; FT_Memory memory; - FT_Stream stream; + FT_Stream stream = 0; FT_Face face = 0; FT_ListNode node = 0; FT_Bool external_stream; @@ -1833,6 +1957,28 @@ if ( !error ) goto Success; +#ifdef FT_CONFIG_OPTION_MAC_FONTS + if ( ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 && + FT_ERROR_BASE( error ) == FT_Err_Table_Missing ) + { + /* TrueType but essential tables are missing */ + if ( FT_Stream_Seek( stream, 0 ) ) + break; + + error = open_face_PS_from_sfnt_stream( library, + stream, + face_index, + num_params, + params, + aface ); + if ( !error ) + { + FT_Stream_Free( stream, external_stream ); + return error; + } + } +#endif + if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format ) goto Fail3; } @@ -2308,8 +2454,8 @@ } else { - metrics->x_scale = 1L << 22; - metrics->y_scale = 1L << 22; + metrics->x_scale = 1L << 16; + metrics->y_scale = 1L << 16; metrics->ascender = bsize->y_ppem; metrics->descender = 0; metrics->height = bsize->height << 6; @@ -2420,8 +2566,8 @@ else { FT_ZERO( metrics ); - metrics->x_scale = 1L << 22; - metrics->y_scale = 1L << 22; + metrics->x_scale = 1L << 16; + metrics->y_scale = 1L << 16; } } @@ -3302,11 +3448,11 @@ if ( size == NULL ) - return FT_Err_Bad_Argument; + return FT_Err_Invalid_Argument; face = size->face; if ( face == NULL || face->driver == NULL ) - return FT_Err_Bad_Argument; + return FT_Err_Invalid_Argument; /* we don't need anything more complex than that; all size objects */ /* are already listed by the face */ @@ -4054,7 +4200,11 @@ faces = &FT_DRIVER(module)->faces_list; while ( faces->head ) + { FT_Done_Face( FT_FACE( faces->head->data ) ); + if ( faces->head ) + FT_ERROR(( "FT_Done_Library: failed to free some faces\n" )); + } } } |