@ -144,7 +144,7 @@ struct NameRecord
NameRecord * copy ( hb_serialize_context_t * c , const void * base
NameRecord * copy ( hb_serialize_context_t * c , const void * base
# ifdef HB_EXPERIMENTAL_API
# ifdef HB_EXPERIMENTAL_API
, const hb_hashmap_t < unsigned , hb_bytes_t > * name_table_overrides
, const hb_hashmap_t < hb_ot_name_record_ids_t , hb_bytes_t > * name_table_overrides
# endif
# endif
) const
) const
{
{
@ -153,33 +153,49 @@ struct NameRecord
auto * out = c - > embed ( this ) ;
auto * out = c - > embed ( this ) ;
if ( unlikely ( ! out ) ) return_trace ( nullptr ) ;
if ( unlikely ( ! out ) ) return_trace ( nullptr ) ;
# ifdef HB_EXPERIMENTAL_API
# ifdef HB_EXPERIMENTAL_API
if ( name_table_overrides - > has ( nameID ) )
hb_ot_name_record_ids_t record_ids ( platformID , encodingID , languageID , nameID ) ;
{
hb_bytes_t * name_bytes ;
hb_bytes_t name_bytes = name_table_overrides - > get ( nameID ) ;
unsigned text_size = hb_ot_name_convert_utf < hb_utf8_t , hb_utf16_be_t > ( name_bytes , nullptr , nullptr ) ;
if ( name_table_overrides - > has ( record_ids , & name_bytes ) ) {
hb_bytes_t encoded_bytes = * name_bytes ;
char * name_str_utf16_be = nullptr ;
text_size + + ; // needs to consider NULL terminator for use in hb_ot_name_convert_utf()
if ( platformID ! = 1 )
unsigned byte_len = text_size * hb_utf16_be_t : : codepoint_t : : static_size ;
char * name_str_utf16_be = ( char * ) hb_calloc ( byte_len , 1 ) ;
if ( ! name_str_utf16_be )
{
{
c - > revert ( snap ) ;
unsigned text_size = hb_ot_name_convert_utf < hb_utf8_t , hb_utf16_be_t > ( * name_bytes , nullptr , nullptr ) ;
return_trace ( nullptr ) ;
text_size + + ; // needs to consider NULL terminator for use in hb_ot_name_convert_utf()
unsigned byte_len = text_size * hb_utf16_be_t : : codepoint_t : : static_size ;
name_str_utf16_be = ( char * ) hb_calloc ( byte_len , 1 ) ;
if ( ! name_str_utf16_be )
{
c - > revert ( snap ) ;
return_trace ( nullptr ) ;
}
hb_ot_name_convert_utf < hb_utf8_t , hb_utf16_be_t > ( * name_bytes , & text_size ,
( hb_utf16_be_t : : codepoint_t * ) name_str_utf16_be ) ;
unsigned encoded_byte_len = text_size * hb_utf16_be_t : : codepoint_t : : static_size ;
if ( ! encoded_byte_len | | ! c - > check_assign ( out - > length , encoded_byte_len , HB_SERIALIZE_ERROR_INT_OVERFLOW ) ) {
c - > revert ( snap ) ;
hb_free ( name_str_utf16_be ) ;
return_trace ( nullptr ) ;
}
encoded_bytes = hb_bytes_t ( name_str_utf16_be , encoded_byte_len ) ;
}
}
hb_ot_name_convert_utf < hb_utf8_t , hb_utf16_be_t > ( name_bytes , & text_size ,
else
( hb_utf16_be_t : : codepoint_t * ) name_str_utf16_be ) ;
{
// mac platform, copy the UTF-8 string(all ascii characters) as is
unsigned encoded_byte_len = text_size * hb_utf16_be_t : : codepoint_t : : static_size ;
if ( ! c - > check_assign ( out - > length , encoded_bytes . length , HB_SERIALIZE_ERROR_INT_OVERFLOW ) ) {
if ( ! encoded_byte_len | | ! c - > check_assign ( out - > length , encoded_byte_len , HB_SERIALIZE_ERROR_INT_OVERFLOW ) ) {
c - > revert ( snap ) ;
c - > revert ( snap ) ;
return_trace ( nullptr ) ;
hb_free ( name_str_utf16_be ) ;
}
return_trace ( nullptr ) ;
}
}
hb_bytes_t utf16_be_bytes ( name_str_utf16_be , encoded_byte_len ) ;
out - > offset = 0 ;
out - > offset = 0 ;
c - > push ( ) ;
c - > push ( ) ;
utf16_be_bytes . copy ( c ) ;
encoded _bytes. copy ( c ) ;
c - > add_link ( out - > offset , c - > pop_pack ( ) , hb_serialize_context_t : : Tail , 0 ) ;
c - > add_link ( out - > offset , c - > pop_pack ( ) , hb_serialize_context_t : : Tail , 0 ) ;
hb_free ( name_str_utf16_be ) ;
hb_free ( name_str_utf16_be ) ;
}
}
@ -303,7 +319,8 @@ struct name
Iterator it ,
Iterator it ,
const void * src_string_pool
const void * src_string_pool
# ifdef HB_EXPERIMENTAL_API
# ifdef HB_EXPERIMENTAL_API
, const hb_hashmap_t < unsigned , hb_bytes_t > * name_table_overrides
, const hb_vector_t < hb_ot_name_record_ids_t > & insert_name_records
, const hb_hashmap_t < hb_ot_name_record_ids_t , hb_bytes_t > * name_table_overrides
# endif
# endif
)
)
{
{
@ -311,13 +328,19 @@ struct name
if ( unlikely ( ! c - > extend_min ( ( * this ) ) ) ) return_trace ( false ) ;
if ( unlikely ( ! c - > extend_min ( ( * this ) ) ) ) return_trace ( false ) ;
unsigned total_count = it . len ( )
# ifdef HB_EXPERIMENTAL_API
+ insert_name_records . length
# endif
;
this - > format = 0 ;
this - > format = 0 ;
this - > count = it . len ( ) ;
if ( ! c - > check_assign ( this - > count , total_count , HB_SERIALIZE_ERROR_INT_OVERFLOW ) )
return false ;
NameRecord * name_records = ( NameRecord * ) hb_calloc ( it . len ( ) , NameRecord : : static_size ) ;
NameRecord * name_records = ( NameRecord * ) hb_calloc ( total_count , NameRecord : : static_size ) ;
if ( unlikely ( ! name_records ) ) return_trace ( false ) ;
if ( unlikely ( ! name_records ) ) return_trace ( false ) ;
hb_array_t < NameRecord > records ( name_records , it . len ( ) ) ;
hb_array_t < NameRecord > records ( name_records , total_count ) ;
for ( const NameRecord & record : it )
for ( const NameRecord & record : it )
{
{
@ -325,6 +348,22 @@ struct name
name_records + + ;
name_records + + ;
}
}
# ifdef HB_EXPERIMENTAL_API
for ( unsigned i = 0 ; i < insert_name_records . length ; i + + )
{
const hb_ot_name_record_ids_t & ids = insert_name_records [ i ] ;
NameRecord record ;
record . platformID = ids . platform_id ;
record . encodingID = ids . encoding_id ;
record . languageID = ids . language_id ;
record . nameID = ids . name_id ;
record . length = 0 ; // handled in NameRecord copy()
record . offset = 0 ;
memcpy ( name_records , & record , NameRecord : : static_size ) ;
name_records + + ;
}
# endif
records . qsort ( ) ;
records . qsort ( ) ;
c - > copy_all ( records ,
c - > copy_all ( records ,
@ -350,6 +389,11 @@ struct name
name * name_prime = c - > serializer - > start_embed < name > ( ) ;
name * name_prime = c - > serializer - > start_embed < name > ( ) ;
if ( unlikely ( ! name_prime ) ) return_trace ( false ) ;
if ( unlikely ( ! name_prime ) ) return_trace ( false ) ;
# ifdef HB_EXPERIMENTAL_API
const hb_hashmap_t < hb_ot_name_record_ids_t , hb_bytes_t > * name_table_overrides =
c - > plan - > name_table_overrides ;
# endif
auto it =
auto it =
+ nameRecordZ . as_array ( count )
+ nameRecordZ . as_array ( count )
| hb_filter ( c - > plan - > name_ids , & NameRecord : : nameID )
| hb_filter ( c - > plan - > name_ids , & NameRecord : : nameID )
@ -359,15 +403,48 @@ struct name
( c - > plan - > flags & HB_SUBSET_FLAGS_NAME_LEGACY )
( c - > plan - > flags & HB_SUBSET_FLAGS_NAME_LEGACY )
| | namerecord . isUnicode ( ) ;
| | namerecord . isUnicode ( ) ;
} )
} )
# ifdef HB_EXPERIMENTAL_API
| hb_filter ( [ & ] ( const NameRecord & namerecord ) {
if ( name_table_overrides - > is_empty ( ) )
return true ;
hb_ot_name_record_ids_t rec_ids ( namerecord . platformID ,
namerecord . encodingID ,
namerecord . languageID ,
namerecord . nameID ) ;
hb_bytes_t * p ;
if ( name_table_overrides - > has ( rec_ids , & p ) & &
( * p ) . length = = 0 )
return false ;
return true ;
} )
# endif
;
;
name_prime - > serialize ( c - > serializer ,
it , std : : addressof ( this + stringOffset )
# ifdef HB_EXPERIMENTAL_API
# ifdef HB_EXPERIMENTAL_API
, c - > plan - > name_table_overrides
hb_vector_t < hb_ot_name_record_ids_t > insert_name_records ;
if ( ! name_table_overrides - > is_empty ( ) )
{
if ( unlikely ( ! insert_name_records . alloc ( name_table_overrides - > get_population ( ) ) ) )
return_trace ( false ) ;
for ( const auto & record_ids : name_table_overrides - > keys ( ) )
{
if ( name_table_overrides - > get ( record_ids ) . length = = 0 )
continue ;
if ( has_name_record_with_ids ( record_ids ) )
continue ;
insert_name_records . push ( record_ids ) ;
}
}
# endif
# endif
) ;
return_trace ( name_prime - > count ) ;
return ( name_prime - > serialize ( c - > serializer , it ,
std : : addressof ( this + stringOffset )
# ifdef HB_EXPERIMENTAL_API
, insert_name_records
, name_table_overrides
# endif
) ) ;
}
}
bool sanitize_records ( hb_sanitize_context_t * c ) const
bool sanitize_records ( hb_sanitize_context_t * c ) const
@ -477,6 +554,23 @@ struct name
hb_vector_t < hb_ot_name_entry_t > names ;
hb_vector_t < hb_ot_name_entry_t > names ;
} ;
} ;
private :
// sometimes NameRecords are not sorted in the font file, so use linear search
// here
bool has_name_record_with_ids ( const hb_ot_name_record_ids_t & record_ids ) const
{
for ( const auto & record : nameRecordZ . as_array ( count ) )
{
if ( record . platformID = = record_ids . platform_id & &
record . encodingID = = record_ids . encoding_id & &
record . languageID = = record_ids . language_id & &
record . nameID = = record_ids . name_id )
return true ;
}
return false ;
}
public :
/* We only implement format 0 for now. */
/* We only implement format 0 for now. */
HBUINT16 format ; /* Format selector (=0/1). */
HBUINT16 format ; /* Format selector (=0/1). */
HBUINT16 count ; /* Number of name records. */
HBUINT16 count ; /* Number of name records. */