CID_New_Parser( CID_Parser* parser, FT_Stream stream, FT_Memory memory, PSAux_Service psaux ) { FT_Error error; FT_ULong base_offset, offset, ps_len; FT_Byte buffer[256 + 10]; FT_Int buff_len; FT_MEM_SET( parser, 0, sizeof ( *parser ) ); psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); parser->stream = stream; base_offset = FT_STREAM_POS(); /* first of all, check the font format in the header */ if ( FT_FRAME_ENTER( 31 ) ) goto Exit; if ( ft_strncmp( (char *)stream->cursor, "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) ) { FT_TRACE2(( "[not a valid CID-keyed font]\n" )); error = CID_Err_Unknown_File_Format; } FT_FRAME_EXIT(); if ( error ) goto Exit; /* now, read the rest of the file, until we find a `StartData' */ buff_len = 256; for (;;) { FT_Byte *p, *limit = buffer + 256; FT_ULong top_position; /* fill input buffer */ buff_len -= 256; if ( buff_len > 0 ) FT_MEM_MOVE( buffer, limit, buff_len ); p = buffer + buff_len; if ( FT_STREAM_READ( p, 256 + 10 - buff_len ) ) goto Exit; top_position = FT_STREAM_POS() - buff_len; buff_len = 256 + 10; /* look for `StartData' */ for ( p = buffer; p < limit; p++ ) { if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 ) { /* save offset of binary data after `StartData' */ offset = (FT_ULong)( top_position - ( limit - p ) + 10 ); goto Found; } } } Found: /* we have found the start of the binary data. We will now */ /* rewind and extract the frame of corresponding to the Postscript */ /* section */ ps_len = offset - base_offset; if ( FT_STREAM_SEEK( base_offset ) || FT_FRAME_EXTRACT( ps_len, parser->postscript ) ) goto Exit; parser->data_offset = offset; parser->postscript_len = ps_len; parser->root.base = parser->postscript; parser->root.cursor = parser->postscript; parser->root.limit = parser->root.cursor + ps_len; parser->num_dict = -1; Exit: return error; }
tt_face_load_kern( TT_Face face, FT_Stream stream ) { FT_Error error; FT_ULong table_size; FT_Byte* p; FT_Byte* p_limit; FT_UInt nn, num_tables; FT_UInt32 avail = 0, ordered = 0; /* the kern table is optional; exit silently if it is missing */ error = face->goto_table( face, TTAG_kern, stream, &table_size ); if ( error ) goto Exit; if ( table_size < 4 ) /* the case of a malformed table */ { FT_ERROR( ( "kerning table is too small - ignored\n" ) ); error = SFNT_Err_Table_Missing; goto Exit; } if ( FT_FRAME_EXTRACT( table_size, face->kern_table ) ) { FT_ERROR( ( "could not extract kerning table\n" ) ); goto Exit; } face->kern_table_size = table_size; p = face->kern_table; p_limit = p + table_size; p += 2; /* skip version */ num_tables = FT_NEXT_USHORT( p ); if ( num_tables > 32 ) /* we only support up to 32 sub-tables */ num_tables = 32; for ( nn = 0; nn < num_tables; nn++ ) { FT_UInt num_pairs, length, coverage; FT_Byte* p_next; FT_UInt32 mask = 1UL << nn; if ( p + 6 > p_limit ) break; p_next = p; p += 2; /* skip version */ length = FT_NEXT_USHORT( p ); coverage = FT_NEXT_USHORT( p ); if ( length <= 6 ) break; p_next += length; if ( p_next > p_limit ) /* handle broken table */ p_next = p_limit; /* only use horizontal kerning tables */ if ( ( coverage & ~8 ) != 0x0001 || p + 8 > p_limit ) goto NextTable; num_pairs = FT_NEXT_USHORT( p ); p += 6; if ( ( p_next - p ) / 6 < ( int )num_pairs ) /* handle broken count */ num_pairs = ( FT_UInt )( ( p_next - p ) / 6 ); avail |= mask; /* * Now check whether the pairs in this table are ordered. * We then can use binary search. */ if ( num_pairs > 0 ) { FT_UInt count; FT_UInt old_pair; old_pair = FT_NEXT_ULONG( p ); p += 2; for ( count = num_pairs - 1; count > 0; count-- ) { FT_UInt32 cur_pair; cur_pair = FT_NEXT_ULONG( p ); if ( cur_pair <= old_pair ) break; p += 2; old_pair = cur_pair; } if ( count == 0 ) ordered |= mask; } NextTable: p = p_next; } face->num_kern_tables = nn; face->kern_avail_bits = avail; face->kern_order_bits = ordered; Exit: return error; }
cid_parser_new( CID_Parser* parser, FT_Stream stream, FT_Memory memory, PSAux_Service psaux ) { FT_Error error; FT_ULong base_offset, offset, ps_len; FT_Byte buffer[256 + 10]; FT_Int buff_len; FT_Byte *cur, *limit; FT_Byte *arg1, *arg2; FT_MEM_ZERO( parser, sizeof ( *parser ) ); psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); parser->stream = stream; base_offset = FT_STREAM_POS(); /* first of all, check the font format in the header */ if ( FT_FRAME_ENTER( 31 ) ) goto Exit; if ( ft_strncmp( (char *)stream->cursor, "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) ) { FT_TRACE2(( "[not a valid CID-keyed font]\n" )); error = CID_Err_Unknown_File_Format; } FT_FRAME_EXIT(); if ( error ) goto Exit; Again: /* now, read the rest of the file until we find a `StartData' */ buff_len = 256; for (;;) { FT_Byte* p; FT_ULong top_position; /* fill input buffer */ limit = buffer + 256; buff_len -= 256; if ( buff_len > 0 ) FT_MEM_MOVE( buffer, limit, buff_len ); p = buffer + buff_len; if ( FT_STREAM_READ( p, 256 + 10 - buff_len ) ) goto Exit; top_position = FT_STREAM_POS() - buff_len; buff_len = 256 + 10; /* look for `StartData' */ for ( p = buffer; p < limit; p++ ) { if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 ) { /* save offset of binary data after `StartData' */ offset = (FT_ULong)( top_position - ( limit - p ) + 10 ); goto Found; } } } Found: /* we have found the start of the binary data. We will now */ /* rewind and extract the frame corresponding to the PostScript */ /* section */ ps_len = offset - base_offset; if ( FT_STREAM_SEEK( base_offset ) || FT_FRAME_EXTRACT( ps_len, parser->postscript ) ) goto Exit; parser->data_offset = offset; parser->postscript_len = ps_len; parser->root.base = parser->postscript; parser->root.cursor = parser->postscript; parser->root.limit = parser->root.cursor + ps_len; parser->num_dict = -1; /* Finally, we check whether `StartData' was real -- it could be */ /* in a comment or string. We also get its arguments to find out */ /* whether the data is represented in binary or hex format. */ arg1 = parser->root.cursor; cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); arg2 = parser->root.cursor; cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); limit = parser->root.limit; cur = parser->root.cursor; while ( cur < limit ) { if ( parser->root.error ) break; if ( *cur == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 ) { if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 ) parser->binary_length = ft_atol( (const char *)arg2 ); limit = parser->root.limit; cur = parser->root.cursor; goto Exit; } cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); arg1 = arg2; arg2 = cur; cur = parser->root.cursor; } /* we haven't found the correct `StartData'; go back and continue */ /* searching */ FT_FRAME_RELEASE( parser->postscript ); if ( !FT_STREAM_SEEK( offset ) ) goto Again; Exit: return error; }
cid_parser_new( CID_Parser* parser, FT_Stream stream, FT_Memory memory, PSAux_Service psaux ) { FT_Error error; FT_ULong base_offset, offset, ps_len; FT_Byte *cur, *limit; FT_Byte *arg1, *arg2; FT_MEM_ZERO( parser, sizeof ( *parser ) ); psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); parser->stream = stream; base_offset = FT_STREAM_POS(); /* first of all, check the font format in the header */ if ( FT_FRAME_ENTER( 31 ) ) goto Exit; if ( ft_strncmp( (char *)stream->cursor, "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) ) { FT_TRACE2(( " not a CID-keyed font\n" )); error = FT_THROW( Unknown_File_Format ); } FT_FRAME_EXIT(); if ( error ) goto Exit; Again: /* now, read the rest of the file until we find */ /* `StartData' or `/sfnts' */ { FT_Byte buffer[256 + 10]; FT_ULong read_len = 256 + 10; FT_Byte* p = buffer; for ( offset = FT_STREAM_POS(); ; offset += 256 ) { FT_ULong stream_len; stream_len = stream->size - FT_STREAM_POS(); if ( stream_len == 0 ) { FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } read_len = FT_MIN( read_len, stream_len ); if ( FT_STREAM_READ( p, read_len ) ) goto Exit; if ( read_len < 256 ) p[read_len] = '\0'; limit = p + read_len - 10; for ( p = buffer; p < limit; p++ ) { if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 ) { /* save offset of binary data after `StartData' */ offset += (FT_ULong)( p - buffer + 10 ); goto Found; } else if ( p[1] == 's' && ft_strncmp( (char*)p, "/sfnts", 6 ) == 0 ) { offset += (FT_ULong)( p - buffer + 7 ); goto Found; } } FT_MEM_MOVE( buffer, p, 10 ); read_len = 256; p = buffer + 10; } } Found: /* We have found the start of the binary data or the `/sfnts' token. */ /* Now rewind and extract the frame corresponding to this PostScript */ /* section. */ ps_len = offset - base_offset; if ( FT_STREAM_SEEK( base_offset ) || FT_FRAME_EXTRACT( ps_len, parser->postscript ) ) goto Exit; parser->data_offset = offset; parser->postscript_len = ps_len; parser->root.base = parser->postscript; parser->root.cursor = parser->postscript; parser->root.limit = parser->root.cursor + ps_len; parser->num_dict = -1; /* Finally, we check whether `StartData' or `/sfnts' was real -- */ /* it could be in a comment or string. We also get the arguments */ /* of `StartData' to find out whether the data is represented in */ /* binary or hex format. */ arg1 = parser->root.cursor; cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); arg2 = parser->root.cursor; cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); limit = parser->root.limit; cur = parser->root.cursor; while ( cur < limit ) { if ( parser->root.error ) { error = parser->root.error; goto Exit; } if ( cur[0] == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 ) { if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 ) { FT_Long tmp = ft_atol( (const char *)arg2 ); if ( tmp < 0 ) { FT_ERROR(( "cid_parser_new: invalid length of hex data\n" )); error = FT_THROW( Invalid_File_Format ); } else parser->binary_length = (FT_ULong)tmp; } goto Exit; } else if ( cur[1] == 's' && ft_strncmp( (char*)cur, "/sfnts", 6 ) == 0 ) { FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" )); error = FT_THROW( Unknown_File_Format ); goto Exit; } cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); arg1 = arg2; arg2 = cur; cur = parser->root.cursor; } /* we haven't found the correct `StartData'; go back and continue */ /* searching */ FT_FRAME_RELEASE( parser->postscript ); if ( !FT_STREAM_SEEK( offset ) ) goto Again; Exit: return error; }
static FT_Error tt_face_load_bdf_props( TT_Face face, FT_Stream stream ) { TT_BDF bdf = &face->bdf; FT_ULong length; FT_Error error; FT_ZERO( bdf ); error = tt_face_goto_table( face, TTAG_BDF, stream, &length ); if ( error || length < 8 || FT_FRAME_EXTRACT( length, bdf->table ) ) { error = FT_THROW( Invalid_Table ); goto Exit; } bdf->table_end = bdf->table + length; { FT_Byte* p = bdf->table; FT_UInt version = FT_NEXT_USHORT( p ); FT_UInt num_strikes = FT_NEXT_USHORT( p ); FT_ULong strings = FT_NEXT_ULONG ( p ); FT_UInt count; FT_Byte* strike; if ( version != 0x0001 || strings < 8 || ( strings - 8 ) / 4 < num_strikes || strings + 1 > length ) { goto BadTable; } bdf->num_strikes = num_strikes; bdf->strings = bdf->table + strings; bdf->strings_size = length - strings; count = bdf->num_strikes; p = bdf->table + 8; strike = p + count * 4; for ( ; count > 0; count-- ) { FT_UInt num_items = FT_PEEK_USHORT( p + 2 ); /* * We don't need to check the value sets themselves, since this * is done later. */ strike += 10 * num_items; p += 4; } if ( strike > bdf->strings ) goto BadTable; } bdf->loaded = 1; Exit: return error; BadTable: FT_FRAME_RELEASE( bdf->table ); FT_ZERO( bdf ); error = FT_THROW( Invalid_Table ); goto Exit; }
static FT_Error cff_index_init( CFF_Index idx, FT_Stream stream, FT_Bool load ) { FT_Error error; FT_Memory memory = stream->memory; FT_UShort count; FT_MEM_ZERO( idx, sizeof ( *idx ) ); idx->stream = stream; idx->start = FT_STREAM_POS(); if ( !FT_READ_USHORT( count ) && count > 0 ) { FT_Byte offsize; FT_ULong size; /* there is at least one element; read the offset size, */ /* then access the offset table to compute the index's total size */ if ( FT_READ_BYTE( offsize ) ) goto Exit; if ( offsize < 1 || offsize > 4 ) { error = FT_THROW( Invalid_Table ); goto Exit; } idx->count = count; idx->off_size = offsize; size = (FT_ULong)( count + 1 ) * offsize; idx->data_offset = idx->start + 3 + size; if ( FT_STREAM_SKIP( size - offsize ) ) goto Exit; size = cff_index_read_offset( idx, &error ); if ( error ) goto Exit; if ( size == 0 ) { error = FT_THROW( Invalid_Table ); goto Exit; } idx->data_size = --size; if ( load ) { /* load the data */ if ( FT_FRAME_EXTRACT( size, idx->bytes ) ) goto Exit; } else { /* skip the data */ if ( FT_STREAM_SKIP( size ) ) goto Exit; } } Exit: if ( error ) FT_FREE( idx->offsets ); return error; }
cff_index_access_element( CFF_Index idx, FT_UInt element, FT_Byte** pbytes, FT_ULong* pbyte_len ) { FT_Error error = FT_Err_Ok; if ( idx && idx->count > element ) { /* compute start and end offsets */ FT_Stream stream = idx->stream; FT_ULong off1, off2 = 0; /* load offsets from file or the offset table */ if ( !idx->offsets ) { FT_ULong pos = element * idx->off_size; if ( FT_STREAM_SEEK( idx->start + 3 + pos ) ) goto Exit; off1 = cff_index_read_offset( idx, &error ); if ( error ) goto Exit; if ( off1 != 0 ) { do { element++; off2 = cff_index_read_offset( idx, &error ); } while ( off2 == 0 && element < idx->count ); } } else /* use offsets table */ { off1 = idx->offsets[element]; if ( off1 ) { do { element++; off2 = idx->offsets[element]; } while ( off2 == 0 && element < idx->count ); } } /* XXX: should check off2 does not exceed the end of this entry; */ /* at present, only truncate off2 at the end of this stream */ if ( off2 > stream->size + 1 || idx->data_offset > stream->size - off2 + 1 ) { FT_ERROR(( "cff_index_access_element:" " offset to next entry (%d)" " exceeds the end of stream (%d)\n", off2, stream->size - idx->data_offset + 1 )); off2 = stream->size - idx->data_offset + 1; } /* access element */ if ( off1 && off2 > off1 ) { *pbyte_len = off2 - off1; if ( idx->bytes ) { /* this index was completely loaded in memory, that's easy */ *pbytes = idx->bytes + off1 - 1; } else { /* this index is still on disk/file, access it through a frame */ if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) || FT_FRAME_EXTRACT( off2 - off1, *pbytes ) ) goto Exit; } } else { /* empty index element */ *pbytes = 0; *pbyte_len = 0; } } else error = FT_THROW( Invalid_Argument ); Exit: return error; }
cff_index_access_element( CFF_Index idx, FT_UInt element, FT_Byte** pbytes, FT_ULong* pbyte_len ) { FT_Error error = CFF_Err_Ok; if ( idx && idx->count > element ) { /* compute start and end offsets */ FT_Stream stream = idx->stream; FT_ULong off1, off2 = 0; /* load offsets from file or the offset table */ if ( !idx->offsets ) { FT_ULong pos = element * idx->off_size; if ( FT_STREAM_SEEK( idx->start + 3 + pos ) ) goto Exit; off1 = cff_index_read_offset( idx, &error ); if ( error ) goto Exit; if ( off1 != 0 ) { do { element++; off2 = cff_index_read_offset( idx, &error ); } while ( off2 == 0 && element < idx->count ); } } else /* use offsets table */ { off1 = idx->offsets[element]; if ( off1 ) { do { element++; off2 = idx->offsets[element]; } while ( off2 == 0 && element < idx->count ); } } /* access element */ if ( off1 && off2 > off1 ) { *pbyte_len = off2 - off1; if ( idx->bytes ) { /* this index was completely loaded in memory, that's easy */ *pbytes = idx->bytes + off1 - 1; } else { /* this index is still on disk/file, access it through a frame */ if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) || FT_FRAME_EXTRACT( off2 - off1, *pbytes ) ) goto Exit; } } else { /* empty index element */ *pbytes = 0; *pbyte_len = 0; } } else error = CFF_Err_Invalid_Argument; Exit: return error; }
static FT_Error cff_new_index( CFF_Index idx, FT_Stream stream, FT_Bool load ) { FT_Error error; FT_Memory memory = stream->memory; FT_UShort count; FT_MEM_ZERO( idx, sizeof ( *idx ) ); idx->stream = stream; if ( !FT_READ_USHORT( count ) && count > 0 ) { FT_Byte* p; FT_Byte offsize; FT_ULong data_size; FT_ULong* poff; /* there is at least one element; read the offset size, */ /* then access the offset table to compute the index's total size */ if ( FT_READ_BYTE( offsize ) ) goto Exit; idx->stream = stream; idx->count = count; idx->off_size = offsize; data_size = (FT_ULong)( count + 1 ) * offsize; if ( FT_NEW_ARRAY( idx->offsets, count + 1 ) || FT_FRAME_ENTER( data_size ) ) goto Exit; poff = idx->offsets; p = (FT_Byte*)stream->cursor; for ( ; (FT_Short)count >= 0; count-- ) { poff[0] = cff_get_offset( p, offsize ); poff++; p += offsize; } FT_FRAME_EXIT(); idx->data_offset = FT_STREAM_POS(); data_size = poff[-1] - 1; if ( load ) { /* load the data */ if ( FT_FRAME_EXTRACT( data_size, idx->bytes ) ) goto Exit; } else { /* skip the data */ if ( FT_STREAM_SKIP( data_size ) ) goto Exit; } } Exit: if ( error ) FT_FREE( idx->offsets ); return error; }
cff_index_access_element( CFF_Index idx, FT_UInt element, FT_Byte** pbytes, FT_ULong* pbyte_len ) { FT_Error error = 0; if ( idx && idx->count > element ) { /* compute start and end offsets */ FT_ULong off1, off2 = 0; off1 = idx->offsets[element]; if ( off1 ) { do { element++; off2 = idx->offsets[element]; } while ( off2 == 0 && element < idx->count ); if ( !off2 ) off1 = 0; } /* access element */ if ( off1 ) { *pbyte_len = off2 - off1; if ( idx->bytes ) { /* this index was completely loaded in memory, that's easy */ *pbytes = idx->bytes + off1 - 1; } else { /* this index is still on disk/file, access it through a frame */ FT_Stream stream = idx->stream; if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) || FT_FRAME_EXTRACT( off2 - off1, *pbytes ) ) goto Exit; } } else { /* empty index element */ *pbytes = 0; *pbyte_len = 0; } } else error = CFF_Err_Invalid_Argument; Exit: return error; }
tt_face_load_colr( TT_Face face, FT_Stream stream ) { FT_Error error; FT_Memory memory = face->root.memory; FT_Byte* table = NULL; FT_Byte* p = NULL; Colr* colr = NULL; FT_ULong base_glyph_offset, layer_offset; FT_ULong table_size; /* `COLR' always needs `CPAL' */ if ( !face->cpal ) return FT_THROW( Invalid_File_Format ); error = face->goto_table( face, TTAG_COLR, stream, &table_size ); if ( error ) goto NoColr; if ( table_size < COLR_HEADER_SIZE ) goto InvalidTable; if ( FT_FRAME_EXTRACT( table_size, table ) ) goto NoColr; p = table; if ( FT_NEW( colr ) ) goto NoColr; colr->version = FT_NEXT_USHORT( p ); if ( colr->version != 0 ) goto InvalidTable; colr->num_base_glyphs = FT_NEXT_USHORT( p ); base_glyph_offset = FT_NEXT_ULONG( p ); if ( base_glyph_offset >= table_size ) goto InvalidTable; if ( colr->num_base_glyphs * BASE_GLYPH_SIZE > table_size - base_glyph_offset ) goto InvalidTable; layer_offset = FT_NEXT_ULONG( p ); colr->num_layers = FT_NEXT_USHORT( p ); if ( layer_offset >= table_size ) goto InvalidTable; if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset ) goto InvalidTable; colr->base_glyphs = (FT_Byte*)( table + base_glyph_offset ); colr->layers = (FT_Byte*)( table + layer_offset ); colr->table = table; colr->table_size = table_size; face->colr = colr; return FT_Err_Ok; InvalidTable: error = FT_THROW( Invalid_Table ); NoColr: FT_FRAME_RELEASE( table ); FT_FREE( colr ); return error; }
cid_parser_new( CID_Parser* parser, FT_Stream stream, FT_Memory memory, PSAux_Service psaux ) { FT_Error error; FT_ULong base_offset, offset, ps_len; FT_Byte *cur, *limit; FT_Byte *arg1, *arg2; FT_ZERO( parser ); psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); parser->stream = stream; base_offset = FT_STREAM_POS(); /* first of all, check the font format in the header */ if ( FT_FRAME_ENTER( 31 ) ) goto Exit; if ( ft_strncmp( (char *)stream->cursor, "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) ) { FT_TRACE2(( " not a CID-keyed font\n" )); error = FT_THROW( Unknown_File_Format ); } FT_FRAME_EXIT(); if ( error ) goto Exit; Again: /* now, read the rest of the file until we find */ /* `StartData' or `/sfnts' */ { /* * The algorithm is as follows (omitting the case with less than 256 * bytes to fill for simplicity). * * 1. Fill the buffer with 256 + STARTDATA_LEN bytes. * * 2. Search for the STARTDATA and SFNTS strings at positions * buffer[0], buffer[1], ..., * buffer[255 + STARTDATA_LEN - SFNTS_LEN]. * * 3. Move the last STARTDATA_LEN bytes to buffer[0]. * * 4. Fill the buffer with 256 bytes, starting at STARTDATA_LEN. * * 5. Repeat with step 2. * */ FT_Byte buffer[256 + STARTDATA_LEN + 1]; /* values for the first loop */ FT_ULong read_len = 256 + STARTDATA_LEN; FT_ULong read_offset = 0; FT_Byte* p = buffer; for ( offset = FT_STREAM_POS(); ; offset += 256 ) { FT_ULong stream_len; stream_len = stream->size - FT_STREAM_POS(); read_len = FT_MIN( read_len, stream_len ); if ( FT_STREAM_READ( p, read_len ) ) goto Exit; /* ensure that we do not compare with data beyond the buffer */ p[read_len] = '\0'; limit = p + read_len - SFNTS_LEN; for ( p = buffer; p < limit; p++ ) { if ( p[0] == 'S' && ft_strncmp( (char*)p, STARTDATA, STARTDATA_LEN ) == 0 ) { /* save offset of binary data after `StartData' */ offset += (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1; goto Found; } else if ( p[1] == 's' && ft_strncmp( (char*)p, SFNTS, SFNTS_LEN ) == 0 ) { offset += (FT_ULong)( p - buffer ) + SFNTS_LEN + 1; goto Found; } } if ( read_offset + read_len < STARTDATA_LEN ) { FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } FT_MEM_MOVE( buffer, buffer + read_offset + read_len - STARTDATA_LEN, STARTDATA_LEN ); /* values for the next loop */ read_len = 256; read_offset = STARTDATA_LEN; p = buffer + read_offset; } } Found: /* We have found the start of the binary data or the `/sfnts' token. */ /* Now rewind and extract the frame corresponding to this PostScript */ /* section. */ ps_len = offset - base_offset; if ( FT_STREAM_SEEK( base_offset ) || FT_FRAME_EXTRACT( ps_len, parser->postscript ) ) goto Exit; parser->data_offset = offset; parser->postscript_len = ps_len; parser->root.base = parser->postscript; parser->root.cursor = parser->postscript; parser->root.limit = parser->root.cursor + ps_len; parser->num_dict = -1; /* Finally, we check whether `StartData' or `/sfnts' was real -- */ /* it could be in a comment or string. We also get the arguments */ /* of `StartData' to find out whether the data is represented in */ /* binary or hex format. */ arg1 = parser->root.cursor; cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); arg2 = parser->root.cursor; cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); limit = parser->root.limit; cur = parser->root.cursor; while ( cur <= limit - SFNTS_LEN ) { if ( parser->root.error ) { error = parser->root.error; goto Exit; } if ( cur[0] == 'S' && cur <= limit - STARTDATA_LEN && ft_strncmp( (char*)cur, STARTDATA, STARTDATA_LEN ) == 0 ) { if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 ) { FT_Long tmp = ft_strtol( (const char *)arg2, NULL, 10 ); if ( tmp < 0 ) { FT_ERROR(( "cid_parser_new: invalid length of hex data\n" )); error = FT_THROW( Invalid_File_Format ); } else parser->binary_length = (FT_ULong)tmp; } goto Exit; } else if ( cur[1] == 's' && ft_strncmp( (char*)cur, SFNTS, SFNTS_LEN ) == 0 ) { FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" )); error = FT_THROW( Unknown_File_Format ); goto Exit; } cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); arg1 = arg2; arg2 = cur; cur = parser->root.cursor; } /* we haven't found the correct `StartData'; go back and continue */ /* searching */ FT_FRAME_RELEASE( parser->postscript ); if ( !FT_STREAM_SEEK( offset ) ) goto Again; Exit: return error; }