diff options
Diffstat (limited to 'fontconfig/src/ftglue.c')
-rw-r--r-- | fontconfig/src/ftglue.c | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/fontconfig/src/ftglue.c b/fontconfig/src/ftglue.c new file mode 100644 index 000000000..1eca304cf --- /dev/null +++ b/fontconfig/src/ftglue.c @@ -0,0 +1,261 @@ +/* ftglue.c: Glue code for compiling the OpenType code from + * FreeType 1 using only the public API of FreeType 2 + * + * By David Turner, The FreeType Project (www.freetype.org) + * + * This code is explicitely put in the public domain + * + * See ftglue.h for more information. + */ + +#include "ftglue.h" + +#if 0 +#include <stdio.h> +#define LOG(x) ftglue_log x + +static void +ftglue_log( const char* format, ... ) +{ + va_list ap; + + va_start( ap, format ); + vfprintf( stderr, format, ap ); + va_end( ap ); +} + +#else +#define LOG(x) do {} while (0) +#endif + +/* only used internally */ +static FT_Pointer +ftglue_qalloc( FT_Memory memory, + FT_ULong size, + FT_Error *perror ) +{ + FT_Error error = 0; + FT_Pointer block = NULL; + + if ( size > 0 ) + { + block = memory->alloc( memory, size ); + if ( !block ) + error = FT_Err_Out_Of_Memory; + } + + *perror = error; + return block; +} + +#undef QALLOC /* just in case */ +#define QALLOC(ptr,size) ( (ptr) = ftglue_qalloc( memory, (size), &error ), error != 0 ) +#define FREE(_ptr) \ + do { \ + if ( (_ptr) ) \ + { \ + ftglue_free( memory, _ptr ); \ + _ptr = NULL; \ + } \ + } while (0) + + +static void +ftglue_free( FT_Memory memory, + FT_Pointer block ) +{ + if ( block ) + memory->free( memory, block ); +} + +FTGLUE_APIDEF( FT_Long ) +ftglue_stream_pos( FT_Stream stream ) +{ + LOG(( "ftglue:stream:pos() -> %ld\n", stream->pos )); + return stream->pos; +} + + +FTGLUE_APIDEF( FT_Error ) +ftglue_stream_seek( FT_Stream stream, + FT_Long pos ) +{ + FT_Error error = 0; + + stream->pos = pos; + if ( stream->read ) + { + if ( stream->read( stream, pos, 0, 0 ) ) + error = FT_Err_Invalid_Stream_Operation; + } + else if ( pos > stream->size ) + error = FT_Err_Invalid_Stream_Operation; + + LOG(( "ftglue:stream:seek(%ld) -> %d\n", pos, error )); + return error; +} + + +FTGLUE_APIDEF( FT_Error ) +ftglue_stream_frame_enter( FT_Stream stream, + FT_ULong count ) +{ + FT_Error error = FT_Err_Ok; + FT_ULong read_bytes; + + if ( stream->read ) + { + /* allocate the frame in memory */ + FT_Memory memory = stream->memory; + + + if ( QALLOC( stream->base, count ) ) + goto Exit; + + /* read it */ + read_bytes = stream->read( stream, stream->pos, + stream->base, count ); + if ( read_bytes < count ) + { + FREE( stream->base ); + error = FT_Err_Invalid_Stream_Operation; + } + stream->cursor = stream->base; + stream->limit = stream->cursor + count; + stream->pos += read_bytes; + } + else + { + /* check current and new position */ + if ( stream->pos >= stream->size || + stream->pos + count > stream->size ) + { + error = FT_Err_Invalid_Stream_Operation; + goto Exit; + } + + /* set cursor */ + stream->cursor = stream->base + stream->pos; + stream->limit = stream->cursor + count; + stream->pos += count; + } + +Exit: + LOG(( "ftglue:stream:frame_enter(%ld) -> %d\n", count, error )); + return error; +} + + +FTGLUE_APIDEF( void ) +ftglue_stream_frame_exit( FT_Stream stream ) +{ + if ( stream->read ) + { + FT_Memory memory = stream->memory; + + FREE( stream->base ); + } + stream->cursor = 0; + stream->limit = 0; + + LOG(( "ftglue:stream:frame_exit()\n" )); +} + + +FTGLUE_APIDEF( FT_Error ) +ftglue_face_goto_table( FT_Face face, + FT_ULong the_tag, + FT_Stream stream ) +{ + FT_Error error; + + LOG(( "ftglue_face_goto_table( %p, %c%c%c%c, %p )\n", + face, + (int)((the_tag >> 24) & 0xFF), + (int)((the_tag >> 16) & 0xFF), + (int)((the_tag >> 8) & 0xFF), + (int)(the_tag & 0xFF), + stream )); + + if ( !FT_IS_SFNT(face) ) + { + LOG(( "not a SFNT face !!\n" )); + error = FT_Err_Invalid_Face_Handle; + } + else + { + /* parse the directory table directly, without using + * FreeType's built-in data structures + */ + FT_ULong offset = 0, sig; + FT_UInt count, nn; + + if ( FILE_Seek( 0 ) || ACCESS_Frame( 4 ) ) + goto Exit; + + sig = GET_Tag4(); + + FORGET_Frame(); + + if ( sig == FT_MAKE_TAG( 't', 't', 'c', 'f' ) ) + { + /* deal with TrueType collections */ + + LOG(( ">> This is a TrueType Collection\n" )); + + if ( FILE_Seek( 12 + face->face_index*4 ) || + ACCESS_Frame( 4 ) ) + goto Exit; + + offset = GET_ULong(); + + FORGET_Frame(); + } + + LOG(( "TrueType offset = %ld\n", offset )); + + if ( FILE_Seek( offset+4 ) || + ACCESS_Frame( 2 ) ) + goto Exit; + + count = GET_UShort(); + + FORGET_Frame(); + + if ( FILE_Seek( offset+12 ) || + ACCESS_Frame( count*16 ) ) + goto Exit; + + for ( nn = 0; nn < count; nn++ ) + { + FT_ULong tag = GET_ULong(); + FT_ULong checksum = GET_ULong(); + FT_ULong start = GET_ULong(); + FT_ULong size = GET_ULong(); + + FT_UNUSED(checksum); + FT_UNUSED(size); + + if ( tag == the_tag ) + { + LOG(( "TrueType table (start: %ld) (size: %ld)\n", start, size )); + error = ftglue_stream_seek( stream, start ); + goto FoundIt; + } + } + error = FT_Err_Table_Missing; + + FoundIt: + FORGET_Frame(); + } + +Exit: + LOG(( "TrueType error=%d\n", error )); + + return error; +} + +#undef QALLOC +#define __ftglue__ +#include "fcaliastail.h" +#undef __ftglue__ |