#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftstream.h>
#include <freetype/internal/ftrfork.h>
#include "ftbase.h"
#undef FT_COMPONENT
#define FT_COMPONENT …
FT_BASE_DEF( FT_Error )
FT_Raccess_Get_HeaderInfo( FT_Library library,
FT_Stream stream,
FT_Long rfork_offset,
FT_Long *map_offset,
FT_Long *rdata_pos )
{ … }
FT_COMPARE_DEF( int )
ft_raccess_sort_ref_by_id( const void* a,
const void* b )
{ … }
FT_BASE_DEF( FT_Error )
FT_Raccess_Get_DataOffsets( FT_Library library,
FT_Stream stream,
FT_Long map_offset,
FT_Long rdata_pos,
FT_Long tag,
FT_Bool sort_by_res_id,
FT_Long **offsets,
FT_Long *count )
{ … }
#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
static FT_Error
raccess_guess_apple_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_apple_single( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_ufs_export( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_newvfs( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_darwin_hfsplus( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_vfat( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_cap( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_netatalk( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset );
CONST_FT_RFORK_RULE_ARRAY_BEGIN( ft_raccess_guess_table,
ft_raccess_guess_rec )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_double, apple_double )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_single, apple_single )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_ufs_export, darwin_ufs_export )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_newvfs, darwin_newvfs )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_hfsplus, darwin_hfsplus )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( vfat, vfat )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_cap, linux_cap )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_double, linux_double )
CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_netatalk, linux_netatalk )
CONST_FT_RFORK_RULE_ARRAY_END
static FT_Error
raccess_guess_apple_generic( FT_Library library,
FT_Stream stream,
char *base_file_name,
FT_Int32 magic,
FT_Long *result_offset );
static FT_Error
raccess_guess_linux_double_from_file_name( FT_Library library,
char* file_name,
FT_Long *result_offset );
static char *
raccess_make_file_name( FT_Memory memory,
const char *original_name,
const char *insertion );
FT_BASE_DEF( void )
FT_Raccess_Guess( FT_Library library,
FT_Stream stream,
char* base_name,
char **new_names,
FT_Long *offsets,
FT_Error *errors )
{
FT_Int i;
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
{
new_names[i] = NULL;
if ( NULL != stream )
errors[i] = FT_Stream_Seek( stream, 0 );
else
errors[i] = FT_Err_Ok;
if ( errors[i] )
continue;
errors[i] = ft_raccess_guess_table[i].func( library,
stream, base_name,
&(new_names[i]),
&(offsets[i]) );
}
return;
}
#if defined( FT_CONFIG_OPTION_MAC_FONTS ) && !defined( FT_MACINTOSH )
static FT_RFork_Rule
raccess_get_rule_type_from_rule_index( FT_Library library,
FT_UInt rule_index )
{
FT_UNUSED( library );
if ( rule_index >= FT_RACCESS_N_RULES )
return FT_RFork_Rule_invalid;
return ft_raccess_guess_table[rule_index].type;
}
FT_LOCAL_DEF( FT_Bool )
ft_raccess_rule_by_darwin_vfs( FT_Library library,
FT_UInt rule_index )
{
switch( raccess_get_rule_type_from_rule_index( library, rule_index ) )
{
case FT_RFork_Rule_darwin_newvfs:
case FT_RFork_Rule_darwin_hfsplus:
return TRUE;
default:
return FALSE;
}
}
#endif
static FT_Error
raccess_guess_apple_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
FT_Int32 magic = ( 0x00 << 24 ) |
( 0x05 << 16 ) |
( 0x16 << 8 ) |
0x07;
*result_file_name = NULL;
if ( NULL == stream )
return FT_THROW( Cannot_Open_Stream );
return raccess_guess_apple_generic( library, stream, base_file_name,
magic, result_offset );
}
static FT_Error
raccess_guess_apple_single( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
FT_Int32 magic = ( 0x00 << 24 ) |
( 0x05 << 16 ) |
( 0x16 << 8 ) |
0x00;
*result_file_name = NULL;
if ( NULL == stream )
return FT_THROW( Cannot_Open_Stream );
return raccess_guess_apple_generic( library, stream, base_file_name,
magic, result_offset );
}
static FT_Error
raccess_guess_darwin_ufs_export( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Error error;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name, "._" );
if ( !newpath )
return FT_THROW( Out_Of_Memory );
error = raccess_guess_linux_double_from_file_name( library, newpath,
result_offset );
if ( !error )
*result_file_name = newpath;
else
FT_FREE( newpath );
return error;
}
static FT_Error
raccess_guess_darwin_hfsplus( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
FT_Error error;
char* newpath = NULL;
FT_Memory memory;
FT_Long base_file_len = (FT_Long)ft_strlen( base_file_name );
FT_UNUSED( stream );
memory = library->memory;
if ( base_file_len + 6 > FT_INT_MAX )
return FT_THROW( Array_Too_Large );
if ( FT_QALLOC( newpath, base_file_len + 6 ) )
return error;
FT_MEM_COPY( newpath, base_file_name, base_file_len );
FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_darwin_newvfs( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
FT_Error error;
char* newpath = NULL;
FT_Memory memory;
FT_Long base_file_len = (FT_Long)ft_strlen( base_file_name );
FT_UNUSED( stream );
memory = library->memory;
if ( base_file_len + 18 > FT_INT_MAX )
return FT_THROW( Array_Too_Large );
if ( FT_QALLOC( newpath, base_file_len + 18 ) )
return error;
FT_MEM_COPY( newpath, base_file_name, base_file_len );
FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_vfat( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name,
"resource.frk/" );
if ( !newpath )
return FT_THROW( Out_Of_Memory );
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_linux_cap( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
if ( !newpath )
return FT_THROW( Out_Of_Memory );
*result_file_name = newpath;
*result_offset = 0;
return FT_Err_Ok;
}
static FT_Error
raccess_guess_linux_double( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Error error;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name, "%" );
if ( !newpath )
return FT_THROW( Out_Of_Memory );
error = raccess_guess_linux_double_from_file_name( library, newpath,
result_offset );
if ( !error )
*result_file_name = newpath;
else
FT_FREE( newpath );
return error;
}
static FT_Error
raccess_guess_linux_netatalk( FT_Library library,
FT_Stream stream,
char *base_file_name,
char **result_file_name,
FT_Long *result_offset )
{
char* newpath;
FT_Error error;
FT_Memory memory;
FT_UNUSED( stream );
memory = library->memory;
newpath = raccess_make_file_name( memory, base_file_name,
".AppleDouble/" );
if ( !newpath )
return FT_THROW( Out_Of_Memory );
error = raccess_guess_linux_double_from_file_name( library, newpath,
result_offset );
if ( !error )
*result_file_name = newpath;
else
FT_FREE( newpath );
return error;
}
static FT_Error
raccess_guess_apple_generic( FT_Library library,
FT_Stream stream,
char *base_file_name,
FT_Int32 magic,
FT_Long *result_offset )
{
FT_Int32 magic_from_stream;
FT_Error error;
FT_Int32 version_number = 0;
FT_UShort n_of_entries;
int i;
FT_Int32 entry_id, entry_offset, entry_length = 0;
const FT_Int32 resource_fork_entry_id = 0x2;
FT_UNUSED( library );
FT_UNUSED( base_file_name );
FT_UNUSED( version_number );
FT_UNUSED( entry_length );
if ( FT_READ_LONG( magic_from_stream ) )
return error;
if ( magic_from_stream != magic )
return FT_THROW( Unknown_File_Format );
if ( FT_READ_LONG( version_number ) )
return error;
error = FT_Stream_Skip( stream, 16 );
if ( error )
return error;
if ( FT_READ_USHORT( n_of_entries ) )
return error;
if ( n_of_entries == 0 )
return FT_THROW( Unknown_File_Format );
for ( i = 0; i < n_of_entries; i++ )
{
if ( FT_READ_LONG( entry_id ) )
return error;
if ( entry_id == resource_fork_entry_id )
{
if ( FT_READ_LONG( entry_offset ) ||
FT_READ_LONG( entry_length ) )
continue;
*result_offset = entry_offset;
return FT_Err_Ok;
}
else
{
error = FT_Stream_Skip( stream, 4 + 4 );
if ( error )
return error;
}
}
return FT_THROW( Unknown_File_Format );
}
static FT_Error
raccess_guess_linux_double_from_file_name( FT_Library library,
char *file_name,
FT_Long *result_offset )
{
FT_Open_Args args2;
FT_Stream stream2;
char* nouse = NULL;
FT_Error error;
args2.flags = FT_OPEN_PATHNAME;
args2.pathname = file_name;
error = FT_Stream_New( library, &args2, &stream2 );
if ( error )
return error;
error = raccess_guess_apple_double( library, stream2, file_name,
&nouse, result_offset );
FT_Stream_Free( stream2, 0 );
return error;
}
static char*
raccess_make_file_name( FT_Memory memory,
const char *original_name,
const char *insertion )
{
char* new_name = NULL;
const char* tmp;
const char* slash;
size_t new_length;
FT_Error error;
new_length = ft_strlen( original_name ) + ft_strlen( insertion );
if ( FT_QALLOC( new_name, new_length + 1 ) )
return NULL;
tmp = ft_strrchr( original_name, '/' );
if ( tmp )
{
ft_strncpy( new_name,
original_name,
(size_t)( tmp - original_name + 1 ) );
new_name[tmp - original_name + 1] = '\0';
slash = tmp + 1;
}
else
{
slash = original_name;
new_name[0] = '\0';
}
ft_strcat( new_name, insertion );
ft_strcat( new_name, slash );
return new_name;
}
#else
FT_BASE_DEF( void )
FT_Raccess_Guess( FT_Library library,
FT_Stream stream,
char *base_name,
char **new_names,
FT_Long *offsets,
FT_Error *errors )
{ … }
#endif