ftc_basic_family_get_count( FTC_Family ftcfamily, FTC_Manager manager ) { FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; FT_Error error; FT_Face face; FT_UInt result = 0; error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id, &face ); if ( error || !face ) return result; if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs ) { FT_TRACE1(( "ftc_basic_family_get_count: too large number of glyphs " )); FT_TRACE1(( "in this face, truncated\n", face->num_glyphs )); } if ( !error ) result = (FT_UInt)face->num_glyphs; return result; }
FT_Stream_Open( FT_Stream stream, const char* filepathname ) { FT_FILE* file; if ( !stream ) return FT_Err_Invalid_Stream_Handle; file = ft_fopen( filepathname, "rb" ); if ( !file ) { FT_ERROR(( "FT_Stream_Open:" " could not open `%s'\n", filepathname )); return FT_Err_Cannot_Open_Resource; } ft_fseek( file, 0, SEEK_END ); stream->size = ft_ftell( file ); ft_fseek( file, 0, SEEK_SET ); stream->descriptor.pointer = file; stream->pathname.pointer = (char*)filepathname; stream->pos = 0; stream->read = ft_ansi_stream_io; stream->close = ft_ansi_stream_close; FT_TRACE1(( "FT_Stream_Open:" )); FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", filepathname, stream->size )); return FT_Err_Ok; }
FT_Stream_Open( FT_Stream stream, const char* filepathname ) { // FILE* file; BPTR file; // TetiSoft struct FileInfoBlock* fib; // TetiSoft if ( !stream ) return FT_Err_Invalid_Stream_Handle; // file = fopen( filepathname, "rb" ); file = Open( filepathname, MODE_OLDFILE ); // TetiSoft if ( !file ) { FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not open `%s'\n", filepathname )); return FT_Err_Cannot_Open_Resource; } // fseek( file, 0, SEEK_END ); // astream->size = ftell( file ); // fseek( file, 0, SEEK_SET ); fib = AllocDosObject( DOS_FIB, NULL ); if ( !fib ) { Close ( file ); FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not open `%s'\n", filepathname )); return FT_Err_Cannot_Open_Resource; } if ( !( ExamineFH( file, fib ) ) ) { FreeDosObject( DOS_FIB, fib ); Close ( file ); FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not open `%s'\n", filepathname )); return FT_Err_Cannot_Open_Resource; } stream->size = fib->fib_Size; FreeDosObject( DOS_FIB, fib ); // stream->descriptor.pointer = file; stream->descriptor.pointer = (void *)file; stream->pathname.pointer = (char*)filepathname; stream->pos = 0; stream->read = ft_io_stream; stream->close = ft_close_stream; FT_TRACE1(( "FT_Stream_Open:" )); FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", filepathname, stream->size )); return FT_Err_Ok; }
FTC_SBitCache_LookupScaler( FTC_SBitCache cache, FTC_Scaler scaler, FT_ULong load_flags, FT_UInt gindex, FTC_SBit *ansbit, FTC_Node *anode ) { FT_Error error; FTC_BasicQueryRec query; FTC_Node node = 0; /* make compiler happy */ FT_UInt32 hash; if ( anode ) *anode = NULL; /* other argument checks delayed to FTC_Cache_Lookup */ if ( !ansbit || !scaler ) return FTC_Err_Invalid_Argument; *ansbit = NULL; /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */ if ( load_flags > FT_UINT_MAX ) { FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" )); FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) )); } query.attrs.scaler = scaler[0]; query.attrs.load_flags = (FT_UInt)load_flags; /* beware, the hash must be the same for all glyph ranges! */ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex / FTC_SBIT_ITEMS_PER_NODE; FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, FTC_SNode_Compare, hash, gindex, &query, node, error ); if ( error ) goto Exit; *ansbit = FTC_SNODE( node )->sbits + ( gindex - FTC_GNODE( node )->gindex ); if ( anode ) { *anode = node; node->ref_count++; } Exit: return error; }
FTC_ImageCache_LookupScaler( FTC_ImageCache cache, FTC_Scaler scaler, FT_ULong load_flags, FT_UInt gindex, FT_Glyph *aglyph, FTC_Node *anode ) { FTC_BasicQueryRec query; FTC_Node node = 0; /* make compiler happy */ FT_Error error; FT_UInt32 hash; /* some argument checks are delayed to FTC_Cache_Lookup */ if ( !aglyph || !scaler ) { error = FTC_Err_Invalid_Argument; goto Exit; } *aglyph = NULL; if ( anode ) *anode = NULL; /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */ if ( load_flags > FT_UINT_MAX ) { FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" )); FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) )); } query.attrs.scaler = scaler[0]; query.attrs.load_flags = (FT_UInt)load_flags; hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex; FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, FTC_GNode_Compare, hash, gindex, &query, node, error ); if ( !error ) { *aglyph = FTC_INODE( node )->glyph; if ( anode ) { *anode = node; node->ref_count++; } } Exit: return error; }
/* * CID INFO SERVICE * */ static FT_Error cff_get_ros( CFF_Face face, const char* *registry, const char* *ordering, FT_Int *supplement ) { FT_Error error = CFF_Err_Ok; CFF_Font cff = (CFF_Font)face->extra.data; if ( cff ) { CFF_FontRecDict dict = &cff->top_font.font_dict; if ( dict->cid_registry == 0xFFFFU ) { error = CFF_Err_Invalid_Argument; goto Fail; } if ( registry ) { if ( cff->registry == NULL ) cff->registry = cff_index_get_sid_string( cff, dict->cid_registry ); *registry = cff->registry; } if ( ordering ) { if ( cff->ordering == NULL ) cff->ordering = cff_index_get_sid_string( cff, dict->cid_ordering ); *ordering = cff->ordering; } /* * XXX: According to Adobe TechNote #5176, the supplement in CFF * can be a real number. We truncate it to fit public API * since freetype-2.3.6. */ if ( supplement ) { if ( dict->cid_supplement < FT_INT_MIN || dict->cid_supplement > FT_INT_MAX ) FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n", dict->cid_supplement )); *supplement = (FT_Int)dict->cid_supplement; } } Fail: return error; }
FT_Stream_Open( FT_Stream stream, const char* filepathname) { Dir *dir; int file; if ( !stream ) return FT_Err_Invalid_Stream_Handle; file = kopen( (char*)filepathname, OREAD); if ( file < 0) { FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not open `%s'\n", filepathname )); return FT_Err_Cannot_Open_Resource; } dir = kdirfstat(file); if (dir == nil) { kclose(file); FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not stat `%s'\n", filepathname )); return FT_Err_Cannot_Open_Resource; } stream->size = dir->length; free(dir); stream->descriptor.pointer = (void*)file; stream->pathname.pointer = (char*)filepathname; stream->pos = 0; stream->read = ft_ansi_stream_io; stream->close = ft_ansi_stream_close; FT_TRACE1(( "FT_Stream_Open:" )); FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", filepathname, stream->size )); return FT_Err_Ok; }
T42_GlyphSlot_Load( FT_GlyphSlot glyph, FT_Size size, FT_UInt glyph_index, FT_Int32 load_flags ) { FT_Error error; T42_GlyphSlot t42slot = (T42_GlyphSlot)glyph; T42_Size t42size = (T42_Size)size; T42_Face t42face = (T42_Face)size->face; FT_Driver_Class ttclazz = ((T42_Driver)glyph->face->driver)->ttclazz; FT_TRACE1(( "T42_GlyphSlot_Load: glyph index %d\n", glyph_index )); /* map T42 glyph index to embedded TTF's glyph index */ glyph_index = (FT_UInt)ft_strtol( (const char *)t42face->type1.charstrings[glyph_index], NULL, 10 ); t42_glyphslot_clear( t42slot->ttslot ); error = ttclazz->load_glyph( t42slot->ttslot, t42size->ttsize, glyph_index, load_flags | FT_LOAD_NO_BITMAP ); if ( !error ) { glyph->metrics = t42slot->ttslot->metrics; glyph->linearHoriAdvance = t42slot->ttslot->linearHoriAdvance; glyph->linearVertAdvance = t42slot->ttslot->linearVertAdvance; glyph->format = t42slot->ttslot->format; glyph->outline = t42slot->ttslot->outline; glyph->bitmap = t42slot->ttslot->bitmap; glyph->bitmap_left = t42slot->ttslot->bitmap_left; glyph->bitmap_top = t42slot->ttslot->bitmap_top; glyph->num_subglyphs = t42slot->ttslot->num_subglyphs; glyph->subglyphs = t42slot->ttslot->subglyphs; glyph->control_data = t42slot->ttslot->control_data; glyph->control_len = t42slot->ttslot->control_len; } return error; }
FT_EXPORT_FUNC(FT_Error) FT_Register_Extension( FT_Driver driver, FT_Extension_Class *clazz) { FT_Extension_Registry *registry; if(!driver) { return FT_Err_Invalid_Driver_Handle; } if(!clazz) { return FT_Err_Invalid_Argument; } registry = (FT_Extension_Registry *)driver->extensions; if(registry) { FT_Int n = registry->num_extensions; FT_Extension_Class *cur = registry->classes + n; if(n >= FT_MAX_EXTENSIONS) { return FT_Err_Too_Many_Extensions; } *cur = *clazz; cur->offset = registry->cur_offset; registry->num_extensions++; registry->cur_offset += (cur->size + FT_ALIGNMENT - 1) & - FT_ALIGNMENT; FT_TRACE1(("FT_Register_Extension: `%s' successfully registered\n", cur->id)); } return FT_Err_Ok; }
FT_EXPORT_FUNC(void *) FT_Get_Extension( FT_Face face, const char *extension_id, void **extension_interface) { FT_Extension_Registry *registry; if(!face || !extension_id || !extension_interface) { return 0; } registry = (FT_Extension_Registry *)face->driver->extensions; if(registry && face->extensions) { FT_Extension_Class *cur = registry->classes; FT_Extension_Class *limit = cur + registry->num_extensions; for(; cur < limit; cur++) if(strcmp(cur->id, extension_id) == 0) { *extension_interface = cur->interface; FT_TRACE1(("FT_Get_Extension: got `%s'\n", extension_id)); return (void *)((char *)face->extensions + cur->offset); } } /* could not find the extension id */ FT_ERROR(("FT_Get_Extension: couldn't find `%s'\n", extension_id)); *extension_interface = 0; return 0; }
cff_glyph_load( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */ FT_Size cffsize, /* CFF_Size */ FT_UInt glyph_index, FT_Int32 load_flags ) { FT_Error error; CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot; CFF_Size size = (CFF_Size)cffsize; if ( !slot ) return FT_THROW( Invalid_Slot_Handle ); FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index )); /* check whether we want a scaled outline or bitmap */ if ( !size ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; /* reset the size object if necessary */ if ( load_flags & FT_LOAD_NO_SCALE ) size = NULL; if ( size ) { /* these two objects must have the same parent */ if ( cffsize->face != cffslot->face ) return FT_THROW( Invalid_Face_Handle ); } /* now load the glyph outline if necessary */ error = cff_slot_load( slot, size, glyph_index, load_flags ); /* force drop-out mode to 2 - irrelevant now */ /* slot->outline.dropout_mode = 2; */ return error; }
/* open a standard stream from a given pathname */ static void ft_std_stream_init( FT_StdStream stream, const char* pathname ) { FT_ASSERT( pathname != NULL ); stream->file = fopen( pathname, "rb" ); if ( stream->file == NULL ) { FT_ERROR(( "iso.stream.init: could not open '%s'\n", pathname )); FT_XTHROW( FT_Err_Stream_Open ); } /* compute total size in bytes */ fseek( file, 0, SEEK_END ); FT_STREAM__SIZE(stream) = ftell( file ); fseek( file, 0, SEEK_SET ); stream->pathname = pathname; stream->pos = 0; FT_TRACE1(( "iso.stream.init: opened '%s' (%ld bytes) succesfully\n", pathname, FT_STREAM__SIZE(stream) )); }
static FT_Error otv_validate( FT_Face volatile face, FT_UInt ot_flags, FT_Bytes *ot_base, FT_Bytes *ot_gdef, FT_Bytes *ot_gpos, FT_Bytes *ot_gsub, FT_Bytes *ot_jstf ) { FT_Error error = OTV_Err_Ok; FT_Byte* volatile base; FT_Byte* volatile gdef; FT_Byte* volatile gpos; FT_Byte* volatile gsub; FT_Byte* volatile jstf; FT_Byte* volatile math; FT_ULong len_base, len_gdef, len_gpos, len_gsub, len_jstf; FT_ULong len_math; FT_UInt num_glyphs = (FT_UInt)face->num_glyphs; FT_ValidatorRec volatile valid; base = gdef = gpos = gsub = jstf = math = NULL; len_base = len_gdef = len_gpos = len_gsub = len_jstf = len_math = 0; /* * XXX: OpenType tables cannot handle 32-bit glyph index, * although broken TrueType can have 32-bit glyph index. */ if ( face->num_glyphs > 0xFFFFL ) { FT_TRACE1(( "otv_validate: Invalid glyphs index (0x0000FFFF - 0x%08x) ", face->num_glyphs )); FT_TRACE1(( "are not handled by OpenType tables\n" )); num_glyphs = 0xFFFF; } /* load tables */ if ( ot_flags & FT_VALIDATE_BASE ) { error = otv_load_table( face, TTAG_BASE, &base, &len_base ); if ( error ) goto Exit; } if ( ot_flags & FT_VALIDATE_GDEF ) { error = otv_load_table( face, TTAG_GDEF, &gdef, &len_gdef ); if ( error ) goto Exit; } if ( ot_flags & FT_VALIDATE_GPOS ) { error = otv_load_table( face, TTAG_GPOS, &gpos, &len_gpos ); if ( error ) goto Exit; } if ( ot_flags & FT_VALIDATE_GSUB ) { error = otv_load_table( face, TTAG_GSUB, &gsub, &len_gsub ); if ( error ) goto Exit; } if ( ot_flags & FT_VALIDATE_JSTF ) { error = otv_load_table( face, TTAG_JSTF, &jstf, &len_jstf ); if ( error ) goto Exit; } if ( ot_flags & FT_VALIDATE_MATH ) { error = otv_load_table( face, TTAG_MATH, &math, &len_math ); if ( error ) goto Exit; } /* validate tables */ if ( base ) { ft_validator_init( &valid, base, base + len_base, FT_VALIDATE_DEFAULT ); if ( ft_setjmp( valid.jump_buffer ) == 0 ) otv_BASE_validate( base, &valid ); error = valid.error; if ( error ) goto Exit; } if ( gpos ) { ft_validator_init( &valid, gpos, gpos + len_gpos, FT_VALIDATE_DEFAULT ); if ( ft_setjmp( valid.jump_buffer ) == 0 ) otv_GPOS_validate( gpos, num_glyphs, &valid ); error = valid.error; if ( error ) goto Exit; } if ( gsub ) { ft_validator_init( &valid, gsub, gsub + len_gsub, FT_VALIDATE_DEFAULT ); if ( ft_setjmp( valid.jump_buffer ) == 0 ) otv_GSUB_validate( gsub, num_glyphs, &valid ); error = valid.error; if ( error ) goto Exit; } if ( gdef ) { ft_validator_init( &valid, gdef, gdef + len_gdef, FT_VALIDATE_DEFAULT ); if ( ft_setjmp( valid.jump_buffer ) == 0 ) otv_GDEF_validate( gdef, gsub, gpos, num_glyphs, &valid ); error = valid.error; if ( error ) goto Exit; } if ( jstf ) { ft_validator_init( &valid, jstf, jstf + len_jstf, FT_VALIDATE_DEFAULT ); if ( ft_setjmp( valid.jump_buffer ) == 0 ) otv_JSTF_validate( jstf, gsub, gpos, num_glyphs, &valid ); error = valid.error; if ( error ) goto Exit; } if ( math ) { ft_validator_init( &valid, math, math + len_math, FT_VALIDATE_DEFAULT ); if ( ft_setjmp( valid.jump_buffer ) == 0 ) otv_MATH_validate( math, num_glyphs, &valid ); error = valid.error; if ( error ) goto Exit; } *ot_base = (FT_Bytes)base; *ot_gdef = (FT_Bytes)gdef; *ot_gpos = (FT_Bytes)gpos; *ot_gsub = (FT_Bytes)gsub; *ot_jstf = (FT_Bytes)jstf; Exit: if ( error ) { FT_Memory memory = FT_FACE_MEMORY( face ); FT_FREE( base ); FT_FREE( gdef ); FT_FREE( gpos ); FT_FREE( gsub ); FT_FREE( jstf ); } { FT_Memory memory = FT_FACE_MEMORY( face ); FT_FREE( math ); /* Can't return this as API is frozen */ } return error; }
FTC_ImageCache_LookupScaler( FTC_ImageCache cache, FTC_Scaler scaler, FT_ULong load_flags, FT_UInt gindex, FT_Glyph *aglyph, FTC_Node *anode ) { FTC_BasicQueryRec query; FTC_Node node = 0; /* make compiler happy */ FT_Error error; FT_Offset hash; /* some argument checks are delayed to `FTC_Cache_Lookup' */ if ( !aglyph || !scaler ) { error = FT_THROW( Invalid_Argument ); goto Exit; } *aglyph = NULL; if ( anode ) *anode = NULL; /* * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt', * but public `FT_Face->face_flags' is of type `FT_Long'. * * On long > int systems, higher bits of load_flags cannot be handled. */ #if FT_ULONG_MAX > FT_UINT_MAX if ( load_flags > FT_UINT_MAX ) FT_TRACE1(( "FTC_ImageCache_LookupScaler:" " higher bits in load_flags 0x%x are dropped\n", load_flags & ~((FT_ULong)FT_UINT_MAX) )); #endif query.attrs.scaler = scaler[0]; query.attrs.load_flags = (FT_UInt)load_flags; hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex; FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, FTC_GNode_Compare, hash, gindex, &query, node, error ); if ( !error ) { *aglyph = FTC_INODE( node )->glyph; if ( anode ) { *anode = node; node->ref_count++; } } Exit: return error; }
cid_load_glyph( T1_Decoder decoder, FT_UInt glyph_index ) { CID_Face face = (CID_Face)decoder->builder.face; CID_FaceInfo cid = &face->cid; FT_Byte* p; FT_ULong fd_select; FT_Stream stream = face->cid_stream; FT_Error error = FT_Err_Ok; FT_Byte* charstring = 0; FT_Memory memory = face->root.memory; FT_ULong glyph_length = 0; PSAux_Service psaux = (PSAux_Service)face->psaux; #ifdef FT_CONFIG_OPTION_INCREMENTAL FT_Incremental_InterfaceRec *inc = face->root.internal->incremental_interface; #endif FT_TRACE1(( "cid_load_glyph: glyph index %d\n", glyph_index )); #ifdef FT_CONFIG_OPTION_INCREMENTAL /* For incremental fonts get the character data using */ /* the callback function. */ if ( inc ) { FT_Data glyph_data; error = inc->funcs->get_glyph_data( inc->object, glyph_index, &glyph_data ); if ( error ) goto Exit; p = (FT_Byte*)glyph_data.pointer; fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); if ( glyph_data.length != 0 ) { glyph_length = (FT_ULong)( glyph_data.length - cid->fd_bytes ); (void)FT_ALLOC( charstring, glyph_length ); if ( !error ) ft_memcpy( charstring, glyph_data.pointer + cid->fd_bytes, glyph_length ); } inc->funcs->free_glyph_data( inc->object, &glyph_data ); if ( error ) goto Exit; } else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ /* For ordinary fonts read the CID font dictionary index */ /* and charstring offset from the CIDMap. */ { FT_UInt entry_len = (FT_UInt)( cid->fd_bytes + cid->gd_bytes ); FT_ULong off1; if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset + glyph_index * entry_len ) || FT_FRAME_ENTER( 2 * entry_len ) ) goto Exit; p = (FT_Byte*)stream->cursor; fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); off1 = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ); p += cid->fd_bytes; glyph_length = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1; FT_FRAME_EXIT(); if ( fd_select >= (FT_ULong)cid->num_dicts ) { error = FT_THROW( Invalid_Offset ); goto Exit; } if ( glyph_length == 0 ) goto Exit; if ( FT_ALLOC( charstring, glyph_length ) ) goto Exit; if ( FT_STREAM_READ_AT( cid->data_offset + off1, charstring, glyph_length ) ) goto Exit; } /* Now set up the subrs array and parse the charstrings. */ { CID_FaceDict dict; CID_Subrs cid_subrs = face->subrs + fd_select; FT_UInt cs_offset; /* Set up subrs */ decoder->num_subrs = cid_subrs->num_subrs; decoder->subrs = cid_subrs->code; decoder->subrs_len = 0; /* Set up font matrix */ dict = cid->font_dicts + fd_select; decoder->font_matrix = dict->font_matrix; decoder->font_offset = dict->font_offset; decoder->lenIV = dict->private_dict.lenIV; /* Decode the charstring. */ /* Adjustment for seed bytes. */ cs_offset = decoder->lenIV >= 0 ? (FT_UInt)decoder->lenIV : 0; /* Decrypt only if lenIV >= 0. */ if ( decoder->lenIV >= 0 ) psaux->t1_decrypt( charstring, glyph_length, 4330 ); error = decoder->funcs.parse_charstrings( decoder, charstring + cs_offset, glyph_length - cs_offset ); } FT_FREE( charstring ); #ifdef FT_CONFIG_OPTION_INCREMENTAL /* Incremental fonts can optionally override the metrics. */ if ( !error && inc && inc->funcs->get_glyph_metrics ) { FT_Incremental_MetricsRec metrics; metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x ); metrics.bearing_y = 0; metrics.advance = FIXED_TO_INT( decoder->builder.advance.x ); metrics.advance_v = FIXED_TO_INT( decoder->builder.advance.y ); error = inc->funcs->get_glyph_metrics( inc->object, glyph_index, FALSE, &metrics ); decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x ); decoder->builder.advance.x = INT_TO_FIXED( metrics.advance ); decoder->builder.advance.y = INT_TO_FIXED( metrics.advance_v ); } #endif /* FT_CONFIG_OPTION_INCREMENTAL */ Exit: return error; }
FT_Stream_Open( FT_Stream stream, const char* filepathname ) { int file; struct stat stat_buf; if ( !stream ) return FT_THROW( Invalid_Stream_Handle ); /* open the file */ file = open( filepathname, O_RDONLY ); if ( file < 0 ) { FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not open `%s'\n", filepathname )); return FT_THROW( Cannot_Open_Resource ); } /* Here we ensure that a "fork" will _not_ duplicate */ /* our opened input streams on Unix. This is critical */ /* since it avoids some (possible) access control */ /* issues and cleans up the kernel file table a bit. */ /* */ #ifdef F_SETFD #ifdef FD_CLOEXEC (void)fcntl( file, F_SETFD, FD_CLOEXEC ); #else (void)fcntl( file, F_SETFD, 1 ); #endif /* FD_CLOEXEC */ #endif /* F_SETFD */ if ( fstat( file, &stat_buf ) < 0 ) { FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not `fstat' file `%s'\n", filepathname )); goto Fail_Map; } /* XXX: TODO -- real 64bit platform support */ /* */ /* `stream->size' is typedef'd to unsigned long (in `ftsystem.h'); */ /* `stat_buf.st_size', however, is usually typedef'd to off_t */ /* (in sys/stat.h). */ /* On some platforms, the former is 32bit and the latter is 64bit. */ /* To avoid overflow caused by fonts in huge files larger than */ /* 2GB, do a test. Temporary fix proposed by Sean McBride. */ /* */ if ( stat_buf.st_size > LONG_MAX ) { FT_ERROR(( "FT_Stream_Open: file is too big\n" )); goto Fail_Map; } else if ( stat_buf.st_size == 0 ) { FT_ERROR(( "FT_Stream_Open: zero-length file\n" )); goto Fail_Map; } /* This cast potentially truncates a 64bit to 32bit! */ stream->size = (unsigned long)stat_buf.st_size; stream->pos = 0; stream->base = (unsigned char *)mmap( NULL, stream->size, PROT_READ, MAP_FILE | MAP_PRIVATE, file, 0 ); /* on some RTOS, mmap might return 0 */ if ( (long)stream->base != -1 && stream->base != NULL ) stream->close = ft_close_stream_by_munmap; else { ssize_t total_read_count; FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not `mmap' file `%s'\n", filepathname )); stream->base = (unsigned char*)ft_alloc( NULL, stream->size ); if ( !stream->base ) { FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not `alloc' memory\n" )); goto Fail_Map; } total_read_count = 0; do { ssize_t read_count; read_count = read( file, stream->base + total_read_count, stream->size - total_read_count ); if ( read_count <= 0 ) { if ( read_count == -1 && errno == EINTR ) continue; FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " error while `read'ing file `%s'\n", filepathname )); goto Fail_Read; } total_read_count += read_count; } while ( (unsigned long)total_read_count != stream->size ); stream->close = ft_close_stream_by_free; } close( file ); stream->descriptor.pointer = stream->base; stream->pathname.pointer = (char*)filepathname; stream->read = 0; FT_TRACE1(( "FT_Stream_Open:" )); FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", filepathname, stream->size )); return FT_Err_Ok; Fail_Read: ft_free( NULL, stream->base ); Fail_Map: close( file ); stream->base = NULL; stream->size = 0; stream->pos = 0; return FT_THROW( Cannot_Open_Stream ); }
FTC_SBitCache_Lookup( FTC_SBitCache cache, FTC_ImageType type, FT_UInt gindex, FTC_SBit *ansbit, FTC_Node *anode ) { FT_Error error; FTC_BasicQueryRec query; FTC_Node node = 0; /* make compiler happy */ FT_Offset hash; if ( anode ) *anode = NULL; /* other argument checks delayed to `FTC_Cache_Lookup' */ if ( !ansbit ) return FT_THROW( Invalid_Argument ); *ansbit = NULL; /* * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt', * but public `FT_ImageType->flags' is of type `FT_Int32'. * * On 16bit systems, higher bits of type->flags cannot be handled. */ #if 0xFFFFFFFFUL > FT_UINT_MAX if ( (type->flags & (FT_ULong)FT_UINT_MAX) ) FT_TRACE1(( "FTC_ImageCache_Lookup:" " higher bits in load_flags 0x%x are dropped\n", (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) )); #endif query.attrs.scaler.face_id = type->face_id; query.attrs.scaler.width = type->width; query.attrs.scaler.height = type->height; query.attrs.load_flags = (FT_UInt)type->flags; query.attrs.scaler.pixel = 1; query.attrs.scaler.x_res = 0; /* make compilers happy */ query.attrs.scaler.y_res = 0; /* beware, the hash must be the same for all glyph ranges! */ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex / FTC_SBIT_ITEMS_PER_NODE; #if 1 /* inlining is about 50% faster! */ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, FTC_SNode_Compare, hash, gindex, &query, node, error ); #else error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex, FTC_GQUERY( &query ), &node ); #endif if ( error ) goto Exit; *ansbit = FTC_SNODE( node )->sbits + ( gindex - FTC_GNODE( node )->gindex ); if ( anode ) { *anode = node; node->ref_count++; } Exit: return error; }
FT_Stream_Open( FT_Stream stream, const char* filepathname ) { struct FileInfoBlock* fib; struct SysFile* sysfile; if ( !stream ) return FT_THROW( Invalid_Stream_Handle ); #ifdef __amigaos4__ sysfile = AllocMem ( sizeof (struct SysFile ), MEMF_SHARED ); #else sysfile = AllocMem ( sizeof (struct SysFile ), MEMF_PUBLIC ); #endif if ( !sysfile ) { FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not open `%s'\n", filepathname )); return FT_THROW( Cannot_Open_Resource ); } sysfile->file = Open( (STRPTR)filepathname, MODE_OLDFILE ); if ( !sysfile->file ) { FreeMem ( sysfile, sizeof ( struct SysFile )); FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not open `%s'\n", filepathname )); return FT_THROW( Cannot_Open_Resource ); } fib = AllocDosObject( DOS_FIB, NULL ); if ( !fib ) { Close ( sysfile->file ); FreeMem ( sysfile, sizeof ( struct SysFile )); FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not open `%s'\n", filepathname )); return FT_THROW( Cannot_Open_Resource ); } if ( !( ExamineFH( sysfile->file, fib ) ) ) { FreeDosObject( DOS_FIB, fib ); Close ( sysfile->file ); FreeMem ( sysfile, sizeof ( struct SysFile )); FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not open `%s'\n", filepathname )); return FT_THROW( Cannot_Open_Resource ); } stream->size = fib->fib_Size; FreeDosObject( DOS_FIB, fib ); stream->descriptor.pointer = (void *)sysfile; stream->pathname.pointer = (char*)filepathname; sysfile->iobuf_start = 0; sysfile->iobuf_end = 0; stream->pos = 0; stream->read = ft_amiga_stream_io; stream->close = ft_amiga_stream_close; if ( !stream->size ) { ft_amiga_stream_close( stream ); FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " opened `%s' but zero-sized\n", filepathname )); return FT_THROW( Cannot_Open_Stream ); } FT_TRACE1(( "FT_Stream_Open:" )); FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n", filepathname, stream->size )); return FT_Err_Ok; }
FTC_ImageCache_Lookup( FTC_ImageCache cache, FTC_ImageType type, FT_UInt gindex, FT_Glyph *aglyph, FTC_Node *anode ) { FTC_BasicQueryRec query; FTC_Node node = 0; /* make compiler happy */ FT_Error error; FT_Offset hash; /* some argument checks are delayed to `FTC_Cache_Lookup' */ if ( !aglyph ) { error = FT_THROW( Invalid_Argument ); goto Exit; } *aglyph = NULL; if ( anode ) *anode = NULL; if ( (FT_ULong)( type->flags - FT_INT_MIN ) > FT_UINT_MAX ) FT_TRACE1(( "FTC_ImageCache_Lookup:" " higher bits in load_flags 0x%x are dropped\n", (FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) )); query.attrs.scaler.face_id = type->face_id; query.attrs.scaler.width = type->width; query.attrs.scaler.height = type->height; query.attrs.load_flags = (FT_UInt)type->flags; query.attrs.scaler.pixel = 1; query.attrs.scaler.x_res = 0; /* make compilers happy */ query.attrs.scaler.y_res = 0; hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex; #if 1 /* inlining is about 50% faster! */ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, FTC_GNode_Compare, hash, gindex, &query, node, error ); #else error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex, FTC_GQUERY( &query ), &node ); #endif if ( !error ) { *aglyph = FTC_INODE( node )->glyph; if ( anode ) { *anode = node; node->ref_count++; } } Exit: return error; }
FTC_SBitCache_LookupScaler( FTC_SBitCache cache, FTC_Scaler scaler, FT_ULong load_flags, FT_UInt gindex, FTC_SBit *ansbit, FTC_Node *anode ) { FT_Error error; FTC_BasicQueryRec query; FTC_Node node = 0; /* make compiler happy */ FT_Offset hash; if ( anode ) *anode = NULL; /* other argument checks delayed to `FTC_Cache_Lookup' */ if ( !ansbit || !scaler ) return FT_THROW( Invalid_Argument ); *ansbit = NULL; /* * Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt', * but public `FT_Face->face_flags' is of type `FT_Long'. * * On long > int systems, higher bits of load_flags cannot be handled. */ #if FT_ULONG_MAX > FT_UINT_MAX if ( load_flags > FT_UINT_MAX ) FT_TRACE1(( "FTC_ImageCache_LookupScaler:" " higher bits in load_flags 0x%x are dropped\n", load_flags & ~((FT_ULong)FT_UINT_MAX) )); #endif query.attrs.scaler = scaler[0]; query.attrs.load_flags = (FT_UInt)load_flags; /* beware, the hash must be the same for all glyph ranges! */ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex / FTC_SBIT_ITEMS_PER_NODE; FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, FTC_SNode_Compare, hash, gindex, &query, node, error ); if ( error ) goto Exit; *ansbit = FTC_SNODE( node )->sbits + ( gindex - FTC_GNODE( node )->gindex ); if ( anode ) { *anode = node; node->ref_count++; } Exit: return error; }
pfr_slot_load( FT_GlyphSlot pfrslot, /* PFR_Slot */ FT_Size pfrsize, /* PFR_Size */ FT_UInt gindex, FT_Int32 load_flags ) { PFR_Slot slot = (PFR_Slot)pfrslot; PFR_Size size = (PFR_Size)pfrsize; FT_Error error; PFR_Face face = (PFR_Face)pfrslot->face; PFR_Char gchar; FT_Outline* outline = &pfrslot->outline; FT_ULong gps_offset; FT_TRACE1(( "pfr_slot_load: glyph index %d\n", gindex )); if ( gindex > 0 ) gindex--; if ( !face || gindex >= face->phy_font.num_chars ) { error = FT_THROW( Invalid_Argument ); goto Exit; } /* try to load an embedded bitmap */ if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 ) { error = pfr_slot_load_bitmap( slot, size, gindex ); if ( error == 0 ) goto Exit; } if ( load_flags & FT_LOAD_SBITS_ONLY ) { error = FT_THROW( Invalid_Argument ); goto Exit; } gchar = face->phy_font.chars + gindex; pfrslot->format = FT_GLYPH_FORMAT_OUTLINE; outline->n_points = 0; outline->n_contours = 0; gps_offset = face->header.gps_section_offset; /* load the glyph outline (FT_LOAD_NO_RECURSE isn't supported) */ error = pfr_glyph_load( &slot->glyph, face->root.stream, gps_offset, gchar->gps_offset, gchar->gps_size ); if ( !error ) { FT_BBox cbox; FT_Glyph_Metrics* metrics = &pfrslot->metrics; FT_Pos advance; FT_UInt em_metrics, em_outline; FT_Bool scaling; scaling = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); /* copy outline data */ *outline = slot->glyph.loader->base.outline; outline->flags &= ~FT_OUTLINE_OWNER; outline->flags |= FT_OUTLINE_REVERSE_FILL; if ( size && pfrsize->metrics.y_ppem < 24 ) outline->flags |= FT_OUTLINE_HIGH_PRECISION; /* compute the advance vector */ metrics->horiAdvance = 0; metrics->vertAdvance = 0; advance = gchar->advance; em_metrics = face->phy_font.metrics_resolution; em_outline = face->phy_font.outline_resolution; if ( em_metrics != em_outline ) advance = FT_MulDiv( advance, (FT_Long)em_outline, (FT_Long)em_metrics ); if ( face->phy_font.flags & PFR_PHY_VERTICAL ) metrics->vertAdvance = advance; else metrics->horiAdvance = advance; pfrslot->linearHoriAdvance = metrics->horiAdvance; pfrslot->linearVertAdvance = metrics->vertAdvance; /* make-up vertical metrics(?) */ metrics->vertBearingX = 0; metrics->vertBearingY = 0; #if 0 /* some fonts seem to be broken here! */ /* Apply the font matrix, if any. */ /* TODO: Test existing fonts with unusual matrix */ /* whether we have to adjust Units per EM. */ { FT_Matrix font_matrix; font_matrix.xx = face->log_font.matrix[0] << 8; font_matrix.yx = face->log_font.matrix[1] << 8; font_matrix.xy = face->log_font.matrix[2] << 8; font_matrix.yy = face->log_font.matrix[3] << 8; FT_Outline_Transform( outline, &font_matrix ); } #endif /* scale when needed */ if ( scaling ) { FT_Int n; FT_Fixed x_scale = pfrsize->metrics.x_scale; FT_Fixed y_scale = pfrsize->metrics.y_scale; FT_Vector* vec = outline->points; /* scale outline points */ for ( n = 0; n < outline->n_points; n++, vec++ ) { vec->x = FT_MulFix( vec->x, x_scale ); vec->y = FT_MulFix( vec->y, y_scale ); } /* scale the advance */ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); } /* compute the rest of the metrics */ FT_Outline_Get_CBox( outline, &cbox ); metrics->width = cbox.xMax - cbox.xMin; metrics->height = cbox.yMax - cbox.yMin; metrics->horiBearingX = cbox.xMin; metrics->horiBearingY = cbox.yMax - metrics->height; } Exit: return error; }
FTC_SBitCache_Lookup( FTC_SBitCache cache, FTC_ImageType type, FT_UInt gindex, FTC_SBit *ansbit, FTC_Node *anode ) { FT_Error error; FTC_BasicQueryRec query; FTC_Node node = 0; /* make compiler happy */ FT_UInt32 hash; if ( anode ) *anode = NULL; /* other argument checks delayed to FTC_Cache_Lookup */ if ( !ansbit ) return FTC_Err_Invalid_Argument; *ansbit = NULL; #if defined( FT_CONFIG_OPTION_OLD_INTERNALS ) && ( FT_INT_MAX > 0xFFFFU ) /* This one is a major hack used to detect whether we are passed a * regular FTC_ImageType handle, or a legacy FTC_OldImageDesc one. */ if ( (FT_ULong)type->width >= 0x10000L ) { FTC_OldImageDesc desc = (FTC_OldImageDesc)type; query.attrs.scaler.face_id = desc->font.face_id; query.attrs.scaler.width = desc->font.pix_width; query.attrs.scaler.height = desc->font.pix_height; query.attrs.load_flags = desc->flags; } else #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ { if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX ) { FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" )); FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) )); } query.attrs.scaler.face_id = type->face_id; query.attrs.scaler.width = type->width; query.attrs.scaler.height = type->height; query.attrs.load_flags = (FT_UInt)type->flags; } query.attrs.scaler.pixel = 1; query.attrs.scaler.x_res = 0; /* make compilers happy */ query.attrs.scaler.y_res = 0; /* beware, the hash must be the same for all glyph ranges! */ hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex / FTC_SBIT_ITEMS_PER_NODE; #if 1 /* inlining is about 50% faster! */ FTC_GCACHE_LOOKUP_CMP( cache, ftc_basic_family_compare, FTC_SNode_Compare, hash, gindex, &query, node, error ); #else error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex, FTC_GQUERY( &query ), &node ); #endif if ( error ) goto Exit; *ansbit = FTC_SNODE( node )->sbits + ( gindex - FTC_GNODE( node )->gindex ); if ( anode ) { *anode = node; node->ref_count++; } Exit: return error; }
T1_Read_Metrics( FT_Face t1_face, FT_Stream stream ) { PSAux_Service psaux; FT_Memory memory = stream->memory; AFM_ParserRec parser; AFM_FontInfo fi = NULL; FT_Error error = FT_ERR( Unknown_File_Format ); T1_Face face = (T1_Face)t1_face; T1_Font t1_font = &face->type1; if ( face->afm_data ) { FT_TRACE1(( "T1_Read_Metrics:" " Freeing previously attached metrics data.\n" )); T1_Done_Metrics( memory, (AFM_FontInfo)face->afm_data ); face->afm_data = NULL; } if ( FT_NEW( fi ) || FT_FRAME_ENTER( stream->size ) ) goto Exit; fi->FontBBox = t1_font->font_bbox; fi->Ascender = t1_font->font_bbox.yMax; fi->Descender = t1_font->font_bbox.yMin; psaux = (PSAux_Service)face->psaux; if ( psaux->afm_parser_funcs ) { error = psaux->afm_parser_funcs->init( &parser, stream->memory, stream->cursor, stream->limit ); if ( !error ) { parser.FontInfo = fi; parser.get_index = t1_get_index; parser.user_data = t1_font; error = psaux->afm_parser_funcs->parse( &parser ); psaux->afm_parser_funcs->done( &parser ); } } if ( FT_ERR_EQ( error, Unknown_File_Format ) ) { FT_Byte* start = stream->cursor; /* MS Windows allows versions up to 0x3FF without complaining */ if ( stream->size > 6 && start[1] < 4 && FT_PEEK_ULONG_LE( start + 2 ) == stream->size ) error = T1_Read_PFM( t1_face, stream, fi ); } if ( !error ) { t1_font->font_bbox = fi->FontBBox; t1_face->bbox.xMin = fi->FontBBox.xMin >> 16; t1_face->bbox.yMin = fi->FontBBox.yMin >> 16; /* no `U' suffix here to 0xFFFF! */ t1_face->bbox.xMax = ( fi->FontBBox.xMax + 0xFFFF ) >> 16; t1_face->bbox.yMax = ( fi->FontBBox.yMax + 0xFFFF ) >> 16; /* no `U' suffix here to 0x8000! */ t1_face->ascender = (FT_Short)( ( fi->Ascender + 0x8000 ) >> 16 ); t1_face->descender = (FT_Short)( ( fi->Descender + 0x8000 ) >> 16 ); if ( fi->NumKernPair ) { t1_face->face_flags |= FT_FACE_FLAG_KERNING; face->afm_data = fi; fi = NULL; } }
T1_Load_Glyph( FT_GlyphSlot t1glyph, /* T1_GlyphSlot */ FT_Size t1size, /* T1_Size */ FT_UInt glyph_index, FT_Int32 load_flags ) { T1_GlyphSlot glyph = (T1_GlyphSlot)t1glyph; FT_Error error; #ifdef __REACTOS__ T1_DecoderRec *decoder = malloc(sizeof(T1_DecoderRec)); if (!decoder) return FT_THROW( Out_Of_Memory ); /* Ugly but it allows us to reduce the diff */ #define decoder (*decoder) { #else T1_DecoderRec decoder; #endif T1_Face face = (T1_Face)t1glyph->face; FT_Bool hinting; FT_Bool scaled; FT_Bool force_scaling = FALSE; T1_Font type1 = &face->type1; PSAux_Service psaux = (PSAux_Service)face->psaux; const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs; FT_Matrix font_matrix; FT_Vector font_offset; FT_Data glyph_data; FT_Bool must_finish_decoder = FALSE; #ifdef FT_CONFIG_OPTION_INCREMENTAL FT_Bool glyph_data_loaded = 0; #endif #ifdef FT_CONFIG_OPTION_INCREMENTAL if ( glyph_index >= (FT_UInt)face->root.num_glyphs && !face->root.internal->incremental_interface ) #else if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { error = FT_THROW( Invalid_Argument ); goto Exit; } FT_TRACE1(( "T1_Load_Glyph: glyph index %d\n", glyph_index )); FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); if ( load_flags & FT_LOAD_NO_RECURSE ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; if ( t1size ) { glyph->x_scale = t1size->metrics.x_scale; glyph->y_scale = t1size->metrics.y_scale; } else { glyph->x_scale = 0x10000L; glyph->y_scale = 0x10000L; } t1glyph->outline.n_points = 0; t1glyph->outline.n_contours = 0; hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); glyph->hint = hinting; glyph->scaled = scaled; t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; error = decoder_funcs->init( &decoder, t1glyph->face, t1size, t1glyph, (FT_Byte**)type1->glyph_names, face->blend, FT_BOOL( hinting ), FT_LOAD_TARGET_MODE( load_flags ), T1_Parse_Glyph ); if ( error ) goto Exit; must_finish_decoder = TRUE; decoder.builder.no_recurse = FT_BOOL( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); decoder.num_subrs = type1->num_subrs; decoder.subrs = type1->subrs; decoder.subrs_len = type1->subrs_len; decoder.subrs_hash = type1->subrs_hash; decoder.buildchar = face->buildchar; decoder.len_buildchar = face->len_buildchar; /* now load the unscaled outline */ error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index, &glyph_data, &force_scaling ); if ( error ) goto Exit; #ifdef FT_CONFIG_OPTION_INCREMENTAL glyph_data_loaded = 1; #endif hinting = glyph->hint; font_matrix = decoder.font_matrix; font_offset = decoder.font_offset; /* save new glyph tables */ decoder_funcs->done( &decoder ); must_finish_decoder = FALSE; /* now, set the metrics -- this is rather simple, as */ /* the left side bearing is the xMin, and the top side */ /* bearing the yMax */ if ( !error ) { t1glyph->outline.flags &= FT_OUTLINE_OWNER; t1glyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; /* for composite glyphs, return only left side bearing and */ /* advance width */ if ( load_flags & FT_LOAD_NO_RECURSE ) { FT_Slot_Internal internal = t1glyph->internal; t1glyph->metrics.horiBearingX = FIXED_TO_INT( decoder.builder.left_bearing.x ); t1glyph->metrics.horiAdvance = FIXED_TO_INT( decoder.builder.advance.x ); internal->glyph_matrix = font_matrix; internal->glyph_delta = font_offset; internal->glyph_transformed = 1; } else { FT_BBox cbox; FT_Glyph_Metrics* metrics = &t1glyph->metrics; /* copy the _unscaled_ advance width */ metrics->horiAdvance = FIXED_TO_INT( decoder.builder.advance.x ); t1glyph->linearHoriAdvance = FIXED_TO_INT( decoder.builder.advance.x ); t1glyph->internal->glyph_transformed = 0; if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) { /* make up vertical ones */ metrics->vertAdvance = ( face->type1.font_bbox.yMax - face->type1.font_bbox.yMin ) >> 16; t1glyph->linearVertAdvance = metrics->vertAdvance; } else { metrics->vertAdvance = FIXED_TO_INT( decoder.builder.advance.y ); t1glyph->linearVertAdvance = FIXED_TO_INT( decoder.builder.advance.y ); } t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; if ( t1size && t1size->metrics.y_ppem < 24 ) t1glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; #if 1 /* apply the font matrix, if any */ if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L || font_matrix.xy != 0 || font_matrix.yx != 0 ) { FT_Outline_Transform( &t1glyph->outline, &font_matrix ); metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, font_matrix.xx ); metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, font_matrix.yy ); } if ( font_offset.x || font_offset.y ) { FT_Outline_Translate( &t1glyph->outline, font_offset.x, font_offset.y ); metrics->horiAdvance += font_offset.x; metrics->vertAdvance += font_offset.y; } #endif if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling ) { /* scale the outline and the metrics */ FT_Int n; FT_Outline* cur = decoder.builder.base; FT_Vector* vec = cur->points; FT_Fixed x_scale = glyph->x_scale; FT_Fixed y_scale = glyph->y_scale; /* First of all, scale the points, if we are not hinting */ if ( !hinting || ! decoder.builder.hints_funcs ) for ( n = cur->n_points; n > 0; n--, vec++ ) { vec->x = FT_MulFix( vec->x, x_scale ); vec->y = FT_MulFix( vec->y, y_scale ); } /* Then scale the metrics */ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); } /* compute the other metrics */ FT_Outline_Get_CBox( &t1glyph->outline, &cbox ); metrics->width = cbox.xMax - cbox.xMin; metrics->height = cbox.yMax - cbox.yMin; metrics->horiBearingX = cbox.xMin; metrics->horiBearingY = cbox.yMax; if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) { /* make up vertical ones */ ft_synthesize_vertical_metrics( metrics, metrics->vertAdvance ); } }
T1_Load_Glyph( FT_GlyphSlot t1glyph, /* T1_GlyphSlot */ FT_Size t1size, /* T1_Size */ FT_UInt glyph_index, FT_Int32 load_flags ) { T1_GlyphSlot glyph = (T1_GlyphSlot)t1glyph; FT_Error error; #ifdef __REACTOS__ T1_DecoderRec *decoder = malloc(sizeof(T1_DecoderRec)); /* Ugly but it allows us to reduce the diff */ #define decoder (*decoder) #else T1_DecoderRec decoder; #endif T1_Face face = (T1_Face)t1glyph->face; FT_Bool hinting; T1_Font type1 = &face->type1; PSAux_Service psaux = (PSAux_Service)face->psaux; const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs; FT_Matrix font_matrix; FT_Vector font_offset; FT_Data glyph_data; FT_Bool must_finish_decoder = FALSE; #ifdef FT_CONFIG_OPTION_INCREMENTAL FT_Bool glyph_data_loaded = 0; #endif #ifdef FT_CONFIG_OPTION_INCREMENTAL if ( glyph_index >= (FT_UInt)face->root.num_glyphs && !face->root.internal->incremental_interface ) #else if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) #endif /* FT_CONFIG_OPTION_INCREMENTAL */ { error = FT_THROW( Invalid_Argument ); goto Exit; } FT_TRACE1(( "T1_Load_Glyph: glyph index %d\n", glyph_index )); FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); if ( load_flags & FT_LOAD_NO_RECURSE ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; if ( t1size ) { glyph->x_scale = t1size->metrics.x_scale; glyph->y_scale = t1size->metrics.y_scale; } else { glyph->x_scale = 0x10000L; glyph->y_scale = 0x10000L; } t1glyph->outline.n_points = 0; t1glyph->outline.n_contours = 0; hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; error = decoder_funcs->init( &decoder, t1glyph->face, t1size, t1glyph, (FT_Byte**)type1->glyph_names, face->blend, FT_BOOL( hinting ), FT_LOAD_TARGET_MODE( load_flags ), T1_Parse_Glyph ); if ( error ) goto Exit; must_finish_decoder = TRUE; decoder.builder.no_recurse = FT_BOOL( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); decoder.num_subrs = type1->num_subrs; decoder.subrs = type1->subrs; decoder.subrs_len = type1->subrs_len; decoder.buildchar = face->buildchar; decoder.len_buildchar = face->len_buildchar; /* now load the unscaled outline */ error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index, &glyph_data ); if ( error ) goto Exit; #ifdef FT_CONFIG_OPTION_INCREMENTAL glyph_data_loaded = 1; #endif font_matrix = decoder.font_matrix; font_offset = decoder.font_offset; /* save new glyph tables */ decoder_funcs->done( &decoder ); must_finish_decoder = FALSE; /* now, set the metrics -- this is rather simple, as */ /* the left side bearing is the xMin, and the top side */ /* bearing the yMax */ if ( !error ) { t1glyph->outline.flags &= FT_OUTLINE_OWNER; t1glyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; /* for composite glyphs, return only left side bearing and */ /* advance width */ if ( load_flags & FT_LOAD_NO_RECURSE ) { FT_Slot_Internal internal = t1glyph->internal; t1glyph->metrics.horiBearingX = FIXED_TO_INT( decoder.builder.left_bearing.x ); t1glyph->metrics.horiAdvance = FIXED_TO_INT( decoder.builder.advance.x ); internal->glyph_matrix = font_matrix; internal->glyph_delta = font_offset; internal->glyph_transformed = 1; } else { FT_BBox cbox; FT_Glyph_Metrics* metrics = &t1glyph->metrics; /* copy the _unscaled_ advance width */ metrics->horiAdvance = FIXED_TO_INT( decoder.builder.advance.x ); t1glyph->linearHoriAdvance = FIXED_TO_INT( decoder.builder.advance.x ); t1glyph->internal->glyph_transformed = 0; if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) { /* make up vertical ones */ metrics->vertAdvance = ( face->type1.font_bbox.yMax - face->type1.font_bbox.yMin ) >> 16; t1glyph->linearVertAdvance = metrics->vertAdvance; } else {
const char* af_shaper_get_cluster( const char* p, AF_StyleMetrics metrics, void* buf_, unsigned int* count ) { AF_StyleClass style_class; const hb_feature_t* feature; FT_Int upem; const char* q; int len; hb_buffer_t* buf = (hb_buffer_t*)buf_; hb_font_t* font; hb_codepoint_t dummy; upem = (FT_Int)metrics->globals->face->units_per_EM; style_class = metrics->style_class; feature = features[style_class->coverage]; font = metrics->globals->hb_font; /* we shape at a size of units per EM; this means font units */ hb_font_set_scale( font, upem, upem ); while ( *p == ' ' ) p++; /* count bytes up to next space (or end of buffer) */ q = p; while ( !( *q == ' ' || *q == '\0' ) ) GET_UTF8_CHAR( dummy, q ); len = (int)( q - p ); /* feed character(s) to the HarfBuzz buffer */ hb_buffer_clear_contents( buf ); hb_buffer_add_utf8( buf, p, len, 0, len ); /* we let HarfBuzz guess the script and writing direction */ hb_buffer_guess_segment_properties( buf ); /* shape buffer, which means conversion from character codes to */ /* glyph indices, possibly applying a feature */ hb_shape( font, buf, feature, feature ? 1 : 0 ); if ( feature ) { hb_buffer_t* hb_buf = metrics->globals->hb_buf; unsigned int gcount; hb_glyph_info_t* ginfo; unsigned int hb_gcount; hb_glyph_info_t* hb_ginfo; /* we have to check whether applying a feature does actually change */ /* glyph indices; otherwise the affected glyph or glyphs aren't */ /* available at all in the feature */ hb_buffer_clear_contents( hb_buf ); hb_buffer_add_utf8( hb_buf, p, len, 0, len ); hb_buffer_guess_segment_properties( hb_buf ); hb_shape( font, hb_buf, NULL, 0 ); ginfo = hb_buffer_get_glyph_infos( buf, &gcount ); hb_ginfo = hb_buffer_get_glyph_infos( hb_buf, &hb_gcount ); if ( gcount == hb_gcount ) { unsigned int i; for (i = 0; i < gcount; i++ ) if ( ginfo[i].codepoint != hb_ginfo[i].codepoint ) break; if ( i == gcount ) { /* both buffers have identical glyph indices */ hb_buffer_clear_contents( buf ); } } } *count = hb_buffer_get_length( buf ); #ifdef FT_DEBUG_LEVEL_TRACE if ( feature && *count > 1 ) FT_TRACE1(( "af_shaper_get_cluster:" " input character mapped to multiple glyphs\n" )); #endif return q; }
FT_Stream_Open( FT_Stream stream, const char* filepathname ) { int file; struct stat stat_buf; if ( !stream ) return FT_Err_Invalid_Stream_Handle; /* open the file */ file = open( filepathname, O_RDONLY ); if ( file < 0 ) { FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not open `%s'\n", filepathname )); return FT_Err_Cannot_Open_Resource; } /* Here we ensure that a "fork" will _not_ duplicate */ /* our opened input streams on Unix. This is critical */ /* since it avoids some (possible) access control */ /* issues and cleans up the kernel file table a bit. */ /* */ #ifdef F_SETFD #ifdef FD_CLOEXEC (void)fcntl( file, F_SETFD, FD_CLOEXEC ); #else (void)fcntl( file, F_SETFD, 1 ); #endif /* FD_CLOEXEC */ #endif /* F_SETFD */ if ( fstat( file, &stat_buf ) < 0 ) { FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not `fstat' file `%s'\n", filepathname )); goto Fail_Map; } stream->size = stat_buf.st_size; stream->pos = 0; stream->base = (unsigned char *)mmap( NULL, stream->size, PROT_READ, MAP_FILE | MAP_PRIVATE, file, 0 ); if ( (long)stream->base == -1 ) { FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not `mmap' file `%s'\n", filepathname )); goto Fail_Map; } close( file ); stream->descriptor.pointer = stream->base; stream->pathname.pointer = (char*)filepathname; stream->close = ft_close_stream; stream->read = 0; FT_TRACE1(( "FT_Stream_Open:" )); FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", filepathname, stream->size )); return FT_Err_Ok; Fail_Map: close( file ); stream->base = NULL; stream->size = 0; stream->pos = 0; return FT_Err_Cannot_Open_Stream; }
FT_Error af_get_char_index( AF_StyleMetrics metrics, FT_ULong charcode, FT_ULong *codepoint, FT_Long *y_offset ) { AF_StyleClass style_class; const hb_feature_t* feature; FT_ULong in_idx, out_idx; if ( !metrics ) return FT_THROW( Invalid_Argument ); in_idx = FT_Get_Char_Index( metrics->globals->face, charcode ); style_class = metrics->style_class; feature = features[style_class->coverage]; if ( feature ) { FT_Int upem = (FT_Int)metrics->globals->face->units_per_EM; hb_font_t* font = metrics->globals->hb_font; hb_buffer_t* buf = hb_buffer_create(); uint32_t c = (uint32_t)charcode; hb_glyph_info_t* ginfo; hb_glyph_position_t* gpos; unsigned int gcount; /* we shape at a size of units per EM; this means font units */ hb_font_set_scale( font, upem, upem ); /* XXX: is this sufficient for a single character of any script? */ hb_buffer_set_direction( buf, HB_DIRECTION_LTR ); hb_buffer_set_script( buf, scripts[style_class->script] ); /* we add one character to `buf' ... */ hb_buffer_add_utf32( buf, &c, 1, 0, 1 ); /* ... and apply one feature */ hb_shape( font, buf, feature, 1 ); ginfo = hb_buffer_get_glyph_infos( buf, &gcount ); gpos = hb_buffer_get_glyph_positions( buf, &gcount ); out_idx = ginfo[0].codepoint; /* getting the same index indicates no substitution, */ /* which means that the glyph isn't available in the feature */ if ( in_idx == out_idx ) { *codepoint = 0; *y_offset = 0; } else { *codepoint = out_idx; *y_offset = gpos[0].y_offset; } hb_buffer_destroy( buf ); #ifdef FT_DEBUG_LEVEL_TRACE if ( gcount > 1 ) FT_TRACE1(( "af_get_char_index:" " input character mapped to multiple glyphs\n" )); #endif } else { *codepoint = in_idx; *y_offset = 0; } return FT_Err_Ok; }
FT_Stream_Open( FT_Stream stream, const char* filepathname ) { int file; struct stat stat_buf; if ( !stream ) return FT_THROW( Invalid_Stream_Handle ); /* open the file */ file = open( filepathname, O_RDONLY ); if ( file < 0 ) { FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not open `%s'\n", filepathname )); return FT_THROW( Cannot_Open_Resource ); } if ( fstat( file, &stat_buf ) < 0 ) { FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not `fstat' file `%s'\n", filepathname )); goto Fail_Map; } stream->size = stat_buf.st_size; if ( !stream->size ) { FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " opened `%s' but zero-sized\n", filepathname )); goto Fail_Map; } stream->pos = 0; stream->base = (unsigned char *)mmap( NULL, stream->size, PROT_READ, MAP_FILE | MAP_PRIVATE, file, 0 ); if ( (long)stream->base == -1 ) { FT_ERROR(( "FT_Stream_Open:" )); FT_ERROR(( " could not `mmap' file `%s'\n", filepathname )); goto Fail_Map; } close( file ); stream->descriptor.pointer = stream->base; stream->pathname.pointer = (char*)filepathname; stream->close = ft_close_stream; stream->read = 0; FT_TRACE1(( "FT_Stream_Open:" )); FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", filepathname, stream->size )); return FT_Err_Ok; Fail_Map: close( file ); stream->base = NULL; stream->size = 0; stream->pos = 0; return FT_THROW( Cannot_Open_Stream ); }
sfnt_init_face( FT_Stream stream, TT_Face face, FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { FT_Error error; FT_Library library = face->root.driver->root.library; SFNT_Service sfnt; SFNT_HeaderRec sfnt_header; /* for now, parameters are unused */ FT_UNUSED( num_params ); FT_UNUSED( params ); FT_TRACE1( ( "john1\n" ) ); sfnt = (SFNT_Service)face->sfnt; FT_TRACE1( ( "john2\n" ) ); if ( !sfnt ) { sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); FT_TRACE1( ( "john3\n" ) ); if ( !sfnt ) { error = SFNT_Err_Invalid_File_Format; goto Exit; } face->sfnt = sfnt; face->goto_table = sfnt->goto_table; } FT_TRACE1( ( "john4\n" ) ); FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); /* check that we have a valid TrueType file */ error = sfnt->load_sfnt_header( face, stream, face_index, &sfnt_header ); FT_TRACE1( ( "john5\n" ) ); if ( error ) goto Exit; face->format_tag = sfnt_header.format_tag; face->num_tables = sfnt_header.num_tables; /* Load font directory */ error = sfnt->load_directory( face, stream, &sfnt_header ); FT_TRACE1( ( "john6\n" ) ); if ( error ) goto Exit; FT_TRACE1( ( "john7\n" ) ); face->root.num_faces = face->ttc_header.count; FT_TRACE1( ( "john8\n" ) ); if ( face->root.num_faces < 1 ) face->root.num_faces = 1; FT_TRACE1( ( "john9\n" ) ); Exit: return error; }