From 9c075dc4cdaeef79bc570ed2219bb757cb325c47 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 15 May 2018 20:21:34 +0200 Subject: Update in-tree freetype2 lib (unused) to 2.9.1 --- modules/freetype2/src/sfnt/Jamfile | 2 +- modules/freetype2/src/sfnt/module.mk | 2 +- modules/freetype2/src/sfnt/pngshim.c | 91 +++- modules/freetype2/src/sfnt/pngshim.h | 2 +- modules/freetype2/src/sfnt/rules.mk | 2 +- modules/freetype2/src/sfnt/sfdriver.c | 867 +++++++++++++++++++++++++++++++--- modules/freetype2/src/sfnt/sfdriver.h | 2 +- modules/freetype2/src/sfnt/sferrors.h | 2 +- modules/freetype2/src/sfnt/sfnt.c | 26 +- modules/freetype2/src/sfnt/sfntpic.c | 2 +- modules/freetype2/src/sfnt/sfntpic.h | 2 +- modules/freetype2/src/sfnt/sfobjs.c | 270 +++++++---- modules/freetype2/src/sfnt/sfobjs.h | 2 +- modules/freetype2/src/sfnt/ttbdf.c | 9 +- modules/freetype2/src/sfnt/ttbdf.h | 6 +- modules/freetype2/src/sfnt/ttcmap.c | 159 ++++++- modules/freetype2/src/sfnt/ttcmap.h | 4 +- modules/freetype2/src/sfnt/ttcmapc.h | 2 +- modules/freetype2/src/sfnt/ttkern.c | 17 +- modules/freetype2/src/sfnt/ttkern.h | 2 +- modules/freetype2/src/sfnt/ttload.c | 147 ++++-- modules/freetype2/src/sfnt/ttload.h | 2 +- modules/freetype2/src/sfnt/ttmtx.c | 10 +- modules/freetype2/src/sfnt/ttmtx.h | 2 +- modules/freetype2/src/sfnt/ttpost.c | 24 +- modules/freetype2/src/sfnt/ttpost.h | 2 +- modules/freetype2/src/sfnt/ttsbit.c | 45 +- modules/freetype2/src/sfnt/ttsbit.h | 2 +- 28 files changed, 1430 insertions(+), 275 deletions(-) (limited to 'modules/freetype2/src/sfnt') diff --git a/modules/freetype2/src/sfnt/Jamfile b/modules/freetype2/src/sfnt/Jamfile index 089cc269b..57977fc96 100644 --- a/modules/freetype2/src/sfnt/Jamfile +++ b/modules/freetype2/src/sfnt/Jamfile @@ -1,6 +1,6 @@ # FreeType 2 src/sfnt Jamfile # -# Copyright 2001-2016 by +# Copyright 2001-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/sfnt/module.mk b/modules/freetype2/src/sfnt/module.mk index ca19e096a..51ca67e78 100644 --- a/modules/freetype2/src/sfnt/module.mk +++ b/modules/freetype2/src/sfnt/module.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/sfnt/pngshim.c b/modules/freetype2/src/sfnt/pngshim.c index ff6729273..16020266a 100644 --- a/modules/freetype2/src/sfnt/pngshim.c +++ b/modules/freetype2/src/sfnt/pngshim.c @@ -4,7 +4,7 @@ /* */ /* PNG Bitmap glyph support. */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* Google, Inc. */ /* Written by Stuart Gill and Behdad Esfahbod. */ /* */ @@ -24,9 +24,10 @@ #include FT_CONFIG_STANDARD_LIBRARY_H -#ifdef FT_CONFIG_OPTION_USE_PNG +#if defined( TT_CONFIG_OPTION_EMBEDDED_BITMAPS ) && \ + defined( FT_CONFIG_OPTION_USE_PNG ) - /* We always include , so make libpng shut up! */ + /* We always include , so make libpng shut up! */ #define PNG_SKIP_SETJMP_CHECK 1 #include #include "pngshim.h" @@ -48,18 +49,85 @@ } - /* Premultiplies data and converts RGBA bytes => native endian. */ + /* Premultiplies data and converts RGBA bytes => BGRA. */ static void premultiply_data( png_structp png, png_row_infop row_info, png_bytep data ) { - unsigned int i; + unsigned int i = 0, limit; + + /* The `vector_size' attribute was introduced in gcc 3.1, which */ + /* predates clang; the `__BYTE_ORDER__' preprocessor symbol was */ + /* introduced in gcc 4.6 and clang 3.2, respectively. */ + /* `__builtin_shuffle' for gcc was introduced in gcc 4.7.0. */ +#if ( ( defined( __GNUC__ ) && \ + ( ( __GNUC__ >= 5 ) || \ + ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 7 ) ) ) ) || \ + ( defined( __clang__ ) && \ + ( ( __clang_major__ >= 4 ) || \ + ( ( __clang_major__ == 3 ) && ( __clang_minor__ >= 2 ) ) ) ) ) && \ + defined( __OPTIMIZE__ ) && \ + __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + +#ifdef __clang__ + /* the clang documentation doesn't cover the two-argument case of */ + /* `__builtin_shufflevector'; however, it is is implemented since */ + /* version 2.8 */ +#define vector_shuffle __builtin_shufflevector +#else +#define vector_shuffle __builtin_shuffle +#endif - FT_UNUSED( png ); + typedef unsigned short v82 __attribute__(( vector_size( 16 ) )); - for ( i = 0; i < row_info->rowbytes; i += 4 ) + if ( row_info->rowbytes > 15 ) + { + /* process blocks of 16 bytes in one rush, which gives a nice speed-up */ + limit = row_info->rowbytes - 16 + 1; + for ( ; i < limit; i += 16 ) + { + unsigned char* base = &data[i]; + + v82 s, s0, s1, a; + + /* clang <= 3.9 can't apply scalar values to vectors */ + /* (or rather, it needs a different syntax) */ + v82 n0x80 = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }; + v82 n0xFF = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + v82 n8 = { 8, 8, 8, 8, 8, 8, 8, 8 }; + + v82 ma = { 1, 1, 3, 3, 5, 5, 7, 7 }; + v82 o1 = { 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF }; + v82 m0 = { 1, 0, 3, 2, 5, 4, 7, 6 }; + + + ft_memcpy( &s, base, 16 ); /* RGBA RGBA RGBA RGBA */ + s0 = s & n0xFF; /* R B R B R B R B */ + s1 = s >> n8; /* G A G A G A G A */ + + a = vector_shuffle( s1, ma ); /* A A A A A A A A */ + s1 |= o1; /* G 1 G 1 G 1 G 1 */ + s0 = vector_shuffle( s0, m0 ); /* B R B R B R B R */ + + s0 *= a; + s1 *= a; + s0 += n0x80; + s1 += n0x80; + s0 = ( s0 + ( s0 >> n8 ) ) >> n8; + s1 = ( s1 + ( s1 >> n8 ) ) >> n8; + + s = s0 | ( s1 << n8 ); + ft_memcpy( base, &s, 16 ); + } + } +#endif /* use `vector_size' */ + + FT_UNUSED( png ); + + limit = row_info->rowbytes; + for ( ; i < limit; i += 4 ) { unsigned char* base = &data[i]; unsigned int alpha = base[3]; @@ -169,7 +237,7 @@ return; } - memcpy( data, stream->cursor, length ); + ft_memcpy( data, stream->cursor, length ); FT_FRAME_EXIT(); } @@ -377,7 +445,12 @@ return error; } -#endif /* FT_CONFIG_OPTION_USE_PNG */ +#else /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ + + /* ANSI C doesn't like empty source files */ + typedef int _pngshim_dummy; + +#endif /* !(TT_CONFIG_OPTION_EMBEDDED_BITMAPS && FT_CONFIG_OPTION_USE_PNG) */ /* END */ diff --git a/modules/freetype2/src/sfnt/pngshim.h b/modules/freetype2/src/sfnt/pngshim.h index 0af4bfc5b..194238c3a 100644 --- a/modules/freetype2/src/sfnt/pngshim.h +++ b/modules/freetype2/src/sfnt/pngshim.h @@ -4,7 +4,7 @@ /* */ /* PNG Bitmap glyph support. */ /* */ -/* Copyright 2013-2016 by */ +/* Copyright 2013-2018 by */ /* Google, Inc. */ /* Written by Stuart Gill and Behdad Esfahbod. */ /* */ diff --git a/modules/freetype2/src/sfnt/rules.mk b/modules/freetype2/src/sfnt/rules.mk index e9fc42156..83acc66a8 100644 --- a/modules/freetype2/src/sfnt/rules.mk +++ b/modules/freetype2/src/sfnt/rules.mk @@ -3,7 +3,7 @@ # -# Copyright 1996-2016 by +# Copyright 1996-2018 by # David Turner, Robert Wilhelm, and Werner Lemberg. # # This file is part of the FreeType project, and may only be used, modified, diff --git a/modules/freetype2/src/sfnt/sfdriver.c b/modules/freetype2/src/sfnt/sfdriver.c index 1f15223cb..303e1ca9f 100644 --- a/modules/freetype2/src/sfnt/sfdriver.c +++ b/modules/freetype2/src/sfnt/sfdriver.c @@ -4,7 +4,7 @@ /* */ /* High-level SFNT driver interface (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,6 +20,7 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_SFNT_H #include FT_INTERNAL_OBJECTS_H +#include FT_TRUETYPE_IDS_H #include "sfdriver.h" #include "ttload.h" @@ -50,6 +51,11 @@ #include FT_SERVICE_SFNT_H #include FT_SERVICE_TT_CMAP_H +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include FT_MULTIPLE_MASTERS_H +#include FT_SERVICE_MULTIPLE_MASTERS_H +#endif + /*************************************************************************/ /* */ @@ -220,113 +226,841 @@ * */ - static const char* - sfnt_get_ps_name( TT_Face face ) + /* an array representing allowed ASCII characters in a PS string */ + static const unsigned char sfnt_ps_map[16] = { - FT_Int n, found_win, found_apple; - const char* result = NULL; + /* 4 0 C 8 */ + 0x00, 0x00, /* 0x00: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */ + 0x00, 0x00, /* 0x10: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */ + 0xDE, 0x7C, /* 0x20: 1 1 0 1 1 1 1 0 0 1 1 1 1 1 0 0 */ + 0xFF, 0xAF, /* 0x30: 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 */ + 0xFF, 0xFF, /* 0x40: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */ + 0xFF, 0xD7, /* 0x50: 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 */ + 0xFF, 0xFF, /* 0x60: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */ + 0xFF, 0x57 /* 0x70: 1 1 1 1 1 1 1 1 0 1 0 1 0 1 1 1 */ + }; + + + static int + sfnt_is_postscript( int c ) + { + unsigned int cc; - /* shouldn't happen, but just in case to avoid memory leaks */ - if ( face->postscript_name ) - return face->postscript_name; + if ( c < 0 || c >= 0x80 ) + return 0; - /* scan the name table to see whether we have a Postscript name here, */ - /* either in Macintosh or Windows platform encodings */ - found_win = -1; - found_apple = -1; + cc = (unsigned int)c; + + return sfnt_ps_map[cc >> 3] & ( 1 << ( cc & 0x07 ) ); + } + + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + + /* Only ASCII letters and digits are taken for a variation font */ + /* instance's PostScript name. */ + /* */ + /* `ft_isalnum' is a macro, but we need a function here, thus */ + /* this definition. */ + static int + sfnt_is_alphanumeric( int c ) + { + return ft_isalnum( c ); + } + + + /* the implementation of MurmurHash3 is taken and adapted from */ + /* https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp */ + +#define ROTL32( x, r ) ( x << r ) | ( x >> ( 32 - r ) ) + + + static FT_UInt32 + fmix32( FT_UInt32 h ) + { + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + + return h; + } + + + static void + murmur_hash_3_128( const void* key, + const unsigned int len, + FT_UInt32 seed, + void* out ) + { + const FT_Byte* data = (const FT_Byte*)key; + const int nblocks = (int)len / 16; + + FT_UInt32 h1 = seed; + FT_UInt32 h2 = seed; + FT_UInt32 h3 = seed; + FT_UInt32 h4 = seed; + + const FT_UInt32 c1 = 0x239b961b; + const FT_UInt32 c2 = 0xab0e9789; + const FT_UInt32 c3 = 0x38b34ae5; + const FT_UInt32 c4 = 0xa1e38b93; + + const FT_UInt32* blocks = (const FT_UInt32*)( data + nblocks * 16 ); + + int i; + + + for( i = -nblocks; i; i++ ) + { + FT_UInt32 k1 = blocks[i * 4 + 0]; + FT_UInt32 k2 = blocks[i * 4 + 1]; + FT_UInt32 k3 = blocks[i * 4 + 2]; + FT_UInt32 k4 = blocks[i * 4 + 3]; + + + k1 *= c1; + k1 = ROTL32( k1, 15 ); + k1 *= c2; + h1 ^= k1; + + h1 = ROTL32( h1, 19 ); + h1 += h2; + h1 = h1 * 5 + 0x561ccd1b; + + k2 *= c2; + k2 = ROTL32( k2, 16 ); + k2 *= c3; + h2 ^= k2; + + h2 = ROTL32( h2, 17 ); + h2 += h3; + h2 = h2 * 5 + 0x0bcaa747; + + k3 *= c3; + k3 = ROTL32( k3, 17 ); + k3 *= c4; + h3 ^= k3; + + h3 = ROTL32( h3, 15 ); + h3 += h4; + h3 = h3 * 5 + 0x96cd1c35; + + k4 *= c4; + k4 = ROTL32( k4, 18 ); + k4 *= c1; + h4 ^= k4; + + h4 = ROTL32( h4, 13 ); + h4 += h1; + h4 = h4 * 5 + 0x32ac3b17; + } - for ( n = 0; n < face->num_names; n++ ) { - TT_NameEntryRec* name = face->name_table.names + n; + const FT_Byte* tail = (const FT_Byte*)( data + nblocks * 16 ); + FT_UInt32 k1 = 0; + FT_UInt32 k2 = 0; + FT_UInt32 k3 = 0; + FT_UInt32 k4 = 0; - if ( name->nameID == 6 && name->stringLength > 0 ) + + switch ( len & 15 ) { - if ( name->platformID == 3 && - name->encodingID == 1 && - name->languageID == 0x409 ) - found_win = n; - - if ( name->platformID == 1 && - name->encodingID == 0 && - name->languageID == 0 ) - found_apple = n; + case 15: + k4 ^= (FT_UInt32)tail[14] << 16; + case 14: + k4 ^= (FT_UInt32)tail[13] << 8; + case 13: + k4 ^= (FT_UInt32)tail[12]; + k4 *= c4; + k4 = ROTL32( k4, 18 ); + k4 *= c1; + h4 ^= k4; + + case 12: + k3 ^= (FT_UInt32)tail[11] << 24; + case 11: + k3 ^= (FT_UInt32)tail[10] << 16; + case 10: + k3 ^= (FT_UInt32)tail[9] << 8; + case 9: + k3 ^= (FT_UInt32)tail[8]; + k3 *= c3; + k3 = ROTL32( k3, 17 ); + k3 *= c4; + h3 ^= k3; + + case 8: + k2 ^= (FT_UInt32)tail[7] << 24; + case 7: + k2 ^= (FT_UInt32)tail[6] << 16; + case 6: + k2 ^= (FT_UInt32)tail[5] << 8; + case 5: + k2 ^= (FT_UInt32)tail[4]; + k2 *= c2; + k2 = ROTL32( k2, 16 ); + k2 *= c3; + h2 ^= k2; + + case 4: + k1 ^= (FT_UInt32)tail[3] << 24; + case 3: + k1 ^= (FT_UInt32)tail[2] << 16; + case 2: + k1 ^= (FT_UInt32)tail[1] << 8; + case 1: + k1 ^= (FT_UInt32)tail[0]; + k1 *= c1; + k1 = ROTL32( k1, 15 ); + k1 *= c2; + h1 ^= k1; } } - if ( found_win != -1 ) + h1 ^= len; + h2 ^= len; + h3 ^= len; + h4 ^= len; + + h1 += h2; + h1 += h3; + h1 += h4; + + h2 += h1; + h3 += h1; + h4 += h1; + + h1 = fmix32( h1 ); + h2 = fmix32( h2 ); + h3 = fmix32( h3 ); + h4 = fmix32( h4 ); + + h1 += h2; + h1 += h3; + h1 += h4; + + h2 += h1; + h3 += h1; + h4 += h1; + + ((FT_UInt32*)out)[0] = h1; + ((FT_UInt32*)out)[1] = h2; + ((FT_UInt32*)out)[2] = h3; + ((FT_UInt32*)out)[3] = h4; + } + + +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + + typedef int (*char_type_func)( int c ); + + + /* handling of PID/EID 3/0 and 3/1 is the same */ +#define IS_WIN( n ) ( (n)->platformID == 3 && \ + ( (n)->encodingID == 1 || (n)->encodingID == 0 ) && \ + (n)->languageID == 0x409 ) + +#define IS_APPLE( n ) ( (n)->platformID == 1 && \ + (n)->encodingID == 0 && \ + (n)->languageID == 0 ) + + static char* + get_win_string( FT_Memory memory, + FT_Stream stream, + TT_Name entry, + char_type_func char_type, + FT_Bool report_invalid_characters ) + { + FT_Error error = FT_Err_Ok; + + char* result = NULL; + FT_String* r; + FT_Char* p; + FT_UInt len; + + FT_UNUSED( error ); + + + if ( FT_ALLOC( result, entry->stringLength / 2 + 1 ) ) + return NULL; + + if ( FT_STREAM_SEEK( entry->stringOffset ) || + FT_FRAME_ENTER( entry->stringLength ) ) { - FT_Memory memory = face->root.memory; - TT_NameEntryRec* name = face->name_table.names + found_win; - FT_UInt len = name->stringLength / 2; - FT_Error error = FT_Err_Ok; + FT_FREE( result ); + entry->stringLength = 0; + entry->stringOffset = 0; + FT_FREE( entry->string ); - FT_UNUSED( error ); + return NULL; + } + r = (FT_String*)result; + p = (FT_Char*)stream->cursor; - if ( !FT_ALLOC( result, name->stringLength + 1 ) ) + for ( len = entry->stringLength / 2; len > 0; len--, p += 2 ) + { + if ( p[0] == 0 ) { - FT_Stream stream = face->name_table.stream; - FT_String* r = (FT_String*)result; - FT_Char* p; + if ( char_type( p[1] ) ) + *r++ = p[1]; + else + { + if ( report_invalid_characters ) + { + FT_TRACE0(( "get_win_string:" + " Character `%c' (0x%X) invalid in PS name string\n", + p[1], p[1] )); + /* it's not the job of FreeType to correct PS names... */ + *r++ = p[1]; + } + } + } + } + *r = '\0'; + + FT_FRAME_EXIT(); + + return result; + } + + + static char* + get_apple_string( FT_Memory memory, + FT_Stream stream, + TT_Name entry, + char_type_func char_type, + FT_Bool report_invalid_characters ) + { + FT_Error error = FT_Err_Ok; + + char* result = NULL; + FT_String* r; + FT_Char* p; + FT_UInt len; + + FT_UNUSED( error ); + + if ( FT_ALLOC( result, entry->stringLength + 1 ) ) + return NULL; + + if ( FT_STREAM_SEEK( entry->stringOffset ) || + FT_FRAME_ENTER( entry->stringLength ) ) + { + FT_FREE( result ); + entry->stringOffset = 0; + entry->stringLength = 0; + FT_FREE( entry->string ); + + return NULL; + } - if ( FT_STREAM_SEEK( name->stringOffset ) || - FT_FRAME_ENTER( name->stringLength ) ) + r = (FT_String*)result; + p = (FT_Char*)stream->cursor; + + for ( len = entry->stringLength; len > 0; len--, p++ ) + { + if ( char_type( *p ) ) + *r++ = *p; + else + { + if ( report_invalid_characters ) { - FT_FREE( result ); - name->stringLength = 0; - name->stringOffset = 0; - FT_FREE( name->string ); + FT_TRACE0(( "get_apple_string:" + " Character `%c' (0x%X) invalid in PS name string\n", + *p, *p )); + /* it's not the job of FreeType to correct PS names... */ + *r++ = *p; + } + } + } + *r = '\0'; + + FT_FRAME_EXIT(); + + return result; + } - goto Exit; + + static FT_Bool + sfnt_get_name_id( TT_Face face, + FT_UShort id, + FT_Int *win, + FT_Int *apple ) + { + FT_Int n; + + + *win = -1; + *apple = -1; + + for ( n = 0; n < face->num_names; n++ ) + { + TT_Name name = face->name_table.names + n; + + + if ( name->nameID == id && name->stringLength > 0 ) + { + if ( IS_WIN( name ) ) + *win = n; + + if ( IS_APPLE( name ) ) + *apple = n; + } + } + + return ( *win >= 0 ) || ( *apple >= 0 ); + } + + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + + /* + The maximum length of an axis value descriptor. + + We need 65536 different values for the decimal fraction; this fits + nicely into five decimal places. Consequently, it consists of + + . the minus sign if the number is negative, + . up to five characters for the digits before the decimal point, + . the decimal point if there is a fractional part, and + . up to five characters for the digits after the decimal point. + + We also need one byte for the leading `_' character and up to four + bytes for the axis tag. + */ +#define MAX_VALUE_DESCRIPTOR_LEN ( 1 + 5 + 1 + 5 + 1 + 4 ) + + + /* the maximum length of PostScript font names */ +#define MAX_PS_NAME_LEN 127 + + + /* + * Find the shortest decimal representation of a 16.16 fixed point + * number. The function fills `buf' with the result, returning a pointer + * to the position after the representation's last byte. + */ + + static char* + fixed2float( FT_Int fixed, + char* buf ) + { + char* p; + char* q; + char tmp[5]; + + FT_Int int_part; + FT_Int frac_part; + + FT_Int i; + + + p = buf; + + if ( fixed == 0 ) + { + *p++ = '0'; + return p; + } + + if ( fixed < 0 ) + { + *p++ = '-'; + fixed = -fixed; + } + + int_part = ( fixed >> 16 ) & 0xFFFF; + frac_part = fixed & 0xFFFF; + + /* get digits of integer part (in reverse order) */ + q = tmp; + while ( int_part > 0 ) + { + *q++ = '0' + int_part % 10; + int_part /= 10; + } + + /* copy digits in correct order to buffer */ + while ( q > tmp ) + *p++ = *--q; + + if ( !frac_part ) + return p; + + /* save position of point */ + q = p; + *p++ = '.'; + + /* apply rounding */ + frac_part = frac_part * 10 + 5; + + /* get digits of fractional part */ + for ( i = 0; i < 5; i++ ) + { + *p++ = '0' + (char)( frac_part / 0x10000L ); + + frac_part %= 0x10000L; + if ( !frac_part ) + break; + + frac_part *= 10; + } + + /* + If the remainder stored in `frac_part' (after the last FOR loop) is + smaller than 34480*10, the resulting decimal value minus 0.00001 is + an equivalent representation of `fixed'. + + The above FOR loop always finds the larger of the two values; I + verified this by iterating over all possible fixed point numbers. + + If the remainder is 17232*10, both values are equally good, and we + take the next even number (following IEEE 754's `round to nearest, + ties to even' rounding rule). + + If the remainder is smaller than 17232*10, the lower of the two + numbers is nearer to the exact result (values 17232 and 34480 were + also found by testing all possible fixed point values). + + We use this to find a shorter decimal representation. If not ending + with digit zero, we take the representation with less error. + */ + p--; + if ( p - q == 5 ) /* five digits? */ + { + /* take the representation that has zero as the last digit */ + if ( frac_part < 34480 * 10 && + *p == '1' ) + *p = '0'; + + /* otherwise use the one with less error */ + else if ( frac_part == 17232 * 10 && + *p & 1 ) + *p -= 1; + + else if ( frac_part < 17232 * 10 && + *p != '0' ) + *p -= 1; + } + + /* remove trailing zeros */ + while ( *p == '0' ) + *p-- = '\0'; + + return p + 1; + } + + + static const char hexdigits[16] = + { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + + + static const char* + sfnt_get_var_ps_name( TT_Face face ) + { + FT_Error error; + FT_Memory memory = face->root.memory; + + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + FT_UInt num_coords; + FT_Fixed* coords; + FT_MM_Var* mm_var; + + FT_Int found, win, apple; + FT_UInt i, j; + + char* result = NULL; + char* p; + + + if ( !face->var_postscript_prefix ) + { + FT_UInt len; + + + /* check whether we have a Variations PostScript Name Prefix */ + found = sfnt_get_name_id( face, + TT_NAME_ID_VARIATIONS_PREFIX, + &win, + &apple ); + if ( !found ) + { + /* otherwise use the typographic family name */ + found = sfnt_get_name_id( face, + TT_NAME_ID_TYPOGRAPHIC_FAMILY, + &win, + &apple ); + } + + if ( !found ) + { + /* as a last resort we try the family name; note that this is */ + /* not in the Adobe TechNote, but GX fonts (which predate the */ + /* TechNote) benefit from this behaviour */ + found = sfnt_get_name_id( face, + TT_NAME_ID_FONT_FAMILY, + &win, + &apple ); + } + + if ( !found ) + { + FT_TRACE0(( "sfnt_get_var_ps_name:" + " Can't construct PS name prefix for font instances\n" )); + return NULL; + } + + /* prefer Windows entries over Apple */ + if ( win != -1 ) + result = get_win_string( face->root.memory, + face->name_table.stream, + face->name_table.names + win, + sfnt_is_alphanumeric, + 0 ); + else + result = get_apple_string( face->root.memory, + face->name_table.stream, + face->name_table.names + apple, + sfnt_is_alphanumeric, + 0 ); + + len = ft_strlen( result ); + + /* sanitize if necessary; we reserve space for 36 bytes (a 128bit */ + /* checksum as a hex number, preceded by `-' and followed by three */ + /* ASCII dots, to be used if the constructed PS name would be too */ + /* long); this is also sufficient for a single instance */ + if ( len > MAX_PS_NAME_LEN - ( 1 + 32 + 3 ) ) + { + len = MAX_PS_NAME_LEN - ( 1 + 32 + 3 ); + result[len] = '\0'; + + FT_TRACE0(( "sfnt_get_var_ps_name:" + " Shortening variation PS name prefix\n" + " " + " to %d characters\n", len )); + } + + face->var_postscript_prefix = result; + face->var_postscript_prefix_len = len; + } + + mm->get_var_blend( FT_FACE( face ), + &num_coords, + &coords, + NULL, + &mm_var ); + + if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) && + !FT_IS_VARIATION( FT_FACE( face ) ) ) + { + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + + FT_Long instance = ( ( face->root.face_index & 0x7FFF0000L ) >> 16 ) - 1; + FT_UInt psid = mm_var->namedstyle[instance].psid; + + char* ps_name = NULL; + + + /* try first to load the name string with index `postScriptNameID' */ + if ( psid == 6 || + ( psid > 255 && psid < 32768 ) ) + (void)sfnt->get_name( face, (FT_UShort)psid, &ps_name ); + + if ( ps_name ) + { + result = ps_name; + p = result + ft_strlen( result ) + 1; + + goto check_length; + } + else + { + /* otherwise construct a name using `subfamilyNameID' */ + FT_UInt strid = mm_var->namedstyle[instance].strid; + + char* subfamily_name; + char* s; + + + (void)sfnt->get_name( face, (FT_UShort)strid, &subfamily_name ); + + if ( !subfamily_name ) + { + FT_TRACE1(( "sfnt_get_var_ps_name:" + " can't construct named instance PS name;\n" + " " + " trying to construct normal instance PS name\n" )); + goto construct_instance_name; } - p = (FT_Char*)stream->cursor; + /* after the prefix we have character `-' followed by the */ + /* subfamily name (using only characters a-z, A-Z, and 0-9) */ + if ( FT_ALLOC( result, face->var_postscript_prefix_len + + 1 + ft_strlen( subfamily_name ) + 1 ) ) + return NULL; + + ft_strcpy( result, face->var_postscript_prefix ); + + p = result + face->var_postscript_prefix_len; + *p++ = '-'; - for ( ; len > 0; len--, p += 2 ) + s = subfamily_name; + while ( *s ) { - if ( p[0] == 0 && p[1] >= 32 ) - *r++ = p[1]; + if ( ft_isalnum( *s ) ) + *p++ = *s; + s++; } - *r = '\0'; + *p++ = '\0'; + + FT_FREE( subfamily_name ); + } + } + else + { + FT_Var_Axis* axis; + + + construct_instance_name: + axis = mm_var->axis; - FT_FRAME_EXIT(); + if ( FT_ALLOC( result, + face->var_postscript_prefix_len + + num_coords * MAX_VALUE_DESCRIPTOR_LEN + 1 ) ) + return NULL; + + p = result; + + ft_strcpy( p, face->var_postscript_prefix ); + p += face->var_postscript_prefix_len; + + for ( i = 0; i < num_coords; i++, coords++, axis++ ) + { + char t; + + + /* omit axis value descriptor if it is identical */ + /* to the default axis value */ + if ( *coords == axis->def ) + continue; + + *p++ = '_'; + p = fixed2float( *coords, p ); + + t = (char)( axis->tag >> 24 ); + if ( t != ' ' && ft_isalnum( t ) ) + *p++ = t; + t = (char)( axis->tag >> 16 ); + if ( t != ' ' && ft_isalnum( t ) ) + *p++ = t; + t = (char)( axis->tag >> 8 ); + if ( t != ' ' && ft_isalnum( t ) ) + *p++ = t; + t = (char)axis->tag; + if ( t != ' ' && ft_isalnum( t ) ) + *p++ = t; } - goto Exit; } - if ( found_apple != -1 ) + check_length: + if ( p - result > MAX_PS_NAME_LEN ) { - FT_Memory memory = face->root.memory; - TT_NameEntryRec* name = face->name_table.names + found_apple; - FT_UInt len = name->stringLength; - FT_Error error = FT_Err_Ok; + /* the PS name is too long; replace the part after the prefix with */ + /* a checksum; we use MurmurHash 3 with a hash length of 128 bit */ - FT_UNUSED( error ); + FT_UInt32 seed = 123456789; + FT_UInt32 hash[4]; + FT_UInt32* h; - if ( !FT_ALLOC( result, len + 1 ) ) + + murmur_hash_3_128( result, p - result, seed, hash ); + + p = result + face->var_postscript_prefix_len; + *p++ = '-'; + + /* we convert the hash value to hex digits from back to front */ + p += 32 + 3; + h = hash + 3; + + *p-- = '\0'; + *p-- = '.'; + *p-- = '.'; + *p-- = '.'; + + for ( i = 0; i < 4; i++, h-- ) { - FT_Stream stream = face->name_table.stream; + FT_UInt32 v = *h; - if ( FT_STREAM_SEEK( name->stringOffset ) || - FT_STREAM_READ( result, len ) ) + for ( j = 0; j < 8; j++ ) { - name->stringOffset = 0; - name->stringLength = 0; - FT_FREE( name->string ); - FT_FREE( result ); - goto Exit; + *p-- = hexdigits[v & 0xF]; + v >>= 4; } - ((char*)result)[len] = '\0'; } } - Exit: + return result; + } + +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + + static const char* + sfnt_get_ps_name( TT_Face face ) + { + FT_Int found, win, apple; + const char* result = NULL; + + + if ( face->postscript_name ) + return face->postscript_name; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( face->blend && + ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || + FT_IS_VARIATION( FT_FACE( face ) ) ) ) + { + face->postscript_name = sfnt_get_var_ps_name( face ); + return face->postscript_name; + } +#endif + + /* scan the name table to see whether we have a Postscript name here, */ + /* either in Macintosh or Windows platform encodings */ + found = sfnt_get_name_id( face, TT_NAME_ID_PS_NAME, &win, &apple ); + if ( !found ) + return NULL; + + /* prefer Windows entries over Apple */ + if ( win != -1 ) + result = get_win_string( face->root.memory, + face->name_table.stream, + face->name_table.names + win, + sfnt_is_postscript, + 1 ); + else + result = get_apple_string( face->root.memory, + face->name_table.stream, + face->name_table.names + apple, + sfnt_is_postscript, + 1 ); + face->postscript_name = result; + return result; } @@ -528,7 +1262,8 @@ tt_face_get_metrics, /* TT_Get_Metrics_Func get_metrics */ - tt_face_get_name /* TT_Get_Name_Func get_name */ + tt_face_get_name, /* TT_Get_Name_Func get_name */ + sfnt_get_name_id /* TT_Get_Name_ID_Func get_name_id */ ) diff --git a/modules/freetype2/src/sfnt/sfdriver.h b/modules/freetype2/src/sfnt/sfdriver.h index 2694488e2..81c22d288 100644 --- a/modules/freetype2/src/sfnt/sfdriver.h +++ b/modules/freetype2/src/sfnt/sfdriver.h @@ -4,7 +4,7 @@ /* */ /* High-level SFNT driver interface (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/sferrors.h b/modules/freetype2/src/sfnt/sferrors.h index c2f9fdfea..74003d4b3 100644 --- a/modules/freetype2/src/sfnt/sferrors.h +++ b/modules/freetype2/src/sfnt/sferrors.h @@ -4,7 +4,7 @@ /* */ /* SFNT error codes (specification only). */ /* */ -/* Copyright 2001-2016 by */ +/* Copyright 2001-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/sfnt.c b/modules/freetype2/src/sfnt/sfnt.c index 952d6d425..8b9a6b345 100644 --- a/modules/freetype2/src/sfnt/sfnt.c +++ b/modules/freetype2/src/sfnt/sfnt.c @@ -4,7 +4,7 @@ /* */ /* Single object library component. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -17,27 +17,19 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT - #include + +#include "pngshim.c" +#include "sfdriver.c" #include "sfntpic.c" -#include "ttload.c" -#include "ttmtx.c" +#include "sfobjs.c" +#include "ttbdf.c" #include "ttcmap.c" #include "ttkern.c" -#include "sfobjs.c" -#include "sfdriver.c" - -#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS -#include "pngshim.c" -#include "ttsbit.c" -#endif - -#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES +#include "ttload.c" +#include "ttmtx.c" #include "ttpost.c" -#endif +#include "ttsbit.c" -#ifdef TT_CONFIG_OPTION_BDF -#include "ttbdf.c" -#endif /* END */ diff --git a/modules/freetype2/src/sfnt/sfntpic.c b/modules/freetype2/src/sfnt/sfntpic.c index 1f596c093..db2d816ce 100644 --- a/modules/freetype2/src/sfnt/sfntpic.c +++ b/modules/freetype2/src/sfnt/sfntpic.c @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for sfnt module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/sfntpic.h b/modules/freetype2/src/sfnt/sfntpic.h index 5ce96d393..8f43122d8 100644 --- a/modules/freetype2/src/sfnt/sfntpic.h +++ b/modules/freetype2/src/sfnt/sfntpic.h @@ -4,7 +4,7 @@ /* */ /* The FreeType position independent code services for sfnt module. */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/sfobjs.c b/modules/freetype2/src/sfnt/sfobjs.c index 818009ef5..6ba8509f5 100644 --- a/modules/freetype2/src/sfnt/sfobjs.c +++ b/modules/freetype2/src/sfnt/sfobjs.c @@ -4,7 +4,7 @@ /* */ /* SFNT object management (base). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -54,8 +54,8 @@ /* convert a UTF-16 name entry to ASCII */ static FT_String* - tt_name_entry_ascii_from_utf16( TT_NameEntry entry, - FT_Memory memory ) + tt_name_ascii_from_utf16( TT_Name entry, + FT_Memory memory ) { FT_String* string = NULL; FT_UInt len, code, n; @@ -89,8 +89,8 @@ /* convert an Apple Roman or symbol name entry to ASCII */ static FT_String* - tt_name_entry_ascii_from_other( TT_NameEntry entry, - FT_Memory memory ) + tt_name_ascii_from_other( TT_Name entry, + FT_Memory memory ) { FT_String* string = NULL; FT_UInt len, code, n; @@ -122,8 +122,8 @@ } - typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry, - FT_Memory memory ); + typedef FT_String* (*TT_Name_ConvertFunc)( TT_Name entry, + FT_Memory memory ); /* documentation is in sfnt.h */ @@ -133,20 +133,21 @@ FT_UShort nameid, FT_String** name ) { - FT_Memory memory = face->root.memory; - FT_Error error = FT_Err_Ok; - FT_String* result = NULL; - FT_UShort n; - TT_NameEntryRec* rec; - FT_Int found_apple = -1; - FT_Int found_apple_roman = -1; - FT_Int found_apple_english = -1; - FT_Int found_win = -1; - FT_Int found_unicode = -1; + FT_Memory memory = face->root.memory; + FT_Error error = FT_Err_Ok; + FT_String* result = NULL; + FT_UShort n; + TT_Name rec; - FT_Bool is_english = 0; + FT_Int found_apple = -1; + FT_Int found_apple_roman = -1; + FT_Int found_apple_english = -1; + FT_Int found_win = -1; + FT_Int found_unicode = -1; - TT_NameEntry_ConvertFunc convert; + FT_Bool is_english = 0; + + TT_Name_ConvertFunc convert; FT_ASSERT( name ); @@ -231,7 +232,7 @@ /* all Unicode strings are encoded using UTF-16BE */ case TT_MS_ID_UNICODE_CS: case TT_MS_ID_SYMBOL_CS: - convert = tt_name_entry_ascii_from_utf16; + convert = tt_name_ascii_from_utf16; break; case TT_MS_ID_UCS_4: @@ -240,7 +241,7 @@ /* MsGothic font shipped with Windows Vista shows that this really */ /* means UTF-16 encoded names (UCS-4 values are only used within */ /* charmaps). */ - convert = tt_name_entry_ascii_from_utf16; + convert = tt_name_ascii_from_utf16; break; default: @@ -250,12 +251,12 @@ else if ( found_apple >= 0 ) { rec = face->name_table.names + found_apple; - convert = tt_name_entry_ascii_from_other; + convert = tt_name_ascii_from_other; } else if ( found_unicode >= 0 ) { rec = face->name_table.names + found_unicode; - convert = tt_name_entry_ascii_from_utf16; + convert = tt_name_ascii_from_utf16; } if ( rec && convert ) @@ -310,7 +311,7 @@ { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS }, - { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, FT_ENCODING_GB2312 }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_PRC, FT_ENCODING_PRC }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG }, { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB } @@ -786,6 +787,8 @@ tag != TTAG_OTTO && tag != TTAG_true && tag != TTAG_typ1 && + tag != TTAG_0xA5kbd && + tag != TTAG_0xA5lst && tag != 0x00020000UL ) { FT_TRACE2(( " not a font using the SFNT container format\n" )); @@ -893,7 +896,17 @@ 0 ); } - FT_FACE_FIND_GLOBAL_SERVICE( face, face->var, METRICS_VARIATIONS ); + if ( !face->var ) + { + /* we want the metrics variations interface */ + /* from the `truetype' module only */ + FT_Module tt_module = FT_Get_Module( library, "truetype" ); + + + face->var = ft_module_get_service( tt_module, + FT_SERVICE_ID_METRICS_VARIATIONS, + 0 ); + } #endif FT_TRACE2(( "SFNT driver\n" )); @@ -909,6 +922,10 @@ face_index = FT_ABS( face_instance_index ) & 0xFFFF; + /* value -(N+1) requests information on index N */ + if ( face_instance_index < 0 ) + face_index--; + if ( face_index >= face->ttc_header.count ) { if ( face_instance_index >= 0 ) @@ -927,6 +944,8 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT { + FT_Memory memory = face->root.memory; + FT_ULong fvar_len; FT_ULong version; @@ -939,8 +958,9 @@ FT_Int instance_index; + FT_Byte* default_values = NULL; + FT_Byte* instance_values = NULL; - face->is_default_instance = 1; instance_index = FT_ABS( face_instance_index ) >> 16; @@ -949,7 +969,7 @@ fvar_len < 20 || FT_READ_ULONG( version ) || FT_READ_USHORT( offset ) || - FT_STREAM_SKIP( 2 ) /* count_size_pairs */ || + FT_STREAM_SKIP( 2 ) /* reserved */ || FT_READ_USHORT( num_axes ) || FT_READ_USHORT( axis_size ) || FT_READ_USHORT( num_instances ) || @@ -965,18 +985,13 @@ /* check that the data is bound by the table length */ if ( version != 0x00010000UL || -#if 0 - /* fonts like `JamRegular.ttf' have an incorrect value for */ - /* `count_size_pairs'; since value 2 is hard-coded in `fvar' */ - /* version 1.0, we simply ignore it */ - count_size_pairs != 2 || -#endif axis_size != 20 || num_axes == 0 || /* `num_axes' limit implied by 16-bit `instance_size' */ num_axes > 0x3FFE || !( instance_size == 4 + 4 * num_axes || instance_size == 6 + 4 * num_axes ) || + /* `num_instances' limit implied by limited range of name IDs */ num_instances > 0x7EFF || offset + axis_size * num_axes + @@ -985,19 +1000,73 @@ else face->variation_support |= TT_FACE_FLAG_VAR_FVAR; - /* we don't support Multiple Master CFFs yet */ - if ( !face->goto_table( face, TTAG_CFF, stream, 0 ) ) - num_instances = 0; + /* + * As documented in the OpenType specification, an entry for the + * default instance may be omitted in the named instance table. In + * particular this means that even if there is no named instance + * table in the font we actually do have a named instance, namely the + * default instance. + * + * For consistency, we always want the default instance in our list + * of named instances. If it is missing, we try to synthesize it + * later on. Here, we have to adjust `num_instances' accordingly. + */ - /* we support at most 2^15 - 1 instances */ - if ( num_instances >= ( 1U << 15 ) - 1 ) + if ( ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) && + !( FT_ALLOC( default_values, num_axes * 4 ) || + FT_ALLOC( instance_values, num_axes * 4 ) ) ) { - if ( face_instance_index >= 0 ) - return FT_THROW( Invalid_Argument ); - else - num_instances = 0; + /* the current stream position is 16 bytes after the table start */ + FT_ULong array_start = FT_STREAM_POS() - 16 + offset; + FT_ULong default_value_offset, instance_offset; + + FT_Byte* p; + FT_UInt i; + + + default_value_offset = array_start + 8; + p = default_values; + + for ( i = 0; i < num_axes; i++ ) + { + (void)FT_STREAM_READ_AT( default_value_offset, p, 4 ); + + default_value_offset += axis_size; + p += 4; + } + + instance_offset = array_start + axis_size * num_axes + 4; + + for ( i = 0; i < num_instances; i++ ) + { + (void)FT_STREAM_READ_AT( instance_offset, + instance_values, + num_axes * 4 ); + + if ( !ft_memcmp( default_values, instance_values, num_axes * 4 ) ) + break; + + instance_offset += instance_size; + } + + if ( i == num_instances ) + { + /* no default instance in named instance table; */ + /* we thus have to synthesize it */ + num_instances++; + } } + FT_FREE( default_values ); + FT_FREE( instance_values ); + + /* we don't support Multiple Master CFFs yet; */ + /* note that `glyf' or `CFF2' have precedence */ + if ( face->goto_table( face, TTAG_glyf, stream, 0 ) && + face->goto_table( face, TTAG_CFF2, stream, 0 ) && + !face->goto_table( face, TTAG_CFF, stream, 0 ) ) + num_instances = 0; + /* instance indices in `face_instance_index' start with index 1, */ /* thus `>' and not `>=' */ if ( instance_index > num_instances ) @@ -1075,8 +1144,10 @@ 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; + FT_Bool has_CBLC; + FT_Bool has_CBDT; + FT_Bool ignore_typographic_family = FALSE; + FT_Bool ignore_typographic_subfamily = FALSE; SFNT_Service sfnt = (SFNT_Service)face->sfnt; @@ -1091,10 +1162,10 @@ for ( i = 0; i < num_params; i++ ) { - if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY ) - ignore_preferred_family = TRUE; - else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY ) - ignore_preferred_subfamily = TRUE; + if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY ) + ignore_typographic_family = TRUE; + else if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY ) + ignore_typographic_subfamily = TRUE; } } @@ -1155,7 +1226,17 @@ goto Exit; } - if ( face->header.Units_Per_EM == 0 ) + has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 ); + has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 ); + + /* Ignore outlines for CBLC/CBDT fonts. */ + if ( has_CBLC || has_CBDT ) + has_outline = FALSE; + + /* OpenType 1.8.2 introduced limits to this value; */ + /* however, they make sense for older SFNT fonts also */ + if ( face->header.Units_Per_EM < 16 || + face->header.Units_Per_EM > 16384 ) { error = FT_THROW( Invalid_Table ); @@ -1258,30 +1339,10 @@ /* embedded bitmap support */ if ( sfnt->load_eblc ) - { LOAD_( eblc ); - if ( error ) - { - /* a font which contains neither bitmaps nor outlines is */ - /* still valid (although rather useless in most cases); */ - /* however, you can find such stripped fonts in PDFs */ - if ( FT_ERR_EQ( error, Table_Missing ) ) - error = FT_Err_Ok; - else - goto Exit; - } - } + /* consider the pclt, kerning, and gasp tables as optional */ LOAD_( pclt ); - if ( error ) - { - if ( FT_ERR_NEQ( error, Table_Missing ) ) - goto Exit; - - face->pclt.Version = 0; - } - - /* consider the kerning and gasp tables as optional */ LOAD_( gasp ); LOAD_( kern ); @@ -1297,27 +1358,27 @@ face->root.style_name = NULL; if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) { - if ( !ignore_preferred_family ) - GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); + if ( !ignore_typographic_family ) + GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); if ( !face->root.family_name ) GET_NAME( FONT_FAMILY, &face->root.family_name ); - if ( !ignore_preferred_subfamily ) - GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); + if ( !ignore_typographic_subfamily ) + GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); if ( !face->root.style_name ) GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); } else { GET_NAME( WWS_FAMILY, &face->root.family_name ); - if ( !face->root.family_name && !ignore_preferred_family ) - GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); + if ( !face->root.family_name && !ignore_typographic_family ) + GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); if ( !face->root.family_name ) GET_NAME( FONT_FAMILY, &face->root.family_name ); GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); - if ( !face->root.style_name && !ignore_preferred_subfamily ) - GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); + if ( !face->root.style_name && !ignore_typographic_subfamily ) + GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); if ( !face->root.style_name ) GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); } @@ -1415,7 +1476,8 @@ /* Polish the charmaps. */ /* */ /* Try to set the charmap encoding according to the platform & */ - /* encoding ID of each charmap. */ + /* encoding ID of each charmap. Emulate Unicode charmap if one */ + /* is missing. */ /* */ tt_face_build_cmaps( face ); /* ignore errors */ @@ -1423,7 +1485,10 @@ /* set the encoding fields */ { - FT_Int m; + FT_Int m; +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + FT_Bool has_unicode = FALSE; +#endif for ( m = 0; m < root->num_charmaps; m++ ) @@ -1434,14 +1499,34 @@ charmap->encoding = sfnt_find_encoding( charmap->platform_id, charmap->encoding_id ); -#if 0 - if ( !root->charmap && - charmap->encoding == FT_ENCODING_UNICODE ) - { - /* set 'root->charmap' to the first Unicode encoding we find */ - root->charmap = charmap; - } -#endif +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + + if ( charmap->encoding == FT_ENCODING_UNICODE || + charmap->encoding == FT_ENCODING_MS_SYMBOL ) /* PUA */ + has_unicode = TRUE; + } + + /* synthesize Unicode charmap if one is missing */ + if ( !has_unicode ) + { + FT_CharMapRec cmaprec; + + + cmaprec.face = root; + cmaprec.platform_id = TT_PLATFORM_MICROSOFT; + cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; + cmaprec.encoding = FT_ENCODING_UNICODE; + + + error = FT_CMap_New( (FT_CMap_Class)&tt_cmap_unicode_class_rec, + NULL, &cmaprec, NULL ); + if ( error && + FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) + goto Exit; + error = FT_Err_Ok; + +#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + } } @@ -1608,9 +1693,9 @@ (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max : root->height ); - /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */ - /* Adjust underline position from top edge to centre of */ - /* stroke to convert TrueType meaning to FreeType meaning. */ + /* See https://www.microsoft.com/typography/otspec/post.htm -- */ + /* Adjust underline position from top edge to centre of */ + /* stroke to convert TrueType meaning to FreeType meaning. */ root->underline_position = face->postscript.underlinePosition - face->postscript.underlineThickness / 2; root->underline_thickness = face->postscript.underlineThickness; @@ -1707,7 +1792,10 @@ FT_FREE( face->sbit_strike_map ); face->root.num_fixed_sizes = 0; +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_FREE( face->postscript_name ); + FT_FREE( face->var_postscript_prefix ); +#endif face->sfnt = NULL; } diff --git a/modules/freetype2/src/sfnt/sfobjs.h b/modules/freetype2/src/sfnt/sfobjs.h index 60b5698ed..1b8d1be5b 100644 --- a/modules/freetype2/src/sfnt/sfobjs.h +++ b/modules/freetype2/src/sfnt/sfobjs.h @@ -4,7 +4,7 @@ /* */ /* SFNT object management (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/ttbdf.c b/modules/freetype2/src/sfnt/ttbdf.c index 62acf090c..534201f22 100644 --- a/modules/freetype2/src/sfnt/ttbdf.c +++ b/modules/freetype2/src/sfnt/ttbdf.c @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded BDF properties (body). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -246,7 +246,12 @@ return error; } -#endif /* TT_CONFIG_OPTION_BDF */ +#else /* !TT_CONFIG_OPTION_BDF */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_bdf_dummy; + +#endif /* !TT_CONFIG_OPTION_BDF */ /* END */ diff --git a/modules/freetype2/src/sfnt/ttbdf.h b/modules/freetype2/src/sfnt/ttbdf.h index ae521c60b..809a66300 100644 --- a/modules/freetype2/src/sfnt/ttbdf.h +++ b/modules/freetype2/src/sfnt/ttbdf.h @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded BDF properties (specification). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -28,6 +28,8 @@ FT_BEGIN_HEADER +#ifdef TT_CONFIG_OPTION_BDF + FT_LOCAL( void ) tt_face_free_bdf_props( TT_Face face ); @@ -37,6 +39,8 @@ FT_BEGIN_HEADER const char* property_name, BDF_PropertyRec *aprop ); +#endif /* TT_CONFIG_OPTION_BDF */ + FT_END_HEADER diff --git a/modules/freetype2/src/sfnt/ttcmap.c b/modules/freetype2/src/sfnt/ttcmap.c index e48c15c65..996e66485 100644 --- a/modules/freetype2/src/sfnt/ttcmap.c +++ b/modules/freetype2/src/sfnt/ttcmap.c @@ -4,7 +4,7 @@ /* */ /* TrueType character mapping table (cmap) support (body). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -23,8 +23,10 @@ #include FT_INTERNAL_VALIDATE_H #include FT_INTERNAL_STREAM_H +#include FT_SERVICE_POSTSCRIPT_CMAPS_H #include "ttload.h" #include "ttcmap.h" +#include "ttpost.h" #include "sfntpic.h" @@ -220,10 +222,10 @@ /***** The following charmap lookup and iteration functions all *****/ /***** assume that the value `charcode' fulfills the following. *****/ /***** *****/ - /***** - For one byte characters, `charcode' is simply the *****/ + /***** - For one-byte characters, `charcode' is simply the *****/ /***** character code. *****/ /***** *****/ - /***** - For two byte characters, `charcode' is the 2-byte *****/ + /***** - For two-byte characters, `charcode' is the 2-byte *****/ /***** character code in big endian format. More precisely: *****/ /***** *****/ /***** (charcode >> 8) is the first byte value *****/ @@ -250,11 +252,11 @@ /* subs 518 SUBHEAD[NSUBS] sub-headers array */ /* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */ /* */ - /* The `keys' table is used to map charcode high-bytes to sub-headers. */ + /* The `keys' table is used to map charcode high bytes to sub-headers. */ /* The value of `NSUBS' is the number of sub-headers defined in the */ /* table and is computed by finding the maximum of the `keys' table. */ /* */ - /* Note that for any n, `keys[n]' is a byte offset within the `subs' */ + /* Note that for any `n', `keys[n]' is a byte offset within the `subs' */ /* table, i.e., it is the corresponding sub-header index multiplied */ /* by 8. */ /* */ @@ -267,8 +269,8 @@ /* delta 4 SHORT see below */ /* offset 6 USHORT see below */ /* */ - /* A sub-header defines, for each high-byte, the range of valid */ - /* low-bytes within the charmap. Note that the range defined by `first' */ + /* A sub-header defines, for each high byte, the range of valid */ + /* low bytes within the charmap. Note that the range defined by `first' */ /* and `count' must be completely included in the interval [0..255] */ /* according to the specification. */ /* */ @@ -358,7 +360,7 @@ /* check range within 0..255 */ if ( valid->level >= FT_VALIDATE_PARANOID ) { - if ( first_code >= 256 || first_code + code_count > 256 ) + if ( first_code >= 256 || code_count > 256 - first_code ) FT_INVALID_DATA; } @@ -410,7 +412,7 @@ { FT_UInt char_lo = (FT_UInt)( char_code & 0xFF ); FT_UInt char_hi = (FT_UInt)( char_code >> 8 ); - FT_Byte* p = table + 6; /* keys table */ + FT_Byte* p = table + 6; /* keys table */ FT_Byte* subs = table + 518; /* subheaders table */ FT_Byte* sub; @@ -423,8 +425,8 @@ sub = subs; /* jump to first sub-header */ /* check that the sub-header for this byte is 0, which */ - /* indicates that it is really a valid one-byte value */ - /* Otherwise, return 0 */ + /* indicates that it is really a valid one-byte value; */ + /* otherwise, return 0 */ /* */ p += char_lo * 2; if ( TT_PEEK_USHORT( p ) != 0 ) @@ -443,6 +445,7 @@ if ( sub == subs ) goto Exit; } + result = sub; } @@ -515,8 +518,19 @@ FT_UInt pos, idx; + if ( char_lo >= start + count && charcode <= 0xFF ) + { + /* this happens only for a malformed cmap */ + charcode = 0x100; + continue; + } + if ( offset == 0 ) + { + if ( charcode == 0x100 ) + goto Exit; /* this happens only for a malformed cmap */ goto Next_SubHeader; + } if ( char_lo < start ) { @@ -543,11 +557,20 @@ } } } + + /* if unsuccessful, avoid `charcode' leaving */ + /* the current 256-character block */ + if ( count ) + charcode--; } - /* jump to next sub-header, i.e. higher byte value */ + /* If `charcode' is <= 0xFF, retry with `charcode + 1'. */ + /* Otherwise jump to the next 256-character block and retry. */ Next_SubHeader: - charcode = FT_PAD_FLOOR( charcode, 256 ) + 256; + if ( charcode <= 0xFF ) + charcode++; + else + charcode = FT_PAD_FLOOR( charcode, 0x100 ) + 0x100; } Exit: @@ -3622,6 +3645,110 @@ #endif /* TT_CONFIG_CMAP_FORMAT_14 */ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** SYNTHETIC UNICODE *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* This charmap is generated using postscript glyph names. */ + +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + + FT_CALLBACK_DEF( const char * ) + tt_get_glyph_name( TT_Face face, + FT_UInt idx ) + { + FT_String* PSname; + + + tt_face_get_ps_name( face, idx, &PSname ); + + return PSname; + } + + + FT_CALLBACK_DEF( FT_Error ) + tt_cmap_unicode_init( PS_Unicodes unicodes, + FT_Pointer pointer ) + { + TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + + FT_UNUSED( pointer ); + + + return psnames->unicodes_init( memory, + unicodes, + face->root.num_glyphs, + (PS_GetGlyphNameFunc)&tt_get_glyph_name, + (PS_FreeGlyphNameFunc)NULL, + (FT_Pointer)face ); + } + + + FT_CALLBACK_DEF( void ) + tt_cmap_unicode_done( PS_Unicodes unicodes ) + { + FT_Face face = FT_CMAP_FACE( unicodes ); + FT_Memory memory = FT_FACE_MEMORY( face ); + + + FT_FREE( unicodes->maps ); + unicodes->num_maps = 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap_unicode_char_index( PS_Unicodes unicodes, + FT_UInt32 char_code ) + { + TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + + + return psnames->unicodes_char_index( unicodes, char_code ); + } + + + FT_CALLBACK_DEF( FT_UInt32 ) + tt_cmap_unicode_char_next( PS_Unicodes unicodes, + FT_UInt32 *pchar_code ) + { + TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + + + return psnames->unicodes_char_next( unicodes, pchar_code ); + } + + + FT_DEFINE_TT_CMAP( + tt_cmap_unicode_class_rec, + + sizeof ( PS_UnicodesRec ), + + (FT_CMap_InitFunc) tt_cmap_unicode_init, /* init */ + (FT_CMap_DoneFunc) tt_cmap_unicode_done, /* done */ + (FT_CMap_CharIndexFunc)tt_cmap_unicode_char_index, /* char_index */ + (FT_CMap_CharNextFunc) tt_cmap_unicode_char_next, /* char_next */ + + (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ + (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ + (FT_CMap_VariantListFunc) NULL, /* variant_list */ + (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ + (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ + + ~0U, + (TT_CMap_ValidateFunc)NULL, /* validate */ + (TT_CMap_Info_GetFunc)NULL /* get_cmap_info */ + ) + +#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + #ifndef FT_CONFIG_OPTION_PIC static const TT_CMap_Class tt_cmap_classes[] = @@ -3801,8 +3928,10 @@ FT_CMap cmap = (FT_CMap)charmap; TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz; - - return clazz->get_cmap_info( charmap, cmap_info ); + if ( clazz->get_cmap_info ) + return clazz->get_cmap_info( charmap, cmap_info ); + else + return FT_THROW( Invalid_CharMap_Format ); } diff --git a/modules/freetype2/src/sfnt/ttcmap.h b/modules/freetype2/src/sfnt/ttcmap.h index 2273cbd96..d264d99d2 100644 --- a/modules/freetype2/src/sfnt/ttcmap.h +++ b/modules/freetype2/src/sfnt/ttcmap.h @@ -4,7 +4,7 @@ /* */ /* TrueType character mapping table (cmap) support (specification). */ /* */ -/* Copyright 2002-2016 by */ +/* Copyright 2002-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -141,6 +141,8 @@ FT_BEGIN_HEADER #define TT_VALID_GLYPH_COUNT( x ) TT_VALIDATOR( x )->num_glyphs + FT_CALLBACK_TABLE const TT_CMap_ClassRec tt_cmap_unicode_class_rec; + FT_LOCAL( FT_Error ) tt_face_build_cmaps( TT_Face face ); diff --git a/modules/freetype2/src/sfnt/ttcmapc.h b/modules/freetype2/src/sfnt/ttcmapc.h index 7c732fbd3..4980e9dd3 100644 --- a/modules/freetype2/src/sfnt/ttcmapc.h +++ b/modules/freetype2/src/sfnt/ttcmapc.h @@ -4,7 +4,7 @@ /* */ /* TT CMAP classes definitions (specification only). */ /* */ -/* Copyright 2009-2016 by */ +/* Copyright 2009-2018 by */ /* Oran Agra and Mickey Gabel. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/ttkern.c b/modules/freetype2/src/sfnt/ttkern.c index 6f9fa522d..68f15a201 100644 --- a/modules/freetype2/src/sfnt/ttkern.c +++ b/modules/freetype2/src/sfnt/ttkern.c @@ -5,7 +5,7 @@ /* Load the basic TrueType kerning table. This doesn't handle */ /* kerning data within the GPOS table at the moment. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -85,7 +85,7 @@ for ( nn = 0; nn < num_tables; nn++ ) { - FT_UInt num_pairs, length, coverage; + FT_UInt num_pairs, length, coverage, format; FT_Byte* p_next; FT_UInt32 mask = (FT_UInt32)1UL << nn; @@ -107,9 +107,15 @@ if ( p_next > p_limit ) /* handle broken table */ p_next = p_limit; + format = coverage >> 8; + + /* we currently only support format 0 kerning tables */ + if ( format != 0 ) + goto NextTable; + /* only use horizontal kerning tables */ - if ( ( coverage & ~8U ) != 0x0001 || - p + 8 > p_limit ) + if ( ( coverage & 3U ) != 0x0001 || + p + 8 > p_next ) goto NextTable; num_pairs = FT_NEXT_USHORT( p ); @@ -214,8 +220,7 @@ if ( ( face->kern_avail_bits & mask ) == 0 ) goto NextTable; - if ( p + 8 > next ) - goto NextTable; + FT_ASSERT( p + 8 <= next ); /* tested in tt_face_load_kern */ num_pairs = FT_NEXT_USHORT( p ); p += 6; diff --git a/modules/freetype2/src/sfnt/ttkern.h b/modules/freetype2/src/sfnt/ttkern.h index 85dd5c31a..4e45d0964 100644 --- a/modules/freetype2/src/sfnt/ttkern.h +++ b/modules/freetype2/src/sfnt/ttkern.h @@ -5,7 +5,7 @@ /* Load the basic TrueType kerning table. This doesn't handle */ /* kerning data within the GPOS table at the moment. */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/ttload.c b/modules/freetype2/src/sfnt/ttload.c index d615bba04..a86a546c3 100644 --- a/modules/freetype2/src/sfnt/ttload.c +++ b/modules/freetype2/src/sfnt/ttload.c @@ -5,7 +5,7 @@ /* Load the basic TrueType tables, i.e., tables that can be either in */ /* TTF or OTF fonts (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -338,7 +338,7 @@ SFNT_HeaderRec sfnt; FT_Error error; FT_Memory memory = stream->memory; - FT_UShort nn, valid_entries; + FT_UShort nn, valid_entries = 0; static const FT_Frame_Field offset_table_fields[] = { @@ -808,7 +808,6 @@ FT_Memory memory = stream->memory; FT_ULong table_pos, table_len; FT_ULong storage_start, storage_limit; - FT_UInt count; TT_NameTable table; static const FT_Frame_Field name_table_fields[] = @@ -826,7 +825,7 @@ static const FT_Frame_Field name_record_fields[] = { #undef FT_STRUCTURE -#define FT_STRUCTURE TT_NameEntryRec +#define FT_STRUCTURE TT_NameRec /* no FT_FRAME_START */ FT_FRAME_USHORT( platformID ), @@ -838,6 +837,17 @@ FT_FRAME_END }; + static const FT_Frame_Field langTag_record_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_LangTagRec + + /* no FT_FRAME_START */ + FT_FRAME_USHORT( stringLength ), + FT_FRAME_USHORT( stringOffset ), + FT_FRAME_END + }; + table = &face->name_table; table->stream = stream; @@ -848,18 +858,17 @@ table_pos = FT_STREAM_POS(); - if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) ) goto Exit; - /* Some popular Asian fonts have an invalid `storageOffset' value */ - /* (it should be at least "6 + 12*num_names"). However, the string */ - /* offsets, computed as "storageOffset + entry->stringOffset", are */ - /* valid pointers within the name table... */ - /* */ - /* We thus can't check `storageOffset' right now. */ - /* */ - storage_start = table_pos + 6 + 12*table->numNameRecords; + /* Some popular Asian fonts have an invalid `storageOffset' value (it */ + /* should be at least `6 + 12*numNameRecords'). However, the string */ + /* offsets, computed as `storageOffset + entry->stringOffset', are */ + /* valid pointers within the name table... */ + /* */ + /* We thus can't check `storageOffset' right now. */ + /* */ + storage_start = table_pos + 6 + 12 * table->numNameRecords; storage_limit = table_pos + table_len; if ( storage_start > storage_limit ) @@ -869,18 +878,56 @@ goto Exit; } - /* Allocate the array of name records. */ - count = table->numNameRecords; - table->numNameRecords = 0; + /* `name' format 1 contains additional language tag records, */ + /* which we load first */ + if ( table->format == 1 ) + { + if ( FT_STREAM_SEEK( storage_start ) || + FT_READ_USHORT( table->numLangTagRecords ) ) + goto Exit; + + storage_start += 2 + 4 * table->numLangTagRecords; + + /* allocate language tag records array */ + if ( FT_NEW_ARRAY( table->langTags, table->numLangTagRecords ) || + FT_FRAME_ENTER( table->numLangTagRecords * 4 ) ) + goto Exit; - if ( FT_NEW_ARRAY( table->names, count ) || - FT_FRAME_ENTER( count * 12 ) ) + /* load language tags */ + { + TT_LangTag entry = table->langTags; + TT_LangTag limit = entry + table->numLangTagRecords; + + + for ( ; entry < limit; entry++ ) + { + (void)FT_STREAM_READ_FIELDS( langTag_record_fields, entry ); + + /* check that the langTag string is within the table */ + entry->stringOffset += table_pos + table->storageOffset; + if ( entry->stringOffset < storage_start || + entry->stringOffset + entry->stringLength > storage_limit ) + { + /* invalid entry; ignore it */ + entry->stringLength = 0; + } + } + } + + FT_FRAME_EXIT(); + + (void)FT_STREAM_SEEK( table_pos + 6 ); + } + + /* allocate name records array */ + if ( FT_NEW_ARRAY( table->names, table->numNameRecords ) || + FT_FRAME_ENTER( table->numNameRecords * 12 ) ) goto Exit; - /* Load the name records and determine how much storage is needed */ - /* to hold the strings themselves. */ + /* load name records */ { - TT_NameEntryRec* entry = table->names; + TT_Name entry = table->names; + FT_UInt count = table->numNameRecords; for ( ; count > 0; count-- ) @@ -897,22 +944,37 @@ if ( entry->stringOffset < storage_start || entry->stringOffset + entry->stringLength > storage_limit ) { - /* invalid entry - ignore it */ - entry->stringOffset = 0; - entry->stringLength = 0; + /* invalid entry; ignore it */ continue; } + /* assure that we have a valid language tag ID, and */ + /* that the corresponding langTag entry is valid, too */ + if ( table->format == 1 && entry->languageID >= 0x8000U ) + { + if ( entry->languageID - 0x8000U >= table->numLangTagRecords || + !table->langTags[entry->languageID - 0x8000U].stringLength ) + { + /* invalid entry; ignore it */ + continue; + } + } + entry++; } - table->numNameRecords = (FT_UInt)( entry - table->names ); + /* reduce array size to the actually used elements */ + count = (FT_UInt)( entry - table->names ); + (void)FT_RENEW_ARRAY( table->names, + table->numNameRecords, + count ); + table->numNameRecords = count; } FT_FRAME_EXIT(); /* everything went well, update face->num_names */ - face->num_names = (FT_UShort) table->numNameRecords; + face->num_names = (FT_UShort)table->numNameRecords; Exit: return error; @@ -922,7 +984,7 @@ /*************************************************************************/ /* */ /* */ - /* tt_face_free_names */ + /* tt_face_free_name */ /* */ /* */ /* Frees the name records. */ @@ -935,25 +997,36 @@ { FT_Memory memory = face->root.driver->root.memory; TT_NameTable table = &face->name_table; - TT_NameEntry entry = table->names; - FT_UInt count = table->numNameRecords; if ( table->names ) { - for ( ; count > 0; count--, entry++ ) - { + TT_Name entry = table->names; + TT_Name limit = entry + table->numNameRecords; + + + for ( ; entry < limit; entry++ ) FT_FREE( entry->string ); - entry->stringLength = 0; - } - /* free strings table */ FT_FREE( table->names ); } - table->numNameRecords = 0; - table->format = 0; - table->storageOffset = 0; + if ( table->langTags ) + { + TT_LangTag entry = table->langTags; + TT_LangTag limit = entry + table->numLangTagRecords; + + + for ( ; entry < limit; entry++ ) + FT_FREE( entry->string ); + + FT_FREE( table->langTags ); + } + + table->numNameRecords = 0; + table->numLangTagRecords = 0; + table->format = 0; + table->storageOffset = 0; } diff --git a/modules/freetype2/src/sfnt/ttload.h b/modules/freetype2/src/sfnt/ttload.h index bec42b94b..f94be8b7b 100644 --- a/modules/freetype2/src/sfnt/ttload.h +++ b/modules/freetype2/src/sfnt/ttload.h @@ -5,7 +5,7 @@ /* Load the basic TrueType tables, i.e., tables that can be either in */ /* TTF or OTF fonts (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/ttmtx.c b/modules/freetype2/src/sfnt/ttmtx.c index 8c5508e24..6ddda95b5 100644 --- a/modules/freetype2/src/sfnt/ttmtx.c +++ b/modules/freetype2/src/sfnt/ttmtx.c @@ -4,7 +4,7 @@ /* */ /* Load the metrics tables common to TTF and OTF fonts (body). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -30,6 +30,14 @@ #include "sferrors.h" + /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ + /* be identical except for the names of their fields, */ + /* which are different. */ + /* */ + /* This ensures that `tt_face_load_hmtx' is able to read */ + /* both the horizontal and vertical headers. */ + + /*************************************************************************/ /* */ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ diff --git a/modules/freetype2/src/sfnt/ttmtx.h b/modules/freetype2/src/sfnt/ttmtx.h index 78395def3..ab00acd79 100644 --- a/modules/freetype2/src/sfnt/ttmtx.h +++ b/modules/freetype2/src/sfnt/ttmtx.h @@ -4,7 +4,7 @@ /* */ /* Load the metrics tables common to TTF and OTF fonts (specification). */ /* */ -/* Copyright 2006-2016 by */ +/* Copyright 2006-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/ttpost.c b/modules/freetype2/src/sfnt/ttpost.c index ef81e63a3..6de99ef97 100644 --- a/modules/freetype2/src/sfnt/ttpost.c +++ b/modules/freetype2/src/sfnt/ttpost.c @@ -5,7 +5,7 @@ /* PostScript name table processing for TrueType and OpenType fonts */ /* (body). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -29,6 +29,10 @@ #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_STREAM_H #include FT_TRUETYPE_TAGS_H + + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + #include "ttpost.h" #include "sferrors.h" @@ -321,7 +325,6 @@ FT_UNUSED( post_limit ); - /* UNDOCUMENTED! This value appears only in the Apple TT specs. */ if ( FT_READ_USHORT( num_glyphs ) ) goto Exit; @@ -404,7 +407,7 @@ /* now read postscript table */ if ( format == 0x00020000L ) error = load_format_20( face, stream, post_limit ); - else if ( format == 0x00028000L ) + else if ( format == 0x00025000L ) error = load_format_25( face, stream, post_limit ); else error = FT_THROW( Invalid_File_Format ); @@ -443,7 +446,7 @@ FT_FREE( table->glyph_names ); table->num_names = 0; } - else if ( format == 0x00028000L ) + else if ( format == 0x00025000L ) { TT_Post_25 table = &names->names.format_25; @@ -470,8 +473,8 @@ /* idx :: The glyph index. */ /* */ /* */ - /* PSname :: The address of a string pointer. Will be NULL in case */ - /* of error, otherwise it is a pointer to the glyph name. */ + /* PSname :: The address of a string pointer. Undefined in case of */ + /* error, otherwise it is a pointer to the glyph name. */ /* */ /* You must not modify the returned string! */ /* */ @@ -539,7 +542,7 @@ *PSname = (FT_String*)table->glyph_names[name_index - 258]; } } - else if ( format == 0x00028000L ) + else if ( format == 0x00025000L ) { TT_Post_25 table = &names->names.format_25; @@ -561,5 +564,12 @@ return FT_Err_Ok; } +#else /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_post_dummy; + +#endif /* !TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + /* END */ diff --git a/modules/freetype2/src/sfnt/ttpost.h b/modules/freetype2/src/sfnt/ttpost.h index ede45fd84..3bec07e44 100644 --- a/modules/freetype2/src/sfnt/ttpost.h +++ b/modules/freetype2/src/sfnt/ttpost.h @@ -5,7 +5,7 @@ /* PostScript name table processing for TrueType and OpenType fonts */ /* (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ diff --git a/modules/freetype2/src/sfnt/ttsbit.c b/modules/freetype2/src/sfnt/ttsbit.c index bf6ecca5a..33b8640bc 100644 --- a/modules/freetype2/src/sfnt/ttsbit.c +++ b/modules/freetype2/src/sfnt/ttsbit.c @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded bitmap support (body). */ /* */ -/* Copyright 2005-2016 by */ +/* Copyright 2005-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* Copyright 2013 by Google, Inc. */ @@ -24,6 +24,10 @@ #include FT_INTERNAL_STREAM_H #include FT_TRUETYPE_TAGS_H #include FT_BITMAP_H + + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + #include "ttsbit.h" #include "sferrors.h" @@ -444,6 +448,15 @@ metrics->max_advance = FT_MulDiv( hori->advance_Width_Max, ppem_ * 64, upem ); + /* set the scale values (in 16.16 units) so advances */ + /* from the hmtx and vmtx table are scaled correctly */ + metrics->x_scale = FT_MulDiv( metrics->x_ppem, + 64 * 0x10000, + face->header.Units_Per_EM ); + metrics->y_scale = FT_MulDiv( metrics->y_ppem, + 64 * 0x10000, + face->header.Units_Per_EM ); + return error; } @@ -994,8 +1007,9 @@ goto Fail; } - FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %d components\n", - num_components )); + FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %d component%s\n", + num_components, + num_components == 1 ? "" : "s" )); for ( nn = 0; nn < num_components; nn++ ) { @@ -1435,10 +1449,17 @@ return FT_THROW( Invalid_Table ); NoBitmap: + if ( recurse_count ) + { + FT_TRACE4(( "tt_sbit_decoder_load_image:" + " missing subglyph sbit with glyph index %d\n", + glyph_index )); + return FT_THROW( Invalid_Composite ); + } + FT_TRACE4(( "tt_sbit_decoder_load_image:" " no sbit found for glyph index %d\n", glyph_index )); - - return FT_THROW( Invalid_Argument ); + return FT_THROW( Missing_Bitmap ); } @@ -1460,6 +1481,9 @@ FT_Byte* p; FT_UNUSED( map ); +#ifndef FT_CONFIG_OPTION_USE_PNG + FT_UNUSED( metrics_only ); +#endif strike_index = face->sbit_strike_map[strike_index]; @@ -1490,7 +1514,7 @@ FT_FRAME_EXIT(); if ( glyph_start == glyph_end ) - return FT_THROW( Invalid_Argument ); + return FT_THROW( Missing_Bitmap ); if ( glyph_start > glyph_end || glyph_end - glyph_start < 8 || face->ebdt_size - strike_offset < glyph_end ) @@ -1647,5 +1671,12 @@ return error; } +#else /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /* ANSI C doesn't like empty source files */ + typedef int _tt_sbit_dummy; + +#endif /* !TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + -/* EOF */ +/* END */ diff --git a/modules/freetype2/src/sfnt/ttsbit.h b/modules/freetype2/src/sfnt/ttsbit.h index d8a816708..ce2af3c16 100644 --- a/modules/freetype2/src/sfnt/ttsbit.h +++ b/modules/freetype2/src/sfnt/ttsbit.h @@ -4,7 +4,7 @@ /* */ /* TrueType and OpenType embedded bitmap support (specification). */ /* */ -/* Copyright 1996-2016 by */ +/* Copyright 1996-2018 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ -- cgit v1.2.3