📄 ftobjs.c
字号:
/* test for valid `library' and `aface' delayed to FT_Open_Face() */ if ( !pathname ) return FT_Err_Invalid_Argument; args.flags = FT_OPEN_PATHNAME; args.pathname = (char*)pathname; return FT_Open_Face( library, &args, face_index, aface ); }#endif /* !FT_MACINTOSH */ /* documentation is in freetype.h */ FT_EXPORT_DEF( FT_Error ) FT_New_Memory_Face( FT_Library library, const FT_Byte* file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface ) { FT_Open_Args args; /* test for valid `library' and `face' delayed to FT_Open_Face() */ if ( !file_base ) return FT_Err_Invalid_Argument; args.flags = FT_OPEN_MEMORY; args.memory_base = file_base; args.memory_size = file_size; return FT_Open_Face( library, &args, face_index, aface ); }#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS ) /* The behavior here is very similar to that in base/ftmac.c, but it */ /* is designed to work on non-mac systems, so no mac specific calls. */ /* */ /* We look at the file and determine if it is a mac dfont file or a mac */ /* resource file, or a macbinary file containing a mac resource file. */ /* */ /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */ /* the point, especially since there may be multiple `FOND' resources. */ /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */ /* they occur in the file. */ /* */ /* Note that multiple `POST' resources do not mean multiple postscript */ /* fonts; they all get jammed together to make what is essentially a */ /* pfb file. */ /* */ /* We aren't interested in `NFNT' or `FONT' bitmap resources. */ /* */ /* As soon as we get an `sfnt' load it into memory and pass it off to */ /* FT_Open_Face. */ /* */ /* If we have a (set of) `POST' resources, massage them into a (memory) */ /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */ /* going to try to save the kerning info. After all that lives in the */ /* `FOND' which isn't in the file containing the `POST' resources so */ /* we don't really have access to it. */ /* Finalizer for a memory stream; gets called by FT_Done_Face(). It frees the memory it uses. */ /* from ftmac.c */ static void memory_stream_close( FT_Stream stream ) { FT_Memory memory = stream->memory; FT_FREE( stream->base ); stream->size = 0; stream->base = 0; stream->close = 0; } /* Create a new memory stream from a buffer and a size. */ /* from ftmac.c */ static FT_Error new_memory_stream( FT_Library library, FT_Byte* base, FT_ULong size, FT_Stream_CloseFunc close, FT_Stream *astream ) { FT_Error error; FT_Memory memory; FT_Stream stream; if ( !library ) return FT_Err_Invalid_Library_Handle; if ( !base ) return FT_Err_Invalid_Argument; *astream = 0; memory = library->memory; if ( FT_NEW( stream ) ) goto Exit; FT_Stream_OpenMemory( stream, base, size ); stream->close = close; *astream = stream; Exit: return error; } /* Create a new FT_Face given a buffer and a driver name. */ /* from ftmac.c */ static FT_Error open_face_from_buffer( FT_Library library, FT_Byte* base, FT_ULong size, FT_Long face_index, const char* driver_name, FT_Face *aface ) { FT_Open_Args args; FT_Error error; FT_Stream stream; FT_Memory memory = library->memory; error = new_memory_stream( library, base, size, memory_stream_close, &stream ); if ( error ) { FT_FREE( base ); return error; } args.flags = FT_OPEN_STREAM; args.stream = stream; if ( driver_name ) { args.flags = args.flags | FT_OPEN_DRIVER; args.driver = FT_Get_Module( library, driver_name ); } error = FT_Open_Face( library, &args, face_index, aface ); if ( error == FT_Err_Ok ) (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; else { FT_Stream_Close( stream ); FT_FREE( stream ); } return error; } /* The resource header says we've got resource_cnt `POST' (type1) */ /* resources in this file. They all need to be coalesced into */ /* one lump which gets passed on to the type1 driver. */ /* Here can be only one PostScript font in a file so face_index */ /* must be 0 (or -1). */ /* */ static FT_Error Mac_Read_POST_Resource( FT_Library library, FT_Stream stream, FT_Long resource_listoffset, FT_Long resource_cnt, FT_Long resource_data, FT_Long face_index, FT_Face *aface ) { FT_Error error = FT_Err_Cannot_Open_Resource; FT_Memory memory = library->memory; FT_Byte* pfb_data; int i, type, flags, len; FT_Long pfb_len, pfb_pos, pfb_lenpos; FT_Long rlen, junk, temp; FT_Long *offsets; if ( face_index == -1 ) face_index = 0; if ( face_index != 0 ) return error; if ( FT_ALLOC( offsets, (FT_Long)resource_cnt * sizeof ( FT_Long ) ) ) return error; error = FT_Stream_Seek( stream, resource_listoffset ); if ( error ) goto Exit; /* Find all the POST resource offsets */ for ( i = 0; i < resource_cnt; ++i ) { (void)FT_READ_USHORT( junk ); /* resource id */ (void)FT_READ_USHORT( junk ); /* rsource name */ if ( FT_READ_LONG( temp ) ) goto Exit; offsets[i] = resource_data + ( temp & 0xFFFFFFL ); (void)FT_READ_LONG( junk ); /* mbz */ } /* Find the length of all the POST resources, concatenated. Assume */ /* worst case (each resource in its own section). */ pfb_len = 0; for ( i = 0; i < resource_cnt; ++i ) { error = FT_Stream_Seek( stream, offsets[i] ); if ( error ) goto Exit; if ( FT_READ_LONG( temp ) ) goto Exit; pfb_len += temp + 6; } if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) ) goto Exit; pfb_pos = 0; pfb_data[pfb_pos++] = 0x80; pfb_data[pfb_pos++] = 1; /* Ascii section */ pfb_lenpos = pfb_pos; pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */ pfb_data[pfb_pos++] = 0; pfb_data[pfb_pos++] = 0; pfb_data[pfb_pos++] = 0; len = 0; type = 1; for ( i = 0; i < resource_cnt; ++i ) { error = FT_Stream_Seek( stream, offsets[i] ); if ( error ) goto Exit2; if ( FT_READ_LONG( rlen ) ) goto Exit; if ( FT_READ_USHORT( flags ) ) goto Exit; rlen -= 2; /* the flags are part of the resource */ if ( ( flags >> 8 ) == type ) len += rlen; else { pfb_data[pfb_lenpos ] = len & 0xFF; pfb_data[pfb_lenpos + 1] = ( len >> 8 ) & 0xFF; pfb_data[pfb_lenpos + 2] = ( len >> 16 ) & 0xFF; pfb_data[pfb_lenpos + 3] = ( len >> 24 ) & 0xFF; if ( ( flags >> 8 ) == 5 ) /* End of font mark */ break; pfb_data[pfb_pos++] = 0x80; type = flags >> 8; len = rlen; pfb_data[pfb_pos++] = type; pfb_lenpos = pfb_pos; pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */ pfb_data[pfb_pos++] = 0; pfb_data[pfb_pos++] = 0; pfb_data[pfb_pos++] = 0; } error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen ); pfb_pos += rlen; } pfb_data[pfb_pos++] = 0x80; pfb_data[pfb_pos++] = 3; pfb_data[pfb_lenpos ] = len & 0xFF; pfb_data[pfb_lenpos + 1] = ( len >> 8 ) & 0xFF; pfb_data[pfb_lenpos + 2] = ( len >> 16 ) & 0xFF; pfb_data[pfb_lenpos + 3] = ( len >> 24 ) & 0xFF; return open_face_from_buffer( library, pfb_data, pfb_pos, face_index, "type1", aface ); Exit2: FT_FREE( pfb_data ); Exit: FT_FREE( offsets ); return error; } /* The resource header says we've got resource_cnt `sfnt' */ /* (TrueType/OpenType) resources in this file. Look through */ /* them for the one indicated by face_index, load it into mem, */ /* pass it on the the truetype driver and return it. */ /* */ static FT_Error Mac_Read_sfnt_Resource( FT_Library library, FT_Stream stream, FT_Long resource_listoffset, FT_Long resource_cnt, FT_Long resource_data, FT_Long face_index, FT_Face *aface ) { FT_Memory memory = library->memory; FT_Byte* sfnt_data; FT_Error error; int i; FT_Long flag_offset= 0xFFFFFFL; FT_Long rlen, junk; int is_cff; if ( face_index == -1 ) face_index = 0; if ( face_index >= resource_cnt ) return FT_Err_Cannot_Open_Resource; error = FT_Stream_Seek( stream, resource_listoffset ); if ( error ) goto Exit; for ( i = 0; i <= face_index; ++i ) { (void)FT_READ_USHORT( junk ); /* resource id */ (void)FT_READ_USHORT( junk ); /* rsource name */ if ( FT_READ_LONG( flag_offset ) ) goto Exit; flag_offset &= 0xFFFFFFL; (void)FT_READ_LONG( junk ); /* mbz */ } if ( flag_offset == 0xFFFFFFL ) return FT_Err_Cannot_Open_Resource; error = FT_Stream_Seek( stream, flag_offset + resource_data ); if ( error ) goto Exit; if ( FT_READ_LONG( rlen ) ) goto Exit; if ( rlen == -1 ) return FT_Err_Cannot_Open_Resource; if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) ) return error; error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen ); if ( error ) goto Exit; is_cff = rlen > 4 && sfnt_data[0] == 'O' && sfnt_data[1] == 'T' && sfnt_data[2] == 'T' && sfnt_data[3] == 'O'; error = open_face_from_buffer( library, sfnt_data, rlen, face_index, is_cff ? "cff" : "truetype", aface ); Exit: return error; } /* Check for a valid resource fork header, or a valid dfont */ /* header. In a resource fork the first 16 bytes are repeated */ /* at the location specified by bytes 4-7. In a dfont bytes */ /* 4-7 point to 16 bytes of zeroes instead. */ /* */ static FT_Error IsMacResource( FT_Library library, FT_Stream stream, FT_Long resource_offset, FT_Long face_index, FT_Face *aface ) { FT_Error error; unsigned char head[16], head2[16]; FT_Long rdata_pos, map_pos, rdata_len, map_len; int allzeros, allmatch, i, cnt, subcnt; FT_Long type_list, tag, rpos, junk; error = FT_Stream_Seek( stream, resource_offset ); if ( error ) goto Exit; error = FT_Stream_Read( stream, (FT_Byte *)head, 16 ); if ( error ) goto Exit; rdata_pos = resource_offset + ( ( head[0] << 24 ) | ( head[1] << 16 ) | ( head[2] << 8 ) | head[3] ); map_pos = resource_offset + ( ( head[4] << 24 ) | ( head[5] << 16 ) | ( head[6] << 8 ) | head[7] ); rdata_len = ( head[ 8] << 24 ) | ( head[ 9] << 16 ) | ( head[10] << 8 ) | head[11]; map_len = ( head[12] << 24 ) | ( head[13] << 16 ) | ( head[14] << 8 ) | head[15]; if ( rdata_pos + rdata_len != map_pos || map_pos == resource_offset ) return FT_Err_Unknown_File_Format; error = FT_Stream_Seek( stream, map_pos ); if ( error ) goto Exit; head2[15] = head[15] + 1; /* make it be different */ error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 ); if ( error ) goto Exit; allzeros = 1; allmatch = 1; for ( i = 0; i < 16; ++i ) { if ( head2[i] != 0 ) allzeros = 0; if ( head2[i] != head[i] ) allmatch = 0; } if ( !allzeros && !allmatch ) return FT_Err_Unknown_File_Format; /* If we've gotten this far then it's probably a mac resource file. */ /* Now, does it contain any interesting resources? */ (void)FT_READ_LONG( junk ); /* skip handle to next resource map */ (void)FT_READ_USHORT( junk ); /* skip file resource number */ (void)FT_READ_USHORT( junk ); /* skip attributes */ if ( FT_READ_USHORT( type_list ) ) goto Exit; if ( type_list == -1 ) return FT_Err_Unknown_File_Format;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -