static FT_Error ftc_sbit_copy_bitmap( FTC_SBit sbit, FT_Bitmap* bitmap, FT_Memory memory ) { FT_Error error; FT_Int pitch = bitmap->pitch; FT_ULong size; if ( pitch < 0 ) pitch = -pitch; size = (FT_ULong)( pitch * bitmap->rows ); if ( !FT_ALLOC( sbit->buffer, size ) ) FT_MEM_COPY( sbit->buffer, bitmap->buffer, size ); return error; }
/* * Load a name from the auxiliary data. Since this extracts undocumented * strings from the font file, we need to be careful here. */ static FT_Error pfr_aux_name_load( FT_Byte* p, FT_UInt len, FT_Memory memory, FT_String* *astring ) { FT_Error error = FT_Err_Ok; FT_String* result = NULL; FT_UInt n, ok; if ( *astring ) FT_FREE( *astring ); if ( len > 0 && p[len - 1] == 0 ) len--; /* check that each character is ASCII */ /* for making sure not to load garbage */ ok = ( len > 0 ); for ( n = 0; n < len; n++ ) if ( p[n] < 32 || p[n] > 127 ) { ok = 0; break; } if ( ok ) { if ( FT_ALLOC( result, len + 1 ) ) goto Exit; FT_MEM_COPY( result, p, len ); result[len] = 0; } Exit: *astring = result; return error; }
FT_Error autofit_module_class_pic_init( FT_Library library ) { FT_PIC_Container* pic_container = &library->pic_container; FT_UInt ss; FT_Error error = AF_Err_Ok; AFModulePIC* container; FT_Memory memory = library->memory; /* allocate pointer, clear and set global container pointer */ if ( FT_ALLOC ( container, sizeof ( *container ) ) ) return error; FT_MEM_SET( container, 0, sizeof ( *container ) ); pic_container->autofit = container; /* initialize pointer table - this is how the module usually expects this data */ for ( ss = 0 ; ss < AF_SCRIPT_CLASSES_REC_COUNT ; ss++ ) { container->af_script_classes[ss] = &container->af_script_classes_rec[ss]; } container->af_script_classes[AF_SCRIPT_CLASSES_COUNT-1] = NULL; /* add call to initialization function when you add new scripts */ ss = 0; FT_Init_Class_af_dummy_script_class(&container->af_script_classes_rec[ss++]); #ifdef FT_OPTION_AUTOFIT2 FT_Init_Class_af_latin2_script_class(&container->af_script_classes_rec[ss++]); #endif FT_Init_Class_af_latin_script_class(&container->af_script_classes_rec[ss++]); FT_Init_Class_af_cjk_script_class(&container->af_script_classes_rec[ss++]); FT_Init_Class_af_indic_script_class(&container->af_script_classes_rec[ss++]); FT_Init_Class_af_autofitter_service(library, &container->af_autofitter_service); /*Exit:*/ if(error) autofit_module_class_pic_free(library); return error; }
FT_LruList_New( FT_LruList_Class clazz, FT_UInt max_nodes, FT_Pointer user_data, FT_Memory memory, FT_LruList *alist ) { FT_Error error; FT_LruList list; if ( !alist || !clazz ) return FTC_Err_Invalid_Argument; *alist = NULL; if ( !FT_ALLOC( list, clazz->list_size ) ) { /* initialize common fields */ list->clazz = clazz; list->memory = memory; list->max_nodes = max_nodes; list->data = user_data; if ( clazz->list_init ) { error = clazz->list_init( list ); if ( error ) { if ( clazz->list_done ) clazz->list_done( list ); FT_FREE( list ); } } *alist = list; } return error; }
FT_Error pshinter_module_class_pic_init( FT_Library library ) { FT_PIC_Container* pic_container = &library->pic_container; FT_Error error = FT_Err_Ok; PSHinterPIC* container; FT_Memory memory = library->memory; /* allocate pointer, clear and set global container pointer */ if ( FT_ALLOC ( container, sizeof ( *container ) ) ) return error; FT_MEM_SET( container, 0, sizeof(*container) ); pic_container->pshinter = container; /* add call to initialization function when you add new scripts */ FT_Init_Class_pshinter_interface(library, &container->pshinter_interface); /*Exit:*/ if(error) pshinter_module_class_pic_free(library); return error; }
static FT_Error ft_bitmap_copy( FT_Memory memory, FT_Bitmap* source, FT_Bitmap* target ) { FT_Error error; FT_Int pitch = source->pitch; FT_ULong size; *target = *source; if ( pitch < 0 ) pitch = -pitch; size = (FT_ULong)( pitch * source->rows ); if ( !FT_ALLOC( target->buffer, size ) ) FT_MEM_COPY( target->buffer, source->buffer, size ); return error; }
pfr_extra_item_load_font_id( FT_Byte* p, FT_Byte* limit, PFR_PhyFont phy_font ) { FT_Error error = FT_Err_Ok; FT_Memory memory = phy_font->memory; FT_UInt len = (FT_UInt)( limit - p ); if ( phy_font->font_id ) goto Exit; if ( FT_ALLOC( phy_font->font_id, len + 1 ) ) goto Exit; /* copy font ID name, and terminate it for safety */ FT_MEM_COPY( phy_font->font_id, p, len ); phy_font->font_id[len] = 0; Exit: return error; }
af_face_globals_new( FT_Face face, AF_FaceGlobals *aglobals, AF_Module module ) { FT_Error error; FT_Memory memory; AF_FaceGlobals globals = NULL; memory = face->memory; if ( FT_ALLOC( globals, sizeof ( *globals ) + (FT_ULong)face->num_glyphs * sizeof ( FT_Byte ) ) ) goto Exit; globals->face = face; globals->glyph_count = face->num_glyphs; globals->glyph_styles = (FT_Byte*)( globals + 1 ); globals->module = module; #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ globals->hb_font = hb_ft_font_create( face, NULL ); #endif error = af_face_globals_compute_style_coverage( globals ); if ( error ) { af_face_globals_free( globals ); globals = NULL; } else globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX; Exit: *aglobals = globals; return error; }
FT_Error cff_driver_class_pic_init(FT_Library library) { FT_PIC_Container *pic_container = &library->pic_container; FT_Error error = CFF_Err_Ok; CffModulePIC *container; FT_Memory memory = library->memory; /* allocate pointer, clear and set global container pointer */ if (FT_ALLOC (container, sizeof(*container))) return error; FT_MEM_SET(container, 0, sizeof(*container)); pic_container->cff = container; /* initialize pointer table - this is how the module usually expects this data */ error = FT_Create_Class_cff_services(library, &container->cff_services); if (error) goto Exit; error = FT_Create_Class_cff_field_handlers(library, &container->cff_field_handlers); if (error) goto Exit; FT_Init_Class_cff_service_ps_info(library, &container->cff_service_ps_info); FT_Init_Class_cff_service_glyph_dict(library, &container->cff_service_glyph_dict); FT_Init_Class_cff_service_ps_name(library, &container->cff_service_ps_name); FT_Init_Class_cff_service_get_cmap_info(library, &container->cff_service_get_cmap_info); FT_Init_Class_cff_service_cid_info(library, &container->cff_service_cid_info); FT_Init_Class_cff_cmap_encoding_class_rec(library, &container->cff_cmap_encoding_class_rec); FT_Init_Class_cff_cmap_unicode_class_rec(library, &container->cff_cmap_unicode_class_rec); Exit: if (error) cff_driver_class_pic_free(library); return error; }
static FT_Error ft_new_glyph( FT_Library library, const FT_Glyph_Class* clazz, FT_Glyph* aglyph ) { FT_Memory memory = library->memory; FT_Error error; FT_Glyph glyph = NULL; *aglyph = 0; if ( !FT_ALLOC( glyph, clazz->glyph_size ) ) { glyph->library = library; glyph->clazz = clazz; glyph->format = clazz->glyph_format; *aglyph = glyph; } return error; }
FT_Error ft_base_pic_init( FT_Library library ) { FT_PIC_Container* pic_container = &library->pic_container; FT_Error error = FT_Err_Ok; BasePIC* container = NULL; FT_Memory memory = library->memory; /* allocate pointer, clear and set global container pointer */ if ( FT_ALLOC( container, sizeof ( *container ) ) ) return error; FT_MEM_SET( container, 0, sizeof ( *container ) ); pic_container->base = container; /* initialize default modules list and pointers */ error = ft_create_default_module_classes( library ); if ( error ) goto Exit; /* initialize pointer table - */ /* this is how the module usually expects this data */ FT_Init_Class_ft_outline_glyph_class( &container->ft_outline_glyph_class ); FT_Init_Class_ft_bitmap_glyph_class( &container->ft_bitmap_glyph_class ); #ifdef FT_CONFIG_OPTION_MAC_FONTS FT_Init_Table_ft_raccess_guess_table( (ft_raccess_guess_rec*)&container->ft_raccess_guess_table ); #endif Exit: if ( error ) ft_base_pic_free( library ); return error; }
/* Create a new FT_Face from an SFNT resource, specified by res ID. */ static FT_Error FT_New_Face_From_SFNT( FT_Library library, short sfnt_id, FT_Long face_index, FT_Face *aface ) { Handle sfnt = NULL; FT_Byte* sfnt_data; size_t sfnt_size; FT_Error error = 0; FT_Memory memory = library->memory; sfnt = GetResource( 'sfnt', sfnt_id ); if ( ResError() ) return FT_Err_Invalid_Handle; sfnt_size = (FT_ULong)GetHandleSize( sfnt ); if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) ) { ReleaseResource( sfnt ); return error; } HLock( sfnt ); ft_memcpy( sfnt_data, *sfnt, sfnt_size ); HUnlock( sfnt ); ReleaseResource( sfnt ); return open_face_from_buffer( library, sfnt_data, sfnt_size, face_index, "truetype", aface ); }
static FT_Error otv_load_table( FT_Face face, FT_Tag tag, FT_Byte* volatile* table, FT_ULong* table_len ) { FT_Error error; FT_Memory memory = FT_FACE_MEMORY( face ); error = FT_Load_Sfnt_Table( face, tag, 0, NULL, table_len ); if ( error == OTV_Err_Table_Missing ) return OTV_Err_Ok; if ( error ) goto Exit; if ( FT_ALLOC( *table, *table_len ) ) goto Exit; error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len ); Exit: return error; }
cff_index_get_name( CFF_Index idx, FT_UInt element ) { FT_Memory memory = idx->stream->memory; FT_Byte* bytes; FT_ULong byte_len; FT_Error error; FT_String* name = 0; error = cff_index_access_element( idx, element, &bytes, &byte_len ); if ( error ) goto Exit; if ( !FT_ALLOC( name, byte_len + 1 ) ) { FT_MEM_COPY( name, bytes, byte_len ); name[byte_len] = 0; } cff_index_forget_element( idx, &bytes ); Exit: return name; }
FT_LruList_Lookup( FT_LruList list, FT_LruKey key, FT_LruNode *anode ) { FT_Error error = 0; FT_LruNode node, *pnode; FT_LruList_Class clazz; FT_LruNode* plast; FT_LruNode result = NULL; FT_Memory memory; if ( !list || !key || !anode ) return FTC_Err_Invalid_Argument; pnode = &list->nodes; plast = pnode; node = NULL; clazz = list->clazz; memory = list->memory; if ( clazz->node_compare ) { for (;;) { node = *pnode; if ( node == NULL ) break; if ( clazz->node_compare( node, key, list->data ) ) break; plast = pnode; pnode = &(*pnode)->next; } } else { for (;;) { node = *pnode; if ( node == NULL ) break; if ( node->key == key ) break; plast = pnode; pnode = &(*pnode)->next; } } if ( node ) { /* move element to top of list */ if ( list->nodes != node ) { *pnode = node->next; node->next = list->nodes; list->nodes = node; } result = node; goto Exit; } /* we haven't found the relevant element. We will now try */ /* to create a new one. */ /* */ /* first, check if our list if full, when appropriate */ if ( list->max_nodes > 0 && list->num_nodes >= list->max_nodes ) { /* this list list is full; we will now flush */ /* the oldest node, if there's one! */ FT_LruNode last = *plast; if ( last ) { if ( clazz->node_flush ) { error = clazz->node_flush( last, key, list->data ); } else { if ( clazz->node_done ) clazz->node_done( last, list->data ); last->key = key; error = clazz->node_init( last, key, list->data ); } if ( !error ) { /* move it to the top of the list */ *plast = NULL; last->next = list->nodes; list->nodes = last; result = last; goto Exit; } /* in case of error during the flush or done/init cycle, */ /* we need to discard the node */ if ( clazz->node_done ) clazz->node_done( last, list->data ); *plast = NULL; list->num_nodes--; FT_FREE( last ); goto Exit; } } /* otherwise, simply allocate a new node */ if ( FT_ALLOC( node, clazz->node_size ) ) goto Exit; node->key = key; error = clazz->node_init( node, key, list->data ); if ( error ) { FT_FREE( node ); goto Exit; } result = node; node->next = list->nodes; list->nodes = node; list->num_nodes++; Exit: *anode = result; return error; }
/* convert a slot's glyph image into a bitmap */ static FT_Error ft_smooth_render( FT_Renderer render, FT_GlyphSlot slot, FT_UInt mode, FT_Vector* origin ) { FT_Error error; FT_Outline* outline = NULL; FT_BBox cbox; FT_UInt width, height, pitch; FT_Bitmap* bitmap; FT_Memory memory; FT_Raster_Params params; /* check glyph image format */ if ( slot->format != render->glyph_format ) { error = Smooth_Err_Invalid_Argument; goto Exit; } /* check mode */ if ( mode != ft_render_mode_normal ) return Smooth_Err_Cannot_Render_Glyph; outline = &slot->outline; /* translate the outline to the new origin if needed */ if ( origin ) FT_Outline_Translate( outline, origin->x, origin->y ); /* compute the control box, and grid fit it */ FT_Outline_Get_CBox( outline, &cbox ); cbox.xMin &= -64; cbox.yMin &= -64; cbox.xMax = ( cbox.xMax + 63 ) & -64; cbox.yMax = ( cbox.yMax + 63 ) & -64; width = ( cbox.xMax - cbox.xMin ) >> 6; height = ( cbox.yMax - cbox.yMin ) >> 6; bitmap = &slot->bitmap; memory = render->root.memory; /* release old bitmap buffer */ if ( slot->flags & FT_GLYPH_OWN_BITMAP ) { FT_FREE( bitmap->buffer ); slot->flags &= ~FT_GLYPH_OWN_BITMAP; } /* allocate new one, depends on pixel format */ pitch = width; bitmap->pixel_mode = ft_pixel_mode_grays; bitmap->num_grays = 256; bitmap->width = width; bitmap->rows = height; bitmap->pitch = pitch; if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) ) goto Exit; slot->flags |= FT_GLYPH_OWN_BITMAP; /* translate outline to render it into the bitmap */ FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin ); /* set up parameters */ params.target = bitmap; params.source = outline; params.flags = ft_raster_flag_aa; /* render outline into the bitmap */ error = render->raster_render( render->raster, ¶ms ); FT_Outline_Translate( outline, cbox.xMin, cbox.yMin ); if ( error ) goto Exit; slot->format = ft_glyph_format_bitmap; slot->bitmap_left = cbox.xMin >> 6; slot->bitmap_top = cbox.yMax >> 6; Exit: if ( outline && origin ) FT_Outline_Translate( outline, -origin->x, -origin->y ); return error; }
af_face_globals_get_metrics( AF_FaceGlobals globals, FT_UInt gindex, FT_UInt options, AF_ScriptMetrics *ametrics ) { AF_ScriptMetrics metrics = NULL; FT_UInt gidx; AF_ScriptClass clazz; FT_UInt script = options & 15; const FT_Offset script_max = sizeof ( AF_SCRIPT_CLASSES_GET ) / sizeof ( AF_SCRIPT_CLASSES_GET[0] ); FT_Error error = AF_Err_Ok; if ( gindex >= (FT_ULong)globals->glyph_count ) { error = AF_Err_Invalid_Argument; goto Exit; } gidx = script; if ( gidx == 0 || gidx + 1 >= script_max ) gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_LIST_NONE; clazz = AF_SCRIPT_CLASSES_GET[gidx]; if ( script == 0 ) script = clazz->script; metrics = globals->metrics[clazz->script]; if ( metrics == NULL ) { /* create the global metrics object when needed */ FT_Memory memory = globals->face->memory; if ( FT_ALLOC( metrics, clazz->script_metrics_size ) ) goto Exit; metrics->clazz = clazz; if ( clazz->script_metrics_init ) { error = clazz->script_metrics_init( metrics, globals->face ); if ( error ) { if ( clazz->script_metrics_done ) clazz->script_metrics_done( metrics ); FT_FREE( metrics ); goto Exit; } } globals->metrics[clazz->script] = metrics; } Exit: *ametrics = metrics; return error; }
static FT_Error pcf_interpret_style( PCF_Face pcf ) { FT_Error error = PCF_Err_Ok; FT_Face face = FT_FACE( pcf ); FT_Memory memory = face->memory; PCF_Property prop; int nn, len; char* strings[4] = { NULL, NULL, NULL, NULL }; int lengths[4]; face->style_flags = 0; prop = pcf_find_property( pcf, "SLANT" ); if ( prop && prop->isString && ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' || *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) ) { face->style_flags |= FT_STYLE_FLAG_ITALIC; strings[2] = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ) ? (char *)"Oblique" : (char *)"Italic"; } prop = pcf_find_property( pcf, "WEIGHT_NAME" ); if ( prop && prop->isString && ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) ) { face->style_flags |= FT_STYLE_FLAG_BOLD; strings[1] = (char *)"Bold"; } prop = pcf_find_property( pcf, "SETWIDTH_NAME" ); if ( prop && prop->isString && *(prop->value.atom) && !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) ) strings[3] = (char *)(prop->value.atom); prop = pcf_find_property( pcf, "ADD_STYLE_NAME" ); if ( prop && prop->isString && *(prop->value.atom) && !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) ) strings[0] = (char *)(prop->value.atom); for ( len = 0, nn = 0; nn < 4; nn++ ) { lengths[nn] = 0; if ( strings[nn] ) { lengths[nn] = ft_strlen( strings[nn] ); len += lengths[nn] + 1; } } if ( len == 0 ) { strings[0] = (char *)"Regular"; lengths[0] = ft_strlen( strings[0] ); len = lengths[0] + 1; } { char* s; if ( FT_ALLOC( face->style_name, len ) ) return error; s = face->style_name; for ( nn = 0; nn < 4; nn++ ) { char* src = strings[nn]; len = lengths[nn]; if ( src == NULL ) continue; /* separate elements with a space */ if ( s != face->style_name ) *s++ = ' '; ft_memcpy( s, src, len ); /* need to convert spaces to dashes for */ /* add_style_name and setwidth_name */ if ( nn == 0 || nn == 3 ) { int mm; for ( mm = 0; mm < len; mm++ ) if (s[mm] == ' ') s[mm] = '-'; } s += len; } *s = 0; } return error; }
T1_Get_Private_Dict( T1_Parser parser, PSAux_Service psaux ) { FT_Stream stream = parser->stream; FT_Memory memory = parser->root.memory; FT_Error error = FT_Err_Ok; FT_ULong size; if ( parser->in_pfb ) { /* in the case of the PFB format, the private dictionary can be */ /* made of several segments. We thus first read the number of */ /* segments to compute the total size of the private dictionary */ /* then re-read them into memory. */ FT_Long start_pos = FT_STREAM_POS(); FT_UShort tag; parser->private_len = 0; for (;;) { error = read_pfb_tag( stream, &tag, &size ); if ( error ) goto Fail; if ( tag != 0x8002U ) break; parser->private_len += size; if ( FT_STREAM_SKIP( size ) ) goto Fail; } /* Check that we have a private dictionary there */ /* and allocate private dictionary buffer */ if ( parser->private_len == 0 ) { FT_ERROR(( "T1_Get_Private_Dict:" " invalid private dictionary section\n" )); error = FT_THROW( Invalid_File_Format ); goto Fail; } if ( FT_STREAM_SEEK( start_pos ) || FT_ALLOC( parser->private_dict, parser->private_len ) ) goto Fail; parser->private_len = 0; for (;;) { error = read_pfb_tag( stream, &tag, &size ); if ( error || tag != 0x8002U ) { error = FT_Err_Ok; break; } if ( FT_STREAM_READ( parser->private_dict + parser->private_len, size ) ) goto Fail; parser->private_len += size; } } else { /* We have already `loaded' the whole PFA font file into memory; */ /* if this is a memory resource, allocate a new block to hold */ /* the private dict. Otherwise, simply overwrite into the base */ /* dictionary block in the heap. */ /* first of all, look at the `eexec' keyword */ FT_Byte* cur = parser->base_dict; FT_Byte* limit = cur + parser->base_len; FT_Byte c; Again: for (;;) { c = cur[0]; if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */ /* whitespace + 4 chars */ { if ( cur[1] == 'e' && cur[2] == 'x' && cur[3] == 'e' && cur[4] == 'c' ) break; } cur++; if ( cur >= limit ) { FT_ERROR(( "T1_Get_Private_Dict:" " could not find `eexec' keyword\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } } /* check whether `eexec' was real -- it could be in a comment */ /* or string (as e.g. in u003043t.gsf from ghostscript) */ parser->root.cursor = parser->base_dict; /* set limit to `eexec' + whitespace + 4 characters */ parser->root.limit = cur + 10; cur = parser->root.cursor; limit = parser->root.limit; while ( cur < limit ) { if ( *cur == 'e' && ft_strncmp( (char*)cur, "eexec", 5 ) == 0 ) goto Found; T1_Skip_PS_Token( parser ); if ( parser->root.error ) break; T1_Skip_Spaces ( parser ); cur = parser->root.cursor; } /* we haven't found the correct `eexec'; go back and continue */ /* searching */ cur = limit; limit = parser->base_dict + parser->base_len; goto Again; /* now determine where to write the _encrypted_ binary private */ /* dictionary. We overwrite the base dictionary for disk-based */ /* resources and allocate a new block otherwise */ Found: parser->root.limit = parser->base_dict + parser->base_len; T1_Skip_PS_Token( parser ); cur = parser->root.cursor; limit = parser->root.limit; /* according to the Type1 spec, the first cipher byte must not be */ /* an ASCII whitespace character code (blank, tab, carriage return */ /* or line feed). We have seen Type 1 fonts with two line feed */ /* characters... So skip now all whitespace character codes. */ /* SumatraPDF: stop at \r if it's not used for EOL - cf. https://code.google.com/p/sumatrapdf/issues/detail?id=2408 */ c = !memchr(cur, '\n', limit - cur) || memchr(cur, '\n', limit - cur) > memchr(cur, '\r', limit - cur); while ( cur < limit && ( *cur == ' ' || *cur == '\t' || ( c && *cur == '\r' ) || *cur == '\n' ) ) ++cur; if ( cur >= limit ) { FT_ERROR(( "T1_Get_Private_Dict:" " `eexec' not properly terminated\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } size = (FT_ULong)( parser->base_len - ( cur - parser->base_dict ) ); if ( parser->in_memory ) { /* note that we allocate one more byte to put a terminating `0' */ if ( FT_ALLOC( parser->private_dict, size + 1 ) ) goto Fail; parser->private_len = size; } else { parser->single_block = 1; parser->private_dict = parser->base_dict; parser->private_len = size; parser->base_dict = 0; parser->base_len = 0; } /* now determine whether the private dictionary is encoded in binary */ /* or hexadecimal ASCII format -- decode it accordingly */ /* we need to access the next 4 bytes (after the final whitespace */ /* following the `eexec' keyword); if they all are hexadecimal */ /* digits, then we have a case of ASCII storage */ if ( cur + 3 < limit && ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) && ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) ) { /* ASCII hexadecimal encoding */ FT_Long len; parser->root.cursor = cur; (void)psaux->ps_parser_funcs->to_bytes( &parser->root, parser->private_dict, parser->private_len, &len, 0 ); parser->private_len = len; /* put a safeguard */ parser->private_dict[len] = '\0'; } else /* binary encoding -- copy the private dict */ FT_MEM_MOVE( parser->private_dict, cur, size ); } /* we now decrypt the encoded binary private dictionary */ psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U ); if ( parser->private_len < 4 ) { FT_ERROR(( "T1_Get_Private_Dict:" " invalid private dictionary section\n" )); error = FT_THROW( Invalid_File_Format ); goto Fail; } /* replace the four random bytes at the beginning with whitespace */ parser->private_dict[0] = ' '; parser->private_dict[1] = ' '; parser->private_dict[2] = ' '; parser->private_dict[3] = ' '; parser->root.base = parser->private_dict; parser->root.cursor = parser->private_dict; parser->root.limit = parser->root.cursor + parser->private_len; Fail: Exit: return error; }
FT_Stream_OpenGzip( FT_Stream stream, FT_Stream source ) { FT_Error error; FT_Memory memory = source->memory; FT_GZipFile zip; /* * check the header right now; this prevents allocating un-necessary * objects when we don't need them */ error = ft_gzip_check_header( source ); if ( error ) goto Exit; FT_ZERO( stream ); stream->memory = memory; if ( !FT_QNEW( zip ) ) { error = ft_gzip_file_init( zip, stream, source ); if ( error ) { FT_FREE( zip ); goto Exit; } stream->descriptor.pointer = zip; } /* * We use the following trick to try to dramatically improve the * performance while dealing with small files. If the original stream * size is less than a certain threshold, we try to load the whole font * file into memory. This saves us from using the 32KB buffer needed * to inflate the file, plus the two 4KB intermediate input/output * buffers used in the `FT_GZipFile' structure. */ { FT_ULong zip_size = ft_gzip_get_uncompressed_size( source ); if ( zip_size != 0 && zip_size < 40 * 1024 ) { FT_Byte* zip_buff; if ( !FT_ALLOC( zip_buff, zip_size ) ) { FT_ULong count; count = ft_gzip_file_io( zip, 0, zip_buff, zip_size ); if ( count == zip_size ) { ft_gzip_file_done( zip ); FT_FREE( zip ); stream->descriptor.pointer = NULL; stream->size = zip_size; stream->pos = 0; stream->base = zip_buff; stream->read = NULL; stream->close = ft_gzip_stream_close; goto Exit; } ft_gzip_file_io( zip, 0, NULL, 0 ); FT_FREE( zip_buff ); } error = 0; } } stream->size = 0x7FFFFFFFL; /* don't know the real size! */ stream->pos = 0; stream->base = 0; stream->read = ft_gzip_stream_io; stream->close = ft_gzip_stream_close; Exit: return error; }
T1_New_Parser( T1_Parser parser, FT_Stream stream, FT_Memory memory, PSAux_Service psaux ) { FT_Error error; FT_UShort tag; FT_ULong size; psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); parser->stream = stream; parser->base_len = 0; parser->base_dict = 0; parser->private_len = 0; parser->private_dict = 0; parser->in_pfb = 0; parser->in_memory = 0; parser->single_block = 0; /* check the header format */ error = check_type1_format( stream, "%!PS-AdobeFont", 14 ); if ( error ) { if ( FT_ERR_NEQ( error, Unknown_File_Format ) ) goto Exit; error = check_type1_format( stream, "%!FontType", 10 ); if ( error ) { FT_TRACE2(( " not a Type 1 font\n" )); goto Exit; } } /******************************************************************/ /* */ /* Here a short summary of what is going on: */ /* */ /* When creating a new Type 1 parser, we try to locate and load */ /* the base dictionary if this is possible (i.e., for PFB */ /* files). Otherwise, we load the whole font into memory. */ /* */ /* When `loading' the base dictionary, we only setup pointers */ /* in the case of a memory-based stream. Otherwise, we */ /* allocate and load the base dictionary in it. */ /* */ /* parser->in_pfb is set if we are in a binary (`.pfb') font. */ /* parser->in_memory is set if we have a memory stream. */ /* */ /* try to compute the size of the base dictionary; */ /* look for a Postscript binary file tag, i.e., 0x8001 */ if ( FT_STREAM_SEEK( 0L ) ) goto Exit; error = read_pfb_tag( stream, &tag, &size ); if ( error ) goto Exit; if ( tag != 0x8001U ) { /* assume that this is a PFA file for now; an error will */ /* be produced later when more things are checked */ if ( FT_STREAM_SEEK( 0L ) ) goto Exit; size = stream->size; } else parser->in_pfb = 1; /* now, try to load `size' bytes of the `base' dictionary we */ /* found previously */ /* if it is a memory-based resource, set up pointers */ if ( !stream->read ) { parser->base_dict = (FT_Byte*)stream->base + stream->pos; parser->base_len = size; parser->in_memory = 1; /* check that the `size' field is valid */ if ( FT_STREAM_SKIP( size ) ) goto Exit; } else { /* read segment in memory -- this is clumsy, but so does the format */ if ( FT_ALLOC( parser->base_dict, size ) || FT_STREAM_READ( parser->base_dict, size ) ) goto Exit; parser->base_len = size; } parser->root.base = parser->base_dict; parser->root.cursor = parser->base_dict; parser->root.limit = parser->root.cursor + parser->base_len; Exit: if ( error && !parser->in_memory ) FT_FREE( parser->base_dict ); return error; }
static FT_Error T42_Open_Face( T42_Face face ) { T42_LoaderRec loader; T42_Parser parser; T1_Font type1 = &face->type1; FT_Memory memory = face->root.memory; FT_Error error; PSAux_Service psaux = (PSAux_Service)face->psaux; t42_loader_init( &loader, face ); parser = &loader.parser; if ( FT_ALLOC( face->ttf_data, 12 ) ) goto Exit; error = t42_parser_init( parser, face->root.stream, memory, psaux); if ( error ) goto Exit; error = t42_parse_dict( face, &loader, parser->base_dict, parser->base_len ); if ( error ) goto Exit; if ( type1->font_type != 42 ) { error = T42_Err_Unknown_File_Format; goto Exit; } /* now, propagate the charstrings and glyphnames tables */ /* to the Type1 data */ type1->num_glyphs = loader.num_glyphs; if ( !loader.charstrings.init ) { FT_ERROR(( "T42_Open_Face: no charstrings array in face!\n" )); error = T42_Err_Invalid_File_Format; } loader.charstrings.init = 0; type1->charstrings_block = loader.charstrings.block; type1->charstrings = loader.charstrings.elements; type1->charstrings_len = loader.charstrings.lengths; /* we copy the glyph names `block' and `elements' fields; */ /* the `lengths' field must be released later */ type1->glyph_names_block = loader.glyph_names.block; type1->glyph_names = (FT_String**)loader.glyph_names.elements; loader.glyph_names.block = 0; loader.glyph_names.elements = 0; /* we must now build type1.encoding when we have a custom array */ if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY ) { FT_Int charcode, idx, min_char, max_char; FT_Byte* char_name; FT_Byte* glyph_name; /* OK, we do the following: for each element in the encoding */ /* table, look up the index of the glyph having the same name */ /* as defined in the CharStrings array. */ /* The index is then stored in type1.encoding.char_index, and */ /* the name in type1.encoding.char_name */ min_char = +32000; max_char = -32000; charcode = 0; for ( ; charcode < loader.encoding_table.max_elems; charcode++ ) { type1->encoding.char_index[charcode] = 0; type1->encoding.char_name [charcode] = (char *)".notdef"; char_name = loader.encoding_table.elements[charcode]; if ( char_name ) for ( idx = 0; idx < type1->num_glyphs; idx++ ) { glyph_name = (FT_Byte*)type1->glyph_names[idx]; if ( ft_strcmp( (const char*)char_name, (const char*)glyph_name ) == 0 ) { type1->encoding.char_index[charcode] = (FT_UShort)idx; type1->encoding.char_name [charcode] = (char*)glyph_name; /* Change min/max encoded char only if glyph name is */ /* not /.notdef */ if ( ft_strcmp( (const char*)".notdef", (const char*)glyph_name ) != 0 ) { if ( charcode < min_char ) min_char = charcode; if ( charcode > max_char ) max_char = charcode; } break; } } } type1->encoding.code_first = min_char; type1->encoding.code_last = max_char; type1->encoding.num_chars = loader.num_chars; } Exit: t42_loader_done( &loader ); return error; }
/* Read Type 1 data from the POST resources inside the LWFN file, return a PFB buffer. This is somewhat convoluted because the FT2 PFB parser wants the ASCII header as one chunk, and the LWFN chunks are often not organized that way, so we glue chunks of the same type together. */ static FT_Error read_lwfn( FT_Memory memory, ResFileRefNum res, FT_Byte** pfb_data, FT_ULong* size ) { FT_Error error = FT_Err_Ok; ResID res_id; unsigned char *buffer, *p, *size_p = NULL; FT_ULong total_size = 0; FT_ULong old_total_size = 0; FT_ULong post_size, pfb_chunk_size; Handle post_data; char code, last_code; UseResFile( res ); /* First pass: load all POST resources, and determine the size of */ /* the output buffer. */ res_id = 501; last_code = -1; for (;;) { post_data = Get1Resource( TTAG_POST, res_id++ ); if ( post_data == NULL ) break; /* we are done */ code = (*post_data)[0]; if ( code != last_code ) { if ( code == 5 ) total_size += 2; /* just the end code */ else total_size += 6; /* code + 4 bytes chunk length */ } total_size += GetHandleSize( post_data ) - 2; last_code = code; /* detect integer overflows */ if ( total_size < old_total_size ) { error = FT_Err_Array_Too_Large; goto Error; } old_total_size = total_size; } if ( FT_ALLOC( buffer, (FT_Long)total_size ) ) goto Error; /* Second pass: append all POST data to the buffer, add PFB fields. */ /* Glue all consecutive chunks of the same type together. */ p = buffer; res_id = 501; last_code = -1; pfb_chunk_size = 0; for (;;) { post_data = Get1Resource( TTAG_POST, res_id++ ); if ( post_data == NULL ) break; /* we are done */ post_size = (FT_ULong)GetHandleSize( post_data ) - 2; code = (*post_data)[0]; if ( code != last_code ) { if ( last_code != -1 ) { /* we are done adding a chunk, fill in the size field */ if ( size_p != NULL ) { *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF ); *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF ); *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF ); *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF ); } pfb_chunk_size = 0; } *p++ = 0x80; if ( code == 5 ) *p++ = 0x03; /* the end */ else if ( code == 2 ) *p++ = 0x02; /* binary segment */ else *p++ = 0x01; /* ASCII segment */ if ( code != 5 ) { size_p = p; /* save for later */ p += 4; /* make space for size field */ } } ft_memcpy( p, *post_data + 2, post_size ); pfb_chunk_size += post_size; p += post_size; last_code = code; }
af_face_globals_get_metrics( AF_FaceGlobals globals, FT_UInt gindex, FT_UInt options, AF_StyleMetrics *ametrics ) { AF_StyleMetrics metrics = NULL; AF_Style style = (AF_Style)options; AF_WritingSystemClass writing_system_class; AF_StyleClass style_class; FT_Error error = FT_Err_Ok; if ( gindex >= (FT_ULong)globals->glyph_count ) { error = FT_THROW( Invalid_Argument ); goto Exit; } /* if we have a forced style (via `options'), use it, */ /* otherwise look into `glyph_styles' array */ if ( style == AF_STYLE_NONE_DFLT || style + 1 >= AF_STYLE_MAX ) style = (AF_Style)( globals->glyph_styles[gindex] & AF_STYLE_UNASSIGNED ); style_class = AF_STYLE_CLASSES_GET[style]; writing_system_class = AF_WRITING_SYSTEM_CLASSES_GET [style_class->writing_system]; metrics = globals->metrics[style]; if ( metrics == NULL ) { /* create the global metrics object if necessary */ FT_Memory memory = globals->face->memory; if ( FT_ALLOC( metrics, writing_system_class->style_metrics_size ) ) goto Exit; metrics->style_class = style_class; metrics->globals = globals; if ( writing_system_class->style_metrics_init ) { error = writing_system_class->style_metrics_init( metrics, globals->face ); if ( error ) { if ( writing_system_class->style_metrics_done ) writing_system_class->style_metrics_done( metrics ); FT_FREE( metrics ); goto Exit; } } globals->metrics[style] = metrics; } Exit: *ametrics = metrics; return error; }
cf2_decoder_parse_charstrings( CFF_Decoder* decoder, FT_Byte* charstring_base, FT_ULong charstring_len ) { FT_Memory memory; FT_Error error = FT_Err_Ok; CF2_Font font; FT_ASSERT( decoder && decoder->cff ); memory = decoder->builder.memory; /* CF2 data is saved here across glyphs */ font = (CF2_Font)decoder->cff->cf2_instance.data; /* on first glyph, allocate instance structure */ if ( decoder->cff->cf2_instance.data == NULL ) { decoder->cff->cf2_instance.finalizer = (FT_Generic_Finalizer)cf2_free_instance; if ( FT_ALLOC( decoder->cff->cf2_instance.data, sizeof ( CF2_FontRec ) ) ) return FT_THROW( Out_Of_Memory ); font = (CF2_Font)decoder->cff->cf2_instance.data; font->memory = memory; /* initialize a client outline, to be shared by each glyph rendered */ cf2_outline_init( &font->outline, font->memory, &font->error ); } /* save decoder; it is a stack variable and will be different on each */ /* call */ font->decoder = decoder; font->outline.decoder = decoder; { /* build parameters for Adobe engine */ CFF_Builder* builder = &decoder->builder; CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face ); /* local error */ FT_Error error2 = FT_Err_Ok; CF2_BufferRec buf; CF2_Matrix transform; CF2_F16Dot16 glyphWidth; FT_Bool hinted; FT_Bool scaled; /* FreeType has already looked up the GID; convert to */ /* `RegionBuffer', assuming that the input has been validated */ FT_ASSERT( charstring_base + charstring_len >= charstring_base ); FT_ZERO( &buf ); buf.start = buf.ptr = charstring_base; buf.end = charstring_base + charstring_len; FT_ZERO( &transform ); cf2_getScaleAndHintFlag( decoder, &transform.a, &transform.d, &hinted, &scaled ); font->renderingFlags = 0; if ( hinted ) font->renderingFlags |= CF2_FlagsHinted; if ( scaled && !driver->no_stem_darkening ) font->renderingFlags |= CF2_FlagsDarkened; font->darkenParams[0] = driver->darken_params[0]; font->darkenParams[1] = driver->darken_params[1]; font->darkenParams[2] = driver->darken_params[2]; font->darkenParams[3] = driver->darken_params[3]; font->darkenParams[4] = driver->darken_params[4]; font->darkenParams[5] = driver->darken_params[5]; font->darkenParams[6] = driver->darken_params[6]; font->darkenParams[7] = driver->darken_params[7]; /* now get an outline for this glyph; */ /* also get units per em to validate scale */ font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder ); if ( scaled ) { error2 = cf2_checkTransform( &transform, font->unitsPerEm ); if ( error2 ) return error2; } error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth ); if ( error2 ) return FT_ERR( Invalid_File_Format ); cf2_setGlyphWidth( &font->outline, glyphWidth ); return FT_Err_Ok; } }
/* Create a new FT_Face from an SFNT resource, specified by res ID. */ static FT_Error FT_New_Face_From_SFNT( FT_Library library, ResID sfnt_id, FT_Long face_index, FT_Face* aface ) { Handle sfnt = NULL; FT_Byte* sfnt_data; size_t sfnt_size; FT_Error error = FT_Err_Ok; FT_Memory memory = library->memory; int is_cff, is_sfnt_ps; sfnt = GetResource( TTAG_sfnt, sfnt_id ); if ( sfnt == NULL ) return FT_Err_Invalid_Handle; sfnt_size = (FT_ULong)GetHandleSize( sfnt ); if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) ) { ReleaseResource( sfnt ); return error; } ft_memcpy( sfnt_data, *sfnt, sfnt_size ); ReleaseResource( sfnt ); is_cff = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 ); is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 ); if ( is_sfnt_ps ) { FT_Stream stream; if ( FT_NEW( stream ) ) goto Try_OpenType; FT_Stream_OpenMemory( stream, sfnt_data, sfnt_size ); if ( !open_face_PS_from_sfnt_stream( library, stream, face_index, 0, NULL, aface ) ) { FT_Stream_Close( stream ); FT_FREE( stream ); FT_FREE( sfnt_data ); goto Exit; } FT_FREE( stream ); } Try_OpenType: error = open_face_from_buffer( library, sfnt_data, sfnt_size, face_index, is_cff ? "cff" : "truetype", aface ); Exit: return error; }
static FT_Error cff_ps_get_font_extra( CFF_Face face, PS_FontExtraRec* afont_extra ) { CFF_Font cff = (CFF_Font)face->extra.data; FT_Error error = FT_Err_Ok; if ( cff && cff->font_extra == NULL ) { CFF_FontRecDict dict = &cff->top_font.font_dict; PS_FontExtraRec* font_extra = NULL; FT_Memory memory = face->root.memory; FT_String* embedded_postscript; if ( FT_ALLOC( font_extra, sizeof ( *font_extra ) ) ) goto Fail; font_extra->fs_type = 0U; embedded_postscript = cff_index_get_sid_string( cff, dict->embedded_postscript ); if ( embedded_postscript ) { FT_String* start_fstype; FT_String* start_def; /* Identify the XYZ integer in `/FSType XYZ def' substring. */ if ( ( start_fstype = ft_strstr( embedded_postscript, "/FSType" ) ) != NULL && ( start_def = ft_strstr( start_fstype + sizeof ( "/FSType" ) - 1, "def" ) ) != NULL ) { FT_String* s; for ( s = start_fstype + sizeof ( "/FSType" ) - 1; s != start_def; s++ ) { if ( *s >= '0' && *s <= '9' ) { if ( font_extra->fs_type >= ( FT_USHORT_MAX - 9 ) / 10 ) { /* Overflow - ignore the FSType value. */ font_extra->fs_type = 0U; break; } font_extra->fs_type *= 10; font_extra->fs_type += (FT_UShort)( *s - '0' ); } else if ( *s != ' ' && *s != '\n' && *s != '\r' ) { /* Non-whitespace character between `/FSType' and next `def' */ /* - ignore the FSType value. */ font_extra->fs_type = 0U; break; } } } } cff->font_extra = font_extra; } if ( cff ) *afont_extra = *cff->font_extra; Fail: return error; }
/* entries to C-style strings (this is, NULL-terminated). */ static FT_Error cff_index_get_pointers( CFF_Index idx, FT_Byte*** table, FT_Byte** pool ) { FT_Error error = FT_Err_Ok; FT_Memory memory = idx->stream->memory; FT_Byte** t = NULL; FT_Byte* new_bytes = NULL; *table = NULL; if ( idx->offsets == NULL ) { error = cff_index_load_offsets( idx ); if ( error ) goto Exit; } if ( idx->count > 0 && !FT_NEW_ARRAY( t, idx->count + 1 ) && ( !pool || !FT_ALLOC( new_bytes, idx->data_size + idx->count ) ) ) { FT_ULong n, cur_offset; FT_ULong extra = 0; FT_Byte* org_bytes = idx->bytes; /* at this point, `idx->offsets' can't be NULL */ cur_offset = idx->offsets[0] - 1; /* sanity check */ if ( cur_offset != 0 ) { FT_TRACE0(( "cff_index_get_pointers:" " invalid first offset value %d set to zero\n", cur_offset )); cur_offset = 0; } if ( !pool ) t[0] = org_bytes + cur_offset; else t[0] = new_bytes + cur_offset; for ( n = 1; n <= idx->count; n++ ) { FT_ULong next_offset = idx->offsets[n] - 1; /* two sanity checks for invalid offset tables */ if ( next_offset < cur_offset ) next_offset = cur_offset; else if ( next_offset > idx->data_size ) next_offset = idx->data_size; if ( !pool ) t[n] = org_bytes + next_offset; else { t[n] = new_bytes + next_offset + extra; if ( next_offset != cur_offset ) { FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] ); t[n][0] = '\0'; t[n] += 1; extra++; } } cur_offset = next_offset; } *table = t; if ( pool ) *pool = new_bytes; } Exit: return error; }
static const char* get_sfnt_postscript_name( TT_Face face ) { FT_Int n, found_win, found_apple; const char* result = NULL; /* shouldn't happen, but just in case to avoid memory leaks */ if ( face->root.internal->postscript_name ) return face->root.internal->postscript_name; /* 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; for ( n = 0; n < face->num_names; n++ ) { TT_NameEntryRec* name = face->name_table.names + n; if ( name->nameID == 6 && name->stringLength > 0 ) { 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; } } if ( found_win != -1 ) { FT_Memory memory = face->root.memory; TT_NameEntryRec* name = face->name_table.names + found_win; FT_UInt len = name->stringLength / 2; FT_Error error; if ( !FT_ALLOC( result, name->stringLength + 1 ) ) { FT_Stream stream = face->name_table.stream; FT_String* r = (FT_String*)result; FT_Byte* p = (FT_Byte*)name->string; if ( FT_STREAM_SEEK( name->stringOffset ) || FT_FRAME_ENTER( name->stringLength ) ) { FT_FREE( result ); name->stringLength = 0; name->stringOffset = 0; FT_FREE( name->string ); goto Exit; } p = (FT_Byte*)stream->cursor; for ( ; len > 0; len--, p += 2 ) { if ( p[0] == 0 && p[1] >= 32 && p[1] < 128 ) *r++ = p[1]; } *r = '\0'; FT_FRAME_EXIT(); } goto Exit; } if ( found_apple != -1 ) { FT_Memory memory = face->root.memory; TT_NameEntryRec* name = face->name_table.names + found_apple; FT_UInt len = name->stringLength; FT_Error error; if ( !FT_ALLOC( result, len + 1 ) ) { FT_Stream stream = face->name_table.stream; if ( FT_STREAM_SEEK( name->stringOffset ) || FT_STREAM_READ( result, len ) ) { name->stringOffset = 0; name->stringLength = 0; FT_FREE( name->string ); FT_FREE( result ); goto Exit; } ((char*)result)[len] = '\0'; } } Exit: face->root.internal->postscript_name = result; return result; }
t42_parser_init( T42_Parser parser, FT_Stream stream, FT_Memory memory, PSAux_Service psaux ) { FT_Error error = FT_Err_Ok; FT_Long size; psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); parser->stream = stream; parser->base_len = 0; parser->base_dict = 0; parser->in_memory = 0; /*******************************************************************/ /* */ /* Here a short summary of what is going on: */ /* */ /* When creating a new Type 42 parser, we try to locate and load */ /* the base dictionary, loading the whole font into memory. */ /* */ /* When `loading' the base dictionary, we only set up pointers */ /* in the case of a memory-based stream. Otherwise, we allocate */ /* and load the base dictionary in it. */ /* */ /* parser->in_memory is set if we have a memory stream. */ /* */ if ( FT_STREAM_SEEK( 0L ) || FT_FRAME_ENTER( 17 ) ) goto Exit; if ( ft_memcmp( stream->cursor, "%!PS-TrueTypeFont", 17 ) != 0 ) { FT_TRACE2(( " not a Type42 font\n" )); error = FT_THROW( Unknown_File_Format ); } FT_FRAME_EXIT(); if ( error || FT_STREAM_SEEK( 0 ) ) goto Exit; size = stream->size; /* now, try to load `size' bytes of the `base' dictionary we */ /* found previously */ /* if it is a memory-based resource, set up pointers */ if ( !stream->read ) { parser->base_dict = (FT_Byte*)stream->base + stream->pos; parser->base_len = size; parser->in_memory = 1; /* check that the `size' field is valid */ if ( FT_STREAM_SKIP( size ) ) goto Exit; } else { /* read segment in memory */ if ( FT_ALLOC( parser->base_dict, size ) || FT_STREAM_READ( parser->base_dict, size ) ) goto Exit; parser->base_len = size; } parser->root.base = parser->base_dict; parser->root.cursor = parser->base_dict; parser->root.limit = parser->root.cursor + parser->base_len; Exit: if ( error && !parser->in_memory ) FT_FREE( parser->base_dict ); return error; }