| Index: third_party/freetype/src/sfnt/sfobjs.c
|
| diff --git a/core/src/fxge/fx_freetype/fxft2.5.01/src/sfnt/sfobjs.c b/third_party/freetype/src/sfnt/sfobjs.c
|
| similarity index 75%
|
| rename from core/src/fxge/fx_freetype/fxft2.5.01/src/sfnt/sfobjs.c
|
| rename to third_party/freetype/src/sfnt/sfobjs.c
|
| index 2d5a388ca80bf6bd6ff0f0fc61823c14555e350c..70b988d650e60959d8ec71335555ec78c735311c 100644
|
| --- a/core/src/fxge/fx_freetype/fxft2.5.01/src/sfnt/sfobjs.c
|
| +++ b/third_party/freetype/src/sfnt/sfobjs.c
|
| @@ -4,7 +4,7 @@
|
| /* */
|
| /* SFNT object management (base). */
|
| /* */
|
| -/* Copyright 1996-2008, 2010-2013 by */
|
| +/* Copyright 1996-2008, 2010-2014 by */
|
| /* David Turner, Robert Wilhelm, and Werner Lemberg. */
|
| /* */
|
| /* This file is part of the FreeType project, and may only be used, */
|
| @@ -16,17 +16,18 @@
|
| /***************************************************************************/
|
|
|
|
|
| -#include "../../include/ft2build.h"
|
| +#include <ft2build.h>
|
| #include "sfobjs.h"
|
| #include "ttload.h"
|
| #include "ttcmap.h"
|
| #include "ttkern.h"
|
| -#include "../../include/freetype/internal/sfnt.h"
|
| -#include "../../include/freetype/internal/ftdebug.h"
|
| -#include "../../include/freetype/ttnameid.h"
|
| -#include "../../include/freetype/tttags.h"
|
| -#include "../../include/freetype/internal/services/svpscmap.h"
|
| -#include "../../include/freetype/ftsnames.h"
|
| +#include FT_INTERNAL_SFNT_H
|
| +#include FT_INTERNAL_DEBUG_H
|
| +#include FT_TRUETYPE_IDS_H
|
| +#include FT_TRUETYPE_TAGS_H
|
| +#include FT_SERVICE_POSTSCRIPT_CMAPS_H
|
| +#include FT_SFNT_NAMES_H
|
| +#include FT_GZIP_H
|
| #include "sferrors.h"
|
|
|
| #ifdef TT_CONFIG_OPTION_BDF
|
| @@ -68,9 +69,7 @@
|
| if ( code == 0 )
|
| break;
|
|
|
| - if (code > 255) /*Johnson 2010-10-09, #TESTDOC:0000042_QUT20005_5.pdf.*/
|
| - code = code>>8&0x00ff;
|
| - if ( code < 32 || code > 127 )
|
| + if ( code < 32 || code > 127 )
|
| code = '?';
|
|
|
| string[n] = (char)code;
|
| @@ -349,6 +348,383 @@
|
| }
|
|
|
|
|
| +#define WRITE_USHORT( p, v ) \
|
| + do \
|
| + { \
|
| + *(p)++ = (FT_Byte)( (v) >> 8 ); \
|
| + *(p)++ = (FT_Byte)( (v) >> 0 ); \
|
| + \
|
| + } while ( 0 )
|
| +
|
| +#define WRITE_ULONG( p, v ) \
|
| + do \
|
| + { \
|
| + *(p)++ = (FT_Byte)( (v) >> 24 ); \
|
| + *(p)++ = (FT_Byte)( (v) >> 16 ); \
|
| + *(p)++ = (FT_Byte)( (v) >> 8 ); \
|
| + *(p)++ = (FT_Byte)( (v) >> 0 ); \
|
| + \
|
| + } while ( 0 )
|
| +
|
| +
|
| + static void
|
| + sfnt_stream_close( FT_Stream stream )
|
| + {
|
| + FT_Memory memory = stream->memory;
|
| +
|
| +
|
| + FT_FREE( stream->base );
|
| +
|
| + stream->size = 0;
|
| + stream->base = 0;
|
| + stream->close = 0;
|
| + }
|
| +
|
| +
|
| + FT_CALLBACK_DEF( int )
|
| + compare_offsets( const void* a,
|
| + const void* b )
|
| + {
|
| + WOFF_Table table1 = *(WOFF_Table*)a;
|
| + WOFF_Table table2 = *(WOFF_Table*)b;
|
| +
|
| + FT_ULong offset1 = table1->Offset;
|
| + FT_ULong offset2 = table2->Offset;
|
| +
|
| +
|
| + if ( offset1 > offset2 )
|
| + return 1;
|
| + else if ( offset1 < offset2 )
|
| + return -1;
|
| + else
|
| + return 0;
|
| + }
|
| +
|
| +
|
| + /* Replace `face->root.stream' with a stream containing the extracted */
|
| + /* SFNT of a WOFF font. */
|
| +
|
| + static FT_Error
|
| + woff_open_font( FT_Stream stream,
|
| + TT_Face face )
|
| + {
|
| + FT_Memory memory = stream->memory;
|
| + FT_Error error = FT_Err_Ok;
|
| +
|
| + WOFF_HeaderRec woff;
|
| + WOFF_Table tables = NULL;
|
| + WOFF_Table* indices = NULL;
|
| +
|
| + FT_ULong woff_offset;
|
| +
|
| + FT_Byte* sfnt = NULL;
|
| + FT_Stream sfnt_stream = NULL;
|
| +
|
| + FT_Byte* sfnt_header;
|
| + FT_ULong sfnt_offset;
|
| +
|
| + FT_Int nn;
|
| + FT_ULong old_tag = 0;
|
| +
|
| + static const FT_Frame_Field woff_header_fields[] =
|
| + {
|
| +#undef FT_STRUCTURE
|
| +#define FT_STRUCTURE WOFF_HeaderRec
|
| +
|
| + FT_FRAME_START( 44 ),
|
| + FT_FRAME_ULONG ( signature ),
|
| + FT_FRAME_ULONG ( flavor ),
|
| + FT_FRAME_ULONG ( length ),
|
| + FT_FRAME_USHORT( num_tables ),
|
| + FT_FRAME_USHORT( reserved ),
|
| + FT_FRAME_ULONG ( totalSfntSize ),
|
| + FT_FRAME_USHORT( majorVersion ),
|
| + FT_FRAME_USHORT( minorVersion ),
|
| + FT_FRAME_ULONG ( metaOffset ),
|
| + FT_FRAME_ULONG ( metaLength ),
|
| + FT_FRAME_ULONG ( metaOrigLength ),
|
| + FT_FRAME_ULONG ( privOffset ),
|
| + FT_FRAME_ULONG ( privLength ),
|
| + FT_FRAME_END
|
| + };
|
| +
|
| +
|
| + FT_ASSERT( stream == face->root.stream );
|
| + FT_ASSERT( FT_STREAM_POS() == 0 );
|
| +
|
| + if ( FT_STREAM_READ_FIELDS( woff_header_fields, &woff ) )
|
| + return error;
|
| +
|
| + /* Make sure we don't recurse back here or hit TTC code. */
|
| + if ( woff.flavor == TTAG_wOFF || woff.flavor == TTAG_ttcf )
|
| + return FT_THROW( Invalid_Table );
|
| +
|
| + /* Miscellaneous checks. */
|
| + if ( woff.length != stream->size ||
|
| + woff.num_tables == 0 ||
|
| + 44 + woff.num_tables * 20UL >= woff.length ||
|
| + 12 + woff.num_tables * 16UL >= woff.totalSfntSize ||
|
| + ( woff.totalSfntSize & 3 ) != 0 ||
|
| + ( woff.metaOffset == 0 && ( woff.metaLength != 0 ||
|
| + woff.metaOrigLength != 0 ) ) ||
|
| + ( woff.metaLength != 0 && woff.metaOrigLength == 0 ) ||
|
| + ( woff.privOffset == 0 && woff.privLength != 0 ) )
|
| + return FT_THROW( Invalid_Table );
|
| +
|
| + if ( FT_ALLOC( sfnt, woff.totalSfntSize ) ||
|
| + FT_NEW( sfnt_stream ) )
|
| + goto Exit;
|
| +
|
| + sfnt_header = sfnt;
|
| +
|
| + /* Write sfnt header. */
|
| + {
|
| + FT_UInt searchRange, entrySelector, rangeShift, x;
|
| +
|
| +
|
| + x = woff.num_tables;
|
| + entrySelector = 0;
|
| + while ( x )
|
| + {
|
| + x >>= 1;
|
| + entrySelector += 1;
|
| + }
|
| + entrySelector--;
|
| +
|
| + searchRange = ( 1 << entrySelector ) * 16;
|
| + rangeShift = woff.num_tables * 16 - searchRange;
|
| +
|
| + WRITE_ULONG ( sfnt_header, woff.flavor );
|
| + WRITE_USHORT( sfnt_header, woff.num_tables );
|
| + WRITE_USHORT( sfnt_header, searchRange );
|
| + WRITE_USHORT( sfnt_header, entrySelector );
|
| + WRITE_USHORT( sfnt_header, rangeShift );
|
| + }
|
| +
|
| + /* While the entries in the sfnt header must be sorted by the */
|
| + /* tag value, the tables themselves are not. We thus have to */
|
| + /* sort them by offset and check that they don't overlap. */
|
| +
|
| + if ( FT_NEW_ARRAY( tables, woff.num_tables ) ||
|
| + FT_NEW_ARRAY( indices, woff.num_tables ) )
|
| + goto Exit;
|
| +
|
| + FT_TRACE2(( "\n"
|
| + " tag offset compLen origLen checksum\n"
|
| + " -------------------------------------------\n" ));
|
| +
|
| + if ( FT_FRAME_ENTER( 20L * woff.num_tables ) )
|
| + goto Exit;
|
| +
|
| + for ( nn = 0; nn < woff.num_tables; nn++ )
|
| + {
|
| + WOFF_Table table = tables + nn;
|
| +
|
| + table->Tag = FT_GET_TAG4();
|
| + table->Offset = FT_GET_ULONG();
|
| + table->CompLength = FT_GET_ULONG();
|
| + table->OrigLength = FT_GET_ULONG();
|
| + table->CheckSum = FT_GET_ULONG();
|
| +
|
| + FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx %08lx\n",
|
| + (FT_Char)( table->Tag >> 24 ),
|
| + (FT_Char)( table->Tag >> 16 ),
|
| + (FT_Char)( table->Tag >> 8 ),
|
| + (FT_Char)( table->Tag ),
|
| + table->Offset,
|
| + table->CompLength,
|
| + table->OrigLength,
|
| + table->CheckSum ));
|
| +
|
| + if ( table->Tag <= old_tag )
|
| + {
|
| + FT_FRAME_EXIT();
|
| + error = FT_THROW( Invalid_Table );
|
| + goto Exit;
|
| + }
|
| +
|
| + old_tag = table->Tag;
|
| + indices[nn] = table;
|
| + }
|
| +
|
| + FT_FRAME_EXIT();
|
| +
|
| + /* Sort by offset. */
|
| +
|
| + ft_qsort( indices,
|
| + woff.num_tables,
|
| + sizeof ( WOFF_Table ),
|
| + compare_offsets );
|
| +
|
| + /* Check offsets and lengths. */
|
| +
|
| + woff_offset = 44 + woff.num_tables * 20L;
|
| + sfnt_offset = 12 + woff.num_tables * 16L;
|
| +
|
| + for ( nn = 0; nn < woff.num_tables; nn++ )
|
| + {
|
| + WOFF_Table table = indices[nn];
|
| +
|
| +
|
| + if ( table->Offset != woff_offset ||
|
| + table->CompLength > woff.length ||
|
| + table->Offset > woff.length - table->CompLength ||
|
| + table->OrigLength > woff.totalSfntSize ||
|
| + sfnt_offset > woff.totalSfntSize - table->OrigLength ||
|
| + table->CompLength > table->OrigLength )
|
| + {
|
| + error = FT_THROW( Invalid_Table );
|
| + goto Exit;
|
| + }
|
| +
|
| + table->OrigOffset = sfnt_offset;
|
| +
|
| + /* The offsets must be multiples of 4. */
|
| + woff_offset += ( table->CompLength + 3 ) & ~3;
|
| + sfnt_offset += ( table->OrigLength + 3 ) & ~3;
|
| + }
|
| +
|
| + /*
|
| + * Final checks!
|
| + *
|
| + * We don't decode and check the metadata block.
|
| + * We don't check table checksums either.
|
| + * But other than those, I think we implement all
|
| + * `MUST' checks from the spec.
|
| + */
|
| +
|
| + if ( woff.metaOffset )
|
| + {
|
| + if ( woff.metaOffset != woff_offset ||
|
| + woff.metaOffset + woff.metaLength > woff.length )
|
| + {
|
| + error = FT_THROW( Invalid_Table );
|
| + goto Exit;
|
| + }
|
| +
|
| + /* We have padding only ... */
|
| + woff_offset += woff.metaLength;
|
| + }
|
| +
|
| + if ( woff.privOffset )
|
| + {
|
| + /* ... if it isn't the last block. */
|
| + woff_offset = ( woff_offset + 3 ) & ~3;
|
| +
|
| + if ( woff.privOffset != woff_offset ||
|
| + woff.privOffset + woff.privLength > woff.length )
|
| + {
|
| + error = FT_THROW( Invalid_Table );
|
| + goto Exit;
|
| + }
|
| +
|
| + /* No padding for the last block. */
|
| + woff_offset += woff.privLength;
|
| + }
|
| +
|
| + if ( sfnt_offset != woff.totalSfntSize ||
|
| + woff_offset != woff.length )
|
| + {
|
| + error = FT_THROW( Invalid_Table );
|
| + goto Exit;
|
| + }
|
| +
|
| + /* Write the tables. */
|
| +
|
| + for ( nn = 0; nn < woff.num_tables; nn++ )
|
| + {
|
| + WOFF_Table table = tables + nn;
|
| +
|
| +
|
| + /* Write SFNT table entry. */
|
| + WRITE_ULONG( sfnt_header, table->Tag );
|
| + WRITE_ULONG( sfnt_header, table->CheckSum );
|
| + WRITE_ULONG( sfnt_header, table->OrigOffset );
|
| + WRITE_ULONG( sfnt_header, table->OrigLength );
|
| +
|
| + /* Write table data. */
|
| + if ( FT_STREAM_SEEK( table->Offset ) ||
|
| + FT_FRAME_ENTER( table->CompLength ) )
|
| + goto Exit;
|
| +
|
| + if ( table->CompLength == table->OrigLength )
|
| + {
|
| + /* Uncompressed data; just copy. */
|
| + ft_memcpy( sfnt + table->OrigOffset,
|
| + stream->cursor,
|
| + table->OrigLength );
|
| + }
|
| + else
|
| + {
|
| +#ifdef FT_CONFIG_OPTION_USE_ZLIB
|
| +
|
| + /* Uncompress with zlib. */
|
| + FT_ULong output_len = table->OrigLength;
|
| +
|
| +
|
| + error = FT_Gzip_Uncompress( memory,
|
| + sfnt + table->OrigOffset, &output_len,
|
| + stream->cursor, table->CompLength );
|
| + if ( error )
|
| + goto Exit;
|
| + if ( output_len != table->OrigLength )
|
| + {
|
| + error = FT_THROW( Invalid_Table );
|
| + goto Exit;
|
| + }
|
| +
|
| +#else /* !FT_CONFIG_OPTION_USE_ZLIB */
|
| +
|
| + error = FT_THROW( Unimplemented_Feature );
|
| + goto Exit;
|
| +
|
| +#endif /* !FT_CONFIG_OPTION_USE_ZLIB */
|
| + }
|
| +
|
| + FT_FRAME_EXIT();
|
| +
|
| + /* We don't check whether the padding bytes in the WOFF file are */
|
| + /* actually '\0'. For the output, however, we do set them properly. */
|
| + sfnt_offset = table->OrigOffset + table->OrigLength;
|
| + while ( sfnt_offset & 3 )
|
| + {
|
| + sfnt[sfnt_offset] = '\0';
|
| + sfnt_offset++;
|
| + }
|
| + }
|
| +
|
| + /* Ok! Finally ready. Swap out stream and return. */
|
| + FT_Stream_OpenMemory( sfnt_stream, sfnt, woff.totalSfntSize );
|
| + sfnt_stream->memory = stream->memory;
|
| + sfnt_stream->close = sfnt_stream_close;
|
| +
|
| + FT_Stream_Free(
|
| + face->root.stream,
|
| + ( face->root.face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
|
| +
|
| + face->root.stream = sfnt_stream;
|
| +
|
| + face->root.face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
|
| +
|
| + Exit:
|
| + FT_FREE( tables );
|
| + FT_FREE( indices );
|
| +
|
| + if ( error )
|
| + {
|
| + FT_FREE( sfnt );
|
| + FT_Stream_Close( sfnt_stream );
|
| + FT_FREE( sfnt_stream );
|
| + }
|
| +
|
| + return error;
|
| + }
|
| +
|
| +
|
| +#undef WRITE_USHORT
|
| +#undef WRITE_ULONG
|
| +
|
| +
|
| /* Fill in face->ttc_header. If the font is not a TTC, it is */
|
| /* synthesized into a TTC with one offset table. */
|
| static FT_Error
|
| @@ -375,11 +751,28 @@
|
| face->ttc_header.version = 0;
|
| face->ttc_header.count = 0;
|
|
|
| + retry:
|
| offset = FT_STREAM_POS();
|
|
|
| if ( FT_READ_ULONG( tag ) )
|
| return error;
|
|
|
| + if ( tag == TTAG_wOFF )
|
| + {
|
| + FT_TRACE2(( "sfnt_open_font: file is a WOFF; synthesizing SFNT\n" ));
|
| +
|
| + if ( FT_STREAM_SEEK( offset ) )
|
| + return error;
|
| +
|
| + error = woff_open_font( stream, face );
|
| + if ( error )
|
| + return error;
|
| +
|
| + /* Swap out stream and retry! */
|
| + stream = face->root.stream;
|
| + goto retry;
|
| + }
|
| +
|
| if ( tag != 0x00010000UL &&
|
| tag != TTAG_ttcf &&
|
| tag != TTAG_OTTO &&
|
| @@ -482,6 +875,9 @@
|
| if ( error )
|
| return error;
|
|
|
| + /* Stream may have changed in sfnt_open_font. */
|
| + stream = face->root.stream;
|
| +
|
| FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index ));
|
|
|
| if ( face_index < 0 )
|
| @@ -506,7 +902,8 @@
|
|
|
|
|
| #define LOAD_( x ) \
|
| - do { \
|
| + do \
|
| + { \
|
| FT_TRACE2(( "`" #x "' " )); \
|
| FT_TRACE3(( "-->\n" )); \
|
| \
|
| @@ -521,7 +918,8 @@
|
| } while ( 0 )
|
|
|
| #define LOADM_( x, vertical ) \
|
| - do { \
|
| + do \
|
| + { \
|
| FT_TRACE2(( "`%s" #x "' ", \
|
| vertical ? "vertical " : "" )); \
|
| FT_TRACE3(( "-->\n" )); \
|
| @@ -537,7 +935,8 @@
|
| } while ( 0 )
|
|
|
| #define GET_NAME( id, field ) \
|
| - do { \
|
| + do \
|
| + { \
|
| error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \
|
| if ( error ) \
|
| goto Exit; \
|
| @@ -557,6 +956,7 @@
|
| #endif
|
| FT_Bool has_outline;
|
| FT_Bool is_apple_sbit;
|
| + FT_Bool is_apple_sbix;
|
| FT_Bool ignore_preferred_family = FALSE;
|
| FT_Bool ignore_preferred_subfamily = FALSE;
|
|
|
| @@ -610,6 +1010,13 @@
|
| #endif
|
|
|
| is_apple_sbit = 0;
|
| + is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 );
|
| +
|
| + /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf'
|
| + * outline rendered on top. We don't support that yet, so just ignore
|
| + * the 'glyf' outline and advertise it as a bitmap-only font. */
|
| + if ( is_apple_sbix )
|
| + has_outline = FALSE;
|
|
|
| /* if this font doesn't contain outlines, we try to load */
|
| /* a `bhed' table */
|
| @@ -621,7 +1028,7 @@
|
|
|
| /* load the font header (`head' table) if this isn't an Apple */
|
| /* sbit font file */
|
| - if ( !is_apple_sbit )
|
| + if ( !is_apple_sbit || is_apple_sbix )
|
| {
|
| LOAD_( head );
|
| if ( error )
|
| @@ -705,7 +1112,7 @@
|
| }
|
|
|
| if ( error )
|
| - goto Exit;
|
| + goto Exit;
|
|
|
| /* try to load the `vhea' and `vmtx' tables */
|
| LOADM_( hhea, 1 );
|
| @@ -805,6 +1212,10 @@
|
| /* */
|
| /* Compute face flags. */
|
| /* */
|
| + if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC ||
|
| + face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX )
|
| + flags |= FT_FACE_FLAG_COLOR; /* color glyphs */
|
| +
|
| if ( has_outline == TRUE )
|
| flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */
|
|
|
| @@ -933,7 +1344,7 @@
|
|
|
| if ( em_size == 0 || face->os2.version == 0xFFFFU )
|
| {
|
| - avgwidth = 0;
|
| + avgwidth = 1;
|
| em_size = 1;
|
| }
|
|
|
|
|